This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revision | |||
| en:tech:videodoorbell [2022/11/10 20:06] – bullar | en:tech:videodoorbell [2026/08/12 13:40] (current) – claude | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Video Door Bell ====== | + | ====== Video Doorbell |
| - | Coming soon… | + | ===== Motivation ===== |
| + | |||
| + | Our //front door// sits in the outer wall of our property and is therefore several meters away from the actual house. So far we've used a proprietary wireless doorbell solution, but with only one receiver unit. With an L-shaped bungalow there' | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | On top of that, Thai delivery services show up at very flexible times, so you can't always be on-site. A smart wireless doorbell was therefore a strong wish of mine. The requirements can be summarized as follows: | ||
| + | * sturdy flush (in-wall) mounting | ||
| + | * glass or metal surface | ||
| + | * touch button as the bell button (wear-free) | ||
| + | * smart display (as a nameplate or with extra information) | ||
| + | * camera | ||
| + | * voice output (e.g. for instructions to the delivery driver) | ||
| + | * integration with [[https:// | ||
| + | |||
| + | ===== Ideas ===== | ||
| + | |||
| + | For this project I started the planning with the mechanics. Since I'll be walking past the new doorbell every day, the whole thing needs to look modern and nearly perfect so it doesn' | ||
| + | Browsing the internet turned up a good number of DIY variants (here' | ||
| + | * https:// | ||
| + | * https:// | ||
| + | * https:// | ||
| + | * https:// | ||
| + | |||
| + | The one I liked best in terms of mechanical design was the variant from [[https:// | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | ===== Solution ===== | ||
| + | |||
| + | As mentioned, looks play an important role in this project, so I start the planning with the mechanics. | ||
| + | |||
| + | The basis for a secure installation is a suitable flush-mount box. I found one at [[https:// | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | The control and viewing area will be glass, which we have cut to size by a local or online supplier: | ||
| + | * clear 2mm float glass, 121 x 84 mm (seamed edges, mitred corners) | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | The cover frame is made from two layers of 2mm milled aluminum, or comes out of the 3D printer/ | ||
| + | |||
| + | To make use of the mounting holes, we modify the empty box slightly by replacing the 4 corner mounting screws with 12mm long M3 hex standoffs. These are secured from below with M3 screws, leaving the M3 threads available for the cover frame. | ||
| + | |||
| + | The glass pane gets a printed foil applied to the back, which you can design freely. It' | ||
| + | * a rear-glass sticker, 90 x 127mm (permanent adhesive, 100µ transparent calendered vinyl foil, glossy, with full-surface white backing print). :!: //The final sticker is the same size as the glass, but the production process requires a 3mm margin.// | ||
| + | |||
| + | You can create the design template to scale in any vector design tool of your choice (I use [[https:// | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | :!: The foil must be ordered with full white backing print so it's also opaque, otherwise you'll see the frame skeleton underneath later. | ||
| + | |||
| + | Behind the red button is where the touch sensor will later sit; the rectangular cutout in the middle is for the display, and the holes at the top are for the camera and flashlight. Before applying the adhesive, the white areas still need to be cut out with a craft knife. | ||
| + | |||
| + | Once the foil arrives from the print shop, it's applied to the glass with a squeegee. The glass can then be fixed to the frame with a special glass adhesive or a suitable tape. I additionally sealed/ | ||
| + | |||
| + | The finished assembly meets my approval and motivates me to carry on... | ||
| + | |||
| + | |||
| + | ===== Hardware ===== | ||
| + | |||
| + | A look at the requirements list shows four functional units that need to be implemented: | ||
| + | * touch button | ||
| + | * smart display | ||
| + | * camera | ||
| + | * voice output | ||
| + | |||
| + | |||
| + | ==== Touch Button ==== | ||
| + | |||
| + | There are ready-made solutions that are entirely sufficient in our case. They mostly have a TTP223 chip onboard providing a capacitive sensor, with the sensor surface already on the PCB. The sensitivity is high enough to respond right through our glass pane. The output provides a digital signal for evaluation. | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | ==== Smart Display ==== | ||
| + | |||
| + | Because of the intense brightness here in Thailand, I avoid self-illuminating displays outdoors, even in shaded areas. That's what gave me the idea of using an e-paper display instead. There won't be rapid content changes, and readability (it also serves as the nameplate) is maintained even during a power outage. Here too there are ready-made solutions with a controller. The largest display that fits the housing is a 2.13 inch model from [[https:// | ||
| + | |||
| + | <WRAP group> | ||
| + | <WRAP half column> | ||
| + | {{ : | ||
| + | </ | ||
| + | <WRAP half column> | ||
| + | {{: | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | I went with the Raspberry Pi HAT variant, since its controller also has a cable connector, simplifying the wiring. | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== Camera ==== | ||
| + | |||
| + | Here too a ready-made solution does the job. The ESP32 CAM module offers a compact camera. We swap the lens for a wide-angle (160°) one with a longer connecting cable. That reduces the blind spot and gives us more mechanical freedom to place the lens further away from the module. | ||
| + | |||
| + | <WRAP group> | ||
| + | <WRAP half column> | ||
| + | {{ : | ||
| + | </ | ||
| + | <WRAP half column> | ||
| + | {{: | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | With this module we're also immediately on the home WiFi network and can use it to also control the other components, such as the touch button and sound. | ||
| + | |||
| + | |||
| + | |||
| + | ==== Voice Output ==== | ||
| + | |||
| + | One option for voice output is a synthetic solution, which would allow arbitrary text on the fly. But since the variety of text snippets needed here is manageable, I instead went the route of an MP3 player. The following compact module, the **DFPlayer Mini**, has everything we need: | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | It's also addressable via a serial interface, has an SD card slot for stored sound files, and can drive a 3W speaker directly. No need to design anything of our own here. To be able to easily call up the saved MP3 files later, I set up the following structure on the SD card: | ||
| + | |||
| + | < | ||
| + | / | ||
| + | /01/ (English) | ||
| + | 001.mp3 | ||
| + | 002.mp3 | ||
| + | 003.mp3 | ||
| + | 004.mp3 | ||
| + | /02/ (Thai) | ||
| + | 001.mp3 | ||
| + | 002.mp3 | ||
| + | 003.mp3 | ||
| + | 004.mp3 | ||
| + | </ | ||
| + | If you don't want to immortalize your own voice there, professional voice recordings in various languages are also available. | ||
| + | Worth a look here: [[https:// | ||
| + | |||
| + | For the speaker I'd already used the compact small speaker **LSM-S30K** in other projects. It fits perfectly here too. Thanks to the resonance chamber of the empty housing, the sound is full and loud enough even through the glass pane. I keep the volume well below max. | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | |||
| + | |||
| + | ==== Mechanics ==== | ||
| + | |||
| + | Before wiring up all the modules, let's first take a look at the inner mechanics. The empty housing has a lower level, 12mm deeper, that we can use to fix both the front and the control modules. A few experiments led to the following mount: | ||
| + | |||
| + | <WRAP group> | ||
| + | <WRAP half column> | ||
| + | {{ : | ||
| + | </ | ||
| + | <WRAP half column> | ||
| + | {{: | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | The 4 blocks house the neodymium magnets (∅ 6 mm) that hold the screw covers in place. The lower frame is for the touch sensor, the middle one for the display, and the top one for the wide-angle lens. Next to the slot for the touch button there' | ||
| + | For the underside we need a frame for the DFPlayer as well as the ESP32 CAM module. After 3D printing, both are glued to the back of the large frame; the hole for the FLASH LED is clearly visible. | ||
| + | |||
| + | Now all that's missing is the mount for the speaker (there' | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | The speaker can be plugged directly onto the middle frame. The power supply also fits there. As with the [[en: | ||
| + | |||
| + | Now we have a compact module that only needs to be connected to 230V and screwed to the empty housing with 4x M3 countersunk screws. | ||
| + | |||
| + | Everything for that needs to come out of the 3D printer: | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | |||
| + | ===== Wiring ===== | ||
| + | |||
| + | The number of free pins on the ESP32 CAM module is just barely enough to connect everything. However, we do have to give up the SD slot for that, and share the FLASH light with the display' | ||
| + | |||
| + | ^ DoorBell Function | ||
| + | | FLASH light / CS - Display | ||
| + | | RESET - Display | ||
| + | | SPI CLK - Display | ||
| + | | DC - Display | ||
| + | | SPI MOSI - Display | ||
| + | | BUSY - Display | ||
| + | | GND ^ GND ^ ^ GPIO16 | ||
| + | | 5V ^ 5V ^ ^ 3.3V | 3.3V | | ||
| + | |||
| + | Once everything is plugged/ | ||
| + | |||
| + | ===== Software ===== | ||
| + | |||
| + | No surprise here — ESPHome does the software work again. This time we don't even need any '' | ||
| + | |||
| + | ==== Touch Button ==== | ||
| + | |||
| + | The touch button becomes a simple binary sensor: | ||
| + | |||
| + | <code yaml> | ||
| + | binary_sensor: | ||
| + | - platform: gpio | ||
| + | pin: GPIO16 | ||
| + | name: "Ring Door" | ||
| + | id: ring_door_sensor | ||
| + | </ | ||
| + | |||
| + | ==== Display ==== | ||
| + | |||
| + | For the display we first need fonts and any special characters we want to use. Any TTF font can be used. The TTF files need to be copied to ''/ | ||
| + | |||
| + | <code yaml> | ||
| + | # e-paper display 250x122 (128) | ||
| + | font: | ||
| + | - file: ' | ||
| + | id: font_comic24 | ||
| + | size: 24 | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | Then the SPI interface and the remaining pins need to be assigned. The lambda function at the end lets you freely program the display contents. The available rendering functions can be found in the Home Assistant documentation under [[https:// | ||
| + | |||
| + | <code yaml> | ||
| + | spi: | ||
| + | clk_pin: GPIO14 | ||
| + | mosi_pin: GPIO13 | ||
| + | |||
| + | display: | ||
| + | - platform: waveshare_epaper | ||
| + | id: doorbell_display | ||
| + | cs_pin: GPIO33 | ||
| + | dc_pin: GPIO15 | ||
| + | busy_pin: GPIO12 | ||
| + | reset_pin: GPIO2 | ||
| + | model: 2.13in-ttgo-dke | ||
| + | full_update_every: | ||
| + | update_interval: | ||
| + | reset_duration: | ||
| + | rotation: 90 | ||
| + | auto_clear_enabled: | ||
| + | lambda: |- | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | Further up we also define a service for updating the display, so its contents can be redrawn on demand outside the normal schedule: | ||
| + | |||
| + | <code yaml> | ||
| + | services: | ||
| + | - service: update_display | ||
| + | then: | ||
| + | - component.update: | ||
| + | </ | ||
| + | |||
| + | ==== Camera ==== | ||
| + | |||
| + | For the camera, a maximum resolution of 800x600 proved to work well; higher resolutions didn't work for me. The CAM module' | ||
| + | |||
| + | <code yaml> | ||
| + | # doorbell camera | ||
| + | esp32_camera: | ||
| + | name: Doorbell_Cam | ||
| + | vertical_flip: | ||
| + | horizontal_mirror: | ||
| + | external_clock: | ||
| + | pin: GPIO0 | ||
| + | frequency: 20MHz | ||
| + | i2c_pins: | ||
| + | sda: GPIO26 | ||
| + | scl: GPIO27 | ||
| + | data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35] | ||
| + | vsync_pin: GPIO25 | ||
| + | href_pin: GPIO23 | ||
| + | pixel_clock_pin: | ||
| + | power_down_pin: | ||
| + | # | ||
| + | resolution: 800x600 | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | </ | ||
| + | |||
| + | |||
| + | To get control over the FLASH light too, we need to add it like this: | ||
| + | |||
| + | <code yaml> | ||
| + | output: | ||
| + | # | ||
| + | - platform: gpio | ||
| + | pin: GPIO4 | ||
| + | id: gpio_4 | ||
| + | |||
| + | light: | ||
| + | # | ||
| + | - platform: binary | ||
| + | output: gpio_4 | ||
| + | id: cam_flash | ||
| + | name: Doorbell Cam flash | ||
| + | </ | ||
| + | |||
| + | ==== DFPlayer ==== | ||
| + | |||
| + | The DFPlayer needs a serial interface for communication: | ||
| + | |||
| + | <code yaml> | ||
| + | # DF MP3 Player | ||
| + | uart: | ||
| + | tx_pin: GPIO1 | ||
| + | rx_pin: GPIO3 | ||
| + | baud_rate: 9600 | ||
| + | |||
| + | dfplayer: | ||
| + | on_finished_playback: | ||
| + | then: | ||
| + | logger.log: ' | ||
| + | </ | ||
| + | |||
| + | and a set of services: | ||
| + | |||
| + | <code yaml> | ||
| + | - service: dfplayer_play_folder | ||
| + | variables: | ||
| + | folder: int | ||
| + | file: int | ||
| + | then: | ||
| + | - dfplayer.play_folder: | ||
| + | folder: !lambda ' | ||
| + | file: !lambda ' | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | |||
| + | ---- | ||
| + | |||
| + | |||
| + | Beyond that, a few more sensors are built in to show WiFi signal strength, outdoor temperature and humidity, the time, and pre-selected texts on the display. Just a gimmick because we can... | ||
| + | |||
| + | ---- | ||
| + | |||
| + | The complete file is listed here once more: | ||
| + | |||
| + | ++++ doorbell.yaml | | ||
| + | |||
| + | <file yaml doorbell.yaml> | ||
| + | substitutions: | ||
| + | device_name: | ||
| + | |||
| + | esphome: | ||
| + | name: " | ||
| + | |||
| + | esp32: | ||
| + | board: esp-wrover-kit | ||
| + | framework: | ||
| + | type: arduino | ||
| + | |||
| + | # Enable logging | ||
| + | logger: | ||
| + | baud_rate: 0 | ||
| + | |||
| + | # Enable Home Assistant API | ||
| + | api: | ||
| + | encryption: | ||
| + | key: " | ||
| + | |||
| + | services: | ||
| + | - service: update_display | ||
| + | then: | ||
| + | - component.update: | ||
| + | |||
| + | - service: dfplayer_next | ||
| + | then: | ||
| + | - dfplayer.play_next: | ||
| + | |||
| + | - service: dfplayer_previous | ||
| + | then: | ||
| + | - dfplayer.play_previous: | ||
| + | |||
| + | - service: dfplayer_play | ||
| + | variables: | ||
| + | file: int | ||
| + | then: | ||
| + | - dfplayer.play: | ||
| + | |||
| + | - service: dfplayer_play_folder | ||
| + | variables: | ||
| + | folder: int | ||
| + | file: int | ||
| + | then: | ||
| + | - dfplayer.play_folder: | ||
| + | folder: !lambda ' | ||
| + | file: !lambda ' | ||
| + | |||
| + | - service: dfplayer_set_device_tf | ||
| + | then: | ||
| + | - dfplayer.set_device: | ||
| + | |||
| + | - service: dfplayer_set_volume | ||
| + | variables: | ||
| + | volume: int | ||
| + | then: | ||
| + | - dfplayer.set_volume: | ||
| + | - service: dfplayer_set_eq | ||
| + | variables: | ||
| + | preset: int | ||
| + | then: | ||
| + | - dfplayer.set_eq: | ||
| + | |||
| + | - service: dfplayer_sleep | ||
| + | then: | ||
| + | - dfplayer.sleep | ||
| + | |||
| + | - service: dfplayer_reset | ||
| + | then: | ||
| + | - dfplayer.reset | ||
| + | |||
| + | - service: dfplayer_start | ||
| + | then: | ||
| + | - dfplayer.start | ||
| + | |||
| + | - service: dfplayer_pause | ||
| + | then: | ||
| + | - dfplayer.pause | ||
| + | |||
| + | - service: dfplayer_stop | ||
| + | then: | ||
| + | - dfplayer.stop | ||
| + | |||
| + | - service: dfplayer_volume_up | ||
| + | then: | ||
| + | - dfplayer.volume_up | ||
| + | |||
| + | - service: dfplayer_volume_down | ||
| + | then: | ||
| + | - dfplayer.volume_down | ||
| + | |||
| + | ota: | ||
| + | password: " | ||
| + | |||
| + | time: | ||
| + | - platform: homeassistant | ||
| + | id: esptime | ||
| + | timezone: Europe/ | ||
| + | - platform: sntp | ||
| + | on_time: | ||
| + | # Every minute | ||
| + | - seconds: 0 | ||
| + | minutes: ' | ||
| + | then: | ||
| + | - component.update: | ||
| + | |||
| + | wifi: | ||
| + | ssid: !secret wifi_ssid | ||
| + | password: !secret wifi_password | ||
| + | |||
| + | # Enable fallback hotspot (captive portal) in case wifi connection fails | ||
| + | ap: | ||
| + | ssid: " | ||
| + | password: " | ||
| + | |||
| + | captive_portal: | ||
| + | |||
| + | # doorbell camera | ||
| + | esp32_camera: | ||
| + | name: Doorbell_Cam | ||
| + | vertical_flip: | ||
| + | horizontal_mirror: | ||
| + | external_clock: | ||
| + | pin: GPIO0 | ||
| + | frequency: 20MHz | ||
| + | i2c_pins: | ||
| + | sda: GPIO26 | ||
| + | scl: GPIO27 | ||
| + | data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35] | ||
| + | vsync_pin: GPIO25 | ||
| + | href_pin: GPIO23 | ||
| + | pixel_clock_pin: | ||
| + | power_down_pin: | ||
| + | # | ||
| + | resolution: 800x600 | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | |||
| + | output: | ||
| + | # | ||
| + | - platform: gpio | ||
| + | pin: GPIO4 | ||
| + | id: gpio_4 | ||
| + | |||
| + | light: | ||
| + | # | ||
| + | - platform: binary | ||
| + | output: gpio_4 | ||
| + | id: cam_flash | ||
| + | name: Doorbell Cam flash | ||
| + | |||
| + | binary_sensor: | ||
| + | - platform: gpio | ||
| + | pin: GPIO16 | ||
| + | name: "Ring Door" | ||
| + | id: ring_door_sensor | ||
| + | # | ||
| + | # then: | ||
| + | # - component.update: | ||
| + | # | ||
| + | # then: | ||
| + | # - component.update: | ||
| + | - platform: homeassistant | ||
| + | id: phone_message | ||
| + | entity_id: input_boolean.phone_message | ||
| + | internal: true | ||
| + | |||
| + | sensor: | ||
| + | - platform: wifi_signal | ||
| + | id: wifi_strength | ||
| + | name: " | ||
| + | update_interval: | ||
| + | - platform: homeassistant | ||
| + | id: outdoor_temperature | ||
| + | entity_id: sensor.aussensensor_temperature | ||
| + | internal: true | ||
| + | - platform: homeassistant | ||
| + | id: outdoor_humidity | ||
| + | entity_id: sensor.aussensensor_humidity | ||
| + | internal: true | ||
| + | |||
| + | text_sensor: | ||
| + | - platform: homeassistant | ||
| + | id: phone_number | ||
| + | entity_id: input_select.door_phone_number | ||
| + | internal: true | ||
| + | |||
| + | # e-paper display 250x122 (128) | ||
| + | font: | ||
| + | - file: ' | ||
| + | id: font_comic24 | ||
| + | size: 24 | ||
| + | - file: ' | ||
| + | id: font_comic_bold24 | ||
| + | size: 24 | ||
| + | - file: " | ||
| + | id: font_roboto20 | ||
| + | size: 20 | ||
| + | - file: " | ||
| + | id: font_roboto_bold24 | ||
| + | size: 24 | ||
| + | - file: ' | ||
| + | id: font_icon20 | ||
| + | size: 20 | ||
| + | glyphs: [ | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | ] | ||
| + | - file: ' | ||
| + | id: font_icon24 | ||
| + | size: 24 | ||
| + | glyphs: [ | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | ] | ||
| + | |||
| + | spi: | ||
| + | clk_pin: GPIO14 | ||
| + | mosi_pin: GPIO13 | ||
| + | |||
| + | display: | ||
| + | - platform: waveshare_epaper | ||
| + | id: doorbell_display | ||
| + | cs_pin: GPIO33 | ||
| + | dc_pin: GPIO15 | ||
| + | busy_pin: GPIO12 | ||
| + | reset_pin: GPIO2 | ||
| + | model: 2.13in-ttgo-dke | ||
| + | full_update_every: | ||
| + | update_interval: | ||
| + | reset_duration: | ||
| + | rotation: 90 | ||
| + | auto_clear_enabled: | ||
| + | lambda: |- | ||
| + | #define H_WIFI 1 | ||
| + | #define V_WIFI 4 | ||
| + | #define H_TEMP 30 | ||
| + | #define V_TEMP 2 | ||
| + | #define H_HUM 115 | ||
| + | #define V_HUM 2 | ||
| + | #define H_CLOCK 180 | ||
| + | #define V_CLOCK 2 | ||
| + | |||
| + | // Wifi | ||
| + | float wifi_rssi = id(wifi_strength).state; | ||
| + | if (wifi_rssi > -50) { | ||
| + | it.printf( H_WIFI, V_WIFI, id(font_icon20), | ||
| + | } else if (wifi_rssi > -60) { | ||
| + | it.printf( H_WIFI, V_WIFI, id(font_icon20), | ||
| + | } else if (wifi_rssi > -70) { | ||
| + | it.printf( H_WIFI, V_WIFI, id(font_icon20), | ||
| + | } else if (wifi_rssi > -80) { | ||
| + | it.printf( H_WIFI, V_WIFI, id(font_icon20), | ||
| + | } else if (wifi_rssi > -90) { | ||
| + | it.printf( H_WIFI, V_WIFI, id(font_icon20), | ||
| + | } else { | ||
| + | it.printf( H_WIFI, V_WIFI, id(font_icon20), | ||
| + | } | ||
| + | |||
| + | // Temp | ||
| + | it.printf( H_TEMP, V_TEMP+2, id(font_icon20), | ||
| + | it.printf(H_TEMP+20, | ||
| + | " | ||
| + | |||
| + | // Humidity | ||
| + | it.printf( H_HUM, V_HUM+2, id(font_icon20), | ||
| + | it.printf(H_HUM+20, | ||
| + | " | ||
| + | |||
| + | // Clock | ||
| + | it.printf( H_CLOCK, V_CLOCK+2, id(font_icon20), | ||
| + | it.strftime(H_CLOCK+20, | ||
| + | " | ||
| + | |||
| + | // ------------------------- | ||
| + | it.line(0, 25, 250, 25); | ||
| + | |||
| + | // Name plate | ||
| + | it.print(70, | ||
| + | it.print(7, 60, id(font_comic_bold24), | ||
| + | if(id(phone_message).state) { | ||
| + | it.printf(05, | ||
| + | it.printf(35, | ||
| + | id(phone_number).state.c_str()); | ||
| + | } else { | ||
| + | it.print(53, | ||
| + | } | ||
| + | |||
| + | # DF MP3 Player | ||
| + | uart: | ||
| + | tx_pin: GPIO1 | ||
| + | rx_pin: GPIO3 | ||
| + | baud_rate: 9600 | ||
| + | |||
| + | dfplayer: | ||
| + | on_finished_playback: | ||
| + | then: | ||
| + | logger.log: ' | ||
| + | </ | ||
| + | |||
| + | ++++ | ||
| + | |||
| + | |||
| + | ===== Result ===== | ||
| + | |||
| + | After compiling and flashing, we integrate the '' | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | When the button on the doorbell panel is touched, the following now happens: | ||
| + | * Sends a message to all HA users | ||
| + | * Plays a doorbell chime on all HomePods | ||
| + | * Saves a timestamped image from the camera to the media folder | ||
| + | * Plays a chime on the video doorbell itself as confirmation | ||
| + | * Optionally speaks a pre-selected text in Thai and English | ||
| + | * Optionally shows a callback phone number on the display | ||
| + | |||
| + | Of course you can also have it email you the captured image, turn on extra lighting, or feed the cat ;-)... | ||
| + | |||
| + | Here's what the finished module looks like inside and outside (display pixelated): | ||
| + | |||
| + | <WRAP group> | ||
| + | <WRAP third column> | ||
| + | {{ : | ||
| + | </ | ||
| + | <WRAP third column> | ||
| + | {{ : | ||
| + | </ | ||
| + | <WRAP third column> | ||
| + | {{: | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | In dry testing in Germany, everything worked perfectly. Installation on-site in Thailand will happen in 2023. I'll keep reporting... | ||
| + | |||
| + | ===== Downloads ===== | ||
| + | |||
| + | * {{: | ||
| + | * {{: | ||
| + | * {{: | ||
| + | |||
| + | |||
| + | |||
| + | =====Links===== | ||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | ===== Donate ===== | ||
| + | |||
| + | If you'd like to support my work, feel free to buy me a cappuccino or so: . | ||
| + | |||
| + | < | ||
| + | |||
| + | <form action=" | ||
| + | <input type=" | ||
| + | <input type=" | ||
| + | <img alt="" | ||
| + | </ | ||
| + | |||
| + | </ | ||