RTL_433 to MQTT with Acurite Weather Sensors and Itron Water Meter

I’ve had an Acurite Access and some sensors for a couple years, but it bugged me that I couldn’t get this data into Home Assistant, so I finally did something about that.

  • Edit 2021-06-24: Modified to have rtl_433 publish to individual topics and removed demux step

This is a complete end-to-end guide of setting up rtl_433 on a Raspberry Pi to read data into MQTT and then into Home Assistant sensors.

For reference, I’m using:

  • A Raspberry Pi 2B v1.1 (which also runs my secondary Pihole DNS server)
  • A $8 RTL2832U USB tuner (identifies as ID 0bda:2838 Realtek Semiconductor Corp. RTL2838 DVB-T)
    RTL2832U
  • Home Assistant and MQTT run on other virtual machines
  • My own 3 Acurite Tower temp+humidity sensors, plus a neighbor’s nearby 5-in-1 weather station and another 3-in-1 station.

A lot of this is based on John’s Tech Blog: 433 MHz Signals and Shit
so much thanks to him!

rtl_433 Setup

Building

sudo apt-get install git libtool libusb-1.0.0-dev librtlsdr-dev rtl-sdr build-essential autoconf cmake pkg-config  

git clone https://github.com/merbanan/rtl_433.git

cd rtl_433/
mkdir build
cd build
cmake ..
make
sudo make install

Running rtl_433

To test it out, simply run rtl_433, and if successful you should start seeing sensor data:

It’s pretty simple then to connect it to MQTT:

rtl_433 -F json -M utc -F mqtt://your_mqtt_server,retain=0,events=rtl_433[/model][/id]

You can also specify user=foo,pass=bar in that connection string.

This streams all sensors to one based on their model and unique id, so for example, rtl_433/Acurite-Tower/8958.

Running as a service

Create a systemd unit file, and move all the command-line options to a config file to make it easier to deal with:

/etc/systemd/system/rtl_433.service:

# based on https://github.com/merbanan/rtl_433/issues/1651
[Unit]
Description=RTL_433 service script
StartLimitIntervalSec=5
Documentation=https://github.com/merbanan/rtl_433/README.md
After=syslog.target network.target

[Service]
Type=exec
ExecStart=/usr/local/bin/rtl_433 -c /etc/rtl_433/service.conf

# Restart script if stopped
Restart=always
# Wait 30s before restart
RestartSec=30s

# Tag things in the log
# View with: sudo journalctl -f -u rtl_433 -o cat
SyslogIdentifier=rtl_433

StandardOutput=syslog
StandardError=syslog

[Install]
WantedBy=multi-user.target

/etc/rtl_433/service.conf:

output json
output mqtt://your_mqtt_server,retain=0,events=rtl_433[/model][/id]
report_meta time:utc

Now you can start with sudo systemctl start rtl_433 and manage it like any other service, and it should auto-start on boot.

Payload Examples

rtl_433/Acurite-Tower/8958

Publishes about every 15-20 seconds:

{
   "time":"2021-06-14 03:31:05",
   "model":"Acurite-Tower",
   "id":8958,
   "channel":"A",
   "battery_ok":0,
   "temperature_C":19.4,
   "humidity":41,
   "mic":"CHECKSUM"
}

rtl_433/Acurite-5n1/1908

This publishes about every 15-20 seconds, but alternates between two payloads:

{
   "time":"2021-06-14 03:24:57",
   "model":"Acurite-3n1",
   "message_type":32,
   "id":824,
   "channel":"A",
   "sequence_num":0,
   "battery_ok":1,
   "wind_avg_mi_h":0,
   "temperature_F":64.8,
   "humidity":87,
   "mic":"CHECKSUM"
}
{
   "time":"2021-06-14 03:25:17",
   "model":"Acurite-5n1",
   "message_type":49,
   "id":1908,
   "channel":"B",
   "sequence_num":0,
   "battery_ok":1,
   "wind_avg_km_h":2.6556,
   "wind_dir_deg":202.5,
   "rain_in":20.43,
   "mic":"CHECKSUM"
}

rtl_433/Acurite-3n1/824

{
   "time":"2021-06-14 03:43:01",
   "model":"Acurite-3n1",
   "message_type":32,
   "id":824,
   "channel":"A",
   "sequence_num":0,
   "battery_ok":1,
   "wind_avg_mi_h":0,
   "temperature_F":64.8,
   "humidity":88,
   "mic":"CHECKSUM"
}

Home Assistant Config

Optional: Handling message_type

As mentioned above, the “5n1” sensor publishes two different payloads, and this causes some problems. If you are using a sensor value of anything that doesn’t appear in both mesages (such as wind_dir_deg) it will be unavailable 50% of the time, and same if you’re making use of any attributes on a dashboard. It also just means the attributes constantly change between the two payloads, which is annoying if nothing else.

If you don’t have sensors that do this (or don’t care), this step can be skipped.

Unfortunately, rtl_433 isn’t aware of the message_type property so can’t handle this natively, but we can use an automation to re-publish these messages to a new topic:

- id: '1624586003695'
  alias: RTL433 MQTT message_type Demuxer
  description: Split rtl_433/# signals into msg topics, if message_type exists
  trigger:
  - platform: mqtt
    topic: rtl_433/+/+
  condition:
  - condition: template
    value_template: '{{ trigger.payload_json.message_type != null }}'
  action:
  - service: mqtt.publish
    data:
      payload: '{{trigger.payload}}'
      topic: rtl_433/{{trigger.payload_json.model or "UnknownModel"}}/{{trigger.payload_json.id
        or "UnknownId"}}/msg{{trigger.payload_json.message_type}}
  mode: single

If a message is received that has a message_type value, it is republished to a topic such as rtl_433/Acurite-5n1/1908/msg56. This can be used within the HomeAssistant sensor configuration to avoid all the issues I mentioned.

Sensors

Now getting these back into normal sensors is pretty simple:

- platform: mqtt
  name: Outside Temperature (Deck)
  device_class: temperature
  unit_of_measurement: '°C'
  value_template: '{{ value_json.temperature_C }}'
  state_topic: rtl_433/Acurite-Tower/8958
  json_attributes_topic: rtl_433/Acurite-Tower/8958

- platform: mqtt
  name: Outside Temperature
  device_class: temperature
  unit_of_measurement: '°C'
  value_template: '{{ ((value_json.temperature_F - 32) * 5/9) | round(1) }}'
  state_topic: rtl_433/Acurite-5n1/1908/msg56
  json_attributes_topic: rtl_433/Acurite-5n1/1908/msg56
- platform: mqtt
  name: Outside Humidity
  device_class: humidity
  value_template: '{{ value_json.humidity }}'
  state_topic: rtl_433/Acurite-5n1/1908/msg56
- platform: mqtt
  name: Outside Wind
  unit_of_measurement: 'km/h'
  value_template: '{{ value_json.wind_avg_km_h  | round(1) }}'
  state_topic: rtl_433/Acurite-5n1/1908/msg49
  json_attributes_topic: rtl_433/Acurite-5n1/1908/msg49

The sensors are usable just like any other, and include a bunch of extra attributes if you want to make use of those:

19 Likes

Water meter

I also managed to collect consumption data from my water meter.

It’s a Itron Hershey Translator Sensus ECR ERW-0771-412, with FCC ID EO960W on 915 MHz.

I found this by just running rtl_433 -f 915M – this got me the ID for the mqtt topic (which is the same as the one printed on the box).

Aside, I’ve also tried other bands but haven’t found anything interesting yet. My power meter is unfortunately in the 2.4GHz band which the USB RTL-SDR can’t do. YMMV

rtl_433

With the above configuration, the biggest change is to get rtl_433 to listen on both the 433MHz and 915Mhz bands. I added the following to my /etc/rtl_433/service.conf:

# scan 433 and 915, but spend more time in 433
hop_interval 60
frequency 433.92M
frequency 915M
frequency 433.92M
frequency 433.92M

The meter broadcasts about every 45 seconds, so with this config, rtl_433 spends 3 minutes listening on 433MHz for every 1 minute on 915MHz.

Home Assistant Sensors

The sensor in Home Assistant is pretty easy:

- platform: mqtt
  name: Water Consumption
  unit_of_measurement: 'm³'
  value_template: '{{ value_json.consumption_data }}'
  state_topic: rtl_433/ERT-SCM/27xxxxxx
  json_attributes_topic: rtl_433/ERT-SCM/27xxxxxx

I also added some utility_meter sensors to track consumption over time:

utility_meter:
  water_consumption_daily:
    source: sensor.water_consumption
    cycle: daily
  water_consumption_weekly:
    source: sensor.water_consumption
    cycle: weekly
  water_consumption_monthly:
    source: sensor.water_consumption
    cycle: monthly

Why?

I don’t know. Because it’s there and was easy.

It’s worth noting that because this is in (1 cubic meter == 1000L == 264.17 gallons) with no fractional value the number changes quite slowly. I’m not sure what I’m going to do with this yet other than show a “weekly/monthly water usage” metric on a dashboard.

I will likely not keep the “daily” consumption meter, because we go through less than 1000L per day and so it often shows 0. I’ve only had it increase by 2 since I started monitoring – I got lucky and the first happened literally within an hour of when I first added the sensor.

2 Likes

Single MQTT topic + Demuxing

In my first iteration of this, I had streamed all rtl_433 data to a single topic and used an automation to demultiplex them (aka: split them into their own MQTT topics) before realizing rtl_433 can do this natively. I’ve edited the post, but in case that’s useful for something, here’s how to accomplish the demux step:

With rtl_433 publishing to a single topic: mqtt://your_mqtt_server,retain=0,events=rtl_433/_raw

Create an automation:

- alias: RTL433 MQTT Demuxer
  description: Split rtl_433/_raw signals into individual topics
  trigger:
  - platform: mqtt
    topic: rtl_433/_raw
  action:
  - service: mqtt.publish
    data:
      payload: '{{trigger.payload}}'
      topic: rtl_433/{{trigger.payload_json.model or "UnknownModel"}}/{{trigger.payload_json.id
        or "UnknownId"}}{%- if trigger.payload_json.message_type -%}/msg{{trigger.payload_json.message_type}}{%-
        endif -%}
  mode: single

This takes any published mqtt message and re-publishes it at rtl_433/Model-Name/1234 (where 1234 is its id) – or if it contains message_type, then rtl_433/Model-Name/1234/msg56.

(this idea is based on Multi sensor using same MQTT topic - #3 by 123 but generic)

rtl_433 built-in demuxing

For reference, rtl_433 has placeholders when publishing, so it supports doing: mqtt://your_mqtt_server,retain=0,events=rtl_433[/model][/id] (see more info here).

hi @gregmac , thanks for sharing your project.
I’m trying to do something similar with inkbird swimming pool sensor supported by this library but I found a problem with it, I use the same set-up than you with that dongle and rpi4 as home assistant but I realized that detection range with the antenna is not enough when I put the sensor in swimming pool, it doesn’t get values updated there but when I get it closer everything works fine with Home assistant, the distance between both can be 8 meters so I’m quite dissapointed due to I thought It should be more distance… I would like to ask you if you had problem on it or if you know how can I change antenna gain to try to get more distance. I saw it can be possible but by command line but I use rtl_433 home assistant addon and adding gain 40 I only can see 19,2 db
Thanks.

I have noticed that when I put the msg# in the state topic it “breaks” the sensor. but without it I am getting other weather stations data. Any clue? And I have a 5-1 but my radio is picking up a prologue as well and pulling its data

I don’t have a lot of experience on this side yet – I guess I got lucky with antenna placement and it just worked for my use.

You can definitely try finding a higher-gain antenna, but this is way, way outside my area of expertise. I would say if you want to learn about and play with antennas and SDR’s, this is a potential way to go, but there’s a chance you spend a lot of money and time and still don’t get a signal.

If you don’t want to move your Home Assistant Pi, another option is to get a second Pi (Zero W perhaps) to run just rtl433, and locate it and the antenna in a place where you get a good signal. If you have two SDR’s you can run rtl433 on both Pi’s; you might get duplicate messages but it’s really a non-issue.

I’m not exactly following, because you seem to be mixing terms. By “msg#” do you mean message_type?

In my setup, rtl_433 publishes to topics like:

rtl_433/Acurite-5n1/1908

where 1908 is the unique ID of that particular device.

I also setup a message_type demuxer automation to re-publish to message-specific topics like:

rtl_433/Acurite-5n1/1908/msg56

where msg56 is the content type of the payload. In my example, I showed the 5n1 publishing msg56 with Temperature and Humidity, and msg49 with Wind.

Your sensors should always subscribe to the device id you care about. If they publish multiple messages, you’ll need to do the demuxer setup, and subscribe to that topic instead.

If in doubt, use a tool like Mosquitto_sub to view the MQTT stream directly, and you can even subscribe with a wildcard like mosquitto_sub -t rtl_433/#. The state_topic configured in the HA sensor needs to match the topic in mqtt.

Before it will start on boot you also need to run this commcand:

sudo systemctl enable /etc/systemd/system/rtl_433.service

Thought I’d pass it on as being a newbie to Linux based O/S it took me a while to track down why it wasn’t working on boot up.

Thank you for the great write up, now to get my 5n1 mounted!

2 Likes

This was awesome! Thank you so much for the write up.

Thank you thank you! I just followed this guide using a headless Debian VM on my Proxmox box. There were some minor tweaks I needed to do, like for Debian I only needed to run “apt install rtl-433” to get rtl_433 installed rather than having to build it manually. Then I just needed to edit the path in the service script from “/usr/local/bin/rtl_433” to “/usr/bin/rtl_433” and enable the service.

I’m also using a rather odd temperature sensor for this, I have a Timex atomic clock that came with an Acurite 606TX sensor and rtl_433 was able to find it just fine.

Hello,

Regarding your water meter - do I understand correctly that it is something installed by the utility?

I have a well with a water filtration system attached to it and want to understand what my water usage looks like. Was looking for wireless zigbee/433Mhz water flow sensors but seems nothing like this exists for a price less than $50

I’m having a hard time with rtl433tomqtt and 515 accurate sensors. For some reason, no sensor readings are showing up in the logs. The sensors are working (they are reporting correctly to the accurate weather station), the rtlsdr usb stick is working (I tried 2 different ones), the rtl433 service running in a docker container is finding the usb stick without issues, connecting to it and tuning to the right frequency, and yet, no sensor readings are showing up in the logs… I’m baffled. Any ideas on how to troubleshoot this?

this is what the logs show:

admin@raspberrypi:~/Containers/rtl433tomqtt $ docker-compose up rtl433tomqtt
Starting rtl433tomqtt ... done
Attaching to rtl433tomqtt
rtl433tomqtt    | rtl_433 version unknown inputs file rtl_tcp RTL-SDR
rtl433tomqtt    | Use -h for usage help and see https://triq.org/ for documentation.
rtl433tomqtt    | Trying conf file at "rtl_433.conf"...
rtl433tomqtt    | Trying conf file at "/home/user/.config/rtl_433/rtl_433.conf"...
rtl433tomqtt    | Reading conf from "/home/user/.config/rtl_433/rtl_433.conf".
rtl433tomqtt    | Publishing MQTT data to mosquitto port 1883
rtl433tomqtt    | Publishing device info to MQTT topic "rtl_433/e466a871c32a/devices[/type][/model][/subtype][/channel][/id]".
rtl433tomqtt    | Publishing events info to MQTT topic "rtl_433/e466a871c32a/events".
rtl433tomqtt    | Publishing states info to MQTT topic "rtl_433/e466a871c32a/states".
rtl433tomqtt    | Registered 145 out of 175 device decoding protocols [ 1-4 8 11-12 15-17 19-21 23 25-26 29-36 38-60 63 67-71 73-100 102-105 108-116 119 121 124-128 130-149 151-161 163-168 170-175 ]
rtl433tomqtt    | Detached kernel driver
rtl433tomqtt    | Found Rafael Micro R820T tuner
rtl433tomqtt    | Exact sample rate is: 250000.000414 Hz
rtl433tomqtt    | [R82XX] PLL not locked!
rtl433tomqtt    | Sample rate set to 250000 S/s.
rtl433tomqtt    | Tuner gain set to Auto.
rtl433tomqtt    | Tuned to 433.920MHz.
rtl433tomqtt    | Allocating 15 zero-copy buffers
rtl433tomqtt    | MQTT Connected...
rtl433tomqtt    | MQTT Connection established.

Have you checked Settings-> Devices and Services → Integrations → Mosquitto broker ->Devices?

I’m not integrating with home assistant yet. I’m just watching the rtl_433 logs to see what’s happening. New readings should show up in the log but they don’t.

Ok, stupid mistake on my part. I installed an old Docker image with a version of rtl_433 that hadn’t been updated yet for the new Acurite sensors. Getting the new docker image from https://github.com/hertzg/rtl_433_docker solved the issue.

I notice that when Home Assistant restarts the rtl_433 loses connection to MQTT and I stop receiving messages. Previously I handled this by rebooting the Pi every hour, but now that I’ve moved to Ubuntu and have other things running on it, I would rather not have to reboot every hour.

is there anyway to detect it failing to post the MQTT messages, and restart the service? or something I can do to have rtl_433 auto restart when needed?

team, I was able to find my gas meter ( I think ) on 915Mhz, this is the MQTT msg, do you know how to integrate this into HA?

{
“time”: “2023-02-08 04:55:10”,
“model”: “ERT-SCM”,
“id”: 45431145,
“physical_tamper”: 2,
“ert_type”: 12,
“encoder_tamper”: 0,
“consumption_data”: 885965,
“mic”: “CRC”
}


( North Colorado )

This sounds strange to me, since rtl_433 has reconnects, and will exit if it can’t connect at all – and your init system can take care of that (I even posted a systemd script in the original post). I’ve had all this running for months, including doing upgrades, and I’ve never had it not work.

What version of rtl_433 are you running? When it stops working, is rtl_433 still running? does it log anything?

I pretty much posted exactly what you need to do in the Water meter post above.

You just need to change a few variables, and verify what units that number actually is in:

- platform: mqtt
  name: Power Consumption
  unit_of_measurement: 'kWh'
  device_class: power
  value_template: '{{ value_json.consumption_data }}'
  state_topic: rtl_433/ERT-SCM/45431145
  json_attributes_topic: rtl_433/ERT-SCM/45431145

You’ll probably want some utility_meter stuff too, rather than a forever-incrementing number.

one issue i had with this is that the station transmits the accumulated rain. Then when i changed the batteries it resetted the counter back to zero. so 2 years of rain data are skewed, i am thinking of creating a template sensor with an initial value that was the last before battery replacement, so it adds up the new one so i can maintain the cumulative. Any thoughts? this is the weather station issue, not HA