Package Delivery Monitor - I made a thing!

If one thing winds our dog up it’s people ringing the doorbell and then walking away. He doesn’t mind if they wait and come in, but when they walk off, cue bark central. So to combat this I decided to combine all of my hobby skills (home automation, CNC machining and electronics) into a single project for the first time and make a quiet way for delivery drivers to alert us that they have left a package in the porch. I present - Package Monitor:


Features:

  • Laser-cut and engraved multi-layer housing
  • ESP32 & ESPHome powered
  • Single button user interface (press for delivery, hold to reset)
  • Visual and audio confirmation cues for set and reset
  • Ring camera snapshot taken on activation
  • Mobile app notification with snapshot
  • Mobile app reset action

Housing

The body is made of 4 layers of 5mm plyboard (basswood or similar) which can easily be cut with the 10W laser on my Snapmaker Artisan. Each layer is cut to allow space for the components and wiring, then the top layer is engraved with the instructions. Then the electronics are installed and the whole thing glued together. If anyone would like the SVG stencils for the cuts/engraving, message me.




Electronics

Parts:

  • ESP 32 Mini
  • Momentary Push Button
  • Green LED
  • Active Piezo Buzzer
  • 270 Ohm Resistor

Nothing too fancy here. The button sits between a GPIO and Ground, the buzzer between a GPIO and Ground and the LED in series with the resistor between another GPIO and ground. I powered it with a USB cable as I had one with a long tail hanging around, if I did it again I’d probably use some bell-wire straight to the terminals as it’s a lot thinner and less obtrusive. Using the USB does give me a failsafe if the WiFi ever changes however, as getting the ESP32 out of the housing is impossible once glued!

Software
ESPHome Config:

esphome:
  name: package-monitor
  friendly_name: package-monitor

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "<<REDACTED>>"

ota:
  password: "<<REDACTED>>"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  domain: .lan

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Package-Monitor Fallback Hotspot"
    password: "<<REDACTED>>"

time:
- platform: homeassistant
  id: my_time
    
output:
  - platform: gpio
    pin: GPIO32
    id: led
  - platform: gpio
    pin: GPIO25
    id: buzzer


globals:
   - id: cool_down_timestamp
     type: int
     restore_value: no
     initial_value: '0'

script:
- id: buzzer_set
  then:
    - output.turn_on: buzzer
    - delay: 100ms
    - output.turn_off: buzzer
    - delay: 50ms
    - output.turn_on: buzzer
    - delay: 100ms
    - output.turn_off: buzzer
    - delay: 50ms
- id: buzzer_reset
  then: 
    - output.turn_on: buzzer
    - delay: 300ms
    - output.turn_off: buzzer

light:
  - platform: binary
    id: package_waiting
    name: "Package Waiting"
    output: led
    icon: mdi:package-variant-closed

number:
  platform: template
  icon: mdi:package-variant-closed
  id: package_count
  name: "Package Waiting Count"
  step: 1
  min_value: 0
  max_value: 1000
  optimistic: true

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO33
      mode:
        input: true
        pullup: true
      inverted: true
    id: button
    filters:
      - delayed_on: 50ms
    on_press:
      then: 
        - if:
            condition: 
              lambda: |-
                return (id(cool_down_timestamp) < (millis() - 5000));
            then:
              - lambda: |-
                  id(cool_down_timestamp) = millis();
              - output.turn_on: led
              - script.execute: buzzer_set
              - delay: 2s
              - if:
                  condition:
                    binary_sensor.is_on: button
                  then: 
                    - light.turn_off: package_waiting
                    - script.execute: buzzer_reset
                    - logger.log: "Indicator Reset"
                    - number.to_min: package_count
                  else:
                    - light.turn_on: package_waiting
                    - logger.log: "Package Waiting"
                    - number.increment: package_count
                 

Notification Automation:

alias: PMON
description: ""
trigger:
  - platform: state
    entity_id:
      - number.package_monitor_package_waiting_count
condition:
  - condition: numeric_state
    entity_id: number.package_monitor_package_waiting_count
    above: 0
action:
  - service: button.press
    data: {}
    target:
      entity_id: button.take_snapshot
  - delay:
      hours: 0
      minutes: 0
      seconds: 2
      milliseconds: 0
  - service: camera.snapshot
    data:
      filename: /config/www/tmp/snapshot_package.jpg
    target:
      device_id: 16f2f3732f512cd6c293fec3bf8ca5f1
  - service: notify.mobile_app_iphone
    data:
      title: A package has been delivered
      data:
        attachment:
          url: /local/tmp/snapshot_package.jpg
          content_type: JPEG
        actions:
          - action: pmon_reset
            title: Reset
      message: >-
        There are {{ states('number.package_monitor_package_waiting_count') |
        int }} packages waiting in the porch.
mode: single

Reset Automation:

alias: PMON Reset Notification
description: ""
trigger:
  - platform: event
    event_type: mobile_app_notification_action
    event_data:
      action: pmon_reset
condition: []
action:
  - service: light.turn_off
    data: {}
    target:
      entity_id: light.package_monitor_package_waiting
  - service: number.set_value
    data:
      value: "0"
    target:
      entity_id: number.package_monitor_package_waiting_count
mode: single

If you want to re-create this and need info on any of the parts/design - happy to help!

Thanks for reading.

6 Likes

Amazing! :+1:t2:

1 Like

It looks pretty nice. However, wouldn’t the delivery guy ringing the doorbell have sufficed?

Please re-read the first paragraph of the first post to understand the motivation for creating a ‘silent’ delivery notification mechanism. :wink:

4 Likes