Skip to content

Commit

Permalink
Add support for MQTT autodiscovery
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronk6 committed Sep 24, 2024
1 parent 6de3012 commit cda315b
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
2 changes: 2 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
46 changes: 46 additions & 0 deletions mqtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions scripts/shairport-sync.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
};
Expand Down
5 changes: 5 additions & 0 deletions shairport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit cda315b

Please sign in to comment.