Skip to content
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

MQTT Discovery - Announce switches #4531

Merged
merged 3 commits into from
Dec 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion sonoff/sonoff.ino
Original file line number Diff line number Diff line change
Expand Up @@ -1310,7 +1310,8 @@ boolean SendKey(byte key, byte device, byte state)
Format(key_topic, tmp, sizeof(key_topic));
if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) {
if (!key && (device > devices_present)) device = 1; // Only allow number of buttons up to number of devices
GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), key)); // cmnd/switchtopic/POWERx
GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand),
(key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx
if (9 == state) {
mqtt_data[0] = '\0';
} else {
Expand Down
154 changes: 107 additions & 47 deletions sonoff/xdrv_12_home_assistant.ino
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,21 @@ const char HASS_DISCOVER_RELAY[] PROGMEM =
"\"payload_available\":\"" D_ONLINE "\"," // Online
"\"payload_not_available\":\"" D_OFFLINE "\""; // Offline

const char HASS_DISCOVER_BUTTON[] PROGMEM =
const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM =
"{\"name\":\"%s\"," // dualr2 1 BTN
"\"state_topic\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",")
// "\"value_template\":\"{{value_json.%s}}\"," // POWER2
"\"payload_on\":\"%s\"," // TOGGLE
"\"payload_on\":\"%s\"," // TOGGLE / ON
// "\"optimistic\":\"false\"," // false is Hass default when state_topic is set
"\"availability_topic\":\"%s\"," // tele/dualr2/LWT
"\"payload_available\":\"" D_ONLINE "\"," // Online
"\"payload_not_available\":\"" D_OFFLINE "\"," // Offline
"\"force_update\":true";
"\"payload_not_available\":\"" D_OFFLINE "\""; // Offline

const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM =
"%s,\"force_update\":true";

const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM =
"%s,\"payload_off\":\"%s\""; // OFF

const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM =
"%s,\"brightness_command_topic\":\"%s\"," // cmnd/led2/Dimmer
Expand Down Expand Up @@ -92,16 +97,22 @@ const char HASS_DISCOVER_RELAY_SHORT[] PROGMEM =
"\"pl_avail\":\"" D_ONLINE "\"," // Online
"\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline

const char HASS_DISCOVER_BUTTON_SHORT[] PROGMEM =
const char HASS_DISCOVER_BUTTON_SWITCH_SHORT[] PROGMEM =
"{\"name\":\"%s\"," // dualr2 1 BTN
"\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",")
// "\"value_template\":\"{{value_json.%s}}\"," // POWER2
"\"pl_on\":\"%s\"," // TOGGLE
// "\"optimistic\":\"false\"," // false is Hass default when state_topic is set
"\"avty_t\":\"%s\"," // tele/dualr2/LWT
"\"pl_avail\":\"" D_ONLINE "\"," // Online
"\"pl_not_avail\":\"" D_OFFLINE "\"," // Offline
"\"frc_upd\":true";
"\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline

const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT[] PROGMEM =
"%s,\"frc_upd\":true";

const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT[] PROGMEM =
"%s,\"pl_off\":\"%s\""; // OFF


const char HASS_DISCOVER_LIGHT_DIMMER_SHORT[] PROGMEM =
"%s,\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer
Expand Down Expand Up @@ -266,9 +277,85 @@ void HAssAnnounceRelayLight(void)
}
}

void HAssAnnounceButton(void)
void HAssAnnounceButtonSwitch(byte device, char* topic, byte present, byte key, byte toggle)
{
char stopic[TOPSZ];
char sidx[8];

mqtt_data[0] = '\0'; // Clear retained message

// Clear or Set topic
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s_%s_%d/config"),
topic, key?"BTN":"SW",device+1);

if (Settings.flag.hass_discovery && present) {
char name[33];
char value_template[33];
char _state_topic[TOPSZ];
char _availability_topic[TOPSZ];
char prefix[TOPSZ];
char *state_topic = _state_topic;
char *availability_topic = _availability_topic;

if (device+1 > MAX_FRIENDLYNAMES) {
snprintf_P(name, sizeof(name), PSTR("%s %s %d"), Settings.friendlyname[0], key?"BTN":"SW", device+1);
} else {
snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[device], key?"BTN":"SW");
}
GetPowerDevice(value_template, device+1, sizeof(value_template), Settings.flag.device_index_enable);
GetTopic_P(state_topic, CMND, topic, value_template); // State of button is sent as CMND TOGGLE, state of switch is sent as ON/OFF
GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT);
FindPrefix(state_topic, availability_topic, prefix);
if (Settings.flag3.hass_short_discovery_msg) {
Shorten(&state_topic, prefix);
Shorten(&availability_topic, prefix);
}
snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_SHORT:HASS_DISCOVER_BUTTON_SWITCH,
name, state_topic, Settings.state_text[toggle?2:1], availability_topic);
if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data),
Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_TOGGLE_SHORT:HASS_DISCOVER_BUTTON_SWITCH_TOGGLE,
mqtt_data);
else snprintf_P(mqtt_data, sizeof(mqtt_data),
Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SWITCH_ONOFF_SHORT:HASS_DISCOVER_BUTTON_SWITCH_ONOFF,
mqtt_data, Settings.state_text[0]);

if (Settings.flag3.hass_short_discovery_msg)
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
}
MqttPublish(stopic, true);
}

void HAssAnnounceSwitches(void)
{
char sw_topic[sizeof(Settings.switch_topic)];

// Send info about buttons
char *tmp = Settings.switch_topic;
Format(sw_topic, tmp, sizeof(sw_topic));
if ((strlen(sw_topic) != 0) && strcmp(sw_topic, "0")) {
for (byte switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) {
byte switch_present = 0;
byte toggle = 1;

if ((pin[GPIO_SWT1 + switch_index] < 99) || (pin[GPIO_SWT1_NP + switch_index] < 99)) {
switch_present = 1;
}

// Check if MQTT message will be ON/OFF or TOGGLE
if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV ||
!strcmp(mqtt_topic, sw_topic) || !strcmp(Settings.mqtt_grptopic, sw_topic))
{
toggle = 0;
}

HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 0, toggle);
}
}
}

void HAssAnnounceButtons(void)
{
char stopic[TOPSZ];
char key_topic[sizeof(Settings.button_topic)];

Expand All @@ -277,52 +364,24 @@ void HAssAnnounceButton(void)
Format(key_topic, tmp, sizeof(key_topic));
if ((strlen(key_topic) != 0) && strcmp(key_topic, "0")) {
for (byte button_index = 0; button_index < MAX_KEYS; button_index++) {
uint8_t button_present = 0;
byte button_present = 0;
byte toggle = 1;

if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) {
button_present = 1;
} else {
if (pin[GPIO_KEY1 + button_index] < 99) {
if ((pin[GPIO_KEY1 + button_index] < 99) || (pin[GPIO_KEY1_NP + button_index] < 99)) {
button_present = 1;
}
}

mqtt_data[0] = '\0'; // Clear retained message

// Clear or Set topic
snprintf_P(sidx, sizeof(sidx), PSTR("_%d"), button_index+1);
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), "binary_sensor", key_topic, sidx);

if (Settings.flag.hass_discovery && button_present) {
char name[33];
char value_template[33];
char _state_topic[TOPSZ];
char _availability_topic[TOPSZ];
char prefix[TOPSZ];
char *state_topic = _state_topic;
char *availability_topic = _availability_topic;

if (button_index+1 > MAX_FRIENDLYNAMES) {
snprintf_P(name, sizeof(name), PSTR("%s %d BTN"), Settings.friendlyname[0], button_index+1);
} else {
snprintf_P(name, sizeof(name), PSTR("%s BTN"), Settings.friendlyname[button_index]);
}
GetPowerDevice(value_template, button_index+1, sizeof(value_template), Settings.flag.device_index_enable);
GetTopic_P(state_topic, CMND, key_topic, value_template); // State of button is sent as CMND TOGGLE
GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT);
FindPrefix(state_topic, availability_topic, prefix);
if (Settings.flag3.hass_short_discovery_msg) {
Shorten(&state_topic, prefix);
Shorten(&availability_topic, prefix);
}
snprintf_P(mqtt_data, sizeof(mqtt_data), Settings.flag3.hass_short_discovery_msg?HASS_DISCOVER_BUTTON_SHORT:HASS_DISCOVER_BUTTON,
name, state_topic, Settings.state_text[2], availability_topic);

if (Settings.flag3.hass_short_discovery_msg)
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
// Check if MQTT message will be ON/OFF or TOGGLE
if (!strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic))
{
toggle = 0;
}
MqttPublish(stopic, true);

HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 1, toggle);
}
}
}
Expand Down Expand Up @@ -440,9 +499,10 @@ void HAssDiscovery(uint8_t mode)
HAssAnnounceRelayLight();

// Send info about buttons
HAssAnnounceButton();
HAssAnnounceButtons();

// TODO: Send info about switches
// Send info about switches
HAssAnnounceSwitches();

// Send info about sensors
HAssAnnounceSensors();
Expand Down