<article-heading
title="Doorbell"
is-published="true"
updated-date="2020-04-10"
/>
<p class="article-description">
I've been working from home a lot more recently, so I've been opting to get packages delivered straight to my home
instead of the office. Since I need to sign for some packages myself, I need a reliable way to hear when someone is
at the door. Now they can press a button outside, which triggers a notification and plays a doorbell chime inside
the house.
</p>
<p>
The obvious fix for this is to buy a simple <abbr title="radio frequency">RF</abbr> doorbell and install it,
however...
<ul>
<li>Cheap RF doorbells seem to have pretty limited range, with the chime only working a short distance inside
the house</li>
<li>You need to be in range of the chime to be able to hear and respond to it</li>
<li>There is no way to keep a record of when the doorbell is pressed</li>
</ul>
In addition, the built-in chimes are bland. My first Nokia phone had better single-channel MIDI tunes.
</p>
<h2>Interaction flow</h2>
<section class="hero">
<figure>
<img src="/content/articles/doorbell/doorbell.png"
alt="A diagram showing how messages from a Mijia button are are delivered to Home Assistant and then through to Pushbullet and a connected speaker." />
<figcaption>A Zigbee button communicates to Zigbee2mqtt and Home Assistant to send a notification and trigger an
audio alert.
</figcaption>
</figure>
</section>
<p>
The interaction flow above is similar to how the <a data-article="mailbox-sensor">Mailbox sensor</a> and <a
data-article="bedside-lamp-button">Bedside lamp button</a> operate, but this time the Raspberry Pi is
connected directly
to an external speaker
</p>
<h2>Devices</h2>
<section class="gallery previews-medium">
<figure>
<img src="/content/articles/doorbell/mijia-button.jpg" alt="A Xiaomi Mijia button" />
<figcaption>Mijia button <br /><a href="https://item.mi.com/product/5006.html">from Xiaomi</a></figcaption>
</figure>
<figure>
<img src="/content/articles/doorbell/doorbell-cap.png" alt="A 3D rendered button cap with a ringing bell outline" />
<figcaption>3D printed doorbell cap
</figcaption>
</figure>
<figure>
<img src="/content/articles/doorbell/speaker.jpg" alt="A speaker" />
<figcaption>Speaker
</figcaption>
</figure>
</section>
<h2>Doorbell cap</h2>
<section class="previews-medium inline">
<figure>
<img src="/content/articles/doorbell/doorbell-with-cap.jpg" alt="The mounted doorbell with a 'ringing bell' icon cap" />
</figure>
</section>
<p>
It needs to be clear that the button is actually a doorbell, so I decorated it with a 3D printed cap with a 'ringing
bell' silhouette from the <a href="https://materialdesignicons.com/">Material Design Icons</a> set. This is just
hot-glued to the button face, making the entire cap pressable.
</p>
<h2>Playing audio</h2>
<p>
Home Assistant offers a few integrations for playing audio. I tried the <a
href="https://www.home-assistant.io/integrations/mpd/">Music Player Daemon</a> and <a
href="https://www.home-assistant.io/integrations/vlc/">VLC</a> integrations, but settled on the low-fi <a
href="https://www.home-assistant.io/integrations/shell_command/">Shell Command</a> with <code
class="inline">aplay</code> due to its speed and minimalism. The only problem with using <code
class="inline">aplay</code> is that it only accepts unencoded waveform audio.
An easy workaround is to transcode audio files manually before using them: <code
class="inline">ffmpeg -i input.mp3 output.wav</code>.
</p>
<p>
In this example, I'm using <code class="inline">sound_file</code> as a parameter to make the <code
class="inline">play_sound</code> command
reusable. My Raspberry Pi has a USB audio card connected, but for the speaker I want to use the onboard audio
card
(which is aliased as 'sysdefault').
</p>
<pre class="prettyprint" v-pre="v-pre">$ cat ${HOME_ASSISTANT}/configuration.yaml
<code class="lang-yaml">
...
shell_command:
play_sound: 'aplay -D sysdefault {{ sound_file }}'
...</code></pre>
<p>
Here, I'm using a new script to handle the "doorbell pressed" notification actions, to keep them decoupled from
the
automation trigger.
</p>
<pre class="prettyprint" v-pre="v-pre">$ cat /home/homeassistant/.homeassistant/scripts.yaml
<code class="lang-yaml">
...
notify_doorbell_pressed:
alias: Notify doorbell pressed
sequence:
- service: shell_command.play_sound
data:
sound_file: /home/pi/puzzle-solved.wav
- service: notify.notify_pushbullet
data:
message: Doorbell was pressed
...</code></pre>
<p>
Finally, the automation simply waits for a <code class="inline">single</code> click trigger, which fires off the
<code class="inline">notify_doorbell_pressed</code> script above.
</p>
<pre class="prettyprint" v-pre="v-pre">$ cat /home/homeassistant/.homeassistant/automations.yaml
<code class="lang-yaml">
...
- id: doorbell_pressed
alias: Doorbell pressed
trigger:
- entity_id: sensor.0x00158d0002c41211_click
platform: state
to: single
action:
- service: script.notify_doorbell_pressed
...</code></pre>
<h2>Wrap-up</h2>
<p>
This serves as a sensible first cut of a doorbell. Next, I'm keen to include some behaviours from other smart
doorbell solutions, such as an intercom.
</p>
<p>
If you have any feedback or questions related to this article, please reply to <a
href="https://twitter.com/TassSinclair/status/1246701205675376642">my post on Twitter</a>.
</p>
<p>
This article is part of the <a data-article="home-automation">Home automation</a> set.
</p>