Compare commits

...
100 Commits
Author SHA1 Message Date
zorruno dd13f52feb various tidyups 2026-07-29 23:18:11 +12:00
ESPHome Device Builder adb533d6a3 Edit esp-bedside-panel.yaml 2026-07-28 18:00:54 +12:00
ESPHome Device Builder b268b3cbf9 Edit esp-bedside-panel.yaml 2026-07-28 17:27:36 +12:00
ESPHome Device Builder a000ee1b11 Edit esp-occupancystair.yaml 2026-07-26 19:48:48 +12:00
ESPHome Device Builder 47b9f79e56 Edit esp-centralstairs-bottom.yaml 2026-07-26 19:48:48 +12:00
ESPHome Device Builder 8c4a3070cd Edit esp-centralstairs-top.yaml 2026-07-26 19:48:48 +12:00
ESPHome Device Builder 8993a02002 Edit esp-breakfastbarleds.yaml 2026-07-26 19:48:48 +12:00
ESPHome Device Builder 86914d2c8b Edit esp-occupancystair.yaml 2026-07-26 19:44:08 +12:00
ESPHome Device Builder 260bd11320 Edit esp-officeusbhubpower.yaml 2026-07-26 19:40:54 +12:00
ESPHome Device Builder edda2027cb Edit esp-masterbdrmsouth.yaml 2026-07-26 19:37:29 +12:00
ESPHome Device Builder f07a0d9292 Edit esp-masterbdrmwest.yaml 2026-07-26 19:37:29 +12:00
ESPHome Device Builder 126ef9c4aa Edit esp-downstloungeentry.yaml 2026-07-26 19:35:07 +12:00
ESPHome Device Builder 5b13bc4350 Edit esp-gasheater.yaml 2026-07-26 18:12:53 +12:00
ESPHome Device Builder 48af152c79 Edit esp-loungecabinetleds.yaml 2026-07-26 17:36:20 +12:00
ESPHome Device Builder 46d28903dc Edit esp-downstairskitchleds.yaml 2026-07-26 17:36:20 +12:00
ESPHome Device Builder b216190c98 Edit esp-breakfastbarleds.yaml 2026-07-26 17:36:20 +12:00
ESPHome Device Builder a73002a902 Edit esp-bedrm1arlecbulb.yaml 2026-07-26 17:36:20 +12:00
ESPHome Device Builder 23f6aff42c Edit esp-loungebookshelfleds.yaml 2026-07-26 17:36:20 +12:00
ESPHome Device Builder 8a629f738e Edit esp-attobattery.yaml 2026-07-25 22:00:04 +12:00
ESPHome Device Builder 696d8e3767 Edit esp-attobattery.yaml 2026-07-25 21:59:53 +12:00
ESPHome Device Builder a38382a22f Edit esp-bedrm2ceilingfan.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 5ba8b009dc Edit esp-loungesouthleftswitch.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 7f6192df94 Edit esp-bedrm3lights.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 89de8a3972 Edit esp-officeelvcontrol.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 44e6274d1b Edit esp-garagelights.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 5118d4eb8f Edit esp-masterbdrmsouth.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder e6a0e41102 Edit esp-occupancystair.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 07efb3662e Edit esp-centralstairs-top.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder a8b409388a Edit esp-datacupboardfans.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 1412e3c0fc Edit esp-3dprinterpow.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 8d5f35e672 Edit esp-attobattery.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder 344efa8232 Edit esp-garageextcornerlight.yaml 2026-07-25 21:59:36 +12:00
ESPHome Device Builder c63cb3d6a5 Edit esp-bedrm1arlecbulb.yaml 2026-07-25 21:59:35 +12:00
ESPHome Device Builder c708075472 Edit esp-breakfastbarleds.yaml 2026-07-25 21:59:35 +12:00
ESPHome Device Builder 9f71152fbf Edit esp-centralstairs-bottom.yaml 2026-07-25 21:59:35 +12:00
ESPHome Device Builder f285a1b20b Edit esp-leafbattery.yaml 2026-07-25 21:59:35 +12:00
ESPHome Device Builder ff1b806aaa Edit esp-officeusbhubpower.yaml 2026-07-25 21:59:35 +12:00
ESPHome Device Builder acd553e883 Edit esp-loungecabinetleds.yaml 2026-07-25 21:59:35 +12:00
ESPHome Device Builder ea13ba3e05 Edit esp-downstairskitchleds.yaml 2026-07-25 21:59:34 +12:00
ESPHome Device Builder cfdeb4a65c Edit esp-underhouselights.yaml 2026-07-25 21:59:34 +12:00
ESPHome Device Builder 2b5d31d415 Edit esp-bedrm3ceilingfan.yaml 2026-07-25 21:59:34 +12:00
ESPHome Device Builder a3ccd16ed4 Edit esp-downstkitchlights.yaml 2026-07-25 21:59:34 +12:00
ESPHome Device Builder 5b10c044c7 Edit esp-officedeskrightgpo.yaml 2026-07-25 21:59:34 +12:00
ESPHome Device Builder b367fef7a8 Edit esp-masterbdrmwest.yaml 2026-07-25 21:59:34 +12:00
ESPHome Device Builder 29258bcb2e Edit esp-reterminal-e1001.yaml 2026-07-25 21:59:34 +12:00
ESPHome Device Builder 6ef266688f Edit esp-loungebookshelfleds.yaml 2026-07-25 21:59:34 +12:00
ESPHome Device Builder ea74c6d855 Edit esp-garagelights.yaml 2026-07-25 21:56:51 +12:00
ESPHome Device Builder c7f4126a75 Edit esp-3dprinterpow.yaml 2026-07-25 21:56:51 +12:00
ESPHome Device Builder 1f7552968b Edit esp-garageextcornerlight.yaml 2026-07-25 21:56:51 +12:00
ESPHome Device Builder cd0760293a Edit esp-masterbdrmsouth.yaml 2026-07-25 21:56:34 +12:00
ESPHome Device Builder 8a5e1b1b74 Edit esp-underhouselights.yaml 2026-07-25 21:56:34 +12:00
ESPHome Device Builder 476b5cffbb Edit esp-officeelvcontrol.yaml 2026-07-25 21:56:34 +12:00
ESPHome Device Builder 8b1ccb4344 Edit esp-reterminal-e1001.yaml 2026-07-25 21:56:34 +12:00
ESPHome Device Builder 4e47d94474 Edit esp-masterbdrmwest.yaml 2026-07-25 21:56:34 +12:00
ESPHome Device Builder b74d0b02d9 Edit esp-officeusbhubpower.yaml 2026-07-25 21:56:34 +12:00
ESPHome Device Builder a11ef51d71 Edit esp-officeelvcontrol.yaml 2026-07-25 21:56:05 +12:00
ESPHome Device Builder dc941745d5 Edit esp-officedeskrightgpo.yaml 2026-07-25 21:56:00 +12:00
ESPHome Device Builder 1d02c6c758 Edit esp-leafbattery.yaml 2026-07-25 21:56:00 +12:00
ESPHome Device Builder de7a46bd25 Edit esp-garageextcornerlight.yaml 2026-07-25 21:55:53 +12:00
ESPHome Device Builder d16ec03db0 Edit esp-datacupboardfans.yaml 2026-07-25 21:55:52 +12:00
ESPHome Device Builder c780a59cd2 Edit esp-bedrm2ceilingfan.yaml 2026-07-25 21:55:45 +12:00
ESPHome Device Builder 644bf978a9 Edit esp-bedrm3ceilingfan.yaml 2026-07-25 21:55:45 +12:00
ESPHome Device Builder b27d2c87b7 Edit esp-attobattery.yaml 2026-07-25 21:55:45 +12:00
ESPHome Device Builder 5e235fda4e Edit esp-3dprinterpow.yaml 2026-07-25 21:55:39 +12:00
ESPHome Device Builder c0b6f8bebd Edit esp-garagelights.yaml 2026-07-25 21:55:17 +12:00
ESPHome Device Builder d1855c5e6b Edit esp-loungecabinetleds.yaml 2026-07-25 21:55:17 +12:00
ESPHome Device Builder 7fef727c68 Edit esp-occupancystair.yaml 2026-07-25 21:55:17 +12:00
ESPHome Device Builder 3467aec947 Edit esp-downstairskitchleds.yaml 2026-07-25 21:55:17 +12:00
ESPHome Device Builder 0af2540480 Edit esp-loungesouthleftswitch.yaml 2026-07-25 21:55:17 +12:00
ESPHome Device Builder f479c67f00 Edit esp-downstkitchlights.yaml 2026-07-25 21:55:17 +12:00
ESPHome Device Builder 3343d0a74a Edit esp-loungebookshelfleds.yaml 2026-07-25 21:55:17 +12:00
ESPHome Device Builder 5a87ddf676 Edit esp-bedrm1arlecbulb.yaml 2026-07-25 21:55:09 +12:00
ESPHome Device Builder b6d39dc81d Edit esp-centralstairs-bottom.yaml 2026-07-25 21:55:09 +12:00
ESPHome Device Builder 146c483e68 Edit esp-breakfastbarleds.yaml 2026-07-25 21:55:09 +12:00
ESPHome Device Builder 3646b697cc Edit esp-centralstairs-top.yaml 2026-07-25 21:55:09 +12:00
ESPHome Device Builder e20365c32b Edit esp-bedrm3lights.yaml 2026-07-25 21:55:09 +12:00
ESPHome Device Builder 9738ba98ac Edit esp-loungecabinetleds.yaml 2026-07-25 21:41:01 +12:00
ESPHome Device Builder e72a5732e2 Edit esp-loungecabinetleds.yaml 2026-07-25 21:40:55 +12:00
ESPHome Device Builder ab62965de8 Edit esp-loungecabinetleds.yaml 2026-07-25 21:40:50 +12:00
ESPHome Device Builder f2924e1d77 Edit esp-downstloungeentry.yaml 2026-07-25 20:49:58 +12:00
ESPHome Device Builder ec42542784 Edit esp-downstloungeentry.yaml 2026-07-25 20:49:48 +12:00
ESPHome Device Builder e351d4728e Edit esp-downstloungemain.yaml 2026-07-25 20:49:32 +12:00
ESPHome Device Builder 4dea67f941 Edit esp-downstloungemain.yaml 2026-07-25 20:49:10 +12:00
ESPHome Device Builder ed17c41764 Edit esp-downstloungemain.yaml 2026-07-25 20:49:00 +12:00
ESPHome Device Builder 08b1619187 Edit esp-downstloungemain.yaml 2026-07-25 20:48:54 +12:00
ESPHome Device Builder 9528344ffe Edit esp-downstloungemain.yaml 2026-07-25 20:48:49 +12:00
ESPHome Device Builder ba2214ae60 Edit esp-downstloungemain.yaml 2026-07-25 20:48:38 +12:00
ESPHome Device Builder 6658a530b8 Edit esp-occupancyoffice.yaml 2026-07-25 17:17:47 +12:00
ESPHome Device Builder d5bf32a37d Edit esp-officeduallights.yaml 2026-07-25 13:13:54 +12:00
ESPHome Device Builder e74ac70ef0 Edit esp-officelights.yaml 2026-07-25 13:08:53 +12:00
ESPHome Device Builder 474a911ba9 Edit esp-occupancyoffice.yaml 2026-07-25 13:08:53 +12:00
ESPHome Device Builder 37faf62809 Edit esp-officeduallights.yaml 2026-07-25 13:08:53 +12:00
ESPHome Device Builder 5891df3c45 Edit esp-officelights.yaml 2026-07-25 12:58:52 +12:00
ESPHome Device Builder b571aff326 Edit esp-officelights.yaml 2026-07-25 12:53:51 +12:00
ESPHome Device Builder 64631fac30 Edit esp-occupancyoffice.yaml 2026-07-25 12:53:51 +12:00
ESPHome Device Builder af3302c9a5 Edit esp-officeduallights.yaml 2026-07-25 12:53:51 +12:00
ESPHome Device Builder 7cb99ed827 Edit esp-reterminal-e1001.yaml 2026-07-24 22:31:37 +12:00
ESPHome Device Builder 23d5c82222 Edit esp-bedside-panel.yaml 2026-07-24 22:31:37 +12:00
ESPHome Device Builder 11249d8645 Edit esp-attobattery.yaml 2026-07-24 22:31:36 +12:00
ESPHome Device Builder aad2988873 Edit esp-leafbattery.yaml 2026-07-24 22:31:36 +12:00
55 changed files with 8540 additions and 4861 deletions
+1 -1
View File
@@ -1 +1 @@
{"pid": 74, "version": 1, "ha_version": "2026.7.3", "start_ts": 1784842567.418518} {"pid": 70, "version": 1, "ha_version": "2026.7.4", "start_ts": 1785317114.2667625}
+42
View File
@@ -0,0 +1,42 @@
# Your own instructions for OpenCode
Rename this file to `AGENTS.local.md` (drop the `.example`) and OpenCode will read
it at the start of every session, alongside the add-on's own `AGENTS.md`.
- The add-on **never** writes to `AGENTS.local.md`. Add-on updates cannot overwrite it.
- Delete the file to stop loading it. There is no setting to toggle.
- `AGENTS.md` wins if the two ever conflict — safety rules and approval requirements
stay in force regardless of what you put here.
- Everything in this file is sent to the model with **every** request, so keep it
short and specific. A page of standing preferences is useful; a diary is not.
- Never put passwords, tokens, or API keys here. Reference them with `!secret` instead.
Delete the examples below and write your own.
---
## About my setup
- All Zigbee devices go through Zigbee2MQTT, not ZHA. Do not suggest ZHA workflows.
- The house has three floors: basement, main, upstairs. Areas are named after rooms.
- Presence detection is unreliable in the garage — treat those sensors with suspicion.
## How I want you to work
- New configuration goes in `packages/`, one file per feature. Do not grow
`configuration.yaml`.
- Prefer template sensors over automations that write to `input_number` helpers.
- Name entities `<area>_<device>_<function>`, for example `kitchen_ceiling_brightness`.
- Always show me the diff before writing, even for one-line changes.
## Leave these alone
- Anything under `custom_components/` — those are managed through HACS.
- The `packages/energy.yaml` file. It is tuned and I do not want it reformatted.
## Useful context
- My electricity tariff changes at 07:00 and 22:00; automations that care about
cost should use those boundaries.
- The Sonos speakers drop off the network occasionally. That is expected, not a
configuration bug.
+807
View File
@@ -0,0 +1,807 @@
# Home Assistant OpenCode Rules
You are working directly within a Home Assistant installation. Your working directory is `/homeassistant`, which is the live Home Assistant configuration directory.
## CRITICAL: User Consent and Scope Rules
You MUST follow these rules strictly:
1. **Never exceed the user's request** - Do exactly what the user asks, nothing more. Do not "improve" or "enhance" beyond the stated scope.
2. **Never make changes without explicit approval** - Before modifying ANY file:
- Show the user exactly what you plan to change
- Wait for their explicit confirmation ("yes", "go ahead", "do it", etc.)
- If they haven't approved, DO NOT proceed
3. **Ask, don't assume** - If the user's request is ambiguous:
- Ask clarifying questions first
- Present options and let them choose
- Never guess at their intent
4. **Read-only by default** - When investigating or troubleshooting:
- Only read files and gather information
- Present findings and recommendations
- Wait for user instruction before making any changes
5. **One change at a time** - When making approved changes:
- Make the minimum change needed
- Show what was changed
- Let the user verify before proceeding to any next step
6. **No unsolicited modifications** - Never:
- "Clean up" code the user didn't ask about
- Add features they didn't request
- Refactor working configurations
- Fix issues they haven't mentioned
7. **Respect "no"** - If a user declines a suggestion, do not:
- Repeat the suggestion
- Make the change anyway
- Try to convince them otherwise
## Environment Context
- You are running inside the OpenCode app
- The current directory (`/homeassistant`) contains the live Home Assistant configuration
- Changes to YAML files here directly affect the Home Assistant instance
- If add-on folder access is enabled, `/addons` and `/addon_configs` are available for Home Assistant add-on development. Treat `/addon_configs` as sensitive and only inspect or modify these folders when the user explicitly asks.
- You may have access to MCP tools for interacting with Home Assistant (check with the user)
## Home Assistant Interaction Model
There are three primary, safe ways to interact with Home Assistant:
### 1. Configuration Files (YAML)
The standard way to define and customize Home Assistant behavior:
- Automations, scripts, scenes, and blueprints
- Integration and sensor configurations
- Templates, packages, and customizations
- Dashboard (Lovelace) definitions
These files are designed for user editing and are the source of truth for your Home Assistant setup.
### 2. MCP Tools (Runtime API)
Real-time interaction with the running Home Assistant instance:
- Query current entity states and history
- Control devices and call services
- Validate configurations
- Diagnose issues and detect anomalies
- Report OpenCode/HA agent capability status with `get_agent_capabilities`
### Native Home Assistant LLM Platform
Home Assistant is developing a native `llm` integration where Core integrations and custom integrations can expose curated tools through `<integration>/llm.py` and registered LLM APIs. New Home Assistant builds may also expose those APIs over native MCP endpoints such as `/api/mcp/<API ID>`; the built-in Assist API uses `/api/mcp/assist`. This is complementary to OpenCode MCP, not a replacement.
- If the optional `homeassistant_native` MCP server is available, prefer it for requests that fit the configured native Home Assistant LLM API because those tools are curated by Home Assistant.
- Use OpenCode MCP for configuration editing, safe writes, validation, admin/dev workflows, screenshots, updates, ESPHome, `hab`, Zigbee tasks, add-on development, and Home Assistant documentation lookup.
- Use `get_agent_capabilities` or `ha://agent/capabilities` to check whether the running HA instance reports the native `llm` component and native MCP endpoints.
- Use `get_home_context` for compact area/domain/entity understanding before broad state dumps.
- Use `get_ha_llm_development_guide` when helping develop or review a custom integration's native `<integration>/llm.py` provider.
- Do not assume this add-on can register tools directly with HA's native `llm` platform; native tool registration is internal to HA integrations/custom integrations. The add-on can consume configured native LLM APIs through native MCP when Home Assistant exposes them.
### 3. hab CLI (Home Assistant Builder)
A CLI tool designed for AI agents to manage Home Assistant. Run `hab` commands via the terminal:
- **Entity management**: `hab entity list`, `hab entity get light.living_room`, `hab entity logbook sensor.power --start 2h`
- **Service calls**: `hab action call light.turn_on --entity light.living_room --data '{"brightness": 200}'`
- **Automation CRUD**: `hab automation list`, `hab automation create`, `hab automation delete`
- **Dashboard management**: `hab dashboard list`, `hab dashboard view create`
- **Area/floor/zone/label**: `hab area list`, `hab area create "Kitchen"`
- **Helpers**: `hab helper list`, `hab helper create`
- **Scripts**: `hab script list`, `hab script create`
- **Scenes**: `hab scene list`, `hab scene create`, `hab scene activate "Movie Time"`
- **Blueprints**: `hab blueprint list`
- **Backups**: `hab backup list`, `hab backup create`
- **System**: `hab system info`, `hab system health`, `hab overview`
- **Devices**: `hab device list`
- **People**: `hab person list`, `hab person create`, `hab person update`
- **Categories**: `hab category list`, `hab category assign --entity light.kitchen`
- **To-do lists**: `hab todo list`, `hab todo item list todo.shopping`, `hab todo item add todo.shopping "Milk"`
- **Notifications**: `hab notification list`, `hab notification create --message "Hello" --title "Alert"`
- **Integrations**: `hab integration list`, `hab integration reload hue`, `hab integration disable mqtt`
- **Repairs**: `hab repairs list`, `hab repairs ignore <issue_id>`
- **Events**: `hab event list`, `hab event fire my_custom_event --data '{"key": "value"}'`
- **Templates**: `hab template render --expression "{{ states('sensor.temperature') }}"`
- **Search**: `hab search related`
`hab` outputs human-readable text by default. Use `--json` for structured JSON output (ideal for parsing).
`hab` is pre-authenticated via the Supervisor token - no login required.
Run `hab --help` or `hab <command> --help` for full usage details.
<!-- HAB_LIVE_HELP_START -->
```
Home Assistant Builder (hab) is a CLI utility designed for LLMs
to build and manage Home Assistant configurations.
Interactive sessions default to human-readable text. Non-interactive sessions default to JSON.
Start with 'hab guide' for workflow-level guidance optimized for LLM and agent usage.
Usage:
hab [command]
Getting Started:
auth Manage authentication
capability Inspect runtime capabilities
guide Display built-in usage guides
overview Show an overview of the Home Assistant instance
schema Show machine-readable command schema
Registry:
area Manage areas
device Manage devices
entity Manage entities
floor Manage floors
label Manage labels
person Manage persons
search Search for items and relationships
zone Manage zones
Automation:
action Call actions (services)
automation Manage automations
blueprint Manage blueprints
category Manage categories
helper Manage groups, templates, and other helpers
scene Manage scenes
script Manage scripts
Dashboard:
dashboard Manage dashboards
Other:
backup Manage backups
calendar Manage calendar events
diagnostics Manage diagnostics handlers
energy Manage energy dashboard settings
esphome Manage ESPHome devices
event Manage Home Assistant events
integration Manage integrations
network Manage network settings
notification Manage persistent notifications
repairs Manage Home Assistant repairs
system Manage system
template Work with Home Assistant templates
thread Manage Thread credentials
todo Manage to-do list items
update Update hab to the latest version
version Show version information
Additional Commands:
help Help about any command
Flags:
--config string Path to config directory (default: ~/.config/home-assistant-builder)
-h, --help help for hab
--json Use JSON output instead of human-readable text
--skip-update-check Skip automatic update check on startup
--text Use human-readable text output
--verbose Show verbose output
Use "hab [command] --help" for more information about a command.
```
<!-- HAB_LIVE_HELP_END -->
**Use configuration files when:** defining behavior, creating automations, setting up integrations
**Use MCP tools when:** checking current state, safe config writing, anomaly detection, entity diagnostics
**Use hab CLI when:** managing dashboards, areas, helpers, backups, blueprints, and bulk admin operations
### 4. zigporter CLI (Zigbee Toolkit)
A CLI for Zigbee device management in Home Assistant. Handles cascade renames (updating entity IDs across automations, scripts, scenes, and all Lovelace dashboards atomically), device inspection, stale device cleanup, and Zigbee mesh visualization.
**Cascade rename** — zigporter's unique value: when you rename an entity or device, it automatically patches every reference in automations, scripts, scenes, and Lovelace dashboards. `hab` can rename a single entity/device but does NOT cascade to references.
Key commands:
- **Cascade rename**: `zigporter rename-entity light.old_id light.new_id --apply`, `zigporter rename-device "Old Name" "New Name" --apply`
- **Device inventory**: `zigporter list-devices --json`, `zigporter list-z2m --json` (requires Z2M config)
- **Device inspection**: `zigporter inspect "Device Name" --json`, `zigporter inspect sensor.entity_id --json`
- **Stale device management**: `zigporter stale "Device" --action remove`, `zigporter stale "Device" --action ignore`
- **Post-migration cleanup**: `zigporter fix-device "Device" --apply`
- **Connectivity check**: `zigporter check`
- **ZHA export**: `zigporter export --output devices.json`
- **Mesh visualization**: `zigporter network-map --format table` (terminal), `zigporter network-map --output mesh.svg` (SVG file)
**Output format**: Use `--json` on listing/inspect commands for structured output (ideal for AI parsing). Rename commands output diffs and confirmation text.
zigporter is pre-authenticated via the Supervisor token. Z2M commands (`list-z2m`, `network-map --backend z2m`) require Z2M URL configuration in the add-on settings.
**Important limitations**:
- `rename-entity` / `rename-device` do NOT patch Jinja2 template expressions (e.g. `{{ states('old.id') }}`). A warning is printed listing affected files — inform the user these need manual review after renaming.
- The `migrate` command is inherently interactive (requires physical device actions) and must NOT be used by AI agents.
- Dry-run is the default for renames — always preview before using `--apply`.
<!-- ZIGPORTER_LIVE_HELP_START -->
```
Usage: zigporter [OPTIONS] COMMAND [ARGS]...
Migrate Zigbee devices between ZHA and Zigbee2MQTT. Supports both ZHA → Z2M
(default) and Z2M → ZHA (--direction z2m-to-zha).
╭─ Options ────────────────────────────────────────────────────────────────────╮
│ --version -v Show version and exit. │
│ --install-completion Install completion for the current shell. │
│ --show-completion Show completion for the current shell, to │
│ copy it or customize the installation. │
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────╮
│ setup Create or update the configuration file in the zigporter │
│ config directory. │
│ check Verify that all requirements are in place before migrating. │
│ export Export current ZHA devices, entities, areas, and automation │
│ references to JSON. │
│ export-z2m Export current Z2M devices, entities, areas, and automation │
│ references to JSON. │
│ list-z2m List all devices currently paired with Zigbee2MQTT. │
│ list-devices List all Home Assistant devices across all integrations. │
│ migrate Interactive wizard to migrate devices between ZHA and │
│ Zigbee2MQTT. │
│ inspect Show all automations, scripts, scenes, and dashboard cards │
│ that depend on a device. │
│ rename-entity Rename an entity ID and update all references in automations, │
│ scripts, scenes, and dashboards. │
│ rename-device Rename a device and cascade the change to all its entities, │
│ automations, scripts, scenes, and dashboards. │
│ stale Identify and manage offline/stale devices across all │
│ integrations. │
│ fix-device Remove stale ZHA device entries left behind after migration │
│ to Zigbee2MQTT. │
│ network-map Show Zigbee mesh topology with signal strength (LQI) for each │
│ device. │
╰──────────────────────────────────────────────────────────────────────────────╯
```
<!-- ZIGPORTER_LIVE_HELP_END -->
**Use zigporter CLI when:** renaming entities/devices with cascade updates, inspecting Zigbee devices across integrations, cleaning up stale or post-migration devices, visualizing the Zigbee mesh
### 5. Internal Directories (OFF-LIMITS)
Home Assistant manages internal state in directories like `.storage/`. These are:
- Not designed for direct access
- Subject to change without notice
- Potentially dangerous to modify
**Never access internal directories directly - use configuration files or MCP tools instead.**
## RESTRICTED: Internal Home Assistant Directories
**NEVER read, modify, or directly interact with these internal directories:**
| Directory | Contains | Use Instead |
|-----------|----------|-------------|
| `.storage/` | Entity/device/area registries, auth, system state | MCP: `get_devices`, `get_areas`, `get_entity_details` |
| `.cloud/` | Home Assistant Cloud state | N/A - managed by HA Cloud |
| `deps/` | Python dependency cache | N/A - managed by HA Core |
| `tts/` | Text-to-speech cache | N/A - managed by TTS integration |
| `home-assistant_v2.db` | History SQLite database | MCP: `get_history`, `get_logbook` |
| `home-assistant.log` | Raw system logs | MCP: `get_error_log` |
These contain internal Home Assistant state that:
1. Is managed exclusively by Home Assistant core
2. Can corrupt your installation if modified incorrectly
3. May be overwritten by Home Assistant at any time
4. Has no stable schema or format guarantees
**For information that seems to require internal access, there is always a proper alternative:**
- Need entity details? -> Read configuration files OR use `get_entity_details`
- Need device info? -> Use `get_devices` MCP tool
- Need to check history? -> Use `get_history` MCP tool
- Need to see errors? -> Use `get_error_log` MCP tool
## File Structure Knowledge
### Configuration Files (Primary Interface - Read/Write with User Approval)
These are the user-facing configuration files - the primary way to define Home Assistant behavior:
- `configuration.yaml` - Main configuration file
- `automations.yaml` - Automation definitions (if using UI or split config)
- `scripts.yaml` - Script definitions
- `scenes.yaml` - Scene definitions
- `secrets.yaml` - Sensitive values (NEVER commit or expose)
- `customize.yaml` - Entity customizations
- `groups.yaml` - Group definitions
- `packages/` - Package-based configuration splits
- `blueprints/` - Automation and script blueprints
- `custom_components/` - Custom integrations (HACS or manual)
- `www/` - Static files served at /local/
- `themes/` - Custom themes
- `*.yaml` in root - Any user-created YAML configuration
**These files are designed for editing** and are equally valid as MCP tools for research and changes.
### Internal Directories (OFF-LIMITS - Never Access Directly)
- `.storage/` - Internal registries and state (use MCP tools)
- `.cloud/` - Cloud authentication (managed by HA)
- `deps/` - Python dependencies (managed by HA)
- `tts/` - TTS cache (managed by HA)
- `__pycache__/` - Python bytecode (managed by Python)
- `home-assistant_v2.db` - History database (use MCP `get_history`)
- `home-assistant.log` - Logs (use MCP `get_error_log`)
## Working with YAML on the Command Line (`yq`)
To read, query, or convert YAML from the shell, use **`yq`** (the mikefarah/Go tool, pre-installed on `PATH`). It is the correct tool because it tolerates Home Assistant's custom tags — `!include`, `!secret`, `!env_var`, `!input`, and the `!include_dir_*` family.
**Do NOT reach for `python3 -c "import yaml"` (PyYAML) or Ruby's YAML for HA config** — both crash with a constructor error on the very first `!include`/`!secret`, because those tags are Home Assistant extensions, not standard YAML. `yq` parses them with no setup.
### Read / query (always safe — never errors on HA tags)
```
yq '.homeassistant.latitude' configuration.yaml # Print a nested value
yq '.automation | tag' configuration.yaml # Inspect the tag itself -> !include
yq 'keys' configuration.yaml # List top-level keys
yq -o=json '.' configuration.yaml | jq '.sensor' # Convert to JSON to pipe into jq
```
Note: output and JSON conversion strip the tag — `!secret home_latitude` prints as `home_latitude`. Use `| tag` when you need to see the tag. Never round-trip a file *through* JSON and back; that permanently loses every `!include`/`!secret`.
### Writing / editing
Prefer the sanctioned write path: **`write_config_safe`** (MCP — validates, backs up, and blocks accidental content loss) or read the full file and use the editor. Reserve `yq -i` for quick, low-risk edits, and only with these two caveats in mind:
1. **A custom tag sticks to the value you overwrite.** `yq -i '.homeassistant.latitude = 52.37'` on a `!secret`-tagged node produces the corrupt `latitude: !secret 52.37`. When replacing a tagged value, reset the tag in the *same* expression:
```
yq -i '(.homeassistant.latitude tag = "") | .homeassistant.latitude = 52.37' configuration.yaml
```
To *add* a secret reference, set the tag explicitly: `yq -i '.http.api_key = "my_api_key" | .http.api_key tag = "!secret"' configuration.yaml`
2. **`yq -i` strips blank separator lines** (and collapses inline-comment spacing) across the whole file. No data is lost, but diffs are noisier. When a clean, minimal diff matters, use the editor instead.
### Validation is not a syntax check
`yq` only confirms YAML *parses*. To validate a Home Assistant *configuration* (resolving `!include`/`!secret` and checking integration schemas), use `check_config_syntax` / `write_config_safe` (MCP), not `yq`.
## YAML Style Guide (MANDATORY)
All YAML written or modified MUST follow the official Home Assistant YAML Style Guide.
Reference: https://developers.home-assistant.io/docs/documenting/yaml-style-guide/
A Prettier formatter is configured for this environment and will auto-format files on save.
However, Prettier only enforces a subset of the rules below. You are responsible for following
ALL rules, especially those Prettier cannot enforce (marked with *).
### Indentation
2 spaces. Tabs are forbidden.
```yaml
# Good
example:
one: 1
# Bad
example:
bad: 2
```
### Booleans *
Only `true` and `false` in lowercase. Never use `Yes`, `No`, `On`, `Off`, `TRUE`, etc.
```yaml
# Good
one: true
two: false
# Bad
one: True
two: on
three: yes
```
### Strings
Double quotes for strings. Single quotes are not allowed.
```yaml
# Good
example: "Hi there!"
# Bad
example: 'Hi there!'
```
**Exceptions** (no quotes needed): entity IDs, area IDs, device IDs, platform types,
trigger types, condition types, action names, device classes, event names, attribute names,
and values from a fixed set of options (e.g., `mode`).
```yaml
# Good
actions:
- action: light.turn_on
target:
entity_id: light.living_room
area_id: living_room
data:
message: "Hello!"
transition: 10
# Bad - don't quote entity IDs and action names
actions:
- action: "light.turn_on"
target:
entity_id: "light.living_room"
```
### Sequences (Lists) *
Use block style. Flow style `[1, 2, 3]` must not be used.
Block sequences must be indented under their key.
```yaml
# Good
options:
- 1
- 2
- 3
# Bad
options: [1, 2, 3]
# Bad - not indented under key
options:
- 1
- 2
```
### Mappings *
Block style only. Flow style `{ key: val }` must not be used.
```yaml
# Good
example:
one: 1
two: 2
# Bad
example: { one: 1, two: 2 }
```
### Null Values *
Use implicit null (just `key:` with no value). Never use `null` or `~`.
```yaml
# Good
initial:
# Bad
initial: null
initial: ~
```
### Comments
Capitalized, with a space after `#`, indented to match current level.
```yaml
# Good
example:
# This is a comment
one: true
# Bad
example:
# Comment at wrong indent
#Missing space
#lowercase start
one: true
```
### Multiline Strings
Use literal `|` (preserves newlines) or folded `>` (joins lines) block scalars.
Avoid `\n` in strings. Prefer no-chomp (`|`, `>`) unless you need strip (`|-`, `>-`).
```yaml
# Good
message: |
Hello!
This is a multiline
notification message.
# Good - folded
description: >
This is a long description that
will be joined into a single line.
# Bad
message: "Hello!\nThis is a multiline\nnotification message.\n"
```
### Templates
Double quotes outside, single quotes inside. Use `states()` and `state_attr()`
helpers, not direct state object access. Split long templates across multiple lines.
```yaml
# Good
value_template: "{{ states('sensor.temperature') }}"
attribute_template: "{{ state_attr('climate.living_room', 'temperature') }}"
# Good - long template split with folded style
value_template: >-
{{
is_state('sensor.bedroom_co_status', 'Ok')
and is_state('sensor.kitchen_co_status', 'Ok')
}}
# Bad - single quotes outside
value_template: '{{ "some_value" == other_value }}'
# Bad - direct state object access
value_template: "{{ states.sensor.temperature.state }}"
```
### Service Action Targets *
Always use `target:` for entity/device/area targeting. Do not put `entity_id` at
the action level or inside `data:`.
```yaml
# Good
actions:
- action: light.turn_on
target:
entity_id: light.living_room
# Bad
actions:
- action: light.turn_on
entity_id: light.living_room
# Bad
actions:
- action: light.turn_on
data:
entity_id: light.living_room
```
### Scalar vs List *
If a property accepts both, use a scalar for single values. Do not wrap a single
value in a list. Do not use comma-separated strings.
```yaml
# Good
entity_id: light.living_room
entity_id:
- light.living_room
- light.office
# Bad - single value in a list
entity_id:
- light.living_room
# Bad - comma separated
entity_id: "light.living_room, light.office"
```
### List of Mappings *
When a property accepts a mapping or list of mappings (e.g., `actions`, `conditions`),
always use a list even for a single item.
```yaml
# Good
actions:
- action: light.turn_on
target:
entity_id: light.living_room
# Bad
actions:
action: light.turn_on
target:
entity_id: light.living_room
```
## Core Competencies
### YAML Configuration
- Follow the YAML Style Guide above for ALL configuration changes
- Use anchors (`&name`) and aliases (`*name`) for DRY configurations
- Understand `!include`, `!include_dir_named`, `!include_dir_list`, `!include_dir_merge_named`, `!include_dir_merge_list`
- To read/query these files from the shell use `yq` (tag-tolerant); PyYAML/Ruby crash on HA tags — see "Working with YAML on the Command Line"
- Know when to use packages for organized configuration
### Automations
- Write automations using both YAML and understand the UI format
- Understand triggers: state, time, event, webhook, mqtt, template, zone, device, etc.
- Understand conditions: state, numeric_state, time, template, zone, and, or, not
- Understand actions: service calls, delays, wait_template, choose, repeat, if/then/else
- Use trigger variables and automation context effectively
- Implement proper error handling with `continue_on_error`
### Templates (Jinja2)
- Write efficient Jinja2 templates for Home Assistant
- Use filters: `float`, `int`, `round`, `timestamp_custom`, `regex_match`, etc.
- Use functions: `states()`, `state_attr()`, `is_state()`, `is_state_attr()`, `has_value()`
- Access trigger data: `trigger.to_state`, `trigger.from_state`, `trigger.entity_id`
- Handle unavailable/unknown states gracefully
### Integrations
- Know common integrations and their configuration patterns
- Understand MQTT, REST, and template-based integrations
- Configure input_* helpers: input_boolean, input_number, input_select, input_text, input_datetime
- Set up utility_meter, statistics, and history_stats sensors
### Lovelace Dashboards
- Write Lovelace YAML configurations
- Know standard cards and their options
- Understand conditional cards, custom cards, and card-mod
- Configure views, themes, and resources
## Best Practices
1. **Always validate** - Remind users to check configuration before restarting
2. **Use secrets** - Never hardcode sensitive data; use `!secret` references
3. **Backup first** - Suggest backups before major changes
4. **Incremental changes** - Make small, testable changes
5. **Comments** - Add YAML comments explaining complex logic
6. **Naming conventions** - Use consistent entity_id naming (e.g., `sensor.room_type_name`)
## Safety Guidelines
- NEVER expose or display contents of `secrets.yaml`
- NEVER include API keys, tokens, or passwords in responses
- NEVER make changes without explicit user approval
- NEVER access `.storage/`, `.cloud/`, or other internal directories
- NEVER attempt to modify Home Assistant's internal databases or registries
- NEVER parse internal JSON files for entity/device/area information
- ALWAYS prefer MCP tools for querying runtime state over internal file access
- ALWAYS use `call_service` through MCP rather than modifying state files
- WARN users before changes that require restart vs reload
- SUGGEST backing up files before major modifications
- CHECK configuration validity when possible
- ALWAYS confirm with user before writing, editing, or deleting any file
## MCP Tools and Configuration Files
You have two complementary interfaces for working with Home Assistant:
### Configuration Files
Read and modify YAML files to understand and change Home Assistant's defined behavior:
- Review `automations.yaml` to understand existing automations
- Edit `configuration.yaml` to add new integrations
- Create new files in `packages/` for organized configuration
- Examine `custom_components/` for custom integration code
### MCP Tools (When Available)
Query and interact with the running Home Assistant instance:
- `get_states`, `search_entities`, `get_home_context` - Current entity states and compact area/domain/entity context
- `call_service` - Control devices (with confirmation)
- `get_history`, `get_logbook` - Historical data
- `get_devices`, `get_areas` - Device and area registry info
- `write_config_safe` - **Safe config writing with automatic validation, content protection, and backup**
- `validate_config` - Check configuration validity
- `get_error_log` - System errors and warnings
- `diagnose_entity` - Comprehensive entity troubleshooting
- `get_agent_capabilities` - OpenCode MCP capabilities and native HA `llm` / MCP readiness
- `get_ha_llm_development_guide` - Upstream references and starter template for native `<integration>/llm.py` providers
- `watch_firmware_update` - **Real-time firmware update monitoring** (ESPHome, WLED, Zigbee, etc.)
- `get_available_updates`, `update_component` - System update management
- `screenshot_url` - **Visual verification** of dashboards and UI pages (requires `screenshot_enabled` option)
### Choosing the Right Approach
| Task | Configuration Files | MCP Tools | hab CLI | zigporter CLI |
|------|---------------------|-----------|---------|---------------|
| Create/edit automations | Primary | **Write with `write_config_safe`** | `hab automation create` | N/A |
| Understand automation logic | Read YAML | Check state with `get_states` | `hab automation get` | N/A |
| Check current device state | Reference only | Primary (`get_home_context` for focused context) | `hab entity get` | N/A |
| Control devices | N/A | `call_service` | `hab action call` | N/A |
| Add new integrations | Primary | N/A | N/A | N/A |
| Troubleshoot issues | Review configs | `diagnose_entity`, `get_error_log` | `hab system health` | N/A |
| Check agent/LLM readiness | N/A | `get_agent_capabilities` | N/A | N/A |
| Develop native HA LLM tools | `custom_components/*/llm.py` | `get_ha_llm_development_guide` | N/A | N/A |
| Find entities | Grep YAML files | `search_entities` | `hab entity list --domain` | N/A |
| View history | N/A | `get_history` | N/A | N/A |
| **Manage dashboards** | Edit YAML | N/A | **`hab dashboard` (primary)** | N/A |
| **Verify UI changes** | N/A | **`screenshot_url`** | N/A | N/A |
| **Manage areas/floors** | N/A | `get_areas` (read-only) | **`hab area/floor` (CRUD)** | N/A |
| **Manage helpers** | N/A | N/A | **`hab helper` (primary)** | N/A |
| **Backups** | N/A | N/A | **`hab backup` (primary)** | N/A |
| **Blueprints** | N/A | N/A | **`hab blueprint` (primary)** | N/A |
| **Update firmware** | N/A | **`watch_firmware_update`** | N/A | N/A |
| **Check for updates** | N/A | `get_available_updates` | N/A | N/A |
| **Update HA Core/OS** | N/A | `update_component` | N/A | N/A |
| **Rename entity with cascade** | N/A | N/A | `hab entity update` (no cascade) | **`zigporter rename-entity` (primary)** |
| **Rename device with cascade** | N/A | N/A | `hab device update` (no cascade) | **`zigporter rename-device` (primary)** |
| **Inspect Zigbee device** | N/A | `get_entity_details` | `hab device list` | **`zigporter inspect --json` (cross-ref ZHA+Z2M+HA)** |
| **List Z2M devices** | N/A | N/A | N/A | **`zigporter list-z2m --json`** |
| **Clean up stale devices** | N/A | N/A | N/A | **`zigporter stale --action`** |
| **Fix post-migration entities** | N/A | N/A | N/A | **`zigporter fix-device --apply`** |
| **Zigbee mesh topology** | N/A | N/A | N/A | **`zigporter network-map`** |
### Update Management (IMPORTANT)
**For device firmware updates (ESPHome, WLED, Zigbee, etc.):**
Always use `watch_firmware_update` - it provides real-time visual progress:
```
watch_firmware_update(entity_id="update.device_firmware", start_update=true)
```
This single tool handles: starting the update, monitoring progress, and reporting results.
**For system updates (Core, OS, Supervisor, Apps):**
```
1. get_available_updates() -> Check what needs updating
2. update_component(component="core") -> Start update (returns job_id)
3. get_update_progress(job_id="...") -> Monitor progress
```
**Both approaches are valid and complementary.** Use configuration files for defining behavior and MCP tools for runtime interaction.
## Documentation Currency
Home Assistant releases monthly updates with new features, deprecations, and breaking changes. Your training data may be outdated. **Always verify configuration syntax against current documentation.**
### Before Writing or Modifying Configuration
**ALWAYS use these MCP tools before suggesting configuration changes:**
1. **Check the installed version**: Use `get_config` to see what HA version is running
2. **Fetch current integration docs**: Use `get_integration_docs` to get current YAML syntax
3. **Check for breaking changes**: Use `get_breaking_changes` to see recent syntax changes
4. **Write config safely**: Use `write_config_safe` with `dry_run=true` to validate before presenting to user
### Documentation Tools (MCP)
| Tool | When to Use |
|------|-------------|
| `get_integration_docs` | Before writing ANY integration configuration |
| `get_breaking_changes` | When user reports config stopped working after update |
| `write_config_safe` | **ALWAYS use to write config files** — validates, blocks accidental content loss, and auto-restores on failure |
| `check_config_syntax` | Quick ad-hoc deprecation check (write_config_safe includes this automatically) |
### Workflow Example
When a user asks "Help me set up a template sensor":
```
1. get_config() -> Check HA version (e.g., 2024.12.1)
2. get_integration_docs("template") -> Get current syntax and examples
3. read_file(path) -> Read the EXISTING file content first
4. Draft configuration: include ALL existing content + new changes
5. write_config_safe(path, yaml, dry_run=true) -> Pre-validate everything
6. If errors: fix and repeat step 5
7. Present validated config to user and get approval
8. write_config_safe(path, yaml) -> Write for real (auto backup + validation)
```
### Common Deprecation Patterns
Be especially careful with these frequently-changed areas:
- **Template sensors/binary_sensors**: `platform: template` under `sensor:` is deprecated; use top-level `template:`
- **Entity configurations**: Many moved from YAML to UI-based config
- **Trigger-based templates**: Newer syntax preferred over legacy template sensors
- **Device triggers**: Syntax evolves with new device types
- **MQTT platform syntax**: `platform: mqtt` under domain keys is deprecated; use top-level `mqtt:` key
- **Direct state access**: `states.sensor.x.state` is fragile; use `states('sensor.x')` helper
- **entity_id in data**: Deprecated; use `target:` for service call targeting
**When in doubt, fetch the docs. Never rely solely on training data for configuration syntax.**
## Common Tasks
### Creating an Automation
1. **Read the existing `automations.yaml` first** — you must include ALL existing automations in the final write
2. Understand the goal and identify trigger conditions
3. Determine required entities (search if MCP available)
4. Draft the automation YAML with clear comments
5. **Show the draft to the user and wait for approval** — the draft must contain all existing automations plus the new one
6. Only write the file after explicit user confirmation
7. Suggest testing approach
> **WARNING:** Never write partial content to ANY config file. Always read the existing file first and include ALL existing content in your write. `write_config_safe` will block writes that would reduce list entries, remove top-level keys, or significantly shrink the file — but you should verify this yourself before presenting the draft to the user.
### Troubleshooting
1. Check entity states and history (via MCP if available)
2. Review relevant configuration files
3. Check Home Assistant logs for errors
4. Identify common issues (unavailable entities, template errors, timing issues)
5. **Present findings and wait for user to request specific fixes**
### Optimizing Configuration
1. Identify redundant or inefficient patterns
2. **Present recommendations to user**
3. Wait for user to approve specific changes
4. Implement only the changes the user explicitly approves
+4349 -3783
View File
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-3dprinterpow.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-3dprinterpow.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.4 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.3 2026-07-12 # V1.3 2026-07-12
# - Added cumulative Load Energy integration sensor for Home Assistant. # - Added cumulative Load Energy integration sensor for Home Assistant.
# - Added seven-day maximum power sensor. # - Added seven-day maximum power sensor.
@@ -97,7 +98,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.POW R1" project_name: "Sonoff Technologies.POW R1"
project_version: "v1.3" project_version: "v1.4"
# Passwords and Secrets # Passwords and Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -224,12 +225,12 @@ logger:
mqtt: mqtt:
on_message: on_message:
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: relay - switch.turn_on: relay
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: relay - switch.turn_off: relay
@@ -419,7 +420,7 @@ switch:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}" topic: "${mqtt_local_status_topic}"
payload: "ON" payload: "On"
retain: false retain: false
on_turn_off: on_turn_off:
@@ -428,7 +429,7 @@ switch:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}" topic: "${mqtt_local_status_topic}"
payload: "OFF" payload: "Off"
retain: false retain: false
#:########################################################################################:# #:########################################################################################:#
@@ -469,7 +470,7 @@ script:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}" topic: "${mqtt_local_status_topic}"
payload: !lambda |- payload: !lambda |-
return id(relay).state ? "ON" : "OFF"; return id(relay).state ? "On" : "Off";
retain: false retain: false
qos: 1 qos: 1
+22 -23
View File
@@ -23,7 +23,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Generic ESP8266.D1 Mini" # Project Details project_name: "Generic ESP8266.D1 Mini" # Project Details
project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v1.2" # Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -43,7 +43,7 @@ substitutions:
wake_interval: "20s" wake_interval: "20s"
sleep_interval: "300s" sleep_interval: "300s"
mqtt_fail_sleep: "1h" # If MQTT is unavailable after boot wait, sleep this long mqtt_fail_sleep: "1h" # If MQTT is unavailable after boot wait, sleep this long
########################################################################################## ##########################################################################################
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
@@ -78,8 +78,8 @@ packages:
#common_sntp: !include common/sntp_common.yaml #common_sntp: !include common/sntp_common.yaml
#### DIAGNOSTICS Sensors #### #### DIAGNOSTICS Sensors ####
diag_basic: !include common/include_basic_diag_sensors.yaml diag_basic: !include common/include_basic_diag_sensors.yaml
diag_more: !include common/include_more_diag_sensors.yaml diag_more: !include common/include_more_diag_sensors.yaml
#diag_debug: !include common/include_debug_diag_sensors.yaml #diag_debug: !include common/include_debug_diag_sensors.yaml
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
@@ -112,7 +112,7 @@ esphome:
- logger.log: "MQTT unreachable after 30s -> entering FALLBACK sleep for ${mqtt_fail_sleep}." - logger.log: "MQTT unreachable after 30s -> entering FALLBACK sleep for ${mqtt_fail_sleep}."
- deep_sleep.enter: - deep_sleep.enter:
id: deep_sleep_1 id: deep_sleep_1
sleep_duration: ${mqtt_fail_sleep} # override only this cycle sleep_duration: ${mqtt_fail_sleep} # override only this cycle
else: else:
- logger.log: "MQTT connected; awaiting '${mqtt_command_topic}/deepsleep' command." - logger.log: "MQTT connected; awaiting '${mqtt_command_topic}/deepsleep' command."
@@ -124,14 +124,14 @@ esphome:
esp8266: esp8266:
board: d1_mini board: d1_mini
framework: framework:
version: latest #recommended, latest or dev version: recommended # latest or dev
########################################################################################## ##########################################################################################
# ESPHome Logging Enable # ESPHome Logging Enable
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
########################################################################################## ##########################################################################################
logger: logger:
level: "${log_level}" #INFO Level suggested, or DEBUG for testing level: "${log_level}" #INFO Level suggested, or DEBUG for testing
#baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM)
#esp8266_store_log_strings_in_flash: false #esp8266_store_log_strings_in_flash: false
#tx_buffer_size: 64 #tx_buffer_size: 64
@@ -159,13 +159,13 @@ mqtt:
# Control deep sleep over MQTT # Control deep sleep over MQTT
on_message: on_message:
- topic: ${mqtt_command_topic}/deepsleep - topic: ${mqtt_command_topic}/deepsleep
payload: "ON" payload: "On"
then: then:
- deep_sleep.allow: deep_sleep_1 - deep_sleep.allow: deep_sleep_1
- logger.log: "Deep sleep ALLOWED via MQTT. Device will sleep when run_duration elapses." - logger.log: "Deep sleep ALLOWED via MQTT. Device will sleep when run_duration elapses."
- topic: ${mqtt_command_topic}/deepsleep - topic: ${mqtt_command_topic}/deepsleep
payload: "OFF" payload: "Off"
then: then:
- deep_sleep.prevent: deep_sleep_1 - deep_sleep.prevent: deep_sleep_1
- logger.log: "Deep sleep PREVENTED via MQTT." - logger.log: "Deep sleep PREVENTED via MQTT."
@@ -193,19 +193,19 @@ sensor:
filters: filters:
- multiply: 3.3 - multiply: 3.3
- calibrate_linear: - calibrate_linear:
- 3.11 -> 14.00 - 3.11 -> 14.00
- 3.00 -> 13.50 - 3.00 -> 13.50
- 2.89 -> 13.00 - 2.89 -> 13.00
- 2.77 -> 12.50 - 2.77 -> 12.50
- 2.67 -> 12.00 - 2.67 -> 12.00
- 2.55 -> 11.50 - 2.55 -> 11.50
- 2.45 -> 11.00 - 2.45 -> 11.00
- 2.34 -> 10.50 - 2.34 -> 10.50
- 2.22 -> 10.00 - 2.22 -> 10.00
- 2.11 -> 09.50 - 2.11 -> 09.50
- 2.00 -> 09.00 - 2.00 -> 09.00
- delta: 0.05 # publish immediately if change >= 0.05 V - delta: 0.05 # publish immediately if change >= 0.05 V
- throttle: 2s # avoid bursts if noisy - throttle: 2s # avoid bursts if noisy
on_value: on_value:
then: then:
- mqtt.publish: - mqtt.publish:
@@ -216,4 +216,3 @@ sensor:
char buf[10]; char buf[10];
snprintf(buf, sizeof(buf), "%.2f", x); snprintf(buf, sizeof(buf), "%.2f", x);
return std::string(buf); return std::string(buf);
+15 -3
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm1arlecbulb.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm1arlecbulb.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v1.5 2026-07-26 Republish retained MQTT status whenever the broker reconnects
# v1.4 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# v1.3 2026-07-20 Simplified local MQTT command and status topics to the device root # v1.3 2026-07-20 Simplified local MQTT command and status topics to the device root
# v1.2 2026-02-25 Updated yaml to zorruno layout V1.1 # v1.2 2026-02-25 Updated yaml to zorruno layout V1.1
# v1.1 2026-02-21 Add "Jump Fade Up/Down" switch + configurable Jump Fade (%) # v1.1 2026-02-21 Add "Jump Fade Up/Down" switch + configurable Jump Fade (%)
@@ -56,7 +58,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Grid Connect GLD120HA RGBWW.Arlec" project_name: "Grid Connect GLD120HA RGBWW.Arlec"
project_version: "v1.3" project_version: "v1.5"
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
# Re-using your existing bulb flasher secrets (adjust if you prefer per-device secrets) # Re-using your existing bulb flasher secrets (adjust if you prefer per-device secrets)
@@ -74,8 +76,8 @@ substitutions:
mqtt_local_status_main_topic: !secret mqtt_status_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic
mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}"
mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}"
mqtt_local_device_command_ON: "ON" mqtt_local_device_command_ON: "On"
mqtt_local_device_command_OFF: "OFF" mqtt_local_device_command_OFF: "Off"
# Device Specific Settings # Device Specific Settings
log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE
@@ -300,6 +302,16 @@ logger:
# MQTT COMMANDS (adds device-specific triggers to common MQTT) # MQTT COMMANDS (adds device-specific triggers to common MQTT)
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
on_connect:
then:
- mqtt.publish:
topic: "${mqtt_local_status_topic}"
payload: !lambda |-
return id(bulb_light).current_values.is_on()
? "${mqtt_local_device_command_ON}"
: "${mqtt_local_device_command_OFF}";
retain: true
on_message: on_message:
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
+6 -20
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm2ceilingfan.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm2ceilingfan.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.1 2026-03-04 Updated yaml to zorruno layout V1.1 # V1.1 2026-03-04 Updated yaml to zorruno layout V1.1
# V1.0 2025-07-21 First Setup (and replacement of Tasmota) # V1.0 2025-07-21 First Setup (and replacement of Tasmota)
#:########################################################################################:# #:########################################################################################:#
@@ -43,7 +44,6 @@
# - Accurate time is NOT needed (SNTP not required) for core operation (no schedules/timeclocks used) # - Accurate time is NOT needed (SNTP not required) for core operation (no schedules/timeclocks used)
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -57,7 +57,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff iFan02" # Project Details project_name: "Sonoff Technologies.Sonoff iFan02" # Project Details
project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v1.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords and Secrets # Passwords and Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -85,7 +85,6 @@ substitutions:
switch_3_name: "Fan 3 Relay" switch_3_name: "Fan 3 Relay"
switch_4_name: "Fan 4 Relay" switch_4_name: "Fan 4 Relay"
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html # https://esphome.io/components/packages.html
@@ -125,7 +124,6 @@ packages:
diag_debug: !include common/include_debug_diag_sensors.yaml diag_debug: !include common/include_debug_diag_sensors.yaml
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
#:########################################################################################:# #:########################################################################################:#
# ESPHOME: # ESPHOME:
# https://esphome.io/components/esphome.html # https://esphome.io/components/esphome.html
@@ -149,7 +147,6 @@ esphome:
# - "-fno-exceptions" # strip C++ exceptions # - "-fno-exceptions" # strip C++ exceptions
# - "-fno-rtti" # strip C++ RTTI # - "-fno-rtti" # strip C++ RTTI
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK: # ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266/ # https://esphome.io/components/esp8266/
@@ -165,7 +162,6 @@ preferences:
mdns: mdns:
disabled: true # Disabling will make the build file smaller (and it is still available via static IP) disabled: true # Disabling will make the build file smaller (and it is still available via static IP)
#:########################################################################################:# #:########################################################################################:#
# GLOBAL VARIABLES: # GLOBAL VARIABLES:
# https://esphome.io/guides/automations.html#global-variables # https://esphome.io/guides/automations.html#global-variables
@@ -176,7 +172,6 @@ globals:
restore_value: true restore_value: true
initial_value: "0" initial_value: "0"
#:########################################################################################:# #:########################################################################################:#
# LOGGING: ESPHome Logging Enable # LOGGING: ESPHome Logging Enable
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
@@ -185,7 +180,6 @@ logger:
level: "${log_level}" # INFO suggested, or DEBUG for testing level: "${log_level}" # INFO suggested, or DEBUG for testing
baud_rate: 0 # set to 0 for no logging via UART (UART0 used for fan MCU sniffing) baud_rate: 0 # set to 0 for no logging via UART (UART0 used for fan MCU sniffing)
#:########################################################################################:# #:########################################################################################:#
# UART: # UART:
# Fan MCU / RF Remote Sniff (iFan02 -> ESP over UART0) # Fan MCU / RF Remote Sniff (iFan02 -> ESP over UART0)
@@ -203,7 +197,6 @@ uart:
# NOTE: If no frames appear at either 9600 or 19200, try moving rx_pin to GPIO13 and reflash: # NOTE: If no frames appear at either 9600 or 19200, try moving rx_pin to GPIO13 and reflash:
# rx_pin: GPIO13 # rx_pin: GPIO13
#:########################################################################################:# #:########################################################################################:#
# INTERVAL COMPONENT: # INTERVAL COMPONENT:
# https://esphome.io/components/interval.html # https://esphome.io/components/interval.html
@@ -235,7 +228,6 @@ interval:
frame.clear(); frame.clear();
} }
#:########################################################################################:# #:########################################################################################:#
# TEXT SENSORS COMPONENT: # TEXT SENSORS COMPONENT:
# https://esphome.io/components/text_sensor/index.html # https://esphome.io/components/text_sensor/index.html
@@ -246,7 +238,6 @@ text_sensor:
name: "iFan02 Remote Last Frame" name: "iFan02 Remote Last Frame"
update_interval: never update_interval: never
#:########################################################################################:# #:########################################################################################:#
# MQTT: # MQTT:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
@@ -255,12 +246,12 @@ mqtt:
on_message: on_message:
# Light control # Light control
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}/light/set"
payload: "ON" payload: "On"
then: then:
- light.turn_on: ifan02_light - light.turn_on: ifan02_light
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}/light/set"
payload: "OFF" payload: "Off"
then: then:
- light.turn_off: ifan02_light - light.turn_off: ifan02_light
@@ -297,7 +288,6 @@ mqtt:
id: ifan02_fan id: ifan02_fan
speed: !lambda "return id(speed_value);" speed: !lambda "return id(speed_value);"
#:########################################################################################:# #:########################################################################################:#
# SWITCH COMPONENT: # SWITCH COMPONENT:
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
@@ -327,7 +317,6 @@ switch:
restore_mode: RESTORE_DEFAULT_OFF restore_mode: RESTORE_DEFAULT_OFF
internal: true internal: true
#:########################################################################################:# #:########################################################################################:#
# SELECT COMPONENT: # SELECT COMPONENT:
# https://esphome.io/components/select/index.html # https://esphome.io/components/select/index.html
@@ -392,7 +381,6 @@ select:
id: ifan02_fan id: ifan02_fan
speed: 3 speed: 3
#:########################################################################################:# #:########################################################################################:#
# OUTPUT COMPONENT: # OUTPUT COMPONENT:
# https://esphome.io/components/output/ # https://esphome.io/components/output/
@@ -430,7 +418,6 @@ output:
id(fan4sw).turn_on(); id(fan4sw).turn_on();
} }
#:########################################################################################:# #:########################################################################################:#
# LIGHT COMPONENT: # LIGHT COMPONENT:
# https://esphome.io/components/light/ # https://esphome.io/components/light/
@@ -445,12 +432,11 @@ light:
on_turn_on: on_turn_on:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}/light/state"
payload: "ON" payload: "On"
on_turn_off: on_turn_off:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}/light/state"
payload: "OFF" payload: "Off"
#:########################################################################################:# #:########################################################################################:#
# FAN COMPONENT: # FAN COMPONENT:
+6 -17
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm3ceilingfan.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm3ceilingfan.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.1 2026-03-05 Updated yaml to zorruno layout V1.1 # V1.1 2026-03-05 Updated yaml to zorruno layout V1.1
# V1.0 2025-07-21 First Setup (and replacement of Tasmota) # V1.0 2025-07-21 First Setup (and replacement of Tasmota)
#:########################################################################################:# #:########################################################################################:#
@@ -43,7 +44,6 @@
# - Accurate time is NOT needed (SNTP not required) for core operation # - Accurate time is NOT needed (SNTP not required) for core operation
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -57,7 +57,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff iFan02" # Project Details project_name: "Sonoff Technologies.Sonoff iFan02" # Project Details
project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v1.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords and Secrets # Passwords and Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -85,7 +85,6 @@ substitutions:
switch_3_name: "Fan 3 Relay" switch_3_name: "Fan 3 Relay"
switch_4_name: "Fan 4 Relay" switch_4_name: "Fan 4 Relay"
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html # https://esphome.io/components/packages.html
@@ -125,7 +124,6 @@ packages:
diag_debug: !include common/include_debug_diag_sensors.yaml diag_debug: !include common/include_debug_diag_sensors.yaml
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
#:########################################################################################:# #:########################################################################################:#
# ESPHOME: # ESPHOME:
# https://esphome.io/components/esphome.html # https://esphome.io/components/esphome.html
@@ -146,7 +144,6 @@ esphome:
topic: "${mqtt_local_status_topic}/speed/state" topic: "${mqtt_local_status_topic}/speed/state"
payload: !lambda "return to_string(id(speed_value));" payload: !lambda "return to_string(id(speed_value));"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK: # ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266/ # https://esphome.io/components/esp8266/
@@ -161,7 +158,6 @@ preferences:
mdns: mdns:
disabled: true # Disabling will make the build file smaller (and it is still available via static IP) disabled: true # Disabling will make the build file smaller (and it is still available via static IP)
#:########################################################################################:# #:########################################################################################:#
# GLOBAL VARIABLES: # GLOBAL VARIABLES:
# https://esphome.io/guides/automations.html#global-variables # https://esphome.io/guides/automations.html#global-variables
@@ -172,7 +168,6 @@ globals:
restore_value: true restore_value: true
initial_value: "0" initial_value: "0"
#:########################################################################################:# #:########################################################################################:#
# LOGGING: ESPHome Logging Enable # LOGGING: ESPHome Logging Enable
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
@@ -181,7 +176,6 @@ logger:
level: "${log_level}" # INFO suggested, or DEBUG for testing level: "${log_level}" # INFO suggested, or DEBUG for testing
baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things
#:########################################################################################:# #:########################################################################################:#
# MQTT: # MQTT:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
@@ -190,12 +184,12 @@ mqtt:
on_message: on_message:
# Light control # Light control
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}/light/set"
payload: "ON" payload: "On"
then: then:
- light.turn_on: ifan02_light - light.turn_on: ifan02_light
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}/light/set"
payload: "OFF" payload: "Off"
then: then:
- light.turn_off: ifan02_light - light.turn_off: ifan02_light
@@ -232,7 +226,6 @@ mqtt:
id: ifan02_fan id: ifan02_fan
speed: !lambda "return id(speed_value);" speed: !lambda "return id(speed_value);"
#:########################################################################################:# #:########################################################################################:#
# SWITCH COMPONENT: # SWITCH COMPONENT:
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
@@ -262,7 +255,6 @@ switch:
restore_mode: RESTORE_DEFAULT_OFF restore_mode: RESTORE_DEFAULT_OFF
internal: true internal: true
#:########################################################################################:# #:########################################################################################:#
# SELECT COMPONENT: # SELECT COMPONENT:
# https://esphome.io/components/select/index.html # https://esphome.io/components/select/index.html
@@ -327,7 +319,6 @@ select:
id: ifan02_fan id: ifan02_fan
speed: 3 speed: 3
#:########################################################################################:# #:########################################################################################:#
# OUTPUT COMPONENT: # OUTPUT COMPONENT:
# https://esphome.io/components/output/ # https://esphome.io/components/output/
@@ -365,7 +356,6 @@ output:
id(fan4sw).turn_on(); id(fan4sw).turn_on();
} }
#:########################################################################################:# #:########################################################################################:#
# LIGHT COMPONENT: # LIGHT COMPONENT:
# https://esphome.io/components/light/ # https://esphome.io/components/light/
@@ -380,12 +370,11 @@ light:
on_turn_on: on_turn_on:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}/light/state"
payload: "ON" payload: "On"
on_turn_off: on_turn_off:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}/light/state"
payload: "OFF" payload: "Off"
#:########################################################################################:# #:########################################################################################:#
# FAN COMPONENT: # FAN COMPONENT:
+5 -14
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm3lights.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm3lights.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V3.7 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V3.6 2026-03-05 Updated yaml to zorruno layout V1.1 # V3.6 2026-03-05 Updated yaml to zorruno layout V1.1
# V3.5 2025-07-24 YAML tidyups # V3.5 2025-07-24 YAML tidyups
#:########################################################################################:# #:########################################################################################:#
@@ -43,7 +44,6 @@
# - Accurate time is NOT needed (SNTP not required) for core operation # - Accurate time is NOT needed (SNTP not required) for core operation
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -57,7 +57,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Double" # Project Details project_name: "Zemismart Technologies.KS-811 Double" # Project Details
project_version: "v3.6" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v3.7" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords and Secrets # Passwords and Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -83,18 +83,17 @@ substitutions:
# Remote Light # Remote Light
mqtt_remote_device_command_topic1: "${mqtt_local_command_main_topic}/${mqtt_remote_device_name}/light/set" mqtt_remote_device_command_topic1: "${mqtt_local_command_main_topic}/${mqtt_remote_device_name}/light/set"
mqtt_remote_status_topic1: "${mqtt_local_status_main_topic}/${mqtt_remote_device_name}/light/state" mqtt_remote_status_topic1: "${mqtt_local_status_main_topic}/${mqtt_remote_device_name}/light/state"
mqtt_remote_device_command_ON: "ON" mqtt_remote_device_command_ON: "On"
mqtt_remote_device_command_OFF: "OFF" mqtt_remote_device_command_OFF: "Off"
# Remote Fan Speed (used for All Off) # Remote Fan Speed (used for All Off)
mqtt_remote_device_command_topic2: "${mqtt_local_command_main_topic}/${mqtt_remote_device_name}/speed/set" mqtt_remote_device_command_topic2: "${mqtt_local_command_main_topic}/${mqtt_remote_device_name}/speed/set"
mqtt_remote_device_command_0: "0" mqtt_remote_device_command_0: "0"
# Switch Naming # Switch Naming
switch_1_name: "Main Lights" # Nothing physically connected to this output (ifan02 light is the real load) switch_1_name: "Main Lights" # Nothing physically connected to this output (ifan02 light is the real load)
switch_2_name: "All Lights Off" # Nothing physically connected to this output switch_2_name: "All Lights Off" # Nothing physically connected to this output
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html # https://esphome.io/components/packages.html
@@ -134,7 +133,6 @@ packages:
diag_debug: !include common/include_debug_diag_sensors.yaml diag_debug: !include common/include_debug_diag_sensors.yaml
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
#:########################################################################################:# #:########################################################################################:#
# ESPHOME: # ESPHOME:
# https://esphome.io/components/esphome.html # https://esphome.io/components/esphome.html
@@ -148,7 +146,6 @@ esphome:
name: "${project_name}" name: "${project_name}"
version: "${project_version}" version: "${project_version}"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK: # ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266/ # https://esphome.io/components/esp8266/
@@ -158,7 +155,6 @@ esp8266:
early_pin_init: false # Recommended false where switches are involved. Defaults to true. early_pin_init: false # Recommended false where switches are involved. Defaults to true.
board_flash_mode: dout # Default is dout board_flash_mode: dout # Default is dout
#:########################################################################################:# #:########################################################################################:#
# LOGGING: ESPHome Logging Enable # LOGGING: ESPHome Logging Enable
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
@@ -169,7 +165,6 @@ logger:
#esp8266_store_log_strings_in_flash: false #esp8266_store_log_strings_in_flash: false
#tx_buffer_size: 64 #tx_buffer_size: 64
#:########################################################################################:# #:########################################################################################:#
# GLOBAL VARIABLES: # GLOBAL VARIABLES:
# https://esphome.io/guides/automations.html#global-variables # https://esphome.io/guides/automations.html#global-variables
@@ -180,7 +175,6 @@ globals:
restore_value: false restore_value: false
initial_value: "0" initial_value: "0"
#:########################################################################################:# #:########################################################################################:#
# STATUS LED: # STATUS LED:
# https://esphome.io/components/status_led.html # https://esphome.io/components/status_led.html
@@ -190,7 +184,6 @@ status_led:
number: GPIO2 number: GPIO2
inverted: true inverted: true
#:########################################################################################:# #:########################################################################################:#
# BINARY SENSORS: # BINARY SENSORS:
# https://esphome.io/components/binary_sensor/ # https://esphome.io/components/binary_sensor/
@@ -255,7 +248,6 @@ binary_sensor:
qos: 0 qos: 0
retain: false retain: false
#:########################################################################################:# #:########################################################################################:#
# SWITCH COMPONENT: # SWITCH COMPONENT:
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
@@ -272,7 +264,6 @@ switch:
pin: GPIO12 pin: GPIO12
id: Relay_2 id: Relay_2
#:########################################################################################:# #:########################################################################################:#
# MQTT: # MQTT:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
File diff suppressed because it is too large Load Diff
+17 -5
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-breakfastbarleds.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-breakfastbarleds.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.3 2026-07-26 Republish retained MQTT status whenever the broker reconnects
# V2.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V2.1 2026-07-20 Simplified local MQTT command and status topics to the device root # V2.1 2026-07-20 Simplified local MQTT command and status topics to the device root
# V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices # V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices
# V1.0 2025-08-17 First setup (and replacement of Tasmota) # V1.0 2025-08-17 First setup (and replacement of Tasmota)
@@ -48,10 +50,10 @@
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
# Local MQTT light control: # Local MQTT light control:
# - ${mqtt_local_command_topic} -> ON,OFF # - ${mqtt_local_command_topic} -> On,Off
# #
# Local MQTT light status: # Local MQTT light status:
# - ${mqtt_local_status_topic} -> ON,OFF # - ${mqtt_local_status_topic} -> On,Off
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, but Network and MQTT ONLINE # a) Home Assistant OFFLINE, but Network and MQTT ONLINE
@@ -81,7 +83,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Manufacturer before the dot, device after the dot. project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Manufacturer before the dot, device after the dot.
project_version: "v2.1" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version project_version: "v2.3" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -98,8 +100,8 @@ substitutions:
mqtt_local_status_main_topic: !secret mqtt_status_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic
mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA
mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA
mqtt_local_device_command_ON: "ON" mqtt_local_device_command_ON: "On"
mqtt_local_device_command_OFF: "OFF" mqtt_local_device_command_OFF: "Off"
# Device Specific Settings # Device Specific Settings
log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE
@@ -343,6 +345,16 @@ status_led:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
on_connect:
then:
- mqtt.publish:
topic: "${mqtt_local_status_topic}"
payload: !lambda |-
return id(mosfet_leds).current_values.is_on()
? "${mqtt_local_device_command_ON}"
: "${mqtt_local_device_command_OFF}";
retain: true
on_message: on_message:
# Light control to ramp up # Light control to ramp up
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
+8 -7
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-centralstairs-bottom.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-centralstairs-bottom.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V3.10 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V3.9 2026-07-21 Added retained MQTT status mirroring for HA-independent two-way switching # V3.9 2026-07-21 Added retained MQTT status mirroring for HA-independent two-way switching
# V3.8 2026-06-09 Added Downstairs Lights Bulk Activation virtual switch toggled by Button 1 double-click # V3.8 2026-06-09 Added Downstairs Lights Bulk Activation virtual switch toggled by Button 1 double-click
# V3.7 2025-09-24 Upload to this device # V3.7 2025-09-24 Upload to this device
@@ -24,12 +25,12 @@
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
# Remote device 1 (Main Stair Lights): # Remote device 1 (Main Stair Lights):
# - Command topic: ${mqtt_command_topic_1} -> ON,OFF # - Command topic: ${mqtt_command_topic_1} -> On,Off
# - Status topic: ${mqtt_status_topic_1} -> ON,OFF # - Status topic: ${mqtt_status_topic_1} -> On,Off
# #
# Remote device 2 (Stair Footer Lights): # Remote device 2 (Stair Footer Lights):
# - Command topic: ${mqtt_command_topic_2} -> ON,OFF # - Command topic: ${mqtt_command_topic_2} -> On,Off
# - Status topic: ${mqtt_status_topic_2} -> ON,OFF # - Status topic: ${mqtt_status_topic_2} -> On,Off
# #
# HA virtual switch: # HA virtual switch:
# - Downstairs Lights Bulk Activation is exposed as a virtual switch for Home Assistant automations # - Downstairs Lights Bulk Activation is exposed as a virtual switch for Home Assistant automations
@@ -84,7 +85,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Double" # Project Details project_name: "Zemismart Technologies.KS-811 Double" # Project Details
project_version: "v3.9" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v3.10" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# MQTT Controls # MQTT Controls
mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_command_main_topic: !secret mqtt_command_main_topic
@@ -93,8 +94,8 @@ substitutions:
mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}" mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}"
mqtt_command_topic_2: "${mqtt_command_main_topic}/${mqtt_device_name_2}" mqtt_command_topic_2: "${mqtt_command_main_topic}/${mqtt_device_name_2}"
mqtt_status_topic_2: "${mqtt_status_main_topic}/${mqtt_device_name_2}" mqtt_status_topic_2: "${mqtt_status_main_topic}/${mqtt_device_name_2}"
mqtt_command_ON: "ON" mqtt_command_ON: "On"
mqtt_command_OFF: "OFF" mqtt_command_OFF: "Off"
# General Settings # General Settings
log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
+8 -7
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-centralstairs-top.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-centralstairs-top.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V3.10 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V3.9 2026-07-21 Added retained MQTT status mirroring for HA-independent two-way switching # V3.9 2026-07-21 Added retained MQTT status mirroring for HA-independent two-way switching
# V3.8 2026-04-26 Added Downstairs Lights Bulk Activation virtual switch toggled by Button 1 double-click # V3.8 2026-04-26 Added Downstairs Lights Bulk Activation virtual switch toggled by Button 1 double-click
# V3.7 2025-09-24 Upload to this device # V3.7 2025-09-24 Upload to this device
@@ -24,12 +25,12 @@
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
# Remote device 1 (Main Stair Lights): # Remote device 1 (Main Stair Lights):
# - Command topic: ${mqtt_command_topic_1} -> ON,OFF # - Command topic: ${mqtt_command_topic_1} -> On,Off
# - Status topic: ${mqtt_status_topic_1} -> ON,OFF # - Status topic: ${mqtt_status_topic_1} -> On,Off
# #
# Remote device 2 (Stair Footer Lights): # Remote device 2 (Stair Footer Lights):
# - Command topic: ${mqtt_command_topic_2} -> ON,OFF # - Command topic: ${mqtt_command_topic_2} -> On,Off
# - Status topic: ${mqtt_status_topic_2} -> ON,OFF # - Status topic: ${mqtt_status_topic_2} -> On,Off
# #
# HA virtual switch: # HA virtual switch:
# - Downstairs Lights Bulk Activation is exposed as a virtual switch for Home Assistant automations # - Downstairs Lights Bulk Activation is exposed as a virtual switch for Home Assistant automations
@@ -84,7 +85,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Double" # Project Details project_name: "Zemismart Technologies.KS-811 Double" # Project Details
project_version: "v3.9" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v3.10" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# MQTT Controls # MQTT Controls
mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_command_main_topic: !secret mqtt_command_main_topic
@@ -93,8 +94,8 @@ substitutions:
mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}" mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}"
mqtt_command_topic_2: "${mqtt_command_main_topic}/${mqtt_device_name_2}" mqtt_command_topic_2: "${mqtt_command_main_topic}/${mqtt_device_name_2}"
mqtt_status_topic_2: "${mqtt_status_main_topic}/${mqtt_device_name_2}" mqtt_status_topic_2: "${mqtt_status_main_topic}/${mqtt_device_name_2}"
mqtt_command_ON: "ON" mqtt_command_ON: "On"
mqtt_command_OFF: "OFF" mqtt_command_OFF: "Off"
# General Settings # General Settings
log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
+6 -5
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-datacupboardfans.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-datacupboardfans.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.4 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.3 2026-02-20 Remove invalid allow_other_uses on pulse_counter pins (ESPHome 2026.2.x) # V1.3 2026-02-20 Remove invalid allow_other_uses on pulse_counter pins (ESPHome 2026.2.x)
# V1.2 2026-02-20 Use common SNTP package, and publish fan fault/status via interval script # V1.2 2026-02-20 Use common SNTP package, and publish fan fault/status via interval script
# V1.1 2026-02-20 Fix template binary_sensor update method for ESPHome 2026.2.x # V1.1 2026-02-20 Fix template binary_sensor update method for ESPHome 2026.2.x
@@ -52,7 +53,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Yunshan.HW-622 ESP8266MOD Relay Board" project_name: "Yunshan.HW-622 ESP8266MOD Relay Board"
project_version: "v1.3" project_version: "v1.4"
# Passwords and Secrets (Unfortunately, you cannot use substitutions inside secret names) # Passwords and Secrets (Unfortunately, you cannot use substitutions inside secret names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -624,20 +625,20 @@ mqtt:
on_message: on_message:
# Relay control # Relay control
- topic: "${mqtt_main_topic}/relay/set" - topic: "${mqtt_main_topic}/relay/set"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: fan_relay - switch.turn_on: fan_relay
- topic: "${mqtt_main_topic}/relay/set" - topic: "${mqtt_main_topic}/relay/set"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: fan_relay - switch.turn_off: fan_relay
# Override control # Override control
- topic: "${mqtt_main_topic}/override/set" - topic: "${mqtt_main_topic}/override/set"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: override_fans_on - switch.turn_on: override_fans_on
- topic: "${mqtt_main_topic}/override/set" - topic: "${mqtt_main_topic}/override/set"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: override_fans_on - switch.turn_off: override_fans_on
+15 -3
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstairskitchleds.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstairskitchleds.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v2.4 2026-07-26 Republish retained MQTT status whenever the broker reconnects
# v2.3 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# v2.2 2026-07-20 Simplified local MQTT command and status topics to the device root # v2.2 2026-07-20 Simplified local MQTT command and status topics to the device root
# v2.1 2026-02-25 Updated yaml to zorruno layout V1.1 # v2.1 2026-02-25 Updated yaml to zorruno layout V1.1
# v2.0 2025-09-15 A bunch of fixes. # v2.0 2025-09-15 A bunch of fixes.
@@ -95,7 +97,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot. project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot.
project_version: "v2.2" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version project_version: "v2.4" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -112,8 +114,8 @@ substitutions:
mqtt_local_status_main_topic: !secret mqtt_status_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic
mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA
mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA
mqtt_local_device_command_ON: "ON" mqtt_local_device_command_ON: "On"
mqtt_local_device_command_OFF: "OFF" mqtt_local_device_command_OFF: "Off"
# Device Specific Settings # Device Specific Settings
log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE
@@ -355,6 +357,16 @@ status_led:
# MQTT: Device-specific command triggers # MQTT: Device-specific command triggers
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
on_connect:
then:
- mqtt.publish:
topic: "${mqtt_local_status_topic}"
payload: !lambda |-
return id(mosfet_leds).current_values.is_on()
? "${mqtt_local_device_command_ON}"
: "${mqtt_local_device_command_OFF}";
retain: true
on_message: on_message:
# Light control to ramp up # Light control to ramp up
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
+4 -3
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstkitchlights.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstkitchlights.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v2.3 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# v2.2 2026-07-20 Restored direct MQTT control of pantry LEDs using the flattened topic # v2.2 2026-07-20 Restored direct MQTT control of pantry LEDs using the flattened topic
# v2.1 2026-02-25 Updated yaml to zorruno layout V1.1 # v2.1 2026-02-25 Updated yaml to zorruno layout V1.1
# v2.0 2025-06-05 YAML tidyups # v2.0 2025-06-05 YAML tidyups
@@ -57,7 +58,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v2.2" project_version: "v2.3"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -72,8 +73,8 @@ substitutions:
mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_command_main_topic: !secret mqtt_command_main_topic
mqtt_remote_device_name: "downstairskitchen-pantryleds" mqtt_remote_device_name: "downstairskitchen-pantryleds"
mqtt_remote_device_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}" mqtt_remote_device_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}"
mqtt_remote_device_command_on: "ON" mqtt_remote_device_command_on: "On"
mqtt_remote_device_command_off: "OFF" mqtt_remote_device_command_off: "Off"
# Device Settings # Device Settings
log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
+5 -1
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungeentry.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungeentry.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v3.10 2026-07-26 Made the physical main switch the sole retained status publisher
# v3.9 2026-07-25 Added on_connect republish and state guards for reliable two-way sync
# v3.8 2026-07-20 Updated remote MQTT topics for the flattened downstairs lounge main lights topic # v3.8 2026-07-20 Updated remote MQTT topics for the flattened downstairs lounge main lights topic
# v3.7 2026-02-25 Updated yaml to zorruno layout V1.1 # v3.7 2026-02-25 Updated yaml to zorruno layout V1.1
# v3.6 2025-07-24 YAML tidyups # v3.6 2025-07-24 YAML tidyups
@@ -59,7 +61,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Single" project_name: "Zemismart Technologies.KS-811 Single"
project_version: "v3.8" project_version: "v3.10"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -162,6 +164,8 @@ logger:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
# The physical main switch is the sole retained status publisher. This remote
# mirror only consumes that authoritative state and publishes commands.
on_message: on_message:
# Mirror remote state onto Relay_1 (only toggle if a change is needed) # Mirror remote state onto Relay_1 (only toggle if a change is needed)
- topic: "${mqtt_remote_status_topic}" - topic: "${mqtt_remote_status_topic}"
+111 -12
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungemain.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungemain.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v3.8 2026-07-25 Two-way MQTT sync with entry switch; scripts, template switches,
# on_connect republish, state guards, internal relays
# v3.7 2026-07-20 Simplified local MQTT command and status topics to the device root # v3.7 2026-07-20 Simplified local MQTT command and status topics to the device root
# v3.6 2026-02-25 Updated yaml to zorruno layout V1.1 # v3.6 2026-02-25 Updated yaml to zorruno layout V1.1
# v3.5 2025-07-28 YAML tidyups # v3.5 2025-07-28 YAML tidyups
@@ -16,10 +18,12 @@
#:########################################################################################:# #:########################################################################################:#
# OPERATION NOTES: # OPERATION NOTES:
# - 3-gang KS-811 triple switch. # - 3-gang KS-811 triple switch.
# - Button 1 toggles Relay 1 (Main Lights). Relay 1 also supports local MQTT ON/OFF commands. # - Button 1 toggles Relay 1 (Main Lights) via script that publishes MQTT command.
# - Relay 1 publishes MQTT state updates on turn on/off.
# - Button 2 toggles Relay 2 (Back Wall Lights). # - Button 2 toggles Relay 2 (Back Wall Lights).
# - Button 3 toggles Relay 3 (Spare). NOTE: nothing connected to this output (as noted). # - Button 3 toggles Relay 3 (Spare). NOTE: nothing connected to this output.
# - Template switches expose HA control that also publishes MQTT commands.
# - Physical relays publish retained MQTT status on state changes.
# - State guards prevent ping-pong between local and remote control.
# - GPIO16 does not support interrupts; polling is used for Button 1 (suppresses warning). # - GPIO16 does not support interrupts; polling is used for Button 1 (suppresses warning).
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
@@ -30,7 +34,10 @@
# #
# - Local status topic (Main Lights): # - Local status topic (Main Lights):
# ${mqtt_local_status_topic} # ${mqtt_local_status_topic}
# Payload "On" / "Off" published when Relay 1 changes state # Payload "On" / "Off" published retained when Relay 1 changes state
#
# - Button presses and HA control publish command topics.
# - Relay callbacks publish retained status only (no command ping-pong).
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, WiFi OK # a) Home Assistant OFFLINE, WiFi OK
@@ -59,7 +66,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v3.7" project_version: "v3.8"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -76,6 +83,9 @@ substitutions:
log_level: "INFO" log_level: "INFO"
update_interval: "60s" update_interval: "60s"
# Default relay restore mode
relay_restore_mode: "RESTORE_DEFAULT_OFF"
# MQTT LOCAL Controls # MQTT LOCAL Controls
mqtt_device_name: "downst-lounge-main-lights" mqtt_device_name: "downst-lounge-main-lights"
mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}"
@@ -154,16 +164,33 @@ logger:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
# Republish current relay states whenever MQTT reconnects so retained status stays accurate
# for subscribers that reconnect later.
on_connect:
- mqtt.publish:
topic: "${mqtt_local_status_topic}"
payload: !lambda |-
return id(relay_1).state ? "On" : "Off";
retain: true
on_message: on_message:
# Main Lights control (Relay 1) # Main Lights control (Relay 1) — state guard prevents ping-pong
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
payload: "On" payload: "On"
then: then:
- switch.turn_on: relay_1 - if:
condition:
lambda: "return !id(relay_1).state;"
then:
- switch.turn_on: relay_1
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
payload: "Off" payload: "Off"
then: then:
- switch.turn_off: relay_1 - if:
condition:
lambda: "return id(relay_1).state;"
then:
- switch.turn_off: relay_1
#:########################################################################################:# #:########################################################################################:#
# STATUS LED # STATUS LED
@@ -174,6 +201,52 @@ status_led:
number: GPIO2 number: GPIO2
inverted: true inverted: true
#:########################################################################################:#
# SCRIPTS
# https://esphome.io/components/script.html
#:########################################################################################:#
script:
# Local/HA requested ON for Main Lights. Change the local relay immediately, then
# publish a non-retained command so any linked switch follows.
- id: mainlights_on
mode: restart
then:
- if:
condition:
lambda: "return !id(relay_1).state;"
then:
- switch.turn_on: relay_1
- mqtt.publish:
topic: "${mqtt_local_command_topic}"
payload: "On"
retain: false
# Local/HA requested OFF for Main Lights.
- id: mainlights_off
mode: restart
then:
- if:
condition:
lambda: "return id(relay_1).state;"
then:
- switch.turn_off: relay_1
- mqtt.publish:
topic: "${mqtt_local_command_topic}"
payload: "Off"
retain: false
# Physical Button 1 toggle logic.
- id: mainlights_toggle
mode: restart
then:
- if:
condition:
lambda: "return id(relay_1).state;"
then:
- script.execute: mainlights_off
else:
- script.execute: mainlights_on
#:########################################################################################:# #:########################################################################################:#
# BINARY SENSORS # BINARY SENSORS
# https://esphome.io/components/binary_sensor/ # https://esphome.io/components/binary_sensor/
@@ -187,8 +260,11 @@ binary_sensor:
inverted: true inverted: true
use_interrupt: false use_interrupt: false
name: "Button 1: ${switch_1_name}" name: "Button 1: ${switch_1_name}"
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press: on_press:
- switch.toggle: relay_1 - script.execute: mainlights_toggle
# Button 2 (GPIO05) # Button 2 (GPIO05)
- platform: gpio - platform: gpio
@@ -197,16 +273,22 @@ binary_sensor:
mode: INPUT mode: INPUT
inverted: true inverted: true
name: "Button 2: ${switch_2_name}" name: "Button 2: ${switch_2_name}"
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press: on_press:
- switch.toggle: relay_2 - switch.toggle: relay_2
# Button 3 (GPIO04) # Button 3 (GPIO04)
- platform: gpio - platform: gpio
pin: pin:
number: GPIO4 number: GPIO04
mode: INPUT mode: INPUT
inverted: true inverted: true
name: "Button 3: ${switch_3_name}" name: "Button 3: ${switch_3_name}"
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press: on_press:
- switch.toggle: relay_3 - switch.toggle: relay_3
@@ -215,19 +297,36 @@ binary_sensor:
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
#:########################################################################################:# #:########################################################################################:#
switch: switch:
# Relay 1 (GPIO13) + publish MQTT status # Exposed Home Assistant control for Main Lights. This controls the local relay and
- platform: gpio # publishes the matching command so linked switches follow.
- platform: template
name: "Relay 1: ${switch_1_name}" name: "Relay 1: ${switch_1_name}"
id: relay_1_ha
lambda: |-
return id(relay_1).state;
turn_on_action:
- script.execute: mainlights_on
turn_off_action:
- script.execute: mainlights_off
# Physical Relay 1. Kept internal so HA uses the template switch above.
# Relay callbacks publish retained status only, not commands.
- platform: gpio
name: "Internal Relay 1: ${switch_1_name}"
internal: true
pin: GPIO13 pin: GPIO13
id: relay_1 id: relay_1
restore_mode: ${relay_restore_mode}
on_turn_on: on_turn_on:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}" topic: "${mqtt_local_status_topic}"
payload: "On" payload: "On"
retain: true
on_turn_off: on_turn_off:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}" topic: "${mqtt_local_status_topic}"
payload: "Off" payload: "Off"
retain: true
# Relay 2 (GPIO12) # Relay 2 (GPIO12)
- platform: gpio - platform: gpio
+9 -19
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garageextcornerlight.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garageextcornerlight.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V2.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.1 2026-03-11 Updated yaml to zorruno layout V1.1
# V2.0 2025-10-22 Latest layout with home MQTT code # V2.0 2025-10-22 Latest layout with home MQTT code
# V1.0 2025-10-22 Initial Version # V1.0 2025-10-22 Initial Version
@@ -39,7 +40,6 @@
# - Accurate time is not needed (SNTP not required) # - Accurate time is not needed (SNTP not required)
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -55,7 +55,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details
project_version: "v2.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v2.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -80,7 +80,6 @@ substitutions:
mqtt_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" mqtt_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}"
mqtt_status_topic: "${mqtt_status_main_topic}/${mqtt_device_name}" mqtt_status_topic: "${mqtt_status_main_topic}/${mqtt_device_name}"
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html # https://esphome.io/components/packages.html
@@ -120,7 +119,6 @@ packages:
#diag_debug: !include common/include_debug_diag_sensors.yaml #diag_debug: !include common/include_debug_diag_sensors.yaml
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
#:########################################################################################:# #:########################################################################################:#
# ESPHOME: # ESPHOME:
# https://esphome.io/components/esphome.html # https://esphome.io/components/esphome.html
@@ -131,7 +129,6 @@ esphome:
comment: "${description_comment}" # Appears on the ESPHome page in HA comment: "${description_comment}" # Appears on the ESPHome page in HA
area: "${device_area}" area: "${device_area}"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK: # ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266.html # https://esphome.io/components/esp8266.html
@@ -140,7 +137,6 @@ esp8266:
board: esp01_1m # The original Sonoff Basic board: esp01_1m # The original Sonoff Basic
restore_from_flash: true # restore some values on reboot restore_from_flash: true # restore some values on reboot
#:########################################################################################:# #:########################################################################################:#
# PREFERENCES: # PREFERENCES:
# https://esphome.io/components/preferences.html # https://esphome.io/components/preferences.html
@@ -148,7 +144,6 @@ esp8266:
preferences: preferences:
flash_write_interval: 5min flash_write_interval: 5min
#:########################################################################################:# #:########################################################################################:#
# MDNS: # MDNS:
# https://esphome.io/components/mdns.html # https://esphome.io/components/mdns.html
@@ -156,7 +151,6 @@ preferences:
mdns: mdns:
disabled: false disabled: false
#:########################################################################################:# #:########################################################################################:#
# LOGGING: # LOGGING:
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
@@ -165,7 +159,6 @@ logger:
level: "${log_level}" level: "${log_level}"
baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM)
#:########################################################################################:# #:########################################################################################:#
# SWITCH COMPONENT: # SWITCH COMPONENT:
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
@@ -179,7 +172,6 @@ switch:
restore_mode: RESTORE_DEFAULT_OFF restore_mode: RESTORE_DEFAULT_OFF
icon: "${relay_icon}" icon: "${relay_icon}"
#:########################################################################################:# #:########################################################################################:#
# BINARY SENSORS: # BINARY SENSORS:
# https://esphome.io/components/binary_sensor/ # https://esphome.io/components/binary_sensor/
@@ -217,12 +209,11 @@ binary_sensor:
on_press: on_press:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}" topic: "${mqtt_status_topic}"
payload: "ON" payload: "On"
on_release: on_release:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}" topic: "${mqtt_status_topic}"
payload: "OFF" payload: "Off"
#:########################################################################################:# #:########################################################################################:#
# STATUS LED: # STATUS LED:
@@ -234,7 +225,6 @@ status_led:
number: GPIO13 number: GPIO13
inverted: true inverted: true
#:########################################################################################:# #:########################################################################################:#
# MQTT: Device-specific command triggers # MQTT: Device-specific command triggers
#:########################################################################################:# #:########################################################################################:#
@@ -242,7 +232,7 @@ mqtt:
on_message: on_message:
# Relay control (only act and publish if a change is needed) # Relay control (only act and publish if a change is needed)
- topic: "${mqtt_command_topic}" - topic: "${mqtt_command_topic}"
payload: "ON" payload: "On"
then: then:
- if: - if:
condition: condition:
@@ -252,10 +242,10 @@ mqtt:
- switch.turn_on: relay1 - switch.turn_on: relay1
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}" topic: "${mqtt_status_topic}"
payload: "ON" payload: "On"
- topic: "${mqtt_command_topic}" - topic: "${mqtt_command_topic}"
payload: "OFF" payload: "Off"
then: then:
- if: - if:
condition: condition:
@@ -265,11 +255,11 @@ mqtt:
- switch.turn_off: relay1 - switch.turn_off: relay1
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}" topic: "${mqtt_status_topic}"
payload: "OFF" payload: "Off"
# Announce current state whenever MQTT (re)connects # Announce current state whenever MQTT (re)connects
on_connect: on_connect:
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}" topic: "${mqtt_status_topic}"
payload: !lambda 'return id(relay1).state ? "ON" : "OFF";' payload: !lambda 'return id(relay1).state ? "On" : "Off";'
+5 -13
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garagelights.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garagelights.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V2.1 2026-03-04 Updated yaml to zorruno layout V1.1 # V2.1 2026-03-04 Updated yaml to zorruno layout V1.1
# V2.0 2025-10-22 Latest layout with home MQTT code # V2.0 2025-10-22 Latest layout with home MQTT code
# V1.0 2025-10-22 Initial Version # V1.0 2025-10-22 Initial Version
@@ -41,7 +42,6 @@
# - Accurate time is NOT needed (SNTP not required) for core operation # - Accurate time is NOT needed (SNTP not required) for core operation
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -56,7 +56,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details
project_version: "v2.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v2.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -72,8 +72,8 @@ substitutions:
mqtt_status_main_topic: !secret mqtt_status_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic
mqtt_command_topic_1: "${mqtt_command_main_topic}/${mqtt_device_name_1}" mqtt_command_topic_1: "${mqtt_command_main_topic}/${mqtt_device_name_1}"
mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}" mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}"
mqtt_command_ON: "ON" mqtt_command_ON: "On"
mqtt_command_OFF: "OFF" mqtt_command_OFF: "Off"
# I/O Naming # I/O Naming
relay_1_name: "Garage Lights" relay_1_name: "Garage Lights"
@@ -84,7 +84,6 @@ substitutions:
log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
update_interval: "60s" # update time for for general sensors etc update_interval: "60s" # update time for for general sensors etc
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html # https://esphome.io/components/packages.html
@@ -124,7 +123,6 @@ packages:
#diag_debug: !include common/include_debug_diag_sensors.yaml #diag_debug: !include common/include_debug_diag_sensors.yaml
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
#:########################################################################################:# #:########################################################################################:#
# ESPHOME: # ESPHOME:
# https://esphome.io/components/esphome.html # https://esphome.io/components/esphome.html
@@ -144,7 +142,6 @@ esphome:
# - "-fno-exceptions" # strip C++ exceptions # - "-fno-exceptions" # strip C++ exceptions
# - "-fno-rtti" # strip C++ RTTI # - "-fno-rtti" # strip C++ RTTI
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK: # ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266.html # https://esphome.io/components/esp8266.html
@@ -159,7 +156,6 @@ preferences:
mdns: mdns:
disabled: false disabled: false
#:########################################################################################:# #:########################################################################################:#
# LOGGING: # LOGGING:
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
@@ -170,7 +166,6 @@ logger:
#esp8266_store_log_strings_in_flash: false #esp8266_store_log_strings_in_flash: false
#tx_buffer_size: 64 #tx_buffer_size: 64
#:########################################################################################:# #:########################################################################################:#
# SWITCH COMPONENT: # SWITCH COMPONENT:
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
@@ -184,7 +179,6 @@ switch:
restore_mode: RESTORE_DEFAULT_OFF restore_mode: RESTORE_DEFAULT_OFF
icon: "${relay_icon}" icon: "${relay_icon}"
#:########################################################################################:# #:########################################################################################:#
# BINARY SENSORS: # BINARY SENSORS:
# https://esphome.io/components/binary_sensor/ # https://esphome.io/components/binary_sensor/
@@ -228,7 +222,6 @@ binary_sensor:
topic: "${mqtt_status_topic_1}" topic: "${mqtt_status_topic_1}"
payload: "${mqtt_command_OFF}" payload: "${mqtt_command_OFF}"
#:########################################################################################:# #:########################################################################################:#
# STATUS LED: # STATUS LED:
# https://esphome.io/components/status_led.html # https://esphome.io/components/status_led.html
@@ -239,7 +232,6 @@ status_led:
number: GPIO13 number: GPIO13
inverted: true inverted: true
#:########################################################################################:# #:########################################################################################:#
# MQTT: # MQTT:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
@@ -280,5 +272,5 @@ mqtt:
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic_1}" topic: "${mqtt_status_topic_1}"
payload: !lambda 'return id(relay1).state ? "ON" : "OFF";' payload: !lambda 'return id(relay1).state ? "On" : "Off";'
#retain: true #retain: true
+25 -23
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-gasheater.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-gasheater.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.13 2026-07-26 Updated Template Select state reads for ESPHome 2026.7.x.
# Replaced removed `.state` access with `.current_option()`.
# V1.12 2026-06-12 Added managed OFF mode separate from BYPASS (Remote Only). # V1.12 2026-06-12 Added managed OFF mode separate from BYPASS (Remote Only).
# OFF is now the normal startup/thermostat-off mode and will # OFF is now the normal startup/thermostat-off mode and will
# take over if the heater is locally started via the physical button. # take over if the heater is locally started via the physical button.
@@ -131,7 +133,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff DEV" project_name: "Sonoff Technologies.Sonoff DEV"
project_version: "v1.12" project_version: "v1.13"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -429,7 +431,7 @@ binary_sensor:
on_press: on_press:
- lambda: |- - lambda: |-
id(last_on_ms) = millis(); id(last_on_ms) = millis();
if (!id(test_mode_enabled).state && id(mode_select).state == "AUTO") { if (!id(test_mode_enabled).state && id(mode_select).current_option() == "AUTO") {
id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL);
} }
# ESPHome does not support Home Assistant's `choose:` action here, # ESPHome does not support Home Assistant's `choose:` action here,
@@ -439,7 +441,7 @@ binary_sensor:
# OFF mode watches for local physical heater starts. # OFF mode watches for local physical heater starts.
# If someone presses the real heater ON button, the LEDs come on, this # If someone presses the real heater ON button, the LEDs come on, this
# powered_state turns ON, and ESPHome changes to AUTO and takes over. # powered_state turns ON, and ESPHome changes to AUTO and takes over.
lambda: 'return !id(test_mode_enabled).state && id(mode_select).state == "OFF" && !id(self_power_on);' lambda: 'return !id(test_mode_enabled).state && id(mode_select).current_option() == "OFF" && !id(self_power_on);'
then: then:
- script.execute: local_on_takeover - script.execute: local_on_takeover
else: else:
@@ -447,7 +449,7 @@ binary_sensor:
condition: condition:
# In AUTO/MANUAL, if the controller intended the heater OFF but LEDs say ON, # In AUTO/MANUAL, if the controller intended the heater OFF but LEDs say ON,
# force the heater OFF. OFF is excluded because OFF performs local-start takeover. # force the heater OFF. OFF is excluded because OFF performs local-start takeover.
lambda: 'return !id(test_mode_enabled).state && id(mode_select).state != "BYPASS (Remote Only)" && id(mode_select).state != "OFF" && !id(power_intended_on) && !id(self_power_on);' lambda: 'return !id(test_mode_enabled).state && id(mode_select).current_option() != "BYPASS (Remote Only)" && id(mode_select).current_option() != "OFF" && !id(power_intended_on) && !id(self_power_on);'
then: then:
- script.execute: enforce_heater_off - script.execute: enforce_heater_off
else: else:
@@ -455,7 +457,7 @@ binary_sensor:
condition: condition:
# If the heater turns on externally while AUTO already intended it ON, # If the heater turns on externally while AUTO already intended it ON,
# re-baseline after warmup and continue normal automatic control. # re-baseline after warmup and continue normal automatic control.
lambda: 'return !id(test_mode_enabled).state && id(mode_select).state == "AUTO" && id(power_intended_on) && !id(self_power_on);' lambda: 'return !id(test_mode_enabled).state && id(mode_select).current_option() == "AUTO" && id(power_intended_on) && !id(self_power_on);'
then: then:
- lambda: |- - lambda: |-
id(ramp_until_ms) = millis() + (${fast_ramp_seconds} * 1000UL); id(ramp_until_ms) = millis() + (${fast_ramp_seconds} * 1000UL);
@@ -527,7 +529,7 @@ switch:
name: "Heater Operation" name: "Heater Operation"
icon: mdi:radiator icon: mdi:radiator
lambda: |- lambda: |-
return id(mode_select).state == "AUTO"; return id(mode_select).current_option() == "AUTO";
turn_on_action: turn_on_action:
- if: - if:
@@ -554,12 +556,12 @@ switch:
return id(powered_state).state; return id(powered_state).state;
turn_on_action: turn_on_action:
- lambda: |- - lambda: |-
if (id(mode_select).state != "BYPASS (Remote Only)" || id(test_mode_enabled).state) { if (id(mode_select).current_option() != "BYPASS (Remote Only)" || id(test_mode_enabled).state) {
id(power_intended_on) = true; id(power_intended_on) = true;
} }
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state == "BYPASS (Remote Only)" && !id(test_mode_enabled).state;' lambda: 'return id(mode_select).current_option() == "BYPASS (Remote Only)" && !id(test_mode_enabled).state;'
then: then:
- logger.log: "BYPASS (Remote Only): ignoring Power ON." - logger.log: "BYPASS (Remote Only): ignoring Power ON."
else: else:
@@ -580,12 +582,12 @@ switch:
turn_off_action: turn_off_action:
- lambda: |- - lambda: |-
if (id(mode_select).state != "BYPASS (Remote Only)" || id(test_mode_enabled).state) { if (id(mode_select).current_option() != "BYPASS (Remote Only)" || id(test_mode_enabled).state) {
id(power_intended_on) = false; id(power_intended_on) = false;
} }
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state == "BYPASS (Remote Only)" && !id(test_mode_enabled).state;' lambda: 'return id(mode_select).current_option() == "BYPASS (Remote Only)" && !id(test_mode_enabled).state;'
then: then:
- logger.log: "BYPASS (Remote Only): ignoring Power OFF." - logger.log: "BYPASS (Remote Only): ignoring Power OFF."
else: else:
@@ -665,7 +667,7 @@ text_sensor:
const bool use_test_temp = id(test_mode_enabled).state; const bool use_test_temp = id(test_mode_enabled).state;
const float effective_t = use_test_temp ? id(test_temp_c) : id(room_temp).state; const float effective_t = use_test_temp ? id(test_temp_c) : id(room_temp).state;
const float at_temp_threshold = id(setpoint_c) + ${off_above_c}; const float at_temp_threshold = id(setpoint_c) + ${off_above_c};
const std::string mode = id(mode_select).state; const std::string mode = id(mode_select).current_option();
if (!use_test_temp && id(room_temp_lost_fault)) { if (!use_test_temp && id(room_temp_lost_fault)) {
return std::string("Fault (Room Temperature Lost)"); return std::string("Fault (Room Temperature Lost)");
@@ -802,7 +804,7 @@ select:
else: else:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' lambda: 'return id(mode_select).current_option() != "BYPASS (Remote Only)";'
then: then:
- select.set: - select.set:
id: mode_select id: mode_select
@@ -853,7 +855,7 @@ button:
on_press: on_press:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' lambda: 'return id(mode_select).current_option() != "BYPASS (Remote Only)";'
then: then:
- lambda: |- - lambda: |-
id(power_intended_on) = true; id(power_intended_on) = true;
@@ -870,7 +872,7 @@ button:
on_press: on_press:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' lambda: 'return id(mode_select).current_option() != "BYPASS (Remote Only)";'
then: then:
- lambda: |- - lambda: |-
id(power_intended_on) = true; id(power_intended_on) = true;
@@ -972,7 +974,7 @@ interval:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state == "AUTO";' lambda: 'return id(mode_select).current_option() == "AUTO";'
then: then:
- script.execute: auto_control_tick - script.execute: auto_control_tick
@@ -984,7 +986,7 @@ interval:
then: then:
- if: - if:
condition: condition:
lambda: 'return !id(test_mode_enabled).state && id(mode_select).state != "BYPASS (Remote Only)" && id(mode_select).state != "OFF" && !id(power_intended_on) && id(powered_state).state && !id(self_power_on);' lambda: 'return !id(test_mode_enabled).state && id(mode_select).current_option() != "BYPASS (Remote Only)" && id(mode_select).current_option() != "OFF" && !id(power_intended_on) && id(powered_state).state && !id(self_power_on);'
then: then:
- script.execute: enforce_heater_off - script.execute: enforce_heater_off
@@ -1085,7 +1087,7 @@ script:
- script.execute: recompute_powered_state - script.execute: recompute_powered_state
- if: - if:
condition: condition:
lambda: 'return !id(test_mode_enabled).state && id(mode_select).state != "BYPASS (Remote Only)" && id(mode_select).state != "OFF" && !id(power_intended_on) && id(powered_state).state && !id(self_power_on);' lambda: 'return !id(test_mode_enabled).state && id(mode_select).current_option() != "BYPASS (Remote Only)" && id(mode_select).current_option() != "OFF" && !id(power_intended_on) && id(powered_state).state && !id(self_power_on);'
then: then:
- logger.log: "Heater should be OFF but LEDs still show ON. Pulsing power to force OFF." - logger.log: "Heater should be OFF but LEDs still show ON. Pulsing power to force OFF."
- script.execute: press_power - script.execute: press_power
@@ -1130,7 +1132,7 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' lambda: 'return id(mode_select).current_option() != "BYPASS (Remote Only)";'
then: then:
- script.execute: - script.execute:
id: press_with_gap id: press_with_gap
@@ -1142,7 +1144,7 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' lambda: 'return id(mode_select).current_option() != "BYPASS (Remote Only)";'
then: then:
- script.execute: - script.execute:
id: press_with_gap id: press_with_gap
@@ -1194,7 +1196,7 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state != "BYPASS (Remote Only)" && id(mode_select).state != "OFF" && id(powered_state).state;' lambda: 'return id(mode_select).current_option() != "BYPASS (Remote Only)" && id(mode_select).current_option() != "OFF" && id(powered_state).state;'
then: then:
- lambda: |- - lambda: |-
id(calibrating) = true; id(calibrating) = true;
@@ -1265,7 +1267,7 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state != "BYPASS (Remote Only)";' lambda: 'return id(mode_select).current_option() != "BYPASS (Remote Only)";'
then: then:
- lambda: |- - lambda: |-
id(power_intended_on) = true; id(power_intended_on) = true;
@@ -1275,7 +1277,7 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(mode_select).state == "AUTO";' lambda: 'return id(mode_select).current_option() == "AUTO";'
then: then:
- lambda: |- - lambda: |-
id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL); id(warmup_until_ms) = millis() + (${warmup_seconds} * 1000UL);
@@ -1314,7 +1316,7 @@ script:
mode: queued mode: queued
then: then:
- lambda: |- - lambda: |-
if (id(mode_select).state != "AUTO") { if (id(mode_select).current_option() != "AUTO") {
ESP_LOGD("gas", "AUTO: skipping control tick because Mode is not AUTO"); ESP_LOGD("gas", "AUTO: skipping control tick because Mode is not AUTO");
return; return;
} }
+5 -5
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-leafbattery.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-leafbattery.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.1 2026-03-22 Updated yaml to zorruno layout V1.1 # V1.1 2026-03-22 Updated yaml to zorruno layout V1.1
# V1.0 2025-??-?? Initial Version # V1.0 2025-??-?? Initial Version
#:########################################################################################:# #:########################################################################################:#
@@ -53,7 +54,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Generic ESP8266.D1 Mini" # Project Details project_name: "Generic ESP8266.D1 Mini" # Project Details
project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v1.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -164,7 +165,7 @@ esphome:
esp8266: esp8266:
board: d1_mini board: d1_mini
framework: framework:
version: latest # recommended, latest or dev version: recommended # latest or dev
#:########################################################################################:# #:########################################################################################:#
# LOGGER: # LOGGER:
@@ -199,13 +200,13 @@ mqtt:
# Control deep sleep over MQTT # Control deep sleep over MQTT
on_message: on_message:
- topic: ${mqtt_command_topic}/deepsleep - topic: ${mqtt_command_topic}/deepsleep
payload: "ON" payload: "On"
then: then:
- deep_sleep.allow: deep_sleep_1 - deep_sleep.allow: deep_sleep_1
- logger.log: "Deep sleep ALLOWED via MQTT. Device will sleep when run_duration elapses." - logger.log: "Deep sleep ALLOWED via MQTT. Device will sleep when run_duration elapses."
- topic: ${mqtt_command_topic}/deepsleep - topic: ${mqtt_command_topic}/deepsleep
payload: "OFF" payload: "Off"
then: then:
- deep_sleep.prevent: deep_sleep_1 - deep_sleep.prevent: deep_sleep_1
- logger.log: "Deep sleep PREVENTED via MQTT." - logger.log: "Deep sleep PREVENTED via MQTT."
@@ -274,4 +275,3 @@ interval:
char buf[10]; char buf[10];
snprintf(buf, sizeof(buf), "%.2f", v); snprintf(buf, sizeof(buf), "%.2f", v);
return std::string(buf); return std::string(buf);
+15 -3
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungebookshelfleds.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungebookshelfleds.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.4 2026-07-26 Republish retained MQTT status whenever the broker reconnects
# V2.3 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V2.2 2026-07-20 Simplified local MQTT command and status topics to the device root # V2.2 2026-07-20 Simplified local MQTT command and status topics to the device root
# V2.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.1 2026-03-11 Updated yaml to zorruno layout V1.1
# V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices # V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices
@@ -85,7 +87,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Project details. Manufacturer before the dot, device after the dot. project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Project details. Manufacturer before the dot, device after the dot.
project_version: "v2.2" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version project_version: "v2.4" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
api_key: !secret esp-api_key # If using HA API api_key: !secret esp-api_key # If using HA API
@@ -99,8 +101,8 @@ substitutions:
mqtt_local_status_main_topic: !secret mqtt_status_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic
mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA
mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA
mqtt_local_device_command_ON: "ON" mqtt_local_device_command_ON: "On"
mqtt_local_device_command_OFF: "OFF" mqtt_local_device_command_OFF: "Off"
# Device Specific Settings # Device Specific Settings
log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE
@@ -349,6 +351,16 @@ status_led:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
on_connect:
then:
- mqtt.publish:
topic: "${mqtt_local_status_topic}"
payload: !lambda |-
return id(mosfet_leds).current_values.is_on()
? "${mqtt_local_device_command_ON}"
: "${mqtt_local_device_command_OFF}";
retain: true
on_message: on_message:
# Light control to ramp up # Light control to ramp up
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
+18 -5
View File
@@ -6,6 +6,9 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungecabinetleds.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungecabinetleds.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.5 2026-07-26 Republish retained MQTT status whenever the broker reconnects
# V2.4 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V2.3 2026-07-25 Made light internal to stop auto-MQTT topics with extra /light/ level
# V2.2 2026-07-20 Simplified local MQTT command and status topics to the device root # V2.2 2026-07-20 Simplified local MQTT command and status topics to the device root
# V2.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.1 2026-03-11 Updated yaml to zorruno layout V1.1
# V2.0 2025-09-15 A bunch of fixes, this is now the master for other similar mosfet controllers of mine # V2.0 2025-09-15 A bunch of fixes, this is now the master for other similar mosfet controllers of mine
@@ -81,7 +84,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot. project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot.
project_version: "v2.2" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version project_version: "v2.5" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
api_key: !secret esp-api_key # If using HA API api_key: !secret esp-api_key # If using HA API
@@ -92,14 +95,14 @@ substitutions:
# Don't forget to switch it back when changed. # Don't forget to switch it back when changed.
current_ip_address: ${static_ip_address} current_ip_address: ${static_ip_address}
# MQTT LOCAL Controls (This is just my local method of controlling via MQTT, I also use the built in method) # MQTT LOCAL Controls
mqtt_local_device_name: "lounge-cabinetleds" mqtt_local_device_name: "lounge-cabinetleds"
mqtt_local_command_main_topic: !secret mqtt_command_main_topic mqtt_local_command_main_topic: !secret mqtt_command_main_topic
mqtt_local_status_main_topic: !secret mqtt_status_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic
mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA
mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA
mqtt_local_device_command_ON: "ON" mqtt_local_device_command_ON: "On"
mqtt_local_device_command_OFF: "OFF" mqtt_local_device_command_OFF: "Off"
# Device Specific Settings # Device Specific Settings
log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE
@@ -363,6 +366,16 @@ status_led:
# This adds device-specific MQTT command triggers to the common MQTT configuration. # This adds device-specific MQTT command triggers to the common MQTT configuration.
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
on_connect:
then:
- mqtt.publish:
topic: "${mqtt_local_status_topic}"
payload: !lambda |-
return id(mosfet_leds).current_values.is_on()
? "${mqtt_local_device_command_ON}"
: "${mqtt_local_device_command_OFF}";
retain: true
on_message: on_message:
# Light control to ramp up # Light control to ramp up
- topic: "${mqtt_local_command_topic}" - topic: "${mqtt_local_command_topic}"
@@ -597,7 +610,7 @@ output:
light: light:
- platform: monochromatic - platform: monochromatic
id: mosfet_leds id: mosfet_leds
name: "${friendly_name}" internal: true
output: mosfet_pwm output: mosfet_pwm
restore_mode: RESTORE_DEFAULT_OFF restore_mode: RESTORE_DEFAULT_OFF
default_transition_length: 2s default_transition_length: 2s
+9 -8
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungesouthleftswitch.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungesouthleftswitch.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V4.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V4.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V4.1 2026-03-11 Updated yaml to zorruno layout V1.1
# V4.0 2025-10-04 Copied from other device # V4.0 2025-10-04 Copied from other device
#:########################################################################################:# #:########################################################################################:#
@@ -70,7 +71,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Double" # Project Details project_name: "Zemismart Technologies.KS-811 Double" # Project Details
project_version: "v4.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v4.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -93,8 +94,8 @@ substitutions:
mqtt_remote_device_name: "garage-corridor-lights" mqtt_remote_device_name: "garage-corridor-lights"
mqtt_remote_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}" mqtt_remote_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}"
mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}" mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}"
mqtt_remote_device_command_ON: "ON" mqtt_remote_device_command_ON: "On"
mqtt_remote_device_command_OFF: "OFF" mqtt_remote_device_command_OFF: "Off"
# Switch Naming # Switch Naming
switch_1_name: "Wall Washer Left" switch_1_name: "Wall Washer Left"
@@ -167,7 +168,7 @@ esp8266:
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
#:########################################################################################:# #:########################################################################################:#
logger: logger:
level: "${log_level}" #INFO Level suggested, or DEBUG for testing level: "${log_level}" #INFO Level suggested, or DEBUG for testing
#baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM)
#esp8266_store_log_strings_in_flash: false #esp8266_store_log_strings_in_flash: false
#tx_buffer_size: 64 #tx_buffer_size: 64
@@ -268,18 +269,18 @@ switch:
on_turn_on: on_turn_on:
- if: - if:
condition: condition:
lambda: 'return !id(relay2_change_origin_remote);' lambda: "return !id(relay2_change_origin_remote);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_remote_command_topic}" topic: "${mqtt_remote_command_topic}"
payload: "${mqtt_remote_device_command_ON}" payload: "${mqtt_remote_device_command_ON}"
- lambda: 'id(relay2_change_origin_remote) = false;' - lambda: "id(relay2_change_origin_remote) = false;"
on_turn_off: on_turn_off:
- if: - if:
condition: condition:
lambda: 'return !id(relay2_change_origin_remote);' lambda: "return !id(relay2_change_origin_remote);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_remote_command_topic}" topic: "${mqtt_remote_command_topic}"
payload: "${mqtt_remote_device_command_OFF}" payload: "${mqtt_remote_device_command_OFF}"
- lambda: 'id(relay2_change_origin_remote) = false;' - lambda: "id(relay2_change_origin_remote) = false;"
+20 -7
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbdrmsouth.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbdrmsouth.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v1.6 2026-07-26 Suppressed command-producing mirror callbacks during startup
# v1.5 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# v1.4 2026-07-20 Flattened retained North and South MQTT status topics to the device roots. # v1.4 2026-07-20 Flattened retained North and South MQTT status topics to the device roots.
# v1.3 2026-06-12 Reassigned logical controls after live wiring checks. # v1.3 2026-06-12 Reassigned logical controls after live wiring checks.
# Relay 1 on both switches = North Lights virtual/Tasmota control. # Relay 1 on both switches = North Lights virtual/Tasmota control.
@@ -101,7 +103,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v1.4" project_version: "v1.6"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -192,6 +194,11 @@ esphome:
project: project:
name: "${project_name}" name: "${project_name}"
version: "${project_version}" version: "${project_version}"
on_boot:
priority: -100
then:
- delay: 5s
- lambda: "id(command_callbacks_ready) = true;"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK # ESP PLATFORM AND FRAMEWORK
@@ -215,6 +222,12 @@ logger:
# Used to suppress MQTT/HA feedback loops and hold the last known remote states. # Used to suppress MQTT/HA feedback loops and hold the last known remote states.
#:########################################################################################:# #:########################################################################################:#
globals: globals:
# Prevent restored/default mirror states from issuing commands during startup.
- id: command_callbacks_ready
type: bool
restore_value: false
initial_value: "false"
- id: north_update_from_sync - id: north_update_from_sync
type: bool type: bool
restore_value: false restore_value: false
@@ -393,14 +406,14 @@ script:
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${north_lights_tasmota_command_topic}" topic: "${north_lights_tasmota_command_topic}"
payload: "ON" payload: "On"
- id: request_north_lights_off - id: request_north_lights_off
mode: restart mode: restart
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${north_lights_tasmota_command_topic}" topic: "${north_lights_tasmota_command_topic}"
payload: "OFF" payload: "Off"
- id: set_north_on_from_tasmota - id: set_north_on_from_tasmota
mode: restart mode: restart
@@ -566,12 +579,12 @@ switch:
restore_mode: RESTORE_DEFAULT_OFF restore_mode: RESTORE_DEFAULT_OFF
on_turn_on: on_turn_on:
- lambda: |- - lambda: |-
if (!id(north_update_from_sync)) { if (id(command_callbacks_ready) && !id(north_update_from_sync)) {
id(request_north_lights_on).execute(); id(request_north_lights_on).execute();
} }
on_turn_off: on_turn_off:
- lambda: |- - lambda: |-
if (!id(north_update_from_sync)) { if (id(command_callbacks_ready) && !id(north_update_from_sync)) {
id(request_north_lights_off).execute(); id(request_north_lights_off).execute();
} }
@@ -583,12 +596,12 @@ switch:
restore_mode: RESTORE_DEFAULT_OFF restore_mode: RESTORE_DEFAULT_OFF
on_turn_on: on_turn_on:
- lambda: |- - lambda: |-
if (!id(south_update_from_sync)) { if (id(command_callbacks_ready) && !id(south_update_from_sync)) {
id(request_south_lights_on).execute(); id(request_south_lights_on).execute();
} }
on_turn_off: on_turn_off:
- lambda: |- - lambda: |-
if (!id(south_update_from_sync)) { if (id(command_callbacks_ready) && !id(south_update_from_sync)) {
id(request_south_lights_off).execute(); id(request_south_lights_off).execute();
} }
+18 -5
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbdrmwest.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbdrmwest.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v1.6 2026-07-26 Suppressed command-producing mirror callbacks during startup
# v1.5 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# v1.4 2026-07-20 Flattened retained North and South MQTT status topics to the device roots. # v1.4 2026-07-20 Flattened retained North and South MQTT status topics to the device roots.
# v1.3 2026-06-12 Reassigned logical controls after live wiring checks. # v1.3 2026-06-12 Reassigned logical controls after live wiring checks.
# Relay 1 on both switches = North Lights virtual/Tasmota control. # Relay 1 on both switches = North Lights virtual/Tasmota control.
@@ -102,7 +104,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v1.4" project_version: "v1.6"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -191,6 +193,11 @@ esphome:
project: project:
name: "${project_name}" name: "${project_name}"
version: "${project_version}" version: "${project_version}"
on_boot:
priority: -100
then:
- delay: 5s
- lambda: "id(command_callbacks_ready) = true;"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK # ESP PLATFORM AND FRAMEWORK
@@ -214,6 +221,12 @@ logger:
# Used to suppress MQTT/HA feedback loops and hold the last known remote states. # Used to suppress MQTT/HA feedback loops and hold the last known remote states.
#:########################################################################################:# #:########################################################################################:#
globals: globals:
# Prevent restored/default mirror states from issuing commands during startup.
- id: command_callbacks_ready
type: bool
restore_value: false
initial_value: "false"
- id: north_update_from_sync - id: north_update_from_sync
type: bool type: bool
restore_value: false restore_value: false
@@ -398,14 +411,14 @@ script:
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${north_lights_tasmota_command_topic}" topic: "${north_lights_tasmota_command_topic}"
payload: "ON" payload: "On"
- id: request_north_lights_off - id: request_north_lights_off
mode: restart mode: restart
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${north_lights_tasmota_command_topic}" topic: "${north_lights_tasmota_command_topic}"
payload: "OFF" payload: "Off"
- id: set_north_on_from_tasmota - id: set_north_on_from_tasmota
mode: restart mode: restart
@@ -531,12 +544,12 @@ switch:
restore_mode: RESTORE_DEFAULT_OFF restore_mode: RESTORE_DEFAULT_OFF
on_turn_on: on_turn_on:
- lambda: |- - lambda: |-
if (!id(north_update_from_sync)) { if (id(command_callbacks_ready) && !id(north_update_from_sync)) {
id(request_north_lights_on).execute(); id(request_north_lights_on).execute();
} }
on_turn_off: on_turn_off:
- lambda: |- - lambda: |-
if (!id(north_update_from_sync)) { if (id(command_callbacks_ready) && !id(north_update_from_sync)) {
id(request_north_lights_off).execute(); id(request_north_lights_off).execute();
} }
+26 -14
View File
@@ -6,6 +6,10 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-occupancyoffice.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-occupancyoffice.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v1.3 2026-07-25 Restored MQTT light timer commands. Light 2-way sync is handled directly
# between esp-officelights and esp-officeduallights via MQTT. This device
# sends On/timer commands to all 4 light topics for occupancy-based control.
# v1.2 2026-07-25 Removed MQTT light control commands (reverted)
# v1.1 2026-04-24 Added MQTT remote timer command script triggered by mmWave occupancy or movement # v1.1 2026-04-24 Added MQTT remote timer command script triggered by mmWave occupancy or movement
# v1.0 2026-02-25 Updated yaml to zorruno layout V1.1 # v1.0 2026-02-25 Updated yaml to zorruno layout V1.1
#:########################################################################################:# #:########################################################################################:#
@@ -33,26 +37,29 @@
# - Publishes a text occupancy state (Movement/Occupancy/Clearance) and binary sensors for: # - Publishes a text occupancy state (Movement/Occupancy/Clearance) and binary sensors for:
# - mmWave Occupancy or Movement (occupancy) # - mmWave Occupancy or Movement (occupancy)
# - mmWave Movement (motion) # - mmWave Movement (motion)
# - When mmWave Occupancy or Movement turns ON, this device publishes MQTT timer commands to: # - When mmWave Occupancy or Movement turns ON, this device publishes MQTT On commands to
# - ${mqtt_remote_device1_command_topic} # all 4 office light topics. When it turns OFF, it publishes timer commands (10s or 360s)
# - ${mqtt_remote_device2_command_topic} # so lights stay on briefly after the room is vacated.
# - Light 2-way sync between esp-officelights and esp-officeduallights ensures both switches
# stay in sync regardless of which device initiates the change.
# - BLE scanning is started/stopped based on HA API client connection (reduces BLE load when unused). # - BLE scanning is started/stopped based on HA API client connection (reduces BLE load when unused).
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, but Network and MQTT ONLINE # a) Home Assistant OFFLINE, but Network and MQTT ONLINE
# - Device continues running mmWave logic and environment sensors. # - Device continues running mmWave logic and environment sensors.
# - MQTT remote timer commands still function if MQTT is online. # - MQTT light timer commands still function if MQTT is online.
# - HA entities will update again when HA returns. # - HA entities will update again when HA returns.
# - Physical buttons on esp-officelights and esp-officeduallights still work and cancel
# any active timer if pressed.
# b) MQTT OFFLINE (or broker unreachable) # b) MQTT OFFLINE (or broker unreachable)
# - Device continues running locally and via HA API (if HA is reachable). # - Device continues running locally and via HA API (if HA is reachable).
# - MQTT-based remote timer commands will not function until MQTT returns. # - MQTT-based light timer commands will not function until MQTT returns.
# c) Entire WiFi/Network OFFLINE # c) Entire WiFi/Network OFFLINE
# - Device continues running local mmWave/environment logic, but HA/MQTT integration is unavailable. # - Device continues running local mmWave/environment logic, but HA/MQTT integration is unavailable.
# - Accurate time is NOT needed (SNTP not needed): logic uses relative time (time since boot), # - Accurate time is NOT needed (SNTP not needed): logic uses relative time (time since boot),
# but timing resets on reboot. # but timing resets on reboot.
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -66,7 +73,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "HiLink.LD1125H Office Occupancy" project_name: "HiLink.LD1125H Office Occupancy"
project_version: "v1.1" project_version: "v1.3"
# Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names)
api_key: !secret esp-occupancyoffice_api_key api_key: !secret esp-occupancyoffice_api_key
@@ -84,29 +91,34 @@ substitutions:
update_interval: "60s" # general sensor update interval update_interval: "60s" # general sensor update interval
# Remote light timer payloads, in seconds. # Remote light timer payloads, in seconds.
remote_timer_left_lights_payload: "10" # Dual R1: left=overhead(cool white)=10s, right=bunker=360s
remote_timer_right_lights_payload: "360" # Main lightswitch: left=bunker=360s, right=overhead(virtual mirror)=10s
# Note: "left"/"right" mean opposite things on each device due to physical wiring.
remote_timer_dual_left_payload: "10"
remote_timer_dual_right_payload: "360"
remote_timer_main_left_payload: "360"
remote_timer_main_right_payload: "10"
# MQTT REMOTE Controls # MQTT REMOTE Controls
mqtt_remote_device1_name: "office-dual-lights-left" mqtt_remote_device1_name: "office-dual-lights-left"
mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}" mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}"
mqtt_remote_device1_command1: "On" mqtt_remote_device1_command1: "On"
mqtt_remote_device1_command2: "${remote_timer_left_lights_payload}" mqtt_remote_device1_command2: "${remote_timer_dual_left_payload}"
mqtt_remote_device2_name: "office-dual-lights-right" mqtt_remote_device2_name: "office-dual-lights-right"
mqtt_remote_device2_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device2_name}" mqtt_remote_device2_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device2_name}"
mqtt_remote_device2_command1: "On" mqtt_remote_device2_command1: "On"
mqtt_remote_device2_command2: "${remote_timer_right_lights_payload}" mqtt_remote_device2_command2: "${remote_timer_dual_right_payload}"
mqtt_remote_device3_name: "office-main-lights-left" mqtt_remote_device3_name: "office-main-lights-left"
mqtt_remote_device3_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device3_name}" mqtt_remote_device3_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device3_name}"
mqtt_remote_device3_command1: "On" mqtt_remote_device3_command1: "On"
mqtt_remote_device3_command2: "${remote_timer_left_lights_payload}" mqtt_remote_device3_command2: "${remote_timer_main_left_payload}"
mqtt_remote_device4_name: "office-main-lights-right" mqtt_remote_device4_name: "office-main-lights-right"
mqtt_remote_device4_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device4_name}" mqtt_remote_device4_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device4_name}"
mqtt_remote_device4_command1: "On" mqtt_remote_device4_command1: "On"
mqtt_remote_device4_command2: "${remote_timer_right_lights_payload}" mqtt_remote_device4_command2: "${remote_timer_main_right_payload}"
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
@@ -199,7 +211,7 @@ external_components:
- source: - source:
type: git type: git
url: https://github.com/ssieb/custom_components url: https://github.com/ssieb/custom_components
components: [ serial ] components: [serial]
#:########################################################################################:# #:########################################################################################:#
# LOGGING # LOGGING
+86 -17
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-occupancystair.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-occupancystair.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.4 2026-07-26 Added status-aware ownership for the footer-light auto timer
# V2.3 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V2.2 2026-02-25 Updated yaml to zorruno layout V1.1 # V2.2 2026-02-25 Updated yaml to zorruno layout V1.1
# V2.1 2025-08-25 Added some MQTT to send commands to turn on remote lights # V2.1 2025-08-25 Added some MQTT to send commands to turn on remote lights
# V2.0 2025-06-05 YAML Tidyups # V2.0 2025-06-05 YAML Tidyups
@@ -36,7 +38,7 @@
# - Payloads: ${mqtt_remote_device_command_ON}, ${mqtt_remote_device_command_OFF} # - Payloads: ${mqtt_remote_device_command_ON}, ${mqtt_remote_device_command_OFF}
# #
# Example (as configured by substitutions): # Example (as configured by substitutions):
# - ${mqtt_command_main_topic}/stair-footerlights -> ON, OFF # - ${mqtt_command_main_topic}/stair-footerlights -> On, Off
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, but Network and MQTT ONLINE # a) Home Assistant OFFLINE, but Network and MQTT ONLINE
@@ -64,7 +66,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Generic.ESP32" project_name: "Generic.ESP32"
project_version: "v2.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v2.4" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -84,8 +86,9 @@ substitutions:
# MQTT REMOTE Controls # MQTT REMOTE Controls
mqtt_remote_device1_name: "stair-footerlights" mqtt_remote_device1_name: "stair-footerlights"
mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}" mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}"
mqtt_remote_device_command_ON: "ON" mqtt_remote_device1_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device1_name}"
mqtt_remote_device_command_OFF: "OFF" mqtt_remote_device_command_ON: "On"
mqtt_remote_device_command_OFF: "Off"
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
@@ -144,7 +147,7 @@ esphome:
esp32: esp32:
board: esp32dev board: esp32dev
framework: framework:
type: esp-idf # "esp-idf" OR "arduino" type: esp-idf # "esp-idf" OR "arduino"
version: recommended version: recommended
#:########################################################################################:# #:########################################################################################:#
@@ -157,6 +160,26 @@ globals:
restore_value: true restore_value: true
initial_value: "20" initial_value: "20"
- id: stair_footer_state_known
type: bool
restore_value: false
initial_value: "false"
- id: stair_footer_is_on
type: bool
restore_value: false
initial_value: "false"
- id: stair_footer_auto_owns_light
type: bool
restore_value: false
initial_value: "false"
- id: stair_footer_auto_on_pending
type: bool
restore_value: false
initial_value: "false"
#:########################################################################################:# #:########################################################################################:#
# I2C BUS: # I2C BUS:
# https://esphome.io/components/i2c.html # https://esphome.io/components/i2c.html
@@ -175,6 +198,31 @@ logger:
level: "${log_level}" level: "${log_level}"
baud_rate: 0 baud_rate: 0
#:########################################################################################:#
# MQTT STATUS:
# Tracks the authoritative footer-light state so auto control only turns off a
# light that it turned on itself.
#:########################################################################################:#
mqtt:
on_message:
- topic: "${mqtt_remote_device1_status_topic}"
payload: "${mqtt_remote_device_command_ON}"
then:
- lambda: |-
id(stair_footer_state_known) = true;
id(stair_footer_is_on) = true;
id(stair_footer_auto_on_pending) = false;
- topic: "${mqtt_remote_device1_status_topic}"
payload: "${mqtt_remote_device_command_OFF}"
then:
- lambda: |-
id(stair_footer_state_known) = true;
id(stair_footer_is_on) = false;
if (!id(stair_footer_auto_on_pending)) {
id(stair_footer_auto_owns_light) = false;
}
#:########################################################################################:# #:########################################################################################:#
# UART: # UART:
# https://esphome.io/components/uart.html # https://esphome.io/components/uart.html
@@ -466,17 +514,38 @@ script:
- id: stair_footer_auto_script - id: stair_footer_auto_script
mode: restart mode: restart
then: then:
# Turn lights on (command the Top switch's footer relay) - if:
- mqtt.publish: condition:
topic: "${mqtt_remote_device1_command_topic}" lambda: |-
payload: "${mqtt_remote_device_command_ON}" return id(stair_footer_auto_owns_light)
retain: false || !id(stair_footer_state_known)
|| !id(stair_footer_is_on);
then:
# Acquire ownership only when this automation needs to turn the light on.
- if:
condition:
lambda: "return !id(stair_footer_auto_owns_light);"
then:
- lambda: |-
id(stair_footer_auto_owns_light) = true;
id(stair_footer_auto_on_pending) = true;
- mqtt.publish:
topic: "${mqtt_remote_device1_command_topic}"
payload: "${mqtt_remote_device_command_ON}"
retain: false
# Wait for the HA-adjustable timeout # Repeated occupancy restarts this delay while retaining ownership.
- delay: !lambda "return (uint32_t)(id(stair_footer_auto_time_s).state) * 1000;" - delay: !lambda "return (uint32_t)(id(stair_footer_auto_time_s).state) * 1000;"
# Turn lights back off # An external OFF status releases ownership and suppresses this command.
- mqtt.publish: - if:
topic: "${mqtt_remote_device1_command_topic}" condition:
payload: "${mqtt_remote_device_command_OFF}" lambda: "return id(stair_footer_auto_owns_light);"
retain: false then:
- lambda: |-
id(stair_footer_auto_owns_light) = false;
id(stair_footer_auto_on_pending) = false;
- mqtt.publish:
topic: "${mqtt_remote_device1_command_topic}"
payload: "${mqtt_remote_device_command_OFF}"
retain: false
+7 -15
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officedeskrightgpo.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officedeskrightgpo.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.1 2026-03-08 Updated yaml to zorruno layout V1.1 # V1.1 2026-03-08 Updated yaml to zorruno layout V1.1
# V1.0 2025-06-14 Initial Version # V1.0 2025-06-14 Initial Version
#:########################################################################################:# #:########################################################################################:#
@@ -44,7 +45,6 @@
# - Accurate time is NOT needed (SNTP not required) # - Accurate time is NOT needed (SNTP not required)
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -58,7 +58,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details
project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v1.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -83,7 +83,6 @@ substitutions:
mqtt_device_name: "office-deskright-gpo" mqtt_device_name: "office-deskright-gpo"
mqtt_main_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" # Topic we will use to command stuff from external without HA mqtt_main_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" # Topic we will use to command stuff from external without HA
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html # https://esphome.io/components/packages.html
@@ -123,7 +122,6 @@ packages:
#diag_debug: !include common/include_debug_diag_sensors.yaml #diag_debug: !include common/include_debug_diag_sensors.yaml
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
#:########################################################################################:# #:########################################################################################:#
# ESPHOME: # ESPHOME:
# https://esphome.io/components/esphome.html # https://esphome.io/components/esphome.html
@@ -137,13 +135,12 @@ esphome:
name: "${project_name}" name: "${project_name}"
version: "${project_version}" version: "${project_version}"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK: # ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266.html # https://esphome.io/components/esp8266.html
#:########################################################################################:# #:########################################################################################:#
esp8266: esp8266:
board: esp01_1m # The original Sonoff Basic board: esp01_1m # The original Sonoff Basic
restore_from_flash: true # restore some values on reboot restore_from_flash: true # restore some values on reboot
preferences: preferences:
@@ -152,7 +149,6 @@ preferences:
mdns: mdns:
disabled: false disabled: false
#:########################################################################################:# #:########################################################################################:#
# LOGGING: # LOGGING:
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
@@ -161,7 +157,6 @@ logger:
level: "${log_level}" level: "${log_level}"
baud_rate: 0 # set to 0 for no logging via UART baud_rate: 0 # set to 0 for no logging via UART
#:########################################################################################:# #:########################################################################################:#
# STATUS LED: # STATUS LED:
# https://esphome.io/components/status_led.html # https://esphome.io/components/status_led.html
@@ -172,7 +167,6 @@ status_led:
number: GPIO13 number: GPIO13
inverted: true inverted: true
#:########################################################################################:# #:########################################################################################:#
# SWITCH COMPONENT: # SWITCH COMPONENT:
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
@@ -186,7 +180,6 @@ switch:
restore_mode: RESTORE_DEFAULT_ON restore_mode: RESTORE_DEFAULT_ON
icon: "${relay_icon}" icon: "${relay_icon}"
#:########################################################################################:# #:########################################################################################:#
# BINARY SENSORS: # BINARY SENSORS:
# https://esphome.io/components/binary_sensor/ # https://esphome.io/components/binary_sensor/
@@ -222,12 +215,11 @@ binary_sensor:
on_press: on_press:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_main_topic}/relay1/state" topic: "${mqtt_main_topic}/relay1/state"
payload: "ON" payload: "On"
on_release: on_release:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_main_topic}/relay1/state" topic: "${mqtt_main_topic}/relay1/state"
payload: "OFF" payload: "Off"
#:########################################################################################:# #:########################################################################################:#
# MQTT: # MQTT:
@@ -237,11 +229,11 @@ mqtt:
on_message: on_message:
# Relay 1 control # Relay 1 control
- topic: "${mqtt_main_topic}/relay1/set" - topic: "${mqtt_main_topic}/relay1/set"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: relay1 - switch.turn_on: relay1
- topic: "${mqtt_main_topic}/relay1/set" - topic: "${mqtt_main_topic}/relay1/set"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: relay1 - switch.turn_off: relay1
+151 -28
View File
@@ -6,6 +6,10 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeduallights.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeduallights.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.8 2026-07-25 Added 2-way MQTT sync with esp-officelights (office main lightswitch).
# on_connect republishes retained status on MQTT reconnect. on_message
# subscribes to main lightswitch command topics for offline HA-independent
# operation.
# V2.7 2026-04-24 Updated MQTT local topics, retain false, and timed control using seconds # V2.7 2026-04-24 Updated MQTT local topics, retain false, and timed control using seconds
# V2.6 2026-04-23 Added independent MQTT timed ON control for relay1 and relay2 # V2.6 2026-04-23 Added independent MQTT timed ON control for relay1 and relay2
# V2.5 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.5 2026-03-11 Updated yaml to zorruno layout V1.1
@@ -22,11 +26,11 @@
#:########################################################################################:# #:########################################################################################:#
# OPERATION NOTES: # OPERATION NOTES:
# - Controls 2 office light circuits: # - Controls 2 office light circuits:
# - Overhead cool white lights # - Right hand warm bunker light (relay/light 1)
# - Right hand warm bunker light # - Overhead cool white lights (relay/light 2)
# - Local button 1 toggles relay/light 1 and cancels any active timer for relay 1 # - Local button 1 toggles relay/light 1 and cancels any active timer for relay 1
# - Local button 2 toggles relay/light 2 and cancels any active timer for relay 2 # - Local button 2 toggles relay/light 2 and cancels any active timer for relay 2
# - Relay state changes are sent out via MQTT status topics with retain false # - Relay state changes are sent out via MQTT status topics with retain true
# - MQTT can command each relay with: # - MQTT can command each relay with:
# - On = turn on with no timer and cancel any active timer # - On = turn on with no timer and cancel any active timer
# - Off = turn off immediately and cancel any active timer # - Off = turn off immediately and cancel any active timer
@@ -35,31 +39,42 @@
# - Invalid MQTT timer values are ignored # - Invalid MQTT timer values are ignored
# - Template binary lights drive the template relay switches # - Template binary lights drive the template relay switches
# - Sonoff Dual R1 requires UART serial packets to operate the physical relays # - Sonoff Dual R1 requires UART serial packets to operate the physical relays
# - 2-way sync with esp-officelights (office main lightswitch) for offline HA-independent
# operation. This device subscribes to command topics from the main lightswitch and
# publishes retained status for the main lightswitch to mirror.
# #
# MQTT COMMANDS: # MQTT COMMANDS:
# - Command relay 1: # Bunker Light (relay 1):
# - ${mqtt_local_command1_topic} On, Off, or 1 to 3600 seconds # - Command topics:
# - Command relay 2: # - ${mqtt_local_command1_topic} On, Off, or 1 to 3600 seconds (from occupancy sensor)
# - ${mqtt_local_command2_topic} On, Off, or 1 to 3600 seconds # - ${mqtt_mainlight_command_bunker} On or Off (from esp-officelights button 1)
# - Relay 1 status publishes to: # - Status topic:
# - ${mqtt_local_status1_topic} On or Off # - ${mqtt_local_status1_topic} On or Off (retained)
# - Relay 2 status publishes to: #
# - ${mqtt_local_status2_topic} On or Off # Overhead Lights (relay 2):
# - Command topics:
# - ${mqtt_local_command2_topic} On, Off, or 1 to 3600 seconds (from occupancy sensor)
# - ${mqtt_mainlight_command_overhead} On or Off (from esp-officelights button 2)
# - Status topic:
# - ${mqtt_local_status2_topic} On or Off (retained)
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant offline (network and MQTT still online): # a) Home Assistant offline (network and MQTT still online):
# - Device continues to operate from local buttons # - Device continues to operate from local buttons.
# - Device can still be controlled directly by MQTT # - Device can still be controlled directly by MQTT.
# - Relay status still publishes by MQTT if broker is available # - 2-way sync with esp-officelights continues via MQTT.
# - Relay status still publishes by MQTT if broker is available.
# - HA entities are unavailable until HA returns.
# #
# b) MQTT offline (or HA and MQTT both offline): # b) MQTT offline (or HA and MQTT both offline):
# - Device continues to operate from local buttons only # - Device continues to operate from local buttons only.
# - No direct inter-ESP MQTT control available # - No direct inter-ESP MQTT control available.
# - No MQTT state feedback available # - No MQTT state feedback available to esp-officelights.
# - No MQTT state feedback available to esp-officelights.
# #
# c) Entire WiFi / Network offline: # c) Entire WiFi / Network offline:
# - Device continues to operate from local buttons only # - Device continues to operate from local buttons only.
# - No HA control or MQTT control/status available # - No HA control or MQTT control/status available.
# - Accurate time is not needed; SNTP is not required for operation # - Accurate time is not needed; SNTP is not required for operation
#:########################################################################################:# #:########################################################################################:#
@@ -76,7 +91,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff Dual R1" project_name: "Sonoff Technologies.Sonoff Dual R1"
project_version: "v2.7" project_version: "v2.8"
# Passwords and Secrets # Passwords and Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -100,10 +115,24 @@ substitutions:
mqtt_local_command2_topic: "${mqtt_command_main_topic}/${mqtt_local_device2_name}" mqtt_local_command2_topic: "${mqtt_command_main_topic}/${mqtt_local_device2_name}"
mqtt_local_status2_topic: "${mqtt_status_main_topic}/${mqtt_local_device2_name}" mqtt_local_status2_topic: "${mqtt_status_main_topic}/${mqtt_local_device2_name}"
# MQTT REMOTE Controls # MQTT REMOTE Controls - esp-officelights (office main lightswitch)
# mqtt_remote_device1_name: "masterbath-towelrail" # Command topics: this device subscribes to these to receive button press commands
# mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}/operation" # from the main lightswitch for 2-way sync.
# mqtt_remote_device1_command1: "BOOST" mqtt_mainlight_function_bunker: "office-main-lights-left"
mqtt_mainlight_command_bunker: "${mqtt_command_main_topic}/${mqtt_mainlight_function_bunker}"
mqtt_mainlight_function_overhead: "office-main-lights-right"
mqtt_mainlight_command_overhead: "${mqtt_command_main_topic}/${mqtt_mainlight_function_overhead}"
# MQTT Overhead Status - shared topic for overhead state sync
# Both this device and esp-officelights publish and subscribe to this topic so
# whichever device's timer finishes first keeps the other in sync.
mqtt_shared_overhead_status_function: "office-overhead-status"
mqtt_shared_overhead_status_topic: "${mqtt_status_main_topic}/${mqtt_shared_overhead_status_function}"
# MQTT Status/Command payloads
mqtt_command_on: "On"
mqtt_command_off: "Off"
# Switch Naming # Switch Naming
switch_1_name: "Dual L1 Relay" switch_1_name: "Dual L1 Relay"
@@ -195,6 +224,25 @@ uart:
# https://esphome.io/components/mqtt.html # https://esphome.io/components/mqtt.html
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
# Republish current relay states whenever MQTT reconnects so retained status stays accurate
# for subscribers that reconnect later.
on_connect:
- mqtt.publish:
topic: "${mqtt_local_status1_topic}"
payload: !lambda |-
return id(relay_1).state ? "${mqtt_command_on}" : "${mqtt_command_off}";
retain: true
- mqtt.publish:
topic: "${mqtt_local_status2_topic}"
payload: !lambda |-
return id(relay_2).state ? "${mqtt_command_on}" : "${mqtt_command_off}";
retain: true
- mqtt.publish:
topic: "${mqtt_shared_overhead_status_topic}"
payload: !lambda |-
return id(relay_2).state ? "${mqtt_command_on}" : "${mqtt_command_off}";
retain: true
on_message: on_message:
- topic: "${mqtt_local_command1_topic}" - topic: "${mqtt_local_command1_topic}"
payload: "On" payload: "On"
@@ -272,6 +320,73 @@ mqtt:
id(relay_2_timer_script)->execute(timer_seconds * 1000); id(relay_2_timer_script)->execute(timer_seconds * 1000);
# Mirror remote bunker command from esp-officelights onto light_1, but only if a real
# state change is needed. Do not republish the command from here. Relay status is
# published by the relay callback below.
- topic: "${mqtt_mainlight_command_bunker}"
payload: "${mqtt_command_on}"
then:
- script.stop: relay_1_timer_script
- if:
condition:
lambda: "return !id(relay_1).state;"
then:
- light.turn_on: light_1
- topic: "${mqtt_mainlight_command_bunker}"
payload: "${mqtt_command_off}"
then:
- script.stop: relay_1_timer_script
- if:
condition:
lambda: "return id(relay_1).state;"
then:
- light.turn_off: light_1
# Mirror remote overhead command from esp-officelights onto light_2, but only if a real
# state change is needed.
- topic: "${mqtt_mainlight_command_overhead}"
payload: "${mqtt_command_on}"
then:
- script.stop: relay_2_timer_script
- if:
condition:
lambda: "return !id(relay_2).state;"
then:
- light.turn_on: light_2
- topic: "${mqtt_mainlight_command_overhead}"
payload: "${mqtt_command_off}"
then:
- script.stop: relay_2_timer_script
- if:
condition:
lambda: "return id(relay_2).state;"
then:
- light.turn_off: light_2
# Mirror shared overhead status from esp-officelights onto light_2. This handles the
# case where the main lightswitch's overhead timer finishes and turns off the overhead.
# State guards prevent ping-pong with the command topic handlers above.
- topic: "${mqtt_shared_overhead_status_topic}"
payload: "${mqtt_command_on}"
then:
- if:
condition:
lambda: "return !id(relay_2).state;"
then:
- light.turn_on: light_2
- topic: "${mqtt_shared_overhead_status_topic}"
payload: "${mqtt_command_off}"
then:
- script.stop: relay_2_timer_script
- if:
condition:
lambda: "return id(relay_2).state;"
then:
- light.turn_off: light_2
#:########################################################################################:# #:########################################################################################:#
# SCRIPT COMPONENT: # SCRIPT COMPONENT:
# Independent per-relay timer scripts # Independent per-relay timer scripts
@@ -351,7 +466,7 @@ switch:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status1_topic}" topic: "${mqtt_local_status1_topic}"
payload: "On" payload: "On"
retain: false retain: true
- if: - if:
condition: condition:
switch.is_off: relay_2 switch.is_off: relay_2
@@ -363,7 +478,7 @@ switch:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status1_topic}" topic: "${mqtt_local_status1_topic}"
payload: "Off" payload: "Off"
retain: false retain: true
- if: - if:
condition: condition:
switch.is_off: relay_2 switch.is_off: relay_2
@@ -382,7 +497,11 @@ switch:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status2_topic}" topic: "${mqtt_local_status2_topic}"
payload: "On" payload: "On"
retain: false retain: true
- mqtt.publish:
topic: "${mqtt_shared_overhead_status_topic}"
payload: "On"
retain: true
- if: - if:
condition: condition:
switch.is_off: relay_1 switch.is_off: relay_1
@@ -394,7 +513,11 @@ switch:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status2_topic}" topic: "${mqtt_local_status2_topic}"
payload: "Off" payload: "Off"
retain: false retain: true
- mqtt.publish:
topic: "${mqtt_shared_overhead_status_topic}"
payload: "Off"
retain: true
- if: - if:
condition: condition:
switch.is_off: relay_1 switch.is_off: relay_1
+7 -15
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeelvcontrol.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeelvcontrol.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.1 2026-03-08 Updated yaml to zorruno layout V1.1 # V1.1 2026-03-08 Updated yaml to zorruno layout V1.1
# V1.0 2025-06-14 Initial Version # V1.0 2025-06-14 Initial Version
#:########################################################################################:# #:########################################################################################:#
@@ -44,7 +45,6 @@
# - Accurate time is NOT needed (SNTP not required) # - Accurate time is NOT needed (SNTP not required)
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -58,7 +58,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details
project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v1.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -83,7 +83,6 @@ substitutions:
mqtt_device_name: "office-elv-control" mqtt_device_name: "office-elv-control"
mqtt_main_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" # Topic we will use to command stuff from external without HA mqtt_main_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" # Topic we will use to command stuff from external without HA
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html # https://esphome.io/components/packages.html
@@ -123,7 +122,6 @@ packages:
#diag_debug: !include common/include_debug_diag_sensors.yaml #diag_debug: !include common/include_debug_diag_sensors.yaml
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
#:########################################################################################:# #:########################################################################################:#
# ESPHOME: # ESPHOME:
# https://esphome.io/components/esphome.html # https://esphome.io/components/esphome.html
@@ -137,13 +135,12 @@ esphome:
name: "${project_name}" name: "${project_name}"
version: "${project_version}" version: "${project_version}"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK: # ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266.html # https://esphome.io/components/esp8266.html
#:########################################################################################:# #:########################################################################################:#
esp8266: esp8266:
board: esp01_1m # The original Sonoff Basic board: esp01_1m # The original Sonoff Basic
restore_from_flash: true # restore some values on reboot restore_from_flash: true # restore some values on reboot
preferences: preferences:
@@ -152,7 +149,6 @@ preferences:
mdns: mdns:
disabled: false disabled: false
#:########################################################################################:# #:########################################################################################:#
# LOGGING: # LOGGING:
# https://esphome.io/components/logger.html # https://esphome.io/components/logger.html
@@ -161,7 +157,6 @@ logger:
level: "${log_level}" level: "${log_level}"
baud_rate: 0 # set to 0 for no logging via UART baud_rate: 0 # set to 0 for no logging via UART
#:########################################################################################:# #:########################################################################################:#
# STATUS LED: # STATUS LED:
# https://esphome.io/components/status_led.html # https://esphome.io/components/status_led.html
@@ -172,7 +167,6 @@ status_led:
number: GPIO13 number: GPIO13
inverted: true inverted: true
#:########################################################################################:# #:########################################################################################:#
# SWITCH COMPONENT: # SWITCH COMPONENT:
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
@@ -186,7 +180,6 @@ switch:
restore_mode: RESTORE_DEFAULT_ON restore_mode: RESTORE_DEFAULT_ON
icon: "${relay_icon}" icon: "${relay_icon}"
#:########################################################################################:# #:########################################################################################:#
# BINARY SENSORS: # BINARY SENSORS:
# https://esphome.io/components/binary_sensor/ # https://esphome.io/components/binary_sensor/
@@ -222,12 +215,11 @@ binary_sensor:
on_press: on_press:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_main_topic}/relay1/state" topic: "${mqtt_main_topic}/relay1/state"
payload: "ON" payload: "On"
on_release: on_release:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_main_topic}/relay1/state" topic: "${mqtt_main_topic}/relay1/state"
payload: "OFF" payload: "Off"
#:########################################################################################:# #:########################################################################################:#
# MQTT: # MQTT:
@@ -237,11 +229,11 @@ mqtt:
on_message: on_message:
# Relay 1 control # Relay 1 control
- topic: "${mqtt_main_topic}/relay1/set" - topic: "${mqtt_main_topic}/relay1/set"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: relay1 - switch.turn_on: relay1
- topic: "${mqtt_main_topic}/relay1/set" - topic: "${mqtt_main_topic}/relay1/set"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: relay1 - switch.turn_off: relay1
+427 -153
View File
@@ -6,6 +6,10 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officelights.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officelights.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v3.0 2026-07-25 Refactored MQTT sync to use template HA switch actions; physical button and
# HA control now publish command topics to officeduallights; relay callbacks
# publish status only to prevent command ping-pong/chattering. 2-way sync with
# esp-officeduallights for offline HA-independent operation.
# v2.1 2026-02-25 Updated yaml to zorruno layout V1.1 # v2.1 2026-02-25 Updated yaml to zorruno layout V1.1
# v2.0 2025-06-05 YAML Tidyups # v2.0 2025-06-05 YAML Tidyups
# v1.0 2025-05-31 Initial Version # v1.0 2025-05-31 Initial Version
@@ -16,26 +20,52 @@
#:########################################################################################:# #:########################################################################################:#
# OPERATION NOTES: # OPERATION NOTES:
# - Office 3-gang KS-811 (Triple) wall switch. # - Office 3-gang KS-811 (Triple) wall switch.
# - Button 1 toggles Relay 1 (Nighttime Lights) - only relay actually wired to a load. # - Button 1 (top) toggles Bunker Lights (both local Relay 1 physical bunker + remote dual light_1
# - Button 2 toggles Relay 2 (Daytime Lights) - virtual only (no physical load connected). # Right Bunker via MQTT). Local Relay 1 is a physical load; remote is the Sonoff Dual R1.
# - Button 3 toggles Relay 3 (Spare) - virtual only (no physical load connected). # - Button 2 (middle) toggles Overhead Lights (remote dual light_2 via MQTT). Local Relay 2 is
# - GPIO16 does not support interrupts; polling is used for Button 1. # a virtual mirror of the remote state only (no physical load connected).
# - Button 3 (bottom) is spare - no function assigned.
# - Home Assistant control of the exposed template switches also toggles the matching groups.
# - MQTT command topics request On/Off changes.
# - Relay state changes publish retained status only.
# - Relays never publish command topics directly. This prevents command ping-pong/chattering.
# - GPIO16 on ESP8266 does not support normal GPIO interrupts, so Button 1 uses polling mode.
#:########################################################################################:#
# MQTT COMMANDS:
# Bunker Lights (Button 1):
# - Command topic: ${mqtt_this_device_command_topic_bunker}
# Payloads: ${mqtt_command_on}, ${mqtt_command_off}, or 1 to 3600 (timer seconds)
# - Status topic: ${mqtt_this_device_status_topic_bunker}
# Payloads mirror the actual bunker relay state and are published retained.
#
# Overhead Lights (Button 2):
# - Command topic: ${mqtt_this_device_command_topic_overhead}
# Payloads: ${mqtt_command_on}, ${mqtt_command_off}, or 1 to 3600 (timer seconds)
# - Status topic: ${mqtt_this_device_status_topic_overhead}
# Payloads mirror the overhead virtual relay state and are published retained.
#
# This device subscribes to status topics from esp-officeduallights to mirror remote state.
# Timer values from esp-occupancyoffice are handled locally (countdown runs on this device).
# Physical button presses cancel any active timer before toggling.
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, WiFi OK # - a) Home Assistant offline (network and MQTT online):
# - Physical buttons still control relays locally. # - Local button control continues for both bunker and overhead lights.
# - MQTT is optional; device operates as a normal switch without HA. # - MQTT command/status operation continues for 2-way sync with esp-officeduallights.
# # - HA entities are unavailable until HA returns.
# b) MQTT OFFLINE (or broker unreachable) # - b) MQTT offline (or Home Assistant and MQTT offline):
# - Physical buttons still control relays locally. # - Local button control continues.
# - HA/API control (if available) still works, but no MQTT command/status. # - Bunker lights still toggle locally (physical relay).
# # - Overhead lights cannot be toggled remotely (no MQTT transport).
# c) Entire WiFi/Network OFFLINE # - If Home Assistant is online and connected by native ESPHome API, HA control can still
# - Physical buttons still control relays locally. # change the local relays but remote MQTT sync is unavailable until MQTT returns.
# - Accurate time is NOT needed (SNTP not needed). # - c) Entire WiFi/network offline:
# - Local wall-switch button control continues for both buttons.
# - Bunker lights still toggle locally (physical relay).
# - Overhead lights cannot be controlled (no network transport).
# - Accurate time is not needed. SNTP is not used for this device.
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -44,12 +74,12 @@ substitutions:
# Device Naming # Device Naming
device_name: "esp-officelights" device_name: "esp-officelights"
friendly_name: "Office Main Lightswitch (3)" friendly_name: "Office Main Lightswitch (3)"
description_comment: "Office Main Lightswitch using a Zemismart KS-811 Triple Push Button. Bunker Light A (1), Spare A (2), Spare B (3) (Layout V1.1)" description_comment: "Office Main Lightswitch using a Zemismart KS-811 Triple Push Button. Bunker Lights (1), Overhead Lights (2), Spare (3) (Layout V1.1)"
device_area: "Office" device_area: "Office"
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v2.1" project_version: "v3.0"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -66,20 +96,40 @@ substitutions:
log_level: "INFO" log_level: "INFO"
update_interval: "60s" update_interval: "60s"
# MQTT LOCAL Controls # Default relay restore mode
# Topic that remote things will use to command this locally without HA # Options: RESTORE_DEFAULT_OFF, RESTORE_DEFAULT_ON, ALWAYS_ON, ALWAYS_OFF
mqtt_local_device1_name: "office-main-lights-left" relay_restore_mode: "RESTORE_DEFAULT_OFF"
mqtt_local_command1_topic: "${mqtt_command_main_topic}/${mqtt_local_device1_name}"
mqtt_local_status1_topic: "${mqtt_status_main_topic}/${mqtt_local_device1_name}"
mqtt_local_device2_name: "office-main-lights-right" # MQTT LOCAL Controls - Bunker Lights
mqtt_local_command2_topic: "${mqtt_command_main_topic}/${mqtt_local_device2_name}" # Command topics: this device publishes here when Button 1 or HA toggles bunker.
mqtt_local_status2_topic: "${mqtt_status_main_topic}/${mqtt_local_device2_name}" # Status topics: this device publishes retained status here on relay state changes.
# esp-officeduallights subscribes to mirror remote bunker state.
mqtt_this_device_function_bunker: "office-main-lights-left"
mqtt_this_device_command_topic_bunker: "${mqtt_command_main_topic}/${mqtt_this_device_function_bunker}"
mqtt_this_device_status_topic_bunker: "${mqtt_status_main_topic}/${mqtt_this_device_function_bunker}"
# Switch Naming # MQTT LOCAL Controls - Overhead Lights
switch_1_name: "Nighttime Lights" # Only one light (Bunker Light) actually connected to this relay # Command topics: this device publishes here when Button 2 or HA toggles overhead.
switch_2_name: "Daytime Lights" # Virtual only, no power connected to 2nd relay # Status topics: this device publishes retained status here on virtual relay state changes.
switch_3_name: "Spare" # Virtual only, no power connected to 3rd relay # esp-officeduallights subscribes to mirror remote overhead state.
mqtt_this_device_function_overhead: "office-main-lights-right"
mqtt_this_device_command_topic_overhead: "${mqtt_command_main_topic}/${mqtt_this_device_function_overhead}"
mqtt_this_device_status_topic_overhead: "${mqtt_status_main_topic}/${mqtt_this_device_function_overhead}"
# MQTT Status/Command payloads
mqtt_command_on: "On"
mqtt_command_off: "Off"
# MQTT Overhead Status - shared topic for overhead state sync
# Both this device and esp-officeduallights publish and subscribe to this topic so
# whichever device's timer finishes first keeps the other in sync.
mqtt_shared_overhead_status_function: "office-overhead-status"
mqtt_shared_overhead_status_topic: "${mqtt_status_main_topic}/${mqtt_shared_overhead_status_function}"
# Switch/Relay/Button Naming
switch_1_name: "Bunker Lights" # Physical relay (GPIO13) connected to bunker light load
switch_2_name: "Overhead Lights" # Virtual mirror of esp-officeduallights overhead state
switch_3_name: "Spare" # Virtual only, no function assigned
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: Included Common Packages # PACKAGES: Included Common Packages
@@ -126,10 +176,6 @@ esphome:
project: project:
name: "${project_name}" name: "${project_name}"
version: "${project_version}" version: "${project_version}"
#on_boot:
# priority: 200
# then:
# - switch.turn_on: relay_3
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK # ESP PLATFORM AND FRAMEWORK
@@ -137,7 +183,7 @@ esphome:
#:########################################################################################:# #:########################################################################################:#
esp8266: esp8266:
board: esp01_1m board: esp01_1m
early_pin_init: false early_pin_init: false # Recommended false where relays/switches are involved
board_flash_mode: dout board_flash_mode: dout
#:########################################################################################:# #:########################################################################################:#
@@ -158,6 +204,280 @@ status_led:
number: GPIO2 number: GPIO2
inverted: true inverted: true
#:########################################################################################:#
# MQTT: Device-specific MQTT command triggers
# This extends the common MQTT package with local custom command/status topics.
#:########################################################################################:#
mqtt:
# Republish current relay states whenever MQTT reconnects so retained status stays accurate
# for subscribers that reconnect later.
on_connect:
- mqtt.publish:
topic: "${mqtt_this_device_status_topic_bunker}"
payload: !lambda |-
return id(Relay_1).state ? "${mqtt_command_on}" : "${mqtt_command_off}";
retain: true
- mqtt.publish:
topic: "${mqtt_this_device_status_topic_overhead}"
payload: !lambda |-
return id(Relay_2).state ? "${mqtt_command_on}" : "${mqtt_command_off}";
retain: true
- mqtt.publish:
topic: "${mqtt_shared_overhead_status_topic}"
payload: !lambda |-
return id(Relay_2).state ? "${mqtt_command_on}" : "${mqtt_command_off}";
retain: true
on_message:
# Mirror remote overhead command onto virtual Relay_2, but only if a real state change
# is needed. Do not republish the command from here. Relay status is published by the
# relay callback below.
- topic: "${mqtt_this_device_command_topic_overhead}"
payload: "${mqtt_command_on}"
then:
- script.stop: overhead_timer_script
- if:
condition:
lambda: "return !id(Relay_2).state;"
then:
- switch.turn_on: Relay_2
- topic: "${mqtt_this_device_command_topic_overhead}"
payload: "${mqtt_command_off}"
then:
- script.stop: overhead_timer_script
- if:
condition:
lambda: "return id(Relay_2).state;"
then:
- switch.turn_off: Relay_2
- topic: "${mqtt_this_device_command_topic_overhead}"
then:
- lambda: |-
if (x.empty()) {
return;
}
bool numeric_payload = true;
for (char c : x) {
if (c < '0' || c > '9') {
numeric_payload = false;
break;
}
}
if (!numeric_payload) {
return;
}
const int timer_seconds = atoi(x.c_str());
if (timer_seconds < 1 || timer_seconds > 3600) {
return;
}
id(overhead_timer_script)->execute(timer_seconds * 1000);
# Mirror shared overhead status from esp-officeduallights onto virtual Relay_2.
# This handles the case where the dual lights' overhead timer finishes and turns off
# the overhead — the main lightswitch mirrors the state so its virtual relay stays
# in sync. State guards prevent ping-pong with the command topic handlers above.
- topic: "${mqtt_shared_overhead_status_topic}"
payload: "${mqtt_command_on}"
then:
- if:
condition:
lambda: "return !id(Relay_2).state;"
then:
- switch.turn_on: Relay_2
- topic: "${mqtt_shared_overhead_status_topic}"
payload: "${mqtt_command_off}"
then:
- if:
condition:
lambda: "return id(Relay_2).state;"
then:
- switch.turn_off: Relay_2
# Mirror remote bunker command onto Relay_1, but only if a real state change is needed.
# This handles commands from esp-officeduallights when its local button toggles the
# physical bunker light and publishes status.
- topic: "${mqtt_this_device_status_topic_bunker}"
payload: "${mqtt_command_on}"
then:
- if:
condition:
lambda: "return !id(Relay_1).state;"
then:
- switch.turn_on: Relay_1
- topic: "${mqtt_this_device_status_topic_bunker}"
payload: "${mqtt_command_off}"
then:
- if:
condition:
lambda: "return id(Relay_1).state;"
then:
- switch.turn_off: Relay_1
# Bunker command from occupancy sensor or other MQTT publishers. Handles On, Off,
# and numeric timer values (1 to 3600 seconds).
- topic: "${mqtt_this_device_command_topic_bunker}"
payload: "${mqtt_command_on}"
then:
- script.stop: bunker_timer_script
- if:
condition:
lambda: "return !id(Relay_1).state;"
then:
- switch.turn_on: Relay_1
- topic: "${mqtt_this_device_command_topic_bunker}"
payload: "${mqtt_command_off}"
then:
- script.stop: bunker_timer_script
- if:
condition:
lambda: "return id(Relay_1).state;"
then:
- switch.turn_off: Relay_1
- topic: "${mqtt_this_device_command_topic_bunker}"
then:
- lambda: |-
if (x.empty()) {
return;
}
bool numeric_payload = true;
for (char c : x) {
if (c < '0' || c > '9') {
numeric_payload = false;
break;
}
}
if (!numeric_payload) {
return;
}
const int timer_seconds = atoi(x.c_str());
if (timer_seconds < 1 || timer_seconds > 3600) {
return;
}
id(bunker_timer_script)->execute(timer_seconds * 1000);
#:########################################################################################:#
# SCRIPTS
# https://esphome.io/components/script.html
#:########################################################################################:#
script:
# Local/HA requested ON for Bunker Lights. Change the local relay immediately, then publish
# a non-retained command so esp-officeduallights follows.
- id: office_bunker_on
mode: restart
then:
- if:
condition:
lambda: "return !id(Relay_1).state;"
then:
- switch.turn_on: Relay_1
- mqtt.publish:
topic: "${mqtt_this_device_command_topic_bunker}"
payload: "${mqtt_command_on}"
retain: false
# Local/HA requested OFF for Bunker Lights.
- id: office_bunker_off
mode: restart
then:
- if:
condition:
lambda: "return id(Relay_1).state;"
then:
- switch.turn_off: Relay_1
- mqtt.publish:
topic: "${mqtt_this_device_command_topic_bunker}"
payload: "${mqtt_command_off}"
retain: false
# Physical Button 1 toggle logic for Bunker Lights. This is the only place that decides
# ON vs OFF for the bunker.
- id: office_bunker_toggle
mode: restart
then:
- if:
condition:
lambda: "return id(Relay_1).state;"
then:
- script.execute: office_bunker_off
else:
- script.execute: office_bunker_on
# Local/HA requested ON for Overhead Lights. Change the virtual mirror immediately, then
# publish a non-retained command so esp-officeduallights follows.
- id: office_overhead_on
mode: restart
then:
- if:
condition:
lambda: "return !id(Relay_2).state;"
then:
- switch.turn_on: Relay_2
- mqtt.publish:
topic: "${mqtt_this_device_command_topic_overhead}"
payload: "${mqtt_command_on}"
retain: false
# Local/HA requested OFF for Overhead Lights.
- id: office_overhead_off
mode: restart
then:
- if:
condition:
lambda: "return id(Relay_2).state;"
then:
- switch.turn_off: Relay_2
- mqtt.publish:
topic: "${mqtt_this_device_command_topic_overhead}"
payload: "${mqtt_command_off}"
retain: false
# Physical Button 2 toggle logic for Overhead Lights.
- id: office_overhead_toggle
mode: restart
then:
- if:
condition:
lambda: "return id(Relay_2).state;"
then:
- script.execute: office_overhead_off
else:
- script.execute: office_overhead_on
# Bunker timer script. Turns on immediately, waits for the duration, then turns off.
# mode: restart means a new valid timer value restarts the timer from zero.
- id: bunker_timer_script
mode: restart
parameters:
timer_duration_ms: int
then:
- switch.turn_on: Relay_1
- delay: !lambda "return timer_duration_ms;"
- switch.turn_off: Relay_1
# Overhead timer script. Turns on immediately, waits for the duration, then turns off.
- id: overhead_timer_script
mode: restart
parameters:
timer_duration_ms: int
then:
- switch.turn_on: Relay_2
- delay: !lambda "return timer_duration_ms;"
- switch.turn_off: Relay_2
#:########################################################################################:# #:########################################################################################:#
# BINARY SENSORS # BINARY SENSORS
# https://esphome.io/components/binary_sensor/ # https://esphome.io/components/binary_sensor/
@@ -171,8 +491,11 @@ binary_sensor:
inverted: true inverted: true
use_interrupt: false use_interrupt: false
name: "Button 1: ${switch_1_name}" name: "Button 1: ${switch_1_name}"
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press: on_press:
- switch.toggle: Relay_1 - script.execute: office_bunker_toggle
# Button 2 (GPIO05) # Button 2 (GPIO05)
- platform: gpio - platform: gpio
@@ -181,145 +504,96 @@ binary_sensor:
mode: INPUT mode: INPUT
inverted: true inverted: true
name: "Button 2: ${switch_2_name}" name: "Button 2: ${switch_2_name}"
filters:
- delayed_on: 10ms
- delayed_off: 10ms
on_press: on_press:
- switch.toggle: Relay_2 - script.execute: office_overhead_toggle
# Button 3 (GPIO4) # Button 3 (GPIO4) - Spare
- platform: gpio - platform: gpio
pin: pin:
number: GPIO4 number: GPIO4
mode: INPUT mode: INPUT
inverted: true inverted: true
name: "Button 3: ${switch_3_name}" name: "Button 3: ${switch_3_name}"
on_press:
- switch.toggle: Relay_3
#:########################################################################################:#
# MQTT COMPONENT:
# Device-specific MQTT command triggers
# https://esphome.io/components/mqtt.html
#:########################################################################################:#
mqtt:
on_message:
- topic: "${mqtt_local_command1_topic}"
payload: "On"
then:
- script.stop: relay_1_timer_script
- switch.turn_on: Relay_1
- topic: "${mqtt_local_command1_topic}"
payload: "Off"
then:
- script.stop: relay_1_timer_script
- switch.turn_off: Relay_1
- topic: "${mqtt_local_command1_topic}"
then:
- lambda: |-
if (x.empty()) {
return;
}
bool numeric_payload = true;
for (char c : x) {
if (c < '0' || c > '9') {
numeric_payload = false;
break;
}
}
if (!numeric_payload) {
return;
}
const int timer_seconds = atoi(x.c_str());
if (timer_seconds < 1 || timer_seconds > 3600) {
return;
}
id(relay_1_timer_script)->execute(timer_seconds * 1000);
- topic: "${mqtt_local_command2_topic}"
payload: "On"
then:
- script.stop: relay_2_timer_script
- switch.turn_on: Relay_2
- topic: "${mqtt_local_command2_topic}"
payload: "Off"
then:
- script.stop: relay_2_timer_script
- switch.turn_off: Relay_2
- topic: "${mqtt_local_command2_topic}"
then:
- lambda: |-
if (x.empty()) {
return;
}
bool numeric_payload = true;
for (char c : x) {
if (c < '0' || c > '9') {
numeric_payload = false;
break;
}
}
if (!numeric_payload) {
return;
}
const int timer_seconds = atoi(x.c_str());
if (timer_seconds < 1 || timer_seconds > 3600) {
return;
}
id(relay_2_timer_script)->execute(timer_seconds * 1000);
#:########################################################################################:#
# SCRIPT COMPONENT:
# Relay 1 timer script
# mode: restart means a new valid timer value restarts the timer from zero
# https://esphome.io/components/script.html
#:########################################################################################:#
script:
- id: relay_1_timer_script
mode: restart
parameters:
timer_duration_ms: int
then:
- switch.turn_on: Relay_1
- delay: !lambda "return timer_duration_ms;"
- switch.turn_off: Relay_1
- id: relay_2_timer_script
mode: restart
parameters:
timer_duration_ms: int
then:
- switch.turn_on: Relay_2
- delay: !lambda "return timer_duration_ms;"
- switch.turn_off: Relay_2
#:########################################################################################:# #:########################################################################################:#
# SWITCH # SWITCH
# https://esphome.io/components/switch/ # https://esphome.io/components/switch/
#:########################################################################################:# #:########################################################################################:#
switch: switch:
# Relay 1 (GPIO13) # Exposed Home Assistant control for Bunker Lights. This controls the local relay and
- platform: gpio # publishes the matching command so esp-officeduallights follows.
- platform: template
name: "Relay 1: ${switch_1_name}" name: "Relay 1: ${switch_1_name}"
id: Relay_1_HA
lambda: |-
return id(Relay_1).state;
turn_on_action:
- script.execute: office_bunker_on
turn_off_action:
- script.execute: office_bunker_off
# Exposed Home Assistant control for Overhead Lights. This publishes the matching command
# so esp-officeduallights follows. Local Relay_2 is a virtual mirror of remote state.
- platform: template
name: "Relay 2: ${switch_2_name}"
id: Relay_2_HA
lambda: |-
return id(Relay_2).state;
turn_on_action:
- script.execute: office_overhead_on
turn_off_action:
- script.execute: office_overhead_off
# Physical Relay 1 (Bunker Lights). Kept internal so HA uses the template switch above.
# Relay callbacks publish retained status only, not commands.
- platform: gpio
name: "Internal Relay 1: ${switch_1_name}"
internal: true
pin: GPIO13 pin: GPIO13
id: Relay_1 id: Relay_1
restore_mode: ${relay_restore_mode}
on_turn_on:
- mqtt.publish:
topic: "${mqtt_this_device_status_topic_bunker}"
payload: "${mqtt_command_on}"
retain: true
on_turn_off:
- mqtt.publish:
topic: "${mqtt_this_device_status_topic_bunker}"
payload: "${mqtt_command_off}"
retain: true
# Relay 2 (GPIO12) # Virtual Relay 2 (Overhead Lights mirror). No physical load connected. Mirrors the state
# of esp-officeduallights overhead light via MQTT status subscription.
- platform: gpio - platform: gpio
name: "Relay 2: ${switch_2_name}" name: "Internal Relay 2: ${switch_2_name}"
internal: true
pin: GPIO12 pin: GPIO12
id: Relay_2 id: Relay_2
restore_mode: ${relay_restore_mode}
on_turn_on:
- mqtt.publish:
topic: "${mqtt_this_device_status_topic_overhead}"
payload: "${mqtt_command_on}"
retain: true
- mqtt.publish:
topic: "${mqtt_shared_overhead_status_topic}"
payload: "${mqtt_command_on}"
retain: true
on_turn_off:
- mqtt.publish:
topic: "${mqtt_this_device_status_topic_overhead}"
payload: "${mqtt_command_off}"
retain: true
- mqtt.publish:
topic: "${mqtt_shared_overhead_status_topic}"
payload: "${mqtt_command_off}"
retain: true
# Relay 3 (GPIO14) # Relay 3 (Spare) - no function assigned
- platform: gpio - platform: gpio
name: "Relay 3: ${switch_3_name}" name: "Relay 3: ${switch_3_name}"
pin: GPIO14 pin: GPIO14
+25 -15
View File
@@ -6,6 +6,8 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeusbhubpower.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeusbhubpower.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.4 2026-07-26 Added retained relay status and reconnect republishing
# V1.3 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.2 2026-07-20 Simplified local MQTT command and status topics to the device root # V1.2 2026-07-20 Simplified local MQTT command and status topics to the device root
# V1.1 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.1 2026-02-25 Updated yaml to zorruno layout V1.1
# V1.0 2025-06-14 Initial Version # V1.0 2025-06-14 Initial Version
@@ -23,10 +25,10 @@
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
# Command (set relay): # Command (set relay):
# - ${mqtt_command_topic} -> ON, OFF # - ${mqtt_command_topic} -> On, Off
# #
# Status (published from template sensor): # Status (published from template sensor):
# - ${mqtt_status_topic} -> ON, OFF # - ${mqtt_status_topic} -> On, Off (retained)
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, but Network and MQTT ONLINE # a) Home Assistant OFFLINE, but Network and MQTT ONLINE
@@ -55,7 +57,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff Basic V1" project_name: "Sonoff Technologies.Sonoff Basic V1"
project_version: "v1.2" project_version: "v1.4"
# Passwords & Secrets (Unfortunately, you cannot use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you cannot use substitutions inside secret names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -168,6 +170,16 @@ switch:
id: relay1 id: relay1
restore_mode: RESTORE_DEFAULT_ON restore_mode: RESTORE_DEFAULT_ON
icon: "${relay_icon}" icon: "${relay_icon}"
on_turn_on:
- mqtt.publish:
topic: "${mqtt_status_topic}"
payload: "On"
retain: true
on_turn_off:
- mqtt.publish:
topic: "${mqtt_status_topic}"
payload: "Off"
retain: true
#:########################################################################################:# #:########################################################################################:#
# BINARY SENSORS: # BINARY SENSORS:
@@ -200,16 +212,6 @@ binary_sensor:
name: "${relay_1_name} Status" name: "${relay_1_name} Status"
lambda: |- lambda: |-
return id(relay1).state; return id(relay1).state;
on_press:
- mqtt.publish:
topic: "${mqtt_status_topic}"
payload: "ON"
retain: false
on_release:
- mqtt.publish:
topic: "${mqtt_status_topic}"
payload: "OFF"
retain: false
#:########################################################################################:# #:########################################################################################:#
# STATUS LED: # STATUS LED:
@@ -227,13 +229,21 @@ status_led:
# https://esphome.io/components/mqtt.html # https://esphome.io/components/mqtt.html
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
on_connect:
then:
- mqtt.publish:
topic: "${mqtt_status_topic}"
payload: !lambda |-
return id(relay1).state ? "On" : "Off";
retain: true
on_message: on_message:
- topic: "${mqtt_command_topic}" - topic: "${mqtt_command_topic}"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: relay1 - switch.turn_on: relay1
- topic: "${mqtt_command_topic}" - topic: "${mqtt_command_topic}"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: relay1 - switch.turn_off: relay1
+7 -5
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-reterminal-e1001.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-reterminal-e1001.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V0.6.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V0.6.1 2026-07-20 Allowed GPIO4/GPIO5 to be shared by the EXT1 deep-sleep # V0.6.1 2026-07-20 Allowed GPIO4/GPIO5 to be shared by the EXT1 deep-sleep
# wake source and the normal white-button binary sensors. # wake source and the normal white-button binary sensors.
# V0.6 2026-07-20 Added open/closed-eye panel-state indicator, retained MQTT awake/sleep # V0.6 2026-07-20 Added open/closed-eye panel-state indicator, retained MQTT awake/sleep
@@ -86,7 +87,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "SeeedStudio.reTerminal-E1001" project_name: "SeeedStudio.reTerminal-E1001"
project_version: "v0.6.1" project_version: "v0.6.2"
# Passwords and Secrets # Passwords and Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -164,6 +165,7 @@ esphome:
friendly_name: "${friendly_name}" friendly_name: "${friendly_name}"
comment: "${description_comment}" comment: "${description_comment}"
area: "${device_area}" area: "${device_area}"
min_version: 2026.7.0
project: project:
name: "${project_name}" name: "${project_name}"
version: "${project_version}" version: "${project_version}"
@@ -1442,7 +1444,7 @@ mqtt:
on_message: on_message:
- topic: "${mqtt_command_topic}/deepsleep" - topic: "${mqtt_command_topic}/deepsleep"
payload: "ON" payload: "On"
then: then:
- lambda: |- - lambda: |-
id(sleep_allowed) = true; id(sleep_allowed) = true;
@@ -1452,12 +1454,12 @@ mqtt:
- logger.log: "Deep sleep ALLOWED by retained MQTT command." - logger.log: "Deep sleep ALLOWED by retained MQTT command."
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}/deepsleep" topic: "${mqtt_status_topic}/deepsleep"
payload: "ON" payload: "On"
qos: 1 qos: 1
retain: true retain: true
- topic: "${mqtt_command_topic}/deepsleep" - topic: "${mqtt_command_topic}/deepsleep"
payload: "OFF" payload: "Off"
then: then:
- lambda: |- - lambda: |-
id(sleep_allowed) = false; id(sleep_allowed) = false;
@@ -1466,7 +1468,7 @@ mqtt:
- logger.log: "Deep sleep PREVENTED by retained MQTT command." - logger.log: "Deep sleep PREVENTED by retained MQTT command."
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}/deepsleep" topic: "${mqtt_status_topic}/deepsleep"
payload: "OFF" payload: "Off"
qos: 1 qos: 1
retain: true retain: true
- mqtt.publish: - mqtt.publish:
+10 -9
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-underhouselights.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-underhouselights.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.2 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off"
# V1.1 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.1 2026-02-25 Updated yaml to zorruno layout V1.1
# V1.0 2025-06-18 Initial Version # V1.0 2025-06-18 Initial Version
#:########################################################################################:# #:########################################################################################:#
@@ -59,7 +60,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff 4Ch R2" # Project Details project_name: "Sonoff Technologies.Sonoff 4Ch R2" # Project Details
project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version project_version: "v1.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords # Passwords
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -304,40 +305,40 @@ mqtt:
on_message: on_message:
# Relay 1 control # Relay 1 control
- topic: "${mqtt_local_command_topic}/relay1/set" - topic: "${mqtt_local_command_topic}/relay1/set"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: relay1 - switch.turn_on: relay1
- topic: "${mqtt_local_command_topic}/relay1/set" - topic: "${mqtt_local_command_topic}/relay1/set"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: relay1 - switch.turn_off: relay1
# Relay 2 control # Relay 2 control
- topic: "${mqtt_local_command_topic}/relay2/set" - topic: "${mqtt_local_command_topic}/relay2/set"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: relay2 - switch.turn_on: relay2
- topic: "${mqtt_local_command_topic}/relay2/set" - topic: "${mqtt_local_command_topic}/relay2/set"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: relay2 - switch.turn_off: relay2
# Relay 3 control # Relay 3 control
- topic: "${mqtt_local_command_topic}/relay3/set" - topic: "${mqtt_local_command_topic}/relay3/set"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: relay3 - switch.turn_on: relay3
- topic: "${mqtt_local_command_topic}/relay3/set" - topic: "${mqtt_local_command_topic}/relay3/set"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: relay3 - switch.turn_off: relay3
# Relay 4 control # Relay 4 control
- topic: "${mqtt_local_command_topic}/relay4/set" - topic: "${mqtt_local_command_topic}/relay4/set"
payload: "ON" payload: "On"
then: then:
- switch.turn_on: relay4 - switch.turn_on: relay4
- topic: "${mqtt_local_command_topic}/relay4/set" - topic: "${mqtt_local_command_topic}/relay4/set"
payload: "OFF" payload: "Off"
then: then:
- switch.turn_off: relay4 - switch.turn_off: relay4
+21 -1
View File
@@ -8,6 +8,10 @@
# packages/16a_ev_charging_controls.yaml # packages/16a_ev_charging_controls.yaml
# #
# VERSION: # VERSION:
# V1.3 2026-07-24
# - Added startup catch-up to offpeak_end: when HA starts outside the
# offpeak window in Normal mode, the relay is turned off immediately.
#
# V1.2 2026-07-20 # V1.2 2026-07-20
# - Added structured mode, timing, and restart behavior documentation. # - Added structured mode, timing, and restart behavior documentation.
# #
@@ -56,7 +60,8 @@
# #
# OPERATION NOTES: # OPERATION NOTES:
# - Normal offpeak start and end use exact-time triggers. # - Normal offpeak start and end use exact-time triggers.
# - There is no startup catch-up if Home Assistant is offline at either time. # - The offpeak_end automation includes a startup trigger: if HA restarts
# outside the offpeak window in Normal mode, the relay turns off immediately.
# #
# PACKAGE SETTINGS: # PACKAGE SETTINGS:
# Car display name: # Car display name:
@@ -168,12 +173,27 @@ automation:
triggers: triggers:
- trigger: time - trigger: time
at: input_datetime.ev_16a_offpeak_end at: input_datetime.ev_16a_offpeak_end
- trigger: homeassistant
event: start
conditions: conditions:
- condition: state - condition: state
entity_id: input_select.ev_16a_charge_mode entity_id: input_select.ev_16a_charge_mode
state: "Normal (Offpeak)" state: "Normal (Offpeak)"
- condition: template
value_template: >
{% set start = states('input_datetime.ev_16a_offpeak_start') %}
{% set end = states('input_datetime.ev_16a_offpeak_end') %}
{% set now_time = now().strftime('%H:%M:%S') %}
{% if start == end %}
{{ false }}
{% elif start < end %}
{{ not (start <= now_time < end) }}
{% else %}
{{ not (now_time >= start or now_time < end) }}
{% endif %}
actions: actions:
- action: switch.turn_off - action: switch.turn_off
target: target:
@@ -2,8 +2,8 @@
# PACKAGE: Appliance Monitor Processor # PACKAGE: Appliance Monitor Processor
################################################################################ ################################################################################
# #
# Version: 1.3 # Version: 1.5
# Date: 2026-07-11 # Date: 2026-07-26
# #
# Purpose: # Purpose:
# Shared appliance power monitoring processor. # Shared appliance power monitoring processor.
@@ -41,6 +41,15 @@
# Finished # Finished
# #
# Notes: # Notes:
# Version 1.5:
# - Standardized Sony TV and Pushover appliance notification titles as
# "Appliance Notification".
#
# Version 1.4:
# - Added power_available field and state machine guard.
# - Prevents false Operating→Finished transitions when power sensor is
# unavailable (e.g. during Home Assistant startup).
#
# Version 1.3: # Version 1.3:
# - Updated completion announcements to support all current View Road # - Updated completion announcements to support all current View Road
# announcement router channels. # announcement router channels.
@@ -213,6 +222,12 @@ script:
selector: selector:
text: text:
power_available:
name: Power Available
description: Whether the power sensor reported a valid numeric state.
selector:
boolean:
sequence: sequence:
########################################################################## ##########################################################################
# CORE DEFAULTS AND PASSED VALUES # CORE DEFAULTS AND PASSED VALUES
@@ -239,6 +254,8 @@ script:
am_max_sample_gap_seconds: "{{ max_sample_gap_seconds | default(900, true) | int(900) }}" am_max_sample_gap_seconds: "{{ max_sample_gap_seconds | default(900, true) | int(900) }}"
am_min_cycle_notify_seconds: "{{ min_cycle_notify_seconds | default(300, true) | int(300) }}" am_min_cycle_notify_seconds: "{{ min_cycle_notify_seconds | default(300, true) | int(300) }}"
am_power_available: "{{ power_available | default(true, true) | bool(true) }}"
########################################################################## ##########################################################################
# ANNOUNCEMENT DEFAULTS AND PASSED VALUES # ANNOUNCEMENT DEFAULTS AND PASSED VALUES
########################################################################## ##########################################################################
@@ -280,7 +297,7 @@ script:
{{ long_announcement | default('', true) | string }} {{ long_announcement | default('', true) | string }}
am_announcement_title: >- am_announcement_title: >-
{{ title | default(am_appliance_name ~ ' Notification', true) | string }} Appliance Notification
am_announcement_payload: >- am_announcement_payload: >-
{% if announcement_payload is defined %} {% if announcement_payload is defined %}
@@ -394,7 +411,9 @@ script:
{% set standby = am_standby_power | float(2) %} {% set standby = am_standby_power | float(2) %}
{% set operate = am_operating_power_min | float(12) %} {% set operate = am_operating_power_min | float(12) %}
{% set prev = am_previous_state | string %} {% set prev = am_previous_state | string %}
{% if prev == 'Operating' and avg < operate %} {% if prev == 'Operating' and not am_power_available %}
{{ prev }}
{% elif prev == 'Operating' and avg < operate %}
Finished Finished
{% elif avg < standby %} {% elif avg < standby %}
Off Off
@@ -51,6 +51,10 @@
# matrix_indicator. # matrix_indicator.
# #
# VERSION HISTORY: # VERSION HISTORY:
# V1.6 2026-07-24
# - Added startup delay guard to prevent false completion announcements.
# - Added power_available field for the processor availability check.
#
# V1.5 2026-07-11 # V1.5 2026-07-11
# - Added full View Road announcement router parameter support. # - Added full View Road announcement router parameter support.
# - Added per-appliance announcement_enabled. # - Added per-appliance announcement_enabled.
@@ -421,6 +425,15 @@ automation:
mqtt_feed: "3d_printer" mqtt_feed: "3d_printer"
action: action:
# On startup, wait for power sensors to report real values before processing.
- choose:
- conditions:
- condition: trigger
id:
- ha_start
sequence:
- delay: "00:01:00"
#:####################################################################################:# #:####################################################################################:#
# PUBLISH / REFRESH MQTT DISCOVERY CONFIG # # PUBLISH / REFRESH MQTT DISCOVERY CONFIG #
#:####################################################################################:# #:####################################################################################:#
@@ -574,6 +587,9 @@ automation:
am_power_w: >- am_power_w: >-
{{ states(repeat.item.power_entity) | float(0) }} {{ states(repeat.item.power_entity) | float(0) }}
am_power_available: >-
{{ states(repeat.item.power_entity) not in ['unknown', 'unavailable'] }}
- action: script.appliance_monitor_process_sample - action: script.appliance_monitor_process_sample
data: data:
appliance_id: "{{ repeat.item.appliance_id }}" appliance_id: "{{ repeat.item.appliance_id }}"
@@ -581,6 +597,7 @@ automation:
appliance_action: "{{ repeat.item.appliance_action }}" appliance_action: "{{ repeat.item.appliance_action }}"
power_w: "{{ am_power_w }}" power_w: "{{ am_power_w }}"
power_available: "{{ am_power_available }}"
monitor_sensor: "{{ am_monitor_sensor }}" monitor_sensor: "{{ am_monitor_sensor }}"
state_topic: "{{ am_state_topic }}" state_topic: "{{ am_state_topic }}"
@@ -113,13 +113,12 @@ automation:
# Re-apply when the openHASP display comes online # Re-apply when the openHASP display comes online
########################################################################## ##########################################################################
- trigger: mqtt - trigger: mqtt
topic: hasp/openhasp_1/status topic: "hasp/openhasp_1/LWT"
payload: online
actions: actions:
- if: - if:
- condition: template - condition: template
value_template: "{{ trigger.platform in ['homeassistant', 'mqtt'] }}" value_template: "{{ trigger.platform == 'homeassistant' or (trigger.platform == 'mqtt' and trigger.payload == 'online') }}"
then: then:
- delay: "00:00:02" - delay: "00:00:02"
+2 -2
View File
@@ -17,8 +17,8 @@ group:
basement_lights: basement_lights:
name: "Basement Lights" name: "Basement Lights"
entities: entities:
- switch.esp_officelights_relay_1_nighttime_lights - switch.office_office_main_lightswitch_3_relay_1_bunker_lights
- switch.esp_officelights_relay_2_daytime_lights - switch.office_office_main_lightswitch_3_relay_2_overhead_lights
- switch.esp_underhouselights_underhouse_entrance_lights - switch.esp_underhouselights_underhouse_entrance_lights
- switch.esp_underhouselights_underhouse_storage_lights - switch.esp_underhouselights_underhouse_storage_lights
- switch.esp_laundrylights_relay_1_laundry_lights - switch.esp_laundrylights_relay_1_laundry_lights
+642
View File
@@ -0,0 +1,642 @@
#:########################################################################################:#
# Flounder Kiosk Package #
#:########################################################################################:#
#
# TITLE:
# Flounder Kiosk
#
# FILE:
# flounder_kiosk.yaml
#
# VERSION:
# V2.0 - 2026-07-28
#
# PURPOSE:
# Provides Home Assistant controls and status entities for the Flounder portrait
# touchscreen kiosk.
#
# DISPLAY CONTROL MODEL:
# A single MQTT select sets one persistent display mode:
# - Screen Lock
# - Screen Off
# - Screensaver
# - Screen On
#
# The selected display mode is separate from the actual physical screen and
# screensaver states. For example, Screen Off remains selected while a touch
# temporarily wakes the physical display.
#
# MQTT DEVICE:
# Name: Flounder Kiosk
# Identifier: flounder_kiosk
# Manufacturer: Dell
# Model: Portrait Touchscreen Kiosk
# Suggested Area: Lounge
#
# ENTITIES:
# select.flounder_kiosk_display_mode
# number.flounder_kiosk_brightness
# number.flounder_kiosk_presence_brightness
# sensor.flounder_kiosk_actual_brightness
# number.flounder_kiosk_presence_timeout
# binary_sensor.flounder_kiosk_presence_active
# switch.flounder_kiosk_motion_wake
# number.flounder_kiosk_volume
# switch.flounder_kiosk_mute
# binary_sensor.flounder_kiosk_screen_on
# binary_sensor.flounder_kiosk_screensaver_active
# binary_sensor.flounder_kiosk_motion
#
# REPLACED ENTITIES:
# The following writable entities from V1.7 are removed:
# - switch.flounder_kiosk_screen
# - switch.flounder_kiosk_screensaver
#
# They are replaced by:
# - select.flounder_kiosk_display_mode
# - binary_sensor.flounder_kiosk_screen_on
# - binary_sensor.flounder_kiosk_screensaver_active
#
# MQTT COMMAND TOPICS:
# viewroad-commands/flounder/display_mode/set
# viewroad-commands/flounder/brightness/set
# viewroad-commands/flounder/brightness/presence/set
# viewroad-commands/flounder/presence/timeout/set
# viewroad-commands/flounder/motion_wake/set
# viewroad-commands/flounder/audio/volume/set
# viewroad-commands/flounder/audio/mute/set
#
# MQTT STATE TOPICS:
# viewroad-status/flounder/display_mode/state
# viewroad-status/flounder/screen/state
# viewroad-status/flounder/screensaver/state
# viewroad-status/flounder/brightness/state
# viewroad-status/flounder/brightness/actual/state
# viewroad-status/flounder/brightness/presence/state
# viewroad-status/flounder/presence/state
# viewroad-status/flounder/presence/timeout/state
# viewroad-status/flounder/motion_wake/state
# viewroad-status/flounder/audio/volume/state
# viewroad-status/flounder/audio/mute/state
# viewroad-status/flounder/motion/state
#
# MQTT AVAILABILITY TOPIC:
# viewroad-status/flounder/availability
#
# DISPLAY MODES:
# Screen Lock:
# - Stops XScreenSaver.
# - Disables touchscreen input.
# - Keeps the physical panel off.
# - Ignores camera motion even when Motion Wake is enabled.
# - Camera motion detection and reporting continue in the background.
#
# Screen Off:
# - Keeps the physical panel off while activity is inactive.
# - Keeps the touchscreen enabled.
# - Touch always wakes the panel temporarily.
# - Camera motion wakes it when Motion Wake is enabled.
# - Activity applies Presence Brightness.
# - The panel returns to Screen Off after the shared Presence Timeout.
#
# Screensaver:
# - Turns the panel on at Current Brightness.
# - Starts XScreenSaver immediately.
# - Touch stops XScreenSaver and applies Presence Brightness.
# - Camera motion does the same when Motion Wake is enabled.
# - XScreenSaver restarts after the shared Presence Timeout.
#
# Screen On:
# - Keeps the panel on at Current Brightness while activity is inactive.
# - Touch applies Presence Brightness.
# - Camera motion does the same when Motion Wake is enabled.
# - The panel returns to Current Brightness after the Presence Timeout.
#
# PRESENCE AND TOUCH OPERATION:
# - Touch and camera motion use the same Presence Timeout.
# - Touch is active in every mode except Screen Lock.
# - Motion Wake controls camera motion only and does not disable touch wake.
# - Qualifying activity immediately applies Presence Brightness.
# - Camera motion holds presence active until the Motion entity returns to OFF.
# - A touch starts or restarts the ten-step brightness ramp immediately unless
# qualifying camera motion is currently holding presence active.
# - Presence Timeout is the total duration of the ten-step brightness ramp.
# - The final ramp step applies the latest Current Brightness.
# - The selected display mode is then restored automatically.
#
# DIAGNOSTIC STATE MEANING:
# - Screen On reports the real Linux DPMS panel state.
# - Screensaver Active reports whether XScreenSaver is running.
# - Presence Active reports whether temporary activity behaviour is active.
# - Actual Brightness reports the physical backlight percentage.
#
# VERSION HISTORY:
# V2.0 - 2026-07-28
# - Replaced the separate Screen and Screensaver switches with one persistent
# four-option Display Mode select.
# - Added Screen Lock, Screen Off, Screensaver, and Screen On modes.
# - Added shared touchscreen and camera-presence behaviour.
# - Added automatic return to the selected mode after the presence ramp.
# - Replaced writable Screen and Screensaver entities with diagnostics.
#
# V1.7 - 2026-07-27
# - Re-enabled DPMS after XScreenSaver activation.
# - Corrected Screen state reporting while XScreenSaver was running.
#
# V1.6 - 2026-07-27
# - Grouped all MQTT entities under one Flounder Kiosk device.
#
# V1.5 - 2026-07-27
# - Added Motion Wake control.
#
# V1.4 - 2026-07-27
# - Added the ten-step presence-brightness fade.
#
# V1.3 - 2026-07-27
# - Added presence brightness, timeout, and diagnostic entities.
#
# V1.2 - 2026-07-27
# - Added XScreenSaver control.
#
# V1.1 - 2026-07-27
# - Added MQTT availability monitoring.
#
# V1.0 - 2026-07-26
# - Initial package.
#
#:########################################################################################:#
# MQTT Entities #
#:########################################################################################:#
mqtt:
#:########################################################################################:#
# Flounder Kiosk Display Mode #
#:########################################################################################:#
#
# Selects the persistent display operating mode.
#
# The selected mode remains unchanged while touch or camera activity temporarily
# changes the real panel or screensaver state.
#
- select:
name: "Display Mode"
unique_id: flounder_kiosk_display_mode
default_entity_id: select.flounder_kiosk_display_mode
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
command_topic: "viewroad-commands/flounder/display_mode/set"
state_topic: "viewroad-status/flounder/display_mode/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
options:
- "Screen Lock"
- "Screen Off"
- "Screensaver"
- "Screen On"
optimistic: false
retain: false
icon: mdi:monitor-dashboard
#:########################################################################################:#
# Flounder Kiosk Current Brightness #
#:########################################################################################:#
#
# Stores the normal inactive brightness from 1 to 100 percent.
#
# In Screensaver and Screen On modes it is the normal visible brightness.
# In Screen Off mode it is the final ramp target before the panel powers off.
# In Screen Lock mode it is stored for the next unlocked mode.
#
- number:
name: "Brightness"
unique_id: flounder_kiosk_brightness
default_entity_id: number.flounder_kiosk_brightness
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
command_topic: "viewroad-commands/flounder/brightness/set"
state_topic: "viewroad-status/flounder/brightness/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
min: 1
max: 100
step: 1
mode: slider
unit_of_measurement: "%"
optimistic: false
retain: false
icon: mdi:brightness-6
#:########################################################################################:#
# Flounder Kiosk Presence Brightness #
#:########################################################################################:#
#
# Sets the temporary brightness used after touch or qualifying camera motion.
#
# Changing it while Presence Active is ON immediately updates the physical
# backlight.
#
- number:
name: "Presence Brightness"
unique_id: flounder_kiosk_presence_brightness
default_entity_id: number.flounder_kiosk_presence_brightness
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
entity_category: config
command_topic: "viewroad-commands/flounder/brightness/presence/set"
state_topic: "viewroad-status/flounder/brightness/presence/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
min: 1
max: 100
step: 1
mode: slider
unit_of_measurement: "%"
optimistic: false
retain: false
icon: mdi:brightness-7
#:########################################################################################:#
# Flounder Kiosk Actual Brightness #
#:########################################################################################:#
#
# Reports the physical display backlight percentage.
#
# This may differ from Current Brightness while temporary activity is active or
# while the ten-step brightness ramp is running.
#
- sensor:
name: "Actual Brightness"
unique_id: flounder_kiosk_actual_brightness
default_entity_id: sensor.flounder_kiosk_actual_brightness
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
entity_category: diagnostic
state_topic: "viewroad-status/flounder/brightness/actual/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
unit_of_measurement: "%"
state_class: measurement
icon: mdi:brightness-percent
#:########################################################################################:#
# Flounder Kiosk Presence Timeout #
#:########################################################################################:#
#
# Sets the shared touch and camera-presence timeout.
#
# The value is the total duration of the ten-step brightness ramp. Home Assistant
# displays whole minutes while MQTT stores and transfers seconds.
#
- number:
name: "Presence Timeout"
unique_id: flounder_kiosk_presence_timeout
default_entity_id: number.flounder_kiosk_presence_timeout
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
entity_category: config
command_topic: "viewroad-commands/flounder/presence/timeout/set"
state_topic: "viewroad-status/flounder/presence/timeout/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
command_template: >-
{{ (value | float(1) * 60) | round(0) | int }}
value_template: >-
{{ (value | float(60) / 60) | round(0) | int }}
min: 1
max: 1440
step: 1
mode: box
unit_of_measurement: "min"
optimistic: false
retain: false
icon: mdi:timer-outline
#:########################################################################################:#
# Flounder Kiosk Presence Active #
#:########################################################################################:#
#
# Reports whether temporary touch or camera-presence behaviour is active.
#
# It remains ON through the brightness ramp and returns to OFF when the selected
# display mode has been restored.
#
- binary_sensor:
name: "Presence Active"
unique_id: flounder_kiosk_presence_active
default_entity_id: binary_sensor.flounder_kiosk_presence_active
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
entity_category: diagnostic
state_topic: "viewroad-status/flounder/presence/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
payload_on: "ON"
payload_off: "OFF"
icon: mdi:account-eye
#:########################################################################################:#
# Flounder Kiosk Motion Wake #
#:########################################################################################:#
#
# Controls whether camera motion counts as display activity.
#
# Motion Wake does not affect touchscreen activity. Screen Lock ignores camera
# motion regardless of this switch while motion detection continues reporting.
#
- switch:
name: "Motion Wake"
unique_id: flounder_kiosk_motion_wake
default_entity_id: switch.flounder_kiosk_motion_wake
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
entity_category: config
command_topic: "viewroad-commands/flounder/motion_wake/set"
state_topic: "viewroad-status/flounder/motion_wake/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
payload_on: "ON"
payload_off: "OFF"
optimistic: false
retain: false
icon: mdi:motion-sensor
#:########################################################################################:#
# Flounder Kiosk Volume #
#:########################################################################################:#
#
# Controls the active PipeWire audio-sink volume from 0 to 100 percent.
#
- number:
name: "Volume"
unique_id: flounder_kiosk_volume
default_entity_id: number.flounder_kiosk_volume
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
command_topic: "viewroad-commands/flounder/audio/volume/set"
state_topic: "viewroad-status/flounder/audio/volume/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
min: 0
max: 100
step: 1
mode: slider
unit_of_measurement: "%"
optimistic: false
retain: false
icon: mdi:volume-high
#:########################################################################################:#
# Flounder Kiosk Mute #
#:########################################################################################:#
#
# Controls the mute state of the active PipeWire audio sink.
#
- switch:
name: "Mute"
unique_id: flounder_kiosk_mute
default_entity_id: switch.flounder_kiosk_mute
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
command_topic: "viewroad-commands/flounder/audio/mute/set"
state_topic: "viewroad-status/flounder/audio/mute/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
payload_on: "ON"
payload_off: "OFF"
optimistic: false
retain: false
icon: mdi:volume-mute
#:########################################################################################:#
# Flounder Kiosk Screen On #
#:########################################################################################:#
#
# Reports the real physical panel state from Linux DPMS.
#
# This can report ON while Display Mode remains Screen Off because touch or
# qualifying camera motion has temporarily woken the panel.
#
- binary_sensor:
name: "Screen On"
unique_id: flounder_kiosk_screen_on
default_entity_id: binary_sensor.flounder_kiosk_screen_on
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
entity_category: diagnostic
state_topic: "viewroad-status/flounder/screen/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
payload_on: "ON"
payload_off: "OFF"
device_class: power
icon: mdi:monitor
#:########################################################################################:#
# Flounder Kiosk Screensaver Active #
#:########################################################################################:#
#
# Reports whether XScreenSaver is currently running.
#
# In Screensaver mode it normally reports ON, but temporarily reports OFF while
# touch or qualifying camera motion displays the Home Assistant kiosk.
#
- binary_sensor:
name: "Screensaver Active"
unique_id: flounder_kiosk_screensaver_active
default_entity_id: binary_sensor.flounder_kiosk_screensaver_active
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
entity_category: diagnostic
state_topic: "viewroad-status/flounder/screensaver/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
payload_on: "ON"
payload_off: "OFF"
icon: mdi:monitor-shimmer
#:########################################################################################:#
# Flounder Kiosk Motion #
#:########################################################################################:#
#
# Reports raw movement detected by the local Motion camera service.
#
# Motion continues reporting in Screen Lock and while Motion Wake is OFF. It only
# affects display activity when Motion Wake is ON and Display Mode is not
# Screen Lock.
#
- binary_sensor:
name: "Motion"
unique_id: flounder_kiosk_motion
default_entity_id: binary_sensor.flounder_kiosk_motion
device:
identifiers:
- flounder_kiosk
name: "Flounder Kiosk"
manufacturer: "Dell"
model: "Portrait Touchscreen Kiosk"
suggested_area: "Lounge"
state_topic: "viewroad-status/flounder/motion/state"
availability_topic: "viewroad-status/flounder/availability"
payload_available: "ON"
payload_not_available: "OFF"
payload_on: "ON"
payload_off: "OFF"
device_class: motion
+11
View File
@@ -2,6 +2,11 @@
# PACKAGE: Free Power Time Automation # # PACKAGE: Free Power Time Automation #
#:########################################################################################:# #:########################################################################################:#
# VERSION: # VERSION:
# 1.2.0 - 2026-07-24
# - Added startup catch-up to end_actions: when HA starts outside the
# free power window, the end actions (chargers off, dehumidifier off)
# are applied immediately.
#
# 1.1.0 - 2026-06-24 # 1.1.0 - 2026-06-24
# - Changed gas-to-heatpump handover so the heat pump setpoint is offset from # - Changed gas-to-heatpump handover so the heat pump setpoint is offset from
# the gas heater setpoint. # the gas heater setpoint.
@@ -316,5 +321,11 @@ automation:
triggers: triggers:
- trigger: time - trigger: time
at: input_datetime.free_power_end_time at: input_datetime.free_power_end_time
- trigger: homeassistant
event: start
conditions:
- condition: state
entity_id: binary_sensor.free_power_time_active
state: "off"
actions: actions:
- action: script.free_power_end_actions - action: script.free_power_end_actions
@@ -9,9 +9,14 @@
# packages/heat_pump_master_bedroom_schedules.yaml # packages/heat_pump_master_bedroom_schedules.yaml
# #
# VERSION: # VERSION:
# V1.1 2026-07-20 # V1.2 2026-07-24
# #
# VERSION HISTORY: # VERSION HISTORY:
# V1.2 2026-07-24
# - Added startup catch-up to midnight_off: when HA starts between
# midnight and 21:00 with the Midnight Off or Night Power toggle on,
# the heat pump is turned off immediately.
#
# V1.1 2026-07-20 # V1.1 2026-07-20
# - Added structured documentation for schedules, boost, and helper behavior. # - Added structured documentation for schedules, boost, and helper behavior.
# #
@@ -50,7 +55,9 @@
# #
# OPERATION NOTES: # OPERATION NOTES:
# - The 21:00 and midnight schedules use exact-time triggers. # - The 21:00 and midnight schedules use exact-time triggers.
# - There is no startup catch-up if Home Assistant is offline at either time. # - The midnight_off automation includes a startup trigger: if HA restarts
# between midnight and 21:00 with the Midnight Off or Night Power toggle
# on, the heat pump is turned off immediately.
# #
########################################################################################## ##########################################################################################
@@ -214,6 +221,11 @@ automation:
trigger: trigger:
- platform: time - platform: time
at: "00:00:00" at: "00:00:00"
- platform: homeassistant
event: start
condition:
- condition: template
value_template: "{{ now().hour < 21 }}"
action: action:
- choose: - choose:
- conditions: - conditions:
+7 -7
View File
@@ -126,7 +126,7 @@ script:
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "on" #switch.esp_loungemiddleswitch_relay_3_downlights_north: "on"
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "on" # non dimmable pair switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "on" # non dimmable pair
light.esp_breakfastbarleds_breakfast_bar_leds: 90 light.esp_breakfastbarleds_breakfast_bar_leds: 90
light.esp_loungecabinetleds_lounge_cabinet_leds: 90 number.esp_loungecabinetleds_lounge_cabinet_leds_output_set_0_100: 100
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 90 light.esp_loungebookshelfleds_lounge_bookshelf_leds: 90
switch.lounge_cupboard_dual_usb_xus09_l2: "on" switch.lounge_cupboard_dual_usb_xus09_l2: "on"
switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "on" switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "on"
@@ -146,7 +146,7 @@ script:
light.esp_lounge6chdimmer_lounge_downlights_south: 60 light.esp_lounge6chdimmer_lounge_downlights_south: 60
light.esp_lounge6chdimmer_lounge_rafter_buttons: 40 light.esp_lounge6chdimmer_lounge_rafter_buttons: 40
light.esp_breakfastbarleds_breakfast_bar_leds: 60 light.esp_breakfastbarleds_breakfast_bar_leds: 60
light.esp_loungecabinetleds_lounge_cabinet_leds: 60 number.esp_loungecabinetleds_lounge_cabinet_leds_output_set_0_100: 66
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 60 light.esp_loungebookshelfleds_lounge_bookshelf_leds: 60
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" # non-dimmable pair #switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" # non-dimmable pair
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
@@ -167,7 +167,7 @@ script:
light.esp_lounge6chdimmer_lounge_downlights_south: 40 light.esp_lounge6chdimmer_lounge_downlights_south: 40
light.esp_lounge6chdimmer_lounge_rafter_buttons: 30 light.esp_lounge6chdimmer_lounge_rafter_buttons: 30
light.esp_breakfastbarleds_breakfast_bar_leds: 50 light.esp_breakfastbarleds_breakfast_bar_leds: 50
light.esp_loungecabinetleds_lounge_cabinet_leds: 50 number.esp_loungecabinetleds_lounge_cabinet_leds_output_set_0_100: 55
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 50 light.esp_loungebookshelfleds_lounge_bookshelf_leds: 50
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" # non-dimmable pair #switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" # non-dimmable pair
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
@@ -188,7 +188,7 @@ script:
light.esp_lounge6chdimmer_lounge_downlights_south: 30 light.esp_lounge6chdimmer_lounge_downlights_south: 30
light.esp_lounge6chdimmer_lounge_rafter_buttons: 0 light.esp_lounge6chdimmer_lounge_rafter_buttons: 0
light.esp_breakfastbarleds_breakfast_bar_leds: 40 light.esp_breakfastbarleds_breakfast_bar_leds: 40
light.esp_loungecabinetleds_lounge_cabinet_leds: 40 number.esp_loungecabinetleds_lounge_cabinet_leds_output_set_0_100: 44
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 40 light.esp_loungebookshelfleds_lounge_bookshelf_leds: 40
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" #switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
@@ -228,7 +228,7 @@ script:
light.esp_lounge6chdimmer_lounge_downlights_south: 0 light.esp_lounge6chdimmer_lounge_downlights_south: 0
light.esp_lounge6chdimmer_lounge_rafter_buttons: 0 light.esp_lounge6chdimmer_lounge_rafter_buttons: 0
light.esp_breakfastbarleds_breakfast_bar_leds: 5 light.esp_breakfastbarleds_breakfast_bar_leds: 5
light.esp_loungecabinetleds_lounge_cabinet_leds: 5 number.esp_loungecabinetleds_lounge_cabinet_leds_output_set_0_100: 4
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 5 light.esp_loungebookshelfleds_lounge_bookshelf_leds: 5
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" #switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
@@ -246,7 +246,7 @@ script:
light.esp_lounge6chdimmer_couch_spots_right: 20 light.esp_lounge6chdimmer_couch_spots_right: 20
light.esp_lounge6chdimmer_lounge_rafter_buttons: 15 light.esp_lounge6chdimmer_lounge_rafter_buttons: 15
light.esp_breakfastbarleds_breakfast_bar_leds: 25 light.esp_breakfastbarleds_breakfast_bar_leds: 25
light.esp_loungecabinetleds_lounge_cabinet_leds: 30 number.esp_loungecabinetleds_lounge_cabinet_leds_output_set_0_100: 33
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 30 light.esp_loungebookshelfleds_lounge_bookshelf_leds: 30
#light.tasmo_h801_loungeled1_6180_a: 25 #light.tasmo_h801_loungeled1_6180_a: 25
#light.tasmo_h801_loungeled1_6180_b: 25 #light.tasmo_h801_loungeled1_6180_b: 25
@@ -270,7 +270,7 @@ script:
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" #switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
light.esp_breakfastbarleds_breakfast_bar_leds: 0 light.esp_breakfastbarleds_breakfast_bar_leds: 0
light.esp_loungecabinetleds_lounge_cabinet_leds: 0 number.esp_loungecabinetleds_lounge_cabinet_leds_output_set_0_100: 0
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 0 light.esp_loungebookshelfleds_lounge_bookshelf_leds: 0
switch.lounge_cupboard_dual_usb_xus09_l2: "off" switch.lounge_cupboard_dual_usb_xus09_l2: "off"
switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "off" switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "off"
@@ -1,8 +1,12 @@
################################################################################ ################################################################################
# PACKAGE: Office Lights And Power Backup Occupancy Automation # PACKAGE: Office Power Backup Occupancy Automation
################################################################################ ################################################################################
# #
# Version: # Version:
# - 1.1 - 2026-07-25
# - Stripped light control (now handled by direct MQTT)
# - Retains power supply backup control only
#
# - 1.0 - 2026-04-25 # - 1.0 - 2026-04-25
# - Initial package version. # - Initial package version.
# - Backup automation for Office lights and Office power. # - Backup automation for Office lights and Office power.
@@ -10,19 +14,18 @@
# - Uses Office spare button / relay as a backup manual master. # - Uses Office spare button / relay as a backup manual master.
# #
# Operation: # Operation:
# - Turns Office lights and power on when the Office mmWave occupancy sensor # - Turns Office power supplies on when the Office mmWave occupancy sensor
# detects occupancy or movement. # detects occupancy or movement.
# #
# - Turns Office lights and power off after the Office mmWave occupancy sensor # - Turns Office power supplies off after the Office mmWave occupancy sensor
# has been clear for the configured delay period. # has been clear for the configured delay period.
# #
# - Provides a backup manual control path using the Office spare button. # - Provides a backup manual control path using the Office spare button.
# This is useful if the occupancy sensor is offline. # This is useful if the occupancy sensor is offline.
# #
# Notes: # Notes:
# - This is treated as a BACKUP automation. # - This is treated as a BACKUP automation for POWER SUPPLIES ONLY.
# - The standard method should still be the direct ESPHome/MQTT control path. # - Light control is handled by direct ESPHome/MQTT (see device YAMLs).
# - This HA automation provides a fallback path using HA entity states.
# - The physical spare button is read using: # - The physical spare button is read using:
# binary_sensor.esp_officelights_button_3_spare # binary_sensor.esp_officelights_button_3_spare
# - The spare relay is used as the manual master/latch state: # - The spare relay is used as the manual master/latch state:
@@ -36,7 +39,7 @@
input_number: input_number:
office_lights_backup_clear_delay_seconds: office_lights_backup_clear_delay_seconds:
name: "Office Lights Backup Clear Delay Seconds" name: "Office Power Backup Clear Delay Seconds"
min: 0 min: 0
max: 3600 max: 3600
step: 1 step: 1
@@ -50,13 +53,14 @@ input_number:
################################################################################ ################################################################################
automation: automation:
- id: office_lights_power_backup_occupancy_control - id: office_power_backup_occupancy_control
alias: "Office Lights And Power - Backup Occupancy Control" alias: "Office Power - Backup Occupancy Control"
description: > description: >
Backup automation for Office lights and power. Turns required devices on Backup automation for Office power supplies. Turns power on when Office
when Office mmWave occupancy or movement is detected. Turns them off after mmWave occupancy or movement is detected. Turns power off after the
the occupancy sensor is clear for the configured delay period. Also allows occupancy sensor is clear for the configured delay period. Also allows
manual backup toggling using the Office spare button and spare relay. manual backup toggling using the Office spare button and spare relay.
Light control is handled by direct ESPHome/MQTT sync.
mode: restart mode: restart
triggers: triggers:
########################################################################## ##########################################################################
@@ -79,8 +83,8 @@ automation:
# Manual backup button press. # Manual backup button press.
# #
# The spare relay state is used as the master/latch: # The spare relay state is used as the master/latch:
# - If spare relay is OFF when the button is pressed, turn everything ON. # - If spare relay is OFF when the button is pressed, turn power ON.
# - If spare relay is ON when the button is pressed, turn everything OFF. # - If spare relay is ON when the button is pressed, turn power OFF.
########################################################################## ##########################################################################
- trigger: state - trigger: state
entity_id: binary_sensor.esp_officelights_button_3_spare entity_id: binary_sensor.esp_officelights_button_3_spare
@@ -102,15 +106,15 @@ automation:
- choose: - choose:
###################################################################### ######################################################################
# ON LOGIC: # ON LOGIC:
# Occupancy detected - turn everything on. # Occupancy detected - turn power supplies on.
###################################################################### ######################################################################
- alias: "Occupancy detected - turn Office lights and power on" - alias: "Occupancy detected - turn Office power on"
conditions: conditions:
- condition: trigger - condition: trigger
id: occupancy_detected id: occupancy_detected
sequence: sequence:
############################################################## ##############################################################
# Power first. # Power supplies.
############################################################## ##############################################################
- alias: "Turn on Office ELV power supply if needed" - alias: "Turn on Office ELV power supply if needed"
if: if:
@@ -132,59 +136,6 @@ automation:
target: target:
entity_id: switch.esp_officedeskrightgpo_office_right_hand_gpo entity_id: switch.esp_officedeskrightgpo_office_right_hand_gpo
#- alias: "Turn on Office USB Hub if needed"
# if:
# - condition: state
# entity_id: switch.esp_officeusbhubpower_usb_hub_power_supply
# state: "off"
# then:
# - action: switch.turn_on
# target:
# entity_id: switch.esp_officeusbhubpower_usb_hub_power_supply
##############################################################
# Lights.
##############################################################
- alias: "Turn on Office right hand bunker light if needed"
if:
- condition: state
entity_id: light.esp_officeduallights_light_1_right_hand_bunker_light
state: "off"
then:
- action: light.turn_on
target:
entity_id: light.esp_officeduallights_light_1_right_hand_bunker_light
- alias: "Turn on Office cool white overhead lights if needed"
if:
- condition: state
entity_id: light.esp_officeduallights_light_2_cool_white_overhead_lights
state: "off"
then:
- action: light.turn_on
target:
entity_id: light.esp_officeduallights_light_2_cool_white_overhead_lights
- alias: "Turn on Office nighttime lights relay if needed"
if:
- condition: state
entity_id: switch.esp_officelights_relay_1_nighttime_lights
state: "off"
then:
- action: switch.turn_on
target:
entity_id: switch.esp_officelights_relay_1_nighttime_lights
- alias: "Turn on Office daytime lights relay if needed"
if:
- condition: state
entity_id: switch.esp_officelights_relay_2_daytime_lights
state: "off"
then:
- action: switch.turn_on
target:
entity_id: switch.esp_officelights_relay_2_daytime_lights
############################################################## ##############################################################
# Manual master/latch relay. # Manual master/latch relay.
############################################################## ##############################################################
@@ -200,9 +151,9 @@ automation:
###################################################################### ######################################################################
# OFF LOGIC: # OFF LOGIC:
# Occupancy clear - wait, re-check, then turn everything off. # Occupancy clear - wait, re-check, then turn power supplies off.
###################################################################### ######################################################################
- alias: "Occupancy clear - wait, re-check, then turn Office lights and power off" - alias: "Occupancy clear - wait, re-check, then turn Office power off"
conditions: conditions:
- condition: template - condition: template
value_template: > value_template: >
@@ -229,50 +180,7 @@ automation:
state: "off" state: "off"
############################################################## ##############################################################
# Lights off first. # Power off.
##############################################################
- alias: "Turn off Office right hand bunker light if needed"
if:
- condition: state
entity_id: light.esp_officeduallights_light_1_right_hand_bunker_light
state: "on"
then:
- action: light.turn_off
target:
entity_id: light.esp_officeduallights_light_1_right_hand_bunker_light
- alias: "Turn off Office cool white overhead lights if needed"
if:
- condition: state
entity_id: light.esp_officeduallights_light_2_cool_white_overhead_lights
state: "on"
then:
- action: light.turn_off
target:
entity_id: light.esp_officeduallights_light_2_cool_white_overhead_lights
- alias: "Turn off Office nighttime lights relay if needed"
if:
- condition: state
entity_id: switch.esp_officelights_relay_1_nighttime_lights
state: "on"
then:
- action: switch.turn_off
target:
entity_id: switch.esp_officelights_relay_1_nighttime_lights
- alias: "Turn off Office daytime lights relay if needed"
if:
- condition: state
entity_id: switch.esp_officelights_relay_2_daytime_lights
state: "on"
then:
- action: switch.turn_off
target:
entity_id: switch.esp_officelights_relay_2_daytime_lights
##############################################################
# Power off after lights.
############################################################## ##############################################################
- alias: "Turn off Office right hand GPO if needed" - alias: "Turn off Office right hand GPO if needed"
if: if:
@@ -294,16 +202,6 @@ automation:
target: target:
entity_id: switch.esp_officeelvcontrol_office_elv_power_supply entity_id: switch.esp_officeelvcontrol_office_elv_power_supply
#- alias: "Turn off Office USB Hub power supply if needed"
# if:
# - condition: state
# entity_id: switch.esp_officeusbhubpower_usb_hub_power_supply
# state: "on"
# then:
# - action: switch.turn_off
# target:
# entity_id: switch.esp_officeusbhubpower_usb_hub_power_supply
############################################################## ##############################################################
# Manual master/latch relay off last. # Manual master/latch relay off last.
############################################################## ##############################################################
@@ -319,9 +217,9 @@ automation:
###################################################################### ######################################################################
# MANUAL BACKUP LOGIC: # MANUAL BACKUP LOGIC:
# Button pressed while spare relay master is ON - turn everything OFF. # Button pressed while spare relay master is ON - turn power off.
###################################################################### ######################################################################
- alias: "Backup button pressed - spare relay on, turn everything off" - alias: "Backup button pressed - spare relay on, turn power off"
conditions: conditions:
- condition: trigger - condition: trigger
id: backup_button_pressed id: backup_button_pressed
@@ -330,50 +228,7 @@ automation:
state: "on" state: "on"
sequence: sequence:
############################################################## ##############################################################
# Lights off first. # Power off.
##############################################################
- alias: "Turn off Office right hand bunker light if needed"
if:
- condition: state
entity_id: light.esp_officeduallights_light_1_right_hand_bunker_light
state: "on"
then:
- action: light.turn_off
target:
entity_id: light.esp_officeduallights_light_1_right_hand_bunker_light
- alias: "Turn off Office cool white overhead lights if needed"
if:
- condition: state
entity_id: light.esp_officeduallights_light_2_cool_white_overhead_lights
state: "on"
then:
- action: light.turn_off
target:
entity_id: light.esp_officeduallights_light_2_cool_white_overhead_lights
- alias: "Turn off Office nighttime lights relay if needed"
if:
- condition: state
entity_id: switch.esp_officelights_relay_1_nighttime_lights
state: "on"
then:
- action: switch.turn_off
target:
entity_id: switch.esp_officelights_relay_1_nighttime_lights
- alias: "Turn off Office daytime lights relay if needed"
if:
- condition: state
entity_id: switch.esp_officelights_relay_2_daytime_lights
state: "on"
then:
- action: switch.turn_off
target:
entity_id: switch.esp_officelights_relay_2_daytime_lights
##############################################################
# Power off after lights.
############################################################## ##############################################################
- alias: "Turn off Office right hand GPO if needed" - alias: "Turn off Office right hand GPO if needed"
if: if:
@@ -395,16 +250,6 @@ automation:
target: target:
entity_id: switch.esp_officeelvcontrol_office_elv_power_supply entity_id: switch.esp_officeelvcontrol_office_elv_power_supply
#- alias: "Turn off Office USB Hub power supply if needed"
# if:
# - condition: state
# entity_id: switch.esp_officeusbhubpower_usb_hub_power_supply
# state: "on"
# then:
# - action: switch.turn_off
# target:
# entity_id: switch.esp_officeusbhubpower_usb_hub_power_supply
############################################################## ##############################################################
# Manual master/latch relay off last. # Manual master/latch relay off last.
############################################################## ##############################################################
@@ -420,12 +265,12 @@ automation:
###################################################################### ######################################################################
# MANUAL BACKUP LOGIC: # MANUAL BACKUP LOGIC:
# Button pressed while spare relay master is OFF - turn everything ON. # Button pressed while spare relay master is OFF - turn power on.
# #
# No off timer is started from this manual press. If the occupancy # No off timer is started from this manual press. If the occupancy
# sensor later changes to clear, the normal clear-delay logic will run. # sensor later changes to clear, the normal clear-delay logic will run.
###################################################################### ######################################################################
- alias: "Backup button pressed - spare relay off, turn everything on" - alias: "Backup button pressed - spare relay off, turn power on"
conditions: conditions:
- condition: trigger - condition: trigger
id: backup_button_pressed id: backup_button_pressed
@@ -434,7 +279,7 @@ automation:
state: "off" state: "off"
sequence: sequence:
############################################################## ##############################################################
# Power first. # Power supplies.
############################################################## ##############################################################
- alias: "Turn on Office ELV power supply if needed" - alias: "Turn on Office ELV power supply if needed"
if: if:
@@ -456,59 +301,6 @@ automation:
target: target:
entity_id: switch.esp_officedeskrightgpo_office_right_hand_gpo entity_id: switch.esp_officedeskrightgpo_office_right_hand_gpo
# alias: "Turn on Office USB Hub power supply if needed"
# if:
# - condition: state
# entity_id: switch.esp_officeusbhubpower_usb_hub_power_supply
# state: "off"
# then:
# - action: switch.turn_on
# target:
# entity_id: switch.esp_officeusbhubpower_usb_hub_power_supply
##############################################################
# Lights.
##############################################################
- alias: "Turn on Office right hand bunker light if needed"
if:
- condition: state
entity_id: light.esp_officeduallights_light_1_right_hand_bunker_light
state: "off"
then:
- action: light.turn_on
target:
entity_id: light.esp_officeduallights_light_1_right_hand_bunker_light
- alias: "Turn on Office cool white overhead lights if needed"
if:
- condition: state
entity_id: light.esp_officeduallights_light_2_cool_white_overhead_lights
state: "off"
then:
- action: light.turn_on
target:
entity_id: light.esp_officeduallights_light_2_cool_white_overhead_lights
- alias: "Turn on Office nighttime lights relay if needed"
if:
- condition: state
entity_id: switch.esp_officelights_relay_1_nighttime_lights
state: "off"
then:
- action: switch.turn_on
target:
entity_id: switch.esp_officelights_relay_1_nighttime_lights
- alias: "Turn on Office daytime lights relay if needed"
if:
- condition: state
entity_id: switch.esp_officelights_relay_2_daytime_lights
state: "off"
then:
- action: switch.turn_on
target:
entity_id: switch.esp_officelights_relay_2_daytime_lights
############################################################## ##############################################################
# Manual master/latch relay. # Manual master/latch relay.
############################################################## ##############################################################
+139 -2
View File
@@ -1,12 +1,14 @@
#:########################################################################################:# #:########################################################################################:#
# Package: Pet Feeding and Jobs Timing # Package: Pet Feeding and Jobs Timing
# File: pet_feeding_and_jobs.yaml # File: pet_feeding_and_jobs.yaml
# Version: v1.1.0 # Version: v1.4.0
# Date: 2026-07-21 # Date: 2026-07-26
# #
# Purpose: # Purpose:
# Provides legacy MQTT pet activity sensors and Jobs-derived timing sensors for # Provides legacy MQTT pet activity sensors and Jobs-derived timing sensors for
# the Lounge dog-feeding and depooping gauges. # the Lounge dog-feeding and depooping gauges.
# v1.2.0: Added input_datetime helpers and automations so the View Road Events
# home-feed-card shows correct X minutes ago after HA restart.
# #
# Behaviour: # Behaviour:
# - Dog feeding reports the newest valid morning or evening completion time. # - Dog feeding reports the newest valid morning or evening completion time.
@@ -15,6 +17,12 @@
# instead of exposing a numeric sentinel value. # instead of exposing a numeric sentinel value.
# #
# Version History: # Version History:
# - v1.4.0 (2026-07-26): Announce four physical job completions on the Sony
# lounge TV and both Pushover devices.
# - v1.3.0 (2026-07-26): Restore retained dog-fed and jobs-done activity
# feed publishing when physical completion events are received.
# - v1.2.0 (2026-07-24): Added persistent input_datetime timestamps for
# home-feed-card so time-ago survives HA restart.
# - v1.1.0 (2026-07-21): Reject invalid Jobs timing attributes and remove the # - v1.1.0 (2026-07-21): Reject invalid Jobs timing attributes and remove the
# 999999-hour fallback from the dog-feeding gauge source. # 999999-hour fallback from the dog-feeding gauge source.
# - v1.0.0 (2026-07-21): Added Jobs-derived dog timing sensors for P010. # - v1.0.0 (2026-07-21): Added Jobs-derived dog timing sensors for P010.
@@ -90,3 +98,132 @@ template:
state: >- state: >-
{% set hours = state_attr('sensor.jobs_tracker_dog_depooping', 'hours_since_completed') %} {% set hours = state_attr('sensor.jobs_tracker_dog_depooping', 'hours_since_completed') %}
{{ hours | float(0) if is_number(hours) else none }} {{ hours | float(0) if is_number(hours) else none }}
#:######################################################################################:#
# PERSISTENT EVENT TIMESTAMPS (survive HA restart)
#:######################################################################################:#
# These input_datetime entities store the actual wall-clock time of the most recent
# event. The home-feed-card uses last_changed for "X minutes ago".
# Since input_datetime state is restored from the database after restart,
# last_changed reflects the actual event time, not the restart time.
# input_datetime entities created via HA API (not in YAML)
#:######################################################################################:#
# AUTOMATIONS: Update timestamps on event
#:######################################################################################:#
automation:
- id: timestamp_dog_fed
alias: "Timestamp - Dog Fed"
mode: single
triggers:
- trigger: state
entity_id: event.jobs_dog_fed_button_x14bt_action
conditions:
- condition: template
value_template: >-
{{ trigger.to_state.state not in ['unknown', 'unavailable'] }}
actions:
- action: input_datetime.set_datetime
target:
entity_id: input_datetime.dog_last_fed
data:
timestamp: "{{ as_timestamp(now()) }}"
- action: mqtt.publish
data:
topic: "viewroad-status/activityfeed/dogfed"
payload: "{{ now().strftime('%H:%M') }}"
qos: 0
retain: true
- id: timestamp_dog_depooped
alias: "Timestamp - Dog Depooped"
mode: single
triggers:
- trigger: state
entity_id: event.jobs_dog_depooped_button_x15bt_action
conditions:
- condition: template
value_template: >-
{{ trigger.to_state.state not in ['unknown', 'unavailable'] }}
actions:
- action: input_datetime.set_datetime
target:
entity_id: input_datetime.dog_last_depooped
data:
timestamp: "{{ as_timestamp(now()) }}"
- id: timestamp_jobs_done
alias: "Timestamp - Any Job Completed"
description: >-
Updates the jobs-done timestamp whenever any tracked job completion
event fires. This keeps the "Jobs Done" entry in the home-feed-card
showing the time of the most recent job completion.
mode: single
triggers:
- trigger: state
entity_id:
- event.jobs_dog_fed_button_x14bt_action
- event.jobs_dog_depooped_button_x15bt_action
- event.kitchen_jobs_kitchen_completed_buttons_button_1
- event.kitchen_jobs_kitchen_completed_buttons_button_2
conditions:
- condition: template
value_template: >-
{{ trigger.to_state.state not in ['unknown', 'unavailable'] }}
actions:
- action: input_datetime.set_datetime
target:
entity_id: input_datetime.last_jobs_done
data:
timestamp: "{{ as_timestamp(now()) }}"
- action: mqtt.publish
data:
topic: "viewroad-status/activityfeed/jobsdone"
payload: "{{ now().strftime('%-I:%M %p') }}"
qos: 0
retain: true
- id: jobs_completion_announcements
alias: "Jobs - Completion Announcements"
description: >-
Announces physical dog feeding, dog depooping, dishwasher and rubbish
completion events on the lounge Sony TV and both Pushover devices.
mode: queued
max: 10
triggers:
- trigger: state
entity_id:
- event.jobs_dog_fed_button_x14bt_action
- event.jobs_dog_depooped_button_x15bt_action
- event.kitchen_jobs_kitchen_completed_buttons_button_1
- event.kitchen_jobs_kitchen_completed_buttons_button_2
conditions:
- condition: template
value_template: >-
{% set valid_state = trigger.to_state is not none
and trigger.to_state.state not in ['unknown', 'unavailable'] %}
{% set event_ts = as_timestamp(trigger.to_state.state, 0)
if valid_state else 0 %}
{% set event_age = as_timestamp(now()) - event_ts %}
{{ valid_state and event_ts > 0 and event_age >= 0 and event_age <= 30 }}
actions:
- variables:
completion_message: >-
{% if trigger.entity_id == 'event.jobs_dog_fed_button_x14bt_action' %}
Zorro has been fed
{% elif trigger.entity_id == 'event.jobs_dog_depooped_button_x15bt_action' %}
Zorro has been depooped
{% elif trigger.entity_id == 'event.kitchen_jobs_kitchen_completed_buttons_button_1' %}
Dishwasher has been emptied
{% elif trigger.entity_id == 'event.kitchen_jobs_kitchen_completed_buttons_button_2' %}
Rubbish has been removed
{% else %}
Job has been completed
{% endif %}
- action: script.view_road_announcement
data:
channels: "sony_tv_lounge, pushover_zorruno, pushover_kim"
title: "Jobs Announcement"
short_announcement: "{{ completion_message }}"
long_announcement: "{{ completion_message }}"
+97
View File
@@ -0,0 +1,97 @@
#:########################################################################################:#
# PACKAGE: Zorro Evening Feeding Reminder (P017-S013)
# FILE: packages/p017_s013_zorro_feeding_reminder.yaml
# VERSION: v1.0.1 2026-07-26
#:########################################################################################:#
# PURPOSE:
# Remind to feed Zorro (evening feeding) if not completed.
# LED matrix shows "Feed Zorro" every 30 min from 5pm to 10pm.
# Voice says "Zorro has not been fed this afternoon" every 30 min from 5pm to 8pm.
# Each announcement has a random delay of 0-10 min for natural variation.
# Clears LED matrix immediately when evening feeding is completed.
#:########################################################################################:#
# DEPENDENCIES:
# - packages/view_road_announcement_router.yaml for LED/voice announcements
# - packages/Job_Chore_Tracking/jobs_tracker_jobs.yaml for evening feeding sensor
# - ESPHome LED matrix for cancel_id MQTT topic
#:########################################################################################:#
input_boolean:
zorro_feeding_reminder_enabled:
name: Zorro Feeding Reminder
icon: mdi:dog
initial: true
automation:
##############################################################################
# EVENING FEEDING REMINDER
##############################################################################
- id: zorro_evening_feeding_reminder
alias: "Zorro - Evening Feeding Reminder"
mode: single
trigger:
- trigger: time_pattern
minutes: "/30"
- trigger: homeassistant
event: start
condition:
- condition: state
entity_id: input_boolean.zorro_feeding_reminder_enabled
state: "on"
- condition: template
value_template: >
{{ now().hour >= 17 and now().hour < 22 }}
- condition: template
value_template: >
{{ states('sensor.jobs_tracker_dog_feeding_evening') != 'Complete' }}
action:
- variables:
voice_hours: "{{ now().hour < 20 }}"
quiet_time: "{{ is_state('input_boolean.quiet_time', 'on') }}"
- delay:
seconds: "{{ range(0, 601) | random | int }}"
- action: script.view_road_announcement
data:
channels: "led_matrix_1, sony_tv_lounge"
title: "Zorro"
short_announcement: "Feed Zorro"
indicator: "zorro,1,15,10,6,5,0,0"
- if:
- condition: template
value_template: "{{ voice_hours and not quiet_time }}"
then:
- action: script.view_road_announcement
data:
channels: "lounge_google_home_voice"
title: "Zorro"
short_announcement: "Zorro has not been fed this afternoon"
##############################################################################
# CLEAR LED MATRIX WHEN FED
##############################################################################
- id: zorro_clear_led_when_fed
alias: "Zorro - Clear LED Matrix When Fed"
mode: single
trigger:
- trigger: state
entity_id: sensor.jobs_tracker_dog_feeding_evening
to: "Complete"
action:
- action: mqtt.publish
data:
topic: "viewroad-commands/ledmatrix1/cancel_id"
payload: "zorro"
qos: 0
retain: false
+188
View File
@@ -0,0 +1,188 @@
#:########################################################################################:#
# PACKAGE: Potplant Moisture Alerts
# FILE: packages/potplant_moisture_alerts.yaml
# VERSION: v1.1.0 2026-07-29
# - Preserve user-selected thresholds and master enable state across restarts.
#:########################################################################################:#
# PURPOSE:
# Alert when potplant soil moisture drops below a configurable threshold.
# Displays on the Lounge LED matrix and announces via Lounge Google Home voice.
#:########################################################################################:#
# SETTINGS:
# - input_number.*_moisture_threshold: per-plant dry threshold (default 30%)
# - input_boolean.potplant_alert_enabled: master enable toggle
#:########################################################################################:#
# DEPENDENCIES:
# - packages/view_road_announcement_router.yaml for script.view_road_announcement
# - sensor.table_plant_soil_moisture
# - sensor.tv_plant_soil_moisture
#:########################################################################################:#
input_number:
table_plant_moisture_threshold:
name: Table Plant Moisture Threshold
min: 0
max: 100
step: 5
unit_of_measurement: "%"
icon: mdi:water-percent
tv_plant_moisture_threshold:
name: TV Plant Moisture Threshold
min: 0
max: 100
step: 5
unit_of_measurement: "%"
icon: mdi:water-percent
input_boolean:
potplant_alert_enabled:
name: Potplant Moisture Alerts
icon: mdi:sprout
template:
- binary_sensor:
- name: "Table Plant Needs Water"
unique_id: table_plant_needs_water
icon: mdi:flower
state: >-
{{ (states('sensor.table_plant_soil_moisture') | float(100)) <
(states('input_number.table_plant_moisture_threshold') | float(30)) }}
- name: "TV Plant Needs Water"
unique_id: tv_plant_needs_water
icon: mdi:flower
state: >-
{{ (states('sensor.tv_plant_soil_moisture') | float(100)) <
(states('input_number.tv_plant_moisture_threshold') | float(30)) }}
automation:
##############################################################################
# TABLE PLANT
##############################################################################
- id: potplant_table_plant_alert
alias: "Potplant - Table Plant Needs Water"
mode: single
trigger:
- trigger: state
entity_id: binary_sensor.table_plant_needs_water
to: "on"
- trigger: time_pattern
hours: "/2"
- trigger: homeassistant
event: start
condition:
- condition: state
entity_id: input_boolean.potplant_alert_enabled
state: "on"
- condition: state
entity_id: input_boolean.quiet_time
state: "off"
- condition: state
entity_id: binary_sensor.table_plant_needs_water
state: "on"
action:
- action: script.view_road_announcement
data:
channels: "led_matrix_1"
title: "Plants"
short_announcement: "Water Table Plant"
indicator: "table,1,15,10,6,5,0,0"
- action: script.view_road_announcement
data:
channels: "lounge_google_home_voice"
title: "Plants"
short_announcement: "Table plant needs water"
- action: script.view_road_announcement
data:
channels: "sony_tv_lounge"
title: "Plants Announcement"
short_announcement: "Table plant needs water"
- id: potplant_table_clear_led
alias: "Potplant - Clear Table Plant LED"
mode: single
trigger:
- trigger: state
entity_id: binary_sensor.table_plant_needs_water
to: "off"
action:
- action: mqtt.publish
data:
topic: "viewroad-commands/ledmatrix1/cancel_id"
payload: "table"
qos: 0
retain: false
##############################################################################
# TV PLANT
##############################################################################
- id: potplant_tv_plant_alert
alias: "Potplant - TV Plant Needs Water"
mode: single
trigger:
- trigger: state
entity_id: binary_sensor.tv_plant_needs_water
to: "on"
- trigger: time_pattern
hours: "/2"
- trigger: homeassistant
event: start
condition:
- condition: state
entity_id: input_boolean.potplant_alert_enabled
state: "on"
- condition: state
entity_id: input_boolean.quiet_time
state: "off"
- condition: state
entity_id: binary_sensor.tv_plant_needs_water
state: "on"
action:
- action: script.view_road_announcement
data:
channels: "led_matrix_1"
title: "Plants"
short_announcement: "Water TV Plant"
indicator: "tvplant,1,15,10,6,5,0,0"
- action: script.view_road_announcement
data:
channels: "lounge_google_home_voice"
title: "Plants"
short_announcement: "TV plant needs water"
- action: script.view_road_announcement
data:
channels: "sony_tv_lounge"
title: "Plants Announcement"
short_announcement: "TV plant needs water"
- id: potplant_tv_clear_led
alias: "Potplant - Clear TV Plant LED"
mode: single
trigger:
- trigger: state
entity_id: binary_sensor.tv_plant_needs_water
to: "off"
action:
- action: mqtt.publish
data:
topic: "viewroad-commands/ledmatrix1/cancel_id"
payload: "tvplant"
qos: 0
retain: false
+10 -2
View File
@@ -1,8 +1,8 @@
#:########################################################################################:# #:########################################################################################:#
# Package: Recorder Configuration # Package: Recorder Configuration
# File: recorder.yaml # File: recorder.yaml
# Version: v1.1.0 # Version: v1.2.0
# Date: 2026-07-23 # Date: 2026-07-24
# #
# Purpose: # Purpose:
# Enables Home Assistant Recorder with targeted exclusions for high-frequency # Enables Home Assistant Recorder with targeted exclusions for high-frequency
@@ -12,6 +12,8 @@
# - ESPHome uptime sensors. # - ESPHome uptime sensors.
# - Home Assistant summary v2 sensors. # - Home Assistant summary v2 sensors.
# - Jobs Tracker summary sensor. # - Jobs Tracker summary sensor.
# - Fisher & Paykel oven temperature sensors reporting Fahrenheit as Celsius.
# - Creality K1C static hardware-limit max-temp sensors.
# #
# Notes: # Notes:
# - Excluded entities remain available for current-state use. # - Excluded entities remain available for current-state use.
@@ -19,6 +21,7 @@
# defaults unless configured elsewhere. # defaults unless configured elsewhere.
# #
# Version History: # Version History:
# - v1.2.0 (2026-07-24): Added GE Home oven F→C bogus sensor exclusions for F043 and 3D printer static max-temp exclusions for F044.
# - v1.1.0 (2026-07-23): Added targeted exclusions during P013-F010 cleanup. # - v1.1.0 (2026-07-23): Added targeted exclusions during P013-F010 cleanup.
# - v1.0.0 (2022-10-11): Initial Recorder package. # - v1.0.0 (2022-10-11): Initial Recorder package.
#:########################################################################################:# #:########################################################################################:#
@@ -30,3 +33,8 @@ recorder:
- sensor.ha_summary_v2_* - sensor.ha_summary_v2_*
entities: entities:
- sensor.jobs_tracker_summary - sensor.jobs_tracker_summary
- sensor.ulv316566_user_temp_offset
- sensor.ulv316566_raw_temperature
- sensor.ulv316566_probe_display_temp
- sensor.under_house_creality_k1c_eff9_max_nozzle_temperature
- sensor.under_house_creality_k1c_eff9_max_bed_temperature
+369
View File
@@ -0,0 +1,369 @@
#:########################################################################################:#
# Package: Security Notifications
# File: security_notifications.yaml
# Version: v1.0.0
# Date: 2026-07-25
#
# Purpose:
# Sends security alerts through the View Road announcement router when doors
# and access points open or close. Includes a startup gate to suppress false
# alerts after HA or Zigbee coordinator restarts, and a garage-door reminder
# loop for prolonged-open warnings.
#
# Channels used per sensor:
# Kitchen Top Cupboard → pushover_zorruno
# Key Cupboard → pushover_zorruno
# Loft Hatch → pushover_zorruno, sony_tv_lounge
# Underhouse Stealth Door → pushover_zorruno
# Garage Roller Door → pushover_zorruno, sony_tv_lounge
#
# Startup gate:
# Every automation checks:
# 1. HA core uptime > 120 s (blocks false alerts after HA restart)
# 2. Previous state != unavailable/unknown (blocks false alerts after
# Zigbee coordinator restart devices briefly go unavailable then
# re-report their last state)
#
# Garage reminder:
# When opened: immediate alert + 1-hour timer started
# Timer fires: door still open → reminder + restart (max 24 times)
# Door closed: timer cancelled, reminder count reset
#
# Dependencies:
# - packages/view_road_announcement_router.yaml (script.view_road_announcement)
#
# Version History:
# - v1.0.0 (2026-07-25): Created from Node-RED Security Alerts tab.
#:########################################################################################:#
###########################################################################################
# HELPERS
###########################################################################################
input_number:
garage_door_reminder_count:
name: Garage Door Reminder Count
icon: mdi:counter
min: 0
max: 24
step: 1
mode: box
timer:
garage_door_open_reminder:
name: Garage Door Open Reminder
duration: "01:00:00"
icon: mdi:timer-outline
###########################################################################################
# STARTUP GATE common condition template
###########################################################################################
#
# Every automation below includes these two conditions:
#
# 1. HA has been running > 120 s
# "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
#
# 2. Entity was not unavailable/unknown before this transition
# "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
#
# These are inlined so the package is self-contained and each automation
# remains easy to read, disable, or override individually.
#
###########################################################################################
###########################################################################################
# KITCHEN TOP CUPBOARD
###########################################################################################
automation:
- id: security_kitchen_cupboard_opened
alias: "Security Kitchen Top Cupboard Opened"
description: "Notify via Pushover when the kitchen top cupboard is opened."
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.kitchen_top_cupboard_x04rs_contact
from: "off"
to: "on"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno"
title: "Security Alert"
short_announcement: "Kitchen cupboard opened"
long_announcement: "The kitchen top cupboard has been opened."
- id: security_kitchen_cupboard_closed
alias: "Security Kitchen Top Cupboard Closed"
description: "Notify via Pushover when the kitchen top cupboard is closed."
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.kitchen_top_cupboard_x04rs_contact
from: "on"
to: "off"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno"
title: "Security Alert"
short_announcement: "Kitchen cupboard closed"
long_announcement: "The kitchen top cupboard is now closed."
###########################################################################################
# KEY CUPBOARD
###########################################################################################
- id: security_key_cupboard_opened
alias: "Security Key Cupboard Opened"
description: "Notify via Pushover when the key cupboard is opened."
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.key_cupboard_zrs06
from: "off"
to: "on"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno"
title: "Security Alert"
short_announcement: "Key cupboard opened"
long_announcement: "The key cupboard has been opened."
- id: security_key_cupboard_closed
alias: "Security Key Cupboard Closed"
description: "Notify via Pushover when the key cupboard is closed."
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.key_cupboard_zrs06
from: "on"
to: "off"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno"
title: "Security Alert"
short_announcement: "Key cupboard closed"
long_announcement: "The key cupboard is now closed."
###########################################################################################
# LOFT HATCH
###########################################################################################
- id: security_loft_hatch_opened
alias: "Security Loft Hatch Opened"
description: "Notify via Pushover and Sony TV when the loft hatch is opened."
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.upstairs_loft_hatch_x02rs_contact
from: "off"
to: "on"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno, sony_tv_lounge"
title: "Security Alert"
short_announcement: "Loft hatch opened"
long_announcement: "The upstairs loft hatch has been opened."
- id: security_loft_hatch_closed
alias: "Security Loft Hatch Closed"
description: "Notify via Pushover and Sony TV when the loft hatch is closed."
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.upstairs_loft_hatch_x02rs_contact
from: "on"
to: "off"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno, sony_tv_lounge"
title: "Security Alert"
short_announcement: "Loft hatch closed"
long_announcement: "The upstairs loft hatch is now closed."
###########################################################################################
# UNDERHOUSE STEALTH DOOR
###########################################################################################
- id: security_underhouse_stealth_door_opened
alias: "Security Underhouse Stealth Door Opened"
description: "Notify via Pushover when the underhouse stealth door is opened."
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.underhouse_stealth_door_x07rs_contact
from: "off"
to: "on"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno"
title: "Security Alert"
short_announcement: "Stealth door opened"
long_announcement: "The underhouse stealth door has been opened."
- id: security_underhouse_stealth_door_closed
alias: "Security Underhouse Stealth Door Closed"
description: "Notify via Pushover when the underhouse stealth door is closed."
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.underhouse_stealth_door_x07rs_contact
from: "on"
to: "off"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno"
title: "Security Alert"
short_announcement: "Stealth door closed"
long_announcement: "The underhouse stealth door is now closed."
###########################################################################################
# GARAGE ROLLER DOOR
###########################################################################################
- id: security_garage_door_opened
alias: "Security Garage Roller Door Opened"
description: >
Notify via Pushover and Sony TV when the garage roller door opens.
Also starts the 1-hour reminder timer so a follow-up alert is sent
if the door stays open.
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.garage_roller_door_x18rs_contact
from: "off"
to: "on"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: script.view_road_announcement
data:
channels: "pushover_zorruno, sony_tv_lounge"
title: "Security Alert"
short_announcement: "Garage door opened"
long_announcement: "The garage roller door has been opened."
- action: input_number.set_value
data:
entity_id: input_number.garage_door_reminder_count
value: 0
- action: timer.start
data:
entity_id: timer.garage_door_open_reminder
duration: "01:00:00"
- id: security_garage_door_closed
alias: "Security Garage Roller Door Closed"
description: >
Notify via Pushover and Sony TV when the garage roller door closes.
Cancels the reminder timer and resets the reminder counter.
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.garage_roller_door_x18rs_contact
from: "on"
to: "off"
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: template
value_template: "{{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown'] }}"
actions:
- action: timer.cancel
data:
entity_id: timer.garage_door_open_reminder
- action: input_number.set_value
data:
entity_id: input_number.garage_door_reminder_count
value: 0
- action: script.view_road_announcement
data:
channels: "pushover_zorruno, sony_tv_lounge"
title: "Security Alert"
short_announcement: "Garage door closed"
long_announcement: "The garage roller door is now closed."
- id: security_garage_door_reminder
alias: "Security Garage Roller Door Reminder"
description: >
Fires when the reminder timer finishes. If the door is still open and
the reminder has fired fewer than 24 times, send another reminder and
restart the timer.
mode: single
triggers:
- trigger: event
event_type: timer.finished
event_data:
entity_id: timer.garage_door_open_reminder
conditions:
- condition: template
value_template: "{{ states('sensor.home_assistant_core_uptime') | int(0) > 120 }}"
- condition: state
entity_id: binary_sensor.garage_roller_door_x18rs_contact
state: "on"
- condition: template
value_template: "{{ states('input_number.garage_door_reminder_count') | int(0) < 24 }}"
actions:
- action: input_number.increment
data:
entity_id: input_number.garage_door_reminder_count
- action: script.view_road_announcement
data:
channels: "pushover_zorruno, sony_tv_lounge"
title: "Security Alert"
short_announcement: "Garage door still open"
long_announcement: "A reminder, the garage roller door is still open."
- action: timer.start
data:
entity_id: timer.garage_door_open_reminder
duration: "01:00:00"
+12 -2
View File
@@ -1,7 +1,7 @@
#:########################################################################################:# #:########################################################################################:#
# Package: Away-Light Security Simulation # Package: Away-Light Security Simulation
# File: simulation_lights.yaml # File: simulation_lights.yaml
# Version: v1.0.0 # Version: v1.1.0
# Date: 2026-07-24 # Date: 2026-07-24
# #
# Purpose: # Purpose:
@@ -10,6 +10,9 @@
# automation selects a configured entity and operates it for a random period. # automation selects a configured entity and operates it for a random period.
# #
# Version History: # Version History:
# - v1.1.0 (2026-07-24): Replaced stale group.downstairs_flat_lights member with direct
# entity IDs so downstairs flat lights participate in away simulation.
#
# - v1.0.0 (2026-07-24): Consolidated the simulation groups, away automation, and timed helper # - v1.0.0 (2026-07-24): Consolidated the simulation groups, away automation, and timed helper
# script into one feature package. # script into one feature package.
# - Preserved the existing automation ID, group keys, and script key. # - Preserved the existing automation ID, group keys, and script key.
@@ -33,7 +36,14 @@ group:
simulation_lights_all: simulation_lights_all:
name: "Simulation Lights (All)" name: "Simulation Lights (All)"
entities: entities:
- group.downstairs_flat_lights - switch.esp_downstloungemain_relay_1_main_lights
- switch.esp_downstloungemain_relay_2_back_wall_lights
- switch.esp_downstmasterbedrmlights_relay_1_main_lights
- switch.esp_downstbedrm2lights_relay_1_main_lights
- switch.esp_downstkitchlights_relay_2_kitchen_light
- switch.esp_downstkitchlights_relay_1_dining_light
- switch.esp_downstbathswitch_relay_1_main_lights
- switch.esp_downstbathswitch_relay_2_cabinet_light
- switch.esp_centralstairs_top_relay_2_stair_footer_lights - switch.esp_centralstairs_top_relay_2_stair_footer_lights
- switch.esp_centralstairs_bottom_relay_1_main_stair_lights_lower - switch.esp_centralstairs_bottom_relay_1_main_stair_lights_lower
- switch.esp_entrancebathrmlights_relay_1_main_lights - switch.esp_entrancebathrmlights_relay_1_main_lights
+15 -3
View File
@@ -1,11 +1,13 @@
#:########################################################################################:# #:########################################################################################:#
# Package: Vehicle Announcements # Package: Vehicle Announcements
# File: vehicle_announcements.yaml # File: vehicle_announcements.yaml
# Version: v1.0.0 # Version: v1.1.0
# Date: 2026-07-23 # Date: 2026-07-26
# #
# Purpose: # Purpose:
# Sends vehicle arrival announcements through the View Road announcement router. # Sends vehicle arrival announcements through the View Road announcement router.
# Requires the vehicle to have been continuously away for 20 minutes before
# announcing, suppressing short Bluetooth range dropouts while parked at home.
#:########################################################################################:# #:########################################################################################:#
automation: automation:
@@ -13,13 +15,23 @@ automation:
alias: "BYD Atto 3 - Arrival Announcement" alias: "BYD Atto 3 - Arrival Announcement"
description: > description: >
Sends a Pushover notification to the Zorruno phone when the BYD Atto 3 Sends a Pushover notification to the Zorruno phone when the BYD Atto 3
Bermuda tracker arrives home. Bermuda tracker arrives home after at least 20 minutes away.
mode: single mode: single
variables:
minimum_away_minutes: 20
triggers: triggers:
- trigger: state - trigger: state
entity_id: device_tracker.byd_atto3_ibeacon_bur4c2a_bermuda_tracker entity_id: device_tracker.byd_atto3_ibeacon_bur4c2a_bermuda_tracker
from: "not_home" from: "not_home"
to: "home" to: "home"
conditions:
- condition: template
value_template: >-
{% set away_started = as_timestamp(trigger.from_state.last_changed, 0) %}
{% set arrived = as_timestamp(trigger.to_state.last_changed, 0) %}
{{ away_started > 0
and arrived > away_started
and (arrived - away_started) >= (minimum_away_minutes * 60) }}
actions: actions:
- action: script.view_road_announcement - action: script.view_road_announcement
data: data:
+39 -7
View File
@@ -1,6 +1,16 @@
################################################################################ ################################################################################
# PACKAGE: View Road Announcement Router # PACKAGE: View Road Announcement Router
################################################################################ ################################################################################
# 1.10: Date: 2026-07-24
# - Added 2s delay before TTS speak to separate the cast chime from
# the voice announcement.
#
# 1.9: Date: 2026-07-24
# - Added continue_on_error to all 7 channel blocks so a single channel
# failure does not block remaining channels.
# - Google Home voice channel now saves and restores the previous volume
# level after TTS completes.
#
# 1.8: Date: 2026-07-11 # 1.8: Date: 2026-07-11
# - Added MQTT View Rd Feed announcement channel. # - Added MQTT View Rd Feed announcement channel.
# - Added mqtt_feed script field. # - Added mqtt_feed script field.
@@ -483,7 +493,8 @@ script:
# CHANNEL: PUSHOVER ZORRUNO # CHANNEL: PUSHOVER ZORRUNO
########################################################################## ##########################################################################
- if: - continue_on_error: true
if:
- condition: template - condition: template
value_template: "{{ ',pushover_zorruno,' in ann_channels_normalised }}" value_template: "{{ ',pushover_zorruno,' in ann_channels_normalised }}"
- condition: state - condition: state
@@ -499,7 +510,8 @@ script:
# CHANNEL: PUSHOVER KIM # CHANNEL: PUSHOVER KIM
########################################################################## ##########################################################################
- if: - continue_on_error: true
if:
- condition: template - condition: template
value_template: "{{ ',pushover_kim,' in ann_channels_normalised }}" value_template: "{{ ',pushover_kim,' in ann_channels_normalised }}"
- condition: state - condition: state
@@ -515,7 +527,8 @@ script:
# CHANNEL: SONY TV LOUNGE # CHANNEL: SONY TV LOUNGE
########################################################################## ##########################################################################
- if: - continue_on_error: true
if:
- condition: template - condition: template
value_template: "{{ ',sony_tv_lounge,' in ann_channels_normalised }}" value_template: "{{ ',sony_tv_lounge,' in ann_channels_normalised }}"
- condition: state - condition: state
@@ -539,7 +552,8 @@ script:
# #
########################################################################## ##########################################################################
- if: - continue_on_error: true
if:
- condition: template - condition: template
value_template: >- value_template: >-
{{ {{
@@ -561,6 +575,9 @@ script:
- condition: template - condition: template
value_template: "{{ ann_voice_message | string | trim | length > 0 }}" value_template: "{{ ann_voice_message | string | trim | length > 0 }}"
then: then:
- variables:
previous_volume: >-
{{ state_attr(lounge_google_home_voice_media_player, 'volume_level') | float(-1) }}
- choose: - choose:
- conditions: - conditions:
- condition: template - condition: template
@@ -594,6 +611,9 @@ script:
- delay: - delay:
seconds: 1 seconds: 1
- delay:
seconds: 2
- action: tts.speak - action: tts.speak
target: target:
entity_id: "{{ lounge_google_home_voice_tts_entity }}" entity_id: "{{ lounge_google_home_voice_tts_entity }}"
@@ -606,6 +626,15 @@ script:
preferred_format: mp3 preferred_format: mp3
preferred_sample_rate: 44100 preferred_sample_rate: 44100
- if:
- condition: template
value_template: "{{ previous_volume >= 0 }}"
then:
- action: media_player.volume_set
data:
entity_id: "{{ lounge_google_home_voice_media_player }}"
volume_level: "{{ previous_volume }}"
########################################################################## ##########################################################################
# CHANNEL: LOUNGE TOUCHSCREEN VOICE # CHANNEL: LOUNGE TOUCHSCREEN VOICE
########################################################################## ##########################################################################
@@ -640,7 +669,8 @@ script:
# #
########################################################################## ##########################################################################
- if: - continue_on_error: true
if:
- condition: template - condition: template
value_template: "{{ ',mqtt_view_rd_feed,' in ann_channels_normalised }}" value_template: "{{ ',mqtt_view_rd_feed,' in ann_channels_normalised }}"
- condition: state - condition: state
@@ -679,7 +709,8 @@ script:
# #
########################################################################## ##########################################################################
- if: - continue_on_error: true
if:
- condition: template - condition: template
value_template: "{{ ',led_matrix_1,' in ann_channels_normalised }}" value_template: "{{ ',led_matrix_1,' in ann_channels_normalised }}"
- condition: state - condition: state
@@ -716,7 +747,8 @@ script:
# #
########################################################################## ##########################################################################
- if: - continue_on_error: true
if:
- condition: template - condition: template
value_template: "{{ ',led_matrix_2,' in ann_channels_normalised }}" value_template: "{{ ',led_matrix_2,' in ann_channels_normalised }}"
- condition: state - condition: state