mirror of https://github.com/arendst/Tasmota.git
Refactor Tasmota Discovery
This commit is contained in:
parent
b5777aeb25
commit
c2cde43a54
|
@ -127,3 +127,9 @@ String NetworkMacAddress(void) {
|
|||
#endif
|
||||
return WiFi.macAddress();
|
||||
}
|
||||
|
||||
String NetworkUniqueId(void) {
|
||||
String unique_id = WiFi.macAddress();
|
||||
unique_id.replace(":", ""); // Full 12 chars MAC address as ID
|
||||
return unique_id;
|
||||
}
|
||||
|
|
|
@ -43,8 +43,7 @@ char* Format(char* output, const char* input_p, int size)
|
|||
snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits);
|
||||
snprintf_P(output, size, tmp, ESP_getChipId() & 0x1fff); // %04d - short chip ID in dec, like in hostname
|
||||
} else {
|
||||
String mac_address = WiFi.macAddress();
|
||||
mac_address.replace(":", "");
|
||||
String mac_address = NetworkUniqueId();
|
||||
if (digits > 12) { digits = 12; }
|
||||
String mac_part = mac_address.substring(12 - digits);
|
||||
snprintf_P(output, size, PSTR("%s%s"), output, mac_part.c_str()); // %01X .. %12X - mac address in hex
|
||||
|
@ -122,9 +121,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi
|
|||
|
||||
fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), (const __FlashStringHelper *)topic);
|
||||
fulltopic.replace(F("%hostname%"), TasmotaGlobal.hostname);
|
||||
String token_id = WiFi.macAddress();
|
||||
token_id.replace(":", "");
|
||||
fulltopic.replace(F("%id%"), token_id);
|
||||
fulltopic.replace(F("%id%"), NetworkUniqueId());
|
||||
}
|
||||
fulltopic.replace(F("#"), "");
|
||||
fulltopic.replace(F("//"), "/");
|
||||
|
|
|
@ -759,9 +759,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
|
|||
RulesVarReplace(commands, F("%TOPIC%"), TasmotaGlobal.mqtt_topic);
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%06X"), ESP_getChipId());
|
||||
RulesVarReplace(commands, F("%DEVICEID%"), stemp);
|
||||
String mac_address = WiFi.macAddress();
|
||||
mac_address.replace(":", "");
|
||||
RulesVarReplace(commands, F("%MACADDR%"), mac_address);
|
||||
RulesVarReplace(commands, F("%MACADDR%"), NetworkUniqueId());
|
||||
#if defined(USE_TIMERS) && defined(USE_SUNRISE)
|
||||
RulesVarReplace(commands, F("%SUNRISE%"), String(SunMinutes(0)));
|
||||
RulesVarReplace(commands, F("%SUNSET%"), String(SunMinutes(1)));
|
||||
|
|
|
@ -32,10 +32,30 @@
|
|||
|
||||
#define XDRV_12 12
|
||||
|
||||
const char TASMOTA_DISCOVER_DEVICE[] PROGMEM = // Basic parameters for Discovery
|
||||
"{\"ip\":\"%_I\"," // IP Address
|
||||
uint8_t TasDiscoverData_init_step;
|
||||
|
||||
void TasDiscoverMessage(void) {
|
||||
Response_P(PSTR("{\"ip\":\"%_I\"," // IP Address
|
||||
"\"dn\":\"%s\"," // Device Name
|
||||
"\"fn\":[%s]," // Friendly Names
|
||||
"\"fn\":["), // Friendly Names (start)
|
||||
(uint32_t)WiFi.localIP(),
|
||||
SettingsText(SET_DEVICENAME));
|
||||
|
||||
uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present;
|
||||
for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) {
|
||||
char fname[TOPSZ];
|
||||
snprintf_P(fname, sizeof(fname), PSTR("\"%s\""), EscapeJSONString(SettingsText(SET_FRIENDLYNAME1 +i)).c_str());
|
||||
ResponseAppend_P(PSTR("%s%s"), (i > 0 ? "," : ""), (i < maxfn) ? fname : PSTR("null"));
|
||||
}
|
||||
|
||||
bool TuyaMod = false;
|
||||
bool iFanMod = false;
|
||||
#ifdef ESP8266
|
||||
if ((TUYA_DIMMER == TasmotaGlobal.module_type) || (SK03_TUYA == TasmotaGlobal.module_type)) { TuyaMod = true; };
|
||||
if ((SONOFF_IFAN02 == TasmotaGlobal.module_type) || (SONOFF_IFAN03 == TasmotaGlobal.module_type)) { iFanMod = true; };
|
||||
#endif // ESP8266
|
||||
|
||||
ResponseAppend_P(PSTR("]," // Friendly Names (end)
|
||||
"\"hn\":\"%s\"," // Host Name
|
||||
"\"mac\":\"%s\"," // Full MAC as Device id
|
||||
"\"md\":\"%s\"," // Module or Template Name
|
||||
|
@ -47,20 +67,18 @@ const char TASMOTA_DISCOVER_DEVICE[] PROGMEM = // Basic par
|
|||
"\"t\":\"%s\"," // Topic
|
||||
"\"ft\":\"%s\"," // Full Topic
|
||||
"\"tp\":[\"%s\",\"%s\",\"%s\"]," // Topics for command, stat and tele
|
||||
"\"rl\":[%s],\"swc\":[%s],\"swn\":[%s],\"btn\":[%s]," // Inputs / Outputs
|
||||
"\"so\":{\"4\":%d,\"11\":%d,\"13\":%d,\"17\":%d,\"20\":%d," // SetOptions
|
||||
"\"30\":%d,\"68\":%d,\"73\":%d,\"82\":%d,\"114\":%d,\"117\":%d},"
|
||||
"\"lk\":%d,\"lt_st\":%d,\"sho\":[%s],\"ver\":1}"; // Light SubType, Shutter Options and Discovery version
|
||||
|
||||
struct {
|
||||
uint8_t init_step;
|
||||
} TasDiscoverData;
|
||||
|
||||
void TasDiscovery(void) {
|
||||
bool iFan = false;
|
||||
#ifdef ESP8266
|
||||
if ((SONOFF_IFAN02 == TasmotaGlobal.module_type) || (SONOFF_IFAN03 == TasmotaGlobal.module_type)) { iFan = true; }
|
||||
#endif // ESP8266
|
||||
"\"rl\":["), // Relays (start)
|
||||
TasmotaGlobal.hostname,
|
||||
NetworkUniqueId().c_str(),
|
||||
ModuleName().c_str(),
|
||||
TuyaMod, iFanMod,
|
||||
GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3),
|
||||
TasmotaGlobal.version,
|
||||
TasmotaGlobal.mqtt_topic,
|
||||
SettingsText(SET_MQTT_FULLTOPIC),
|
||||
PSTR(SUB_PREFIX),
|
||||
PSTR(PUB_PREFIX),
|
||||
PSTR(PUB_PREFIX2));
|
||||
|
||||
uint8_t lightidx = MAX_RELAYS + 1; // Will store the starting position of the lights
|
||||
if (Light.subtype > LST_NONE) {
|
||||
|
@ -77,7 +95,6 @@ void TasDiscovery(void) {
|
|||
|
||||
uint16_t Relay[MAX_RELAYS] = { 0 }; // Base array to store the relay type
|
||||
uint16_t Shutter[MAX_RELAYS] = { 0 }; // Array to store a temp list for shutters
|
||||
char RelLst[MAX_RELAYS*2] = { 0 }; // Relay as a char list, "0,0,0,0,0,0,0,0"
|
||||
for (uint32_t i = 0; i < MAX_RELAYS; i++) {
|
||||
if (i < TasmotaGlobal.devices_present) {
|
||||
|
||||
|
@ -98,86 +115,98 @@ void TasDiscovery(void) {
|
|||
if (Shutter[i] != 0) { // Check if there are shutters present
|
||||
Relay[i] = 3; // Relay is a shutter
|
||||
} else {
|
||||
if (i >= lightidx || (iFan && i == 0)) { // First relay on Ifan controls the light
|
||||
if (i >= lightidx || (iFanMod && (0 == i))) { // First relay on Ifan controls the light
|
||||
Relay[i] = 2; // Relay is a light
|
||||
} else {
|
||||
if (!iFan) { // Relays 2-4 for ifan are controlled by FANSPEED and don't need to be present if TasmotaGlobal.module_type = SONOFF_IFAN02 or SONOFF_IFAN03
|
||||
if (!iFanMod) { // Relays 2-4 for ifan are controlled by FANSPEED and don't need to be present if TasmotaGlobal.module_type = SONOFF_IFAN02 or SONOFF_IFAN03
|
||||
Relay[i] = 1; // Simple Relay
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
snprintf_P(RelLst, sizeof(RelLst), PSTR("%s%s%d"), RelLst, (i > 0 ? "," : ""), Relay[i]); // Vector for the Official Integration
|
||||
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), Relay[i]); // Vector for the Official Integration
|
||||
}
|
||||
|
||||
bool TuyaMod = false;
|
||||
bool iFanMod = false;
|
||||
#ifdef ESP8266
|
||||
if ((TUYA_DIMMER == TasmotaGlobal.module_type) || (SK03_TUYA == TasmotaGlobal.module_type)) { TuyaMod = true; };
|
||||
if ((SONOFF_IFAN02 == TasmotaGlobal.module_type) || (SONOFF_IFAN03 == TasmotaGlobal.module_type)) { iFanMod = true; };
|
||||
#endif // ESP8266
|
||||
ResponseAppend_P(PSTR("]," // Relays (end)
|
||||
"\"swc\":[")); // Switch modes (start)
|
||||
|
||||
char friendly_name[200];
|
||||
friendly_name[0] = '\0';
|
||||
uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present;
|
||||
for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) {
|
||||
char fname[TOPSZ];
|
||||
snprintf_P(fname, sizeof(fname), PSTR("\"%s\""), EscapeJSONString(SettingsText(SET_FRIENDLYNAME1 +i)).c_str());
|
||||
snprintf_P(friendly_name, sizeof(friendly_name), PSTR("%s%s%s"), friendly_name, (i > 0 ? "," : ""), (i < maxfn) ? fname : PSTR("null"));
|
||||
// Enable Discovery for Switches only if SetOption114 is enabled
|
||||
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
|
||||
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) && Settings.flag5.mqtt_switches) ? Settings.switchmode[i] : -1);
|
||||
}
|
||||
|
||||
char switch_mode[90];
|
||||
switch_mode[0] = '\0';
|
||||
char switch_name[300];
|
||||
switch_name[0] = '\0';
|
||||
ResponseAppend_P(PSTR("]," // Switch modes (end)
|
||||
"\"swn\":[")); // Switch names (start)
|
||||
|
||||
// Enable Discovery for Switches only if SetOption114 is enabled
|
||||
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
|
||||
char sname[TOPSZ];
|
||||
snprintf_P(sname, sizeof(sname), PSTR("\"%s\""), GetSwitchText(i).c_str());
|
||||
snprintf_P(switch_mode, sizeof(switch_mode), PSTR("%s%s%d"), switch_mode, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? Settings.switchmode[i] : -1);
|
||||
snprintf_P(switch_name, sizeof(switch_name), PSTR("%s%s%s"), switch_name, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? sname : PSTR("null"));
|
||||
ResponseAppend_P(PSTR("%s%s"), (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) && Settings.flag5.mqtt_switches) ? sname : PSTR("null"));
|
||||
}
|
||||
|
||||
ResponseAppend_P(PSTR("]," // Switch names (end)
|
||||
"\"btn\":[")); // Button flag (start)
|
||||
|
||||
bool SerialButton = false;
|
||||
char button_flag[90];
|
||||
button_flag[0] = '\0';
|
||||
// Enable Discovery for Buttons only if SetOption73 is enabled
|
||||
for (uint32_t i = 0; i < MAX_KEYS; i++) {
|
||||
#ifdef ESP8266
|
||||
SerialButton = ((0 == i) && (SONOFF_DUAL == TasmotaGlobal.module_type ));
|
||||
#endif // ESP8266
|
||||
snprintf_P(button_flag, sizeof(button_flag), PSTR("%s%s%d"), button_flag, (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) & Settings.flag3.mqtt_buttons));
|
||||
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) && Settings.flag3.mqtt_buttons));
|
||||
}
|
||||
|
||||
char shutter_option[90];
|
||||
shutter_option[0] = '\0';
|
||||
ResponseAppend_P(PSTR("]," // Button flag (end)
|
||||
"\"so\":{\"4\":%d," // SetOptions
|
||||
"\"11\":%d,"
|
||||
"\"13\":%d,"
|
||||
"\"17\":%d,"
|
||||
"\"20\":%d,"
|
||||
"\"30\":%d,"
|
||||
"\"68\":%d,"
|
||||
"\"73\":%d,"
|
||||
"\"82\":%d,"
|
||||
"\"114\":%d,"
|
||||
"\"117\":%d},"
|
||||
"\"lk\":%d," // Light CTRGB linked
|
||||
"\"lt_st\":%d," // Light SubType
|
||||
"\"sho\":["), // Shutter Options (start)
|
||||
Settings.flag.mqtt_response,
|
||||
Settings.flag.button_swap,
|
||||
Settings.flag.button_single,
|
||||
Settings.flag.decimal_text,
|
||||
Settings.flag.not_power_linked,
|
||||
Settings.flag.hass_light,
|
||||
Settings.flag3.pwm_multi_channels,
|
||||
Settings.flag3.mqtt_buttons,
|
||||
Settings.flag4.alexa_ct_range,
|
||||
Settings.flag5.mqtt_switches,
|
||||
Settings.flag5.fade_fixed_duration,
|
||||
light_controller.isCTRGBLinked(),
|
||||
Light.subtype);
|
||||
|
||||
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
|
||||
#ifdef USE_SHUTTER
|
||||
snprintf_P(shutter_option, sizeof(shutter_option), PSTR("%s%s%d"), shutter_option, (i > 0 ? "," : ""), Settings.shutter_options[i]);
|
||||
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), Settings.shutter_options[i]);
|
||||
#else
|
||||
snprintf_P(shutter_option, sizeof(shutter_option), PSTR("%s%s0"), shutter_option, (i > 0 ? "," : ""));
|
||||
ResponseAppend_P(PSTR("%s0"), (i > 0 ? "," : ""));
|
||||
#endif // USE_SHUTTER
|
||||
}
|
||||
|
||||
// Full 12 chars MAC address as ID
|
||||
String mac_address = WiFi.macAddress();
|
||||
mac_address.replace(":", "");
|
||||
char unique_id[30];
|
||||
snprintf_P(unique_id, sizeof(unique_id), PSTR("%s"), mac_address.c_str());
|
||||
ResponseAppend_P(PSTR("]," // Shutter Options (end)
|
||||
"\"ver\":1}")); // Discovery version
|
||||
}
|
||||
|
||||
void TasDiscovery(void) {
|
||||
TasmotaGlobal.masterlog_level = LOG_LEVEL_DEBUG_MORE; // Hide topic on clean and remove use weblog 4 to show it
|
||||
|
||||
ResponseClear(); // Clear retained message
|
||||
if (!Settings.flag.hass_discovery) { // SetOption19 - Clear retained message
|
||||
Response_P(TASMOTA_DISCOVER_DEVICE, (uint32_t)WiFi.localIP(), SettingsText(SET_DEVICENAME),
|
||||
friendly_name, TasmotaGlobal.hostname, unique_id, ModuleName().c_str(), TuyaMod, iFanMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3),
|
||||
TasmotaGlobal.version, TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), PSTR(SUB_PREFIX), PSTR(PUB_PREFIX), PSTR(PUB_PREFIX2), RelLst, switch_mode, switch_name,
|
||||
button_flag, Settings.flag.mqtt_response, Settings.flag.button_swap, Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked,
|
||||
Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, Settings.flag3.mqtt_buttons, Settings.flag4.alexa_ct_range, Settings.flag5.mqtt_switches,
|
||||
Settings.flag5.fade_fixed_duration, light_controller.isCTRGBLinked(), Light.subtype, shutter_option);
|
||||
TasDiscoverMessage(); // Build discovery message
|
||||
}
|
||||
char stopic[TOPSZ];
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/config"), unique_id);
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/config"), NetworkUniqueId().c_str());
|
||||
MqttPublish(stopic, true);
|
||||
|
||||
if (!Settings.flag.hass_discovery) { // SetOption19 - Clear retained message
|
||||
|
@ -185,14 +214,14 @@ void TasDiscovery(void) {
|
|||
MqttShowSensor();
|
||||
ResponseAppend_P(PSTR(",\"ver\":1}"));
|
||||
}
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/sensors"), unique_id);
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/sensors"), NetworkUniqueId().c_str());
|
||||
MqttPublish(stopic, true);
|
||||
|
||||
TasmotaGlobal.masterlog_level = LOG_LEVEL_NONE; // Restore WebLog state
|
||||
}
|
||||
|
||||
void TasRediscover(void) {
|
||||
TasDiscoverData.init_step = 1; // Delayed discovery or clear retained messages
|
||||
TasDiscoverData_init_step = 1; // Delayed discovery or clear retained messages
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -205,15 +234,15 @@ bool Xdrv12(uint8_t function) {
|
|||
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
|
||||
switch (function) {
|
||||
case FUNC_EVERY_SECOND:
|
||||
if (TasDiscoverData.init_step) {
|
||||
TasDiscoverData.init_step--;
|
||||
if (!TasDiscoverData.init_step) {
|
||||
if (TasDiscoverData_init_step) {
|
||||
TasDiscoverData_init_step--;
|
||||
if (!TasDiscoverData_init_step) {
|
||||
TasDiscovery(); // Send the topics for discovery
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FUNC_MQTT_INIT:
|
||||
TasDiscoverData.init_step = 10; // Delayed discovery
|
||||
TasDiscoverData_init_step = 10; // Delayed discovery
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,9 +329,7 @@ void NewHAssDiscovery(void)
|
|||
ResponseClear(); // Clear retained message
|
||||
|
||||
// Full 12 chars MAC address as ID
|
||||
String mac_address = WiFi.macAddress();
|
||||
mac_address.replace(":", "");
|
||||
snprintf_P(unique_id, sizeof(unique_id), PSTR("%s"), mac_address.c_str());
|
||||
snprintf_P(unique_id, sizeof(unique_id), PSTR("%s"), NetworkUniqueId().c_str());
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/config"), unique_id);
|
||||
|
||||
// Send empty message if new discovery is disabled
|
||||
|
|
|
@ -172,8 +172,7 @@ const char HUE_API[] PROGMEM = "\x00\x06\x3B\x37\x8C\xEC\x2D\x10\xEC\x9C\x2F\x9D
|
|||
|
||||
String HueBridgeId(void)
|
||||
{
|
||||
String temp = WiFi.macAddress();
|
||||
temp.replace(":", "");
|
||||
String temp = NetworkUniqueId();
|
||||
String bridgeid = temp.substring(0, 6);
|
||||
bridgeid += F("FFFE");
|
||||
bridgeid += temp.substring(6);
|
||||
|
@ -182,8 +181,7 @@ String HueBridgeId(void)
|
|||
|
||||
String HueSerialnumber(void)
|
||||
{
|
||||
String serial = WiFi.macAddress();
|
||||
serial.replace(":", "");
|
||||
String serial = NetworkUniqueId();
|
||||
serial.toLowerCase();
|
||||
return serial; // 5ccf7f139f3d
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue