14static const char *
const TAG =
"mqtt.component";
33static constexpr size_t TOPIC_PREFIX_MAX_LEN = 64;
34static constexpr size_t DISCOVERY_PREFIX_MAX_LEN = 64;
38static constexpr size_t DEFAULT_TOPIC_MAX_LEN =
39 TOPIC_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 1 + MQTT_SUFFIX_MAX_LEN + 1;
41static constexpr size_t DISCOVERY_TOPIC_MAX_LEN = DISCOVERY_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 +
42 ESPHOME_DEVICE_NAME_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 7 + 1;
53 char object_id_buf[OBJECT_ID_MAX_LEN];
56 char buf[DISCOVERY_TOPIC_MAX_LEN];
61 p =
append_str(p, comp_type, strlen(comp_type));
63 p =
append_str(p, sanitized_name.data(), sanitized_name.size());
68 return std::string(buf, p - buf);
73 if (topic_prefix.empty()) {
79 char object_id_buf[OBJECT_ID_MAX_LEN];
82 char buf[DEFAULT_TOPIC_MAX_LEN];
85 p =
append_str(p, topic_prefix.data(), topic_prefix.size());
87 p =
append_str(p, comp_type, strlen(comp_type));
91 p =
append_str(p, suffix.data(), suffix.size());
93 return std::string(buf, p - buf);
109 return this->
publish(topic, payload.data(), payload.size());
127 if (discovery_info.
clean) {
128 ESP_LOGV(TAG,
"'%s': Cleaning discovery", this->
friendly_name_().c_str());
132 ESP_LOGV(TAG,
"'%s': Sending discovery", this->
friendly_name_().c_str());
137 [
this](JsonObject root) {
152 root[MQTT_ENABLED_BY_DEFAULT] =
false;
155 if (!icon_ref.empty()) {
156 root[MQTT_ICON] = icon_ref;
161 switch (entity_category) {
175 root[MQTT_COMMAND_RETAIN] =
true;
179 if (!avail.
topic.empty()) {
180 root[MQTT_AVAILABILITY_TOPIC] = avail.
topic;
188 char object_id_buf[OBJECT_ID_MAX_LEN];
191 char friendly_name_hash[9];
193 friendly_name_hash[8] = 0;
196 char unique_id[MAC_ADDRESS_BUFFER_SIZE + ESPHOME_DOMAIN_MAX_LEN + 11];
197 char mac_buf[MAC_ADDRESS_BUFFER_SIZE];
199 snprintf(unique_id,
sizeof(unique_id),
"%s-%s-%s", mac_buf, this->
component_type(), friendly_name_hash);
200 root[MQTT_UNIQUE_ID] = unique_id;
209 root[MQTT_OBJECT_ID] = node_name +
"_" + object_id.
c_str();
212 const std::string &node_friendly_name = friendly_name_ref.empty() ? node_name : friendly_name_ref;
215 JsonObject device_info = root[MQTT_DEVICE].to<JsonObject>();
216 char mac[MAC_ADDRESS_BUFFER_SIZE];
218 device_info[MQTT_DEVICE_IDENTIFIERS] = mac;
219 device_info[MQTT_DEVICE_NAME] = node_friendly_name;
220#ifdef ESPHOME_PROJECT_NAME
221 device_info[MQTT_DEVICE_SW_VERSION] = ESPHOME_PROJECT_VERSION
" (ESPHome " ESPHOME_VERSION
")";
222 const char *model = std::strchr(ESPHOME_PROJECT_NAME,
'.');
223 device_info[MQTT_DEVICE_MODEL] = model ==
nullptr ? ESPHOME_BOARD : model + 1;
224 device_info[MQTT_DEVICE_MANUFACTURER] =
225 model ==
nullptr ? ESPHOME_PROJECT_NAME : std::string(ESPHOME_PROJECT_NAME, model - ESPHOME_PROJECT_NAME);
227 static const char ver_fmt[]
PROGMEM = ESPHOME_VERSION
" (config hash 0x%08" PRIx32
")";
229 char fmt_buf[
sizeof(ver_fmt)];
230 strcpy_P(fmt_buf, ver_fmt);
231 const char *fmt = fmt_buf;
233 const char *fmt = ver_fmt;
236 device_info[MQTT_DEVICE_MODEL] = ESPHOME_BOARD;
237#if defined(USE_ESP8266) || defined(USE_ESP32)
238 device_info[MQTT_DEVICE_MANUFACTURER] =
"Espressif";
239#elif defined(USE_RP2040)
240 device_info[MQTT_DEVICE_MANUFACTURER] =
"Raspberry Pi";
241#elif defined(USE_BK72XX)
242 device_info[MQTT_DEVICE_MANUFACTURER] =
"Beken";
243#elif defined(USE_RTL87XX)
244 device_info[MQTT_DEVICE_MANUFACTURER] =
"Realtek";
245#elif defined(USE_HOST)
246 device_info[MQTT_DEVICE_MANUFACTURER] =
"Host";
249 if (!node_area.empty()) {
250 device_info[MQTT_DEVICE_SUGGESTED_AREA] = node_area;
253 device_info[MQTT_DEVICE_CONNECTIONS][0][0] =
"mac";
254 device_info[MQTT_DEVICE_CONNECTIONS][0][1] = mac;
283 std::string payload_not_available) {
286 this->
availability_->payload_available = std::move(payload_available);
287 this->
availability_->payload_not_available = std::move(payload_not_available);
const std::string & get_friendly_name() const
Get the friendly name of this Application set by pre_setup().
constexpr uint32_t get_config_hash()
Get the config hash as a 32-bit integer.
const char * get_area() const
Get the area of this Application set by pre_setup().
const std::string & get_name() const
Get the name of this Application set by pre_setup().
virtual void setup()
Where the component's initialization should happen.
virtual void dump_config()
virtual void loop()
This method will be called repeatedly.
bool has_own_name() const
const StringRef & get_name() const
StringRef get_icon_ref() const
bool is_disabled_by_default() const
EntityCategory get_entity_category() const
StringRef get_object_id_to(std::span< char, OBJECT_ID_MAX_LEN > buf) const
Get object_id with zero heap allocation For static case: returns StringRef to internal storage (buffe...
StringRef is a reference to a string owned by something else.
constexpr const char * c_str() const
constexpr size_type size() const
const std::string & get_topic_prefix() const
Get the topic prefix of this device, using default if necessary.
void subscribe_json(const std::string &topic, const mqtt_json_callback_t &callback, uint8_t qos=0)
Subscribe to a MQTT topic and automatically parse JSON payload.
void register_mqtt_component(MQTTComponent *component)
bool publish(const MQTTMessage &message)
Publish a MQTTMessage.
const MQTTDiscoveryInfo & get_discovery_info() const
Get Home Assistant discovery info.
void subscribe(const std::string &topic, mqtt_callback_t callback, uint8_t qos=0)
Subscribe to an MQTT topic and call callback when a message is received.
const Availability & get_availability()
bool publish_json(const std::string &topic, const json::json_build_t &f, uint8_t qos=0, bool retain=false)
Construct and send a JSON MQTT message.
bool is_discovery_enabled() const
TemplatableValue< std::string > custom_state_topic_
TemplatableValue< std::string > custom_command_topic_
void disable_availability()
std::unique_ptr< Availability > availability_
virtual bool is_internal()
bool is_connected_() const
bool is_disabled_by_default_() const
Get whether the underlying Entity is disabled by default.
void call_loop() override
MQTTComponent()
Constructs a MQTTComponent.
void set_qos(uint8_t qos)
Set QOS for state messages.
bool is_discovery_enabled() const
void schedule_resend_state()
Internal method for the MQTT client base to schedule a resend of the state on reconnect.
bool publish(const std::string &topic, const std::string &payload)
Send a MQTT message.
void set_command_retain(bool command_retain)
Set whether command message should be retained.
bool send_discovery_()
Internal method to start sending discovery info, this will call send_discovery().
void set_subscribe_qos(uint8_t qos)
Set the QOS for subscribe messages (used in discovery).
void call_dump_config() override
void subscribe_json(const std::string &topic, const mqtt_json_callback_t &callback, uint8_t qos=0)
Subscribe to a MQTT topic and automatically parse JSON payload.
void call_setup() override
Override setup_ so that we can call send_discovery() when needed.
bool publish_json(const std::string &topic, const json::json_build_t &f)
Construct and send a JSON MQTT message.
std::string get_discovery_topic_(const MQTTDiscoveryInfo &discovery_info) const
Helper method to get the discovery topic for this component.
std::string get_default_topic_for_(const std::string &suffix) const
Get this components state/command/... topic.
StringRef get_default_object_id_to_(std::span< char, OBJECT_ID_MAX_LEN > buf) const
Get the object ID for this MQTT component, writing to the provided buffer.
void set_retain(bool retain)
Set whether state message should be retained.
virtual const EntityBase * get_entity() const =0
Gets the Entity served by this MQTT component.
std::string get_state_topic_() const
Get the MQTT topic that new states will be shared to.
virtual void send_discovery(JsonObject root, SendDiscoveryConfig &config)=0
Send discovery info the Home Assistant, override this.
std::string friendly_name_() const
Get the friendly name of this MQTT component.
virtual bool send_initial_state()=0
void disable_discovery()
Disable discovery. Sets friendly name to "".
float get_setup_priority() const override
MQTT_COMPONENT setup priority.
void set_availability(std::string topic, std::string payload_available, std::string payload_not_available)
Set the Home Assistant availability data.
std::string get_command_topic_() const
Get the MQTT topic for listening to commands.
void subscribe(const std::string &topic, mqtt_callback_t callback, uint8_t qos=0)
Subscribe to a MQTT topic.
virtual const char * component_type() const =0
Override this method to return the component type (e.g. "light", "sensor", ...)
StringRef get_icon_ref_() const
Get the icon field of this component as StringRef.
std::function< void(JsonObject)> json_build_t
Callback function typedef for building JsonObjects.
@ MQTT_DEVICE_NAME_OBJECT_ID_GENERATOR
@ MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR
std::function< void(const std::string &, JsonObject)> mqtt_json_callback_t
char * append_char(char *p, char c)
char * append_str(char *p, const char *s, size_t len)
std::function< void(const std::string &, const std::string &)> mqtt_callback_t
Callback for MQTT subscriptions.
MQTTClientComponent * global_mqtt_client
const float AFTER_CONNECTION
For components that should be initialized after a data connection (API/MQTT) is connected.
std::string str_sanitize(const std::string &str)
Sanitizes the input string by removing all characters but alphanumerics, dashes and underscores.
uint32_t fnv1_hash(const char *str)
Calculate a FNV-1 hash of str.
@ ENTITY_CATEGORY_DIAGNOSTIC
void get_mac_address_into_buffer(std::span< char, MAC_ADDRESS_BUFFER_SIZE > buf)
Get the device MAC address into the given buffer, in lowercase hex notation.
std::string str_sprintf(const char *fmt,...)
Application App
Global storage of Application pointer - only one Application can exist.
Simple data struct for Home Assistant component availability.
std::string payload_not_available
std::string topic
Empty means disabled.
std::string payload_available
Internal struct for MQTT Home Assistant discovery.
MQTTDiscoveryUniqueIdGenerator unique_id_generator
std::string prefix
The Home Assistant discovery prefix. Empty means disabled.
MQTTDiscoveryObjectIdGenerator object_id_generator
bool retain
Whether to retain discovery messages.
Simple Helper struct used for Home Assistant MQTT send_discovery().
bool command_topic
If the command topic should be included. Default to true.
bool state_topic
If the state topic should be included. Defaults to true.
const uint8_t ESPHOME_WEBSERVER_INDEX_HTML[] PROGMEM