12static const char *
const TAG =
"mqtt.fan";
17 return direction == FanDirection::FORWARD ? ESPHOME_F(
"forward") : ESPHOME_F(
"reverse");
21 return oscillating ? ESPHOME_F(
"oscillate_on") : ESPHOME_F(
"oscillate_off");
35 ESP_LOGD(TAG,
"'%s' Turning Fan ON.", this->
friendly_name_().c_str());
39 ESP_LOGD(TAG,
"'%s' Turning Fan OFF.", this->
friendly_name_().c_str());
43 ESP_LOGD(TAG,
"'%s' Toggling Fan.", this->
friendly_name_().c_str());
48 ESP_LOGW(TAG,
"Unknown state payload %s", payload.c_str());
55 this->
subscribe(this->get_direction_command_topic(), [
this](
const std::string &topic,
const std::string &payload) {
59 ESP_LOGD(TAG,
"'%s': Setting direction FORWARD", this->
friendly_name_().c_str());
63 ESP_LOGD(TAG,
"'%s': Setting direction REVERSE", this->
friendly_name_().c_str());
73 ESP_LOGW(TAG,
"Unknown direction Payload %s", payload.c_str());
81 this->
subscribe(this->get_oscillation_command_topic(),
82 [
this](
const std::string &topic,
const std::string &payload) {
83 auto val =
parse_on_off(payload.c_str(),
"oscillate_on",
"oscillate_off");
86 ESP_LOGD(TAG,
"'%s': Setting oscillating ON", this->
friendly_name_().c_str());
90 ESP_LOGD(TAG,
"'%s': Setting oscillating OFF", this->
friendly_name_().c_str());
97 ESP_LOGW(TAG,
"Unknown Oscillation Payload %s", payload.c_str());
105 this->
subscribe(this->get_speed_level_command_topic(),
106 [
this](
const std::string &topic,
const std::string &payload) {
108 if (speed_level_opt.has_value()) {
109 const int speed_level = speed_level_opt.value();
111 ESP_LOGD(TAG,
"New speed level %d", speed_level);
114 ESP_LOGW(TAG,
"Invalid speed level %d", speed_level);
118 ESP_LOGW(TAG,
"Invalid speed level %s (int expected)", payload.c_str());
129 LOG_MQTT_COMPONENT(
true,
true);
132 " Direction State Topic: '%s'\n"
133 " Direction Command Topic: '%s'",
134 this->get_direction_state_topic().c_str(), this->get_direction_command_topic().c_str());
138 " Oscillation State Topic: '%s'\n"
139 " Oscillation Command Topic: '%s'",
140 this->get_oscillation_state_topic().c_str(), this->get_oscillation_command_topic().c_str());
144 " Speed Level State Topic: '%s'\n"
145 " Speed Level Command Topic: '%s'",
146 this->get_speed_level_state_topic().c_str(), this->get_speed_level_command_topic().c_str());
155 root[MQTT_DIRECTION_COMMAND_TOPIC] = this->get_direction_command_topic();
156 root[MQTT_DIRECTION_STATE_TOPIC] = this->get_direction_state_topic();
159 root[MQTT_OSCILLATION_COMMAND_TOPIC] = this->get_oscillation_command_topic();
160 root[MQTT_OSCILLATION_STATE_TOPIC] = this->get_oscillation_state_topic();
163 root[MQTT_PERCENTAGE_COMMAND_TOPIC] = this->get_speed_level_command_topic();
164 root[MQTT_PERCENTAGE_STATE_TOPIC] = this->get_speed_level_state_topic();
169 char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN];
170 const char *state_s = this->
state_->
state ?
"ON" :
"OFF";
175 bool success = this->
publish(this->get_direction_state_topic_to(topic_buf),
177 failed = failed || !success;
180 bool success = this->
publish(this->get_oscillation_state_topic_to(topic_buf),
182 failed = failed || !success;
185 if (traits.supports_speed()) {
187 size_t len = buf_append_printf(buf,
sizeof(buf), 0,
"%d", this->
state_->
speed);
188 bool success = this->
publish(this->get_speed_level_state_topic_to(topic_buf), buf,
len);
189 failed = failed || !success;
ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") void defer(const std voi defer)(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call.
void status_momentary_warning(const char *name, uint32_t length=5000)
Set warning status flag and automatically clear it after a timeout.
const StringRef & get_name() const
constexpr const char * c_str() const
FanCall & set_oscillating(bool oscillating)
FanCall & set_direction(FanDirection direction)
FanCall & set_speed(int speed)
void add_on_state_callback(F &&callback)
Register a callback that will be called each time the state changes.
virtual FanTraits get_traits()=0
FanDirection direction
The current direction of the fan.
bool oscillating
The current oscillation state of the fan.
bool state
The current on/off state of the fan.
int speed
The current fan speed level.
int supported_speed_count() const
Return how many speed levels the fan has.
bool supports_direction() const
Return if this fan supports changing direction.
bool supports_speed() const
Return if this fan supports speed modes.
bool supports_oscillation() const
Return if this fan supports oscillation.
bool publish(const std::string &topic, const std::string &payload)
Send a MQTT message.
StringRef get_state_topic_to_(std::span< char, MQTT_DEFAULT_TOPIC_MAX_LEN > buf) const
Get the MQTT state topic into a buffer (no heap allocation for non-lambda custom topics).
const StringRef & friendly_name_() const
Get the friendly name of this MQTT component.
std::string get_command_topic_() const
Get the MQTT topic for listening to commands (allocates std::string).
void subscribe(const std::string &topic, mqtt_callback_t callback, uint8_t qos=0)
Subscribe to a MQTT topic.
fan::Fan * get_state() const
void dump_config() override
state state state state void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override
bool send_initial_state() override
Send the full current state to MQTT.
void setup() override
Setup the fan subscriptions and discovery.
MQTTFanComponent(fan::Fan *state)
FanDirection
Simple enum to represent the direction of a fan.
MQTT_COMPONENT_TYPE(MQTTAlarmControlPanelComponent, "alarm_control_panel") const EntityBase *MQTTAlarmControlPanelComponent
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off)
Parse a string that contains either on, off or toggle.
optional< T > parse_number(const char *str)
Parse an unsigned decimal number from a null-terminated string.
const __FlashStringHelper * ProgmemStr
Simple Helper struct used for Home Assistant MQTT send_discovery().