Honeywell 5800 series 345Mhz door and window sensor integration with HA

Hey all. First timer here. I wanted to share with you how I got my existing and embedded Honeywell opening sensors working with Home Assistant.

Required Components:

  • Working Home Assistant Installation (any platform)
  • Preferably a separate linux box for wireless reception. (running rtl-sdr, rtl_433, mosquitto)
  • A sensor or two.
  • an RTL-SDR USB stick receiver and an antenna (the little chincy one that comes with it suffices just fine.)

My Current Setup:

My setup is probably more complex than many will have to deal with so if I can get it working, so you can you. I’m running two VMs in virtualbox on Windows. Why virtualbox? Because USB passthrough and I don’t want to pay for VMWare. Most of you will likely do this on Raspbian or a dedicated server and that’s fine. My HA VM is an Ubuntu 16 VM with docker installed (to make handling HA updates way easier). The second VM is the one that handles radio reception and has the MQTT broker installed on it.

It’s totally ok to do your radio reception with the same machine that’s running HA. Especially for you Raspian folks. Very little CPU is used in the process. I’m going to write this assuming you’re going to follow my lead and use a separate machine to do this since this tutorial is based on mosquitto for mqtt brokering. If you’re using Docker on Windows or Mac, I would really implore you to either create a separate container or use a different VM altogether. If you’re using Docker on Windows, you’ll want to use Docker Toolbox instead of base Docker to ensure you can use Virtualbox as your hypervisor as Hyper-V doesn’t yet allow for passing through USB devices to the VM (No foggy idea why…)

Setup Steps:

On your HA box you’ll need to install rtl-sdr and associated libraries.

Please see the instructions:

For CentOS/RHEL
For Ubuntu, Debian

Once you can run rtl_test without any errors then you can move on.

Download and compile and install rtl_433
This is the software that listens and decodes M2M wireless messages in various protocols. It was originally designed around the vast number of devices that run on 433 Mhz, however you’re able to listen on any frequency and bandwidth that your receiver supports.

If you’re able to run rtl_433 -G without any errors, congratulations!

Next, if you’re not running the receiver on your HA box you’ll need to install mosquitto and its associated clients. HA already has an mqtt broker and can publish. This tutorial, however, is written with mosquitto in mind so I’m not sure how to use the built in broker that ships with HA. Be sure to start the mosquitto service with a command such as:
sudo systemctl start mosquitto
Or you’re going to have issues. :slight_smile:

Finding your Sensors

Time to bust out notepad or grab a sheet of paper out of the printer (do people still own printers? What dismal devices) Time to find all your sensors and document their ID’s as you’ll need to reference them in your HA config later on.

Run: rtl_433 -f 344975000

rtl_433 should run and start idling listening for your sensors. Go crack open a door for about 5 seconds and then close it again. You should get some output such as this:

2017-06-01 16:41:37 : Honeywell Door/Window Sensor : 7726b : 8 : 80 : open : no

That doesn’t look inherently useful to Home Assistant and it doesn’t contain the device id we need. So let’s try a slightly different command to make rtl_433 spit out a json statement as opposed to it’s own internal preformatted data.

Run: rtl_433 -f 344975000 -F json

Now we’re cooking with dead dinosaur squeezins!

{"time" : "2017-06-01 16:44:31", "model" : "Honeywell Door/Window Sensor", "id" : 488043, "channel" : 8, "event" : 0, "state" : "closed", "heartbeat" : "no"}

Hopefully you know which door or window you just opened or closed and all you have to do is write down the "id".

Do this for all of your applicable sensors until you have a nice list.

Getting the Data to Home Assistant

So in order to get the data to Home Assistant we’re going to use mqtt. But how do we get the output from rtl_433 to mosquitto? Pipe it! Here’s how:

rtl_433 -f 344975000 -F json -U | mosquitto_pub -t homeassistant/sensor/honeywell -l -V mqttv311

What does this command do? Well, let’s break it down. There’s a little bit to unpack about the why…

rtl_433 -f 344975000 -F json -U fires up rtl_433 at a center freq of 344.975Mhz with default 250Khz bandwidth. This means that the radio is tuned to 344.975Mhz but can see 125Khz in either direction. This is to account for the multiple channels that the Honeywell sensors use along that band. It also allows for some wiggle room with regards to an uncalibrated RTL-SDR dongle.

The -F json portion tells rtl_433 to format as a json statement.

And -U tells rtl_433 to format the timestamp as UTC making it a more applicable variable for HA or other applications.

Then there’s the pipe which basically connects the output of rtl_433 with the -m input of mosquitto.

mosquitto_pub the client program we’re using the publish the mqtt message;
-t homeassistant/sensor/honeywell is the mqtt topic we’re going to publish to. You can make it whatever string of text you’d like, but for simplicity of this tutorial, this is what we’re going to use.
l (lowercase L) tells mosquitto to interpret the message (stdin) as a single line at a time instead of a paragraph.
-V mqttv311 This is the forced mqtt protocol which is crucial crucial as the latest mosquitto will have issues talking to HA without it.

Once you get this running you can just let it chooch as you’re now done here. Onto Home Assistant configuration!!

Since you’re presumably following my steps and using a second linux box for your receiver and MQTT broker, please add the following to your configuration.yaml:

mqtt:
    broker: <broker ip address>

Then in your sensors section of your configuration.yaml you’re going to add a single sensor entity for each of the sensors you’re radio is listening for. But you’re going to need some conditional Jinga trickery in your value_templates in order to be able to split out and parse the various sources of JSON data because we’re going to have different device ID’s and their states all being piped to the same mqtt topic. Follow me little bird, I’ll feed ya:

sensor:
  - platform: mqtt
    state_topic: "homeassistant/sensor/honeywell"
    name: "Back Door"
    qos: 0
    device_class: opening
#On the next line you'll input the device ID you got for your sensors when you were wandering around your house like a crazy person opening and closing doors and windows.  So I know here I need the ID for the Back Door sensor.
    value_template: '{% if value_json.id is equalto 488043 %} {{value_json.state}} {% else %}
 {{states.sensor.back_door.state}} {% endif %}'
    
  - platform: mqtt
    state_topic: "homeassistant/sensor/honeywell"
    name: "Front Door"
    qos: 0
    device_class: opening
    value_template: '{% if value_json.id is equalto 477731 %} {{value_json.state}} {% else %} {{states.sensor.front_door.state}} {% endif %}'
    
  - platform: mqtt
    state_topic: "homeassistant/sensor/honeywell"
    name: "Garage Door"
    qos: 0
    device_class: opening
    value_template: '{% if value_json.id is equalto 294890 %} {{value_json.state}} {% else %} {{states.sensor.garage_door.state}} {% endif %}'

Notice each sensor is listening on the same topic. But we only grab the state information for the sensor we’re looking for. The key to this is the Jinga conditional filter. We check the incoming JSON for a pre-specified device id.

Take special note of the {% else %} clause. Since all of the sensor entities are listening on that same mqtt topic, if you don’t have something else for it to do and the device ID coming in on the json value doesn’t match then it’ll set the sensor state to nothing. So we tell it then to reset it with the current state: {{states.sensor.back_door.state}} So while the state value does, in fact, get overwritten, it’s overwritten with its current, pre-existing state.

In Closing (see what I did there?)

There are so many people to thank for this coming to fruition. I have yet heard of anyone else successfully integrating these sensors with HA. I know there’s another piece of software alternative to rtl_433 that works on the Raspberry Pi but I haven’t played with it. Thus far I’ve had complete success and accuracy with this setup. Additionally, you can also grab heartbeat and battery low statuses from the sensors, setup automation for notification when a sensor battery is low or add the tamper sensor to HA automation as well.

Huge thanks to github user merbanan for rtl_433, Jon Lundy for the Jinga help, Dan Englender for helping us understand these sensors and their protocol.

Happy Integrating!!!

-Joe Hancuff

7 Likes

Quick note about some of the Honeywell sensors. Some door and window sensors will use the state variable as open or closed. However, some sensors will continually leave that state set to open. If that’s the case, you need to go look at the event ID in the JSON that’s spit out and align your Jinga statement accordingly to catch it.

  - platform: mqtt
    state_topic: "homeassistant/sensor/honeywell"
    name: "Garage Door"
    qos: 0
    device_class: opening
    value_template: '{% if (value_json.id is equalto 294890) and (value_json.event is equalto 160) %} open {% elif (value_json.id is equalto 294890) and (value_json.event is equalto 128) %} closed {% else %} {{states.sensor.garage_door.state}} {% endif %}'
3 Likes

First, thank you for this. I thought my RTL-SDR dongle was going to be useless after discovering that I can’t successfully capture packets from my smart meter from Duke Energy. This pot revives it for me.

However, I do have a question. How are you getting your command to run? Specifically, I don’t want to have to enter this command in every time. I created a service in systemd and made sure it would autostart at boot. Unfortunately, it looks like the rtl_433 runs, but it doesn’t add the mosquitto part to it.

Any insight?

1 Like

Hrm… Well for testing, I usually only had to run it once on the RTL vm and then it just chooched without issue. If it crashes and says user cancellation after you open a door then there’s an error in your mosquitto_pub command. As for auto-starting it, I’d probably dump that command line into a shell script and set that script to autostart instead of just the command line. I’m not sure if you can pipe stdout of commands when using systemd for autoexec. creating a shell script and the associated handling code in rc.local is probably the easiest way rather than using systemd. But I’m a n00b according to my friends so what do I know?

Let me know what you find out. I’m soon going to be putting this into production on an AIO RPi installation so I, too, would like to know the best way to keep it chooching proper.

I ran a script through rc.local on my Pi. Wasn’t an easy task at first because I couldn’t get it to also execute the “|” in the script at first, and then after messing around with it, I got it to autostart. I’ll past my findings when I get home.

I tried using systemd to autostart it as well and got confused. I think it’s in /etc/rc.local and then there is a .sh file I created to execute.

Another thing you can do in your shell script is a do while true block to handle when the rtl crap the bed and dies out it just restarts again. Currently, I’m just running the script with nohup ./rtlstartup.sh & which seems to work rather well.

FYI, this doesn’t work well on the RPi because of interference from the Zstick. Everything installs and runs but the radio doesn’t receive crap.

Just throwing this out here for those people use Docker, this docker image works perfectly

https://hub.docker.com/r/roflmao/rtl2mqtt/

Chris

1 Like

I just thought I’d post this here to see if anyone else has experienced and solved this particular issue. I have a range of Honeywell sensors that I am capturing packets from (contact sensors for doors, motion sensors, and a smoke detector).

I’m getting a real hit and miss with the sensors and it’s starting to look like there is a missing piece to the puzzle. Two of the four contact sensors work perfectly, but two work at first and then stop working. Likewise, one of my two motion sensors work great!

All of the sensors have brand new batteries – so that’s not it.

It seems to me like some versions of the sensors might need to be “poked” into transmitting? I’ve read elsewhere that, in an effort to conserve battery life, the motion sensors for example won’t “turn on” until they receive a command indicating the house has been put in “away” mode (to avoid unnecessary transmissions of state when they aren’t normally needed). This obviously doesn’t make sense in a home automation situation – does anyone have a clue what might be going on?

John

I have seen the same thing too. It’s REALLY frustrating, and I haven’t been able to resolve it. That said, I found this:

https://products.z-wavealliance.org/products/1173

This actually works with the Honeywell 5800 series sensors, and translates them to Z-wave. I just ordered it, and I think it will work (provided the command classes are there).

Chris

Could this be used to control 315mhz gear too?

That is the bomb! I switched out for Zwave sensors since I wrote this. MUCH easier and more consistent. Just cost that sweet sweet green.

Good info here, thank you!

In implementing my own solution to utilize these sensors, I’ve made it to the point that I want to implement an actual sensor component for this device under custom_components (https://home-assistant.io/developers/platform_example_sensor/). The value_template method offers little ability to handle all the bit conditions that could be present (battery low and state on, for example), and there’s a lot of boilerplate code that could be done once for a home full of honeywell sensors instead of cut-and-paste to each instance (with all the bugs that arise from a cut-and-paste coding style).

Does anyone have a custom_components implementation? Or any advice on creating one? If not, I’m going to work on creating one to use myself as well as share.

Has anyone gotten a “signal caught, exiting now” code? I put fresh batteries in my honeywell sensors and it seems to quit responding after an unknown amount of time.

I know there was a comment about sending a signal to keep the honeywell sensors awake, was that true? and was that resolved?

I am having an issue waking the devices up. I have probably close to 10 devices on different doors and windows, but whenever I reboot HA the device state returns to unknown. I have to then open/close the window or door for the device to register with the proper open or closed state. Once I have all the sensors up and running I don’t want to have to manually wake all of them up every time I reboot. The device will be fine until the raspberry pi is rebooted… Please any help would be awesome!!

back

@brakow87 My RTL-SDR is supposed to be arriving today. I think I have an idea on how to solve this problem. My MVP would be a program that caches the rtl events, keeping a last_seen_event for each of the devices. Then, on an interval, it would rebroadcast those to the mqtt topic.

I think a fancier solution, which I may look into after getting the above to work, would be to make this program/service also consume the HA mqtt event stream and listen for some sort of event signal HA is starting back up (I’m new to HA, I’m assuming this exists). On that event, it’d send the last seen events for each of the components.

Edit: Now that I think of it, if HA restarts or goes away then the mqtt connection would be lost. So that itself would be an indicator to resend all of the last seen events, once the mqtt event stream comes back up.

Having a difficult time getting my service to start automatically. I can get it to start, however, after a trigger or time (not sure which yet), the service comes up with an exit code. Here’s my service file:

[Unit]
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash /home/pi/433Mhz_auto.sh
User=pi
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

Here’s the error I’m getting:

pi@hassbian:/etc/systemd/system $ sudo systemctl status rtlsdr
● rtlsdr.service
Loaded: loaded (/etc/systemd/system/rtlsdr.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Sun 2018-06-17 11:50:18 EDT; 18s ago
Main PID: 11581 (code=exited, status=127)
Jun 17 11:49:34 hassbian bash[11581]: Exact sample rate is: 250000.000414 Hz
Jun 17 11:49:35 hassbian bash[11581]: [R82XX] PLL not locked!
Jun 17 11:49:35 hassbian bash[11581]: Sample rate set to 250000.
Jun 17 11:49:35 hassbian bash[11581]: Bit detection level set to 0 (Auto).
Jun 17 11:49:35 hassbian bash[11581]: Tuner gain set to Auto.
Jun 17 11:49:35 hassbian bash[11581]: Reading samples in async mode…
Jun 17 11:49:35 hassbian bash[11581]: Tuned to 344975000 Hz.
Jun 17 11:50:18 hassbian systemd[1]: rtlsdr.service: Main process exited, code=exited, status=127/n/a
Jun 17 11:50:18 hassbian systemd[1]: rtlsdr.service: Unit entered failed state.
Jun 17 11:50:18 hassbian systemd[1]: rtlsdr.service: Failed with result ‘exit-code’.

However, if I run the bash script manually:

rtl_433 -f 344975000 -F json -U | mosquitto_pub -t homeassistant/sensor/honeywell -l -V mqttv311

it gives me this:

mosquitto_pub: command not found
[R82XX] PLL not locked!
rtlsdr_demon_write_reg failed with -9
r82xx_write: i2c wr failed=-9 reg=06 len=1

It does show that PLL is not locked

EDIT: Fixed. For some reason after I had to do a reinstall of my entire system (MicroSD failure), I forgot to install mosquitto_clients:

sudo apt-get install mosquitto-clients

then, edited my .sh file, took off the -v mqttv311 and added:

-u username -P password

after mosquitto_pub. Reloaded daemons, restarted, tested, and now my doors are showing in HASS again! horray!

Not much of a coder but her is the python script I use to periodically send updates (debug junk still present). I pipe rtl_433 to this script instead of directly to mosquitto_pub.

#!/usr/bin/env python3

import sys, os
import json
import signal
import threading
import time

HOST_NAME = "host"
PORT = 1883
CA = "/etc/ssl/certs/ca-certificates.crt"
USERNAME = "user"
PASSWORD = "password"
BASE_TOPIC = "base/topic"
PUBLISH_RATE = 120

_sensors = {}
_debug = False
_running = True

def publish(id, value):
    try:
        #Ignore mqtt errors and timeouts
        if (PORT == 1883):
            #Normal
            runCMD = 'mosquitto_pub -h {} -p {} -u {} -P {} -t {}/{} -m {}'.format(HOST_NAME, PORT, USERNAME, PASSWORD, BASE_TOPIC, id, value)
        else:
            #SSL
            runCMD = 'mosquitto_pub -h {} -p {} --cafile {} -u {} -P {} -t {}/{} -m {}'.format(HOST_NAME, PORT, CA, USERNAME, PASSWORD, BASE_TOPIC, id, value)
        debug_out(runCMD)
        #Using os to avoid setting up client
        os.system(runCMD)
    except:
        pass

def publish_thread():
    loop_timer = 0
    while _running:
        time.sleep(1)
        #Use loop timer so thread kill happens within 1 second
        loop_timer += 1
        if (loop_timer >= PUBLISH_RATE):
            loop_timer = 0
            debug_out("PUBLISH")
            #Publish last values periodicly
            for key, value in _sensors.items():
                publish(key, value)  

def debug_out(message):
    if _debug:
        print(message)

def set_exit_handler(func):
    signal.signal(signal.SIGTERM, func)

def on_exit(sig, func=None):
    global _running
    debug_out("EXIT")
    #Kill thread
    _running = False            
    sys.exit(0)

if __name__ == '__main__':
    debug_out("Started mqtt")
    set_exit_handler(on_exit)
    #Start periodic publish thread
    thread = threading.Thread(target=publish_thread)
    thread.start()
    for line in sys.stdin:
        #Have line from rtl_433
        try:
            #Throw error if something not valid
            data = json.loads(line)
            sensor_id = data['id']
            sensor_event = data['event']
            #Save and publish only once - sensors repeat themselves
            if (sensor_id in _sensors):
                if (_sensors[sensor_id] != sensor_event):
                    debug_out("CHANGE")
                    publish(sensor_id, sensor_event)
                    _sensors[sensor_id] = sensor_event
            else:
                debug_out("NEW")
                publish(sensor_id, sensor_event)
                _sensors[sensor_id] = sensor_event                
        except (KeyboardInterrupt) as error: # Ctrl-C
            debug_out("STOP")
            #Kill thread
            _running = False            
            break;
        except (SystemExit) as error: # sys.exit()
            debug_out("STOP")
            #Kill thread
            _running = False            
            break;
        except (Exception) as error:
            debug_out("ERROR")
            #Ignore and keep going
            pass
    debug_out("END")
1 Like

I just came across this today, and wanted to thank @Vexamus for it. I have an Andersen Verilock sensor on my sliding door and had it reporting through the Andersen Translator that I could only get working with z-wave on my old smartthings. It was the last remaining thing I needed to move over. The Verilocks show up as honeywell sensors, and the evernts/states show the lock and opening status. So know with an RTL usb stick and a pi-zero I have this working and going right into HA without a need for the translator and z-wave/smartthings!

I set it up like this:

- platform: mqtt
  state_topic: "homeassistant/sensor/honeywell"
  name: "Sliding Door"
  qos: 0
  value_template: '{% if value_json.id is equalto 591203 %} {{value_json.state}} {% else %} {{states.sensor.sliding_door.state}} {% endif %}'
 
- platform: mqtt
  state_topic: "homeassistant/sensor/honeywell"
  name: "Sliding Door Lock"
  qos: 0
  value_template: '{% if (value_json.id is equalto 591203) and (value_json.event is equalto 32) %} unlocked {% elif (value_json.id is equalto 591203) and (value_json.event is equalto 0) %} locked {% else %} {{states.sensor.sliding_door_lock.state}} {% endif %}'
2 Likes

Thanks for pointing me towards this docker image.

I tweaked it a little to allow for each sensor to have it’s own MQTT topic and persistent states.

I added ‘jq’ to the Docker file build and added $USER and $PASS environment variables.

I also configured my docker run command to restart=unless-stopped

Here’s the content of my rtl2mqtt.sh file

rtl_433 -f 344975000 -F json -M utc | while read line
do
  sensor_id=`echo $line |  jq -c ".id"`
  sensor_data=`echo "$line"`
  
  echo $sensor_id
  echo $sensor_data
  #send sensor data to unique MQTT topic by sensor ID. MQTT debug on '-d'
  echo $sensor_data | mosquitto_pub -h $MQTT_HOST -p 1883 -i RTL_433 -l -t honeywell/sensor/$sensor_id -u $USER -P $PASS -d

done

Chris, were you able to integrate the Anderson Translator with one of the door/window sensors to communicate with Home Assistant’s z-wave integration? I’m thinking about ordering the Verilock and the Translator.