ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
mqtt_valve.cpp
Go to the documentation of this file.
1#include "mqtt_valve.h"
2#include "esphome/core/log.h"
4
5#include "mqtt_const.h"
6
7#ifdef USE_MQTT
8#ifdef USE_VALVE
9
10namespace esphome::mqtt {
11
12static const char *const TAG = "mqtt.valve";
13
14using namespace esphome::valve;
15
16static ProgmemStr valve_state_to_mqtt_str(ValveOperation operation, float position, bool supports_position) {
17 if (operation == VALVE_OPERATION_OPENING)
18 return ESPHOME_F("opening");
19 if (operation == VALVE_OPERATION_CLOSING)
20 return ESPHOME_F("closing");
22 return ESPHOME_F("closed");
23 if (position == VALVE_OPEN)
24 return ESPHOME_F("open");
25 if (supports_position)
26 return ESPHOME_F("open");
27 return ESPHOME_F("unknown");
28}
29
32 auto traits = this->valve_->get_traits();
33 this->valve_->add_on_state_callback([this]() { this->publish_state(); });
34 this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) {
35 auto call = this->valve_->make_call();
36 call.set_command(payload.c_str());
37 call.perform();
38 });
39 if (traits.get_supports_position()) {
40 this->subscribe(this->get_position_command_topic(), [this](const std::string &topic, const std::string &payload) {
41 auto value = parse_number<float>(payload);
42 if (!value.has_value()) {
43 ESP_LOGW(TAG, "Invalid position value: '%s'", payload.c_str());
44 return;
45 }
46 auto call = this->valve_->make_call();
47 call.set_position(*value / 100.0f);
48 call.perform();
49 });
50 }
51}
52
54 ESP_LOGCONFIG(TAG, "MQTT valve '%s':", this->valve_->get_name().c_str());
55 auto traits = this->valve_->get_traits();
56 bool has_command_topic = traits.get_supports_position();
57 LOG_MQTT_COMPONENT(true, has_command_topic);
58 if (traits.get_supports_position()) {
59 ESP_LOGCONFIG(TAG,
60 " Position State Topic: '%s'\n"
61 " Position Command Topic: '%s'",
62 this->get_position_state_topic().c_str(), this->get_position_command_topic().c_str());
63 }
64}
66 // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
67 const auto device_class = this->valve_->get_device_class_ref();
68 if (!device_class.empty()) {
69 root[MQTT_DEVICE_CLASS] = device_class;
70 }
71 // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
72
73 auto traits = this->valve_->get_traits();
74 if (traits.get_is_assumed_state()) {
75 root[MQTT_OPTIMISTIC] = true;
76 }
77 if (traits.get_supports_position()) {
78 root[MQTT_POSITION_TOPIC] = this->get_position_state_topic();
79 root[MQTT_SET_POSITION_TOPIC] = this->get_position_command_topic();
80 }
81}
82
84const EntityBase *MQTTValveComponent::get_entity() const { return this->valve_; }
85
88 auto traits = this->valve_->get_traits();
89 bool success = true;
90 char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN];
91 if (traits.get_supports_position()) {
92 char pos[VALUE_ACCURACY_MAX_LEN];
93 size_t len = value_accuracy_to_buf(pos, roundf(this->valve_->position * 100), 0);
94 if (!this->publish(this->get_position_state_topic_to(topic_buf), pos, len))
95 success = false;
96 }
97 if (!this->publish(this->get_state_topic_to_(topic_buf),
98 valve_state_to_mqtt_str(this->valve_->current_operation, this->valve_->position,
99 traits.get_supports_position())))
100 success = false;
101 return success;
102}
103
104} // namespace esphome::mqtt
105
106#endif
107#endif // USE_MQTT
StringRef get_device_class_ref() const
Get the device class as StringRef.
const StringRef & get_name() const
constexpr const char * c_str() const
Definition string_ref.h:73
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).
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.
state bool send_initial_state() override
MQTTValveComponent(valve::Valve *valve)
void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override
ValveCall & set_position(float position)
Set the call to a certain target position.
Definition valve.cpp:66
ValveCall & set_command(const char *command)
Set the command as a string, "STOP", "OPEN", "CLOSE", "TOGGLE".
Definition valve.cpp:36
void perform()
Perform the valve call.
Definition valve.cpp:70
Base class for all valve devices.
Definition valve.h:104
float position
The position of the valve from 0.0 (fully closed) to 1.0 (fully open).
Definition valve.h:115
ValveCall make_call()
Construct a new valve call used to control the valve.
Definition valve.cpp:126
ValveOperation current_operation
The current operation of the valve (idle, opening, closing).
Definition valve.h:109
void add_on_state_callback(std::function< void()> &&f)
Definition valve.cpp:128
virtual ValveTraits get_traits()=0
bool get_supports_position() const
float position
Definition cover.h:0
MQTT_COMPONENT_TYPE(MQTTAlarmControlPanelComponent, "alarm_control_panel") const EntityBase *MQTTAlarmControlPanelComponent
const float VALVE_OPEN
Definition valve.cpp:14
const float VALVE_CLOSED
Definition valve.cpp:15
ValveOperation
Enum encoding the current operation of a valve.
Definition valve.h:74
@ VALVE_OPERATION_OPENING
The valve is currently opening.
Definition valve.h:78
@ VALVE_OPERATION_CLOSING
The valve is currently closing.
Definition valve.h:80
size_t value_accuracy_to_buf(std::span< char, VALUE_ACCURACY_MAX_LEN > buf, float value, int8_t accuracy_decimals)
Format value with accuracy to buffer, returns chars written (excluding null)
Definition helpers.cpp:490
std::string size_t len
Definition helpers.h:817
optional< T > parse_number(const char *str)
Parse an unsigned decimal number from a null-terminated string.
Definition helpers.h:910
size_t size_t pos
Definition helpers.h:854
const __FlashStringHelper * ProgmemStr
Definition progmem.h:26
Simple Helper struct used for Home Assistant MQTT send_discovery().