tetsuo13 / home-assistant-config

Home Assistant configuration
MIT License
2 stars 0 forks source link

Camera snapshot notifications unavailable when Android device off local network #16

Closed tetsuo13 closed 1 year ago

tetsuo13 commented 1 year ago

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:

tetsuo13 commented 1 year ago

One approach that was tried:

  1. Generate camera snapshot image to a file.
  2. Upload the file to a public web server.
  3. Use URL from web server for notification attachment.

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
tetsuo13 commented 1 year ago

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).