Get your smart electric, water and gas meter scm readings into home assistant with a RTL-SDR

Hrm, yeah it’s looking a bit funky…

I’m trying to think what the problem would be. Could it be that your meter is not reading for some time and gives an error after a while? You could try playing with the antenna. You could also adjust the total time for the statistics… Say after 10 minutes the statistics has purged the last value. You could try increasing the total time for the statistics and adjust the current value to reflect this time. For example:

  - platform: template
    sensors:
      current_gas_consumption:
        value_template: >
          {% if states.sensor.gas_stats_mean.attributes.min_value | float == 0 %}0
          {% elif states.sensor.gas_meter.state | float <= states.sensor.gas_stats_mean.attributes.min_value | float %}0
          {% else %}
          {{((states.sensor.gas_meter.state | float) - (states.sensor.gas_stats_mean.attributes.min_value | float)) * 1000 / 30 | max (0) | round(2) }}
          {% endif %}
        unit_of_measurement: 'cdm/min'
        friendly_name: "Average Current Gas Consumption (30 min)"

  - platform: statistics
    name: gas_stats
    entity_id: sensor.gas_meter
    max_age:
      minutes: 30
    friendly_name: "Gas Stats"

Also if you are using the RLT-433 library to send the data via MQTT to Homeassistant, it is less sensitive than the method I used. I actually tried it and had no problem reading my power meter, but had some trouble with my gas meter. you can find some details about this here

1 Like

I’ve found that my water meter does have a sticker/barcode that matches its transmissions. However, for gas, I’ve found that none of the barcodes actually printed on nearby gas meters looks anything like the broadcast IDs. So I’ve done some experimenting and I agree with you - the meter’s radio ID is totally different, and the “consumption” is totally different as well. Again though there’s a linear relationship. So the question is “what units?” is the radio measurement in - since clearly the gas company can convert it to ft^3 no problem. I’m hypothesizing “meter_reading = x*radio_reading + y”, maybe?

Hey all! I have this working for my electric meter but it keeps crashing within a few hours:

Apr 24 04:09:55 harry amrscm2mqtt[823]: 04:09:55.149104 main.go:343: Receiver context cancelled.
Apr 24 04:10:00 harry amrscm2mqtt[823]: 04:09:58.264569 main.go:320: read tcp 127.0.0.1:47792->127.0.0.1:1234: i/o timeout
Apr 24 04:10:00 harry amrscm2mqtt[823]: io.ReadFull
Apr 24 04:10:00 harry amrscm2mqtt[823]: main.(*Receiver).Run.func2
Apr 24 04:10:00 harry amrscm2mqtt[823]:         /home/rlowens/go/src/github.com/bemasher/rtlamr/main.go:181
Apr 24 04:10:00 harry amrscm2mqtt[823]: runtime.goexit
Apr 24 04:10:00 harry amrscm2mqtt[823]:         /usr/lib/go-1.14/src/runtime/asm_amd64.s:1373

Any suggestions for either avoiding it crashing with this io.ReadFull error or a way to get the service to notice this crash and re-start itself?

I think I got a sensor working for “instant usage” approximation on my power meter…

I buffer the sensor because somehow as MQTT starts/restarts it makes “unknown” read “0” and messes up my stats thinking the meter “rolled over”, that is optional.

sensor:

  - platform: mqtt
    name: "Power Company Meter"
    unique_id: "power_company_meter_consumption"
    state_topic: "homeassistant/sensor/rtlamr/scm/1234"
    unit_of_measurement: 'kWh'
    value_template: "{{ value_json.Message.Consumption | float / 100.0 }}"

  - platform: template
    sensors:

      power_company_meter_buffered:
        friendly_name: "Power Company Meter Buffered"
        unit_of_measurement: "kWh"
        value_template: >-
          {% if states('sensor.power_company_meter') == "unknown" %}
            {{ states('sensor.power_company_meter_buffered') }}
          {% else %}
            {{ states('sensor.power_company_meter') }}
          {% endif %}

utility_meter:
  monthly_electric_meter:
    source: sensor.power_company_meter_buffered
    cycle: monthly
    offset:
      days: 0

  weekly_electric_meter:
    source: sensor.power_company_meter_buffered
    cycle: weekly

  daily_electric_meter:
    source: sensor.power_company_meter_buffered
    cycle: daily

The part to make it instant readings…I put in some sanity checks because I know I should never go much above 50kW instant usage (200A 240V main) so I figure if its more than 2x that I have a bad reading. I also can’t backfeed so negative is false data for me.

# Compute real time (approximate) usage by measuring the
# time difference between changes and amount of change

sensor:
  - platform: statistics
    entity_id: sensor.power_company_meter_buffered
    name: "Power Company Meter Stats"
    sampling_size: 2
    # age defines how long previous value waits without change assumed zero
    max_age: '00:10:00'

  - platform: template
    sensors:
      power_meter_current_power:
        friendly_name: "Power Meter Current Power"
        unit_of_measurement: "kW"
        icon_template: hass:flash
        value_template: >-
          {% if state_attr('sensor.power_company_meter_stats','count') | int < 2 %}
            0
          {% else %}
            {% set rate_calc = ( state_attr('sensor.power_company_meter_stats', 'change')|float/
                 ((state_attr('sensor.power_company_meter_stats', 'max_age') - state_attr('sensor.power_company_meter_stats', 'min_age')).total_seconds()/3600)
               ) | round(2) %}
            {% if rate_calc < -100 or rate_calc > 100%}
              0
            {% else %}
              {{ rate_calc }}
            {% endif %}
          {% endif %}

End result:

For another RTL-based addon RTL_433 I looked at one of the sensor values and if it hadn’t changed in an interval I expected it should, I restart the addon. I used a template-sensor on the last_updated attribute and made an educated guess if its gone more than X time in my case that likely means I missed some data and it is stuck as an automation trigger.

I’m using a separate Linux system that pre-dates my home automation to run RTLAMR and push it into MQTT over my network…so I have a number of watchdogs on the services that I don’t think would be possible with HomeAssistant the way it uses containers.

I’m running RTLAMR in a separate VM from HomeAssistant. I just need help creating those watchdogs, if you don’t mind.

Sure.

I run my watchdog with a cron-job (crontab) on the ‘root’ user

*/5 * * * * /root/rtlamr_watchdog.sh >/dev/null 2>&1

Here’s the contents of my script for the watchdog (note: requires lsof utility installed):

#!/bin/bash
#
# This file is designed to monitor for a failure in soundmodem or aprx and restart the process automatically
# Save this file to /root/aprx_watchdog.sh
#
# Crontab entry
# */5 * * * * /root/rtlamr_watchdog.sh >/dev/null 2>&1

# watchdog if rtl_tcp crashes
/bin/systemctl is-active --quiet rtl_tcp || (
        /bin/echo 'Service rtl_tcp failed, restarting rtl_tcp and rtlamr . . .' | /usr/bin/wall
        /usr/sbin/service rtl_tcp restart
        sleep 5
        /usr/sbin/service rtl_amr restart
        sleep 30
)

# watchdog if rtlamr crashes
/bin/systemctl is-active --quiet rtlamr || (
        /bin/echo 'Service rtlamr failed, restarting . . .' | /usr/bin/wall
        /usr/sbin/service rtlamr restart
        sleep 30
)

# watchdog if rtl_tcp networking fails
/usr/bin/lsof -i | grep rtl_tcp | grep LISTEN > /dev/null || (
        /bin/echo 'Network socket rtl_tcp failed, restarting rtl_tcp and rtlamr . . .' | /usr/bin/wall
        /usr/sbin/service rtl_tcp restart
        sleep 5
        /usr/sbin/service rtl_amr restart
        sleep 30
)

# watchdog if rtlamr networking fails
/usr/bin/lsof -i | grep rtlamr | grep ESTABLISHED > /dev/null || (
        /bin/echo 'Network socket rtlamr failed, restarting . . .' | /usr/bin/wall
        /usr/sbin/service rtlamr restart
        sleep 30
)

Here is what I used to build the init-startup scripts for rtl_tcp and rtlamr, note you would probably need to tweak what it runs since mine was aimed a PHP script (which writes to my sqlite app, and also throws out over MQTT)
You will want services for both rtl_tcp and rtlamr separately if you use my watchdog as-is. Basically I clone someone else’s template and change some fields…I automated it for rtl_tcp at least.

At this point I don’t have my repository fully updated but that should give you the bits I use.

Hopefully that helps!

Help Requested.

After running this flawlessly on a raspi zero w for nine months, I shut it down to mount the raspi and reroute some wires. Now I’m not getting any updates to HA. I’m using Mosquito MQTT on the HA side.

What I’m looking for is ways to monitor each process for errors. My concern is that I may have messed up the coax wire into the SDR.

How can I monitor what rtlamr is seeing? How do I see if amrscm2mqtt is pushing a MQTT message and see if the issue is on the HA side? I do not see any MQTT logins like I used to in the HA logs.

Any troubleshooting help would be appreciated. Thanks!

My RTL-SDR has fried on me once and it could not read anything. I am guessing that it was a cooling problem. You can always see the status of the service amridm2mqtt by typing in the console using

sudo systemctl status amridm2mqtt

However, when my SDR died, I confirmed that it was not working by trying to tune it to FM radio on my windows PC using one of many free softwares

As far as looking at MQTT signals, in Home Assistant, you can always listen to all MQTT clients by going in the Configuration > Intergrations > MQTT > Configure. Then in the listen dialogue, type # and listen… It will give every message that Home Assistant can receive.

Just to advise this is working great with the new Energy Monitoring in 2021.8.

Had to add a few more bits to the code per this thread - Energy: Not showing the expected entities for consumption - Configuration - Home Assistant Community (home-assistant.io)

  - platform: mqtt
    state_topic: "utilityreading/100855590/reading"
    name: "House Power Used"
    unit_of_measurement: kWh
    device_class: energy
    state_class: measurement
    value_template: "{{ value |float / 1000 }}"

homeassistant:
  # Customization file
  customize: !include customize.yaml
  customize_glob:
    sensor.*_used:
      last_reset: '1970-01-01T00:00:00+00:00'
      device_class: energy
      state_class: measurement 

I forked the original repo and rewrote the monitor to scan for “all” ERT types, so it includes SCM, SCMplus, IDM.

In addition to that:

  • The “state” value is still the base consumption in kWh but I added all attribute data from the SCM and IDM responses, so you can see extra information (see below for examples)
  • Messages are posted with ‘retain’ flag enabled so that the meter information is immediately available to HASS on restart
  • Messages are published to topics in more unique namespaces for easier filtering
  • Messages are published to an availability topic so that HASS can update accordingly when the service is up or down
  • A last_reset hack value is posted to workaround the issues with MQTT sensor and last_reset.

See the fork here: GitHub - TonyApuzzo/amridm2mqtt: runs rtlamr to read IDM power meter data and send to MQTT broker<

Example reading an SCM Meter:

state_class: measurement
last_reset: '1970-01-01T00:00:00+00:00'
ChecksumVal: 55361
Consumption: 74504
ID: XXXXXXXX
TamperEnc: 0
TamperPhy: 0
Type: 4
unit_of_measurement: kWh
friendly_name: Electric Meter
device_class: energy

Example reading an IDM Meter:

state_class: measurement
last_reset: '1970-01-01T00:00:00+00:00'
ApplicationVersion: 2
AsynchronousCounters: 22389
ConsumptionIntervalCount: 0
DifferentialConsumptionIntervals:  [ 1, 2, 1, 0, 2, 1, 2, 1, 0, 6, 10, 10, 10, 10, 10, 12, 11, 11, 10, 10, 10, 10, 11, 10, 11, 12, 11, 12, 12, 11, 12, 10, 13, 15, 11, 10, 11, 10, 11, 10, 7, 2, 1, 2, 1, 1, 0 ]
ERTSerialNumber: YYYYYYYY
ERTType: 7
HammingCode: 198
LastConsumptionCount: 2673708
ModuleProgrammingState: 204
PacketCRC: 60717
PacketLength: 92
PacketTypeID: 28
PowerOutageFlags: opAwAKEg
Preamble: 1431639715
SerialNumberCRC: 52453
TamperCounters: FoIhbUgS
TransmitTimeOffset: 346
unit_of_measurement: kWh
friendly_name: Electric Meter IDM
device_class: energy

Definitions for the above:

sensor:
  - platform: mqtt
    state_topic: "amr/reading/SCM/4/XXXXXXXX/message"
    name: "Electric Meter"
    unique_id: electric_meter_01
    unit_of_measurement: kWh
    device_class: energy
    state_class: measurement
    availability_topic: amr/status/availability
    last_reset_topic: amr/status/last_reset
    value_template: "{{ value_json.Message.Consumption }}"
    json_attributes_template: "{{ value_json.Message | tojson }}"
    json_attributes_topic: "amr/reading/XXXXXXXX/message"
    
  - platform: mqtt
    state_topic: "amr/reading/IDM/7/YYYYYYYY/message"
    name: "Electric Meter IDM"
    unique_id: electric_meter_02
    unit_of_measurement: kWh
    device_class: energy
    state_class: measurement
    availability_topic: amr/status/availability
    last_reset_topic: amr/status/last_reset
    value_template: "{{ value_json.Message.Consumption }}"
    json_attributes_template: "{{ value_json.Message | tojson }}"
    json_attributes_topic: "amr/reading/IDM/7/YYYYYYYY/message"
2 Likes

I put in a feature request for the Energy dashboard for those using rtlamr to be able to use the ccf reading from this as part of the gas consumption usage for those interested:

I could not find a way currently to get it to show up as an option for consumption.

Note that with the 2021.9 release, using last_reset_topic is deprecated as state_class: total_increasing is available to handle metering logic automatically.

Using my fork, you should be able to use the following definition of an MQTT sensor for gas meters:

packages/energy.yaml:

sensor:
  - platform: mqtt
    state_topic: !secret GAS_METER_01_TOPIC
    name: "Gas Meter"
    unique_id: gas_meter_01
    unit_of_measurement: m³
    device_class: gas
    state_class: total_increasing
    availability_topic: amr/status/availability
    # My meter reads in cubic feet, convert to cubic meters
    value_template: "{{ value_json.Message.Consumption | float * 0.02832 }}"
    json_attributes_template: "{{ value_json.Message | tojson }}"
    json_attributes_topic: !secret GAS_METER_01_TOPIC

secrets.yaml:

GAS_METER_01_TOPIC: 'amr/reading/SCM/2/32109876/message'

It turns out that my home gas meter only broadcasts values once per month when the utility company pings it, so it is hard to figure out if it is fully working or not. In my installation, the above sensor doesn’t show up in the ᴀᴅᴅ ɢᴀs sᴏᴜʀᴄᴇ dialog, so I am not sure if I have to wait until the next reading goes out in a month or if there is something else wrong.

EDIT: corrected state_class value in example.
EDIT2: added conversion from cubic feet to cubic meters

3 Likes

I think part of it too is m³ is supported, but ccf is not for gas from what I recall from the release stream they did, but I’m not 100% on this.

EDIT: Supported for the Energy Dashboard that is
image

yeah, my mqtt sensor said m³ but the consumption value provided by my meter is in cubic feet, I’ve edited my post above to include conversion between cf and m³.

My paper bill shows both therms and ccf, with the ccf number being 1/100 of what my meter reports. Annoyingly, the meter reading is only shown on my paper bill. The online statement that Xcel keeps pushing me to use only shows therms. It would be much harder to figure out what the actual values were if I was using online only billing.

I have it setup like your edited post but still can’t add it under the energy dashboard.

Sadly I am in the same boat. I have been trying to get it to show up without success.

Apologies for excessive confidence above, I was ASSuMEing that mine would show up once I got some MQTT messages from the gas meter, but that isn’t the case.

UPDATE: One month later and now my gas meter defined exactly as before is now showing up in the Energy Configuration page. Not sure what triggered it to start working, but I notice that the selection is now available after installing 2010.10.6

Hi @a3a this is super cool. This question is coming from someone with very little Raspberry Pi or Linux experience. Am I right to assume that all the installing steps (rtl-sdr package, gi, pip, paho-mqtt package, etc.) are done on a RaspBerry Pi running Linux? I see the repo says “Tested under Raspbian GNU/Linux 9.3 (stretch)”. Forgive me if the question is simple. I’d like to set this up myself, and maybe make a little video on how to do it for people who have only used a Pi for Home Assistant.

Is there a list of devices that have been confirmed to not work?

I just got a new meter (Colorado, USA) and it is an itron “Gen 5 Riva” (model: G5R1 and “TYPE R2SID”). The brocure is here and the fcc spec is here. It says things like 2.4GHz and the OS is Linux :frowning: (I like Linux, but that tells me it may be getting too smart). It also has the AMI 900MHz band, so maybe it is doing the mesh networking and the AMI broadcast. My guess is that it could be a config option for the installer.

It would be nice if someone had already done all the legwork to be able to report that, no, it doesn’t work. Instead, I am hoping it is a new kind of meter that no one has tried. I ordered and SDR anyway. Maybe I’ll find a use for it if this doesn’t work.