diff --git a/examples/rtl_433_mqtt_relay.py b/examples/rtl_433_mqtt_relay.py index 505d140cc..6248b75c6 100755 --- a/examples/rtl_433_mqtt_relay.py +++ b/examples/rtl_433_mqtt_relay.py @@ -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.""" @@ -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 @@ -70,7 +103,7 @@ 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: @@ -78,7 +111,7 @@ def publish_sensor_to_mqtt(mqttc, data, line): 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"]) @@ -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) @@ -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.