]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Add support for MQTT autodiscovery
authoraaronk6 <aaronk6@users.noreply.github.com>
Sun, 17 Mar 2024 12:12:55 +0000 (13:12 +0100)
committeraaronk6 <aaronk6@users.noreply.github.com>
Tue, 24 Sep 2024 18:32:08 +0000 (20:32 +0200)
common.h
mqtt.c
scripts/shairport-sync.conf
shairport.c

index 9de26f6366044ad00618127c211f626333ba3ba5..6a341f7be78e3b5218fb4c823b312a74e08c9a55 100644 (file)
--- a/common.h
+++ b/common.h
@@ -175,6 +175,8 @@ typedef struct {
   int mqtt_publish_parsed;
   int mqtt_publish_cover;
   int mqtt_enable_remote;
+  int mqtt_enable_autodiscovery;
+  char *mqtt_autodiscovery_prefix;
   char *mqtt_empty_payload_substitute;
 #endif
   uint8_t ap1_prefix[6];
diff --git a/mqtt.c b/mqtt.c
index fd172161f8087ec663fe567009e0c9baed5c390a..2b9bd5b222bf19ee6ced25ae2821c65a6a78b5f1 100644 (file)
--- a/mqtt.c
+++ b/mqtt.c
@@ -94,6 +94,52 @@ void on_connect(struct mosquitto *mosq, __attribute__((unused)) void *userdata,
     snprintf(remotetopic, strlen(config.mqtt_topic) + 8, "%s/remote", config.mqtt_topic);
     mosquitto_subscribe(mosq, NULL, remotetopic, 0);
   }
+
+  // send autodiscovery messages if enabled
+  if (config.mqtt_enable_autodiscovery && config.mqtt_publish_parsed) {
+    send_autodiscovery_messages(mosq);
+  }
+}
+
+void send_autodiscovery_messages(struct mosquitto *mosq) {
+    const char *autodiscovery_prefix = (config.mqtt_autodiscovery_prefix != NULL) ?
+        config.autodiscovery_prefix : "homeassistant";
+    char base_topic[256];
+    snprintf(base_topic, sizeof(base_topic), "%s/sensor/shairport-sync-", autodiscovery_prefix);
+
+    char full_topic[256];
+    char payload[1024];
+    const char *device_name = config.service_name;
+
+    const char *sensors[] = {
+        "artist", "album", "title", "genre", "format", "track_id", 
+        "client_ip", "client_name", "volume", "is_active", "is_playing", NULL
+    };
+    // Human-readable names
+    const char *sensor_names[] = {
+        "Artist", "Album", "Title", "Genre", "Format", "Track ID", 
+        "Client IP", "Client Name", "Volume", "Is Active", "Is Playing", NULL
+    };
+
+    for (int i = 0; sensors[i] != NULL; i++) {
+        snprintf(full_topic, sizeof(full_topic), "%s%s/config", base_topic, sensors[i]);
+        snprintf(payload, sizeof(payload),
+                 "{\n"
+                 "  \"name\": \"%s\",\n"
+                 "  \"state_topic\": \"%s/%s\",\n"
+                 "  \"icon\": \"mdi:music-note\",\n"
+                 "  \"unique_id\": \"shairport-sync-%s\",\n"
+                 "  \"device\": {\n"
+                 "    \"identifiers\": [\"shairport-sync\"],\n"
+                 "    \"name\": \"%s\",\n"
+                 "    \"model\": \"Shairport-Sync\",\n"
+                 "    \"manufacturer\": \"shairport-sync\"\n"
+                 "  }\n"
+                 "}", sensor_names[i], config.mqtt_topic, sensors[i], sensors[i], device_name);
+
+        mosquitto_publish(mosq, NULL, full_topic, strlen(payload), payload, 0, true);
+        debug(2, "[MQTT Autodiscovery]: Published autodiscovery for %s", sensor_names[i]);
+    }
 }
 
 // helper function to publish under a topic and automatically append the main topic
index 517a7560549b6d0fbcefd5a0f5dc86ba3234e5b3..8423b807b50b1e75ac177b9d3ab8e216846e27ed 100644 (file)
@@ -285,6 +285,8 @@ mqtt =
 //     Currently published topics:artist,album,title,genre,format,songalbum,volume,client_ip,
 //     Additionally, messages at the topics play_start,play_end,play_flush,play_resume are published
 //     publish_cover = "no"; //whether to publish the cover over mqtt in binary form. This may lead to a bit of load on the broker
+//  enable_autodiscovery = "no"; //whether to publish an autodiscovery message to automatically appear in Home Assistant
+//  autodiscovery_prefix = "homeassistant"; //string to prepend to autodiscovery topic
 //     enable_remote = "no"; //whether to remote control via MQTT. RC is available under `topic`/remote.
 //     Available commands are "command", "beginff", "beginrew", "mutetoggle", "nextitem", "previtem", "pause", "playpause", "play", "stop", "playresume", "shuffle_songs", "volumedown", "volumeup"
 };
index 1060e0b7d3cef08a0701db9951391b0aca0f8dfb..87ac0ea758f492267731d6d7ac11c3db694ee17a 100644 (file)
@@ -1300,6 +1300,10 @@ int parse_options(int argc, char **argv) {
     if (config.mqtt_publish_cover && !config.get_coverart) {
       die("You need to have metadata.include_cover_art enabled in order to use mqtt.publish_cover");
     }
+    config_set_lookup_bool(config.cfg, "mqtt.enable_autodiscovery", &config.mqtt_enable_autodiscovery);
+    if (config_lookup_string(config.cfg, "mqtt.autodiscovery_prefix", &str)) {
+      config.mqtt_autodiscovery_prefix = (char *)str;
+    }
     config_set_lookup_bool(config.cfg, "mqtt.enable_remote", &config.mqtt_enable_remote);
     if (config_lookup_string(config.cfg, "mqtt.empty_payload_substitute", &str)) {
       if (strlen(str) == 0)
@@ -2550,6 +2554,7 @@ int main(int argc, char **argv) {
   debug(1, "mqtt will%s publish parsed metadata.", config.mqtt_publish_parsed ? "" : " not");
   debug(1, "mqtt will%s publish cover Art.", config.mqtt_publish_cover ? "" : " not");
   debug(1, "mqtt remote control is %sabled.", config.mqtt_enable_remote ? "en" : "dis");
+  debug(1, "mqtt autodiscovery is %sabled.", config.mqtt_enable_autodiscovery ? "en" : "dis");
 #endif
 
 #ifdef CONFIG_CONVOLUTION