various tidyups

This commit is contained in:
zorruno
2026-07-29 23:18:11 +12:00
parent adb533d6a3
commit dd13f52feb
22 changed files with 6837 additions and 4057 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
+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