-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Read rtl_433_mqtt_hass.py configuration from rtl_433.conf #2841
base: master
Are you sure you want to change the base?
Changes from all commits
aa313f5
c360190
10e5ea9
f109051
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -105,6 +105,26 @@ | |
|
||
discovery_timeouts = {} | ||
|
||
CONFIG_PATHS = [ | ||
"/etc/rtl_433", | ||
"/usr/local/etc/rtl_433", | ||
os.path.expanduser("~/.config/rtl_433"), | ||
os.path.dirname(os.path.realpath(__file__)), | ||
os.path.join(os.path.dirname(os.path.realpath(__file__)), "data") | ||
] | ||
CONFIG_PATHS = [p for p in CONFIG_PATHS if os.path.exists(p)] | ||
|
||
CONFIG_FILENAME = "rtl_433.conf" | ||
|
||
def find_file_in_path(filename, paths, success_log=None): | ||
for path in paths: | ||
fullpath = os.path.join(path, filename) | ||
if os.path.exists(fullpath): | ||
if success_log: | ||
logging.info(success_log % path) | ||
return fullpath | ||
raise FileNotFoundError(f"File {filename} not found in paths: {paths}") | ||
|
||
# Fields that get ignored when publishing to Home Assistant | ||
# (reduces noise to help spot missing field mappings) | ||
SKIP_KEYS = [ "type", "model", "subtype", "channel", "id", "mic", "mod", | ||
|
@@ -863,6 +883,27 @@ def rtl_433_device_info(data, topic_prefix): | |
return (f"{topic_prefix}/{path}", id) | ||
|
||
|
||
def device_topic_from_data(data): | ||
device_topic_suffix = ''+args.device_topic_suffix | ||
keys = re.findall(r'\[([^\]]+)\]', device_topic_suffix) | ||
for key in keys: | ||
default = None | ||
k = key | ||
if key.startswith('/'): | ||
k = key[1:] | ||
if ':' in key: | ||
k, default = key.split(':') | ||
value = data.get(k, default) | ||
if key.startswith('/') and value is None: | ||
device_topic_suffix = device_topic_suffix.replace(f'[{key}]', '') | ||
continue | ||
elif key.startswith('/') and value is not None: | ||
value = '/' + str(value) | ||
|
||
device_topic_suffix = device_topic_suffix.replace(f'[{key}]', str(value)) | ||
return device_topic_suffix | ||
|
||
|
||
def publish_config(mqttc, topic, model, object_id, mapping, key=None): | ||
"""Publish Home Assistant auto discovery data.""" | ||
global discovery_timeouts | ||
|
@@ -923,6 +964,8 @@ def bridge_event_to_hass(mqttc, topic_prefix, data): | |
published_keys = [] | ||
|
||
base_topic, device_id = rtl_433_device_info(data, topic_prefix) | ||
base_topic = device_topic_from_data(data) | ||
|
||
if not device_id: | ||
# no unique device identifier | ||
logging.warning("No suitable identifier found for model: %s", model) | ||
|
@@ -960,7 +1003,7 @@ def bridge_event_to_hass(mqttc, topic_prefix, data): | |
def rtl_433_bridge(): | ||
"""Run a MQTT Home Assistant auto discovery bridge for rtl_433.""" | ||
|
||
mqttc = mqtt.Client() | ||
mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1) | ||
|
||
if args.debug: | ||
mqttc.enable_logger() | ||
|
@@ -1053,13 +1096,67 @@ def run(): | |
if not args.password and 'MQTT_PASSWORD' in os.environ: | ||
args.password = os.environ['MQTT_PASSWORD'] | ||
|
||
if not args.user or not args.password: | ||
logging.warning("User or password is not set. Check credentials if subscriptions do not return messages.") | ||
|
||
if args.ids: | ||
ids = ', '.join(str(id) for id in args.ids) | ||
logging.info("Only discovering devices with ids: [%s]" % ids) | ||
else: | ||
logging.info("Discovering all devices") | ||
|
||
found_config = False | ||
try: | ||
with open(find_file_in_path(CONFIG_FILENAME, CONFIG_PATHS)) as f: | ||
found = re.findall('^output (.*)$', f.read(), re.MULTILINE) | ||
devices = None | ||
events = None | ||
retain = None | ||
user = None | ||
password = None | ||
host = None | ||
port = None | ||
for find in found: | ||
if "mqtt" not in find: continue | ||
host = re.findall(r'mqtt://(.*?),', find)[0] | ||
devices = re.findall(r'devices=(.*?)(?:,+|$)', find) | ||
if len(devices) > 0: devices = devices[0] | ||
events = re.findall(r'events=(.*?)(?:,+|$)', find) | ||
if len(events) > 0: events = events[0] | ||
retain = re.findall(r'retain=(.*?)(?:,+|$)', find) | ||
if len(retain) > 0: retain = retain[0] | ||
|
||
if '@' in host: | ||
user, password = host.split('@')[0].split(':') | ||
host = host.split('@')[1] | ||
if ':' in host: | ||
host, port = host.split(':') | ||
found_config = True | ||
break | ||
except FileNotFoundError: | ||
logging.warning("Config file not found") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be helpful to be less ambiguous about what config file you are talking about in this and the other log messages. I would explicitly mention that it is rtl_433's config file and/or the path. Some of the Home Assistant add-ons have their own config files for this script. |
||
except Exception as e: | ||
logging.exception("Error reading config file") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, be explicit about the file. |
||
|
||
if found_config: | ||
if host: | ||
logging.info(f"Using host {host} from config") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as about, be more explicit about the source, "from config" is a bit ambiguous. |
||
args.host = host | ||
if port: | ||
logging.info(f"Using port {port} from config") | ||
args.port = int(port) | ||
if user: | ||
logging.info(f"Using user {user} from config") | ||
args.user = user | ||
if password: | ||
args.password = password | ||
if retain: | ||
logging.info(f"Using retain {retain} from config") | ||
args.retain = int(retain) | ||
if devices: | ||
logging.info(f"Using device_topic_suffix {devices} from config") | ||
args.device_topic_suffix = devices | ||
if events: | ||
logging.info(f"Using rtl_topic {events} from config") | ||
args.rtl_topic = events | ||
if not args.user or not args.password: | ||
logging.warning("User or password is not set. Check credentials if subscriptions do not return messages.") | ||
|
||
run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit, but it feels a bit unclean that you didn't remove the old assignment to
base_topic
.I know this whole script needs work, but If you don't want to refactor rtl_433_device_info, then just use:
_, device_id = rtl_433_device_info(data, topic_prefix)
.The underscore seems to be the prevailing convention for a value you don't care about when unpacking a tuple during assignment.