Skip to content

Commit

Permalink
examples: Add ability for mqtt_relay to use a config file (#3013)
Browse files Browse the repository at this point in the history
This commit adds the ability to read config values from
rtl_433_mqtt_relay.yaml (overriding defaults).  This read is skipped
if the yaml module can't be loaded or the config file can't be read,
so those without PyYAML or a config file see no change.

Those with a config file can set parameters for address/port to listen
for json-in-sylog, MQTT credentials, whether to post individual
values, a json dictionary, or both.

While rudimentary, this is a huge functional improvement, allowing
those using TLS and broker passwords (as arguably all should be) to
use the script without modifying it.
  • Loading branch information
gdt authored Jul 30, 2024
1 parent 1ab32ec commit d3975a4
Showing 1 changed file with 54 additions and 21 deletions.
75 changes: 54 additions & 21 deletions examples/rtl_433_mqtt_relay.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,52 @@
import json
import paho.mqtt.client as mqtt

# Syslog socket configuration
UDP_IP = "127.0.0.1"
UDP_PORT = 1433

# MQTT broker configuration
MQTT_HOST = "127.0.0.1"
MQTT_PORT = 1883
MQTT_USERNAME = None
MQTT_PASSWORD = None
MQTT_TLS = False
MQTT_PREFIX = "sensor/rtl_433"
MQTT_INDIVIDUAL_TOPICS = True
MQTT_JSON_TOPIC = True
# The config class represents a config object. The constructor takes
# an optional pathname, and will switch on the suffix (.yaml for now)
# and read a dictionary.
class rtlconfig(object):

# Initialize with default values.
c = {
# Syslog socket configuration
'UDP_IP': "127.0.0.1",
'UDP_PORT': 1433,

# MQTT broker configuration
'MQTT_HOST': "127.0.0.1",
'MQTT_PORT': 1883,
'MQTT_USERNAME': None,
'MQTT_PASSWORD': None,
'MQTT_TLS': False,
'MQTT_PREFIX': "sensor/rtl_433",
'MQTT_INDIVIDUAL_TOPICS': True,
'MQTT_JSON_TOPIC': True,
}

def __init__(self, f=None):
fdict = None

# Try to read a dictionary from f.
if f:
try:
# Assume yaml. \todo Check and support other formats
import yaml
with open(f) as fh:
fdict = yaml.safe_load(fh)
except:
print('Did not read {f} (no yaml, not found, bad?).'.format(f=f))

# Merge fdict into configdict.
if fdict:
for (k, v) in fdict.items():
self.c[k] = v

# Support c['name'] references.
def __getitem__(self, k):
return self.c[k]

# Create a config object, defaults modified by the config file if present.
c = rtlconfig("rtl_433_mqtt_relay.yaml")

def mqtt_connect(client, userdata, flags, rc):
"""Handle MQTT connection callback."""
Expand All @@ -50,7 +83,7 @@ def mqtt_disconnect(client, userdata, rc):

# Create listener for incoming json string packets.
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.bind((UDP_IP, UDP_PORT))
sock.bind((c['UDP_IP'], c['UDP_PORT']))


# Map characters that will cause problems or be confusing in mqtt
Expand All @@ -70,15 +103,15 @@ def publish_sensor_to_mqtt(mqttc, data, line):
# Construct a topic from the information that identifies which
# device this frame is from.
# NB: id is only used if channel is not present.
path = MQTT_PREFIX
path = c['MQTT_PREFIX']
if "model" in data:
path += "/" + sanitize(data["model"])
if "channel" in data:
path += "/" + str(data["channel"])
if "id" in data:
path += "/" + str(data["id"])

if MQTT_INDIVIDUAL_TOPICS:
if c['MQTT_INDIVIDUAL_TOPICS']:
# Publish some specific items on subtopics.
if "battery_ok" in data:
mqttc.publish(path + "/battery", data["battery_ok"])
Expand All @@ -92,7 +125,7 @@ def publish_sensor_to_mqtt(mqttc, data, line):
if "depth_cm" in data:
mqttc.publish(path + "/depth", data["depth_cm"])

if MQTT_JSON_TOPIC:
if c['MQTT_JSON_TOPIC']:
# Publish the entire json string on the main topic.
mqttc.publish(path, line)

Expand Down Expand Up @@ -120,11 +153,11 @@ def rtl_433_probe():
mqttc = mqtt.Client()
mqttc.on_connect = mqtt_connect
mqttc.on_disconnect = mqtt_disconnect
if MQTT_USERNAME != None:
mqttc.username_pw_set(MQTT_USERNAME, password=MQTT_PASSWORD)
if MQTT_TLS:
if c['MQTT_USERNAME'] != None:
mqttc.username_pw_set(c['MQTT_USERNAME'], password=c['MQTT_PASSWORD'])
if c['MQTT_TLS']:
mqttc.tls_set()
mqttc.connect_async(MQTT_HOST, MQTT_PORT, 60)
mqttc.connect_async(c['MQTT_HOST'], c['MQTT_PORT'], 60)
mqttc.loop_start()

## Receive UDP datagrams, extract json, and publish.
Expand Down

0 comments on commit d3975a4

Please sign in to comment.