ESPHome  2024.9.0
valve.cpp
Go to the documentation of this file.
1 #include "valve.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace valve {
6 
7 static const char *const TAG = "valve";
8 
9 const float VALVE_OPEN = 1.0f;
10 const float VALVE_CLOSED = 0.0f;
11 
12 const char *valve_command_to_str(float pos) {
13  if (pos == VALVE_OPEN) {
14  return "OPEN";
15  } else if (pos == VALVE_CLOSED) {
16  return "CLOSE";
17  } else {
18  return "UNKNOWN";
19  }
20 }
22  switch (op) {
24  return "IDLE";
26  return "OPENING";
28  return "CLOSING";
29  default:
30  return "UNKNOWN";
31  }
32 }
33 
34 Valve::Valve() : position{VALVE_OPEN} {}
35 
36 ValveCall::ValveCall(Valve *parent) : parent_(parent) {}
37 ValveCall &ValveCall::set_command(const char *command) {
38  if (strcasecmp(command, "OPEN") == 0) {
39  this->set_command_open();
40  } else if (strcasecmp(command, "CLOSE") == 0) {
41  this->set_command_close();
42  } else if (strcasecmp(command, "STOP") == 0) {
43  this->set_command_stop();
44  } else if (strcasecmp(command, "TOGGLE") == 0) {
45  this->set_command_toggle();
46  } else {
47  ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command);
48  }
49  return *this;
50 }
52  this->position_ = VALVE_OPEN;
53  return *this;
54 }
56  this->position_ = VALVE_CLOSED;
57  return *this;
58 }
60  this->stop_ = true;
61  return *this;
62 }
64  this->toggle_ = true;
65  return *this;
66 }
68  this->position_ = position;
69  return *this;
70 }
72  ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
73  auto traits = this->parent_->get_traits();
74  this->validate_();
75  if (this->stop_) {
76  ESP_LOGD(TAG, " Command: STOP");
77  }
78  if (this->position_.has_value()) {
79  if (traits.get_supports_position()) {
80  ESP_LOGD(TAG, " Position: %.0f%%", *this->position_ * 100.0f);
81  } else {
82  ESP_LOGD(TAG, " Command: %s", valve_command_to_str(*this->position_));
83  }
84  }
85  if (this->toggle_.has_value()) {
86  ESP_LOGD(TAG, " Command: TOGGLE");
87  }
88  this->parent_->control(*this);
89 }
90 const optional<float> &ValveCall::get_position() const { return this->position_; }
91 const optional<bool> &ValveCall::get_toggle() const { return this->toggle_; }
93  auto traits = this->parent_->get_traits();
94  if (this->position_.has_value()) {
95  auto pos = *this->position_;
96  if (!traits.get_supports_position() && pos != VALVE_OPEN && pos != VALVE_CLOSED) {
97  ESP_LOGW(TAG, "'%s' - This valve device does not support setting position!", this->parent_->get_name().c_str());
98  this->position_.reset();
99  } else if (pos < 0.0f || pos > 1.0f) {
100  ESP_LOGW(TAG, "'%s' - Position %.2f is out of range [0.0 - 1.0]", this->parent_->get_name().c_str(), pos);
101  this->position_ = clamp(pos, 0.0f, 1.0f);
102  }
103  }
104  if (this->toggle_.has_value()) {
105  if (!traits.get_supports_toggle()) {
106  ESP_LOGW(TAG, "'%s' - This valve device does not support toggle!", this->parent_->get_name().c_str());
107  this->toggle_.reset();
108  }
109  }
110  if (this->stop_) {
111  if (this->position_.has_value()) {
112  ESP_LOGW(TAG, "Cannot set position when stopping a valve!");
113  this->position_.reset();
114  }
115  if (this->toggle_.has_value()) {
116  ESP_LOGW(TAG, "Cannot set toggle when stopping a valve!");
117  this->toggle_.reset();
118  }
119  }
120 }
122  this->stop_ = stop;
123  return *this;
124 }
125 bool ValveCall::get_stop() const { return this->stop_; }
126 
127 ValveCall Valve::make_call() { return {this}; }
128 
129 void Valve::add_on_state_callback(std::function<void()> &&f) { this->state_callback_.add(std::move(f)); }
130 void Valve::publish_state(bool save) {
131  this->position = clamp(this->position, 0.0f, 1.0f);
132 
133  ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str());
134  auto traits = this->get_traits();
135  if (traits.get_supports_position()) {
136  ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f);
137  } else {
138  if (this->position == VALVE_OPEN) {
139  ESP_LOGD(TAG, " State: OPEN");
140  } else if (this->position == VALVE_CLOSED) {
141  ESP_LOGD(TAG, " State: CLOSED");
142  } else {
143  ESP_LOGD(TAG, " State: UNKNOWN");
144  }
145  }
146  ESP_LOGD(TAG, " Current Operation: %s", valve_operation_to_str(this->current_operation));
147 
148  this->state_callback_.call();
149 
150  if (save) {
151  ValveRestoreState restore{};
152  memset(&restore, 0, sizeof(restore));
153  restore.position = this->position;
154  this->rtc_.save(&restore);
155  }
156 }
158  this->rtc_ = global_preferences->make_preference<ValveRestoreState>(this->get_object_id_hash());
159  ValveRestoreState recovered{};
160  if (!this->rtc_.load(&recovered))
161  return {};
162  return recovered;
163 }
164 
165 bool Valve::is_fully_open() const { return this->position == VALVE_OPEN; }
166 bool Valve::is_fully_closed() const { return this->position == VALVE_CLOSED; }
167 
169  auto call = valve->make_call();
170  call.set_position(this->position);
171  return call;
172 }
174  valve->position = this->position;
175  valve->publish_state();
176 }
177 
178 } // namespace valve
179 } // namespace esphome
ValveCall & set_command(const char *command)
Set the command as a string, "STOP", "OPEN", "CLOSE", "TOGGLE".
Definition: valve.cpp:37
ValveCall & set_command_open()
Set the command to open the valve.
Definition: valve.cpp:51
ValveCall to_call(Valve *valve)
Convert this struct to a valve call that can be performed.
Definition: valve.cpp:168
ValveOperation
Enum encoding the current operation of a valve.
Definition: valve.h:75
bool is_fully_closed() const
Helper method to check if the valve is fully closed. Equivalent to comparing .position against 0...
Definition: valve.cpp:166
float position
The position of the valve from 0.0 (fully closed) to 1.0 (fully open).
Definition: valve.h:116
void add_on_state_callback(std::function< void()> &&f)
Definition: valve.cpp:129
virtual void control(const ValveCall &call)=0
const optional< bool > & get_toggle() const
Definition: valve.cpp:91
Struct used to store the restored state of a valve.
Definition: valve.h:65
bool has_value() const
Definition: optional.h:87
void apply(Valve *valve)
Apply these settings to the valve.
Definition: valve.cpp:173
ValveCall & set_command_stop()
Set the command to stop the valve.
Definition: valve.cpp:59
virtual ValveTraits get_traits()=0
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
Definition: helpers.h:92
The valve is currently opening.
Definition: valve.h:79
ValveCall & set_command_toggle()
Set the command to toggle the valve.
Definition: valve.cpp:63
ValveCall make_call()
Construct a new valve call used to control the valve.
Definition: valve.cpp:127
ValveCall & set_command_close()
Set the command to close the valve.
Definition: valve.cpp:55
The valve is currently idle (not moving)
Definition: valve.h:77
The valve is currently closing.
Definition: valve.h:81
void perform()
Perform the valve call.
Definition: valve.cpp:71
const char *const TAG
Definition: spi.cpp:8
ESPPreferences * global_preferences
bool is_fully_open() const
Helper method to check if the valve is fully open. Equivalent to comparing .position against 1...
Definition: valve.cpp:165
bool get_stop() const
Definition: valve.cpp:125
ValveCall & set_stop(bool stop)
Set whether this valve call should stop the valve.
Definition: valve.cpp:121
optional< bool > toggle_
Definition: valve.h:61
const float VALVE_OPEN
Definition: valve.cpp:9
optional< ValveRestoreState > restore_state_()
Definition: valve.cpp:157
constexpr const char * c_str() const
Definition: string_ref.h:68
const char * valve_operation_to_str(ValveOperation op)
Definition: valve.cpp:21
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
const optional< float > & get_position() const
Definition: valve.cpp:90
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
Base class for all valve devices.
Definition: valve.h:105
void publish_state(bool save=true)
Publish the current state of the valve.
Definition: valve.cpp:130
float position
Definition: cover.h:14
ValveCall & set_position(float position)
Set the call to a certain target position.
Definition: valve.cpp:67
optional< float > position_
Definition: valve.h:60
const StringRef & get_name() const
Definition: entity_base.cpp:10
const float VALVE_CLOSED
Definition: valve.cpp:10
ValveCall(Valve *parent)
Definition: valve.cpp:36
const char * valve_command_to_str(float pos)
Definition: valve.cpp:12