mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
add sections for MQTT Discovery
This commit is contained in:
@@ -468,7 +468,7 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
if (sensor.type() != AnalogType::NOTUSED) {
|
if (sensor.type() != AnalogType::NOTUSED) {
|
||||||
if (Mqtt::is_nested()) {
|
if (Mqtt::is_nested()) {
|
||||||
char s[10];
|
char s[10];
|
||||||
JsonObject dataSensor = doc[Helpers::smallitoa(s, sensor.gpio())].add<JsonObject>();
|
JsonObject dataSensor = doc[Helpers::smallitoa(s, sensor.gpio())].to<JsonObject>();
|
||||||
dataSensor["name"] = sensor.name();
|
dataSensor["name"] = sensor.name();
|
||||||
switch (sensor.type()) {
|
switch (sensor.type()) {
|
||||||
case AnalogType::COUNTER:
|
case AnalogType::COUNTER:
|
||||||
@@ -508,7 +508,7 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
doc[sensor.name()] = serialized(Helpers::render_value(s, sensor.value(), 2));
|
doc[sensor.name()] = serialized(Helpers::render_value(s, sensor.value(), 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create HA config
|
// create HA config if hasn't already been done
|
||||||
if (Mqtt::ha_enabled() && (!sensor.ha_registered || force)) {
|
if (Mqtt::ha_enabled() && (!sensor.ha_registered || force)) {
|
||||||
LOG_DEBUG("Recreating HA config for analog sensor GPIO %02d", sensor.gpio());
|
LOG_DEBUG("Recreating HA config for analog sensor GPIO %02d", sensor.gpio());
|
||||||
|
|
||||||
@@ -615,7 +615,16 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
config["stat_cla"] = "measurement";
|
config["stat_cla"] = "measurement";
|
||||||
}
|
}
|
||||||
|
|
||||||
Mqtt::add_ha_sections_to_doc("analog", stat_t, config, true, val_cond);
|
// see if we need to create the [devs] discovery section, as this needs only to be done once for all sensors
|
||||||
|
bool is_ha_device_created = false;
|
||||||
|
for (auto & sensor : sensors_) {
|
||||||
|
if (sensor.ha_registered) {
|
||||||
|
is_ha_device_created = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mqtt::add_ha_sections_to_doc("analog", stat_t, config, !is_ha_device_created, val_cond);
|
||||||
|
|
||||||
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());
|
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
@@ -697,7 +706,7 @@ bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject
|
|||||||
|
|
||||||
for (const auto & sensor : sensors_) {
|
for (const auto & sensor : sensors_) {
|
||||||
if (id == -1) { // show number and id for info command
|
if (id == -1) { // show number and id for info command
|
||||||
JsonObject dataSensor = output[sensor.name()].add<JsonObject>();
|
JsonObject dataSensor = output[sensor.name()].to<JsonObject>();
|
||||||
dataSensor["gpio"] = sensor.gpio();
|
dataSensor["gpio"] = sensor.gpio();
|
||||||
dataSensor["type"] = F_(number);
|
dataSensor["type"] = F_(number);
|
||||||
dataSensor["value"] = sensor.value();
|
dataSensor["value"] = sensor.value();
|
||||||
|
|||||||
36
src/mqtt.cpp
36
src/mqtt.cpp
@@ -500,8 +500,7 @@ void Mqtt::on_connect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send initial MQTT messages for some of our services
|
// send initial MQTT messages for some of our services
|
||||||
EMSESP::shower_.set_shower_state(false, true); // Send shower_activated as false
|
EMSESP::system_.send_heartbeat(); // send heartbeat
|
||||||
EMSESP::system_.send_heartbeat(); // send heartbeat
|
|
||||||
|
|
||||||
// re-subscribe to all custom registered MQTT topics
|
// re-subscribe to all custom registered MQTT topics
|
||||||
resubscribe();
|
resubscribe();
|
||||||
@@ -539,7 +538,7 @@ void Mqtt::ha_status() {
|
|||||||
// doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes
|
// doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes
|
||||||
// doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes
|
// doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes
|
||||||
|
|
||||||
JsonObject dev = doc.add<JsonObject>();
|
JsonObject dev = doc["dev"].to<JsonObject>();
|
||||||
dev["name"] = Mqtt::basename();
|
dev["name"] = Mqtt::basename();
|
||||||
dev["sw"] = "v" + std::string(EMSESP_APP_VERSION);
|
dev["sw"] = "v" + std::string(EMSESP_APP_VERSION);
|
||||||
dev["mf"] = "EMS-ESP";
|
dev["mf"] = "EMS-ESP";
|
||||||
@@ -776,7 +775,7 @@ bool Mqtt::publish_ha_sensor_config(DeviceValue & dv, const char * model, const
|
|||||||
// publish HA sensor for System using the heartbeat tag
|
// publish HA sensor for System using the heartbeat tag
|
||||||
bool Mqtt::publish_system_ha_sensor_config(uint8_t type, const char * name, const char * entity, const uint8_t uom) {
|
bool Mqtt::publish_system_ha_sensor_config(uint8_t type, const char * name, const char * entity, const uint8_t uom) {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonObject dev_json = doc["dev"].add<JsonObject>();
|
JsonObject dev_json = doc["dev"].to<JsonObject>();
|
||||||
|
|
||||||
dev_json["name"] = Mqtt::basename();
|
dev_json["name"] = Mqtt::basename();
|
||||||
JsonArray ids = dev_json["ids"].to<JsonArray>();
|
JsonArray ids = dev_json["ids"].to<JsonArray>();
|
||||||
@@ -1137,8 +1136,8 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doc["dev"] = dev_json; // add the dev json object to the end
|
doc["dev"] = dev_json; // add the dev json object to the end
|
||||||
add_ha_sections_to_doc("", stat_t, doc, false, val_cond); // no name, since the "dev" has already been added
|
add_ha_sections_to_doc(nullptr, stat_t, doc, false, val_cond); // no name, since the "dev" has already been added
|
||||||
|
|
||||||
return queue_ha(topic, doc.as<JsonObject>());
|
return queue_ha(topic, doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
@@ -1217,7 +1216,7 @@ bool Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
||||||
snprintf(mode_cmd_s, sizeof(mode_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
snprintf(mode_cmd_s, sizeof(mode_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
||||||
|
|
||||||
JsonDocument doc; // 1024 is not enough
|
JsonDocument doc;
|
||||||
|
|
||||||
doc["~"] = Mqtt::base();
|
doc["~"] = Mqtt::base();
|
||||||
doc["uniq_id"] = uniq_id_s;
|
doc["uniq_id"] = uniq_id_s;
|
||||||
@@ -1272,19 +1271,19 @@ std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adds availability, dev, ids to the config section to HA Discovery config
|
// adds availability, dev, ids to the config section to HA Discovery config
|
||||||
void Mqtt::add_ha_sections_to_doc(const std::string & name,
|
void Mqtt::add_ha_sections_to_doc(const char * name,
|
||||||
const char * state_t,
|
const char * state_t,
|
||||||
JsonDocument & config,
|
JsonDocument & config,
|
||||||
const bool is_first,
|
const bool is_first,
|
||||||
const char * cond1,
|
const char * cond1,
|
||||||
const char * cond2,
|
const char * cond2,
|
||||||
const char * negcond) {
|
const char * negcond) {
|
||||||
// adds dev section to HA Discovery config
|
// adds dev section to HA Discovery config
|
||||||
if (!name.empty()) {
|
if (name != nullptr) {
|
||||||
JsonObject dev = config.add<JsonObject>();
|
JsonObject dev = config["dev"].to<JsonObject>();
|
||||||
auto cap_name = name;
|
char * cap_name = strdup(name);
|
||||||
cap_name[0] = toupper(name[0]); // capitalize first letter
|
cap_name[0] = toupper(name[0]); // capitalize first letter
|
||||||
dev["name"] = Mqtt::basename() + " " + cap_name;
|
dev["name"] = std::string(Mqtt::basename()) + " " + cap_name;
|
||||||
// if it's the first in the category, attach the group to the main HA device
|
// if it's the first in the category, attach the group to the main HA device
|
||||||
if (is_first) {
|
if (is_first) {
|
||||||
dev["mf"] = "EMS-ESP";
|
dev["mf"] = "EMS-ESP";
|
||||||
@@ -1293,6 +1292,7 @@ void Mqtt::add_ha_sections_to_doc(const std::string & name,
|
|||||||
}
|
}
|
||||||
JsonArray ids = dev["ids"].to<JsonArray>();
|
JsonArray ids = dev["ids"].to<JsonArray>();
|
||||||
ids.add(Mqtt::basename() + "-" + Helpers::toLower(name));
|
ids.add(Mqtt::basename() + "-" + Helpers::toLower(name));
|
||||||
|
free(cap_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds "availability" section to HA Discovery config
|
// adds "availability" section to HA Discovery config
|
||||||
|
|||||||
14
src/mqtt.h
14
src/mqtt.h
@@ -217,13 +217,13 @@ class Mqtt {
|
|||||||
|
|
||||||
static std::string tag_to_topic(uint8_t device_type, uint8_t tag);
|
static std::string tag_to_topic(uint8_t device_type, uint8_t tag);
|
||||||
|
|
||||||
static void add_ha_sections_to_doc(const std::string & name,
|
static void add_ha_sections_to_doc(const char * name,
|
||||||
const char * state_t,
|
const char * state_t,
|
||||||
JsonDocument & config,
|
JsonDocument & config,
|
||||||
const bool is_first = false,
|
const bool is_first = false,
|
||||||
const char * cond1 = nullptr,
|
const char * cond1 = nullptr,
|
||||||
const char * cond2 = nullptr,
|
const char * cond2 = nullptr,
|
||||||
const char * negcond = nullptr);
|
const char * negcond = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ bool TemperatureSensor::command_info(const char * value, const int8_t id, JsonOb
|
|||||||
for (const auto & sensor : sensors_) {
|
for (const auto & sensor : sensors_) {
|
||||||
char val[10];
|
char val[10];
|
||||||
if (id == -1) { // show number and id, info command
|
if (id == -1) { // show number and id, info command
|
||||||
JsonObject dataSensor = output[sensor.name()].add<JsonObject>();
|
JsonObject dataSensor = output[sensor.name()].to<JsonObject>();
|
||||||
dataSensor["id"] = sensor.id();
|
dataSensor["id"] = sensor.id();
|
||||||
dataSensor["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
dataSensor["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
||||||
dataSensor["type"] = F_(number);
|
dataSensor["type"] = F_(number);
|
||||||
@@ -492,23 +492,12 @@ void TemperatureSensor::publish_values(const bool force) {
|
|||||||
|
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
// used to see if we need to create the [devs] discovery section, as this needs only to be done once for all sensors
|
|
||||||
bool is_first_ha = true;
|
|
||||||
if (Mqtt::ha_enabled()) {
|
|
||||||
for (auto & sensor : sensors_) {
|
|
||||||
if (sensor.ha_registered) {
|
|
||||||
is_first_ha = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto & sensor : sensors_) {
|
for (auto & sensor : sensors_) {
|
||||||
bool has_value = Helpers::hasValue(sensor.temperature_c);
|
bool has_value = Helpers::hasValue(sensor.temperature_c);
|
||||||
if (has_value) {
|
if (has_value) {
|
||||||
char val[10];
|
char val[10];
|
||||||
if (Mqtt::is_nested()) {
|
if (Mqtt::is_nested()) {
|
||||||
JsonObject dataSensor = doc[sensor.id()].add<JsonObject>();
|
JsonObject dataSensor = doc[sensor.id()].to<JsonObject>();
|
||||||
dataSensor["name"] = sensor.name();
|
dataSensor["name"] = sensor.name();
|
||||||
dataSensor["temp"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
dataSensor["temp"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
} else {
|
} else {
|
||||||
@@ -566,7 +555,16 @@ void TemperatureSensor::publish_values(const bool force) {
|
|||||||
snprintf(name, sizeof(name), "%s", sensor.name().c_str());
|
snprintf(name, sizeof(name), "%s", sensor.name().c_str());
|
||||||
config["name"] = name;
|
config["name"] = name;
|
||||||
|
|
||||||
Mqtt::add_ha_sections_to_doc("temperature", stat_t, config, is_first_ha, val_cond);
|
// see if we need to create the [devs] discovery section, as this needs only to be done once for all sensors
|
||||||
|
bool is_ha_device_created = false;
|
||||||
|
for (auto & sensor : sensors_) {
|
||||||
|
if (sensor.ha_registered) {
|
||||||
|
is_ha_device_created = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mqtt::add_ha_sections_to_doc("temperature", stat_t, config, !is_ha_device_created, val_cond);
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
// use '_' as HA doesn't like '-' in the topic name
|
// use '_' as HA doesn't like '-' in the topic name
|
||||||
|
|||||||
@@ -353,9 +353,11 @@ void WebCustomEntityService::publish(const bool force) {
|
|||||||
if (force) {
|
if (force) {
|
||||||
ha_registered_ = false;
|
ha_registered_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Mqtt::enabled()) {
|
if (!Mqtt::enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
|
EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
|
||||||
if (customEntityItems->size() == 0) {
|
if (customEntityItems->size() == 0) {
|
||||||
return;
|
return;
|
||||||
@@ -369,6 +371,7 @@ void WebCustomEntityService::publish(const bool force) {
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
JsonObject output = doc.to<JsonObject>();
|
JsonObject output = doc.to<JsonObject>();
|
||||||
bool ha_created = ha_registered_;
|
bool ha_created = ha_registered_;
|
||||||
|
|
||||||
for (const CustomEntityItem & entityItem : *customEntityItems) {
|
for (const CustomEntityItem & entityItem : *customEntityItems) {
|
||||||
render_value(output, entityItem);
|
render_value(output, entityItem);
|
||||||
// create HA config
|
// create HA config
|
||||||
@@ -392,6 +395,7 @@ void WebCustomEntityService::publish(const bool force) {
|
|||||||
config["name"] = entityItem.name.c_str();
|
config["name"] = entityItem.name.c_str();
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
|
|
||||||
if (entityItem.writeable) {
|
if (entityItem.writeable) {
|
||||||
if (entityItem.value_type == DeviceValueType::BOOL) {
|
if (entityItem.value_type == DeviceValueType::BOOL) {
|
||||||
snprintf(topic, sizeof(topic), "switch/%s/custom_%s/config", Mqtt::basename().c_str(), entityItem.name.c_str());
|
snprintf(topic, sizeof(topic), "switch/%s/custom_%s/config", Mqtt::basename().c_str(), entityItem.name.c_str());
|
||||||
@@ -412,6 +416,7 @@ void WebCustomEntityService::publish(const bool force) {
|
|||||||
snprintf(topic, sizeof(topic), "sensor/%s/custom_%s/config", Mqtt::basename().c_str(), entityItem.name.c_str());
|
snprintf(topic, sizeof(topic), "sensor/%s/custom_%s/config", Mqtt::basename().c_str(), entityItem.name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entityItem.value_type == DeviceValueType::BOOL) {
|
if (entityItem.value_type == DeviceValueType::BOOL) {
|
||||||
// applies to both Binary Sensor (read only) and a Switch (for a command)
|
// applies to both Binary Sensor (read only) and a Switch (for a command)
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
@@ -426,11 +431,13 @@ void WebCustomEntityService::publish(const bool force) {
|
|||||||
config["pl_off"] = Helpers::render_boolean(result, false);
|
config["pl_off"] = Helpers::render_boolean(result, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mqtt::add_ha_sections_to_doc("custom", stat_t, config, true, val_cond);
|
|
||||||
|
Mqtt::add_ha_sections_to_doc("custom", stat_t, config, !ha_created, val_cond);
|
||||||
|
|
||||||
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ha_registered_ = ha_created;
|
ha_registered_ = ha_created;
|
||||||
if (output.size() > 0) {
|
if (output.size() > 0) {
|
||||||
Mqtt::queue_publish("custom_data", output);
|
Mqtt::queue_publish("custom_data", output);
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
|||||||
void WebCustomization::read(WebCustomization & customizations, JsonObject & root) {
|
void WebCustomization::read(WebCustomization & customizations, JsonObject & root) {
|
||||||
// Temperature Sensor customization
|
// Temperature Sensor customization
|
||||||
JsonArray sensorsJson = root["ts"].to<JsonArray>();
|
JsonArray sensorsJson = root["ts"].to<JsonArray>();
|
||||||
|
|
||||||
for (const SensorCustomization & sensor : customizations.sensorCustomizations) {
|
for (const SensorCustomization & sensor : customizations.sensorCustomizations) {
|
||||||
JsonObject sensorJson = sensorsJson.add<JsonObject>();
|
JsonObject sensorJson = sensorsJson.add<JsonObject>();
|
||||||
sensorJson["id"] = sensor.id; // ID of chip
|
sensorJson["id"] = sensor.id; // ID of chip
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ bool WebSchedulerService::command_setvalue(const char * value, const std::string
|
|||||||
if (!Helpers::value2bool(value, v)) {
|
if (!Helpers::value2bool(value, v)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; });
|
EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; });
|
||||||
for (ScheduleItem & scheduleItem : *scheduleItems) {
|
for (ScheduleItem & scheduleItem : *scheduleItems) {
|
||||||
if (scheduleItem.name == name) {
|
if (scheduleItem.name == name) {
|
||||||
@@ -143,9 +144,11 @@ bool WebSchedulerService::get_value_info(JsonObject & output, const char * cmd)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scheduleItems->size() == 0) {
|
if (scheduleItems->size() == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) {
|
if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) {
|
||||||
// list all names
|
// list all names
|
||||||
for (const ScheduleItem & scheduleItem : *scheduleItems) {
|
for (const ScheduleItem & scheduleItem : *scheduleItems) {
|
||||||
@@ -162,6 +165,7 @@ bool WebSchedulerService::get_value_info(JsonObject & output, const char * cmd)
|
|||||||
}
|
}
|
||||||
return (output.size() > 0);
|
return (output.size() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char command_s[30];
|
char command_s[30];
|
||||||
strlcpy(command_s, cmd, sizeof(command_s));
|
strlcpy(command_s, cmd, sizeof(command_s));
|
||||||
char * attribute_s = nullptr;
|
char * attribute_s = nullptr;
|
||||||
@@ -172,6 +176,7 @@ bool WebSchedulerService::get_value_info(JsonObject & output, const char * cmd)
|
|||||||
*breakp = '\0';
|
*breakp = '\0';
|
||||||
attribute_s = breakp + 1;
|
attribute_s = breakp + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonVariant data;
|
JsonVariant data;
|
||||||
for (const ScheduleItem & scheduleItem : *scheduleItems) {
|
for (const ScheduleItem & scheduleItem : *scheduleItems) {
|
||||||
if (Helpers::toLower(scheduleItem.name) == Helpers::toLower(command_s)) {
|
if (Helpers::toLower(scheduleItem.name) == Helpers::toLower(command_s)) {
|
||||||
@@ -192,14 +197,17 @@ bool WebSchedulerService::get_value_info(JsonObject & output, const char * cmd)
|
|||||||
output["visible"] = true;
|
output["visible"] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attribute_s && output.containsKey(attribute_s)) {
|
if (attribute_s && output.containsKey(attribute_s)) {
|
||||||
data = output[attribute_s];
|
data = output[attribute_s];
|
||||||
output.clear();
|
output.clear();
|
||||||
output["api_data"] = data;
|
output["api_data"] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.size()) {
|
if (output.size()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
output["message"] = "unknown command";
|
output["message"] = "unknown command";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -209,12 +217,14 @@ void WebSchedulerService::publish_single(const char * name, const bool state) {
|
|||||||
if (!Mqtt::publish_single() || name == nullptr || name[0] == '\0') {
|
if (!Mqtt::publish_single() || name == nullptr || name[0] == '\0') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
if (Mqtt::publish_single2cmd()) {
|
if (Mqtt::publish_single2cmd()) {
|
||||||
snprintf(topic, sizeof(topic), "%s/%s", F_(scheduler), name);
|
snprintf(topic, sizeof(topic), "%s/%s", F_(scheduler), name);
|
||||||
} else {
|
} else {
|
||||||
snprintf(topic, sizeof(topic), "%s%s/%s", F_(scheduler), "_data", name);
|
snprintf(topic, sizeof(topic), "%s%s/%s", F_(scheduler), "_data", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
char payload[12];
|
char payload[12];
|
||||||
Mqtt::queue_publish(topic, Helpers::render_boolean(payload, state));
|
Mqtt::queue_publish(topic, Helpers::render_boolean(payload, state));
|
||||||
}
|
}
|
||||||
@@ -224,13 +234,16 @@ void WebSchedulerService::publish(const bool force) {
|
|||||||
if (force) {
|
if (force) {
|
||||||
ha_registered_ = false;
|
ha_registered_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Mqtt::enabled()) {
|
if (!Mqtt::enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; });
|
EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; });
|
||||||
if (scheduleItems->size() == 0) {
|
if (scheduleItems->size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mqtt::publish_single() && force) {
|
if (Mqtt::publish_single() && force) {
|
||||||
for (const ScheduleItem & scheduleItem : *scheduleItems) {
|
for (const ScheduleItem & scheduleItem : *scheduleItems) {
|
||||||
publish_single(scheduleItem.name.c_str(), scheduleItem.active);
|
publish_single(scheduleItem.name.c_str(), scheduleItem.active);
|
||||||
@@ -272,9 +285,11 @@ void WebSchedulerService::publish(const bool force) {
|
|||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
char command_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char command_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
|
|
||||||
snprintf(topic, sizeof(topic), "switch/%s/scheduler_%s/config", Mqtt::basename().c_str(), scheduleItem.name.c_str());
|
snprintf(topic, sizeof(topic), "switch/%s/scheduler_%s/config", Mqtt::basename().c_str(), scheduleItem.name.c_str());
|
||||||
snprintf(command_topic, sizeof(command_topic), "%s/scheduler/%s", Mqtt::base().c_str(), scheduleItem.name.c_str());
|
snprintf(command_topic, sizeof(command_topic), "%s/scheduler/%s", Mqtt::base().c_str(), scheduleItem.name.c_str());
|
||||||
config["cmd_t"] = command_topic;
|
config["cmd_t"] = command_topic;
|
||||||
|
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
config["pl_on"] = true;
|
config["pl_on"] = true;
|
||||||
config["pl_off"] = false;
|
config["pl_off"] = false;
|
||||||
@@ -287,7 +302,7 @@ void WebSchedulerService::publish(const bool force) {
|
|||||||
config["pl_off"] = Helpers::render_boolean(result, false);
|
config["pl_off"] = Helpers::render_boolean(result, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mqtt::add_ha_sections_to_doc("scheduler", stat_t, config, true, val_cond);
|
Mqtt::add_ha_sections_to_doc("scheduler", stat_t, config, !ha_created, val_cond);
|
||||||
|
|
||||||
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
@@ -304,6 +319,7 @@ bool WebSchedulerService::has_commands() {
|
|||||||
if (scheduleItems->size() == 0) {
|
if (scheduleItems->size() == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ScheduleItem & scheduleItem : *scheduleItems) {
|
for (const ScheduleItem & scheduleItem : *scheduleItems) {
|
||||||
if (!scheduleItem.name.empty()) {
|
if (!scheduleItem.name.empty()) {
|
||||||
return true;
|
return true;
|
||||||
@@ -347,6 +363,7 @@ bool WebSchedulerService::command(const char * cmd, const char * data) {
|
|||||||
} else {
|
} else {
|
||||||
snprintf(error, sizeof(error), "Scheduled command %s failed with error code (%s)", cmd, Command::return_code_string(return_code).c_str());
|
snprintf(error, sizeof(error), "Scheduled command %s failed with error code (%s)", cmd, Command::return_code_string(return_code).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
emsesp::EMSESP::logger().err(error);
|
emsesp::EMSESP::logger().err(error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user