Compare commits

..

12 Commits

Author SHA1 Message Date
zorruno 4e2107f7f7 various tidyups 2026-07-21 13:40:06 +12:00
ESPHome Device Builder 66bee0ccf7 Edit esp-masterbdrmsouth.yaml 2026-07-20 21:02:12 +12:00
ESPHome Device Builder 5b675e1d62 Edit esp-masterbdrmwest.yaml 2026-07-20 21:00:48 +12:00
ESPHome Device Builder a76dbb6b16 Edit esp-downstkitchlights.yaml 2026-07-20 20:47:14 +12:00
ESPHome Device Builder e20e36cdb5 Edit esp-downstloungeentry.yaml 2026-07-20 20:40:18 +12:00
ESPHome Device Builder a2fb86aa93 Edit esp-downstloungemain.yaml 2026-07-20 20:37:50 +12:00
ESPHome Device Builder c6e8d7721c Edit esp-officeusbhubpower.yaml 2026-07-20 20:32:29 +12:00
ESPHome Device Builder 3ff67b883b Edit esp-downstairskitchleds.yaml 2026-07-20 20:17:04 +12:00
ESPHome Device Builder 2e645793f0 Edit esp-bedrm1arlecbulb.yaml 2026-07-20 20:09:41 +12:00
ESPHome Device Builder 4ff90ea60a Edit esp-breakfastbarleds.yaml 2026-07-20 19:59:40 +12:00
ESPHome Device Builder dcd43a18c1 Edit esp-loungecabinetleds.yaml 2026-07-20 19:44:53 +12:00
ESPHome Device Builder 2b6b91f829 Edit esp-loungebookshelfleds.yaml 2026-07-20 19:27:48 +12:00
42 changed files with 3395 additions and 755 deletions
+1 -1
View File
@@ -1 +1 @@
{"pid": 71, "version": 1, "ha_version": "2026.7.2", "start_ts": 1784512870.0398877} {"pid": 71, "version": 1, "ha_version": "2026.7.2", "start_ts": 1784593872.104367}
+13
View File
@@ -39,6 +39,19 @@ You MUST follow these rules strictly:
- Make the change anyway - Make the change anyway
- Try to convince them otherwise - Try to convince them otherwise
## Project Context Protocol
- Treat every user request as related to a tracked project.
- Identify the project by ID or name before beginning work.
- If the project is unclear, ask the user which project applies.
- Read `PROJECTS.md` and the relevant project section before investigating or making recommendations.
- Keep project IDs stable.
- Record durable decisions, changes, verification results, blockers, and next steps under the relevant project.
- Follow the existing approval rules before writing context updates.
- Never mark a project `Complete` unless the user explicitly confirms completion.
- When a project appears complete, ask: "Should I close Pxxx?"
- Do not store secrets, credentials, or large transient logs in project context.
## Environment Context ## Environment Context
- You are running inside the OpenCode app - You are running inside the OpenCode app
+138
View File
@@ -0,0 +1,138 @@
# Project Tracker
Use this file as the source of truth for projects being worked on with OpenCode.
- Associate each user request with a project ID before beginning work.
- Ask the user which project applies when the request is ambiguous.
- Keep project IDs stable and use the relevant section to store durable context.
- Update context as work progresses, subject to the approval rules in `AGENTS.md`.
- Never mark a project complete unless the user explicitly confirms it is complete.
- Ask the user before closing a project that appears complete.
- Use these statuses: `Active`, `Paused`, and `Complete`.
| ID | Project | Status | Next Step | Last Updated |
| --- | --- | --- | --- | --- |
| P001 | Bedside panel alarm audio | Active | Deploy and verify alarm audio and volume behavior. | 2026-07-20 |
| P002 | reTerminal E1001 dashboard | Active | Test display refresh, wake buttons, MQTT control, and deep sleep. | 2026-07-20 |
| P003 | ESPHome MQTT topic normalization | Active | Deploy paired devices and verify retained synchronization and external clients. | 2026-07-20 |
| P004 | Appliance completion announcements | Active | Test an appliance cycle and resolve feed/timestamp inconsistencies. | 2026-07-20 |
| P005 | Jobs and Chore Tracker V2.3 | Active | Test completion boundaries and resolve stale or duplicated entities. | 2026-07-20 |
| P006 | Bedside rain forecast | Active | Verify forecast boundaries and API-failure handling. | 2026-07-20 |
| P007 | Bedtime stair shutdown | Active | Verify both stair relays during a bedtime run. | 2026-07-20 |
| P008 | Spook unused entity cleanup | Complete | None. | 2026-07-21 |
| P009 | Lounge front-door camera layout | Complete | None. | 2026-07-21 |
| P010 | Main-page Jobs timing gauges | Complete | None. | 2026-07-21 |
| P011 | Downstairs occupancy helper cleanup | Complete | None. | 2026-07-21 |
| P012 | EdgeRouter X SNMP monitoring | Active | Investigate the current EdgeOS failure and v3.0.x-compatible SNMP approach. | 2026-07-21 |
## P001: Bedside Panel Alarm Audio
- Objective: Provide reliable local alarm audio and user-adjustable volume on the bedside panel.
- Current context: ES8311 and I2S output, amplifier control, persistent volume, and Beep/Alarm/Stop controls were added and repeatedly tuned. Compilation, deployment, and hardware behavior have not been confirmed.
- Key files: `esphome/esp-bedside-panel.yaml`.
- Known issue: The file changelog records V1.47 while `project_version` still reports v1.46.
- Next step: Compile and deploy, then test startup noise, Beep/Alarm/Stop, volume endpoints, persistence, and amplifier shutdown.
- Activity: 2026-07-20 - Implemented and tuned the alarm-audio feature through V1.47.
## P002: reTerminal E1001 Dashboard
- Objective: Build a low-power e-paper dashboard for job and appliance status.
- Current context: Added ESP32-S3 hardware support, Jobs and Appliances pages, Home Assistant entity imports, icons, buttons, MQTT controls, change-only refresh, retained page hashes, wake-source handling, and deep sleep. Runtime behavior has not been confirmed.
- Key files: `esphome/esp-reterminal-e1001.yaml`.
- Next step: Compile and deploy, then test entity data, rendering, page buttons, timer and button wake, MQTT keep-awake control, fallback sleep, and battery usage.
- Activity: 2026-07-20 - Created the device configuration and developed it through v0.6.1.
## P003: ESPHome MQTT Topic Normalization
- Objective: Simplify MQTT command and status topics across related ESPHome devices while preserving synchronization.
- Current context: Flattened component-specific MQTT topics to logical device roots across eleven devices. Updated paired lounge and master-bedroom consumers and restored direct pantry-light control. Deployment and external-client compatibility have not been confirmed.
- Key files: Related device configurations under `esphome/`, including lounge, kitchen, office, bedroom, breakfast-bar, and master-bedroom devices.
- Next step: Compile and deploy paired devices together, verify root commands and retained state, audit external MQTT consumers, and remove stale retained messages from superseded topics when safe.
- Activity: 2026-07-20 - Applied the MQTT topic normalization across the related devices.
## P004: Appliance Completion Announcements
- Objective: Route appliance completion events to configured announcement channels and MQTT activity feeds.
- Current context: Added per-appliance announcement settings, payloads, channels, LED-matrix indicators, MQTT feed suffixes, suppression logging, retained attributes, and expanded washer, dryer, dishwasher, and EV-charger handling.
- Key files: `packages/Appliance_Monitoring/appliance_monitor_processor.yaml`, `packages/Appliance_Monitoring/appliances_status_monitoring.yaml`, `packages/view_road_announcement_router.yaml`, and `packages/appliance_status_mqttfeed.yaml`.
- Known issues: MQTT feed channels may not yet be enabled for each appliance, and timestamp sensors may receive time-only payloads.
- Next step: Resolve the feed and timestamp inconsistencies, then test a complete appliance cycle end to end.
- Activity: 2026-07-20 - Expanded appliance monitoring and completion-feed routing.
## P005: Jobs and Chore Tracker V2.3
- Objective: Maintain household jobs through a registry-driven tracker with discovery entities and completion windows.
- Current context: Centralized five jobs, added generic completion routing, morning and evening dog-feeding windows, MQTT Discovery entities, summary and count entities, manual buttons, missed-job handling, and completion-window expiry.
- Key files: `packages/Job_Chore_Tracking/jobs_tracker_jobs.yaml` and `packages/Job_Chore_Tracking/jobs_tracker_processor.yaml`.
- Known issue: Some count entities may be stale or have duplicated `jobs_tracker` naming.
- Next step: Test completion-window boundaries and clean up stale or double-prefixed entities after confirming which entities are current.
- Activity: 2026-07-20 - Implemented the V2.3 registry and processor changes.
## P006: Bedside Rain Forecast
- Objective: Supply the bedside panel with useful rain-chance forecasts for today and tomorrow.
- Current context: Added Open-Meteo REST sensors for today's remaining forecast period and tomorrow's daylight period using the Home zone coordinates.
- Key files: `packages/open_meteo_rain_chance.yaml` and `esphome/esp-bedside-panel.yaml`.
- Next step: Verify sunrise and sunset boundary behavior, stale-data handling, and API-failure recovery.
- Activity: 2026-07-20 - Added the Open-Meteo rain forecast package and bedside-panel inputs.
## P007: Bedtime Stair Shutdown
- Objective: Ensure the central stair lighting turns off as part of bedtime mode.
- Current context: Added the lower main stair lights and stair footer lights to the bedtime shutdown sequence with no delay.
- Key files: `packages/bedtime_mode_actions.yaml`.
- Next step: Run bedtime mode and verify both relays switch off as intended.
- Activity: 2026-07-20 - Added both central stair relays to bedtime shutdown.
## P008: Spook Unused Entity Cleanup
- Objective: Resolve Spook warnings caused by stale entity references.
- Current context: The Master Bedroom Echo Show Environment view now uses the live Bedroom 1 Environment (Z19TH) temperature and humidity entities, and the related Spook repair has cleared.
- Replacement entities: `sensor.bedroom_1_environment_z19th_temperature` and `sensor.bedroom_1_environment_z19th_humidity`.
- Verification: The stored card definitions reference the replacement entities, and Spook no longer reports the Master Bedroom Echo Show issue. Automated visual verification was unavailable because the screenshot tool is disabled.
- Next step: None.
- Activity: 2026-07-21 - Created the project and selected the live Bedroom 1 Environment (Z19TH) sensor pair.
- Activity: 2026-07-21 - Replaced both stale dashboard references and confirmed that the Spook repair cleared.
- Activity: 2026-07-21 - User confirmed completion.
## P009: Lounge Front-Door Camera Layout
- Objective: Display the Front Door Camera in landscape orientation on the Lounge dashboard.
- Current context: The Lounge Home view now displays the live `camera.camera2` card at a 4:3 landscape aspect ratio.
- Verification: The saved view retains all seven cards and the Front Door Camera live-view settings, and `camera.camera2` is streaming. Automated visual verification was unavailable because the screenshot tool is disabled.
- Next step: None.
- Activity: 2026-07-21 - Created the project and identified the Front Door Camera card on the Lounge Home view.
- Activity: 2026-07-21 - Changed the Front Door Camera card from 3:4 to 4:3 and verified the saved dashboard configuration.
- Activity: 2026-07-21 - User confirmed completion.
## P010: Main-Page Jobs Timing Gauges
- Objective: Make the Lounge Home dog-feeding and depooping gauges use timing from the Jobs routine.
- Current context: The gauges now use Jobs-derived template sensors. Dog feeding uses the latest morning/evening completion, and depooping uses the weekly job completion.
- Selected design: Keep two gauges. Dog feeding uses the latest morning/evening completion; depooping uses the weekly job completion.
- Key file: `packages/pet_feeding_and_jobs.yaml`.
- Verification: Home Assistant accepted the configuration, both template sensors loaded, the feeding gauge reports 17 hours, the depooping gauge reports 156 hours, and all other Home view cards were preserved. Automated visual verification was unavailable because the screenshot tool is disabled.
- Next step: None.
- Activity: 2026-07-21 - Created the project and selected the two-gauge Jobs-derived design.
- Activity: 2026-07-21 - Added the Jobs-derived sensors, reloaded templates, and updated both Lounge Home gauges.
- Activity: 2026-07-21 - User confirmed completion.
## P011: Downstairs Occupancy Helper Cleanup
- Objective: Eliminate the duplicate downstairs guest occupancy helper.
- Canonical helper: `input_boolean.downstairs_flat_occupied`, which is YAML-managed and used by the downstairs lockout behavior.
- Removed duplicate: `input_boolean.guest_area_occupied`, which was UI-managed and referenced only by the Test dashboard.
- Current context: All nine stored Test dashboard references now use the canonical helper, the duplicate helper has been deleted, and the Lounge row of eight downstairs-flat light icons now greys out and blocks taps while occupied.
- Verification: The duplicate returns entity not found, the canonical helper remains available with its automation and script relationships, no Test dashboard broken-reference repair was created, and the saved Lounge templates render both the enabled and occupied branches correctly. Automated visual verification was unavailable because the screenshot tool is disabled.
- Next step: None.
- Activity: 2026-07-21 - Created the project and completed the dependency audit.
- Activity: 2026-07-21 - Migrated the Test dashboard references and deleted the duplicate helper.
- Activity: 2026-07-21 - Added occupancy-driven greying and tap blocking to the Lounge downstairs-flat light row.
- Activity: 2026-07-21 - User verified the Lounge lockout and confirmed completion.
## P012: EdgeRouter X SNMP Monitoring
- Objective: Restore EdgeRouter X monitoring on firmware v3.0.x using a compatible SNMP-based approach.
- Current context: The existing EdgeRouter interface is not working after the router moved to firmware v3.0.x. Prior EdgeRouter/SNMP work was not recorded in project context.
- Next step: Inspect the current configuration, entities, errors, and documentation without changing runtime behavior.
- Activity: 2026-07-21 - Created the project and began the compatibility investigation.
+1386
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+39 -39
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm1arlecbulb.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm1arlecbulb.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v1.3 2026-07-20 Simplified local MQTT command and status topics to the device root
# v1.2 2026-02-25 Updated yaml to zorruno layout V1.1 # v1.2 2026-02-25 Updated yaml to zorruno layout V1.1
# v1.1 2026-02-21 Add "Jump Fade Up/Down" switch + configurable Jump Fade (%) # v1.1 2026-02-21 Add "Jump Fade Up/Down" switch + configurable Jump Fade (%)
# v1.0 2026-02-21 Initial version (ported from Athom bulb YAML to Arlec GLD120HA) # v1.0 2026-02-21 Initial version (ported from Athom bulb YAML to Arlec GLD120HA)
@@ -42,7 +43,6 @@
# - Accurate time is NOT needed (SNTP not needed). # - Accurate time is NOT needed (SNTP not needed).
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -56,7 +56,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Grid Connect GLD120HA RGBWW.Arlec" project_name: "Grid Connect GLD120HA RGBWW.Arlec"
project_version: "v1.2" project_version: "v1.3"
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
# Re-using your existing bulb flasher secrets (adjust if you prefer per-device secrets) # Re-using your existing bulb flasher secrets (adjust if you prefer per-device secrets)
@@ -156,32 +156,32 @@ esphome:
# Mode 0: Fade up to full (obeys fade settings; forces Warm endpoint) # Mode 0: Fade up to full (obeys fade settings; forces Warm endpoint)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 0;' lambda: "return id(restart_mode) == 0;"
then: then:
- lambda: 'id(ramp_switch_target_on) = true;' - lambda: "id(ramp_switch_target_on) = true;"
- script.execute: ramp_on_script - script.execute: ramp_on_script
# Mode 1: Restore Brightness (deferred; forces Warm endpoint) # Mode 1: Restore Brightness (deferred; forces Warm endpoint)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 1;' lambda: "return id(restart_mode) == 1;"
then: then:
- script.execute: deferred_restore_brightness - script.execute: deferred_restore_brightness
# Mode 2: Remain Off # Mode 2: Remain Off
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 2;' lambda: "return id(restart_mode) == 2;"
then: then:
- script.stop: ramp_on_script - script.stop: ramp_on_script
- script.stop: ramp_off_script - script.stop: ramp_off_script
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- light.turn_off: - light.turn_off:
id: bulb_light id: bulb_light
transition_length: 0s transition_length: 0s
# Boot complete: allow OFF handlers again # Boot complete: allow OFF handlers again
- lambda: 'id(booting) = false;' - lambda: "id(booting) = false;"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK # ESP PLATFORM AND FRAMEWORK
@@ -301,12 +301,12 @@ logger:
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
on_message: on_message:
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
then: then:
- switch.turn_on: bulb_ramp_switch - switch.turn_on: bulb_ramp_switch
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
then: then:
- switch.turn_off: bulb_ramp_switch - switch.turn_off: bulb_ramp_switch
@@ -536,7 +536,7 @@ light:
on_turn_on: on_turn_on:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
retain: true retain: true
- lambda: |- - lambda: |-
@@ -546,20 +546,20 @@ light:
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- script.execute: max_on_watchdog - script.execute: max_on_watchdog
on_turn_off: on_turn_off:
- if: - if:
condition: condition:
lambda: 'return !id(booting);' lambda: "return !id(booting);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
retain: true retain: true
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- lambda: |- - lambda: |-
id(last_brightness_pct) = 0.0f; id(last_brightness_pct) = 0.0f;
@@ -667,9 +667,9 @@ number:
set_action: set_action:
- if: - if:
condition: condition:
lambda: 'return x <= 0.0f;' lambda: "return x <= 0.0f;"
then: then:
- lambda: 'id(suppress_slider_sync) = true;' - lambda: "id(suppress_slider_sync) = true;"
- script.stop: ramp_on_script - script.stop: ramp_on_script
- script.stop: ramp_off_script - script.stop: ramp_off_script
- light.turn_off: - light.turn_off:
@@ -681,7 +681,7 @@ number:
id(last_brightness_pct) = 0.0f; id(last_brightness_pct) = 0.0f;
id(last_set_pos) = 0; id(last_set_pos) = 0;
- delay: 400ms - delay: 400ms
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
else: else:
- lambda: |- - lambda: |-
id(suppress_slider_sync) = true; id(suppress_slider_sync) = true;
@@ -713,7 +713,7 @@ number:
if (out_pct > maxp) out_pct = maxp; if (out_pct > maxp) out_pct = maxp;
id(last_brightness_pct) = out_pct; id(last_brightness_pct) = out_pct;
- delay: 400ms - delay: 400ms
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
- platform: template - platform: template
id: cfg_max_on_hours id: cfg_max_on_hours
@@ -736,12 +736,12 @@ number:
id(cfg_max_on_hours).publish_state((float) hrs); id(cfg_max_on_hours).publish_state((float) hrs);
- if: - if:
condition: condition:
lambda: 'return id(bulb_light).current_values.is_on();' lambda: "return id(bulb_light).current_values.is_on();"
then: then:
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- script.execute: max_on_watchdog - script.execute: max_on_watchdog
@@ -753,7 +753,7 @@ script:
- id: ramp_on_script - id: ramp_on_script
mode: restart mode: restart
then: then:
- lambda: 'id(is_ramping) = true;' - lambda: "id(is_ramping) = true;"
- script.stop: ramp_off_script - script.stop: ramp_off_script
- if: - if:
@@ -766,13 +766,13 @@ script:
- light.turn_on: - light.turn_on:
id: bulb_light id: bulb_light
color_temperature: "${bulb_warm_kelvin}" color_temperature: "${bulb_warm_kelvin}"
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: 80ms transition_length: 80ms
- light.turn_on: - light.turn_on:
id: bulb_light id: bulb_light
color_temperature: "${bulb_warm_kelvin}" color_temperature: "${bulb_warm_kelvin}"
brightness: !lambda 'return id(max_brightness_pct) / 100.0f;' brightness: !lambda "return id(max_brightness_pct) / 100.0f;"
transition_length: !lambda |- transition_length: !lambda |-
const auto &cv = id(bulb_light).current_values; const auto &cv = id(bulb_light).current_values;
const float floor = id(min_brightness_pct) / 100.0f; const float floor = id(min_brightness_pct) / 100.0f;
@@ -795,7 +795,7 @@ script:
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: |- - lambda: |-
id(is_ramping) = false; id(is_ramping) = false;
const auto &cv = id(bulb_light).current_values; const auto &cv = id(bulb_light).current_values;
@@ -807,7 +807,7 @@ script:
- id: ramp_to_target_script - id: ramp_to_target_script
mode: restart mode: restart
then: then:
- lambda: 'id(is_ramping) = true;' - lambda: "id(is_ramping) = true;"
- script.stop: ramp_off_script - script.stop: ramp_off_script
- if: - if:
@@ -820,7 +820,7 @@ script:
- light.turn_on: - light.turn_on:
id: bulb_light id: bulb_light
color_temperature: "${bulb_warm_kelvin}" color_temperature: "${bulb_warm_kelvin}"
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: 80ms transition_length: 80ms
- light.turn_on: - light.turn_on:
@@ -858,7 +858,7 @@ script:
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: |- - lambda: |-
id(is_ramping) = false; id(is_ramping) = false;
const auto &cv = id(bulb_light).current_values; const auto &cv = id(bulb_light).current_values;
@@ -878,7 +878,7 @@ script:
- light.turn_on: - light.turn_on:
id: bulb_light id: bulb_light
color_temperature: "${bulb_warm_kelvin}" color_temperature: "${bulb_warm_kelvin}"
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: !lambda |- transition_length: !lambda |-
const auto &cv = id(bulb_light).current_values; const auto &cv = id(bulb_light).current_values;
const float floor = id(min_brightness_pct) / 100.0f; const float floor = id(min_brightness_pct) / 100.0f;
@@ -895,7 +895,7 @@ script:
id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- light.turn_off: - light.turn_off:
id: bulb_light id: bulb_light
transition_length: 150ms transition_length: 150ms
@@ -913,12 +913,12 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- delay: !lambda 'return (uint32_t) (id(max_on_hours) * 3600000UL);' - delay: !lambda "return (uint32_t) (id(max_on_hours) * 3600000UL);"
- if: - if:
condition: condition:
lambda: 'return id(bulb_light).current_values.is_on();' lambda: "return id(bulb_light).current_values.is_on();"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = false; id(ramp_switch_target_on) = false;
@@ -942,17 +942,17 @@ script:
- if: - if:
condition: condition:
lambda: 'return id(restore_target_pct) > 0.5f;' lambda: "return id(restore_target_pct) > 0.5f;"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = true; id(ramp_switch_target_on) = true;
id(suppress_slider_sync) = true; id(suppress_slider_sync) = true;
- script.stop: ramp_off_script - script.stop: ramp_off_script
- script.execute: ramp_to_target_script - script.execute: ramp_to_target_script
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
else: else:
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- light.turn_off: - light.turn_off:
id: bulb_light id: bulb_light
transition_length: 0s transition_length: 0s
@@ -1013,7 +1013,7 @@ script:
- if: - if:
condition: condition:
lambda: 'return id(bulb_light).current_values.is_on();' lambda: "return id(bulb_light).current_values.is_on();"
then: then:
- light.turn_on: - light.turn_on:
id: bulb_light id: bulb_light
@@ -1043,4 +1043,4 @@ script:
else: else:
- light.turn_off: - light.turn_off:
id: bulb_light id: bulb_light
transition_length: 0s transition_length: 0s
+42 -42
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-breakfastbarleds.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-breakfastbarleds.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.1 2026-07-20 Simplified local MQTT command and status topics to the device root
# V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices # V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices
# V1.0 2025-08-17 First setup (and replacement of Tasmota) # V1.0 2025-08-17 First setup (and replacement of Tasmota)
#:########################################################################################:# #:########################################################################################:#
@@ -47,10 +48,10 @@
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
# Local MQTT light control: # Local MQTT light control:
# - ${mqtt_local_command_topic}/light/set -> ON,OFF # - ${mqtt_local_command_topic} -> ON,OFF
# #
# Local MQTT light status: # Local MQTT light status:
# - ${mqtt_local_status_topic}/light/state -> ON,OFF # - ${mqtt_local_status_topic} -> ON,OFF
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, but Network and MQTT ONLINE # a) Home Assistant OFFLINE, but Network and MQTT ONLINE
@@ -80,7 +81,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Manufacturer before the dot, device after the dot. project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Manufacturer before the dot, device after the dot.
project_version: "v2.0" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version project_version: "v2.1" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -130,8 +131,7 @@ packages:
local_current_ip_address: "${current_ip_address}" local_current_ip_address: "${current_ip_address}"
#### HOME ASSISTANT API (choose encryption or no encryption options) #### #### HOME ASSISTANT API (choose encryption or no encryption options) ####
common_api: !include common_api: !include #file: common/api_common.yaml
#file: common/api_common.yaml
file: common/api_common_noencryption.yaml file: common/api_common_noencryption.yaml
vars: vars:
local_api_key: "${api_key}" local_api_key: "${api_key}"
@@ -178,32 +178,32 @@ esphome:
# Mode 0: Fade up to full (obeys fade settings; no on/off flicker) # Mode 0: Fade up to full (obeys fade settings; no on/off flicker)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 0;' lambda: "return id(restart_mode) == 0;"
then: then:
- lambda: 'id(ramp_switch_target_on) = true;' - lambda: "id(ramp_switch_target_on) = true;"
- script.execute: ramp_on_script - script.execute: ramp_on_script
# Mode 1: Restore Brightness (deferred to avoid races) # Mode 1: Restore Brightness (deferred to avoid races)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 1;' lambda: "return id(restart_mode) == 1;"
then: then:
- script.execute: deferred_restore_brightness - script.execute: deferred_restore_brightness
# Mode 2: Remain Off (no blip; stays off) # Mode 2: Remain Off (no blip; stays off)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 2;' lambda: "return id(restart_mode) == 2;"
then: then:
- script.stop: ramp_on_script - script.stop: ramp_on_script
- script.stop: ramp_off_script - script.stop: ramp_off_script
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 0s transition_length: 0s
# Boot complete: allow OFF handlers again # Boot complete: allow OFF handlers again
- lambda: 'id(booting) = false;' - lambda: "id(booting) = false;"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK: # ESP PLATFORM AND FRAMEWORK:
@@ -345,13 +345,13 @@ status_led:
mqtt: mqtt:
on_message: on_message:
# Light control to ramp up # Light control to ramp up
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
then: then:
- switch.turn_on: mosfet_ramp_switch - switch.turn_on: mosfet_ramp_switch
# Light control to ramp down # Light control to ramp down
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
then: then:
- switch.turn_off: mosfet_ramp_switch - switch.turn_off: mosfet_ramp_switch
@@ -482,7 +482,7 @@ binary_sensor:
on_press: on_press:
- if: - if:
condition: condition:
lambda: 'return id(ramp_switch_target_on);' lambda: "return id(ramp_switch_target_on);"
then: then:
# Target is currently ON -> press should go OFF (start ramp-down) # Target is currently ON -> press should go OFF (start ramp-down)
- lambda: |- - lambda: |-
@@ -584,7 +584,7 @@ light:
on_turn_on: on_turn_on:
- output.turn_on: green_led_out - output.turn_on: green_led_out
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
retain: true retain: true
- lambda: |- - lambda: |-
@@ -595,7 +595,7 @@ light:
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- script.execute: max_on_watchdog - script.execute: max_on_watchdog
@@ -605,13 +605,13 @@ light:
- output.turn_off: green_led_out - output.turn_off: green_led_out
- if: - if:
condition: condition:
lambda: 'return !id(booting);' lambda: "return !id(booting);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
retain: true retain: true
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- lambda: |- - lambda: |-
id(last_brightness_pct) = 0.0f; id(last_brightness_pct) = 0.0f;
@@ -699,9 +699,9 @@ number:
set_action: set_action:
- if: - if:
condition: condition:
lambda: 'return x <= 0.0f;' lambda: "return x <= 0.0f;"
then: then:
- lambda: 'id(suppress_slider_sync) = true;' - lambda: "id(suppress_slider_sync) = true;"
- script.stop: ramp_on_script - script.stop: ramp_on_script
- script.stop: ramp_off_script - script.stop: ramp_off_script
- light.turn_off: - light.turn_off:
@@ -713,7 +713,7 @@ number:
id(last_brightness_pct) = 0.0f; id(last_brightness_pct) = 0.0f;
id(last_set_pos) = 0; id(last_set_pos) = 0;
- delay: 400ms - delay: 400ms
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
else: else:
- lambda: |- - lambda: |-
id(suppress_slider_sync) = true; id(suppress_slider_sync) = true;
@@ -744,7 +744,7 @@ number:
if (out_pct > maxp) out_pct = maxp; if (out_pct > maxp) out_pct = maxp;
id(last_brightness_pct) = out_pct; id(last_brightness_pct) = out_pct;
- delay: 400ms - delay: 400ms
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
- platform: template - platform: template
id: cfg_max_on_hours id: cfg_max_on_hours
@@ -767,12 +767,12 @@ number:
id(cfg_max_on_hours).publish_state((float) hrs); id(cfg_max_on_hours).publish_state((float) hrs);
- if: - if:
condition: condition:
lambda: 'return id(mosfet_leds).current_values.is_on();' lambda: "return id(mosfet_leds).current_values.is_on();"
then: then:
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- script.execute: max_on_watchdog - script.execute: max_on_watchdog
@@ -785,7 +785,7 @@ script:
- id: ramp_on_script - id: ramp_on_script
mode: restart mode: restart
then: then:
- lambda: 'id(is_ramping) = true;' - lambda: "id(is_ramping) = true;"
- script.stop: ramp_off_script - script.stop: ramp_off_script
# Ensure we start at at least the floor without a visible "pop". # Ensure we start at at least the floor without a visible "pop".
@@ -798,13 +798,13 @@ script:
then: then:
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: 80ms transition_length: 80ms
# Ramp from current (>= floor) to cap over a fraction of ramp_up_ms. # Ramp from current (>= floor) to cap over a fraction of ramp_up_ms.
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(max_brightness_pct) / 100.0f;' brightness: !lambda "return id(max_brightness_pct) / 100.0f;"
transition_length: !lambda |- transition_length: !lambda |-
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
const float floor = id(min_brightness_pct) / 100.0f; const float floor = id(min_brightness_pct) / 100.0f;
@@ -825,7 +825,7 @@ script:
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: |- - lambda: |-
id(is_ramping) = false; id(is_ramping) = false;
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
@@ -838,7 +838,7 @@ script:
- id: ramp_to_target_script - id: ramp_to_target_script
mode: restart mode: restart
then: then:
- lambda: 'id(is_ramping) = true;' - lambda: "id(is_ramping) = true;"
- script.stop: ramp_off_script - script.stop: ramp_off_script
# Ensure we start at the floor cleanly. # Ensure we start at the floor cleanly.
@@ -851,7 +851,7 @@ script:
then: then:
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: 80ms transition_length: 80ms
# Ramp from current (>= floor) to restore_target_pct over a fraction of ramp_up_ms. # Ramp from current (>= floor) to restore_target_pct over a fraction of ramp_up_ms.
@@ -884,7 +884,7 @@ script:
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: |- - lambda: |-
id(is_ramping) = false; id(is_ramping) = false;
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
@@ -904,7 +904,7 @@ script:
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: !lambda |- transition_length: !lambda |-
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
const float floor = id(min_brightness_pct) / 100.0f; const float floor = id(min_brightness_pct) / 100.0f;
@@ -918,7 +918,7 @@ script:
id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 150ms transition_length: 150ms
@@ -935,12 +935,12 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- delay: !lambda 'return (uint32_t) (id(max_on_hours) * 3600000UL);' - delay: !lambda "return (uint32_t) (id(max_on_hours) * 3600000UL);"
- if: - if:
condition: condition:
lambda: 'return id(mosfet_leds).current_values.is_on();' lambda: "return id(mosfet_leds).current_values.is_on();"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = false; id(ramp_switch_target_on) = false;
@@ -967,18 +967,18 @@ script:
- if: - if:
condition: condition:
lambda: 'return id(restore_target_pct) > 0.5f;' lambda: "return id(restore_target_pct) > 0.5f;"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = true; id(ramp_switch_target_on) = true;
id(suppress_slider_sync) = true; id(suppress_slider_sync) = true;
- script.stop: ramp_off_script - script.stop: ramp_off_script
- script.execute: ramp_to_target_script - script.execute: ramp_to_target_script
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
else: else:
# Exact last was 0 -> remain OFF # Exact last was 0 -> remain OFF
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 0s transition_length: 0s
+42 -43
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstairskitchleds.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstairskitchleds.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v2.2 2026-07-20 Simplified local MQTT command and status topics to the device root
# v2.1 2026-02-25 Updated yaml to zorruno layout V1.1 # v2.1 2026-02-25 Updated yaml to zorruno layout V1.1
# v2.0 2025-09-15 A bunch of fixes. # v2.0 2025-09-15 A bunch of fixes.
# v1.5 2025-09-04 Adopt ramped "Restore Brightness" (0->last non-zero), avoid boot blip (ALWAYS_OFF + high-priority on_boot), # v1.5 2025-09-04 Adopt ramped "Restore Brightness" (0->last non-zero), avoid boot blip (ALWAYS_OFF + high-priority on_boot),
@@ -60,12 +61,12 @@
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
# - Command topic: # - Command topic:
# ${mqtt_local_command_topic}/light/set # ${mqtt_local_command_topic}
# Payload "${mqtt_local_device_command_ON}" -> fade up (switch ON) # Payload "${mqtt_local_device_command_ON}" -> fade up (switch ON)
# Payload "${mqtt_local_device_command_OFF}" -> fade down (switch OFF) # Payload "${mqtt_local_device_command_OFF}" -> fade down (switch OFF)
# #
# - Status topic: # - Status topic:
# ${mqtt_local_status_topic}/light/state # ${mqtt_local_status_topic}
# Payload "${mqtt_local_device_command_ON}" / "${mqtt_local_device_command_OFF}" # Payload "${mqtt_local_device_command_ON}" / "${mqtt_local_device_command_OFF}"
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
@@ -81,7 +82,6 @@
# - Accurate time is NOT needed (SNTP not needed) # - Accurate time is NOT needed (SNTP not needed)
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -95,7 +95,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot. project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot.
project_version: "v2.1" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version project_version: "v2.2" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -145,8 +145,7 @@ packages:
local_current_ip_address: "${current_ip_address}" local_current_ip_address: "${current_ip_address}"
#### HOME ASSISTANT API (choose encryption or no encryption options) #### #### HOME ASSISTANT API (choose encryption or no encryption options) ####
common_api: !include common_api: !include #file: common/api_common.yaml
#file: common/api_common.yaml
file: common/api_common_noencryption.yaml file: common/api_common_noencryption.yaml
vars: vars:
local_api_key: "${api_key}" local_api_key: "${api_key}"
@@ -193,32 +192,32 @@ esphome:
# Mode 0: Fade up to full (obeys fade settings; no on/off flicker) # Mode 0: Fade up to full (obeys fade settings; no on/off flicker)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 0;' lambda: "return id(restart_mode) == 0;"
then: then:
- lambda: 'id(ramp_switch_target_on) = true;' - lambda: "id(ramp_switch_target_on) = true;"
- script.execute: ramp_on_script - script.execute: ramp_on_script
# Mode 1: Restore Brightness (deferred to avoid races) # Mode 1: Restore Brightness (deferred to avoid races)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 1;' lambda: "return id(restart_mode) == 1;"
then: then:
- script.execute: deferred_restore_brightness - script.execute: deferred_restore_brightness
# Mode 2: Remain Off (no blip; stays off) # Mode 2: Remain Off (no blip; stays off)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 2;' lambda: "return id(restart_mode) == 2;"
then: then:
- script.stop: ramp_on_script - script.stop: ramp_on_script
- script.stop: ramp_off_script - script.stop: ramp_off_script
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 0s transition_length: 0s
# Boot complete: allow OFF handlers again # Boot complete: allow OFF handlers again
- lambda: 'id(booting) = false;' - lambda: "id(booting) = false;"
#:########################################################################################:# #:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK # ESP PLATFORM AND FRAMEWORK
@@ -358,13 +357,13 @@ status_led:
mqtt: mqtt:
on_message: on_message:
# Light control to ramp up # Light control to ramp up
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
then: then:
- switch.turn_on: mosfet_ramp_switch - switch.turn_on: mosfet_ramp_switch
# Light control to ramp down # Light control to ramp down
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
then: then:
- switch.turn_off: mosfet_ramp_switch - switch.turn_off: mosfet_ramp_switch
@@ -492,7 +491,7 @@ binary_sensor:
on_press: on_press:
- if: - if:
condition: condition:
lambda: 'return id(ramp_switch_target_on);' lambda: "return id(ramp_switch_target_on);"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = false; id(ramp_switch_target_on) = false;
@@ -589,7 +588,7 @@ light:
on_turn_on: on_turn_on:
- output.turn_on: green_led_out - output.turn_on: green_led_out
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
retain: true retain: true
- lambda: |- - lambda: |-
@@ -599,7 +598,7 @@ light:
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- script.execute: max_on_watchdog - script.execute: max_on_watchdog
@@ -607,13 +606,13 @@ light:
- output.turn_off: green_led_out - output.turn_off: green_led_out
- if: - if:
condition: condition:
lambda: 'return !id(booting);' lambda: "return !id(booting);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
retain: true retain: true
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- lambda: |- - lambda: |-
id(last_brightness_pct) = 0.0f; id(last_brightness_pct) = 0.0f;
@@ -700,9 +699,9 @@ number:
set_action: set_action:
- if: - if:
condition: condition:
lambda: 'return x <= 0.0f;' lambda: "return x <= 0.0f;"
then: then:
- lambda: 'id(suppress_slider_sync) = true;' - lambda: "id(suppress_slider_sync) = true;"
- script.stop: ramp_on_script - script.stop: ramp_on_script
- script.stop: ramp_off_script - script.stop: ramp_off_script
- light.turn_off: - light.turn_off:
@@ -714,7 +713,7 @@ number:
id(last_brightness_pct) = 0.0f; id(last_brightness_pct) = 0.0f;
id(last_set_pos) = 0; id(last_set_pos) = 0;
- delay: 400ms - delay: 400ms
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
else: else:
- lambda: |- - lambda: |-
id(suppress_slider_sync) = true; id(suppress_slider_sync) = true;
@@ -745,7 +744,7 @@ number:
if (out_pct > maxp) out_pct = maxp; if (out_pct > maxp) out_pct = maxp;
id(last_brightness_pct) = out_pct; id(last_brightness_pct) = out_pct;
- delay: 400ms - delay: 400ms
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
- platform: template - platform: template
id: cfg_max_on_hours id: cfg_max_on_hours
@@ -768,12 +767,12 @@ number:
id(cfg_max_on_hours).publish_state((float) hrs); id(cfg_max_on_hours).publish_state((float) hrs);
- if: - if:
condition: condition:
lambda: 'return id(mosfet_leds).current_values.is_on();' lambda: "return id(mosfet_leds).current_values.is_on();"
then: then:
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- script.execute: max_on_watchdog - script.execute: max_on_watchdog
@@ -785,7 +784,7 @@ script:
- id: ramp_on_script - id: ramp_on_script
mode: restart mode: restart
then: then:
- lambda: 'id(is_ramping) = true;' - lambda: "id(is_ramping) = true;"
- script.stop: ramp_off_script - script.stop: ramp_off_script
- if: - if:
condition: condition:
@@ -796,11 +795,11 @@ script:
then: then:
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: 80ms transition_length: 80ms
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(max_brightness_pct) / 100.0f;' brightness: !lambda "return id(max_brightness_pct) / 100.0f;"
transition_length: !lambda |- transition_length: !lambda |-
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
const float floor = id(min_brightness_pct) / 100.0f; const float floor = id(min_brightness_pct) / 100.0f;
@@ -820,7 +819,7 @@ script:
if (frac > 1.0f) frac = 1.0f; if (frac > 1.0f) frac = 1.0f;
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: |- - lambda: |-
id(is_ramping) = false; id(is_ramping) = false;
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
@@ -832,7 +831,7 @@ script:
- id: ramp_to_target_script - id: ramp_to_target_script
mode: restart mode: restart
then: then:
- lambda: 'id(is_ramping) = true;' - lambda: "id(is_ramping) = true;"
- script.stop: ramp_off_script - script.stop: ramp_off_script
- if: - if:
condition: condition:
@@ -843,7 +842,7 @@ script:
then: then:
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: 80ms transition_length: 80ms
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
@@ -873,7 +872,7 @@ script:
if (frac > 1.0f) frac = 1.0f; if (frac > 1.0f) frac = 1.0f;
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: |- - lambda: |-
id(is_ramping) = false; id(is_ramping) = false;
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
@@ -891,7 +890,7 @@ script:
- script.stop: ramp_on_script - script.stop: ramp_on_script
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: !lambda |- transition_length: !lambda |-
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
const float floor = id(min_brightness_pct) / 100.0f; const float floor = id(min_brightness_pct) / 100.0f;
@@ -904,7 +903,7 @@ script:
if (frac > 1.0f) frac = 1.0f; if (frac > 1.0f) frac = 1.0f;
id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 150ms transition_length: 150ms
@@ -921,12 +920,12 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- delay: !lambda 'return (uint32_t) (id(max_on_hours) * 3600000UL);' - delay: !lambda "return (uint32_t) (id(max_on_hours) * 3600000UL);"
- if: - if:
condition: condition:
lambda: 'return id(mosfet_leds).current_values.is_on();' lambda: "return id(mosfet_leds).current_values.is_on();"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = false; id(ramp_switch_target_on) = false;
@@ -950,17 +949,17 @@ script:
- if: - if:
condition: condition:
lambda: 'return id(restore_target_pct) > 0.5f;' lambda: "return id(restore_target_pct) > 0.5f;"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = true; id(ramp_switch_target_on) = true;
id(suppress_slider_sync) = true; id(suppress_slider_sync) = true;
- script.stop: ramp_off_script - script.stop: ramp_off_script
- script.execute: ramp_to_target_script - script.execute: ramp_to_target_script
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
else: else:
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 0s transition_length: 0s
+25 -3
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstkitchlights.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstkitchlights.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v2.2 2026-07-20 Restored direct MQTT control of pantry LEDs using the flattened topic
# v2.1 2026-02-25 Updated yaml to zorruno layout V1.1 # v2.1 2026-02-25 Updated yaml to zorruno layout V1.1
# v2.0 2025-06-05 YAML tidyups # v2.0 2025-06-05 YAML tidyups
# v1.0 2025-03-28 Initial Version # v1.0 2025-03-28 Initial Version
@@ -21,6 +22,13 @@
# - Relay 1: Dining Light # - Relay 1: Dining Light
# - Relay 2: Kitchen Light # - Relay 2: Kitchen Light
# - Relay 3: Extract Fan (virtual only, no power connected to 3rd relay) # - Relay 3: Extract Fan (virtual only, no power connected to 3rd relay)
# - Relay 2 publishes ON/OFF commands directly to the downstairs kitchen pantry LEDs.
#:########################################################################################:#
# MQTT COMMANDS:
# - Remote command topic:
# ${mqtt_remote_device_command_topic}
# Payload "${mqtt_remote_device_command_on}" -> pantry LEDs ON
# Payload "${mqtt_remote_device_command_off}" -> pantry LEDs OFF
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, but Network and MQTT ONLINE # a) Home Assistant OFFLINE, but Network and MQTT ONLINE
@@ -36,7 +44,6 @@
# - Accurate time is NOT needed (SNTP not needed) # - Accurate time is NOT needed (SNTP not needed)
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -50,7 +57,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v2.1" project_version: "v2.2"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -61,6 +68,13 @@ substitutions:
# Don't forget to switch it back when changed. # Don't forget to switch it back when changed.
current_ip_address: ${static_ip_address} current_ip_address: ${static_ip_address}
# MQTT REMOTE Controls
mqtt_command_main_topic: !secret mqtt_command_main_topic
mqtt_remote_device_name: "downstairskitchen-pantryleds"
mqtt_remote_device_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}"
mqtt_remote_device_command_on: "ON"
mqtt_remote_device_command_off: "OFF"
# Device Settings # Device Settings
log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
update_interval: "60s" # update time for general sensors etc update_interval: "60s" # update time for general sensors etc
@@ -195,8 +209,16 @@ switch:
name: "Relay 2: ${switch_2_name}" name: "Relay 2: ${switch_2_name}"
pin: GPIO12 pin: GPIO12
id: Relay_2 id: Relay_2
on_turn_on:
- mqtt.publish:
topic: "${mqtt_remote_device_command_topic}"
payload: "${mqtt_remote_device_command_on}"
on_turn_off:
- mqtt.publish:
topic: "${mqtt_remote_device_command_topic}"
payload: "${mqtt_remote_device_command_off}"
- platform: gpio - platform: gpio
name: "Relay 3: ${switch_3_name}" name: "Relay 3: ${switch_3_name}"
pin: GPIO14 pin: GPIO14
id: Relay_3 id: Relay_3
+7 -7
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungeentry.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungeentry.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v3.8 2026-07-20 Updated remote MQTT topics for the flattened downstairs lounge main lights topic
# v3.7 2026-02-25 Updated yaml to zorruno layout V1.1 # v3.7 2026-02-25 Updated yaml to zorruno layout V1.1
# v3.6 2025-07-24 YAML tidyups # v3.6 2025-07-24 YAML tidyups
#:########################################################################################:# #:########################################################################################:#
@@ -45,7 +46,6 @@
# - Accurate time is NOT needed (SNTP not needed) # - Accurate time is NOT needed (SNTP not needed)
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -59,7 +59,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Single" project_name: "Zemismart Technologies.KS-811 Single"
project_version: "v3.7" project_version: "v3.8"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -78,8 +78,8 @@ substitutions:
# MQTT REMOTE Controls # MQTT REMOTE Controls
mqtt_remote_device_name: "downst-lounge-main-lights" mqtt_remote_device_name: "downst-lounge-main-lights"
mqtt_remote_device_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}/light1/set" mqtt_remote_device_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}"
mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}/light1/state" mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}"
mqtt_remote_device_command_on: "On" mqtt_remote_device_command_on: "On"
mqtt_remote_device_command_off: "Off" mqtt_remote_device_command_off: "Off"
@@ -170,7 +170,7 @@ mqtt:
- delay: 50ms - delay: 50ms
- if: - if:
condition: condition:
lambda: 'return !id(Relay_1).state;' lambda: "return !id(Relay_1).state;"
then: then:
- switch.turn_on: Relay_1 - switch.turn_on: Relay_1
@@ -180,7 +180,7 @@ mqtt:
- delay: 50ms - delay: 50ms
- if: - if:
condition: condition:
lambda: 'return id(Relay_1).state;' lambda: "return id(Relay_1).state;"
then: then:
- switch.turn_off: Relay_1 - switch.turn_off: Relay_1
@@ -224,4 +224,4 @@ switch:
- platform: gpio - platform: gpio
name: "Relay 1: ${switch_1_name}" name: "Relay 1: ${switch_1_name}"
pin: GPIO12 pin: GPIO12
id: Relay_1 id: Relay_1
+9 -9
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungemain.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungemain.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v3.7 2026-07-20 Simplified local MQTT command and status topics to the device root
# v3.6 2026-02-25 Updated yaml to zorruno layout V1.1 # v3.6 2026-02-25 Updated yaml to zorruno layout V1.1
# v3.5 2025-07-28 YAML tidyups # v3.5 2025-07-28 YAML tidyups
#:########################################################################################:# #:########################################################################################:#
@@ -23,12 +24,12 @@
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
# - Local command topic (Main Lights): # - Local command topic (Main Lights):
# ${mqtt_local_command_topic}/light1/set # ${mqtt_local_command_topic}
# Payload "On" -> Relay 1 ON # Payload "On" -> Relay 1 ON
# Payload "Off" -> Relay 1 OFF # Payload "Off" -> Relay 1 OFF
# #
# - Local status topic (Main Lights): # - Local status topic (Main Lights):
# ${mqtt_local_status_topic}/light1/state # ${mqtt_local_status_topic}
# Payload "On" / "Off" published when Relay 1 changes state # Payload "On" / "Off" published when Relay 1 changes state
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
@@ -45,7 +46,6 @@
# - Accurate time is NOT needed (SNTP not needed). # - Accurate time is NOT needed (SNTP not needed).
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -59,7 +59,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v3.6" project_version: "v3.7"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -156,11 +156,11 @@ logger:
mqtt: mqtt:
on_message: on_message:
# Main Lights control (Relay 1) # Main Lights control (Relay 1)
- topic: "${mqtt_local_command_topic}/light1/set" - topic: "${mqtt_local_command_topic}"
payload: "On" payload: "On"
then: then:
- switch.turn_on: relay_1 - switch.turn_on: relay_1
- topic: "${mqtt_local_command_topic}/light1/set" - topic: "${mqtt_local_command_topic}"
payload: "Off" payload: "Off"
then: then:
- switch.turn_off: relay_1 - switch.turn_off: relay_1
@@ -222,11 +222,11 @@ switch:
id: relay_1 id: relay_1
on_turn_on: on_turn_on:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light1/state" topic: "${mqtt_local_status_topic}"
payload: "On" payload: "On"
on_turn_off: on_turn_off:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light1/state" topic: "${mqtt_local_status_topic}"
payload: "Off" payload: "Off"
# Relay 2 (GPIO12) # Relay 2 (GPIO12)
@@ -239,4 +239,4 @@ switch:
- platform: gpio - platform: gpio
name: "Relay 3: ${switch_3_name}" name: "Relay 3: ${switch_3_name}"
pin: GPIO14 pin: GPIO14
id: relay_3 id: relay_3
+31 -31
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungebookshelfleds.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungebookshelfleds.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.2 2026-07-20 Simplified local MQTT command and status topics to the device root
# V2.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.1 2026-03-11 Updated yaml to zorruno layout V1.1
# V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices # V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices
# V1.0 2025-08-17 First setup (and replacement of Tasmota) # V1.0 2025-08-17 First setup (and replacement of Tasmota)
@@ -48,10 +49,10 @@
# - Maximum ON time before automatic fade-down (1-48 h, 0 = no limit) # - Maximum ON time before automatic fade-down (1-48 h, 0 = no limit)
# #
# MQTT COMMANDS: # MQTT COMMANDS:
# - ${mqtt_local_command_topic}/light/set = ON # - ${mqtt_local_command_topic} = ON
# - ${mqtt_local_command_topic}/light/set = OFF # - ${mqtt_local_command_topic} = OFF
# - State publishes to: # - State publishes to:
# - ${mqtt_local_status_topic}/light/state # - ${mqtt_local_status_topic}
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant offline (network and MQTT online): # a) Home Assistant offline (network and MQTT online):
@@ -84,7 +85,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Project details. Manufacturer before the dot, device after the dot. project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Project details. Manufacturer before the dot, device after the dot.
project_version: "v2.1" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version project_version: "v2.2" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
api_key: !secret esp-api_key # If using HA API api_key: !secret esp-api_key # If using HA API
@@ -102,19 +103,19 @@ substitutions:
mqtt_local_device_command_OFF: "OFF" mqtt_local_device_command_OFF: "OFF"
# Device Specific Settings # Device Specific Settings
log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE
update_interval: "20s" # Update time for general sensors, etc. update_interval: "20s" # Update time for general sensors, etc.
led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM
minimum_led_output: "1" # % If at this value or below, we will switch it completely off minimum_led_output: "1" # % If at this value or below, we will switch it completely off
maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics
max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off
pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts
# Device Specific GPIO (so we can easily update for other devices) # Device Specific GPIO (so we can easily update for other devices)
device_status_led: GPIO2 device_status_led: GPIO2
device_mosfet_out: GPIO12 device_mosfet_out: GPIO12
device_usr_button: GPIO4 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml device_usr_button: GPIO4 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml
device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: # PACKAGES:
@@ -132,8 +133,7 @@ packages:
local_ota_pass: "${ota_pass}" local_ota_pass: "${ota_pass}"
#### HOME ASSISTANT API (choose encryption or no encryption options) #### #### HOME ASSISTANT API (choose encryption or no encryption options) ####
common_api: !include common_api: !include #file: common/api_common.yaml
#file: common/api_common.yaml
file: common/api_common_noencryption.yaml file: common/api_common_noencryption.yaml
vars: vars:
local_api_key: "${api_key}" local_api_key: "${api_key}"
@@ -245,12 +245,12 @@ globals:
- id: min_brightness_pct - id: min_brightness_pct
type: int type: int
restore_value: true restore_value: true
initial_value: "${minimum_led_output}" # start/finish at X% initial_value: "${minimum_led_output}" # start/finish at X%
# Maximum Brightness % for LEDs (should never go beyond this) # Maximum Brightness % for LEDs (should never go beyond this)
- id: max_brightness_pct - id: max_brightness_pct
type: int type: int
restore_value: false restore_value: false
initial_value: "${maximum_led_output}" # hard cap; never exceed this initial_value: "${maximum_led_output}" # hard cap; never exceed this
# The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever # The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever
- id: max_on_hours - id: max_on_hours
type: int type: int
@@ -260,23 +260,23 @@ globals:
- id: led_gamma_f - id: led_gamma_f
type: float type: float
restore_value: false restore_value: false
initial_value: ${led_gamma} # numeric at compile time initial_value: ${led_gamma} # numeric at compile time
# Default Fading Up Time (Selectable and will be retained) # Default Fading Up Time (Selectable and will be retained)
- id: ramp_up_ms # fade-in when turned ON - id: ramp_up_ms # fade-in when turned ON
type: int type: int
restore_value: true restore_value: true
initial_value: "5000" # 5 s initial_value: "5000" # 5 s
# Default Fading Down Time (Selectable and will be retained) # Default Fading Down Time (Selectable and will be retained)
- id: ramp_down_ms # fade-out when turned OFF - id: ramp_down_ms # fade-out when turned OFF
type: int type: int
restore_value: true restore_value: true
initial_value: "10000" # 10 s initial_value: "10000" # 10 s
# Action on Restart. (0=Fade full, 1=Restore brightness, 2=Remain off) # Action on Restart. (0=Fade full, 1=Restore brightness, 2=Remain off)
- id: restart_mode - id: restart_mode
type: int type: int
restore_value: true restore_value: true
initial_value: "0" # default = Fade Up to Full (so can be deployed with no other setup) initial_value: "0" # default = Fade Up to Full (so can be deployed with no other setup)
# Determine last fade direction. # Determine last fade direction.
# true when you asked the light to end up ON (Ramp Up) # true when you asked the light to end up ON (Ramp Up)
@@ -332,7 +332,7 @@ globals:
# Logs all log messages through the serial port and through MQTT topics. # Logs all log messages through the serial port and through MQTT topics.
#:########################################################################################:# #:########################################################################################:#
logger: logger:
level: "${log_level}" # INFO Level suggested, or DEBUG for testing level: "${log_level}" # INFO Level suggested, or DEBUG for testing
baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control)
#:########################################################################################:# #:########################################################################################:#
@@ -351,12 +351,12 @@ status_led:
mqtt: mqtt:
on_message: on_message:
# Light control to ramp up # Light control to ramp up
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
then: then:
- switch.turn_on: mosfet_ramp_switch - switch.turn_on: mosfet_ramp_switch
# Light control to ramp down # Light control to ramp down
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
then: then:
- switch.turn_off: mosfet_ramp_switch - switch.turn_off: mosfet_ramp_switch
@@ -570,7 +570,7 @@ output:
frequency: ${pwm_frequency} frequency: ${pwm_frequency}
- platform: gpio - platform: gpio
id: green_led_out # Green LED id: green_led_out # Green LED
pin: pin:
number: ${device_fading_led} number: ${device_fading_led}
inverted: false inverted: false
@@ -593,7 +593,7 @@ light:
on_turn_on: on_turn_on:
- output.turn_on: green_led_out - output.turn_on: green_led_out
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
retain: true retain: true
- lambda: |- - lambda: |-
@@ -617,7 +617,7 @@ light:
lambda: "return !id(booting);" lambda: "return !id(booting);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
retain: true retain: true
- lambda: "id(ramp_switch_target_on) = false;" - lambda: "id(ramp_switch_target_on) = false;"
@@ -957,7 +957,7 @@ script:
- id: deferred_restore_brightness - id: deferred_restore_brightness
mode: restart mode: restart
then: then:
- delay: 5s # let preferences/globals load and light settle - delay: 5s # let preferences/globals load and light settle
- lambda: |- - lambda: |-
// Use ONLY the exact last saved brightness. // Use ONLY the exact last saved brightness.
float target = id(last_brightness_pct); float target = id(last_brightness_pct);
@@ -987,4 +987,4 @@ script:
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 0s transition_length: 0s
# (Removed: output.turn_off: green_led_out) # make sure LED is off if no ramp # (Removed: output.turn_off: green_led_out) # make sure LED is off if no ramp
+43 -43
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungecabinetleds.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungecabinetleds.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V2.2 2026-07-20 Simplified local MQTT command and status topics to the device root
# V2.1 2026-03-11 Updated yaml to zorruno layout V1.1 # V2.1 2026-03-11 Updated yaml to zorruno layout V1.1
# V2.0 2025-09-15 A bunch of fixes, this is now the master for other similar mosfet controllers of mine # V2.0 2025-09-15 A bunch of fixes, this is now the master for other similar mosfet controllers of mine
# V1.5 2025-09-11 First setup (copied from another template) # V1.5 2025-09-11 First setup (copied from another template)
@@ -50,10 +51,10 @@
# - Maximum ON time before automatic fade-down (1-48 h, 0 = no limit) # - Maximum ON time before automatic fade-down (1-48 h, 0 = no limit)
# #
# MQTT COMMANDS: # MQTT COMMANDS:
# - ${mqtt_local_command_topic}/light/set = ON # - ${mqtt_local_command_topic} = ON
# - ${mqtt_local_command_topic}/light/set = OFF # - ${mqtt_local_command_topic} = OFF
# - State publishes to: # - State publishes to:
# - ${mqtt_local_status_topic}/light/state # - ${mqtt_local_status_topic}
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant offline (network and MQTT online) # a) Home Assistant offline (network and MQTT online)
@@ -80,7 +81,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot. project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot.
project_version: "v2.1" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version project_version: "v2.2" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version
# Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names)
api_key: !secret esp-api_key # If using HA API api_key: !secret esp-api_key # If using HA API
@@ -130,8 +131,7 @@ packages:
local_current_ip_address: "${current_ip_address}" local_current_ip_address: "${current_ip_address}"
#### HOME ASSISTANT API (choose encryption or no encryption options) #### #### HOME ASSISTANT API (choose encryption or no encryption options) ####
common_api: !include common_api: !include #file: common/api_common.yaml
#file: common/api_common.yaml
file: common/api_common_noencryption.yaml file: common/api_common_noencryption.yaml
vars: vars:
local_api_key: "${api_key}" local_api_key: "${api_key}"
@@ -181,32 +181,32 @@ esphome:
# Mode 0: Fade up to full (obeys fade settings; no on/off flicker) # Mode 0: Fade up to full (obeys fade settings; no on/off flicker)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 0;' lambda: "return id(restart_mode) == 0;"
then: then:
- lambda: 'id(ramp_switch_target_on) = true;' - lambda: "id(ramp_switch_target_on) = true;"
- script.execute: ramp_on_script - script.execute: ramp_on_script
# Mode 1: Restore Brightness (deferred to avoid races) # Mode 1: Restore Brightness (deferred to avoid races)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 1;' lambda: "return id(restart_mode) == 1;"
then: then:
- script.execute: deferred_restore_brightness - script.execute: deferred_restore_brightness
# Mode 2: Remain Off (no blip; stays off) # Mode 2: Remain Off (no blip; stays off)
- if: - if:
condition: condition:
lambda: 'return id(restart_mode) == 2;' lambda: "return id(restart_mode) == 2;"
then: then:
- script.stop: ramp_on_script - script.stop: ramp_on_script
- script.stop: ramp_off_script - script.stop: ramp_off_script
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 0s transition_length: 0s
# Boot complete: allow OFF handlers again # Boot complete: allow OFF handlers again
- lambda: 'id(booting) = false;' - lambda: "id(booting) = false;"
# NEW: force indicator OFF after boot logic # NEW: force indicator OFF after boot logic
# (Removed: output.turn_off: green_led_out) # (Removed: output.turn_off: green_led_out)
@@ -365,13 +365,13 @@ status_led:
mqtt: mqtt:
on_message: on_message:
# Light control to ramp up # Light control to ramp up
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
then: then:
- switch.turn_on: mosfet_ramp_switch - switch.turn_on: mosfet_ramp_switch
# Light control to ramp down # Light control to ramp down
- topic: "${mqtt_local_command_topic}/light/set" - topic: "${mqtt_local_command_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
then: then:
- switch.turn_off: mosfet_ramp_switch - switch.turn_off: mosfet_ramp_switch
@@ -503,7 +503,7 @@ binary_sensor:
on_press: on_press:
- if: - if:
condition: condition:
lambda: 'return id(ramp_switch_target_on);' lambda: "return id(ramp_switch_target_on);"
then: then:
# Target is currently ON -> press should go OFF (start ramp-down) # Target is currently ON -> press should go OFF (start ramp-down)
- lambda: |- - lambda: |-
@@ -608,7 +608,7 @@ light:
on_turn_on: on_turn_on:
- output.turn_on: green_led_out - output.turn_on: green_led_out
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_ON}" payload: "${mqtt_local_device_command_ON}"
retain: true retain: true
- lambda: |- - lambda: |-
@@ -619,7 +619,7 @@ light:
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- script.execute: max_on_watchdog - script.execute: max_on_watchdog
@@ -629,13 +629,13 @@ light:
- output.turn_off: green_led_out - output.turn_off: green_led_out
- if: - if:
condition: condition:
lambda: 'return !id(booting);' lambda: "return !id(booting);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic}/light/state" topic: "${mqtt_local_status_topic}"
payload: "${mqtt_local_device_command_OFF}" payload: "${mqtt_local_device_command_OFF}"
retain: true retain: true
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- lambda: |- - lambda: |-
id(last_brightness_pct) = 0.0f; id(last_brightness_pct) = 0.0f;
@@ -724,10 +724,10 @@ number:
set_action: set_action:
- if: - if:
condition: condition:
lambda: 'return x <= 0.0f;' lambda: "return x <= 0.0f;"
then: then:
# 0 means OFF # 0 means OFF
- lambda: 'id(suppress_slider_sync) = true;' - lambda: "id(suppress_slider_sync) = true;"
- script.stop: ramp_on_script - script.stop: ramp_on_script
- script.stop: ramp_off_script - script.stop: ramp_off_script
- light.turn_off: - light.turn_off:
@@ -739,7 +739,7 @@ number:
id(last_brightness_pct) = 0.0f; // persist OFF immediately id(last_brightness_pct) = 0.0f; // persist OFF immediately
id(last_set_pos) = 0; id(last_set_pos) = 0;
- delay: 400ms - delay: 400ms
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
else: else:
# Map 1..100 - [min..max] and set ON # Map 1..100 - [min..max] and set ON
- lambda: |- - lambda: |-
@@ -771,7 +771,7 @@ number:
if (out_pct > maxp) out_pct = maxp; if (out_pct > maxp) out_pct = maxp;
id(last_brightness_pct) = out_pct; // persist exact target now id(last_brightness_pct) = out_pct; // persist exact target now
- delay: 400ms - delay: 400ms
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
- platform: template - platform: template
id: cfg_max_on_hours id: cfg_max_on_hours
@@ -794,12 +794,12 @@ number:
id(cfg_max_on_hours).publish_state((float) hrs); id(cfg_max_on_hours).publish_state((float) hrs);
- if: - if:
condition: condition:
lambda: 'return id(mosfet_leds).current_values.is_on();' lambda: "return id(mosfet_leds).current_values.is_on();"
then: then:
- script.stop: max_on_watchdog - script.stop: max_on_watchdog
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- script.execute: max_on_watchdog - script.execute: max_on_watchdog
@@ -813,7 +813,7 @@ script:
- id: ramp_on_script - id: ramp_on_script
mode: restart mode: restart
then: then:
- lambda: 'id(is_ramping) = true;' - lambda: "id(is_ramping) = true;"
- script.stop: ramp_off_script - script.stop: ramp_off_script
# Ensure we start at at least the floor without a visible "pop". # Ensure we start at at least the floor without a visible "pop".
- if: - if:
@@ -825,12 +825,12 @@ script:
then: then:
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: 80ms transition_length: 80ms
# Ramp from current (>= floor) to cap over a fraction of ramp_up_ms. # Ramp from current (>= floor) to cap over a fraction of ramp_up_ms.
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(max_brightness_pct) / 100.0f;' brightness: !lambda "return id(max_brightness_pct) / 100.0f;"
transition_length: !lambda |- transition_length: !lambda |-
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
const float floor = id(min_brightness_pct) / 100.0f; const float floor = id(min_brightness_pct) / 100.0f;
@@ -850,7 +850,7 @@ script:
if (frac > 1.0f) frac = 1.0f; if (frac > 1.0f) frac = 1.0f;
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: |- - lambda: |-
id(is_ramping) = false; id(is_ramping) = false;
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
@@ -863,7 +863,7 @@ script:
- id: ramp_to_target_script - id: ramp_to_target_script
mode: restart mode: restart
then: then:
- lambda: 'id(is_ramping) = true;' - lambda: "id(is_ramping) = true;"
- script.stop: ramp_off_script - script.stop: ramp_off_script
# Ensure we start at the floor cleanly. # Ensure we start at the floor cleanly.
- if: - if:
@@ -875,7 +875,7 @@ script:
then: then:
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: 80ms transition_length: 80ms
# Ramp from current (>= floor) to restore_target_pct over a fraction of ramp_up_ms. # Ramp from current (>= floor) to restore_target_pct over a fraction of ramp_up_ms.
- light.turn_on: - light.turn_on:
@@ -906,7 +906,7 @@ script:
if (frac > 1.0f) frac = 1.0f; if (frac > 1.0f) frac = 1.0f;
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: |- - lambda: |-
id(is_ramping) = false; id(is_ramping) = false;
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
@@ -925,7 +925,7 @@ script:
- script.stop: ramp_on_script - script.stop: ramp_on_script
- light.turn_on: - light.turn_on:
id: mosfet_leds id: mosfet_leds
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' brightness: !lambda "return id(min_brightness_pct) / 100.0f;"
transition_length: !lambda |- transition_length: !lambda |-
const auto &cv = id(mosfet_leds).current_values; const auto &cv = id(mosfet_leds).current_values;
const float floor = id(min_brightness_pct) / 100.0f; const float floor = id(min_brightness_pct) / 100.0f;
@@ -938,7 +938,7 @@ script:
if (frac > 1.0f) frac = 1.0f; if (frac > 1.0f) frac = 1.0f;
id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac); id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac);
return (uint32_t) id(last_ramp_ms); return (uint32_t) id(last_ramp_ms);
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 150ms transition_length: 150ms
@@ -955,12 +955,12 @@ script:
then: then:
- if: - if:
condition: condition:
lambda: 'return id(max_on_hours) > 0;' lambda: "return id(max_on_hours) > 0;"
then: then:
- delay: !lambda 'return (uint32_t) (id(max_on_hours) * 3600000UL);' - delay: !lambda "return (uint32_t) (id(max_on_hours) * 3600000UL);"
- if: - if:
condition: condition:
lambda: 'return id(mosfet_leds).current_values.is_on();' lambda: "return id(mosfet_leds).current_values.is_on();"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = false; id(ramp_switch_target_on) = false;
@@ -987,19 +987,19 @@ script:
- if: - if:
condition: condition:
lambda: 'return id(restore_target_pct) > 0.5f;' lambda: "return id(restore_target_pct) > 0.5f;"
then: then:
- lambda: |- - lambda: |-
id(ramp_switch_target_on) = true; // reflect our intent id(ramp_switch_target_on) = true; // reflect our intent
id(suppress_slider_sync) = true; id(suppress_slider_sync) = true;
- script.stop: ramp_off_script - script.stop: ramp_off_script
- script.execute: ramp_to_target_script - script.execute: ramp_to_target_script
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - delay: !lambda "return (uint32_t) id(last_ramp_ms);"
- lambda: 'id(suppress_slider_sync) = false;' - lambda: "id(suppress_slider_sync) = false;"
else: else:
# Exact last was 0 -> remain OFF # Exact last was 0 -> remain OFF
- lambda: 'id(ramp_switch_target_on) = false;' - lambda: "id(ramp_switch_target_on) = false;"
- light.turn_off: - light.turn_off:
id: mosfet_leds id: mosfet_leds
transition_length: 0s transition_length: 0s
# (Removed: output.turn_off: green_led_out) # make sure LED is off if no ramp # (Removed: output.turn_off: green_led_out) # make sure LED is off if no ramp
+12 -12
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbdrmsouth.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbdrmsouth.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v1.4 2026-07-20 Flattened retained North and South MQTT status topics to the device roots.
# v1.3 2026-06-12 Reassigned logical controls after live wiring checks. # v1.3 2026-06-12 Reassigned logical controls after live wiring checks.
# Relay 1 on both switches = North Lights virtual/Tasmota control. # Relay 1 on both switches = North Lights virtual/Tasmota control.
# Relay 2 on both switches = South Lights control; WEST Relay 2 is physical load. # Relay 2 on both switches = South Lights control; WEST Relay 2 is physical load.
@@ -55,7 +56,7 @@
# NOTE: TOGGLE is intentionally not handled here to avoid double-toggle if both switches receive it. # NOTE: TOGGLE is intentionally not handled here to avoid double-toggle if both switches receive it.
# #
# - North Lights retained status/sync topic: # - North Lights retained status/sync topic:
# ${mqtt_local_status_topic1}/state # ${mqtt_local_status_topic1}
# Payload "On" / "Off" mirrors the actual North Lights state. # Payload "On" / "Off" mirrors the actual North Lights state.
# #
# - South Lights local command topic: # - South Lights local command topic:
@@ -65,7 +66,7 @@
# NOTE: TOGGLE is intentionally not handled here to avoid ambiguous multi-device toggles. # NOTE: TOGGLE is intentionally not handled here to avoid ambiguous multi-device toggles.
# #
# - South Lights retained status/sync topic: # - South Lights retained status/sync topic:
# ${mqtt_local_status_topic2}/state # ${mqtt_local_status_topic2}
# Payload "On" / "Off" mirrors the actual South Lights state. # Payload "On" / "Off" mirrors the actual South Lights state.
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
@@ -87,7 +88,6 @@
# - Accurate time is NOT needed (SNTP not needed). # - Accurate time is NOT needed (SNTP not needed).
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -101,7 +101,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v1.3" project_version: "v1.4"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -218,22 +218,22 @@ globals:
- id: north_update_from_sync - id: north_update_from_sync
type: bool type: bool
restore_value: false restore_value: false
initial_value: 'false' initial_value: "false"
- id: south_update_from_sync - id: south_update_from_sync
type: bool type: bool
restore_value: false restore_value: false
initial_value: 'false' initial_value: "false"
- id: north_lights_state - id: north_lights_state
type: bool type: bool
restore_value: false restore_value: false
initial_value: 'false' initial_value: "false"
- id: south_lights_state - id: south_lights_state
type: bool type: bool
restore_value: false restore_value: false
initial_value: 'false' initial_value: "false"
#:########################################################################################:# #:########################################################################################:#
# MQTT: Device-specific MQTT command + retained status/sync triggers # MQTT: Device-specific MQTT command + retained status/sync triggers
@@ -275,7 +275,7 @@ mqtt:
} }
# Retained North status is a secondary mirror/sync path. # Retained North status is a secondary mirror/sync path.
- topic: "${mqtt_local_status_topic1}/state" - topic: "${mqtt_local_status_topic1}"
then: then:
- lambda: |- - lambda: |-
if (x == "On" || x == "ON" || x == "on") { if (x == "On" || x == "ON" || x == "on") {
@@ -291,7 +291,7 @@ mqtt:
# retained status after the physical Relay 2 changes, and this switch mirrors # retained status after the physical Relay 2 changes, and this switch mirrors
# that status onto its local Relay 2. # that status onto its local Relay 2.
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
- topic: "${mqtt_local_status_topic2}/state" - topic: "${mqtt_local_status_topic2}"
then: then:
- lambda: |- - lambda: |-
if (x == "On" || x == "ON" || x == "on") { if (x == "On" || x == "ON" || x == "on") {
@@ -410,7 +410,7 @@ script:
id(north_update_from_sync) = true; id(north_update_from_sync) = true;
- switch.turn_on: relay_1 - switch.turn_on: relay_1
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic1}/state" topic: "${mqtt_local_status_topic1}"
payload: "On" payload: "On"
retain: true retain: true
- lambda: |- - lambda: |-
@@ -424,7 +424,7 @@ script:
id(north_update_from_sync) = true; id(north_update_from_sync) = true;
- switch.turn_off: relay_1 - switch.turn_off: relay_1
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic1}/state" topic: "${mqtt_local_status_topic1}"
payload: "Off" payload: "Off"
retain: true retain: true
- lambda: |- - lambda: |-
+16 -16
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbdrmwest.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-masterbdrmwest.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# v1.4 2026-07-20 Flattened retained North and South MQTT status topics to the device roots.
# v1.3 2026-06-12 Reassigned logical controls after live wiring checks. # v1.3 2026-06-12 Reassigned logical controls after live wiring checks.
# Relay 1 on both switches = North Lights virtual/Tasmota control. # Relay 1 on both switches = North Lights virtual/Tasmota control.
# Relay 2 on both switches = South Lights control; WEST Relay 2 is physical load. # Relay 2 on both switches = South Lights control; WEST Relay 2 is physical load.
@@ -55,7 +56,7 @@
# NOTE: TOGGLE is intentionally not handled here to avoid double-toggle if both switches receive it. # NOTE: TOGGLE is intentionally not handled here to avoid double-toggle if both switches receive it.
# #
# - North Lights retained status/sync topic: # - North Lights retained status/sync topic:
# ${mqtt_local_status_topic1}/state # ${mqtt_local_status_topic1}
# Payload "On" / "Off" mirrors the actual North Lights state. # Payload "On" / "Off" mirrors the actual North Lights state.
# #
# - South Lights local command topic: # - South Lights local command topic:
@@ -65,7 +66,7 @@
# NOTE: TOGGLE is intentionally not handled here to avoid ambiguous multi-device toggles. # NOTE: TOGGLE is intentionally not handled here to avoid ambiguous multi-device toggles.
# #
# - South Lights retained status/sync topic: # - South Lights retained status/sync topic:
# ${mqtt_local_status_topic2}/state # ${mqtt_local_status_topic2}
# Payload "On" / "Off" published when Relay 2 changes state. # Payload "On" / "Off" published when Relay 2 changes state.
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
@@ -88,7 +89,6 @@
# - Accurate time is NOT needed (SNTP not needed). # - Accurate time is NOT needed (SNTP not needed).
#:########################################################################################:# #:########################################################################################:#
#:########################################################################################:# #:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions # SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes) # If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -102,7 +102,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Zemismart Technologies.KS-811 Triple" project_name: "Zemismart Technologies.KS-811 Triple"
project_version: "v1.3" project_version: "v1.4"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -217,22 +217,22 @@ globals:
- id: north_update_from_sync - id: north_update_from_sync
type: bool type: bool
restore_value: false restore_value: false
initial_value: 'false' initial_value: "false"
- id: south_update_from_sync - id: south_update_from_sync
type: bool type: bool
restore_value: false restore_value: false
initial_value: 'false' initial_value: "false"
- id: north_lights_state - id: north_lights_state
type: bool type: bool
restore_value: false restore_value: false
initial_value: 'false' initial_value: "false"
- id: south_lights_state - id: south_lights_state
type: bool type: bool
restore_value: false restore_value: false
initial_value: 'false' initial_value: "false"
#:########################################################################################:# #:########################################################################################:#
# MQTT: Device-specific MQTT command + retained status/sync triggers # MQTT: Device-specific MQTT command + retained status/sync triggers
@@ -274,7 +274,7 @@ mqtt:
} }
# Retained North status is a secondary mirror/sync path. # Retained North status is a secondary mirror/sync path.
- topic: "${mqtt_local_status_topic1}/state" - topic: "${mqtt_local_status_topic1}"
then: then:
- lambda: |- - lambda: |-
if (x == "On" || x == "ON" || x == "on") { if (x == "On" || x == "ON" || x == "on") {
@@ -296,7 +296,7 @@ mqtt:
} }
# Retained South status keeps this physical relay and the SOUTH mirror in step. # Retained South status keeps this physical relay and the SOUTH mirror in step.
- topic: "${mqtt_local_status_topic2}/state" - topic: "${mqtt_local_status_topic2}"
then: then:
- lambda: |- - lambda: |-
if (x == "On" || x == "ON" || x == "on") { if (x == "On" || x == "ON" || x == "on") {
@@ -415,7 +415,7 @@ script:
id(north_update_from_sync) = true; id(north_update_from_sync) = true;
- switch.turn_on: relay_1 - switch.turn_on: relay_1
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic1}/state" topic: "${mqtt_local_status_topic1}"
payload: "On" payload: "On"
retain: true retain: true
- lambda: |- - lambda: |-
@@ -429,7 +429,7 @@ script:
id(north_update_from_sync) = true; id(north_update_from_sync) = true;
- switch.turn_off: relay_1 - switch.turn_off: relay_1
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic1}/state" topic: "${mqtt_local_status_topic1}"
payload: "Off" payload: "Off"
retain: true retain: true
- lambda: |- - lambda: |-
@@ -554,10 +554,10 @@ switch:
} }
- if: - if:
condition: condition:
lambda: 'return !id(south_update_from_sync);' lambda: "return !id(south_update_from_sync);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic2}/state" topic: "${mqtt_local_status_topic2}"
payload: "On" payload: "On"
retain: true retain: true
on_turn_off: on_turn_off:
@@ -568,10 +568,10 @@ switch:
} }
- if: - if:
condition: condition:
lambda: 'return !id(south_update_from_sync);' lambda: "return !id(south_update_from_sync);"
then: then:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_local_status_topic2}/state" topic: "${mqtt_local_status_topic2}"
payload: "Off" payload: "Off"
retain: true retain: true
+9 -8
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeusbhubpower.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeusbhubpower.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V1.2 2026-07-20 Simplified local MQTT command and status topics to the device root
# V1.1 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.1 2026-02-25 Updated yaml to zorruno layout V1.1
# V1.0 2025-06-14 Initial Version # V1.0 2025-06-14 Initial Version
#:########################################################################################:# #:########################################################################################:#
@@ -22,10 +23,10 @@
#:########################################################################################:# #:########################################################################################:#
# MQTT COMMANDS: # MQTT COMMANDS:
# Command (set relay): # Command (set relay):
# - ${mqtt_command_topic}/relay1/set -> ON, OFF # - ${mqtt_command_topic} -> ON, OFF
# #
# Status (published from template sensor): # Status (published from template sensor):
# - ${mqtt_status_topic}/relay1/state -> ON, OFF # - ${mqtt_status_topic} -> ON, OFF
#:########################################################################################:# #:########################################################################################:#
# OFFLINE NOTES: # OFFLINE NOTES:
# a) Home Assistant OFFLINE, but Network and MQTT ONLINE # a) Home Assistant OFFLINE, but Network and MQTT ONLINE
@@ -54,7 +55,7 @@ substitutions:
# Project Naming # Project Naming
project_name: "Sonoff Technologies.Sonoff Basic V1" project_name: "Sonoff Technologies.Sonoff Basic V1"
project_version: "v1.1" project_version: "v1.2"
# Passwords & Secrets (Unfortunately, you cannot use substitutions inside secret names) # Passwords & Secrets (Unfortunately, you cannot use substitutions inside secret names)
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -201,12 +202,12 @@ binary_sensor:
return id(relay1).state; return id(relay1).state;
on_press: on_press:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}/relay1/state" topic: "${mqtt_status_topic}"
payload: "ON" payload: "ON"
retain: false retain: false
on_release: on_release:
- mqtt.publish: - mqtt.publish:
topic: "${mqtt_status_topic}/relay1/state" topic: "${mqtt_status_topic}"
payload: "OFF" payload: "OFF"
retain: false retain: false
@@ -227,12 +228,12 @@ status_led:
#:########################################################################################:# #:########################################################################################:#
mqtt: mqtt:
on_message: on_message:
- topic: "${mqtt_command_topic}/relay1/set" - topic: "${mqtt_command_topic}"
payload: "ON" payload: "ON"
then: then:
- switch.turn_on: relay1 - switch.turn_on: relay1
- topic: "${mqtt_command_topic}/relay1/set" - topic: "${mqtt_command_topic}"
payload: "OFF" payload: "OFF"
then: then:
- switch.turn_off: relay1 - switch.turn_off: relay1
+44 -1
View File
@@ -4,17 +4,60 @@
# PACKAGE: 16A EV Charger Control # PACKAGE: 16A EV Charger Control
############################################################################### ###############################################################################
# #
# FILE:
# packages/16a_ev_charging_controls.yaml
#
# VERSION: # VERSION:
# V1.2 2026-07-20
# - Added structured mode, timing, and restart behavior documentation.
#
# V1.1 2026-05-15 # V1.1 2026-05-15
# - Reworked 1hr topup logic to use a hard deadline and watchdog. # - Reworked 1hr topup logic to use a hard deadline and watchdog.
# - Removed dependency on timer.finished event for relay shutoff. # - Removed dependency on timer.finished event for relay shutoff.
# - Offpeak until charged now continues past offpeak end until charging stops. # - Offpeak until charged now continues past offpeak end until charging stops.
# - 1hr topup now now rolls into Normal Offpeak if the hour ends during # - 1hr topup now rolls into Normal Offpeak if the hour ends during
# the offpeak window, without switching the relay off and back on. # the offpeak window, without switching the relay off and back on.
# #
# V1.0 2026-05-11 # V1.0 2026-05-11
# - Initial package for 16A EV charger offpeak and charge-until-full control. # - Initial package for 16A EV charger offpeak and charge-until-full control.
# #
# PURPOSE:
# Controls the Leaf 16A charger relay using scheduled offpeak operation and
# user-selectable immediate or charge-until-full modes.
#
# DEPENDENCIES:
# - switch.garage_db_control_16a_wallcharger_operation controls charger power.
# - binary_sensor.garage_db_control_16a_wallcharger_charging reports whether
# the vehicle is actively charging.
#
# CHARGE MODES:
# - Normal (Offpeak) turns the relay on and off at the configured offpeak
# start and end times. Selecting this mode takes no immediate action.
# - Offpeak until charged starts at the offpeak time, or immediately if
# selected during offpeak, and may continue beyond offpeak end until the
# vehicle stops charging.
# - 1hr topup now turns the relay on immediately and records a hard deadline
# one hour ahead.
# - Charge now until full turns the relay on immediately and keeps it on until
# the vehicle stops charging.
# - Stop charging now turns the relay off immediately and returns the selector
# to Normal (Offpeak).
#
# TIMING AND COMPLETION:
# - Charge-until-full modes allow five minutes for charging to start. This
# also handles a vehicle that is already full.
# - Charging is considered complete after the charging sensor remains off for
# five minutes.
# - The one-hour topup deadline is stored in input_datetime and checked every
# minute and when Home Assistant starts.
# - If a topup ends during offpeak, the relay remains on and the mode returns
# to Normal (Offpeak), avoiding an off/on relay cycle.
# - Equal offpeak start and end times are interpreted as an all-day window.
#
# OPERATION NOTES:
# - Normal offpeak start and end use exact-time triggers.
# - There is no startup catch-up if Home Assistant is offline at either time.
#
# PACKAGE SETTINGS: # PACKAGE SETTINGS:
# Car display name: # Car display name:
# - Leaf # - Leaf
@@ -6,12 +6,16 @@
# Pool Light Operation # Pool Light Operation
# #
# FILE: # FILE:
# packages/pool_light_boost_switch.yaml # packages/Pool_Controls/pool_light_operation.yaml
# #
# VERSION: # VERSION:
# V1.1 2026-06-29 # V1.2 2026-07-20
# #
# VERSION HISTORY: # VERSION HISTORY:
# V1.2 2026-07-20
# - Corrected the documented package filename.
# - Documented the relationship with the native ESPHome controls.
#
# V1.1 2026-06-29 # V1.1 2026-06-29
# - Tidied layout, comments, naming and automation IDs. # - Tidied layout, comments, naming and automation IDs.
# - Added structured package header and section comments. # - Added structured package header and section comments.
@@ -38,8 +42,15 @@
# Operation topic: # Operation topic:
# viewroad-commands/poollight-timer/operation # viewroad-commands/poollight-timer/operation
# #
# DEPENDENCIES:
# - switch.esp_poollightpower2_switch provides the real output state.
# - The ESPHome pool light device subscribes to the MQTT operation topic.
# - Native ESPHome mode, boost, and pool-light-mode entities coexist with
# this one-tap control.
#
# NOTES: # NOTES:
# The input_boolean.timer_light_midnight_pending helper is internal to this package. # The input_boolean.timer_light_midnight_pending helper is internal to this package.
# Dashboard cards currently use input_boolean.poollights_mode_switch.
# #
#:########################################################################################:# #:########################################################################################:#
@@ -1,10 +1,68 @@
# packages/poolpump_operation.yaml #:########################################################################################:#
# Pool Pump Operation Package #
#:########################################################################################:#
#
# TITLE:
# Pool Pump Operation
#
# FILE:
# packages/Pool_Controls/pool_pump_operation.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured package documentation and section comments.
# - Documented the relationship with the native ESPHome controls.
#
# V1.0
# - Initial package.
# - Provides a Home Assistant UI switch for pool pump BOOST / OFF behaviour.
# - Sends TIMER mode again at midnight when required.
#
# PURPOSE:
# Provides a one-tap Home Assistant UI switch for controlling the pool pump.
#
# Behaviour:
# - Turning the UI switch ON sends BOOST if the real pump output is OFF.
# - Turning the UI switch OFF sends OFF if the real pump output is ON.
# - After OFF is requested, TIMER mode is restored at midnight.
# - The UI switch follows the real ESPHome output without publishing MQTT.
#
# MQTT:
# Operation topic:
# viewroad-commands/poolpump-timer/operation
#
# Payloads used by this package:
# BOOST
# OFF
# TIMER
#
# DEPENDENCIES:
# - switch.esp_poolpumppower_power_output provides the real output state.
# - The ESPHome pool pump device subscribes to the MQTT operation topic.
# - Native ESPHome mode and boost entities coexist with this one-tap control.
#
# NOTES:
# - input_boolean.timer_midnight_pending is internal to this package.
# - Dashboard cards currently use input_boolean.poolpump_mode_switch.
#
#:########################################################################################:#
#:########################################################################################:#
# Home Assistant Customisation #
#:########################################################################################:#
homeassistant: homeassistant:
customize: customize:
input_boolean.poolpump_mode_switch: input_boolean.poolpump_mode_switch:
icon: mdi:pump icon: mdi:pump
#:########################################################################################:#
# Input Booleans #
#:########################################################################################:#
input_boolean: input_boolean:
poolpump_mode_switch: poolpump_mode_switch:
name: "Pool Pump Operation" name: "Pool Pump Operation"
@@ -14,6 +72,10 @@ input_boolean:
name: "Send TIMER at Midnight" name: "Send TIMER at Midnight"
initial: false initial: false
#:########################################################################################:#
# Automations #
#:########################################################################################:#
automation: automation:
- alias: "Pool Pump → send BOOST when user turns UI switch ON" - alias: "Pool Pump → send BOOST when user turns UI switch ON"
trigger: trigger:
@@ -6,12 +6,16 @@
# Pool Timer Selection # Pool Timer Selection
# #
# FILE: # FILE:
# pool_timer_selection.yaml # packages/Pool_Controls/pool_timers_selections.yaml
# #
# VERSION: # VERSION:
# V1.0 2026-06-29 # V1.1 2026-07-20
# #
# VERSION HISTORY: # VERSION HISTORY:
# V1.1 2026-07-20
# - Corrected the documented package filename.
# - Documented command selectors versus ESPHome timer feedback.
#
# V1.0 2026-06-29 # V1.0 2026-06-29
# - Initial package. # - Initial package.
# - Adds Home Assistant input_select helpers for Pool Pump and Pool Light timer times. # - Adds Home Assistant input_select helpers for Pool Pump and Pool Light timer times.
@@ -36,6 +40,16 @@
# #
# Payload format is HH:MM. # Payload format is HH:MM.
# #
# STATUS AND FEEDBACK:
# - These input_select helpers send retained MQTT commands to ESPHome.
# - They do not synchronize their displayed options from the ESPHome devices.
# - The ESPHome Timeclock sensors are authoritative for the currently applied
# timer values.
# - A selector displaying "Default" does not prove that the device currently
# uses its default time.
# - Native ESPHome mode controls coexist with this package, while timer
# schedule changes continue to use the MQTT topics above.
#
# IMPORTANT: # IMPORTANT:
# The current ESPHome timer logic only handles same-day timer windows: # The current ESPHome timer logic only handles same-day timer windows:
# current_mins >= on_time AND current_mins < off_time # current_mins >= on_time AND current_mins < off_time
+49
View File
@@ -1,5 +1,52 @@
#:########################################################################################:#
# Alexa TP-Link Guest Wi-Fi Package #
#:########################################################################################:#
#
# TITLE:
# Alexa TP-Link Guest Wi-Fi
#
# FILE:
# packages/alexa_tplink_actions.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured documentation and automation descriptions.
#
# V1.0
# - Initial Alexa-mediated TP-Link guest-network controls.
#
# PURPOSE:
# Enables or disables the TP-Link guest Wi-Fi network by sending custom Alexa
# requests through the kitchen Echo Show.
#
# DEPENDENCIES:
# - input_boolean.wifi_guest_network is a UI-managed helper that represents
# the requested guest-network state.
# - media_player.view_rd_kitchen_echo_show must be available through the Alexa
# Media Player integration.
# - The Alexa account must have a working, linked TP-Link skill.
#
# ALEXA REQUESTS:
# - On: ask t.p.link to enable guest network
# - Off: ask t.p.link to disable guest network
#
# OPERATION NOTES:
# - The helper records requested state; it does not confirm router state.
# - If Alexa or the TP-Link skill fails, the helper can disagree with the
# actual guest-network state.
# - After the helper remains on for two hours, it is turned off. That state
# change then sends the Alexa disable request.
# - The two-hour state-trigger period does not persist through a Home Assistant
# restart or automation reload.
#
#:########################################################################################:#
automation: automation:
- alias: "Turn on the Wifi Guest Network" - alias: "Turn on the Wifi Guest Network"
description: "Asks the linked TP-Link Alexa skill to enable the guest Wi-Fi network."
mode: single mode: single
triggers: triggers:
- trigger: state - trigger: state
@@ -14,6 +61,7 @@ automation:
media_content_id: ask t.p.link to enable guest network media_content_id: ask t.p.link to enable guest network
- alias: "Turn off the Wifi Guest Network" - alias: "Turn off the Wifi Guest Network"
description: "Asks the linked TP-Link Alexa skill to disable the guest Wi-Fi network."
mode: single mode: single
triggers: triggers:
- trigger: state - trigger: state
@@ -28,6 +76,7 @@ automation:
media_content_id: ask t.p.link to disable guest network media_content_id: ask t.p.link to disable guest network
- alias: "Switch guest network off after time" - alias: "Switch guest network off after time"
description: "Turns off the guest-network helper after it remains on for two hours."
mode: single mode: single
triggers: triggers:
- trigger: state - trigger: state
+11 -6
View File
@@ -1,8 +1,8 @@
############################################################################### ###############################################################################
# Bedroom 1 Ikea Air Filter Package # Bedroom 1 Ikea Air Filter Package
# File: /config/packages/bedroom_1_ikea_air_filter.yaml # File: /config/packages/bedroom_1_ikea_air_filter.yaml
# Version: 1.1 # Version: 1.2
# Date: 2026-05-08 # Date: 2026-07-20
# #
# Purpose: # Purpose:
# - Creates a dropdown helper called "Bedroom 1 Ikea Fan". # - Creates a dropdown helper called "Bedroom 1 Ikea Fan".
@@ -11,7 +11,7 @@
# #
# Behaviour notes: # Behaviour notes:
# - Quiet time turning on sets fan speed to 2. # - Quiet time turning on sets fan speed to 2.
# - Bedside lamp turning on sets fan speed to 2. # - Bedside lamp or Jump Fade control turning on sets fan speed to 2.
# - Bedside lamp turning off does not change the fan speed. # - Bedside lamp turning off does not change the fan speed.
# - There is no 10-minute re-check, so the fan will not ramp back up just # - There is no 10-minute re-check, so the fan will not ramp back up just
# because the bedside lamp was switched off. # because the bedside lamp was switched off.
@@ -80,12 +80,16 @@ automation:
entity_id: input_boolean.quiet_time entity_id: input_boolean.quiet_time
to: "on" to: "on"
# Bedside lamp only forces low when it turns on. # The lamp state catches direct light control.
# Turning the lamp off does not change the fan speed.
- trigger: state - trigger: state
entity_id: light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb entity_id: light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb
to: "on" to: "on"
# The Jump Fade switch catches a bedside press while the lamp is already on.
- trigger: state
entity_id: switch.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb_jump_fade_up_down
to: "on"
# Main timing boundaries. # Main timing boundaries.
- trigger: time - trigger: time
at: at:
@@ -104,9 +108,10 @@ automation:
- variables: - variables:
trigger_entity: "{{ trigger.entity_id | default('') }}" trigger_entity: "{{ trigger.entity_id | default('') }}"
bedside_lamp_entity: light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb bedside_lamp_entity: light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb
bedside_lamp_switch_entity: switch.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb_jump_fade_up_down
bedside_lamp_on_trigger: >- bedside_lamp_on_trigger: >-
{{ {{
trigger_entity == bedside_lamp_entity trigger_entity in [bedside_lamp_entity, bedside_lamp_switch_entity]
and trigger.to_state is defined and trigger.to_state is defined
and trigger.to_state.state == 'on' and trigger.to_state.state == 'on'
}} }}
@@ -1,9 +1,9 @@
################################################################################ ################################################################################
# PACKAGE: Downstairs Lights Bulk Activation # PACKAGE: Downstairs Lights Bulk Activation
# FILE: packages/downstairs_lights_bulk_activation.yaml # FILE: packages/downstairs_bulk_lights_on_from_stairs.yaml
# #
# Version: 1.0 # Version: 1.1
# Date: 2026-04-26 # Date: 2026-07-20
# #
# Notes: # Notes:
# - Uses the virtual switch: # - Uses the virtual switch:
@@ -16,16 +16,16 @@
# Turns OFF the listed downstairs lights, but only if each light is currently ON. # Turns OFF the listed downstairs lights, but only if each light is currently ON.
# #
# - No action is taken unless: # - No action is taken unless:
# input_boolean.downstairs_flat_occupied is ON. # input_boolean.downstairs_flat_occupied is OFF.
################################################################################ ################################################################################
automation: automation:
- id: downstairs_lights_bulk_activation - id: downstairs_lights_bulk_activation
alias: "Downstairs Lights Bulk Activation" alias: "Downstairs Lights Bulk Activation"
description: > description: >
V1.0 - 2026-04-26: Bulk ON/OFF control for downstairs lights from the V1.1 - 2026-07-20: Bulk ON/OFF control for downstairs lights from the
central stair lightswitch virtual switch. Only operates when the downstairs central stair lightswitch virtual switch. Only operates when the downstairs
flat occupied input_boolean is ON. flat is not occupied.
mode: single mode: single
+47
View File
@@ -1,3 +1,50 @@
#:########################################################################################:#
# Firewall Internet Control Package #
#:########################################################################################:#
#
# TITLE:
# Firewall Internet Control
#
# FILE:
# packages/firewall_control.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured MQTT and external-firewall documentation.
#
# V1.0
# - Initial persistent and temporary internet-blocking controls.
#
# PURPOSE:
# Provides Home Assistant controls for persistent and temporary internet
# blocking of Mollie's devices through an external MQTT firewall service.
#
# PERSISTENT CONTROL:
# - Blocked enables persistent internet blocking.
# - Unblocked disables persistent internet blocking.
# - The switch state is reported by the external firewall service.
#
# TEMPORARY CONTROLS:
# - One-hour block publishes Blocked to the temporary-block topic.
# - 15-minute unblock publishes Unblocked to the temporary-unblock topic.
# - One-hour unblock publishes Unblocked to its one-hour topic.
#
# EXTERNAL DEPENDENCY:
# - Home Assistant only publishes command requests.
# - The external firewall service implements temporary durations, restores the
# appropriate state afterward, and publishes persistent switch feedback.
#
# MQTT NOTES:
# - All commands are non-retained.
# - No availability topic is configured for these entities.
# - The persistent status topic retains the legacy device label
# block-unblock-mollie-iphone8.
#
#:########################################################################################:#
mqtt: mqtt:
switch: switch:
- unique_id: mollies.internet - unique_id: mollies.internet
+47 -4
View File
@@ -1,11 +1,54 @@
#:########################################################################################:# #:########################################################################################:#
# Home Assistant Summary Package - V2 # # Home Assistant Summary Package - V2 #
#:########################################################################################:# #:########################################################################################:#
# #
# Uses V2 entity IDs to avoid stale/ghost entities from earlier versions. # TITLE:
# Home Assistant Summary V2
# #
# Dashboard entity prefix: # FILE:
# sensor.ha_summary_v2_... # packages/ha_summary.yaml
#
# VERSION:
# V2.1 2026-07-20
#
# VERSION HISTORY:
# V2.1 2026-07-20
# - Added structured documentation for refresh behavior and counting rules.
# - Documented heuristic classifications and their limitations.
#
# V2.0
# - Introduced V2 entity IDs to avoid stale entities from earlier versions.
#
# PURPOSE:
# Provides dashboard summary sensors for Home Assistant entities, devices,
# areas, cameras, scenes, scripts, automations, add-ons, and updates.
#
# It also provides device and entity counts for ESPHome, Tasmota, ZHA,
# Zigbee2MQTT, Matter, and selected cloud integrations.
#
# OUTPUTS:
# Dashboard entity prefix:
# sensor.ha_summary_v2_...
#
# REFRESH:
# Sensors refresh when Home Assistant starts, when the entity, device, or area
# registries change, when core configuration changes, and every five minutes.
#
# COUNTING NOTES:
# - Total devices counts distinct device IDs associated with current entities.
# Devices without entities are not included.
# - Broken entities are entities whose state is unknown or unavailable.
# - Add-ons are inferred from Supervisor update entities, excluding the Core,
# Supervisor, and Operating System update entities.
# - Zigbee2MQTT devices and entities are identified by searching MQTT device
# metadata for "zigbee2mqtt".
# - Matter Wi-Fi and Thread classifications search device metadata for known
# transport terms. These are heuristics rather than authoritative transport
# data, and a device can match both categories.
# - Matter unclassified counts subtract Wi-Fi and Thread counts from totals, so
# overlapping classifications can affect the result.
# - Cloud counts use the explicit integration list in the final two sensors.
# Add or remove integration domains there when maintaining cloud coverage.
# #
template: template:
@@ -1,5 +1,57 @@
########################################################################################## ##########################################################################################
# heat_pump_master_bedroom_schedules.yaml # Master Bedroom Heat Pump Schedules
##########################################################################################
#
# TITLE:
# Master Bedroom Heat Pump Schedules
#
# FILE:
# packages/heat_pump_master_bedroom_schedules.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured documentation for schedules, boost, and helper behavior.
#
# V1.0
# - Initial master bedroom heat pump schedules and boost controls.
#
# PURPOSE:
# Provides optional 21:00 start and midnight stop schedules, a combined Night
# Power mode, and a manual one-hour boost for the master bedroom heat pump.
#
# DEPENDENCIES:
# - climate.master_bedroom provides the Panasonic Comfort Cloud heat pump.
# - The climate entity must support the "boost" and "none" preset modes.
# - packages/heat_pump_master_bedroom_helpers.yaml provides companion
# dashboard, setpoint, HVAC mode, profile, and sleep-timer controls.
#
# SCHEDULE MODES:
# - Night Power Mode turns the heat pump on at 21:00, applies boost for 30
# minutes, returns it to the normal preset, and turns it off at midnight.
# - 9pm On turns the heat pump on at 21:00 without changing its preset.
# - Midnight Off turns the heat pump off at midnight.
# - Enabling Night Power disables the separate 9pm On and Midnight Off modes.
# - Enabling either separate mode disables Night Power. The separate 9pm On
# and Midnight Off modes may be enabled together.
#
# MANUAL BOOST:
# - script.master_bedroom_boost_1hr applies boost for one hour.
# - If the heat pump was off when boost started, it is turned off afterward.
# - If it was already running, boost ends by restoring the normal preset and
# leaving the heat pump running.
#
# INTERNAL STATE:
# - input_boolean.master_bedroom_boost_restore_off records whether manual
# boost should restore the heat pump to off.
# - timer.master_bedroom_boost_timer controls manual and scheduled boost time.
#
# OPERATION NOTES:
# - The 21:00 and midnight schedules use exact-time triggers.
# - There is no startup catch-up if Home Assistant is offline at either time.
#
########################################################################################## ##########################################################################################
########################################################################################## ##########################################################################################
+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_loungecabinetleds2_lounge_cabinet_leds: 90 light.esp_loungecabinetleds_lounge_cabinet_leds: 90
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_loungecabinetleds2_lounge_cabinet_leds: 60 light.esp_loungecabinetleds_lounge_cabinet_leds: 60
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_loungecabinetleds2_lounge_cabinet_leds: 50 light.esp_loungecabinetleds_lounge_cabinet_leds: 50
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_loungecabinetleds2_lounge_cabinet_leds: 40 light.esp_loungecabinetleds_lounge_cabinet_leds: 40
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_loungecabinetleds2_lounge_cabinet_leds: 5 light.esp_loungecabinetleds_lounge_cabinet_leds: 5
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_loungecabinetleds2_lounge_cabinet_leds: 30 light.esp_loungecabinetleds_lounge_cabinet_leds: 30
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_loungecabinetleds2_lounge_cabinet_leds: 0 light.esp_loungecabinetleds_lounge_cabinet_leds: 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"
+41 -4
View File
@@ -1,3 +1,40 @@
#:########################################################################################:#
# Low Battery Device Summary Package #
#:########################################################################################:#
#
# TITLE:
# Low Battery Device Summary
#
# FILE:
# packages/low_battery_device_quantity.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Changed the low-battery threshold from 97% to 20%.
# - Added structured documentation for scope, exclusions, and outputs.
#
# V1.0
# - Initial low-battery count and list sensors.
#
# PURPOSE:
# Finds numeric sensor entities with device_class battery whose value is 20%
# or lower, then exposes a count and a human-readable device list.
#
# SCOPE AND EXCLUSIONS:
# - Only entities in the sensor domain with device_class battery are checked.
# - Unknown, unavailable, non-numeric, and "Ok" states are excluded.
# - Battery entities in other domains are not included.
#
# OUTPUTS:
# - sensor.devices_with_low_battery reports the number of matching sensors.
# - sensor.devices_with_low_battery_list reports names and percentages.
# - The list sensor also exposes count, entities, and names attributes.
#
#:########################################################################################:#
template: template:
- sensor: - sensor:
- name: "Devices with low battery" - name: "Devices with low battery"
@@ -9,7 +46,7 @@ template:
{% if s.attributes.device_class == 'battery' %} {% if s.attributes.device_class == 'battery' %}
{% set st = s.state %} {% set st = s.state %}
{% if st not in ['unknown', 'unavailable', 'Ok'] %} {% if st not in ['unknown', 'unavailable', 'Ok'] %}
{% if st | int(-1) != -1 and (st | int(0)) <= 97 %} {% if st | int(-1) != -1 and (st | int(0)) <= 20 %}
{% set ns.c = ns.c + 1 %} {% set ns.c = ns.c + 1 %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@@ -37,7 +74,7 @@ template:
{% if s.attributes.device_class == 'battery' %} {% if s.attributes.device_class == 'battery' %}
{% set st = s.state %} {% set st = s.state %}
{% if st not in ['unknown', 'unavailable', 'Ok'] %} {% if st not in ['unknown', 'unavailable', 'Ok'] %}
{% if st | int(-1) != -1 and (st | int(0)) <= 97 %} {% if st | int(-1) != -1 and (st | int(0)) <= 20 %}
{% set ns.names = ns.names + [s.name ~ ' (' ~ (st | int(0)) ~ '%)'] %} {% set ns.names = ns.names + [s.name ~ ' (' ~ (st | int(0)) ~ '%)'] %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@@ -56,7 +93,7 @@ template:
{% if s.attributes.device_class == 'battery' %} {% if s.attributes.device_class == 'battery' %}
{% set st = s.state %} {% set st = s.state %}
{% if st not in ['unknown', 'unavailable', 'Ok'] %} {% if st not in ['unknown', 'unavailable', 'Ok'] %}
{% if st | int(-1) != -1 and (st | int(0)) <= 97 %} {% if st | int(-1) != -1 and (st | int(0)) <= 20 %}
{% set ns.e = ns.e + [s.entity_id] %} {% set ns.e = ns.e + [s.entity_id] %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@@ -69,7 +106,7 @@ template:
{% if s.attributes.device_class == 'battery' %} {% if s.attributes.device_class == 'battery' %}
{% set st = s.state %} {% set st = s.state %}
{% if st not in ['unknown', 'unavailable', 'Ok'] %} {% if st not in ['unknown', 'unavailable', 'Ok'] %}
{% if st | int(-1) != -1 and (st | int(0)) <= 97 %} {% if st | int(-1) != -1 and (st | int(0)) <= 20 %}
{% set ns.n = ns.n + [s.name] %} {% set ns.n = ns.n + [s.name] %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@@ -0,0 +1,78 @@
template:
- sensor:
- name: "Devices with low battery"
unique_id: devices_with_low_battery_count
unit_of_measurement: "devices"
state: >
{% set ns = namespace(c=0) %}
{% for s in states.sensor %}
{% if s.attributes.device_class == 'battery' %}
{% set st = s.state %}
{% if st not in ['unknown', 'unavailable', 'Ok'] %}
{% if st | int(-1) != -1 and (st | int(0)) <= 97 %}
{% set ns.c = ns.c + 1 %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{{ ns.c }}
icon: >
{% if this.state | int(0) == 0 %}
mdi:check-circle
{% else %}
mdi:battery-alert
{% endif %}
- name: "Devices with low battery list"
unique_id: devices_with_low_battery_list
icon: >
{% if states('sensor.devices_with_low_battery') | int(0) == 0 %}
mdi:check-circle
{% else %}
mdi:battery-alert
{% endif %}
state: >
{% set ns = namespace(names=[]) %}
{% for s in states.sensor %}
{% if s.attributes.device_class == 'battery' %}
{% set st = s.state %}
{% if st not in ['unknown', 'unavailable', 'Ok'] %}
{% if st | int(-1) != -1 and (st | int(0)) <= 97 %}
{% set ns.names = ns.names + [s.name ~ ' (' ~ (st | int(0)) ~ '%)'] %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% if ns.names | length == 0 %}
None
{% else %}
{{ ns.names | join(', ') }}
{% endif %}
attributes:
count: "{{ states('sensor.devices_with_low_battery') | int(0) }}"
entities: >
{% set ns = namespace(e=[]) %}
{% for s in states.sensor %}
{% if s.attributes.device_class == 'battery' %}
{% set st = s.state %}
{% if st not in ['unknown', 'unavailable', 'Ok'] %}
{% if st | int(-1) != -1 and (st | int(0)) <= 97 %}
{% set ns.e = ns.e + [s.entity_id] %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{{ ns.e }}
names: >
{% set ns = namespace(n=[]) %}
{% for s in states.sensor %}
{% if s.attributes.device_class == 'battery' %}
{% set st = s.state %}
{% if st not in ['unknown', 'unavailable', 'Ok'] %}
{% if st | int(-1) != -1 and (st | int(0)) <= 97 %}
{% set ns.n = ns.n + [s.name] %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{{ ns.n }}
+47 -1
View File
@@ -1,7 +1,52 @@
#:########################################################################################:#
# Main Sony TV Automations Package #
#:########################################################################################:#
#
# TITLE:
# Main Sony TV Automations
#
# FILE:
# packages/main_sony_tv_automations.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured documentation and automation descriptions.
#
# V1.0
# - Initial MQTT TV-off and surround-amplifier following automations.
#
# PURPOSE:
# Accepts an MQTT command to turn off the lounge TV and keeps the loft
# surround-amplifier power synchronized with the TV remote state.
#
# MQTT COMMAND:
# Topic:
# viewroad-commands/maintv/action
#
# Payload:
# OFF
#
# The payload is uppercase and this package does not provide an MQTT ON action.
#
# AMPLIFIER FOLLOWING:
# - remote.lounge_tv is the source-of-truth state for the amplifier.
# - The remote state must remain on or off for five seconds before action.
# - Restart mode cancels the previous wait when another state change occurs,
# preventing brief transitions from toggling amplifier power.
#
# DEPENDENCIES:
# - remote.lounge_tv controls and reports the Sony lounge TV state.
# - switch.tv_surround_amp_power_in_loft_x27pp controls amplifier power.
#
#:########################################################################################:#
automation: automation:
- id: "1669966515993" - id: "1669966515993"
alias: Turn off Lounge TV alias: Turn off Lounge TV
description: "" description: "Turns off the lounge TV when the MQTT OFF command is received."
trigger: trigger:
- platform: mqtt - platform: mqtt
topic: viewroad-commands/maintv/action topic: viewroad-commands/maintv/action
@@ -16,6 +61,7 @@ automation:
- id: tv_amp_follow_remote_state - id: tv_amp_follow_remote_state
alias: Lounge surround amp follows TV remote (5s debounce) alias: Lounge surround amp follows TV remote (5s debounce)
description: "Follows the stable lounge TV remote state after a five-second debounce."
mode: restart mode: restart
trigger: trigger:
- platform: state - platform: state
+69 -1
View File
@@ -1,4 +1,72 @@
# === Add friendly names, icons, and area for printer controls === #:########################################################################################:#
# Moonraker 3D Printer Package #
#:########################################################################################:#
#
# TITLE:
# Moonraker 3D Printer
#
# FILE:
# packages/moonraker_3dprinter.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured documentation for setup, polling, outputs, and safety.
# - Recorded that the Creality printer is not currently connected.
#
# V1.0
# - Initial Moonraker REST sensors, commands, and customizations.
#
# PURPOSE:
# Reads Klipper and Moonraker printer data and provides Home Assistant REST
# commands for controlling a Creality K1C 3D printer.
#
# CURRENT STATUS:
# - As of 2026-07-20, this configuration no longer connects to the printer.
# - It is retained as a reference for future reconnection work.
# - Before reconnecting, verify the printer address, Moonraker availability,
# queried Klipper object names, and companion template entities.
#
# DEPENDENCIES:
# - A reachable Moonraker server for the Klipper printer.
# - Current configured endpoint: http://192.168.2.31:7125
# - Companion templates: templates/moonraker_3dprinter.yaml
# - The queried sensors and object names must match the Klipper configuration.
#
# POLLING:
# - Full printer status, printer info, and server data poll every second.
# - Current print file metadata polls every five seconds.
#
# RAW REST OUTPUTS:
# - sensor.printer_3d_sensor provides printer object status attributes.
# - sensor.printer_3d_info provides printer state and state message.
# - sensor.printer_3d_server provides Mainsail server configuration data.
# - sensor.printer_3d_file_metadata provides current-file metadata.
# - Companion templates derive user-facing sensors from these raw entities.
#
# CONTROLS:
# - Emergency stop immediately halts the printer.
# - Firmware restart restarts the Klipper firmware process.
# - Cancel stops the current print; pause and resume control print progress.
#
# SAFETY AND NETWORK:
# - Emergency stop, firmware restart, and cancel are disruptive actions and
# should only be exposed through dashboard controls with confirmation.
# - The configured endpoint uses unencrypted HTTP without authentication and
# assumes Moonraker is available only on a trusted local network.
#
# USER CONFIGURATION:
# - If the printer address changes, update every Moonraker URL in this file.
# - Confirm the filament and chamber sensor object names before reconnecting.
#
#:########################################################################################:#
#:########################################################################################:#
# Home Assistant Customizations #
#:########################################################################################:#
homeassistant: homeassistant:
customize: customize:
rest_command.3d_printer_emergency_stop: rest_command.3d_printer_emergency_stop:
+56 -3
View File
@@ -1,3 +1,49 @@
#:########################################################################################:#
# Office Media Buttons Package #
#:########################################################################################:#
#
# TITLE:
# Office Media Buttons
#
# FILE:
# packages/office_media_buttons.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured documentation and automation descriptions.
# - Identified the active ZHA implementation and disabled alternatives.
#
# V1.0
# - Initial office media-button automations.
#
# PURPOSE:
# Controls office TV playback from a Zigbee media button using direct ZHA
# click events.
#
# ACTIVE BUTTON MAPPING:
# - Single press pauses playback.
# - Double press starts or resumes playback.
# - Triple press seeks backward by 30 seconds.
#
# DEPENDENCIES:
# - ZHA event source: device IEEE 00:15:8d:00:06:79:46:c8.
# - media_player.office_tv provides the current playback position.
# - The media actions target the office TV device registered in Home Assistant.
#
# NOTES:
# - seek_amount is not normally provided by the event and defaults to -30.
# - Commented MQTT and entity-state implementations below are disabled
# historical alternatives retained for reference.
#
#:########################################################################################:#
#:########################################################################################:#
# Historical Disabled MQTT Sensor #
#:########################################################################################:#
#mqtt: #mqtt:
# sensor: # sensor:
# - unique_id: office_media_button_1 # - unique_id: office_media_button_1
@@ -6,10 +52,14 @@
# unit_of_measurement: "Press" # unit_of_measurement: "Press"
# value_template: "{{ value_json.ZbReceived.Office_Media_Button.Power }}" # value_template: "{{ value_json.ZbReceived.Office_Media_Button.Power }}"
#:########################################################################################:#
# Active ZHA Automations #
#:########################################################################################:#
automation: automation:
- id: pause_office_tv_on_media_button - id: pause_office_tv_on_media_button
alias: Pause Office TV on Media Button alias: Pause Office TV on Media Button
description: "" description: "Pauses the office TV when the media button is pressed once."
trigger: trigger:
- platform: event - platform: event
event_type: zha_event event_type: zha_event
@@ -26,7 +76,7 @@ automation:
mode: single mode: single
- id: play_office_tv_on_media_button - id: play_office_tv_on_media_button
alias: Play Office TV on Media Button alias: Play Office TV on Media Button
description: "" description: "Starts or resumes office TV playback when the media button is pressed twice."
trigger: trigger:
- platform: event - platform: event
event_type: zha_event event_type: zha_event
@@ -43,7 +93,7 @@ automation:
mode: single mode: single
- id: seek_office_tv_on_media_button - id: seek_office_tv_on_media_button
alias: Seek Office TV on Media Button alias: Seek Office TV on Media Button
description: "" description: "Seeks office TV playback backward 30 seconds when the media button is pressed three times."
trigger: trigger:
- platform: event - platform: event
event_type: zha_event event_type: zha_event
@@ -62,6 +112,8 @@ automation:
target: target:
device_id: abb6b5a6b4e4925dcb3a77ea2c293eaa device_id: abb6b5a6b4e4925dcb3a77ea2c293eaa
mode: single mode: single
# Historical disabled MQTT and entity-state alternatives.
# - id: "1629271273958" # - id: "1629271273958"
# alias: Pause office TV on MQTT # alias: Pause office TV on MQTT
# description: "" # description: ""
@@ -90,6 +142,7 @@ automation:
# seek_position: 30 # seek_position: 30
# mode: single # mode: single
# Historical disabled entity-state automation block.
#automation: #automation:
# - id: "1629271273952" # - id: "1629271273952"
# unique_id: pause_office_tv_on_media_button # unique_id: pause_office_tv_on_media_button
+5 -2
View File
@@ -3,6 +3,9 @@
############################################################################### ###############################################################################
# #
# Version: # Version:
# 2026-07-20 v0.3
# - Synchronized the documented Number 16 schedule with the implementation.
#
# 2026-05-09 v0.2 # 2026-05-09 v0.2
# - Refactored scheduled control to use editable schedule lists. # - Refactored scheduled control to use editable schedule lists.
# - Switched lights now use explicit ON/OFF schedule entries instead of # - Switched lights now use explicit ON/OFF schedule entries instead of
@@ -527,8 +530,8 @@ script:
# EDIT SCHEDULE HERE # EDIT SCHEDULE HERE
# Format: trigger, offset_minutes/at, target_brightness, ramp_minutes # Format: trigger, offset_minutes/at, target_brightness, ramp_minutes
# Current schedule: # Current schedule:
# - sunset -30, 80, 30 # - sunset -30, 60, 30
# - 20:00, 50, 30 # - 20:00, 50, 120
# - 01:00, 20, 120 # - 01:00, 20, 120
# - 06:00, 0, 120 # - 06:00, 0, 120
########################################################################### ###########################################################################
+34
View File
@@ -24,3 +24,37 @@ mqtt:
name: "Hours Since DePooped" name: "Hours Since DePooped"
state_topic: "viewroad-tele/petfeeding/hoursSinceDePooped" state_topic: "viewroad-tele/petfeeding/hoursSinceDePooped"
unit_of_measurement: "Hours" unit_of_measurement: "Hours"
template:
- sensor:
- name: "Jobs Tracker Hours Since Dog Fed"
unique_id: "jobs_tracker_hours_since_dog_fed"
device_class: duration
state_class: measurement
unit_of_measurement: "h"
icon: "mdi:dog-side"
availability: >-
{{
state_attr('sensor.jobs_tracker_dog_feeding_morning', 'hours_since_completed') is not none
or state_attr('sensor.jobs_tracker_dog_feeding_evening', 'hours_since_completed') is not none
}}
state: >-
{{
[
state_attr('sensor.jobs_tracker_dog_feeding_morning', 'hours_since_completed') | float(999999),
state_attr('sensor.jobs_tracker_dog_feeding_evening', 'hours_since_completed') | float(999999)
]
| min
| round(0)
}}
- name: "Jobs Tracker Hours Since Dog Depooped"
unique_id: "jobs_tracker_hours_since_dog_depooped"
device_class: duration
state_class: measurement
unit_of_measurement: "h"
icon: "mdi:emoticon-poop"
availability: >-
{{ state_attr('sensor.jobs_tracker_dog_depooping', 'hours_since_completed') is not none }}
state: >-
{{ state_attr('sensor.jobs_tracker_dog_depooping', 'hours_since_completed') | float(none) }}
+26
View File
@@ -0,0 +1,26 @@
mqtt:
sensor:
- unique_id: dog_fed_activity
name: "Dog Fed"
state_topic: "viewroad-status/activityfeed/dogfed"
icon: mdi:dog
- unique_id: depooped_activity
name: "DePooped"
state_topic: "viewroad-status/activityfeed/depooped"
icon: mdi:emoticon-poop
- unique_id: jobs_done_activity
name: "Jobs Done"
state_topic: "viewroad-status/activityfeed/jobsdone"
icon: mdi:notebook
- unique_id: hours_since_jobs_done
name: "Hours Since Jobs Done"
state_topic: "viewroad-tele/petfeeding/hoursSinceJobsDone"
unit_of_measurement: "Hours"
- unique_id: hours_since_zorro_fed
name: "Hours Since Zorro Fed"
state_topic: "viewroad-tele/petfeeding/hoursSinceDogFed"
unit_of_measurement: "Hours"
- unique_id: hours_since_depooped
name: "Hours Since DePooped"
state_topic: "viewroad-tele/petfeeding/hoursSinceDePooped"
unit_of_measurement: "Hours"
+19 -15
View File
@@ -5,7 +5,17 @@
# TITLE: # TITLE:
# Quiet Time # Quiet Time
# #
# VERSIONS: # FILE:
# quiet_time.yaml
#
# VERSION:
# V1.4 2026-07-20
#
# VERSION HISTORY:
# V1.4 2026-07-20
# - Updated documentation for the standalone Quiet Time actions package.
# - Documented the current flattened MQTT status topic.
#
# V1.3 2026-06-07 # V1.3 2026-06-07
# - Added quiet time start and stop entity action lists. # - Added quiet time start and stop entity action lists.
# - Turns the LED matrix display OFF when quiet time starts. # - Turns the LED matrix display OFF when quiet time starts.
@@ -13,7 +23,8 @@
# #
# V1.2 2026-05-21 # V1.2 2026-05-21
# - Added MQTT publishing when input_boolean.quiet_time changes. # - Added MQTT publishing when input_boolean.quiet_time changes.
# - Publishes quiet_time state to viewroad-status/homeassistant/quiet-time. # - Published quiet_time state to viewroad-status/homeassistant/quiet-time.
# This was the historical topic; the current topic is documented below.
# #
# V1.1 2026-05-21 # V1.1 2026-05-21
# - Reduced daily reset check frequency from every minute to every 30 minutes. # - Reduced daily reset check frequency from every minute to every 30 minutes.
@@ -33,20 +44,13 @@
# will automatically be turned OFF. # will automatically be turned OFF.
# - Default reset time is 07:00. # - Default reset time is 07:00.
# - The quiet_time state is published to MQTT whenever it changes. # - The quiet_time state is published to MQTT whenever it changes.
# - When quiet_time changes, editable entity lists can turn things on or off. # - The companion package handles local actions when quiet_time changes.
# #
# QUIET TIME ACTION LISTS: # COMPANION PACKAGE:
# - quiet_time_start_turn_off_entities: # - quiet_time_on_off_actions.yaml owns the editable entity action lists and
# Entities to turn OFF when quiet time starts. # other local actions that run when Quiet Time starts or ends.
# # - This package owns input_boolean.quiet_time, the daily reset behaviour,
# - quiet_time_start_turn_on_entities: # and MQTT status publishing.
# Entities to turn ON when quiet time starts.
#
# - quiet_time_stop_turn_off_entities:
# Entities to turn OFF when quiet time ends.
#
# - quiet_time_stop_turn_on_entities:
# Entities to turn ON when quiet time ends.
# #
# MQTT STATUS: # MQTT STATUS:
# - Topic: # - Topic:
+64
View File
@@ -1,3 +1,67 @@
#:########################################################################################:#
# Raspberry Pi CCTV Monitor Package #
#:########################################################################################:#
#
# TITLE:
# Raspberry Pi CCTV Monitor
#
# FILE:
# packages/raspberry_pi_monitor.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured documentation for MQTT, availability, and controls.
#
# V1.0
# - Initial monitoring and remote-control configuration.
#
# PURPOSE:
# Monitors the cctvquad1 and cctvquad2 Raspberry Pi hosts and provides remote
# reboot and shutdown controls through MQTT.
#
# EXTERNAL DEPENDENCY:
# - Each Raspberry Pi requires an external process that publishes telemetry
# and state, consumes command topics, and performs the requested actions.
# - This package does not install or manage that external process.
#
# MQTT STATUS:
# Topic pattern:
# viewroad-status/rpis/<host>/<field>
#
# Fields:
# cpu-temp, cpu-use, ram-use, disk-use, uptime, last-seen, ipv4-address,
# reboot, and shutdown.
#
# The last-seen payload must be a timestamp that Home Assistant can parse with
# as_timestamp().
#
# MQTT COMMANDS:
# Topic pattern:
# viewroad-commands/rpis/<host>/reboot/set
# viewroad-commands/rpis/<host>/shutdown/set
#
# Commands use the default MQTT switch ON/OFF payloads, QoS 1, and are not
# retained. The external process must publish matching switch state feedback.
#
# AVAILABILITY:
# - A host is considered available when its last-seen timestamp is valid and
# no more than 180 seconds old.
# - The template uses now(), so Home Assistant periodically re-evaluates age.
#
# GROUPS:
# - group.pi_cctvquad1_on collects Quad1 telemetry and controls.
# - group.pi_cctvquad2_on collects Quad2 telemetry and controls.
#
# SAFETY:
# - Reboot and shutdown interrupt CCTV services and host availability.
# - Shutdown may require physical access to power the host back on.
# - Dashboard controls should require confirmation before sending commands.
#
#:########################################################################################:#
mqtt: mqtt:
sensor: sensor:
- unique_id: cctvquad1_cpu_temp - unique_id: cctvquad1_cpu_temp
+58 -7
View File
@@ -1,9 +1,55 @@
########################################################################################## ##########################################################################################
# MASTER BEDROOM FAN (Tasmota / Sonoff iFan02) # Room Fan Control
# Improvements: ##########################################################################################
# - Numeric speed entity (0-3) reflecting actual device state via MQTT #
# - Button to cycle speed 1,2,3,0 # TITLE:
# - Keep input_select in sync with actual FanSpeed (incl after reboots) # Room Fan Control
#
# FILE:
# packages/room_fan_control.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured documentation for all three bedroom fans.
# - Documented the master-bedroom feedback loop and command-only controls.
#
# V1.0
# - Initial Tasmota and Sonoff iFan02 fan controls.
#
# PURPOSE:
# Controls the master-bedroom, Bedroom 2, and Bedroom 3 ceiling-fan speeds
# through Tasmota MQTT commands and Home Assistant dropdown helpers.
#
# SPEED MAPPING:
# - 0 = Off
# - 1 = Low
# - 2 = Medium
# - 3 = High
#
# MASTER BEDROOM:
# - Queries FanSpeed when Home Assistant starts.
# - Listens to Tasmota RESULT and STATE topics for device feedback.
# - Synchronizes the numeric and dropdown helpers with actual device state.
# - Uses optimistic local updates until MQTT feedback corrects the helpers.
# - Provides a button that cycles through speeds 1, 2, 3, and 0.
#
# BEDROOMS 2 AND 3:
# - Dropdown changes publish FanSpeed commands to each Tasmota device.
# - These controls are command-only and do not synchronize from feedback.
# - Their displayed dropdown state may not reflect physical or external changes.
#
# MQTT COMMAND TOPICS:
# - Master bedroom: cmnd/tasmo-ifan02-3793-bedrm1-1/FanSpeed
# - Bedroom 2: cmnd/tasmo-ifan02-7042-bedrm2/FanSpeed
# - Bedroom 3: cmnd/tasmo-ifan02-3497-bedrm3/FanSpeed
#
# DEPENDENCIES:
# - The three Tasmota devices must accept FanSpeed values from 0 through 3.
# - Master-bedroom feedback uses its RESULT and STATE MQTT topics.
#
########################################################################################## ##########################################################################################
input_select: input_select:
@@ -75,6 +121,7 @@ automation:
- id: master_bedroom_fan_query_on_ha_start - id: master_bedroom_fan_query_on_ha_start
initial_state: true initial_state: true
alias: Master Bedroom Fan - Query FanSpeed on HA Start alias: Master Bedroom Fan - Query FanSpeed on HA Start
description: "Requests the current master-bedroom FanSpeed when Home Assistant starts."
trigger: trigger:
- platform: homeassistant - platform: homeassistant
event: start event: start
@@ -90,6 +137,7 @@ automation:
- id: master_bedroom_fan_sync_from_mqtt - id: master_bedroom_fan_sync_from_mqtt
initial_state: true initial_state: true
alias: Master Bedroom Fan - Sync Helpers From MQTT FanSpeed alias: Master Bedroom Fan - Sync Helpers From MQTT FanSpeed
description: "Synchronizes the master-bedroom fan helpers from Tasmota MQTT feedback."
trigger: trigger:
- platform: mqtt - platform: mqtt
topic: stat/tasmo-ifan02-3793-bedrm1-1/RESULT topic: stat/tasmo-ifan02-3793-bedrm1-1/RESULT
@@ -122,6 +170,7 @@ automation:
- id: set_the_master_bedroom_fan - id: set_the_master_bedroom_fan
initial_state: true initial_state: true
alias: Set the Master Bedroom Fan alias: Set the Master Bedroom Fan
description: "Publishes master-bedroom fan speed changes and updates the numeric helper optimistically."
trigger: trigger:
- platform: state - platform: state
entity_id: input_select.master_bedroom_fan_set entity_id: input_select.master_bedroom_fan_set
@@ -145,11 +194,12 @@ automation:
value: "{{ desired }}" value: "{{ desired }}"
######################################################################################## ########################################################################################
# BEDROOM 2 FAN - Unchanged # BEDROOM 2 FAN - Command Only
######################################################################################## ########################################################################################
- id: set_bedroom_2_fan - id: set_bedroom_2_fan
initial_state: true initial_state: true
alias: Set Bedroom 2 Fan Speed alias: Set Bedroom 2 Fan Speed
description: "Publishes Bedroom 2 fan speed dropdown changes to Tasmota."
trigger: trigger:
entity_id: input_select.bedroom_2_fan_set entity_id: input_select.bedroom_2_fan_set
platform: state platform: state
@@ -163,11 +213,12 @@ automation:
' '
######################################################################################## ########################################################################################
# BEDROOM 3 FAN - Unchanged # BEDROOM 3 FAN - Command Only
######################################################################################## ########################################################################################
- id: set_bedroom_3_fan - id: set_bedroom_3_fan
initial_state: true initial_state: true
alias: Set Bedroom 3 Fan Speed alias: Set Bedroom 3 Fan Speed
description: "Publishes Bedroom 3 fan speed dropdown changes to Tasmota."
trigger: trigger:
entity_id: input_select.bedroom_3_fan_set entity_id: input_select.bedroom_3_fan_set
platform: state platform: state
+4 -3
View File
@@ -1,7 +1,8 @@
input_boolean: input_boolean:
quiet_time: # Legacy duplicate retained temporarily for verification.
name: Quiet time for no notifications # quiet_time:
icon: mdi:shield-moon # name: Quiet time for no notifications
# icon: mdi:shield-moon
away_occupied_routine: away_occupied_routine:
name: Automation for Lights etc when away name: Automation for Lights etc when away
icon: mdi:shield-lock icon: mdi:shield-lock
+51
View File
@@ -1,3 +1,52 @@
#:########################################################################################:#
# Main Bathroom Shower Detection Package #
#:########################################################################################:#
#
# TITLE:
# Main Bathroom Shower Detection
#
# FILE:
# packages/shower_controls.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added structured documentation and automation descriptions.
# - Documented current indicator-only usage.
#
# V1.0
# - Initial humidity-rate shower detection.
#
# PURPOSE:
# Detects shower use from the main-bathroom humidity level and its rate of
# change, then maintains input_boolean.main_bathroom_shower as an indicator.
#
# DEPENDENCY:
# sensor.main_bathroom_environment_zth10_humidity_2 provides humidity in %.
#
# DERIVATIVE SENSOR:
# - Calculates humidity change in % per minute over a 15-minute time window.
# - Rounds the result to 0.1.
#
# DETECTION:
# - Humidity change must remain above 0.6 %/min for five minutes.
# - Current humidity must also be above 63%.
#
# CLEARING:
# - Humidity change must remain below 0.2 %/min for 15 minutes.
# - No absolute-humidity condition is required to clear the indicator.
# - The gap between activation and clearing thresholds provides hysteresis
# and prevents rapid toggling near one threshold.
#
# CURRENT USE:
# - The package only maintains input_boolean.main_bathroom_shower.
# - No other user-YAML automation, script, or package currently consumes it.
# - This package does not directly control a bathroom fan or other device.
#
#:########################################################################################:#
input_boolean: input_boolean:
main_bathroom_shower: main_bathroom_shower:
name: Main Bathroom Shower name: Main Bathroom Shower
@@ -14,6 +63,7 @@ sensor:
automation: automation:
- id: main_bathroom_shower_detected - id: main_bathroom_shower_detected
alias: Main Bathroom - Shower detected (humidity rate + min humidity) alias: Main Bathroom - Shower detected (humidity rate + min humidity)
description: "Turns on the shower indicator after a sustained humidity rise above the minimum humidity."
mode: single mode: single
trigger: trigger:
- platform: numeric_state - platform: numeric_state
@@ -31,6 +81,7 @@ automation:
- id: main_bathroom_shower_cleared - id: main_bathroom_shower_cleared
alias: Main Bathroom - Shower cleared (humidity rate) alias: Main Bathroom - Shower cleared (humidity rate)
description: "Turns off the shower indicator after the humidity change rate remains low for 15 minutes."
mode: single mode: single
trigger: trigger:
- platform: numeric_state - platform: numeric_state
+54 -1
View File
@@ -1,8 +1,61 @@
#:########################################################################################:#
# Auckland Council Waste Collection Package #
#:########################################################################################:#
#
# TITLE:
# Auckland Council Waste Collection
#
# FILE:
# packages/waste_collection.yaml
#
# VERSION:
# V1.1 2026-07-20
#
# VERSION HISTORY:
# V1.1 2026-07-20
# - Added source setup, schedule, MQTT, and maintenance documentation.
#
# V1.0
# - Initial Auckland Council schedules and MQTT bin-status sensors.
#
# PURPOSE:
# Provides Auckland Council rubbish, recycling, and food-waste collection
# schedules, plus independent MQTT sensors indicating whether bins are out.
#
# DEPENDENCY:
# Requires the Waste Collection Schedule custom integration and its
# aucklandcouncil_govt_nz source.
#
# AREA NUMBER SETUP:
# - Open the Auckland Council rubbish and recycling collection-day finder.
# - Select the property address.
# - Use the displayed assessment number as area_number below.
# - Source documentation:
# https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/aucklandcouncil_govt_nz.md
#
# SCHEDULE SENSORS:
# - Types are rubbish, recycle, and food-waste.
# - Each sensor returns one upcoming collection with a one-day lead time.
# - details_format is upcoming and add_days_to adds relative-day text.
#
# MQTT BIN-OUT SENSORS:
# - These sensors are independent of the council collection schedules.
# - An external publisher must send status to the configured MQTT topics.
# - Payloads remain raw sensor strings such as "true"; these are not binary
# sensor entities and no boolean conversion is performed here.
#
# CURRENT STATUS:
# - As of 2026-07-20, the rubbish schedule resolves correctly.
# - Recycling and food-waste report unknown; review the source type names when
# investigating those schedules.
#
#:########################################################################################:#
waste_collection_schedule: waste_collection_schedule:
sources: sources:
- name: aucklandcouncil_govt_nz - name: aucklandcouncil_govt_nz
args: args:
area_number: 12344403722 # see 'How to get the source argument below' area_number: 12344403722 # Auckland Council assessment number.
sensor: sensor:
- platform: waste_collection_schedule - platform: waste_collection_schedule