mirror of
https://github.com/esphome/esphome.git
synced 2026-08-24 07:06:20 +00:00
[gpio] Fix linker error when binary sensor only uses expander pins
This commit is contained in:
@@ -133,6 +133,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add(var.set_pin(pin))
|
||||
|
||||
if config[CONF_USE_INTERRUPT]:
|
||||
cg.add_define("USE_GPIO_BINARY_SENSOR_INTERRUPT")
|
||||
cg.add(var.set_interrupt_type(config[CONF_INTERRUPT_TYPE]))
|
||||
else:
|
||||
cg.add(var.set_use_interrupt(False))
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace esphome::gpio {
|
||||
static const char *const TAG = "gpio.binary_sensor";
|
||||
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
|
||||
#ifdef USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
// Interrupt type strings indexed by edge-triggered InterruptType values:
|
||||
// indices 1-3: RISING_EDGE, FALLING_EDGE, ANY_EDGE; other values (e.g. level-triggered) map to UNKNOWN (index 0).
|
||||
PROGMEM_STRING_TABLE(InterruptTypeStrings, "UNKNOWN", "RISING_EDGE", "FALLING_EDGE", "ANY_EDGE");
|
||||
@@ -14,12 +15,14 @@ PROGMEM_STRING_TABLE(InterruptTypeStrings, "UNKNOWN", "RISING_EDGE", "FALLING_ED
|
||||
static const LogString *interrupt_type_to_string(gpio::InterruptType type) {
|
||||
return InterruptTypeStrings::get_log_str(static_cast<uint8_t>(type), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const LogString *gpio_mode_to_string(bool use_interrupt) {
|
||||
return use_interrupt ? LOG_STR("interrupt") : LOG_STR("polling");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
void IRAM_ATTR GPIOBinarySensorStore::gpio_intr(GPIOBinarySensorStore *arg) {
|
||||
bool new_state = arg->isr_pin_.digital_read();
|
||||
if (new_state != arg->state_) {
|
||||
@@ -43,28 +46,34 @@ void GPIOBinarySensorStore::setup(InternalGPIOPin *pin, Component *component) {
|
||||
// Attach interrupt - from this point on, any changes will be caught by the interrupt
|
||||
pin->attach_interrupt(&GPIOBinarySensorStore::gpio_intr, this, this->interrupt_type_);
|
||||
}
|
||||
#endif // USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
|
||||
void GPIOBinarySensor::setup() {
|
||||
#ifdef USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
if (this->store_.use_interrupt_) {
|
||||
auto *internal_pin = static_cast<InternalGPIOPin *>(this->pin_);
|
||||
this->store_.setup(internal_pin, this);
|
||||
this->publish_initial_state(this->store_.get_state());
|
||||
} else {
|
||||
this->pin_->setup();
|
||||
this->publish_initial_state(this->pin_->digital_read());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
this->pin_->setup();
|
||||
this->publish_initial_state(this->pin_->digital_read());
|
||||
}
|
||||
|
||||
void GPIOBinarySensor::dump_config() {
|
||||
LOG_BINARY_SENSOR("", "GPIO Binary Sensor", this);
|
||||
LOG_PIN(" Pin: ", this->pin_);
|
||||
ESP_LOGCONFIG(TAG, " Mode: %s", LOG_STR_ARG(gpio_mode_to_string(this->store_.use_interrupt_)));
|
||||
#ifdef USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
if (this->store_.use_interrupt_) {
|
||||
ESP_LOGCONFIG(TAG, " Interrupt Type: %s", LOG_STR_ARG(interrupt_type_to_string(this->store_.interrupt_type_)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GPIOBinarySensor::loop() {
|
||||
#ifdef USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
if (this->store_.use_interrupt_) {
|
||||
if (this->store_.is_changed()) {
|
||||
// Clear the flag immediately to minimize the window where we might miss changes
|
||||
@@ -78,9 +87,10 @@ void GPIOBinarySensor::loop() {
|
||||
// No changes, disable the loop until the next interrupt
|
||||
this->disable_loop();
|
||||
}
|
||||
} else {
|
||||
this->publish_state(this->pin_->digital_read());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
this->publish_state(this->pin_->digital_read());
|
||||
}
|
||||
|
||||
float GPIOBinarySensor::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
@@ -10,6 +11,7 @@ namespace esphome::gpio {
|
||||
// Store class for ISR data and configuration (no vtables, ISR-safe)
|
||||
class GPIOBinarySensorStore {
|
||||
public:
|
||||
#ifdef USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
void setup(InternalGPIOPin *pin, Component *component);
|
||||
|
||||
static void gpio_intr(GPIOBinarySensorStore *arg);
|
||||
@@ -29,15 +31,18 @@ class GPIOBinarySensorStore {
|
||||
// Separate method to clear the flag
|
||||
this->changed_ = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend class GPIOBinarySensor;
|
||||
#ifdef USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
ISRInternalGPIOPin isr_pin_;
|
||||
Component *component_{nullptr}; // Pointer to the component for enable_loop_soon_any_context()
|
||||
volatile bool state_{false};
|
||||
volatile bool changed_{false};
|
||||
bool use_interrupt_{true};
|
||||
gpio::InterruptType interrupt_type_{gpio::INTERRUPT_ANY_EDGE};
|
||||
#endif
|
||||
bool use_interrupt_{true};
|
||||
};
|
||||
|
||||
class GPIOBinarySensor final : public binary_sensor::BinarySensor, public Component {
|
||||
@@ -47,7 +52,9 @@ class GPIOBinarySensor final : public binary_sensor::BinarySensor, public Compon
|
||||
|
||||
void set_pin(GPIOPin *pin) { this->pin_ = pin; }
|
||||
void set_use_interrupt(bool use_interrupt) { this->store_.use_interrupt_ = use_interrupt; }
|
||||
#ifdef USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
void set_interrupt_type(gpio::InterruptType type) { this->store_.interrupt_type_ = type; }
|
||||
#endif
|
||||
// ========== INTERNAL METHODS ==========
|
||||
// (In most use cases you won't need these)
|
||||
/// Setup pin
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#define USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
#define USE_EVENT
|
||||
#define USE_FAN
|
||||
#define USE_GPIO_BINARY_SENSOR_INTERRUPT
|
||||
#define USE_GPIO_SWITCH_INTERLOCK
|
||||
#define USE_GRAPH
|
||||
#define USE_GRAPHICAL_DISPLAY_MENU
|
||||
|
||||
@@ -3,6 +3,13 @@ binary_sensor:
|
||||
pin: ${binary_sensor_pin}
|
||||
id: gpio_binary_sensor
|
||||
|
||||
# Polling sensor alongside an interrupt sensor: proves the mixed build where
|
||||
# both code paths are compiled and selected per instance at runtime.
|
||||
- platform: gpio
|
||||
pin: ${binary_sensor_pin_2}
|
||||
id: gpio_binary_sensor_polling
|
||||
use_interrupt: false
|
||||
|
||||
output:
|
||||
- platform: gpio
|
||||
pin: ${output_pin}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
binary_sensor_pin: GPIO2
|
||||
binary_sensor_pin_2: GPIO10
|
||||
output_pin: GPIO3
|
||||
switch_pin: GPIO4
|
||||
switch_pin_2: GPIO5
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
binary_sensor_pin: GPIO12
|
||||
binary_sensor_pin_2: GPIO18
|
||||
output_pin: GPIO13
|
||||
switch_pin: GPIO14
|
||||
switch_pin_2: GPIO15
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
binary_sensor_pin: GPIO0
|
||||
binary_sensor_pin_2: GPIO4
|
||||
output_pin: GPIO2
|
||||
switch_pin: GPIO15
|
||||
switch_pin_2: GPIO12
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
substitutions:
|
||||
binary_sensor_pin: GPIO2
|
||||
binary_sensor_pin_2: GPIO8
|
||||
output_pin: GPIO3
|
||||
switch_pin: GPIO4
|
||||
switch_pin_2: GPIO5
|
||||
|
||||
Reference in New Issue
Block a user