Connecting a conventional doorbell to openhab

doorbell
openhab2
mqtt
Tags: #<Tag:0x00007f213c985148> #<Tag:0x00007f213c984fb8> #<Tag:0x00007f213c984e28>

(mlommers) #1

This tutorial will show how I connected my conventional doorbell to Openhab in order to monitor when the doorbell button is pressed causing the doorbell to ring and to be able to mute the doorbell. The latest comes in handy when sleeping durig daytime for example when working in night shifts or having young kids.
As I have a doorbell which is working as expected I don’t want to change to much to the doorbell, furthermore I also want the doorbell to keep functioning when openhab is not working/off.

Altough it is possible to use the GPIO binding of openhab I didn’t used it. The main reason for this is that I don’t want a hard coupling of Openhab running on the raspberry pi. Instead I used nodejs and mqtt for reading the GPIO pin and sending status updates via the mqtt messagebus. This makes it possible for me to have openhab running on another system than where the doorbell is connected to. Next to the decoupling another advantage of this approach is the fact that multiple programs can listen to the messagebus and not only openhab as actor for the doorbell.

###prerequisite
installed packages:

Openhab
InfluxDB en grafana
Openhab MQTT binding

Mosquitto (mqtt messagebroker)
  • sudo apt-get install mosquitto mosquitto-clients python-mosquitto
  • sudo systemctl enable mosquitto
  • sudo systemctl start mosquitto
  • systemctl status mosquitto
nodejs (Upgrade to newer version nodejs)
  • sudo apt-get remove nodejs
  • wget https://nodejs.org/dist/v6.10.0/node-v6.10.0-linux-armv6l.tar.xz
  • sudo mv node-v6.10.0-linux-armv6l.tar.xz /opt
  • cd /opt
  • sudo tar xf node-v6.10.0-linux-armv6l.tar.xz
  • sudo mv node-v6.10.0-linux-armv6l nodejs
  • sudo rm node-v6.10.0-linux-armv6l.tar.xz
  • sudo ln -s /opt/nodejs/bin/node /usr/bin/node
  • sudo ln -s /opt/nodejs/bin/node /usr/bin/nodejs
  • sudo ln -s /opt/nodejs/bin/npm /usr/bin/npm
Install the nodejs gpio and mqtt module
  • sudo npm install onoff
  • sudo npm install mqtt

situation before making the doorbell smart:

1x 230 AC to 8AC transformer
1x Doorbell
1x Doorbell push button

Doorbell Monitor

The doorbell monitor will give an event everytime the doorbell button is pressed. I used an optocoupler to seperate the voltage circuit of the Doorbell with the voltage circuit of the Raspberry Pi. When the doorbell is signalled with an 8AC voltage the Raspberry Pi will also get a signal via the OptoCoupler.

###components used:
D1 = 1n4001 diode
R1 = 680 ohm limitting current resistor
R2 = 10K pull up resistor
R3 = 2k2 protection resistor (to prevent damaging the GPIO when by accicent configured as output)
U1 = 4n35 Optocoupler

Raspberry Pi

###Node js code doorbell_ring.js:
This scripts monitors the GPIO pin and sends a message on the MQTT bus every time the doorbell is pressed. As I saw some false detections I only sent a message when the GPIO pin is detecting 4 falling signals of the 50 Hz sinus signal. 2 successive button presses are noticed when 2 timestamps is bigger than 250 ms.

sudo vim /home/pi/doorbell_ring.js

and add:

var Gpio = require('onoff').Gpio,
    door_bell_button = new Gpio(18, 'in', 'falling');
var mqtt = require('mqtt')
var client  = mqtt.connect('mqtt://localhost:1883')
global.LastRingTime = Date.now()
global.nrOfTriggersWithin100ms = 0
global.HundredMsThreshold = Date.now()
door_bell_button.watch(function(err, value) {
    if (err) exit();
    RingTimeNow = Date.now()
    //console.log('registered falling GPIO18: %s', RingTimeNow); 
    if (RingTimeNow - global.LastRingTime > 250)//20 ms should be enough but somehow the first ring shows around 230 ms delay
    {
       global.nrOfTriggersWithin100ms = 1
       global.HundredMsThreshold  = RingTimeNow + 100
    }
    if ( (global.nrOfTriggersWithin100ms < 4) && (RingTimeNow  < global.HundredMsThreshold ) )
    {
        global.nrOfTriggersWithin100ms++
        if (global.nrOfTriggersWithin100ms == 4)
        {
            client.publish('myHome/doorbell/ring', 'ON')
            console.log('Someone rings the doorbell: %s', RingTimeNow);
        }
    }
    global.LastRingTime = RingTimeNow
});
function exit() {
    console.log('doorbell_ring.js exit');
    process.exit();
}
process.on('SIGINT', exit);

###Install doorbell_ring.js as a service
The following make the nodejs code to be restarted at systemstart.

Create service script: /etc/systemd/system/doorbell_ring.service

sudo vim /etc/systemd/system/doorbell_ring.service

with content:

[Unit]
Description=Doorbell_ring

[Service]
ExecStart=/usr/bin/nodejs /home/pi/doorbell_ring.js
Restart=always
User=pi
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
WorkingDirectory=/home/pi

[Install]
WantedBy=multi-user.target

Change file permissions:

sudo chmod 755 /etc/systemd/system/doorbell_ring.service

Start it with:

sudo systemctl start doorbell_ring

Enable it to run on boot with:

sudo systemctl enable doorbell_ring

Configure openhab MQTT items

Now the hardware is inplace and events are being sent on the MQTT message bus, we want to transform the mqtt message into an event in OpenHAB. This is done via an item. The item “doorbell_ring” of type switch is binded onto the mqtt channel

sudo vim /etc/openhab2/items/mqtt.items

Add:
Switch doorbell_ring {mqtt="<[mosquitto:myHome/doorbell/ring:state:default]"}

Persistence in openhab

I use Influx as persistence service in openhab

Edit:
sudo vim /etc/openhab2/persistence/influxdb.persist:

Add:
doorbell_ring : strategy = everyUpdate, restoreOnStartup

Doorbell mute

The doorbell mute functionality will be used to switch off the actuall ringing of the bell and in such acting as a mute function for the doorbell.

I used a 5V 2 channel relay module to control the signal comming from the button to the doorbell with a raspberry pi. By default the relay is closed causing the doorbell to function as normall. When switching the relay the closed circuit to the doorbell is interupted causing the doorbell NOT to ring. Hence a mute function has been created.

Nodejs code doorbell_mute.js

Now the hardware is connected to the RPI we want to have software inplace to control the relay. I chose to use nodejs and mqtt for this. NodeJS is an easy to use and is based on an event driven model. In the script we listen to events on the MQTT message bus and transform this event to toggle the relay and thus toggeling the doorbel mute on/off

sudo vim /home/pi/doorbell_mute.js

and add:

var mqtt = require('mqtt')
var client  = mqtt.connect('mqtt://localhost:1883')
var Gpio = require('onoff').Gpio,
relay1 = new Gpio(23, 'out'), //GPIO23, PIN16
   
client.on('connect', function () {
  client.subscribe('myHome/doorbell/mute')
})
 
client.on('message', function (topic, message) {
  // message is Buffer 
  // message is 1 when mute active, 0 when mute is inactive
  relay1.writeSync(message.toString().trim() === '1' ? 0 : 1); //low active so sending 1 for 0 and 0 for 1
  console.log(message.toString())
})

Install doorbell_mute.js as a service

The following make the nodejs code to be restarted at systemstart.

Create service script: /etc/systemd/system/doorbell_mute.service
sudo vim /etc/systemd/system/doorbell_mute.service

with content:

[Unit]
Description=Doorbell_mute

[Service]
ExecStart=/usr/bin/nodejs /home/pi/doorbell_mute.js
Restart=always
User=pi
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
WorkingDirectory=/home/pi
		
[Install]
WantedBy=multi-user.target

Change file permissions:
sudo chmod 755 /etc/systemd/system/doorbell_mute.service

Start it with:
sudo systemctl start doorbell_mute

Enable it to run on boot with:
sudo systemctl enable doorbell_mute

Configure openhab MQTT items

Now the hardware is inplace and the nodejs script is listening to events on the MQTT message bus, we want to transform the OpenHAB events into a message on the MQTT messagebus. This is done via an item. The item “doorbell_mute” of type switch is binded onto the mqtt channel causing a message to be sent on every switch of the openhab item.

Edit:
sudo vim /etc/openhab2/items/mqtt.items

Add:
Switch doorbell_mute {mqtt=">[mosquitto:myHome/doorbell/mute:command:ON:1],>[mosquitto:myHome/doorbell/mute:command:OFF:0]"}

Persistence in openhab

I use Influx as persistence service in openhab

Edit:
sudo vim /etc/openhab2/persistence/influxdb.persist

Add:
doorbell_mute : strategy = everyChange, restoreOnStartup

Add doorbell mute button to sitemap

To be able to control the doorbell mute functionality a button needs to be added to a sitemap:
Edit
sudo vim /etc/openhab2/sitemaps/doorbell.sitemap
Add:
sitemap doorbell label="doorbell"
Switch item=doorbell_mute

if you use HABPanel adding the sitemap is not necessary as the openhab item can be chosen directly as a configuration item with for example a button.

Doorbell monitor & mute

situation after making the doorbell smart:

Connecting the monitor functionality before the relayboard to the doorbell makes it possible to monitor the doorbell even when the doorbell is muted.

As I used a 2 channel relay board the 2nd relay could be used to control the doorbell programmatically, by connecting the N/O and COM parallel over the doorbell_button and connecting the IN2 to an RPI GPIO pin.


Doorbell serial port trigger
Doorbell, MQTT and open hab
(Tom) #2

Wow, this is great! Thanks for sharing. Couple questions for you:

  • Do you have any pictures of what you built? I’d love to see it. Did you just use a proto board or something more permanent? Do you put it into an electrical box?

  • Do you think this same concept could be used on a regular PCs serial port rather than a GPIO?


(mlommers) #3

I Used:

to solder the components on. I don’t have a picture of the final results yet, will try to make one soon. Currently I didn’t put it in a box. Stil looking for a nice box which matches the small print size.

If you want to connect the doorbell to a regular PCs serial port you need to add some components to convert the signal to a serial connection and define a protocol to be used on the serial connection. On the PC side the script needs to change to listen to the serial port. If I would connect the doorbel to a regular PC I would go for an USB to GPIO module, as that would be the easiest option:


like: http://numato.com/8-channel-usb-gpio-module-with-analog-inputs/

If you really want to connect to serial port, this is posisble, but requires some extra electronic components.


(Tom) #4

@mlommers - thanks for the info!

I’m seriously considering making one of these using the USB GPIO you suggested. A few differences / questions:

  • My doorbell system is 20V on the secondary of the T1 transformer. I have an old house, not sure if that was an older standard. Anyway, looks like I’d need to adjust the R1 current limiting resistor from 680ohms to 1.7kohms to give the same current.

  • I have a front and side door bell system that uses 2 separate circuits to ring different chimes. My plan is to basically make two detect circuits with outputs to two different GPIOs {and no mute circuit). I’d want the software to be able to see each and trigger different MQTT events. Do you foresee any issues with just running two different instances of this same program - one for each GPIO I connect to?

  • I’ve never really used a GPIO like this before. If I use the USB GPIO you suggested, I’m not sure where I’d get the 3.3V pullup for the output. Would you suggest commanding one of the GPIOs to output 5V and use that as the pullup (Adjusting R2 as needed)? I do also see a header on board that has a Vdd pin, but I can’t figure out for sure if that is the input for an off board power supply (when the USB isn’t enough) or if that is an output.

Thanks again for your help!


(mlommers) #5
  • 2 instances
    2 instances would nog work out of the box as the GPIO pin is hardcoded in the script
    so you could add a 2nd GPIO configuration & .watch function in the script or create 2 seperate scripts and change in one of the scripts the GPIO configuration
    If you also want to determine the difference inside openHab between front door en side door, you should also change the mqtt channels and for example make myHome/front_doorbell/ring and myHome/side_doorbell/ring
    if you do that also not forget to change the .item file by updating the existing mqtt channel and add a 2nd switch which listens to the right mqtt channel. For perstistency also add the 2nd item also to the persistence file if you want to pertain the history.

  • Pull-up resistor:
    if I read the doucmentation: https://docs.numato.com/doc/8-channel-usb-gpio-module-with-analog-inputs/
    1 Introduction
    Pull-up resistors on individual IOs
    This would mean a pull upp resistor is not necessary
    5.2.Using GPIOs with switches
    The pull up resistor is connected between the GPIO and VDD
    and an example is given
    So my conclusion if without is not working you can always add one as suggested and connect to Vdd


(Rossko57) #6

It is possible to use (abuse?) OH serial binding to look for short/open between serial pins 2 & 7 (RTS) to give effectively one single input pin.
http://docs.openhab.org/addons/bindings/serial1/readme.html


(Tom) #7

Hi Rossko57 -

Wondering you you use the serial binding this way? I’ve tied this a bunch of times and spent a few days trying to debug and I can’t seem to get it to work. I have a little DB9 with a wire connected to pins 2 & 7 that I short together, but no change in state of my switch item.


(Rossko57) #8

Nope, no personal experience. I guess the port needs configuring for hardware flow control, operating system dependant.


(Dome) #9

I’m doing something similar with my doorbell. I don’t have easy access to wires coming from the button, so I set up a relay to switch the power being outfitted from the transformer.

I’m using an Arduino Mega with an Ethernet shield and MQTT rather than the GPIO pins. I have time based rules that shut off the doorbell for my son’s nap time and for bedtime. I also have the switch exposed to HomeKit so I can shut it off manually when I work nights (notice how two night shift workers thought of this :grinning:).

At some point I’ll venture into my attic to pursue a more robust solution like yours but for now this helps us stay asleep when the delivery guy comes.

As the pictures show, I’m doing a lot more with the arduino than control the doorbell so my code might not be too helpful… but if there’s interest I will post snippets.


Anyone who connected a regular "old" doorbell to OH?
(dries_dokter) #10

This is what I did (as described in a different thread), making use of as many "of the shelf components as possible…
http://www.redgrendel.com/the-doorbell/

What needs to happen if the bell button is pressed can be set, either the doorbell rings, or the lights flash (or both)
Notification is send to my smart phone…


(Shane Cruz) #11

Can you expand a little regarding how you have this setup and what specific components you used (e.g., for the switch)? I am trying to do something similar with an Arduino Uno, but I don’t have a doorbell chime at all (the buttons will be wired directly to the 16VAC doorbell transformer).

I have received suggestions (at the link below and via private messages) to use either a switch or optocoupler and I am just trying to figure out my easiest option from a hardware perspective. I am more of a software guy, so once I can accurately detect the doorbell button press in the Arduino, I am confident I can program the rest of the behavior that I need.

http://forum.arduino.cc/index.php?topic=521126.new

Thanks!


(Thallaa) #12

I built my doorbell alert on top of an ESP8266 (Wemos D1 mini, to be exact). I have a 18650 Li-Ion battery as power source and a magnetic switch for inputting the doorbell signal to ESP. This has been in use for few months now and so far I have not noticed any missing signals.

These magnetic switches are typically used for detecting door/window open-close state, but since they are quite sensitive to the magnetic field, they are also good for detecting the doorbell coil. Another nice thing with them is that you don’t need to touch any of the doorbell wiring, just place the switch close enough to the coil and it should work fine.

Oh and one thing worth mentioning is that you can use the INPUT_PULLUP on Arduino or ESP so that you don’t need to add a separate pull-up resistor - just hook the magnetic switch between the input pin and GND and you’re good to go.


(rbausdorf) #13

I used an approach based on the piface addon.
My doorbell button is completely decoupled from the bell itself, only connected to an input of the piface module. One of the relays acts as trigger in the physical bell circuit.

This has the drawback that the doorbell completely relays on a working openhab system. The benefit is that the time the bell button is pressed has no influence on the duration the bell rings.


(Dome) #14

@scruzloose33 Sorry, I haven’t had a lot of time for openHAB stuff lately and missed your message.

Basically, I just used a relay to interrupt the power to the doorbell. The doorbell itself is original to the house and consists of the 18v transformer, the bell unit, and a pushbutton. I added the relay between the transformer + terminal and the bell unit.

I used a simple relay board from eBay* hooked up to an Arduino with an Ethernet shield, which in turn connects via MQTT. It’s mapped to a Switch item that’s toggled off while my kids are sleeping. So, basically, my setup currently has no way to detect a button press, it’s more like a “do not disturb” feature.

I am willing to share my code, but frankly the Arduino does lots of other stuff and I’m not sure it’d be more helpful than some of the other examples floating around this forum.

It sounds like you have bigger and better ambitions, so I’m not sure I have much more to offer. I have plans to do something similar down the road, but it’s currently low on my priority list.

*Note: I bought the board a few years ago and can’t find the seller I got it from, so I’m just offering the link as an example.