ESPHome 2025.10.0-dev
Loading...
Searching...
No Matches
gpio_binary_sensor.cpp
Go to the documentation of this file.
2#include "esphome/core/log.h"
3
4namespace esphome {
5namespace gpio {
6
7static const char *const TAG = "gpio.binary_sensor";
8
9#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
10static const LogString *interrupt_type_to_string(gpio::InterruptType type) {
11 switch (type) {
13 return LOG_STR("RISING_EDGE");
15 return LOG_STR("FALLING_EDGE");
17 return LOG_STR("ANY_EDGE");
18 default:
19 return LOG_STR("UNKNOWN");
20 }
21}
22
23static const LogString *gpio_mode_to_string(bool use_interrupt) {
24 return use_interrupt ? LOG_STR("interrupt") : LOG_STR("polling");
25}
26#endif
27
29 bool new_state = arg->isr_pin_.digital_read();
30 if (new_state != arg->last_state_) {
31 arg->state_ = new_state;
32 arg->last_state_ = new_state;
33 arg->changed_ = true;
34 // Wake up the component from its disabled loop state
35 if (arg->component_ != nullptr) {
37 }
38 }
39}
40
42 pin->setup();
43 this->isr_pin_ = pin->to_isr();
44 this->component_ = component;
45
46 // Read initial state
47 this->last_state_ = pin->digital_read();
48 this->state_ = this->last_state_;
49
50 // Attach interrupt - from this point on, any changes will be caught by the interrupt
52}
53
55 if (this->use_interrupt_ && !this->pin_->is_internal()) {
56 ESP_LOGD(TAG, "GPIO is not internal, falling back to polling mode");
57 this->use_interrupt_ = false;
58 }
59
60 if (this->use_interrupt_) {
61 auto *internal_pin = static_cast<InternalGPIOPin *>(this->pin_);
62 this->store_.setup(internal_pin, this->interrupt_type_, this);
64 } else {
65 this->pin_->setup();
67 }
68}
69
71 LOG_BINARY_SENSOR("", "GPIO Binary Sensor", this);
72 LOG_PIN(" Pin: ", this->pin_);
73 ESP_LOGCONFIG(TAG, " Mode: %s", LOG_STR_ARG(gpio_mode_to_string(this->use_interrupt_)));
74 if (this->use_interrupt_) {
75 ESP_LOGCONFIG(TAG, " Interrupt Type: %s", LOG_STR_ARG(interrupt_type_to_string(this->interrupt_type_)));
76 }
77}
78
80 if (this->use_interrupt_) {
81 if (this->store_.is_changed()) {
82 // Clear the flag immediately to minimize the window where we might miss changes
83 this->store_.clear_changed();
84 // Read the state and publish it
85 // Note: If the ISR fires between clear_changed() and get_state(), that's fine -
86 // we'll process the new change on the next loop iteration
87 bool state = this->store_.get_state();
88 this->publish_state(state);
89 } else {
90 // No changes, disable the loop until the next interrupt
91 this->disable_loop();
92 }
93 } else {
94 this->publish_state(this->pin_->digital_read());
95 }
96}
97
99
100} // namespace gpio
101} // namespace esphome
void enable_loop_soon_any_context()
Thread and ISR-safe version of enable_loop() that can be called from any context.
void disable_loop()
Disable this component's loop.
virtual void setup()=0
virtual bool is_internal()
Definition gpio.h:69
virtual bool digital_read()=0
void attach_interrupt(void(*func)(T *), T *arg, gpio::InterruptType type) const
Definition gpio.h:88
virtual ISRInternalGPIOPin to_isr() const =0
void publish_state(bool new_state)
Publish a new state to the front-end.
void publish_initial_state(bool new_state)
Publish the initial state, this will not make the callback manager send callbacks and is meant only f...
void loop() override
Check sensor.
float get_setup_priority() const override
Hardware priority.
void setup() override
Setup pin.
void setup(InternalGPIOPin *pin, gpio::InterruptType type, Component *component)
static void gpio_intr(GPIOBinarySensorStore *arg)
uint16_t type
@ INTERRUPT_FALLING_EDGE
Definition gpio.h:42
@ INTERRUPT_RISING_EDGE
Definition gpio.h:41
@ INTERRUPT_ANY_EDGE
Definition gpio.h:43
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.cpp:48
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7