Skip to content

Commit 8df520c

Browse files
authored
Merge PR #1639: Migrate docker_monitored_containers to modern Group integration
Migrate docker_monitored_containers to modern Group integration
2 parents 401f26d + 9155d0e commit 8df520c

13 files changed

Lines changed: 347 additions & 83 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ hacs
7070
alexa_media
7171
custom_components
7272
config/www/community
73+
config/.cache/brands/integrations/
7374
community
7475
image
7576
tts
@@ -80,3 +81,4 @@ panel-notes
8081
docker_14
8182
docker_69
8283
.codex_tmp/
84+

config/dashboards/infrastructure/partials/docker_containers_sections.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,10 @@
194194
card_param: cards
195195
filter:
196196
include:
197-
- group: group.docker_monitored_containers
197+
- group: switch.docker_monitored_containers
198198
options:
199199
type: custom:button-card
200200
template: bearstone_infra_container_row
201201
icon: mdi:docker
202202
sort:
203203
method: name
204-

config/dashboards/infrastructure/partials/home_sections.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@
449449
card_param: cards
450450
filter:
451451
include:
452-
- group: group.docker_monitored_containers
452+
- group: switch.docker_monitored_containers
453453
options:
454454
type: custom:button-card
455455
template: bearstone_infra_container_row
@@ -636,4 +636,3 @@
636636
name: Download
637637
- entity: sensor.speedtest_upload
638638
name: Upload
639-

config/dashboards/infrastructure/templates/button_card_templates.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ bearstone_infra_container_row:
614614
}
615615
const switchEntity = key ? `switch.${key}_container` : '';
616616
const switchEntityAlt = key ? `switch.${key}_container_2` : '';
617-
const monitored = states['group.docker_monitored_containers']?.attributes?.entity_id || [];
617+
const monitored = states['switch.docker_monitored_containers']?.attributes?.entity_id || [];
618618
const restartCandidates = key ? [
619619
`button.${key}_restart_container`,
620620
`button.${key}_restart_container_2`,

config/packages/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Live collection of plug-and-play Home Assistant packages. Each YAML file in this
5959
| [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` |
6060
| [maintenance_log.yaml](maintenance_log.yaml) | Joanna maintenance webhook ingest for water softener salt with idempotent event handling, Activity feed logging, and recorder-backed helper history for long-term graphing. | `automation.maintenance_log_joanna_webhook_ingest`, `input_number.water_softener_salt_total_added_lb`, `counter.water_softener_salt_event_count`, `sensor.water_softener_salt_days_since_last_add` |
6161
| [powerwall.yaml](powerwall.yaml) | Track Tesla Powerwall grid status and shed loads automatically when off-grid (alerts include Activity feed + Repairs). | `binary_sensor.powerwall_grid_status`, `sensor.powerwall_*`, `repairs.create` |
62+
| [tesla_model_y.yaml](tesla_model_y.yaml) | Remind the garage and parents to plug in the Model Y after low-battery arrivals and after 8 PM when it is home but not charging. | `sensor.spaceship_battery_level`, `switch.spaceship_charge`, `notify.alexa_media_garage`, `script.notify_engine` |
6263
| [vacuum.yaml](vacuum.yaml) | Dreame vacuum orchestration with room tracking, push alerts, Activity feed, Repairs issues on errors, and Alexa one-off room-clean switches. | `input_select.l10s_vacuum_phase`, `sensor.l10s_vacuum_error`, `repairs.create` |
6364
| [hass_agent_homepc.yaml](hass_agent_homepc.yaml) | Mirrors PC lock/unlock state from HASS.Agent to the office lamp for instant desk presence cues. | `sensor.carlo_homepc_carlo_homepc_sessionstate`, `switch.office_lamp_switch` |
6465
| [sleepiq.yaml](sleepiq.yaml) | Sleep Number presence/snore automations; Overview Health consumes direct SleepIQ integration entities for scores, vitals, pressure, and bed controls. | `sensor.sleepnumber_carlo_carlo_sleep_score`, `sensor.sleepnumber_carlo_stacey_sleep_score`, `number.sleepnumber_carlo_carlo_firmness`, `select.sleepnumber_carlo_foundation_preset_right` |

config/packages/bearclaw.yaml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,15 @@ automation:
383383
action:
384384
- variables:
385385
message: "{{ trigger.json.message | default('Joanna: empty reply') }}"
386+
telegram_message: "{{ trigger.json.telegram_message | default(message, true) }}"
387+
telegram_parse_mode: >-
388+
{% set raw = trigger.json.telegram_parse_mode | default('plain_text', true) | string | lower | trim %}
389+
{% if raw in ['html', 'plain_text'] %}
390+
{{ raw }}
391+
{% else %}
392+
plain_text
393+
{% endif %}
394+
telegram_disable_preview: "{{ trigger.json.disable_web_page_preview | default(true, true) }}"
386395
level: "{{ trigger.json.level | default('active') | lower }}"
387396
inline_keyboard_payload: >-
388397
{% set kb = trigger.json.inline_keyboard if trigger.json.inline_keyboard is defined else none %}
@@ -408,14 +417,16 @@ automation:
408417
- service: telegram_bot.send_message
409418
data:
410419
chat_id: !secret telegram_allowed_chat_id_carlo
411-
message: "{{ message }}"
412-
parse_mode: plain_text
413-
disable_web_page_preview: true
420+
message: "{{ telegram_message }}"
421+
parse_mode: "{{ telegram_parse_mode }}"
422+
disable_web_page_preview: "{{ telegram_disable_preview }}"
414423
inline_keyboard: "{{ inline_keyboard_payload }}"
415424
default:
416425
- service: script.joanna_send_telegram
417426
data:
418-
message: "{{ message }}"
427+
message: "{{ telegram_message }}"
428+
parse_mode: "{{ telegram_parse_mode }}"
429+
disable_web_page_preview: "{{ telegram_disable_preview }}"
419430
- service: script.send_to_logbook
420431
data:
421432
topic: JOANNA

config/packages/docker_infrastructure.yaml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
55
# -------------------------------------------------------------------
66
# Docker Infrastructure - Host patching and container alerts
7+
# Related Issue: 1632, 1584
78
# APT webhook results (docker_10/14/17/69) and container down repairs.
89
# -------------------------------------------------------------------
9-
# Related Issue: 1584
1010
# Notes: Hosts run weekly Wed 12:00 APT job and POST JSON to webhooks.
1111
# Notes: Reboots are handled directly on each host by apt_weekly.sh.
1212
# Notes: Reboot staggering: docker_14 first, docker_69 second, docker_10 third.
@@ -66,9 +66,10 @@ input_text:
6666
name: "docker_69 APT last result"
6767
max: 255
6868

69-
group:
70-
docker_monitored_containers:
69+
switch:
70+
- platform: group
7171
name: Docker Monitored Containers
72+
unique_id: docker_monitored_containers
7273
entities:
7374
- switch.cloudflared_kch_container
7475
- switch.cloudflared_wp_container
@@ -206,14 +207,14 @@ template:
206207
unique_id: docker_monitored_container_count
207208
icon: mdi:format-list-numbered
208209
state: >-
209-
{{ state_attr('group.docker_monitored_containers', 'entity_id') | default([], true) | count }}
210+
{{ state_attr('switch.docker_monitored_containers', 'entity_id') | default([], true) | count }}
210211
211212
- name: "Docker Monitored Unavailable Count"
212213
unique_id: docker_monitored_unavailable_count
213214
icon: mdi:lan-disconnect
214215
state: >-
215216
{% set ns = namespace(keys=[], unavailable=0) %}
216-
{% set monitored = state_attr('group.docker_monitored_containers', 'entity_id') | default([], true) %}
217+
{% set monitored = state_attr('switch.docker_monitored_containers', 'entity_id') | default([], true) %}
217218
{% for switch_entity in monitored %}
218219
{% set key = switch_entity | replace('switch.', '') | regex_replace('_container(?:_2)?$', '') %}
219220
{% if key not in ns.keys %}
@@ -257,7 +258,7 @@ template:
257258
icon: mdi:docker
258259
state: >-
259260
{% set ns = namespace(keys=[], down=[]) %}
260-
{% set monitored = state_attr('group.docker_monitored_containers', 'entity_id') | default([], true) | list %}
261+
{% set monitored = state_attr('switch.docker_monitored_containers', 'entity_id') | default([], true) | list %}
261262
{% set telemetry_degraded = is_state('binary_sensor.docker_container_telemetry_degraded', 'on') %}
262263
{% for switch_entity in monitored %}
263264
{% set key = switch_entity | replace('switch.', '') | regex_replace('_container(?:_2)?$', '') %}
@@ -301,7 +302,7 @@ template:
301302
attributes:
302303
down_containers: >-
303304
{% set ns = namespace(keys=[], down=[]) %}
304-
{% set monitored = state_attr('group.docker_monitored_containers', 'entity_id') | default([], true) | list %}
305+
{% set monitored = state_attr('switch.docker_monitored_containers', 'entity_id') | default([], true) | list %}
305306
{% set telemetry_degraded = is_state('binary_sensor.docker_container_telemetry_degraded', 'on') %}
306307
{% for switch_entity in monitored %}
307308
{% set key = switch_entity | replace('switch.', '') | regex_replace('_container(?:_2)?$', '') %}
@@ -437,7 +438,7 @@ script:
437438
status_entity_alt: "binary_sensor.{{ container_key }}_status_2"
438439
state_entity: "sensor.{{ container_key }}_state"
439440
state_entity_alt: "sensor.{{ container_key }}_state_2"
440-
monitored_switches: "{{ state_attr('group.docker_monitored_containers', 'entity_id') | default([], true) }}"
441+
monitored_switches: "{{ state_attr('switch.docker_monitored_containers', 'entity_id') | default([], true) }}"
441442
tracked_container: "{{ switch_entity in monitored_switches or switch_entity_alt in monitored_switches }}"
442443
effective_entity: >-
443444
{% if expand(status_entity) | count > 0 %}
@@ -798,7 +799,7 @@ automation:
798799
entity_id: "{{ trigger.event.data.entity_id | default('') }}"
799800
old_state: "{{ (trigger.event.data.old_state.state if trigger.event.data.old_state is not none else '') | lower }}"
800801
new_state: "{{ (trigger.event.data.new_state.state if trigger.event.data.new_state is not none else '') | lower }}"
801-
monitored_switches: "{{ state_attr('group.docker_monitored_containers', 'entity_id') | default([], true) | list }}"
802+
monitored_switches: "{{ state_attr('switch.docker_monitored_containers', 'entity_id') | default([], true) | list }}"
802803
is_monitored_container_event: >-
803804
{% set ent = entity_id %}
804805
{% if ent.startswith('switch.') and (ent.endswith('_container') or ent.endswith('_container_2')) %}
@@ -888,7 +889,7 @@ automation:
888889
minutes: "/55"
889890
action:
890891
- variables:
891-
monitored_switches: "{{ state_attr('group.docker_monitored_containers', 'entity_id') | default([], true) | list }}"
892+
monitored_switches: "{{ state_attr('switch.docker_monitored_containers', 'entity_id') | default([], true) | list }}"
892893
- repeat:
893894
for_each: "{{ monitored_switches }}"
894895
sequence:

config/packages/garadget.yaml

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -330,13 +330,8 @@ automation:
330330

331331
trigger:
332332
- platform: time_pattern
333-
minutes: '/45'
334-
- platform: state
335-
entity_id:
336-
- cover.large_garage_door
337-
- cover.small_garage_door
338-
to: 'open'
339-
for: "00:01:00"
333+
minutes: '/30'
334+
340335
- platform: state
341336
entity_id: group.family
342337
to: not_home
@@ -392,46 +387,3 @@ automation:
392387
- service: script.speech_engine
393388
data:
394389
value1: "Check the garage doors. The Small garage is {{ states('cover.small_garage_door')}} and the large garage is {{ states('cover.large_garage_door')}} [Always mention the specific garage door that is currently open and remind us to close it for the night]"
395-
396-
# - alias: 'Garage Camera on Alexa Shows'
397-
# id: 4373df2a-77f2-4e19-be7c-46c7b27ca583
398-
# mode: single
399-
# trigger:
400-
# - platform: state
401-
# entity_id:
402-
# - cover.large_garage_door
403-
# - cover.small_garage_door
404-
# from: 'closed'
405-
# to: 'open'
406-
# for: "00:00:15"
407-
408-
# - platform: state
409-
# entity_id: binary_sensor.mcu1_gpio12 #interior Garage Doors
410-
# from: 'off'
411-
# to: 'on'
412-
# for: "00:00:05"
413-
414-
# - platform: state
415-
# entity_id:
416-
# - person.carlo
417-
# - person.stacey
418-
# - person.paige
419-
# - person.justin
420-
# to: 'not_home'
421-
# from: 'home'
422-
423-
# action:
424-
# - service: media_player.play_media
425-
# target:
426-
# entity_id: media_player.kitchen
427-
# data:
428-
# media_content_id: 'show garage camera from home assistant'
429-
# media_content_type: custom
430-
# - delay: '00:20:00'
431-
# - service: media_player.play_media
432-
# target:
433-
# entity_id: media_player.kitchen
434-
# data:
435-
# media_content_id: 'hide garage camera'
436-
# media_content_type: custom
437-

config/packages/llmvision.yaml

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# Trigger with input_button.llmvision_garbage_check, input_button.llmvision_front_door_package_check, or front door person activity to update vision-backed package sensors.
88
# -------------------------------------------------------------------
99
# Notes: LLMVision analyzes camera.garagecam; expects strict "on"/"off" output.
10-
# Notes: Front-door package detection runs 3 minutes after `sensor.frontdoorbell_person_active_count_2` goes above 0.
10+
# Notes: Front-door package detection waits 3 minutes after person activity or 20 seconds after the front door relocks, then analyzes a short live stream for better package accuracy.
1111
# Docs: https://llmvision.gitbook.io/getting-started/usage/image-analyzer
1212
######################################################################
1313

@@ -129,30 +129,79 @@ automation:
129129
- platform: numeric_state
130130
entity_id: sensor.frontdoorbell_person_active_count_2
131131
above: 0
132-
for: "00:03:00"
133132
id: person_count
133+
- platform: state
134+
entity_id: lock.front_door
135+
from: unlocked
136+
to: locked
137+
id: front_door_locked
134138
- platform: state
135139
entity_id: input_button.llmvision_front_door_package_check
136140
id: manual_check
137141
variables:
142+
trigger_source: >-
143+
{% if trigger.id == 'manual_check' %}
144+
manual button
145+
{% elif trigger.id == 'front_door_locked' %}
146+
front door relock
147+
{% else %}
148+
front door person activity
149+
{% endif %}
138150
prompt_text: >-
139-
Examine the front door camera image for delivery packages. Focus only on boxes, padded envelopes,
140-
or shopping bags left on the porch or by the front door. If one or more packages are clearly visible,
141-
respond exactly: on. If no packages are clearly visible, respond exactly: off. No other words.
151+
Examine these front door camera frames for delivery packages. Focus on the porch and doorstep area
152+
near the wall and doormat in the lower-right part of the image. Treat cardboard boxes, padded mailers,
153+
poly bags, and shopping bags as packages. Ignore the street, cars, landscaping, and anything not resting
154+
on the porch or doorstep. If any package is clearly visible, respond exactly: on. If no package is
155+
clearly visible, respond exactly: off. No other words.
142156
action:
143-
- service: llmvision.data_analyzer
157+
- choose:
158+
- conditions:
159+
- condition: template
160+
value_template: "{{ trigger.id == 'person_count' }}"
161+
sequence:
162+
- delay: "00:03:00"
163+
- conditions:
164+
- condition: template
165+
value_template: "{{ trigger.id == 'front_door_locked' }}"
166+
sequence:
167+
- delay: "00:00:20"
168+
- service: llmvision.stream_analyzer
144169
response_variable: llmvision_result
145170
data:
146171
provider: !secret llmvision_provider_entry
147-
model: gpt-4.1-nano
172+
model: gpt-4.1-mini
148173
message: "{{ prompt_text }}"
149-
sensor_entity: input_boolean.front_door_packages_present
150174
image_entity:
151175
- camera.frontdoorbell
176+
duration: 6
177+
max_frames: 5
152178
include_filename: false
153-
target_width: 1280
179+
target_width: 1920
154180
max_tokens: 16
155181
expose_images: true
182+
- variables:
183+
normalized_response: "{{ llmvision_result.response_text | default('') | trim | lower }}"
184+
- choose:
185+
- conditions:
186+
- condition: template
187+
value_template: >-
188+
{{ normalized_response in ['on', 'yes', 'true']
189+
or normalized_response.startswith('on')
190+
or normalized_response.startswith('yes') }}
191+
sequence:
192+
- service: input_boolean.turn_on
193+
target:
194+
entity_id: input_boolean.front_door_packages_present
195+
- conditions:
196+
- condition: template
197+
value_template: >-
198+
{{ normalized_response in ['off', 'no', 'false']
199+
or normalized_response.startswith('off')
200+
or normalized_response.startswith('no') }}
201+
sequence:
202+
- service: input_boolean.turn_off
203+
target:
204+
entity_id: input_boolean.front_door_packages_present
156205
- service: input_text.set_value
157206
target:
158207
entity_id: input_text.llmvision_front_door_last_response
@@ -181,7 +230,7 @@ automation:
181230
data:
182231
topic: PACKAGES
183232
message: >-
184-
Front door package vision check ran via {{ 'manual button' if trigger.id == 'manual_check' else 'front door person activity' }}
233+
Front door package vision check ran via {{ trigger_source }}
185234
and returned {{ llmvision_result.response_text | default(states('input_boolean.front_door_packages_present')) | lower }}.
186235
- choose:
187236
- conditions:

config/packages/telegram_bot.yaml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# Script wrappers for Telegram messaging using UI-configured integration.
88
# -------------------------------------------------------------------
99
# Notes: Do not add `telegram_bot:` YAML here; integration is UI-only.
10-
# Notes: Joanna transport sends as plain_text to avoid Telegram parse-entity failures.
10+
# Notes: Joanna transport defaults to plain_text, but can opt into HTML when the appliance provides a vetted rich message.
1111
# Notes: Keep Skills logic in docker_17/codex_appliance; this package is delivery/transport only.
1212
######################################################################
1313

@@ -20,9 +20,23 @@ script:
2020
message:
2121
description: Message body to send.
2222
example: Joanna is online.
23+
parse_mode:
24+
description: Telegram parse mode (`plain_text` or `html`).
25+
example: html
26+
disable_web_page_preview:
27+
description: Whether Telegram should suppress web page previews.
28+
example: true
2329
sequence:
2430
- variables:
2531
chunk_size: 3400
32+
requested_parse_mode: >-
33+
{% set raw = parse_mode | default('plain_text', true) | string | lower | trim %}
34+
{% if raw in ['html', 'plain_text'] %}
35+
{{ raw }}
36+
{% else %}
37+
plain_text
38+
{% endif %}
39+
preview_disabled: "{{ disable_web_page_preview | default(true, true) }}"
2640
normalized_message: >-
2741
{% set raw = message | default('', true) | string %}
2842
{{ raw | replace('\r\n', '\n') | replace('\r', '\n') | trim }}
@@ -60,8 +74,8 @@ script:
6074
data:
6175
chat_id: !secret telegram_allowed_chat_id_carlo
6276
message: "{{ chunk_message }}"
63-
parse_mode: plain_text
64-
disable_web_page_preview: true
77+
parse_mode: "{{ requested_parse_mode }}"
78+
disable_web_page_preview: "{{ preview_disabled }}"
6579
response_variable: telegram_send_response
6680
- choose:
6781
- conditions:
@@ -77,4 +91,4 @@ script:
7791
chat_id: !secret telegram_allowed_chat_id_carlo
7892
message: "{{ fallback_message if fallback_message | length > 0 else 'Joanna: message delivery fallback (content omitted)' }}"
7993
parse_mode: plain_text
80-
disable_web_page_preview: true
94+
disable_web_page_preview: "{{ preview_disabled }}"

0 commit comments

Comments
 (0)