mirror of
https://github.com/esphome/esphome.git
synced 2026-10-27 16:32:11 +00:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbecd1cbcb | ||
|
|
a4e7f4c680 | ||
|
|
557ed04f7f | ||
|
|
e08cd5a4f0 | ||
|
|
2c11cfd1fa | ||
|
|
3259e72d9d | ||
|
|
29adc6f7e7 |
No files matched your search
@@ -633,7 +633,14 @@ class SubEntities:
|
||||
elif publish == "after":
|
||||
body = [call, apply_entity.publish]
|
||||
elif publish == "on_success":
|
||||
body = [f"if ({expr}) {{ {apply_entity.publish} }}"]
|
||||
# An esp_err_t or int would convert to bool silently and flip the meaning
|
||||
body = [
|
||||
(
|
||||
f"static_assert(std::is_same_v<decltype({expr}), bool>, "
|
||||
'"publish=\\"on_success\\" needs a hub call that returns bool");'
|
||||
),
|
||||
f"if ({expr}) {{ {apply_entity.publish} }}",
|
||||
]
|
||||
elif publish == "momentary":
|
||||
acknowledge, condition = apply_entity.momentary
|
||||
body = [acknowledge, f"if ({condition}) {{ {call} }}"]
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.types import ConfigType
|
||||
from tests.testing_helpers import ComponentManifestOverride
|
||||
|
||||
|
||||
def override_manifest(manifest: ComponentManifestOverride) -> None:
|
||||
# One empty config entry so to_code runs and compiles the PG/GPO switch path.
|
||||
manifest.multi_conf = False
|
||||
manifest.dependencies = manifest.dependencies + ["i2c", "switch"]
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
cg.add_define("USE_BQ25186_PG_GPO")
|
||||
|
||||
manifest.to_code = to_code
|
||||
@@ -0,0 +1,136 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "esphome/components/bq25186/bq25186.h"
|
||||
#include "esphome/components/bq25186/bq25186_switch.h"
|
||||
|
||||
namespace esphome::bq25186::testing {
|
||||
|
||||
static constexpr uint8_t ADDRESS = 0x6A;
|
||||
static constexpr uint8_t SYS_REG_OTHER_BITS = 0x0F;
|
||||
|
||||
// The chip's registers behind an address pointer that moves on after every byte; writes can be made to fail.
|
||||
class RegisterBus final : public i2c::I2CBus {
|
||||
public:
|
||||
i2c::ErrorCode write_readv(uint8_t address, const uint8_t *data, size_t size, uint8_t *out,
|
||||
size_t out_size) override {
|
||||
EXPECT_EQ(address, ADDRESS);
|
||||
if (size > 1 && this->fail_writes)
|
||||
return i2c::ERROR_NOT_ACKNOWLEDGED;
|
||||
if (size != 0) {
|
||||
this->pointer_ = data[0];
|
||||
for (size_t i = 1; i < size; i++)
|
||||
this->registers[this->next_()] = data[i];
|
||||
}
|
||||
for (size_t i = 0; i < out_size; i++)
|
||||
out[i] = this->registers[this->next_()];
|
||||
return i2c::ERROR_OK;
|
||||
}
|
||||
|
||||
std::array<uint8_t, BQ25186_STATUS_REGISTER_COUNT> registers{};
|
||||
bool fail_writes{false};
|
||||
|
||||
protected:
|
||||
size_t next_() { return this->pointer_++ % this->registers.size(); }
|
||||
|
||||
uint8_t pointer_{0};
|
||||
};
|
||||
|
||||
class BQ25186PgGpoTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
this->bus_.registers[BQ25186_REG_MASK_ID] = 0x01; // the BQ25186 device id
|
||||
this->bus_.registers[BQ25186_REG_SYS_REG] = SYS_REG_OTHER_BITS;
|
||||
this->hub_.set_i2c_bus(&this->bus_);
|
||||
this->hub_.set_i2c_address(ADDRESS);
|
||||
this->switch_.set_parent(&this->hub_);
|
||||
this->switch_.set_restore_mode(switch_::SWITCH_RESTORE_DISABLED);
|
||||
this->hub_.set_pg_gpo_switch(&this->switch_);
|
||||
}
|
||||
|
||||
bool level_() const { return (this->bus_.registers[BQ25186_REG_SYS_REG] & BQ25186_SYS_REG_PG_GPO_LEVEL) != 0; }
|
||||
uint8_t other_bits_() const { return this->bus_.registers[BQ25186_REG_SYS_REG] & ~BQ25186_SYS_REG_PG_GPO_LEVEL; }
|
||||
|
||||
RegisterBus bus_;
|
||||
BQ25186Component hub_;
|
||||
BQ25186PgGpoSwitch switch_;
|
||||
};
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, TurnOnSetsTheLevelAndPublishes) {
|
||||
this->switch_.turn_on();
|
||||
EXPECT_TRUE(this->level_());
|
||||
EXPECT_EQ(this->other_bits_(), SYS_REG_OTHER_BITS);
|
||||
EXPECT_TRUE(this->switch_.has_state());
|
||||
EXPECT_TRUE(this->switch_.state);
|
||||
}
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, TurnOffClearsTheLevelAndPublishes) {
|
||||
this->bus_.registers[BQ25186_REG_SYS_REG] |= BQ25186_SYS_REG_PG_GPO_LEVEL;
|
||||
this->switch_.publish_state(true);
|
||||
this->switch_.turn_off();
|
||||
EXPECT_FALSE(this->level_());
|
||||
EXPECT_EQ(this->other_bits_(), SYS_REG_OTHER_BITS);
|
||||
EXPECT_FALSE(this->switch_.state);
|
||||
}
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, FailedWriteLeavesTheStateUnpublished) {
|
||||
this->bus_.fail_writes = true;
|
||||
this->switch_.turn_on();
|
||||
EXPECT_FALSE(this->level_());
|
||||
EXPECT_FALSE(this->switch_.has_state());
|
||||
}
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, FailedWriteKeepsThePreviousState) {
|
||||
// Start from on, so a reset to the default off state would show
|
||||
this->bus_.registers[BQ25186_REG_SYS_REG] |= BQ25186_SYS_REG_PG_GPO_LEVEL;
|
||||
this->switch_.publish_state(true);
|
||||
this->bus_.fail_writes = true;
|
||||
this->switch_.turn_off();
|
||||
EXPECT_TRUE(this->level_());
|
||||
EXPECT_TRUE(this->switch_.state);
|
||||
}
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, InvertedSwitchDrivesTheOppositeLevel) {
|
||||
this->switch_.set_inverted(true);
|
||||
this->switch_.turn_on();
|
||||
EXPECT_FALSE(this->level_());
|
||||
EXPECT_TRUE(this->switch_.state);
|
||||
this->switch_.turn_off();
|
||||
EXPECT_TRUE(this->level_());
|
||||
EXPECT_FALSE(this->switch_.state);
|
||||
}
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, SetupWritesTheRestoredLevel) {
|
||||
this->switch_.set_restore_mode(switch_::SWITCH_ALWAYS_ON);
|
||||
this->hub_.setup();
|
||||
EXPECT_TRUE(this->level_());
|
||||
EXPECT_NE(this->bus_.registers[BQ25186_REG_VBAT_CTRL] & BQ25186_VBAT_CTRL_PG_MODE, 0);
|
||||
EXPECT_TRUE(this->switch_.state);
|
||||
}
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, SetupWritesTheRestoredLevelInverted) {
|
||||
this->bus_.registers[BQ25186_REG_SYS_REG] |= BQ25186_SYS_REG_PG_GPO_LEVEL;
|
||||
this->switch_.set_restore_mode(switch_::SWITCH_ALWAYS_ON);
|
||||
this->switch_.set_inverted(true);
|
||||
this->hub_.setup();
|
||||
EXPECT_FALSE(this->level_());
|
||||
EXPECT_TRUE(this->switch_.state);
|
||||
}
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, SetupWithoutRestoreTakesTheChipLevel) {
|
||||
this->bus_.registers[BQ25186_REG_SYS_REG] |= BQ25186_SYS_REG_PG_GPO_LEVEL;
|
||||
this->hub_.setup();
|
||||
EXPECT_TRUE(this->level_());
|
||||
EXPECT_TRUE(this->switch_.state);
|
||||
}
|
||||
|
||||
TEST_F(BQ25186PgGpoTest, SetupWithoutRestoreTakesTheChipLevelInverted) {
|
||||
this->bus_.registers[BQ25186_REG_SYS_REG] |= BQ25186_SYS_REG_PG_GPO_LEVEL;
|
||||
this->switch_.set_inverted(true);
|
||||
this->hub_.setup();
|
||||
EXPECT_TRUE(this->level_());
|
||||
EXPECT_FALSE(this->switch_.state);
|
||||
}
|
||||
|
||||
} // namespace esphome::bq25186::testing
|
||||
@@ -1716,6 +1716,8 @@ _SELECT_APPLY = entity_helpers.ApplyEntity(
|
||||
"on_success",
|
||||
(
|
||||
"const char *option = entity->option_at(index);\n"
|
||||
"static_assert(std::is_same_v<decltype(::hub->set_mode(option)), bool>, "
|
||||
'"publish=\\"on_success\\" needs a hub call that returns bool");\n'
|
||||
"if (::hub->set_mode(option)) { entity->publish_state(index); }"
|
||||
),
|
||||
),
|
||||
@@ -1898,12 +1900,20 @@ async def test_sub_entities_apply_momentary(
|
||||
(
|
||||
_HUB,
|
||||
"write_level(state)",
|
||||
"if (::hub->write_level(state)) { entity->publish_state(state); }",
|
||||
(
|
||||
"static_assert(std::is_same_v<decltype(::hub->write_level(state)), bool>, "
|
||||
'"publish=\\"on_success\\" needs a hub call that returns bool");\n'
|
||||
"if (::hub->write_level(state)) { entity->publish_state(state); }"
|
||||
),
|
||||
),
|
||||
(
|
||||
None,
|
||||
"chip::write_level(state)",
|
||||
"if (chip::write_level(state)) { entity->publish_state(state); }",
|
||||
(
|
||||
"static_assert(std::is_same_v<decltype(chip::write_level(state)), bool>, "
|
||||
'"publish=\\"on_success\\" needs a hub call that returns bool");\n'
|
||||
"if (chip::write_level(state)) { entity->publish_state(state); }"
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user