From 86a39f2dfb0a4302919d44568514f6dc0bb30a8f Mon Sep 17 00:00:00 2001
From: "Christian W. Zuckschwerdt" <christian@zuckschwerdt.org>
Date: Thu, 28 Dec 2023 21:17:22 +0100
Subject: [PATCH] Add mqtt base topic option (closes #2768)

---
 README.md          | 3 ++-
 man/man1/rtl_433.1 | 5 ++++-
 src/output_mqtt.c  | 7 +++++--
 src/rtl_433.c      | 3 ++-
 4 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 13d7348d..ca7e314c 100644
--- a/README.md
+++ b/README.md
@@ -430,11 +430,12 @@ E.g. -X "n=doorbell,m=OOK_PWM,s=400,l=800,r=7000,g=1000,match={24}0xa9878c,repea
 	Add MQTT options with e.g. -F "mqtt://host:1883,opt=arg"
 	MQTT options are: user=foo, pass=bar, retain[=0|1], <format>[=topic]
 	Default user and password are read from MQTT_USER and MQTT_PASSWORD env vars.
+	A base topic can be set with base=<topic>, default is "rtl_433/HOSTNAME".
 	Supported MQTT formats: (default is all)
 	  events: posts JSON event data
 	  states: posts JSON state data
 	  devices: posts device and sensor info in nested topics
-	The topic string will expand keys like [/model]
+	Any topic string overrides the base topic and will expand keys like [/model]
 	E.g. -F "mqtt://localhost:1883,user=USERNAME,pass=PASSWORD,retain=0,devices=rtl_433[/id]"
 	With MQTT each rtl_433 instance needs a distinct driver selection. The MQTT Client-ID is computed from the driver string.
 	If you use multiple RTL-SDR, perhaps set a serial and select by that (helps not to get the wrong antenna).
diff --git a/man/man1/rtl_433.1 b/man/man1/rtl_433.1
index 06f93aab..7426de0d 100644
--- a/man/man1/rtl_433.1
+++ b/man/man1/rtl_433.1
@@ -347,6 +347,9 @@ MQTT options are: user=foo, pass=bar, retain[=0|1], <format>[=topic]
 Default user and password are read from MQTT_USER and MQTT_PASSWORD env vars.
 .RE
 .RS
+A base topic can be set with base=<topic>, default is "rtl_433/HOSTNAME".
+.RE
+.RS
 Supported MQTT formats: (default is all)
 .RE
 .RS
@@ -359,7 +362,7 @@ Supported MQTT formats: (default is all)
   devices: posts device and sensor info in nested topics
 .RE
 .RS
-The topic string will expand keys like [/model]
+Any topic string overrides the base topic and will expand keys like [/model]
 .RE
 .RS
 E.g. \-F "mqtt://localhost:1883,user=USERNAME,pass=PASSWORD,retain=0,devices=rtl_433[/id]"
diff --git a/src/output_mqtt.c b/src/output_mqtt.c
index 29ff94e0..2ca47166 100644
--- a/src/output_mqtt.c
+++ b/src/output_mqtt.c
@@ -505,8 +505,9 @@ struct data_output *data_output_mqtt_create(struct mg_mgr *mgr, char *param, cha
     snprintf(client_id, sizeof(client_id), "rtl_433-%04x%04x%04x", host_crc, devq_crc, parm_crc);
 
     // default base topic
-    char base_topic[8 + sizeof(mqtt->hostname)];
-    snprintf(base_topic, sizeof(base_topic), "rtl_433/%s", mqtt->hostname);
+    char default_base_topic[8 + sizeof(mqtt->hostname)];
+    snprintf(default_base_topic, sizeof(default_base_topic), "rtl_433/%s", mqtt->hostname);
+    char const *base_topic = default_base_topic;
 
     // default topics
     char const *path_devices = "devices[/type][/model][/subtype][/channel][/id]";
@@ -545,6 +546,8 @@ struct data_output *data_output_mqtt_create(struct mg_mgr *mgr, char *param, cha
             retain = atobv(val, 1);
         else if (!strcasecmp(key, "q") || !strcasecmp(key, "qos"))
             qos = atoiv(val, 1);
+        else if (!strcasecmp(key, "b") || !strcasecmp(key, "base"))
+            base_topic = val;
         // Simple key-topic mapping
         else if (!strcasecmp(key, "d") || !strcasecmp(key, "devices"))
             mqtt->devices = mqtt_topic_default(val, base_topic, path_devices);
diff --git a/src/rtl_433.c b/src/rtl_433.c
index 44988426..c037c797 100644
--- a/src/rtl_433.c
+++ b/src/rtl_433.c
@@ -282,11 +282,12 @@ static void help_output(void)
             "\tAdd MQTT options with e.g. -F \"mqtt://host:1883,opt=arg\"\n"
             "\tMQTT options are: user=foo, pass=bar, retain[=0|1], <format>[=topic]\n"
             "\tDefault user and password are read from MQTT_USER and MQTT_PASSWORD env vars.\n"
+            "\tA base topic can be set with base=<topic>, default is \"rtl_433/HOSTNAME\".\n"
             "\tSupported MQTT formats: (default is all)\n"
             "\t  events: posts JSON event data\n"
             "\t  states: posts JSON state data\n"
             "\t  devices: posts device and sensor info in nested topics\n"
-            "\tThe topic string will expand keys like [/model]\n"
+            "\tAny topic string overrides the base topic and will expand keys like [/model]\n"
             "\tE.g. -F \"mqtt://localhost:1883,user=USERNAME,pass=PASSWORD,retain=0,devices=rtl_433[/id]\"\n"
             "\tWith MQTT each rtl_433 instance needs a distinct driver selection. The MQTT Client-ID is computed from the driver string.\n"
             "\tIf you use multiple RTL-SDR, perhaps set a serial and select by that (helps not to get the wrong antenna).\n"