Closed tetsuo13 closed 1 year ago
One approach that was tried:
Ultimately this approach was abandoned due to complexity and, more importantly, too many failures that were difficult to debug or resolve -- sometimes the camera snapshot would stop creating the image file, sometimes it wouldn't write to /tmp
even though it was listed in allowlist_external_dirs
, often the scp
command failed, restarting Home Assistant sometimes resolved the issue on its own, etc.. There is also the configuration and maintenance on the public web site side. If any of these parts fail for any reason then the end result Android notification is either not sent or is sent without any image.
The WIP code is documented below for future reference or for anyone in the community that could benefit from seeing it.
configuration.yaml
:
shell_command: !include components/shell_commands.yaml
logger:
default: warning
logs:
homeassistant.components.shell_command: debug
components/shell_commands.yaml
(new file):
upload_image_for_companion_notification: /usr/bin/scp -v -i /config/id_rsa -C -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "{{ file_path }}" user@public-web-site:/home/user
# Delete all files in the camera snapshots directory older than specified.
clean_tmp: /usr/bin/find /config/www/tmp -maxdepth 1 -mtime +{{ days_threshold }} -type f -delete -print
automation/motion.yaml
:
- alias: Motion - Send Camera Snapshot Notification On Motion
trigger:
- platform: state
entity_id: binary_sensor.office_motion_alarm
to: "on"
variables:
camera_name: camera.office_main
- platform: state
entity_id: binary_sensor.laundry_motion_alarm
to: "on"
variables:
camera_name: camera.laundry_main
variables:
snapshot_filename: snapshot_{{ camera_name }}-{{ now().strftime("%Y%m%d-%H%M%S.%f") }}.jpg
snapshot_absolute_path: www/tmp/{{ snapshot_filename }}
action:
- delay:
seconds: 4
- service: camera.snapshot
data:
entity_id: "{{ camera_name }}"
filename: "{{ snapshot_absolute_path }}"
- service: shell_command.upload_image_for_companion_notification
data:
file_path: "{{ snapshot_absolute_path }}"
- service: notify_mobile_apps
data:
title: Camera Motion Detected
message: "{{ trigger.to_state.name }}"
data:
image: https://public-web-site/{{ snapshot_filename }}
automation/system.yaml
(new file). An automation takes care of deleting older files so that the disk doesn't fill up. These files are really only needed for a brief instant to send the Android notification so perhaps it should be run with a smaller threshold.
- alias: System - Clean Up Temp Directory Periodically
id: system_clean_up_temp_directory_periodically
description: >
Daily delete of all temp files older than 4 days.
trigger:
- platform: time
at: "05:27:18"
action:
- service: shell_command.clean_tmp
data:
days_threshold: 4
Trying another approach: use a public URL to access saved camera snapshots. I was reluctant to go with this approach initially as I don't like exposing Home Assistant to the public Internet. I might document the approach I took in doing so however I'm using a reverse proxy to expose just a single directory of Home Assistant, www/images/snapshots
, and only allowing requests for JPGs, everything else is rejected. I can use country block lists to restrict to just the country I'm living in, fail2ban to block repeated attempts to probe for files; there's a whole slew of tools to add on top of the reverse proxy to help mitigate attacks all the while keeping the Home Assistant setup simple (still a primary goal of mine).
Sending a notification with a camera snapshot works as expected so long as the target mobile app is on the same network as Home Assistant. When it isn't then the snapshot isn't shown.
The automation uses https://companion.home-assistant.io/docs/notifications/notification-attachments/#automatic-snapshots for Android.
Reference links used during initial development of automation: