From 0ee97c923d5fefd0bd744ca1af21588fd11159f1 Mon Sep 17 00:00:00 2001 From: Carlo Costanzo <2160436+CCOSTAN@users.noreply.github.com> Date: Tue, 14 Apr 2026 17:28:08 -0400 Subject: [PATCH] [codex] HA YAML DRY cleanup - move joanna_send_telegram into config/script - deduplicate Shutdown Helper light automation - remove the duplicate Color Tornado action - update package docs for the shared Telegram helper --- config/automation/color_tornado.yaml | 19 ++-- config/automation/garage_entry_light.yaml | 50 +++------- config/automation/kitchen_helper_light.yaml | 27 ++++++ .../automation/zwave_hallway_door_sensor.yaml | 23 ----- config/packages/README.md | 2 +- config/packages/telegram_bot.yaml | 84 +---------------- config/script/joanna_send_telegram.yaml | 92 +++++++++++++++++++ 7 files changed, 144 insertions(+), 153 deletions(-) create mode 100644 config/automation/kitchen_helper_light.yaml delete mode 100755 config/automation/zwave_hallway_door_sensor.yaml create mode 100644 config/script/joanna_send_telegram.yaml diff --git a/config/automation/color_tornado.yaml b/config/automation/color_tornado.yaml index 3e0c4c29..c55b0cad 100755 --- a/config/automation/color_tornado.yaml +++ b/config/automation/color_tornado.yaml @@ -1,13 +1,20 @@ ###################################################################### -## Color Tornado! +# @CCOSTAN - Follow Me on X +# For more info visit https://www.vcloudinfo.com/click-here +# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig +# ------------------------------------------------------------------- +# Color Tornado - Trigger Justin Go color loop +# Starts the Hue colorloop effect and immediately resets the helper toggle. +# ------------------------------------------------------------------- ###################################################################### -- alias: 'Color Tornado' + +- alias: Color Tornado id: f6e89034-b3e6-4951-9cea-7d7053b30857 trigger: - platform: state entity_id: input_boolean.color_tornado - to: 'on' from: 'off' + to: 'on' action: - service: light.turn_on @@ -16,11 +23,5 @@ data: effect: colorloop - - service: light.turn_on - entity_id: - - light.justin_go - data: - effect: colorloop - - service: input_boolean.turn_off entity_id: input_boolean.color_tornado diff --git a/config/automation/garage_entry_light.yaml b/config/automation/garage_entry_light.yaml index b204b48a..e181c02a 100755 --- a/config/automation/garage_entry_light.yaml +++ b/config/automation/garage_entry_light.yaml @@ -1,18 +1,18 @@ -# https://www.vcloudinfo.com/click-here -# Garage lighting automations below are associated with door sensors and lights in the garage entryway. -# The garage doors themselves are controlled by Garadget (see packages/garadget.yaml). -# For related device and hardware info, see README and config/packages/garadget.yaml. +###################################################################### +# @CCOSTAN - Follow Me on X +# For more info visit https://www.vcloudinfo.com/click-here +# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig +# ------------------------------------------------------------------- +# Garage Entry Lights - Hallway helper automations for the garage entry +# Turns the garage hallway helper on when the entry opens and back off after it closes. +# ------------------------------------------------------------------- +# Notes: Garage doors themselves are managed in config/packages/garadget.yaml. +###################################################################### - - -############################################################## - alias: Garage Light Hallway Helper OPEN id: 5ea2a2b5-e3de-4acd-823c-dac3eeaa6118 trigger: - # - platform: state - # entity_id: binary_sensor.kitchen_door - # to: 'on' - platform: state entity_id: binary_sensor.mcu1_gpio12 to: 'on' @@ -25,9 +25,8 @@ action: - service: light.turn_on entity_id: - - light.garage_hallway + - light.garage_hallway -############################################################## - alias: Garage Light Hallway Helper Closed id: f6060cd7-add7-487f-9b2b-f7849db3b36d mode: restart @@ -38,19 +37,11 @@ to: 'off' for: seconds: 15 - # - platform: state - # entity_id: binary_sensor.kitchen_door - # to: 'off' - # for: - # seconds: 15 condition: - condition: state entity_id: binary_sensor.mcu1_gpio12 state: 'off' - # - condition: state - # entity_id: binary_sensor.kitchen_door - # state: 'off' - condition: state entity_id: light.garage_hallway state: 'on' @@ -58,22 +49,3 @@ action: - service: light.turn_off entity_id: light.garage_hallway - -############################################################## -- alias: Shutdown Helper light - id: 124f95f6-78ca-4c22-9348-1f3a1da2d803 - - trigger: - - platform: state - entity_id: light.k4 - to: 'on' - for: '00:20:00' - - condition: - condition: state - entity_id: light.k1 - state: 'off' - - action: - - service: light.turn_off - entity_id: light.k4 diff --git a/config/automation/kitchen_helper_light.yaml b/config/automation/kitchen_helper_light.yaml new file mode 100644 index 00000000..264c9658 --- /dev/null +++ b/config/automation/kitchen_helper_light.yaml @@ -0,0 +1,27 @@ +###################################################################### +# @CCOSTAN - Follow Me on X +# For more info visit https://www.vcloudinfo.com/click-here +# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig +# ------------------------------------------------------------------- +# Kitchen Helper Light - Turn off helper after the main light stays off +# Powers down `light.k4` after 20 minutes only when `light.k1` remains off. +# ------------------------------------------------------------------- +###################################################################### + +- alias: Shutdown Helper light + id: 124f95f6-78ca-4c22-9348-1f3a1da2d803 + + trigger: + - platform: state + entity_id: light.k4 + to: 'on' + for: '00:20:00' + + condition: + condition: state + entity_id: light.k1 + state: 'off' + + action: + - service: light.turn_off + entity_id: light.k4 diff --git a/config/automation/zwave_hallway_door_sensor.yaml b/config/automation/zwave_hallway_door_sensor.yaml deleted file mode 100755 index 0f593ed0..00000000 --- a/config/automation/zwave_hallway_door_sensor.yaml +++ /dev/null @@ -1,23 +0,0 @@ -################################### -## ZWave Section - -## Home Assistant runs on my [Raspberry Pi 3](https://amzn.to/2e3DOBY) with [Aeon Labs Z Wave Stick (GEN 5)](https://amzn.to/2eAiAP0). -################################### - -############################################################## -- alias: Shutdown Helper light - id: e3f4beff-4fa8-42e3-be5a-32b45106ac8a - - trigger: - - platform: state - entity_id: light.k4 - to: 'on' - for: '00:20:00' - - condition: - condition: state - entity_id: light.k1 - state: 'off' - - action: - - service: light.turn_off - entity_id: light.k4 diff --git a/config/packages/README.md b/config/packages/README.md index 836161ed..68c88839 100755 --- a/config/packages/README.md +++ b/config/packages/README.md @@ -54,7 +54,7 @@ Live collection of plug-and-play Home Assistant packages. Each YAML file in this | [mariadb.yaml](mariadb.yaml) | MariaDB recorder health and capacity SQL sensors. | `sensor.mariadb_status`, `sensor.database_size` | | [tugtainer_updates.yaml](tugtainer_updates.yaml) | Tugtainer container update notifications via webhook + persistent alerts, plus event-based Joanna dispatch when reports include `### Available:` (24h cooldown via `mode: single` + delay, no new helpers). | `persistent_notification.create`, `event: tugtainer_available_detected`, `script.joanna_dispatch`, `input_datetime.tugtainer_last_update` | | [bearclaw.yaml](bearclaw.yaml) | Joanna/BearClaw bridge automations that forward Telegram commands to codex_appliance, include LLM-first routing context for freeform text, relay replies back, ingest `/api/bearclaw/status` telemetry, and expose dispatch plus QMD/memory-index sensors for Infrastructure dashboards. | `rest_command.bearclaw_*`, `sensor.bearclaw_status_telemetry`, `sensor.joanna_*`, `binary_sensor.joanna_*`, `automation.bearclaw_*`, `script.send_to_logbook` | -| [telegram_bot.yaml](telegram_bot.yaml) | Telegram script wrappers used by BearClaw and other ops flows (UI config remains source of truth; wrappers work with polling or webhook transport). | `script.joanna_send_telegram`, `telegram_bot.send_message` | +| [telegram_bot.yaml](telegram_bot.yaml) | Telegram transport package for BearClaw and other ops flows; the shared `joanna_send_telegram` helper now lives under `config/script/`. | `telegram_bot.send_message`, `script.joanna_send_telegram` | | [phynplus.yaml](phynplus.yaml) | Phyn shutoff automations with push + Activity feed + Repairs issues for leak events. | `valve.phyn_shutoff_valve`, `binary_sensor.phyn_leak_test_running`, `repairs.create` | | [water_delivery.yaml](water_delivery.yaml) | ReadyRefresh delivery date helper with night-before + garage door Alexa reminders, plus helper-change audit logging and Telegram confirmations. | `input_datetime.water_delivery_date`, `script.send_to_logbook`, `script.joanna_send_telegram`, `notify.alexa_media_garage` | | [vacation_mode.yaml](vacation_mode.yaml) | Auto-enable vacation mode after 24 hours away or no bed use, track sitter analytics/secure-house checks, and deliver Chromecast-first vacation briefings with a garage Alexa welcome. | `input_boolean.vacation_mode`, `input_boolean.house_sitter_present`, `sensor.vacation_house_sitter_*`, `group.garage_doors`, `lock.front_door`, `script.notify_engine`, `script.joanna_send_telegram` | diff --git a/config/packages/telegram_bot.yaml b/config/packages/telegram_bot.yaml index c3006707..86a79487 100644 --- a/config/packages/telegram_bot.yaml +++ b/config/packages/telegram_bot.yaml @@ -7,89 +7,11 @@ # Script wrappers for Telegram messaging using UI-configured integration. # ------------------------------------------------------------------- # Notes: Do not add `telegram_bot:` YAML here; integration is UI-only. +# Notes: Shared helper `script.joanna_send_telegram` lives in config/script/joanna_send_telegram.yaml. # Notes: Joanna transport defaults to plain_text, but can opt into HTML when the appliance provides a vetted rich message. # Notes: Keep Skills logic in docker_17/codex_appliance; this package is delivery/transport only. # Notes: HA Core 2026.4 webhook support is optional; service-call wrappers remain compatible with polling or webhook transport. ###################################################################### -script: - joanna_send_telegram: - alias: Joanna Send Telegram - description: Sends resilient plain-text Telegram messages with chunking + fallback. - mode: queued - fields: - message: - description: Message body to send. - example: Joanna is online. - parse_mode: - description: Telegram parse mode (`plain_text` or `html`). - example: html - disable_web_page_preview: - description: Whether Telegram should suppress web page previews. - example: true - sequence: - - variables: - chunk_size: 3400 - requested_parse_mode: >- - {% set raw = parse_mode | default('plain_text', true) | string | lower | trim %} - {% if raw in ['html', 'plain_text'] %} - {{ raw }} - {% else %} - plain_text - {% endif %} - preview_disabled: "{{ disable_web_page_preview | default(true, true) }}" - normalized_message: >- - {% set raw = message | default('', true) | string %} - {{ raw | replace('\r\n', '\n') | replace('\r', '\n') | trim }} - safe_message: >- - {% if normalized_message | length > 0 %} - {{ normalized_message }} - {% else %} - Joanna: (empty message) - {% endif %} - total_chunks: >- - {% set size = chunk_size | int(3400) %} - {% set length = safe_message | length %} - {{ ((length + size - 1) // size) if length > 0 else 1 }} - - repeat: - count: "{{ total_chunks | int(1) }}" - sequence: - - variables: - start: "{{ ((repeat.index | int(1)) - 1) * (chunk_size | int(3400)) }}" - stop: "{{ start + (chunk_size | int(3400)) }}" - chunk_body: "{{ safe_message[start:stop] }}" - chunk_message: >- - {% if (total_chunks | int(1)) > 1 %} - [{{ repeat.index }}/{{ total_chunks }}] - {{ chunk_body }} - {% else %} - {{ chunk_body }} - {% endif %} - fallback_message: >- - {{ chunk_message - | regex_replace(find='[\x00-\x08\x0B\x0C\x0E-\x1F]', replace=' ') - | trim }} - telegram_send_response: null - - action: telegram_bot.send_message - continue_on_error: true - data: - chat_id: !secret telegram_allowed_chat_id_carlo - message: "{{ chunk_message }}" - parse_mode: "{{ requested_parse_mode }}" - disable_web_page_preview: "{{ preview_disabled }}" - response_variable: telegram_send_response - - choose: - - conditions: - - condition: template - value_template: >- - {{ telegram_send_response is none - or telegram_send_response.chats is not defined - or (telegram_send_response.chats | count) == 0 }} - sequence: - - action: telegram_bot.send_message - continue_on_error: true - data: - chat_id: !secret telegram_allowed_chat_id_carlo - message: "{{ fallback_message if fallback_message | length > 0 else 'Joanna: message delivery fallback (content omitted)' }}" - parse_mode: plain_text - disable_web_page_preview: "{{ preview_disabled }}" +{} + diff --git a/config/script/joanna_send_telegram.yaml b/config/script/joanna_send_telegram.yaml new file mode 100644 index 00000000..95334445 --- /dev/null +++ b/config/script/joanna_send_telegram.yaml @@ -0,0 +1,92 @@ +###################################################################### +# @CCOSTAN - Follow Me on X +# For more info visit https://www.vcloudinfo.com/click-here +# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig +# ------------------------------------------------------------------- +# Joanna Send Telegram - Shared Telegram delivery helper +# Chunks long messages, sends Telegram replies, and falls back to plain text when needed. +# ------------------------------------------------------------------- +# Notes: Shared helper moved out of packages so cross-file callers resolve from config/script. +# Notes: Keep Joanna/BearClaw decision logic in docker_17/codex_appliance; this script only delivers messages. +###################################################################### + +joanna_send_telegram: + alias: Joanna Send Telegram + description: Sends resilient Telegram messages with chunking and plain-text fallback. + mode: queued + fields: + message: + description: Message body to send. + example: Joanna is online. + parse_mode: + description: Telegram parse mode (`plain_text` or `html`). + example: html + disable_web_page_preview: + description: Whether Telegram should suppress web page previews. + example: true + sequence: + - variables: + chunk_size: 3400 + requested_parse_mode: >- + {% set raw = parse_mode | default('plain_text', true) | string | lower | trim %} + {% if raw in ['html', 'plain_text'] %} + {{ raw }} + {% else %} + plain_text + {% endif %} + preview_disabled: "{{ disable_web_page_preview | default(true, true) }}" + normalized_message: >- + {% set raw = message | default('', true) | string %} + {{ raw | replace('\r\n', '\n') | replace('\r', '\n') | trim }} + safe_message: >- + {% if normalized_message | length > 0 %} + {{ normalized_message }} + {% else %} + Joanna: (empty message) + {% endif %} + total_chunks: >- + {% set size = chunk_size | int(3400) %} + {% set length = safe_message | length %} + {{ ((length + size - 1) // size) if length > 0 else 1 }} + - repeat: + count: "{{ total_chunks | int(1) }}" + sequence: + - variables: + start: "{{ ((repeat.index | int(1)) - 1) * (chunk_size | int(3400)) }}" + stop: "{{ start + (chunk_size | int(3400)) }}" + chunk_body: "{{ safe_message[start:stop] }}" + chunk_message: >- + {% if (total_chunks | int(1)) > 1 %} + [{{ repeat.index }}/{{ total_chunks }}] + {{ chunk_body }} + {% else %} + {{ chunk_body }} + {% endif %} + fallback_message: >- + {{ chunk_message + | regex_replace(find='[\x00-\x08\x0B\x0C\x0E-\x1F]', replace=' ') + | trim }} + telegram_send_response: null + - service: telegram_bot.send_message + continue_on_error: true + data: + chat_id: !secret telegram_allowed_chat_id_carlo + message: "{{ chunk_message }}" + parse_mode: "{{ requested_parse_mode }}" + disable_web_page_preview: "{{ preview_disabled }}" + response_variable: telegram_send_response + - choose: + - conditions: + - condition: template + value_template: >- + {{ telegram_send_response is none + or telegram_send_response.chats is not defined + or (telegram_send_response.chats | count) == 0 }} + sequence: + - service: telegram_bot.send_message + continue_on_error: true + data: + chat_id: !secret telegram_allowed_chat_id_carlo + message: "{{ fallback_message if fallback_message | length > 0 else 'Joanna: message delivery fallback (content omitted)' }}" + parse_mode: plain_text + disable_web_page_preview: "{{ preview_disabled }}"