Compare commits

..
51 changed files with 558 additions and 519 deletions

No files matched your search

-9
View File
@@ -17,15 +17,6 @@ cap1188_ns = cg.esphome_ns.namespace("cap1188")
CONF_CAP1188_ID = "cap1188_id"
CAP1188Component = cap1188_ns.class_("CAP1188Component", cg.Component, i2c.I2CDevice)
# Publishes the channel binary sensors from the touch status read on each loop
CHANNELS_PUBLISHER = cg.HubFunction(
"channels",
cg.void,
[(cg.uint8, "touched")],
define="USE_CAP1188_CHANNELS_PUBLISHER",
)
TOUCHED = CHANNELS_PUBLISHER.param("touched")
MULTI_CONF = True
CONFIG_SCHEMA = (
cv.Schema(
+6 -6
View File
@@ -1,15 +1,15 @@
from esphome.automation import parent_ref
import esphome.codegen as cg
from esphome.components import binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL
from esphome.types import ConfigType
from . import CHANNELS_PUBLISHER, CONF_CAP1188_ID, TOUCHED, CAP1188Component, cap1188_ns
from . import CONF_CAP1188_ID, CAP1188Component, cap1188_ns
DEPENDENCIES = ["cap1188"]
CAP1188Channel = cap1188_ns.class_("CAP1188Channel", binary_sensor.BinarySensor)
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(CAP1188Channel).extend(
{
cv.GenerateID(CONF_CAP1188_ID): cv.use_id(CAP1188Component),
cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7),
@@ -20,6 +20,6 @@ CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
async def to_code(config: ConfigType) -> None:
var = await binary_sensor.new_binary_sensor(config)
hub = await cg.get_variable(config[CONF_CAP1188_ID])
CHANNELS_PUBLISHER.add(
hub, cap1188_ns.publish_channel(parent_ref(var), TOUCHED, config[CONF_CHANNEL])
)
cg.add(var.set_channel(config[CONF_CHANNEL]))
cg.add(hub.register_channel(var))
+3 -4
View File
@@ -79,10 +79,9 @@ void CAP1188Component::loop() {
if (touched)
this->update_register(CAP1188_MAIN, CAP1188_MAIN_INT, 0);
#ifdef USE_CAP1188_CHANNELS_PUBLISHER
if (this->channels_publisher_ != nullptr)
this->channels_publisher_(touched);
#endif
for (auto *channel : this->channels_) {
channel->process(touched);
}
}
} // namespace esphome::cap1188
+13 -8
View File
@@ -4,7 +4,9 @@
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/output/binary_output.h"
#include "esphome/core/helpers.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include <vector>
namespace esphome::cap1188 {
@@ -24,16 +26,18 @@ enum {
CAP1188_SENSITIVITY = 0x1f,
};
// A template on the sensor type keeps binary_sensor.h out of this hub header
template<typename T> inline void publish_channel(T *sensor, uint8_t touched, uint8_t channel) {
sensor->publish_state((touched >> channel) & 1);
}
class CAP1188Channel final : public binary_sensor::BinarySensor {
public:
void set_channel(uint8_t channel) { channel_ = channel; }
void process(uint8_t data) { this->publish_state(static_cast<bool>(data & (1 << this->channel_))); }
protected:
uint8_t channel_{0};
};
class CAP1188Component final : public Component, public i2c::I2CDevice {
public:
#ifdef USE_CAP1188_CHANNELS_PUBLISHER
HUB_PUBLISHER(channels, uint8_t)
#endif
void register_channel(CAP1188Channel *channel) { this->channels_.push_back(channel); }
void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; };
void set_allow_multiple_touches(bool allow_multiple_touches) {
this->allow_multiple_touches_ = allow_multiple_touches ? 0x41 : 0x80;
@@ -46,6 +50,7 @@ class CAP1188Component final : public Component, public i2c::I2CDevice {
protected:
void finish_setup_();
std::vector<CAP1188Channel *> channels_{};
uint8_t touch_threshold_{0x20};
uint8_t allow_multiple_touches_{0x80};
+2 -12
View File
@@ -28,18 +28,6 @@ DOMAIN = "mpr121"
mpr121_ns = cg.esphome_ns.namespace("mpr121")
MPR121Component = mpr121_ns.class_("MPR121Component", cg.Component, i2c.I2CDevice)
# Both run only for channels: the thresholds once at setup, the states on each loop
THRESHOLDS_PUBLISHER = cg.HubFunction(
"thresholds", cg.void, [], define="USE_MPR121_CHANNEL_PUBLISHERS"
)
CHANNELS_PUBLISHER = cg.HubFunction(
"channels",
cg.void,
[(cg.uint16, "touched")],
define="USE_MPR121_CHANNEL_PUBLISHERS",
)
TOUCHED = CHANNELS_PUBLISHER.param("touched")
MPR121GPIOPin = mpr121_ns.class_(
"MPR121GPIOPin", cg.GPIOPin, cg.Parented.template(MPR121Component)
)
@@ -90,6 +78,8 @@ async def to_code(config: ConfigType) -> None:
var = cg.new_Pvariable(config[CONF_ID])
cg.add(var.set_touch_debounce(config[CONF_TOUCH_DEBOUNCE]))
cg.add(var.set_release_debounce(config[CONF_RELEASE_DEBOUNCE]))
cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD]))
cg.add(var.set_release_threshold(config[CONF_RELEASE_THRESHOLD]))
cg.add(var.set_max_touch_channel(config[CONF_MAX_TOUCH_CHANNEL]))
await cg.register_component(var, config)
await i2c.register_i2c_device(var, config)
@@ -1,25 +1,21 @@
from esphome.automation import parent_ref
import esphome.codegen as cg
from esphome.components import binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL
import esphome.final_validate as fv
from esphome.types import ConfigType
from .. import (
CHANNELS_PUBLISHER,
CONF_MPR121_ID,
CONF_RELEASE_THRESHOLD,
CONF_TOUCH_THRESHOLD,
THRESHOLDS_PUBLISHER,
TOUCHED,
MPR121Component,
mpr121_ns,
)
DEPENDENCIES = ["mpr121"]
MPR121BinarySensor = mpr121_ns.class_("MPR121BinarySensor", binary_sensor.BinarySensor)
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(MPR121BinarySensor).extend(
{
cv.GenerateID(CONF_MPR121_ID): cv.use_id(MPR121Component),
cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=11),
@@ -29,26 +25,13 @@ CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
)
def _final_validate(config: ConfigType) -> None:
"""Take the thresholds the channel does not set from its hub."""
hub = fv.get_declaring_config(config[CONF_MPR121_ID])
for key in (CONF_TOUCH_THRESHOLD, CONF_RELEASE_THRESHOLD):
config.setdefault(key, hub[key])
FINAL_VALIDATE_SCHEMA = _final_validate
async def to_code(config: ConfigType) -> None:
var = await binary_sensor.new_binary_sensor(config)
hub = await cg.get_variable(config[CONF_MPR121_ID])
channel = config[CONF_CHANNEL]
THRESHOLDS_PUBLISHER.add(
hub,
hub.write_thresholds(
channel, config[CONF_TOUCH_THRESHOLD], config[CONF_RELEASE_THRESHOLD]
),
)
CHANNELS_PUBLISHER.add(
hub, mpr121_ns.publish_channel(parent_ref(var), TOUCHED, channel)
)
cg.add(var.set_channel(config[CONF_CHANNEL]))
await cg.register_parented(var, hub)
cg.add_optional(var.set_touch_threshold, config.get(CONF_TOUCH_THRESHOLD))
cg.add_optional(var.set_release_threshold, config.get(CONF_RELEASE_THRESHOLD))
cg.add(hub.register_channel(var))
@@ -0,0 +1,18 @@
#include "mpr121_binary_sensor.h"
namespace esphome::mpr121 {
void MPR121BinarySensor::setup() {
uint8_t touch_threshold = this->touch_threshold_.value_or(this->parent_->get_touch_threshold());
this->parent_->write_byte(MPR121_TOUCHTH_0 + 2 * this->channel_, touch_threshold);
uint8_t release_threshold = this->release_threshold_.value_or(this->parent_->get_release_threshold());
this->parent_->write_byte(MPR121_RELEASETH_0 + 2 * this->channel_, release_threshold);
}
void MPR121BinarySensor::process(uint16_t data) {
bool new_state = data & (1 << this->channel_);
this->publish_state(new_state);
}
} // namespace esphome::mpr121
@@ -0,0 +1,26 @@
#pragma once
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "../mpr121.h"
namespace esphome::mpr121 {
class MPR121BinarySensor final : public binary_sensor::BinarySensor,
public MPR121Channel,
public Parented<MPR121Component> {
public:
void set_channel(uint8_t channel) { this->channel_ = channel; }
void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; };
void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; };
void setup() override;
void process(uint16_t data) override;
protected:
uint8_t channel_{0};
optional<uint8_t> touch_threshold_{};
optional<uint8_t> release_threshold_{};
};
} // namespace esphome::mpr121
+9 -18
View File
@@ -17,10 +17,10 @@ void MPR121Component::setup() {
this->set_timeout(100, [this]() {
if (!this->setup_check(this->write_byte(MPR121_ECR, 0x0)))
return;
#ifdef USE_MPR121_CHANNEL_PUBLISHERS
if (this->thresholds_publisher_ != nullptr)
this->thresholds_publisher_();
#endif
// set touch sensitivity for all 12 channels
for (auto *channel : this->channels_) {
channel->setup();
}
this->write_byte(MPR121_MHDR, 0x01);
this->write_byte(MPR121_NHDR, 0x01);
this->write_byte(MPR121_NCLR, 0x0E);
@@ -65,25 +65,16 @@ void MPR121Component::set_release_debounce(uint8_t debounce) {
this->debounce_ |= mask;
};
#ifdef USE_MPR121_CHANNEL_PUBLISHERS
void MPR121Component::write_thresholds(uint8_t channel, uint8_t touch, uint8_t release) {
this->write_byte(MPR121_TOUCHTH_0 + 2 * channel, touch);
this->write_byte(MPR121_RELEASETH_0 + 2 * channel, release);
}
#endif
void MPR121Component::dump_config() {
ESP_LOGCONFIG(TAG, "MPR121:");
LOG_I2C_DEVICE(this);
}
void MPR121Component::loop() {
#ifdef USE_MPR121_CHANNEL_PUBLISHERS
if (this->channels_publisher_ != nullptr) {
uint16_t val = 0;
this->read_byte_16_le(MPR121_TOUCHSTATUS_L, &val);
this->channels_publisher_(val);
}
#endif
uint16_t val = 0;
this->read_byte_16_le(MPR121_TOUCHSTATUS_L, &val);
for (auto *channel : this->channels_)
channel->process(val);
this->read_byte(MPR121_GPIODATA, &this->gpio_input_);
}
+15 -10
View File
@@ -3,11 +3,12 @@
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "esphome/components/i2c/i2c.h"
#include <vector>
namespace esphome::mpr121 {
enum {
@@ -51,20 +52,21 @@ enum {
MPR121_SOFTRESET = 0x80,
};
// A template on the sensor type keeps binary_sensor.h out of this hub header
template<typename T> inline void publish_channel(T *sensor, uint16_t touched, uint8_t channel) {
sensor->publish_state((touched >> channel) & 1);
}
class MPR121Channel {
public:
virtual void setup() = 0;
virtual void process(uint16_t data) = 0;
};
class MPR121Component final : public Component, public i2c::I2CDevice {
public:
#ifdef USE_MPR121_CHANNEL_PUBLISHERS
HUB_PUBLISHER(thresholds)
HUB_PUBLISHER(channels, uint16_t)
void write_thresholds(uint8_t channel, uint8_t touch, uint8_t release);
#endif
void register_channel(MPR121Channel *channel) { this->channels_.push_back(channel); }
void set_touch_debounce(uint8_t debounce);
void set_release_debounce(uint8_t debounce);
void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; };
void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; };
uint8_t get_touch_threshold() const { return this->touch_threshold_; };
uint8_t get_release_threshold() const { return this->release_threshold_; };
void setup() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::IO; }
@@ -78,7 +80,10 @@ class MPR121Component final : public Component, public i2c::I2CDevice {
void pin_mode(uint8_t pin, gpio::Flags flags);
protected:
std::vector<MPR121Channel *> channels_{};
uint8_t debounce_{0};
uint8_t touch_threshold_{};
uint8_t release_threshold_{};
uint8_t max_touch_channel_{3};
bool flush_gpio_();
-9
View File
@@ -13,15 +13,6 @@ MULTI_CONF = True
rdm6300_ns = cg.esphome_ns.namespace("rdm6300")
RDM6300Component = rdm6300_ns.class_("RDM6300Component", cg.Component, uart.UARTDevice)
# Publishes the card binary sensors for each tag read; returns whether one matched
CARDS_PUBLISHER = cg.HubFunction(
"cards",
cg.bool_,
[(cg.uint32, "tag")],
define="USE_RDM6300_CARDS_PUBLISHER",
)
TAG = CARDS_PUBLISHER.param("tag")
_AUTOMATION_LISTS = (
automation.AutomationList(CONF_ON_TAG, "RDM6300_ON_TAG_COUNT", [(cg.uint32, "x")]),
)
+8 -8
View File
@@ -1,19 +1,19 @@
from esphome.automation import parent_ref
import esphome.codegen as cg
from esphome.components import binary_sensor, rdm6300
import esphome.config_validation as cv
from esphome.const import CONF_UID
from esphome.types import ConfigType
from . import CARDS_PUBLISHER, TAG, rdm6300_ns
from . import rdm6300_ns
DEPENDENCIES = ["rdm6300"]
CONF_RDM6300_ID = "rdm6300_id"
RDM6300BinarySensor = rdm6300_ns.class_(
"RDM6300BinarySensor", binary_sensor.BinarySensor
)
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(
binary_sensor.BinarySensorInitiallyOff
).extend(
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(RDM6300BinarySensor).extend(
{
cv.GenerateID(CONF_RDM6300_ID): cv.use_id(rdm6300.RDM6300Component),
cv.Required(CONF_UID): cv.uint32_t,
@@ -23,7 +23,7 @@ CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(
async def to_code(config: ConfigType) -> None:
var = await binary_sensor.new_binary_sensor(config)
hub = await cg.get_variable(config[CONF_RDM6300_ID])
CARDS_PUBLISHER.add(
hub, rdm6300_ns.publish_card(parent_ref(var), TAG, config[CONF_UID])
)
cg.add(hub.register_card(var))
cg.add(var.set_id(config[CONF_UID]))
+5 -4
View File
@@ -48,10 +48,11 @@ void rdm6300::RDM6300Component::loop() {
this->status_clear_warning();
const uint32_t result = encode_uint32(this->buffer_[1], this->buffer_[2], this->buffer_[3], this->buffer_[4]);
bool report = result != last_id_;
#ifdef USE_RDM6300_CARDS_PUBLISHER
if (this->cards_publisher_ != nullptr && this->cards_publisher_(result))
report = false;
#endif
for (auto *card : this->cards_) {
if (card->process(result)) {
report = false;
}
}
#ifdef RDM6300_ON_TAG_COUNT
this->tag_automations_.trigger(result);
#endif
+23 -14
View File
@@ -2,31 +2,21 @@
#include "esphome/core/component.h"
#include "esphome/core/automation.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/uart/uart.h"
#include <cinttypes>
#include <vector>
namespace esphome::rdm6300 {
// A template on the sensor type keeps binary_sensor.h out of this hub header
template<typename T> inline bool publish_card(T *sensor, uint32_t tag, uint32_t card) {
if (tag != card)
return false;
sensor->publish_state(true);
yield();
sensor->publish_state(false);
return true;
}
class RDM6300BinarySensor;
class RDM6300Component final : public Component, public uart::UARTDevice {
public:
void loop() override;
#ifdef USE_RDM6300_CARDS_PUBLISHER
HUB_PUBLISHER_RETURNING(bool, cards, uint32_t)
#endif
void register_card(RDM6300BinarySensor *obj) { this->cards_.push_back(obj); }
#ifdef RDM6300_ON_TAG_COUNT
void add_on_tag_automation(Automation<uint32_t> *automation) { this->tag_automations_.add(automation); }
#endif
@@ -34,10 +24,29 @@ class RDM6300Component final : public Component, public uart::UARTDevice {
protected:
int8_t read_state_{-1};
uint8_t buffer_[6]{};
std::vector<RDM6300BinarySensor *> cards_;
#ifdef RDM6300_ON_TAG_COUNT
AutomationList<RDM6300_ON_TAG_COUNT, uint32_t> tag_automations_;
#endif
uint32_t last_id_{0};
};
class RDM6300BinarySensor final : public binary_sensor::BinarySensorInitiallyOff {
public:
void set_id(uint32_t id) { id_ = id; }
bool process(uint32_t id) {
if (this->id_ == id) {
this->publish_state(true);
yield();
this->publish_state(false);
return true;
}
return false;
}
protected:
uint32_t id_;
};
} // namespace esphome::rdm6300
-9
View File
@@ -30,15 +30,6 @@ DOMAIN = "sx1509"
MULTI_CONF = True
sx1509_ns = cg.esphome_ns.namespace("sx1509")
# Publishes the keypad binary sensors from the key data read on each scan
KEYPAD_PUBLISHER = cg.HubFunction(
"keypad",
cg.void,
[(cg.uint16, "key_data")],
define="USE_SX1509_KEYPAD_PUBLISHER",
)
KEY_DATA = KEYPAD_PUBLISHER.param("key_data")
LedDriverFrequency = sx1509_ns.enum("LedDriverFrequency")
# The PWM frequency is shared by all output pins; the values are nominal (see sx1509.h).
@@ -1,16 +1,16 @@
from esphome.automation import parent_ref
import esphome.codegen as cg
from esphome.components import binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_COL, CONF_ROW
from esphome.core import HexInt
from esphome.types import ConfigType
from .. import CONF_SX1509_ID, KEY_DATA, KEYPAD_PUBLISHER, SX1509Component, sx1509_ns
from .. import CONF_SX1509_ID, SX1509Component, sx1509_ns
DEPENDENCIES = ["sx1509"]
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
SX1509BinarySensor = sx1509_ns.class_("SX1509BinarySensor", binary_sensor.BinarySensor)
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(SX1509BinarySensor).extend(
{
cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component),
cv.Required(CONF_ROW): cv.int_range(min=0, max=7),
@@ -22,6 +22,6 @@ CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
async def to_code(config: ConfigType) -> None:
var = await binary_sensor.new_binary_sensor(config)
hub = await cg.get_variable(config[CONF_SX1509_ID])
# The key data has the column bit in the high byte and the row bit in the low byte
key = HexInt((1 << (config[CONF_COL] + 8)) | (1 << config[CONF_ROW]))
KEYPAD_PUBLISHER.add(hub, sx1509_ns.publish_key(parent_ref(var), KEY_DATA, key))
cg.add(var.set_row_col(config[CONF_ROW], config[CONF_COL]))
cg.add(hub.register_keypad_binary_sensor(var))
@@ -0,0 +1,17 @@
#pragma once
#include "esphome/components/sx1509/sx1509.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
namespace esphome::sx1509 {
class SX1509BinarySensor final : public sx1509::SX1509Processor, public binary_sensor::BinarySensor {
public:
void set_row_col(uint8_t row, uint8_t col) { this->key_ = (1 << (col + 8)) | (1 << row); }
void process(uint16_t data) override { this->publish_state(static_cast<bool>(data == key_)); }
protected:
uint16_t key_{0};
};
} // namespace esphome::sx1509
+2 -4
View File
@@ -40,10 +40,8 @@ void SX1509Component::loop() {
return;
this->last_loop_timestamp_ = millis();
uint16_t key_data = this->read_key_data();
#ifdef USE_SX1509_KEYPAD_PUBLISHER
if (this->keypad_publisher_ != nullptr)
this->keypad_publisher_(key_data);
#endif
for (auto *binary_sensor : this->keypad_binary_sensors_)
binary_sensor->process(key_data);
if (this->keys_ == nullptr)
return;
if (key_data == 0) {
+11 -8
View File
@@ -6,10 +6,11 @@
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "sx1509_registers.h"
#include <vector>
namespace esphome::sx1509 {
// These are used for clock config:
@@ -35,10 +36,11 @@ const uint8_t REG_I_ON[16] = {REG_I_ON_0, REG_I_ON_1, REG_I_ON_2, REG_I_ON_3,
REG_I_ON_6, REG_I_ON_7, REG_I_ON_8, REG_I_ON_9, REG_I_ON_10, REG_I_ON_11,
REG_I_ON_12, REG_I_ON_13, REG_I_ON_14, REG_I_ON_15};
// A template on the sensor type keeps binary_sensor.h out of this hub header
template<typename T> inline void publish_key(T *sensor, uint16_t key_data, uint16_t key) {
sensor->publish_state(key_data == key);
}
// for all components that implement the process(uint16_t data )
class SX1509Processor {
public:
virtual void process(uint16_t data) {};
};
class SX1509Component final : public Component,
public i2c::I2CDevice,
@@ -65,9 +67,9 @@ class SX1509Component final : public Component,
void set_sleep_time(uint16_t sleep_time) { this->sleep_time_ = sleep_time; };
void set_scan_time(uint8_t scan_time) { this->scan_time_ = scan_time; };
void set_debounce_time(uint8_t debounce_time = 1) { this->debounce_time_ = debounce_time; };
#ifdef USE_SX1509_KEYPAD_PUBLISHER
HUB_PUBLISHER(keypad, uint16_t)
#endif
void register_keypad_binary_sensor(SX1509Processor *binary_sensor) {
this->keypad_binary_sensors_.push_back(binary_sensor);
}
#ifdef SX1509_ON_KEY_COUNT
void add_on_key_automation(Automation<uint8_t> *automation) { this->key_automations_.add(automation); }
#endif
@@ -93,6 +95,7 @@ class SX1509Component final : public Component,
uint8_t scan_time_ = 1;
uint8_t debounce_time_ = 1;
uint8_t last_key_ = 0;
std::vector<SX1509Processor *> keypad_binary_sensors_;
#ifdef SX1509_ON_KEY_COUNT
AutomationList<SX1509_ON_KEY_COUNT, uint8_t> key_automations_;
#endif
@@ -12,15 +12,6 @@ ttp229_bsf_ns = cg.esphome_ns.namespace("ttp229_bsf")
TTP229BSFComponent = ttp229_bsf_ns.class_("TTP229BSFComponent", cg.Component)
# Publishes the channel binary sensors from the touch status read on each loop
CHANNELS_PUBLISHER = cg.HubFunction(
"channels",
cg.void,
[(cg.uint16, "touched")],
define="USE_TTP229_BSF_CHANNELS_PUBLISHER",
)
TOUCHED = CHANNELS_PUBLISHER.param("touched")
MULTI_CONF = True
CONFIG_SCHEMA = cv.Schema(
{
+6 -13
View File
@@ -1,21 +1,15 @@
from esphome.automation import parent_ref
import esphome.codegen as cg
from esphome.components import binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL
from esphome.types import ConfigType
from . import (
CHANNELS_PUBLISHER,
CONF_TTP229_ID,
TOUCHED,
TTP229BSFComponent,
ttp229_bsf_ns,
)
from . import CONF_TTP229_ID, TTP229BSFComponent, ttp229_bsf_ns
DEPENDENCIES = ["ttp229_bsf"]
TTP229BSFChannel = ttp229_bsf_ns.class_("TTP229BSFChannel", binary_sensor.BinarySensor)
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(TTP229BSFChannel).extend(
{
cv.GenerateID(CONF_TTP229_ID): cv.use_id(TTP229BSFComponent),
cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15),
@@ -25,8 +19,7 @@ CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
async def to_code(config: ConfigType) -> None:
var = await binary_sensor.new_binary_sensor(config)
cg.add(var.set_channel(config[CONF_CHANNEL]))
hub = await cg.get_variable(config[CONF_TTP229_ID])
CHANNELS_PUBLISHER.add(
hub,
ttp229_bsf_ns.publish_channel(parent_ref(var), TOUCHED, config[CONF_CHANNEL]),
)
cg.add(hub.register_channel(var))
+16 -12
View File
@@ -2,22 +2,26 @@
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include <vector>
namespace esphome::ttp229_bsf {
// A template on the sensor type keeps binary_sensor.h out of this hub header
template<typename T> inline void publish_channel(T *sensor, uint16_t touched, uint8_t channel) {
sensor->publish_state((touched >> channel) & 1);
}
class TTP229BSFChannel final : public binary_sensor::BinarySensor {
public:
void set_channel(uint8_t channel) { channel_ = channel; }
void process(uint16_t data) { this->publish_state(data & (1 << this->channel_)); }
protected:
uint8_t channel_;
};
class TTP229BSFComponent final : public Component {
public:
void set_sdo_pin(GPIOPin *sdo_pin) { sdo_pin_ = sdo_pin; }
void set_scl_pin(GPIOPin *scl_pin) { scl_pin_ = scl_pin; }
#ifdef USE_TTP229_BSF_CHANNELS_PUBLISHER
HUB_PUBLISHER(channels, uint16_t)
#endif
void register_channel(TTP229BSFChannel *channel) { this->channels_.push_back(channel); }
void setup() override;
void dump_config() override;
void loop() override {
@@ -35,15 +39,15 @@ class TTP229BSFComponent final : public Component {
touched |= uint16_t(bitval) << i;
}
#ifdef USE_TTP229_BSF_CHANNELS_PUBLISHER
if (this->channels_publisher_ != nullptr)
this->channels_publisher_(touched);
#endif
for (auto *channel : this->channels_) {
channel->process(touched);
}
}
protected:
GPIOPin *sdo_pin_;
GPIOPin *scl_pin_;
std::vector<TTP229BSFChannel *> channels_{};
};
} // namespace esphome::ttp229_bsf
@@ -14,15 +14,6 @@ TTP229LSFComponent = ttp229_lsf_ns.class_(
"TTP229LSFComponent", cg.Component, i2c.I2CDevice
)
# Publishes the channel binary sensors from the touch status read on each loop
CHANNELS_PUBLISHER = cg.HubFunction(
"channels",
cg.void,
[(cg.uint16, "touched")],
define="USE_TTP229_LSF_CHANNELS_PUBLISHER",
)
TOUCHED = CHANNELS_PUBLISHER.param("touched")
MULTI_CONF = True
CONFIG_SCHEMA = (
cv.Schema(
+6 -13
View File
@@ -1,21 +1,15 @@
from esphome.automation import parent_ref
import esphome.codegen as cg
from esphome.components import binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL
from esphome.types import ConfigType
from . import (
CHANNELS_PUBLISHER,
CONF_TTP229_ID,
TOUCHED,
TTP229LSFComponent,
ttp229_lsf_ns,
)
from . import CONF_TTP229_ID, TTP229LSFComponent, ttp229_lsf_ns
DEPENDENCIES = ["ttp229_lsf"]
TTP229Channel = ttp229_lsf_ns.class_("TTP229Channel", binary_sensor.BinarySensor)
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(TTP229Channel).extend(
{
cv.GenerateID(CONF_TTP229_ID): cv.use_id(TTP229LSFComponent),
cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15),
@@ -25,8 +19,7 @@ CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
async def to_code(config: ConfigType) -> None:
var = await binary_sensor.new_binary_sensor(config)
cg.add(var.set_channel(config[CONF_CHANNEL]))
hub = await cg.get_variable(config[CONF_TTP229_ID])
CHANNELS_PUBLISHER.add(
hub,
ttp229_lsf_ns.publish_channel(parent_ref(var), TOUCHED, config[CONF_CHANNEL]),
)
cg.add(hub.register_channel(var))
+3 -4
View File
@@ -20,10 +20,9 @@ void TTP229LSFComponent::loop() {
return;
touched = i2c::i2ctohs(touched);
touched = reverse_bits(touched);
#ifdef USE_TTP229_LSF_CHANNELS_PUBLISHER
if (this->channels_publisher_ != nullptr)
this->channels_publisher_(touched);
#endif
for (auto *channel : this->channels_) {
channel->process(touched);
}
}
} // namespace esphome::ttp229_lsf
+15 -8
View File
@@ -1,24 +1,31 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/i2c/i2c.h"
#include <vector>
namespace esphome::ttp229_lsf {
// A template on the sensor type keeps binary_sensor.h out of this hub header
template<typename T> inline void publish_channel(T *sensor, uint16_t touched, uint8_t channel) {
sensor->publish_state((touched >> channel) & 1);
}
class TTP229Channel final : public binary_sensor::BinarySensor {
public:
void set_channel(uint8_t channel) { channel_ = channel; }
void process(uint16_t data) { this->publish_state(data & (1 << this->channel_)); }
protected:
uint8_t channel_;
};
class TTP229LSFComponent final : public Component, public i2c::I2CDevice {
public:
#ifdef USE_TTP229_LSF_CHANNELS_PUBLISHER
HUB_PUBLISHER(channels, uint16_t)
#endif
void register_channel(TTP229Channel *channel) { this->channels_.push_back(channel); }
void setup() override;
void dump_config() override;
void loop() override;
protected:
std::vector<TTP229Channel *> channels_{};
};
} // namespace esphome::ttp229_lsf
-6
View File
@@ -70,7 +70,6 @@
#define USE_BUTTON
#define USE_CAMERA
#define USE_CANBUS_FD
#define USE_CAP1188_CHANNELS_PUBLISHER
#define USE_CC1101_LONG_PACKET
#define USE_CLIMATE
#define USE_CLIMATE_VISUAL_OVERRIDES
@@ -225,7 +224,6 @@
#define MODBUS_ON_REQUEST_COUNT 1
#define MODBUS_ON_RESPONSE_COUNT 1
#define USE_MOTION_DATA_PUBLISHER
#define USE_MPR121_CHANNEL_PUBLISHERS
#define NFC_TAG_LISTENER_COUNT 1
#define PN532_BINARY_SENSOR_COUNT 1
#define PN532_ON_TAG_REMOVED_TRIGGER_COUNT 1
@@ -239,7 +237,6 @@
#define RC522_ON_TAG_COUNT 1
#define RC522_ON_TAG_REMOVED_COUNT 1
#define RDM6300_ON_TAG_COUNT 1
#define USE_RDM6300_CARDS_PUBLISHER
#define REMOTE_BASE_DUMPER_COUNT 1
#define REMOTE_BASE_LISTENER_COUNT 1
#define SX1509_ON_KEY_COUNT 1
@@ -365,7 +362,6 @@
#define USE_STATUS_SENSOR
#define USE_SWITCH
#define USE_SWITCH_STORAGE
#define USE_SX1509_KEYPAD_PUBLISHER
#define USE_SY6970_DATA_PUBLISHER
#define USE_TCA8418_KEY_PUBLISHER
#define USE_TEXT
@@ -381,8 +377,6 @@
#define USE_TMP102_TEXT_SENSOR
#define USE_TOSHIBA_RAS_25J2KVSG_ND
#define USE_TOUCHSCREEN
#define USE_TTP229_BSF_CHANNELS_PUBLISHER
#define USE_TTP229_LSF_CHANNELS_PUBLISHER
#define USE_UART_DEBUGGER
#define USE_UART_WAKE_LOOP_ON_RX
#define USE_UFM01_CLEAR_ACCUMULATED_FLOW_ACTION
+3
View File
@@ -25,6 +25,8 @@ CORE_BENCHMARKS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "core"
# allow benchmarks to compile on the host platform.
STUBS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "stubs"
HELPERS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "helpers"
BUILD_FLAGS = [
"-Os", # match firmware optimization level (detects inlining regressions)
"-g", # debug symbols for profiling
@@ -32,6 +34,7 @@ BUILD_FLAGS = [
"-fdata-sections", # required for dead-code stripping with -Os
"-DUSE_BENCHMARK", # disable WarnIfComponentBlockingGuard in finish()
f"-I{STUBS_DIR}", # stub headers for ESP32-only components
f"-I{HELPERS_DIR}", # shared test doubles such as fake_uart.h
]
@@ -0,0 +1,76 @@
#include <benchmark/benchmark.h>
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/ld2450/ld2450.h"
#include "esphome/components/sensor/sensor.h"
#include "fake_uart.h"
namespace esphome::ld2450::benchmarks {
using esphome::benchmarks::FakeUART;
// Inner iteration count to amortize CodSpeed instrumentation overhead.
static constexpr int kInnerIterations = 2000;
static constexpr size_t FRAME_SIZE = 30;
// Periodic frames with one moving target at two positions
static constexpr uint8_t FRAME_A[FRAME_SIZE] = {0xAA, 0xFF, 0x03, 0x00, 0x0E, 0x03, 0xB1, 0x86, 0x10, 0x00,
0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xCC};
static constexpr uint8_t FRAME_B[FRAME_SIZE] = {0xAA, 0xFF, 0x03, 0x00, 0x2A, 0x03, 0xC8, 0x86, 0x10, 0x00,
0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xCC};
// --- loop() parsing one periodic frame, no entities attached ---
static void LD2450_PeriodicFrame(benchmark::State &state) {
FakeUART uart;
LD2450Component radar;
radar.set_uart_parent(&uart);
radar.set_link_timeout(60000);
// Bring the link up outside the timed loop
uart.load(FRAME_B, FRAME_SIZE);
radar.loop();
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
uart.load(FRAME_A, FRAME_SIZE);
radar.loop();
}
benchmark::DoNotOptimize(uart.available());
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(LD2450_PeriodicFrame);
// --- loop() parsing a moving target and publishing its sensors ---
static void LD2450_PeriodicFrameSensors(benchmark::State &state) {
FakeUART uart;
LD2450Component radar;
radar.set_uart_parent(&uart);
radar.set_link_timeout(60000);
sensor::Sensor x, y, speed, distance, angle, count;
binary_sensor::BinarySensor presence;
radar.set_move_x_sensor(0, &x);
radar.set_move_y_sensor(0, &y);
radar.set_move_speed_sensor(0, &speed);
radar.set_move_distance_sensor(0, &distance);
radar.set_move_angle_sensor(0, &angle);
radar.set_target_count_sensor(&count);
radar.set_target_binary_sensor(&presence);
uart.load(FRAME_B, FRAME_SIZE);
radar.loop();
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
uart.load((i & 1) ? FRAME_B : FRAME_A, FRAME_SIZE);
radar.loop();
}
benchmark::DoNotOptimize(x.state);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(LD2450_PeriodicFrameSensors);
} // namespace esphome::ld2450::benchmarks
@@ -0,0 +1,2 @@
sensor:
binary_sensor:
@@ -0,0 +1,63 @@
#include <benchmark/benchmark.h>
#include "esphome/components/modbus/modbus.h"
#include "fake_uart.h"
namespace esphome::modbus::benchmarks {
using esphome::benchmarks::FakeUART;
// Inner iteration count to amortize CodSpeed instrumentation overhead.
static constexpr int kInnerIterations = 2000;
static constexpr uint8_t ADDRESS = 1;
static constexpr uint16_t REGISTER_COUNT = 10;
// Read 10 holding registers from address 0, as an energy meter poll does
static constexpr uint8_t REQUEST_PDU[] = {0x03, 0x00, 0x00, 0x00, REGISTER_COUNT};
// Function 3, byte count 20, 10 registers
static constexpr uint8_t RESPONSE_PDU[] = {0x03, 0x14, 0x09, 0x1F, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x13,
0x88, 0x00, 0x32, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x64, 0x12, 0x34};
class SumDevice : public ModbusClientDevice {
public:
using ModbusClientDevice::ModbusClientDevice;
void on_read_holding_registers(uint16_t start_address, std::span<const uint16_t> registers,
ResponseStatus status) override {
for (uint16_t value : registers)
this->sum += value;
}
uint32_t sum{0};
};
class NoDelayHub : public ModbusClientHub {
protected:
// No wait before a send, so every loop() can send the next poll
int32_t tx_delay_remaining() override { return 0; }
};
// --- One continuous poll cycle per loop(): receive, decode and resend ---
static void Modbus_ReadHoldingPollCycle(benchmark::State &state) {
const ModbusFrame response(ADDRESS, RESPONSE_PDU, sizeof(RESPONSE_PDU));
FakeUART uart;
uart.set_baud_rate(9600);
NoDelayHub hub;
hub.set_uart_parent(&uart);
hub.setup();
SumDevice device(&hub, ADDRESS);
hub.queue_pdu(ADDRESS, REQUEST_PDU, &device, {.continuous = true});
// The first loop() sends the poll; every send rewinds the response, so the device answers each one
hub.loop();
uart.load(response.data.data(), response.size());
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
hub.loop();
}
benchmark::DoNotOptimize(device.sum);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(Modbus_ReadHoldingPollCycle);
} // namespace esphome::modbus::benchmarks
@@ -0,0 +1,56 @@
#include <benchmark/benchmark.h>
#include "esphome/components/uart/uart.h"
#include "fake_uart.h"
namespace esphome::uart::benchmarks {
using esphome::benchmarks::FakeUART;
// Inner iteration count to amortize CodSpeed instrumentation overhead.
static constexpr int kInnerIterations = 2000;
// One second of a GPS module's NMEA output
static constexpr char NMEA_BURST[] = "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47\r\n"
"$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A\r\n"
"$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39\r\n"
"$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75\r\n"
"$GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48\r\n";
// --- read_available(): drain a whole NMEA burst through a byte-sum callback ---
static void UART_ReadAvailable_NmeaBurst(benchmark::State &state) {
FakeUART uart;
UARTDevice dev(&uart);
uint32_t sum = 0;
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
uart.load(reinterpret_cast<const uint8_t *>(NMEA_BURST), sizeof(NMEA_BURST) - 1);
dev.read_available([&](uint8_t b) { sum += b; });
}
benchmark::DoNotOptimize(sum);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(UART_ReadAvailable_NmeaBurst);
// --- discard_available(): drop a 256 byte backlog, two virtual calls per byte ---
static void UART_DiscardAvailable(benchmark::State &state) {
uint8_t backlog[256]{};
FakeUART uart;
UARTDevice dev(&uart);
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
uart.load(backlog, sizeof(backlog));
dev.discard_available();
}
benchmark::DoNotOptimize(uart.available());
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(UART_DiscardAvailable);
} // namespace esphome::uart::benchmarks
@@ -0,0 +1,96 @@
#include <benchmark/benchmark.h>
#include "esphome/core/frame_reader.h"
#include "esphome/core/helpers.h"
#include "esphome/core/line_reader.h"
namespace esphome::benchmarks {
// Inner iteration count to amortize CodSpeed instrumentation overhead.
static constexpr int kInnerIterations = 2000;
static constexpr char NMEA_GGA[] = "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47\r\n";
// A 30 byte frame with a 4 byte header and a 2 byte tail
static constexpr uint8_t FRAME_30[30] = {0xAA, 0xFF, 0x03, 0x00, 0x0E, 0x03, 0xB1, 0x86, 0x10, 0x00,
0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xCC};
// Four A02YYUW frames among noise; the doubled 0xFF fails the checksum and resyncs onto the next frame
static constexpr uint8_t ULTRASONIC_NOISY[] = {0x12, 0xFF, 0x07, 0xA1, 0xA7, 0x34, 0xFF, 0xFF, 0x07, 0xA1, 0xA7,
0x00, 0xFF, 0x07, 0xA1, 0xA7, 0x56, 0xFF, 0x07, 0xA1, 0xA7};
// --- LineReader: one GGA sentence fed byte by byte ---
static void LineReader_NmeaLine(benchmark::State &state) {
LineReader<96> reader;
const auto *bytes = reinterpret_cast<const uint8_t *>(NMEA_GGA);
uint32_t lines = 0;
for (auto _ : state) {
benchmark::DoNotOptimize(bytes);
for (int i = 0; i < kInnerIterations; i++) {
for (size_t j = 0; j < sizeof(NMEA_GGA) - 1; j++) {
char *line = reader.feed(bytes[j]);
if (line == nullptr)
continue;
// Keeps the line copy and its NUL write
benchmark::DoNotOptimize(line);
lines++;
}
}
benchmark::DoNotOptimize(lines);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(LineReader_NmeaLine);
// --- FrameReader: a 30 byte frame behind a 4 byte header ---
static void FrameReader_30ByteFrame(benchmark::State &state) {
FrameReader<sizeof(FRAME_30), 0xAA, 0xFF, 0x03, 0x00> reader;
const uint8_t *bytes = FRAME_30;
uint32_t frames = 0;
for (auto _ : state) {
benchmark::DoNotOptimize(bytes);
for (int i = 0; i < kInnerIterations; i++) {
for (size_t j = 0; j < sizeof(FRAME_30); j++) {
if (reader.feed(bytes[j]) != nullptr)
frames++;
}
}
benchmark::DoNotOptimize(frames);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(FrameReader_30ByteFrame);
// --- FrameReader: 4 byte checksummed frames, skipping noise and resyncing on a bad checksum ---
static void FrameReader_UltrasonicNoisy(benchmark::State &state) {
FrameReader<4, 0xFF> reader;
const uint8_t *bytes = ULTRASONIC_NOISY;
uint32_t frames = 0;
for (auto _ : state) {
benchmark::DoNotOptimize(bytes);
for (int i = 0; i < kInnerIterations; i++) {
for (size_t j = 0; j < sizeof(ULTRASONIC_NOISY); j++) {
const uint8_t *frame = reader.feed(bytes[j]);
if (frame == nullptr)
continue;
if (frame[3] == sum_bytes(frame, 3)) {
frames++;
} else {
reader.resync();
}
}
}
benchmark::DoNotOptimize(frames);
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(FrameReader_UltrasonicNoisy);
} // namespace esphome::benchmarks
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include <cstdint>
#include <cstring>
#include "esphome/components/uart/uart_component.h"
namespace esphome::benchmarks {
// Serves a fixed byte stream as received data. Every write rewinds it, so the stream answers each request.
class FakeUART : public uart::UARTComponent {
public:
void load(const uint8_t *data, size_t len) {
this->data_ = data;
this->len_ = len;
this->pos_ = 0;
}
void write_array(const uint8_t *data, size_t len) override { this->pos_ = 0; }
bool peek_byte(uint8_t *data) override {
if (this->pos_ >= this->len_)
return false;
*data = this->data_[this->pos_];
return true;
}
bool read_array(uint8_t *data, size_t len) override {
if (len > this->len_ - this->pos_)
return false;
std::memcpy(data, this->data_ + this->pos_, len);
this->pos_ += len;
return true;
}
size_t available() override { return this->len_ - this->pos_; }
uart::UARTFlushResult flush() override { return uart::UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS; }
void check_logger_conflict() override {}
protected:
const uint8_t *data_{nullptr};
size_t len_{0};
size_t pos_{0};
};
} // namespace esphome::benchmarks
Whitespace-only changes.
@@ -1,24 +0,0 @@
esphome:
name: test
esp32:
board: esp32dev
i2c:
sda: GPIO21
scl: GPIO22
cap1188:
- id: hub
- id: idle_hub
address: 0x28
binary_sensor:
- platform: cap1188
cap1188_id: hub
id: key0
channel: 0
- platform: cap1188
cap1188_id: hub
id: key7
channel: 7
@@ -1,21 +0,0 @@
"""Tests for the function that publishes the cap1188 channel binary sensors."""
from collections.abc import Callable
from pathlib import Path
def test_channels_publish_through_hub_function(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("hub_function.yaml"))
assert (
"static void esphome__hub__channels_fn(uint8_t esphome__arg_touched) {\n"
" cap1188::publish_channel(::key0, esphome__arg_touched, 0);\n"
" cap1188::publish_channel(::key7, esphome__arg_touched, 7);\n"
"}"
) in main_cpp
assert "hub->set_channels_publisher(esphome__hub__channels_fn);" in main_cpp
# A hub without channels keeps a null publisher
assert "idle_hub->set_channels_publisher" not in main_cpp
Whitespace-only changes.
@@ -1,27 +0,0 @@
esphome:
name: test
esp32:
board: esp32dev
i2c:
sda: GPIO21
scl: GPIO22
mpr121:
- id: hub
touch_threshold: 0x10
release_threshold: 0x08
- id: idle_hub
address: 0x5B
binary_sensor:
- platform: mpr121
mpr121_id: hub
id: key0
channel: 0
- platform: mpr121
mpr121_id: hub
id: key3
channel: 3
touch_threshold: 0x20
@@ -1,29 +0,0 @@
"""Tests for the function that publishes the mpr121 channel binary sensors."""
from collections.abc import Callable
from pathlib import Path
def test_channels_write_thresholds_and_publish_through_hub_functions(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("hub_function.yaml"))
# A channel without its own thresholds takes the hub's (16 and 8)
assert (
"static void esphome__hub__thresholds_fn() {\n"
" hub->write_thresholds(0, 16, 8);\n"
" hub->write_thresholds(3, 32, 8);\n"
"}"
) in main_cpp
assert (
"static void esphome__hub__channels_fn(uint16_t esphome__arg_touched) {\n"
" mpr121::publish_channel(::key0, esphome__arg_touched, 0);\n"
" mpr121::publish_channel(::key3, esphome__arg_touched, 3);\n"
"}"
) in main_cpp
assert "hub->set_thresholds_publisher(esphome__hub__thresholds_fn);" in main_cpp
assert "hub->set_channels_publisher(esphome__hub__channels_fn);" in main_cpp
assert "idle_hub->set_thresholds_publisher" not in main_cpp
assert "idle_hub->set_channels_publisher" not in main_cpp
Whitespace-only changes.
@@ -1,29 +0,0 @@
esphome:
name: test
esp32:
board: esp32dev
uart:
- id: uart_reader
rx_pin: GPIO16
baud_rate: 9600
- id: uart_idle
rx_pin: GPIO17
baud_rate: 9600
rdm6300:
- id: reader
uart_id: uart_reader
- id: idle_reader
uart_id: uart_idle
binary_sensor:
- platform: rdm6300
rdm6300_id: reader
id: card_a
uid: 7616525
- platform: rdm6300
rdm6300_id: reader
id: card_b
uid: 4294967295
@@ -1,27 +0,0 @@
"""Tests for the function that publishes the rdm6300 card binary sensors."""
from collections.abc import Callable
from pathlib import Path
def test_cards_publish_through_hub_function(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("hub_function.yaml"))
# A bool function: every card is checked, and it returns whether one matched
assert (
"static bool esphome__reader__cards_fn(uint32_t esphome__arg_tag) {\n"
" bool esphome__found = false;\n"
" (esphome__found |= rdm6300::publish_card(::card_a, esphome__arg_tag, 7616525));\n"
" (esphome__found |= rdm6300::publish_card(::card_b, esphome__arg_tag, 4294967295UL));\n"
" return esphome__found;\n"
"}"
) in main_cpp
assert "reader->set_cards_publisher(esphome__reader__cards_fn);" in main_cpp
# Cards start OFF, as before; they only pulse ON when their tag is read
for card in ("card_a", "card_b"):
assert f"new({card}) binary_sensor::BinarySensorInitiallyOff();" in main_cpp
# A reader without cards keeps a null publisher
assert "idle_reader->set_cards_publisher" not in main_cpp
@@ -1,29 +0,0 @@
esphome:
name: test
esp32:
board: esp32dev
i2c:
sda: GPIO21
scl: GPIO22
sx1509:
- id: hub
keypad:
key_rows: 2
key_columns: 2
- id: idle_hub
address: 0x3F
binary_sensor:
- platform: sx1509
sx1509_id: hub
id: key_r0_c0
row: 0
col: 0
- platform: sx1509
sx1509_id: hub
id: key_r1_c1
row: 1
col: 1
@@ -1,21 +0,0 @@
"""Tests for the function that publishes the sx1509 keypad binary sensors."""
from collections.abc import Callable
from pathlib import Path
def test_keypad_publishes_through_hub_function(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("hub_function.yaml"))
# The key data has the column bit in the high byte and the row bit in the low byte
assert (
"static void esphome__hub__keypad_fn(uint16_t esphome__arg_key_data) {\n"
" sx1509::publish_key(::key_r0_c0, esphome__arg_key_data, 0x101);\n"
" sx1509::publish_key(::key_r1_c1, esphome__arg_key_data, 0x202);\n"
"}"
) in main_cpp
assert "hub->set_keypad_publisher(esphome__hub__keypad_fn);" in main_cpp
assert "idle_hub->set_keypad_publisher" not in main_cpp
Whitespace-only changes.
@@ -1,19 +0,0 @@
esphome:
name: test
esp32:
board: esp32dev
ttp229_bsf:
- id: hub
sdo_pin: GPIO16
scl_pin: GPIO17
- id: idle_hub
sdo_pin: GPIO18
scl_pin: GPIO19
binary_sensor:
- platform: ttp229_bsf
ttp229_id: hub
id: key3
channel: 3
@@ -1,19 +0,0 @@
"""Tests for the function that publishes the ttp229_bsf channel binary sensors."""
from collections.abc import Callable
from pathlib import Path
def test_channels_publish_through_hub_function(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("hub_function.yaml"))
assert (
"static void esphome__hub__channels_fn(uint16_t esphome__arg_touched) {\n"
" ttp229_bsf::publish_channel(::key3, esphome__arg_touched, 3);\n"
"}"
) in main_cpp
assert "hub->set_channels_publisher(esphome__hub__channels_fn);" in main_cpp
assert "idle_hub->set_channels_publisher" not in main_cpp
Whitespace-only changes.
@@ -1,24 +0,0 @@
esphome:
name: test
esp32:
board: esp32dev
i2c:
sda: GPIO21
scl: GPIO22
ttp229_lsf:
- id: hub
- id: idle_hub
address: 0x58
binary_sensor:
- platform: ttp229_lsf
ttp229_id: hub
id: key0
channel: 0
- platform: ttp229_lsf
ttp229_id: hub
id: key15
channel: 15
@@ -1,20 +0,0 @@
"""Tests for the function that publishes the ttp229_lsf channel binary sensors."""
from collections.abc import Callable
from pathlib import Path
def test_channels_publish_through_hub_function(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("hub_function.yaml"))
assert (
"static void esphome__hub__channels_fn(uint16_t esphome__arg_touched) {\n"
" ttp229_lsf::publish_channel(::key0, esphome__arg_touched, 0);\n"
" ttp229_lsf::publish_channel(::key15, esphome__arg_touched, 15);\n"
"}"
) in main_cpp
assert "hub->set_channels_publisher(esphome__hub__channels_fn);" in main_cpp
assert "idle_hub->set_channels_publisher" not in main_cpp