mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 02:02:51 +00:00
[gpio] Keep each interlock group in one shared flash table (#20238)
This commit is contained in:
@@ -36,11 +36,17 @@ async def to_code(config: ConfigType) -> None:
|
||||
pin = await cg.gpio_pin_expression(config[CONF_PIN])
|
||||
cg.add(var.set_pin(pin))
|
||||
|
||||
if CONF_INTERLOCK in config:
|
||||
if (interlock := config.get(CONF_INTERLOCK)) is not None:
|
||||
cg.add_define("USE_GPIO_SWITCH_INTERLOCK")
|
||||
interlock = []
|
||||
for it in config[CONF_INTERLOCK]:
|
||||
lock = await cg.get_variable(it)
|
||||
interlock.append(lock)
|
||||
cg.add(var.set_interlock(interlock))
|
||||
locks = [await cg.get_variable(it) for it in interlock]
|
||||
# The group's table lists this switch too, so every member shares one table.
|
||||
group = sorted({str(s): s for s in (var, *locks)}.values(), key=str)
|
||||
if len(group) > 1:
|
||||
table = cg.shared_progmem_array(
|
||||
"gpio_interlock",
|
||||
switch.Switch.operator("ptr"),
|
||||
cg.ArrayInitializer(*group),
|
||||
constexpr=False,
|
||||
)
|
||||
cg.add(var.set_interlock(table, len(group)))
|
||||
cg.add(var.set_interlock_wait_time(config[CONF_INTERLOCK_WAIT_TIME]))
|
||||
|
||||
@@ -67,8 +67,4 @@ void GPIOSwitch::write_state(bool state) {
|
||||
this->publish_state(state);
|
||||
}
|
||||
|
||||
#ifdef USE_GPIO_SWITCH_INTERLOCK
|
||||
void GPIOSwitch::set_interlock(const std::initializer_list<Switch *> &interlock) { this->interlock_ = interlock; }
|
||||
#endif
|
||||
|
||||
} // namespace esphome::gpio
|
||||
|
||||
@@ -21,7 +21,10 @@ class GPIOSwitch final : public switch_::Switch, public Component {
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
#ifdef USE_GPIO_SWITCH_INTERLOCK
|
||||
void set_interlock(const std::initializer_list<Switch *> &interlock);
|
||||
/// Codegen only: the table must outlive this switch; it may list this switch, which is skipped.
|
||||
void set_interlock(Switch *const *interlock, size_t count) {
|
||||
this->interlock_ = ConstVector<Switch *>(interlock, count);
|
||||
}
|
||||
void set_interlock_wait_time(uint32_t interlock_wait_time) { interlock_wait_time_ = interlock_wait_time; }
|
||||
#endif
|
||||
|
||||
@@ -30,7 +33,7 @@ class GPIOSwitch final : public switch_::Switch, public Component {
|
||||
|
||||
GPIOPin *pin_{nullptr};
|
||||
#ifdef USE_GPIO_SWITCH_INTERLOCK
|
||||
FixedVector<Switch *> interlock_;
|
||||
ConstVector<Switch *> interlock_;
|
||||
uint32_t interlock_wait_time_{0};
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
"""Tests for the GPIO switch component."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
|
||||
def test_gpio_switch_interlock_group_shares_one_table(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
) -> None:
|
||||
"""Every member of an interlock group points at the same flash table."""
|
||||
main_cpp = generate_main(
|
||||
"tests/component_tests/gpio/test_gpio_switch_interlock.yaml"
|
||||
)
|
||||
|
||||
tables = re.findall(r"(gpio_interlock\w*)\[\] PROGMEM = \{([^}]*)\};", main_cpp)
|
||||
assert tables == [("gpio_interlock", "sw_a, sw_b, sw_c")]
|
||||
for sw in ("sw_a", "sw_b", "sw_c"):
|
||||
assert f"{sw}->set_interlock(gpio_interlock, 3);" in main_cpp
|
||||
|
||||
|
||||
def test_gpio_switch_interlock_with_only_itself_has_no_table(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
) -> None:
|
||||
"""A switch interlocked only with itself gets no table and no set_interlock."""
|
||||
main_cpp = generate_main(
|
||||
"tests/component_tests/gpio/test_gpio_switch_interlock.yaml"
|
||||
)
|
||||
|
||||
assert "sw_self->set_interlock(" not in main_cpp
|
||||
assert "sw_self->set_interlock_wait_time(0);" in main_cpp
|
||||
@@ -0,0 +1,23 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
pin: 12
|
||||
id: sw_a
|
||||
interlock: [sw_b, sw_c]
|
||||
- platform: gpio
|
||||
pin: 13
|
||||
id: sw_b
|
||||
interlock: [sw_a, sw_c]
|
||||
- platform: gpio
|
||||
pin: 14
|
||||
id: sw_c
|
||||
interlock: [sw_a, sw_b]
|
||||
- platform: gpio
|
||||
pin: 15
|
||||
id: sw_self
|
||||
interlock: [sw_self]
|
||||
Reference in New Issue
Block a user