so I got it working. I had to change a few things:
The code for “amrscm2mqtt” had a few syntax errors, please see below the corrected code. I also renamed it to “amrscm2mqtt.py”
#!/usr/bin/env python3
'''
Runs rtlamr to watch for IDM broadcasts from power meter. If meter id
is in the list, usage is sent to 'readings/{meter id}/meter_reading'
topic on the MQTT broker specified in settings.
WATCHED_METERS = A Python list indicating those meter IDs to record and post.
MQTT_HOST = String containing the MQTT server address.
MQTT_PORT = An int containing the port the MQTT server is active on.
'''
import subprocess
import signal
import sys
import time
import paho.mqtt.publish as publish
import settings
# uses signal to shutdown and hard kill opened processes and self
def shutdown(signum, frame):
subprocess.call('/usr/bin/pkill -9 rtlamr', shell=True)
subprocess.call('/usr/bin/pkill -9 rtl_tcp', shell=True)
subprocess.call('/usr/bin/pkill -9 amridm2mqtt', shell=True)
sys.exit(0)
signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)
auth = None
if len(settings.MQTT_USER) and len(settings.MQTT_PASSWORD):
auth = {'username':settings.MQTT_USER, 'password':settings.MQTT_PASSWORD}
def send_mqtt(topic, payload,):
try:
publish.single(topic, payload=payload, qos=1, hostname=settings.MQTT_HOST, port=settings.MQTT_PORT, auth=auth)
except Exception as ex:
print("MQTT Publish Failed: " + str(ex))
time.sleep(30)
# start the rtl_tcp program
rtltcp = subprocess.Popen([settings.RTL_TCP + " > /dev/null 2>&1 &"], shell=True,
stdin=None, stdout=None, stderr=None, close_fds=True)
time.sleep(5)
# start the rtlamr program.
rtlamr = subprocess.Popen([settings.RTLAMR,
'-msgtype=scm',
'-format=csv'], stdout=subprocess.PIPE)
while True:
try:
# rtlamr's readline returns byte list, remove whitespace and convert to string
amrline = rtlamr.stdout.readline().strip().decode()
# split string on commas
flds = amrline.split(',')
if len(flds) != 9:
# proper SCM results have 9 fields
continue
# make sure the meter id is one we want
meter_id = int(flds[3])
if len(settings.WATCHED_METERS) and meter_id not in settings.WATCHED_METERS:
continue
# get some required info: current meter reading, current interval id, most recent interval $
read_cur = int(flds[7])
current_reading_in_kwh = (read_cur * settings.WH_MULTIPLIER) / 1000
send_mqtt(
'readings/' + str(meter_id) + '/meter_reading',
'%s' % (current_reading_in_kwh)
)
except:
time.sleep(2)
Next, I made some changes to the “amridm2mqtt.service” file. For some reason, my system did not like the “User=root” designation, so I deleted it. Also, I needed to explicitly call python3.
[Unit]
Description=AMR IDM to MQTT
After=network.target
[Service]
ExecStart=/usr/bin/python3 /opt/amridm2mqtt/amrscm2mqtt.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=amridm2mqtt
[Install]
WantedBy=multi-user.target
The service now auto starts and pushes MQTT messages to my broker.
I am by no means a python programmer; my strengths are in industrial automation. Therefore I have no idea if what I did was good or not… but it seems to work, so I will let it run for the next few days and see how it goes.
Thanks @biochemguy for the help