ESPHome 2025.5.0
Loading...
Searching...
No Matches
mqtt_fan.cpp
Go to the documentation of this file.
1#include "mqtt_fan.h"
2#include "esphome/core/log.h"
3
4#include "mqtt_const.h"
5
6#ifdef USE_MQTT
7#ifdef USE_FAN
8
9namespace esphome {
10namespace mqtt {
11
12static const char *const TAG = "mqtt.fan";
13
14using namespace esphome::fan;
15
17
18Fan *MQTTFanComponent::get_state() const { return this->state_; }
19std::string MQTTFanComponent::component_type() const { return "fan"; }
20const EntityBase *MQTTFanComponent::get_entity() const { return this->state_; }
21
23 this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) {
24 auto val = parse_on_off(payload.c_str());
25 switch (val) {
26 case PARSE_ON:
27 ESP_LOGD(TAG, "'%s' Turning Fan ON.", this->friendly_name().c_str());
28 this->state_->turn_on().perform();
29 break;
30 case PARSE_OFF:
31 ESP_LOGD(TAG, "'%s' Turning Fan OFF.", this->friendly_name().c_str());
32 this->state_->turn_off().perform();
33 break;
34 case PARSE_TOGGLE:
35 ESP_LOGD(TAG, "'%s' Toggling Fan.", this->friendly_name().c_str());
36 this->state_->toggle().perform();
37 break;
38 case PARSE_NONE:
39 default:
40 ESP_LOGW(TAG, "Unknown state payload %s", payload.c_str());
41 this->status_momentary_warning("state", 5000);
42 break;
43 }
44 });
45
46 if (this->state_->get_traits().supports_direction()) {
47 this->subscribe(this->get_direction_command_topic(), [this](const std::string &topic, const std::string &payload) {
48 auto val = parse_on_off(payload.c_str(), "forward", "reverse");
49 switch (val) {
50 case PARSE_ON:
51 ESP_LOGD(TAG, "'%s': Setting direction FORWARD", this->friendly_name().c_str());
53 break;
54 case PARSE_OFF:
55 ESP_LOGD(TAG, "'%s': Setting direction REVERSE", this->friendly_name().c_str());
57 break;
58 case PARSE_TOGGLE:
59 this->state_->make_call()
62 .perform();
63 break;
64 case PARSE_NONE:
65 ESP_LOGW(TAG, "Unknown direction Payload %s", payload.c_str());
66 this->status_momentary_warning("direction", 5000);
67 break;
68 }
69 });
70 }
71
72 if (this->state_->get_traits().supports_oscillation()) {
73 this->subscribe(this->get_oscillation_command_topic(),
74 [this](const std::string &topic, const std::string &payload) {
75 auto val = parse_on_off(payload.c_str(), "oscillate_on", "oscillate_off");
76 switch (val) {
77 case PARSE_ON:
78 ESP_LOGD(TAG, "'%s': Setting oscillating ON", this->friendly_name().c_str());
79 this->state_->make_call().set_oscillating(true).perform();
80 break;
81 case PARSE_OFF:
82 ESP_LOGD(TAG, "'%s': Setting oscillating OFF", this->friendly_name().c_str());
83 this->state_->make_call().set_oscillating(false).perform();
84 break;
85 case PARSE_TOGGLE:
87 break;
88 case PARSE_NONE:
89 ESP_LOGW(TAG, "Unknown Oscillation Payload %s", payload.c_str());
90 this->status_momentary_warning("oscillation", 5000);
91 break;
92 }
93 });
94 }
95
96 if (this->state_->get_traits().supports_speed()) {
97 this->subscribe(this->get_speed_level_command_topic(),
98 [this](const std::string &topic, const std::string &payload) {
99 optional<int> speed_level_opt = parse_number<int>(payload);
100 if (speed_level_opt.has_value()) {
101 const int speed_level = speed_level_opt.value();
102 if (speed_level >= 0 && speed_level <= this->state_->get_traits().supported_speed_count()) {
103 ESP_LOGD(TAG, "New speed level %d", speed_level);
104 this->state_->make_call().set_speed(speed_level).perform();
105 } else {
106 ESP_LOGW(TAG, "Invalid speed level %d", speed_level);
107 this->status_momentary_warning("speed", 5000);
108 }
109 } else {
110 ESP_LOGW(TAG, "Invalid speed level %s (int expected)", payload.c_str());
111 this->status_momentary_warning("speed", 5000);
112 }
113 });
114 }
115
116 auto f = std::bind(&MQTTFanComponent::publish_state, this);
117 this->state_->add_on_state_callback([this, f]() { this->defer("send", f); });
118}
119
121 ESP_LOGCONFIG(TAG, "MQTT Fan '%s': ", this->state_->get_name().c_str());
122 LOG_MQTT_COMPONENT(true, true);
123 if (this->state_->get_traits().supports_direction()) {
124 ESP_LOGCONFIG(TAG, " Direction State Topic: '%s'", this->get_direction_state_topic().c_str());
125 ESP_LOGCONFIG(TAG, " Direction Command Topic: '%s'", this->get_direction_command_topic().c_str());
126 }
127 if (this->state_->get_traits().supports_oscillation()) {
128 ESP_LOGCONFIG(TAG, " Oscillation State Topic: '%s'", this->get_oscillation_state_topic().c_str());
129 ESP_LOGCONFIG(TAG, " Oscillation Command Topic: '%s'", this->get_oscillation_command_topic().c_str());
130 }
131 if (this->state_->get_traits().supports_speed()) {
132 ESP_LOGCONFIG(TAG, " Speed Level State Topic: '%s'", this->get_speed_level_state_topic().c_str());
133 ESP_LOGCONFIG(TAG, " Speed Level Command Topic: '%s'", this->get_speed_level_command_topic().c_str());
134 }
135}
136
138
140 if (this->state_->get_traits().supports_direction()) {
141 root[MQTT_DIRECTION_COMMAND_TOPIC] = this->get_direction_command_topic();
142 root[MQTT_DIRECTION_STATE_TOPIC] = this->get_direction_state_topic();
143 }
144 if (this->state_->get_traits().supports_oscillation()) {
145 root[MQTT_OSCILLATION_COMMAND_TOPIC] = this->get_oscillation_command_topic();
146 root[MQTT_OSCILLATION_STATE_TOPIC] = this->get_oscillation_state_topic();
147 }
148 if (this->state_->get_traits().supports_speed()) {
149 root[MQTT_PERCENTAGE_COMMAND_TOPIC] = this->get_speed_level_command_topic();
150 root[MQTT_PERCENTAGE_STATE_TOPIC] = this->get_speed_level_state_topic();
152 }
153}
155 const char *state_s = this->state_->state ? "ON" : "OFF";
156 ESP_LOGD(TAG, "'%s' Sending state %s.", this->state_->get_name().c_str(), state_s);
157 this->publish(this->get_state_topic_(), state_s);
158 bool failed = false;
159 if (this->state_->get_traits().supports_direction()) {
160 bool success = this->publish(this->get_direction_state_topic(),
161 this->state_->direction == fan::FanDirection::FORWARD ? "forward" : "reverse");
162 failed = failed || !success;
163 }
164 if (this->state_->get_traits().supports_oscillation()) {
165 bool success = this->publish(this->get_oscillation_state_topic(),
166 this->state_->oscillating ? "oscillate_on" : "oscillate_off");
167 failed = failed || !success;
168 }
169 auto traits = this->state_->get_traits();
170 if (traits.supports_speed()) {
171 std::string payload = to_string(this->state_->speed);
172 bool success = this->publish(this->get_speed_level_state_topic(), payload);
173 failed = failed || !success;
174 }
175 return !failed;
176}
177
178} // namespace mqtt
179} // namespace esphome
180
181#endif
182#endif // USE_MQTT
void status_momentary_warning(const std::string &name, uint32_t length=5000)
void defer(const std::string &name, std::function< void()> &&f)
Defer a callback to the next loop() call.
const StringRef & get_name() const
constexpr const char * c_str() const
Definition string_ref.h:68
FanCall & set_oscillating(bool oscillating)
Definition fan.h:50
FanCall & set_direction(FanDirection direction)
Definition fan.h:66
FanCall & set_speed(int speed)
Definition fan.h:59
FanCall turn_on()
Definition fan.cpp:111
FanCall turn_off()
Definition fan.cpp:112
FanCall make_call()
Definition fan.cpp:114
virtual FanTraits get_traits()=0
FanCall toggle()
Definition fan.cpp:113
void add_on_state_callback(std::function< void()> &&callback)
Register a callback that will be called each time the state changes.
Definition fan.cpp:116
FanDirection direction
The current direction of the fan.
Definition fan.h:116
bool oscillating
The current oscillation state of the fan.
Definition fan.h:112
bool state
The current on/off state of the fan.
Definition fan.h:110
int speed
The current fan speed level.
Definition fan.h:114
int supported_speed_count() const
Return how many speed levels the fan has.
Definition fan_traits.h:24
bool supports_direction() const
Return if this fan supports changing direction.
Definition fan_traits.h:28
bool supports_speed() const
Return if this fan supports speed modes.
Definition fan_traits.h:20
bool supports_oscillation() const
Return if this fan supports oscillation.
Definition fan_traits.h:16
bool publish(const std::string &topic, const std::string &payload)
Send a MQTT message.
virtual std::string friendly_name() const
Get the friendly name of this MQTT component.
std::string get_state_topic_() const
Get the MQTT topic that new states will be shared to.
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.
fan::Fan * get_state() const
Definition mqtt_fan.cpp:18
const EntityBase * get_entity() const override
Definition mqtt_fan.cpp:20
state state state state void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override
Definition mqtt_fan.cpp:139
bool send_initial_state() override
Send the full current state to MQTT.
Definition mqtt_fan.cpp:137
std::string component_type() const override
'fan' component type for discovery.
Definition mqtt_fan.cpp:19
void setup() override
Setup the fan subscriptions and discovery.
Definition mqtt_fan.cpp:22
MQTTFanComponent(fan::Fan *state)
Definition mqtt_fan.cpp:16
bool has_value() const
Definition optional.h:87
value_type const & value() const
Definition optional.h:89
bool state
Definition fan.h:0
mopeka_std_values val[4]
constexpr const char *const MQTT_DIRECTION_COMMAND_TOPIC
Definition mqtt_const.h:67
constexpr const char *const MQTT_DIRECTION_STATE_TOPIC
Definition mqtt_const.h:68
constexpr const char *const MQTT_PERCENTAGE_COMMAND_TOPIC
Definition mqtt_const.h:171
constexpr const char *const MQTT_OSCILLATION_STATE_TOPIC
Definition mqtt_const.h:130
constexpr const char *const MQTT_SPEED_RANGE_MAX
Definition mqtt_const.h:208
constexpr const char *const MQTT_OSCILLATION_COMMAND_TOPIC
Definition mqtt_const.h:129
constexpr const char *const MQTT_PERCENTAGE_STATE_TOPIC
Definition mqtt_const.h:172
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off)
Parse a string that contains either on, off or toggle.
Definition helpers.cpp:420
optional< T > parse_number(const char *str)
Parse an unsigned decimal number from a null-terminated string.
Definition helpers.h:313
std::string to_string(int value)
Definition helpers.cpp:82
@ PARSE_ON
Definition helpers.h:442
@ PARSE_TOGGLE
Definition helpers.h:444
@ PARSE_OFF
Definition helpers.h:443
@ PARSE_NONE
Definition helpers.h:441
Simple Helper struct used for Home Assistant MQTT send_discovery().