mirror of
https://github.com/esphome/esphome.git
synced 2025-11-05 17:41:49 +00:00
Compare commits
46 Commits
2023.9.0b1
...
2023.9.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d800958aa | ||
|
|
471533d041 | ||
|
|
7dfc4c74da | ||
|
|
f709350b04 | ||
|
|
85c5928baa | ||
|
|
f5dfbaff4b | ||
|
|
689c2f11a3 | ||
|
|
f73fd97525 | ||
|
|
40523e6823 | ||
|
|
5e1472185c | ||
|
|
af005a6554 | ||
|
|
efd31be21c | ||
|
|
e9bda2810f | ||
|
|
ec4777b8d0 | ||
|
|
9b75121337 | ||
|
|
d262548d2e | ||
|
|
b5b654e054 | ||
|
|
dae8ab563c | ||
|
|
5751e9ec59 | ||
|
|
cc1b7a7a56 | ||
|
|
29249cdc1b | ||
|
|
e5bae8187f | ||
|
|
69adebfefa | ||
|
|
7dabbb65d0 | ||
|
|
b30bab8c1b | ||
|
|
0a1ed58454 | ||
|
|
5f5ee9c920 | ||
|
|
0aeebdd289 | ||
|
|
33e2aa341e | ||
|
|
a42788812e | ||
|
|
b07a038bc8 | ||
|
|
55e36ab982 | ||
|
|
90835ab917 | ||
|
|
5b46088ae4 | ||
|
|
d7e267eca5 | ||
|
|
807c47a076 | ||
|
|
7ebe6a5894 | ||
|
|
41c829fa32 | ||
|
|
8f1ce8c7f7 | ||
|
|
e55636ed52 | ||
|
|
e886262055 | ||
|
|
2fa7f8c511 | ||
|
|
4622ef770d | ||
|
|
d76f18b4f2 | ||
|
|
ec20778d83 | ||
|
|
b3ca71c6fb |
@@ -131,7 +131,7 @@ esphome/components/i2s_audio/* @jesserockz
|
|||||||
esphome/components/i2s_audio/media_player/* @jesserockz
|
esphome/components/i2s_audio/media_player/* @jesserockz
|
||||||
esphome/components/i2s_audio/microphone/* @jesserockz
|
esphome/components/i2s_audio/microphone/* @jesserockz
|
||||||
esphome/components/i2s_audio/speaker/* @jesserockz
|
esphome/components/i2s_audio/speaker/* @jesserockz
|
||||||
esphome/components/ili9xxx/* @nielsnl68
|
esphome/components/ili9xxx/* @clydebarrow @nielsnl68
|
||||||
esphome/components/improv_base/* @esphome/core
|
esphome/components/improv_base/* @esphome/core
|
||||||
esphome/components/improv_serial/* @esphome/core
|
esphome/components/improv_serial/* @esphome/core
|
||||||
esphome/components/ina260/* @mreditor97
|
esphome/components/ina260/* @mreditor97
|
||||||
@@ -270,7 +270,7 @@ esphome/components/sn74hc165/* @jesserockz
|
|||||||
esphome/components/socket/* @esphome/core
|
esphome/components/socket/* @esphome/core
|
||||||
esphome/components/sonoff_d1/* @anatoly-savchenkov
|
esphome/components/sonoff_d1/* @anatoly-savchenkov
|
||||||
esphome/components/speaker/* @jesserockz
|
esphome/components/speaker/* @jesserockz
|
||||||
esphome/components/spi/* @esphome/core
|
esphome/components/spi/* @clydebarrow @esphome/core
|
||||||
esphome/components/spi_device/* @clydebarrow
|
esphome/components/spi_device/* @clydebarrow
|
||||||
esphome/components/spi_led_strip/* @clydebarrow
|
esphome/components/spi_led_strip/* @clydebarrow
|
||||||
esphome/components/sprinkler/* @kbx81
|
esphome/components/sprinkler/* @kbx81
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ RUN \
|
|||||||
curl=7.74.0-1.3+deb11u7 \
|
curl=7.74.0-1.3+deb11u7 \
|
||||||
openssh-client=1:8.4p1-5+deb11u1 \
|
openssh-client=1:8.4p1-5+deb11u1 \
|
||||||
python3-cffi=1.14.5-1 \
|
python3-cffi=1.14.5-1 \
|
||||||
libcairo2=1.16.0-5; \
|
libcairo2=1.16.0-5 \
|
||||||
|
patch=2.7.6-7; \
|
||||||
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
|
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
build-essential=12.9 \
|
build-essential=12.9 \
|
||||||
|
|||||||
@@ -41,8 +41,15 @@ fi
|
|||||||
|
|
||||||
mkdir -p "${pio_cache_base}"
|
mkdir -p "${pio_cache_base}"
|
||||||
|
|
||||||
|
mkdir -p /config/esphome
|
||||||
|
|
||||||
if bashio::fs.directory_exists '/config/esphome/.esphome'; then
|
if bashio::fs.directory_exists '/config/esphome/.esphome'; then
|
||||||
bashio::log.info "Removing old .esphome directory..."
|
bashio::log.info "Migrating old .esphome directory..."
|
||||||
|
if bashio::fs.file_exists '/config/esphome/.esphome/esphome.json'; then
|
||||||
|
mv /config/esphome/.esphome/esphome.json /data/esphome.json
|
||||||
|
fi
|
||||||
|
mkdir -p "/data/storage"
|
||||||
|
mv /config/esphome/.esphome/*.json /data/storage/ || true
|
||||||
rm -rf /config/esphome/.esphome
|
rm -rf /config/esphome/.esphome
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,14 @@ void BP5758D::loop() {
|
|||||||
uint8_t data[17];
|
uint8_t data[17];
|
||||||
if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 &&
|
if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 &&
|
||||||
this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) {
|
this->pwm_amounts_[3] == 0 && this->pwm_amounts_[4] == 0) {
|
||||||
// Off / Sleep
|
|
||||||
data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY;
|
|
||||||
for (int i = 1; i < 16; i++)
|
for (int i = 1; i < 16; i++)
|
||||||
data[i] = 0;
|
data[i] = 0;
|
||||||
|
|
||||||
|
// First turn all channels off
|
||||||
|
data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_START_3CH;
|
||||||
|
this->write_buffer_(data, 17);
|
||||||
|
// Then sleep
|
||||||
|
data[0] = BP5758D_MODEL_ID + BP5758D_ADDR_STANDBY;
|
||||||
this->write_buffer_(data, 17);
|
this->write_buffer_(data, 17);
|
||||||
} else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 &&
|
} else if (this->pwm_amounts_[0] == 0 && this->pwm_amounts_[1] == 0 && this->pwm_amounts_[2] == 0 &&
|
||||||
(this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) {
|
(this->pwm_amounts_[3] > 0 || this->pwm_amounts_[4] > 0)) {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
).extend(
|
).extend(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent),
|
cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent),
|
||||||
cv.Optional(CONF_ADDRESS): cv.hex_int,
|
cv.Optional(CONF_ADDRESS): cv.hex_uint64_t,
|
||||||
cv.Optional(CONF_INDEX): cv.positive_int,
|
cv.Optional(CONF_INDEX): cv.positive_int,
|
||||||
cv.Optional(CONF_RESOLUTION, default=12): cv.int_range(min=9, max=12),
|
cv.Optional(CONF_RESOLUTION, default=12): cv.int_range(min=9, max=12),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,6 +235,7 @@ ESP32_BOARD_PINS = {
|
|||||||
"SDA": 5,
|
"SDA": 5,
|
||||||
"SS": 15,
|
"SS": 15,
|
||||||
},
|
},
|
||||||
|
"denky_d4": {"RX": 8, "LED": 14},
|
||||||
"esp-wrover-kit": {},
|
"esp-wrover-kit": {},
|
||||||
"esp32-devkitlipo": {},
|
"esp32-devkitlipo": {},
|
||||||
"esp32-evb": {
|
"esp32-evb": {
|
||||||
|
|||||||
@@ -80,8 +80,6 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
|||||||
TEMPLATABLE_VALUE(std::string, url)
|
TEMPLATABLE_VALUE(std::string, url)
|
||||||
TEMPLATABLE_VALUE(const char *, method)
|
TEMPLATABLE_VALUE(const char *, method)
|
||||||
TEMPLATABLE_VALUE(std::string, body)
|
TEMPLATABLE_VALUE(std::string, body)
|
||||||
TEMPLATABLE_VALUE(const char *, useragent)
|
|
||||||
TEMPLATABLE_VALUE(uint16_t, timeout)
|
|
||||||
|
|
||||||
void add_header(const char *key, TemplatableValue<const char *, Ts...> value) { this->headers_.insert({key, value}); }
|
void add_header(const char *key, TemplatableValue<const char *, Ts...> value) { this->headers_.insert({key, value}); }
|
||||||
|
|
||||||
@@ -105,25 +103,18 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
|||||||
auto f = std::bind(&HttpRequestSendAction<Ts...>::encode_json_func_, this, x..., std::placeholders::_1);
|
auto f = std::bind(&HttpRequestSendAction<Ts...>::encode_json_func_, this, x..., std::placeholders::_1);
|
||||||
this->parent_->set_body(json::build_json(f));
|
this->parent_->set_body(json::build_json(f));
|
||||||
}
|
}
|
||||||
if (this->useragent_.has_value()) {
|
std::list<Header> headers;
|
||||||
this->parent_->set_useragent(this->useragent_.value(x...));
|
for (const auto &item : this->headers_) {
|
||||||
}
|
auto val = item.second;
|
||||||
if (this->timeout_.has_value()) {
|
Header header;
|
||||||
this->parent_->set_timeout(this->timeout_.value(x...));
|
header.name = item.first;
|
||||||
}
|
header.value = val.value(x...);
|
||||||
if (!this->headers_.empty()) {
|
headers.push_back(header);
|
||||||
std::list<Header> headers;
|
|
||||||
for (const auto &item : this->headers_) {
|
|
||||||
auto val = item.second;
|
|
||||||
Header header;
|
|
||||||
header.name = item.first;
|
|
||||||
header.value = val.value(x...);
|
|
||||||
headers.push_back(header);
|
|
||||||
}
|
|
||||||
this->parent_->set_headers(headers);
|
|
||||||
}
|
}
|
||||||
|
this->parent_->set_headers(headers);
|
||||||
this->parent_->send(this->response_triggers_);
|
this->parent_->send(this->response_triggers_);
|
||||||
this->parent_->close();
|
this->parent_->close();
|
||||||
|
this->parent_->set_body("");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ def AUTO_LOAD():
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
CODEOWNERS = ["@nielsnl68"]
|
CODEOWNERS = ["@nielsnl68", "@clydebarrow"]
|
||||||
|
|
||||||
ili9XXX_ns = cg.esphome_ns.namespace("ili9xxx")
|
ili9XXX_ns = cg.esphome_ns.namespace("ili9xxx")
|
||||||
ili9XXXSPI = ili9XXX_ns.class_(
|
ili9XXXSPI = ili9XXX_ns.class_(
|
||||||
@@ -42,6 +42,7 @@ MODELS = {
|
|||||||
"ILI9341": ili9XXX_ns.class_("ILI9XXXILI9341", ili9XXXSPI),
|
"ILI9341": ili9XXX_ns.class_("ILI9XXXILI9341", ili9XXXSPI),
|
||||||
"ILI9342": ili9XXX_ns.class_("ILI9XXXILI9342", ili9XXXSPI),
|
"ILI9342": ili9XXX_ns.class_("ILI9XXXILI9342", ili9XXXSPI),
|
||||||
"ILI9481": ili9XXX_ns.class_("ILI9XXXILI9481", ili9XXXSPI),
|
"ILI9481": ili9XXX_ns.class_("ILI9XXXILI9481", ili9XXXSPI),
|
||||||
|
"ILI9481-18": ili9XXX_ns.class_("ILI9XXXILI948118", ili9XXXSPI),
|
||||||
"ILI9486": ili9XXX_ns.class_("ILI9XXXILI9486", ili9XXXSPI),
|
"ILI9486": ili9XXX_ns.class_("ILI9XXXILI9486", ili9XXXSPI),
|
||||||
"ILI9488": ili9XXX_ns.class_("ILI9XXXILI9488", ili9XXXSPI),
|
"ILI9488": ili9XXX_ns.class_("ILI9XXXILI9488", ili9XXXSPI),
|
||||||
"ILI9488_A": ili9XXX_ns.class_("ILI9XXXILI9488A", ili9XXXSPI),
|
"ILI9488_A": ili9XXX_ns.class_("ILI9XXXILI9488A", ili9XXXSPI),
|
||||||
@@ -140,8 +141,6 @@ async def to_code(config):
|
|||||||
rhs = []
|
rhs = []
|
||||||
for x in range(256):
|
for x in range(256):
|
||||||
rhs.extend([HexInt(x), HexInt(x), HexInt(x)])
|
rhs.extend([HexInt(x), HexInt(x), HexInt(x)])
|
||||||
prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
|
|
||||||
cg.add(var.set_palette(prog_arr))
|
|
||||||
elif config[CONF_COLOR_PALETTE] == "IMAGE_ADAPTIVE":
|
elif config[CONF_COLOR_PALETTE] == "IMAGE_ADAPTIVE":
|
||||||
cg.add(var.set_buffer_color_mode(ILI9XXXColorMode.BITS_8_INDEXED))
|
cg.add(var.set_buffer_color_mode(ILI9XXXColorMode.BITS_8_INDEXED))
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
@@ -178,6 +177,4 @@ async def to_code(config):
|
|||||||
if rhs is not None:
|
if rhs is not None:
|
||||||
prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
|
prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
|
||||||
cg.add(var.set_palette(prog_arr))
|
cg.add(var.set_palette(prog_arr))
|
||||||
|
cg.add(var.set_data_rate(config[CONF_DATA_RATE]))
|
||||||
spi_data_rate = str(spi.SPI_DATA_RATE_OPTIONS[config[CONF_DATA_RATE]])
|
|
||||||
cg.add_define("ILI9XXXDisplay_DATA_RATE", cg.RawExpression(spi_data_rate))
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ void ILI9XXXDisplay::dump_config() {
|
|||||||
if (this->is_18bitdisplay_) {
|
if (this->is_18bitdisplay_) {
|
||||||
ESP_LOGCONFIG(TAG, " 18-Bit Mode: YES");
|
ESP_LOGCONFIG(TAG, " 18-Bit Mode: YES");
|
||||||
}
|
}
|
||||||
|
ESP_LOGCONFIG(TAG, " Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000));
|
||||||
|
|
||||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||||
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||||
@@ -387,6 +388,17 @@ void ILI9XXXILI9481::initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ILI9XXXILI948118::initialize() {
|
||||||
|
this->init_lcd_(INITCMD_ILI9481_18);
|
||||||
|
if (this->width_ == 0) {
|
||||||
|
this->width_ = 320;
|
||||||
|
}
|
||||||
|
if (this->height_ == 0) {
|
||||||
|
this->height_ = 480;
|
||||||
|
}
|
||||||
|
this->is_18bitdisplay_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
// 35_TFT display
|
// 35_TFT display
|
||||||
void ILI9XXXILI9486::initialize() {
|
void ILI9XXXILI9486::initialize() {
|
||||||
this->init_lcd_(INITCMD_ILI9486);
|
this->init_lcd_(INITCMD_ILI9486);
|
||||||
|
|||||||
@@ -120,6 +120,12 @@ class ILI9XXXILI9481 : public ILI9XXXDisplay {
|
|||||||
void initialize() override;
|
void initialize() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//----------- ILI9481 in 18 bit mode --------------
|
||||||
|
class ILI9XXXILI948118 : public ILI9XXXDisplay {
|
||||||
|
protected:
|
||||||
|
void initialize() override;
|
||||||
|
};
|
||||||
|
|
||||||
//----------- ILI9XXX_35_TFT rotated display --------------
|
//----------- ILI9XXX_35_TFT rotated display --------------
|
||||||
class ILI9XXXILI9486 : public ILI9XXXDisplay {
|
class ILI9XXXILI9486 : public ILI9XXXDisplay {
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -94,12 +94,36 @@ static const uint8_t PROGMEM INITCMD_ILI9481[] = {
|
|||||||
ILI9XXX_IFCTR , 1, 0x83,
|
ILI9XXX_IFCTR , 1, 0x83,
|
||||||
ILI9XXX_GMCTR ,12, 0x00, 0x26, 0x21, 0x00, 0x00, 0x1F, 0x65, 0x23, 0x77, 0x00, 0x0F, 0x00,
|
ILI9XXX_GMCTR ,12, 0x00, 0x26, 0x21, 0x00, 0x00, 0x1F, 0x65, 0x23, 0x77, 0x00, 0x0F, 0x00,
|
||||||
ILI9XXX_IFMODE , 1, 0x00, // CommandAccessProtect
|
ILI9XXX_IFMODE , 1, 0x00, // CommandAccessProtect
|
||||||
|
ILI9XXX_PTLAR , 4, 0, 0, 1, 0xDF,
|
||||||
0xE4 , 1, 0xA0,
|
0xE4 , 1, 0xA0,
|
||||||
|
ILI9XXX_MADCTL , 1, MADCTL_MV | MADCTL_BGR, // Memory Access Control
|
||||||
ILI9XXX_CSCON , 1, 0x01,
|
ILI9XXX_CSCON , 1, 0x01,
|
||||||
|
ILI9XXX_PIXFMT, 1, 0x55, // 16 bit mode
|
||||||
|
ILI9XXX_INVON, 0,
|
||||||
ILI9XXX_DISPON, 0x80, // Set display on
|
ILI9XXX_DISPON, 0x80, // Set display on
|
||||||
0x00 // end
|
0x00 // end
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint8_t PROGMEM INITCMD_ILI9481_18[] = {
|
||||||
|
ILI9XXX_SLPOUT , 0x80, // Exit sleep mode
|
||||||
|
ILI9XXX_PWSET , 3, 0x07, 0x41, 0x1D,
|
||||||
|
ILI9XXX_VMCTR , 3, 0x00, 0x1C, 0x1F,
|
||||||
|
ILI9XXX_PWSETN , 2, 0x01, 0x11,
|
||||||
|
ILI9XXX_PWCTR1 , 5, 0x10, 0x3B, 0x00, 0x02, 0x11,
|
||||||
|
ILI9XXX_VMCTR1 , 1, 0x03,
|
||||||
|
ILI9XXX_IFCTR , 1, 0x83,
|
||||||
|
ILI9XXX_GMCTR ,12, 0x00, 0x26, 0x21, 0x00, 0x00, 0x1F, 0x65, 0x23, 0x77, 0x00, 0x0F, 0x00,
|
||||||
|
ILI9XXX_IFMODE , 1, 0x00, // CommandAccessProtect
|
||||||
|
ILI9XXX_PTLAR , 4, 0, 0, 1, 0xDF,
|
||||||
|
0xE4 , 1, 0xA0,
|
||||||
|
ILI9XXX_MADCTL , 1, MADCTL_MX| MADCTL_BGR, // Memory Access Control
|
||||||
|
ILI9XXX_CSCON , 1, 0x01,
|
||||||
|
ILI9XXX_PIXFMT, 1, 0x66, // 18 bit mode
|
||||||
|
ILI9XXX_INVON, 0,
|
||||||
|
ILI9XXX_DISPON, 0x80, // Set display on
|
||||||
|
0x00 // end
|
||||||
|
};
|
||||||
|
|
||||||
static const uint8_t PROGMEM INITCMD_ILI9486[] = {
|
static const uint8_t PROGMEM INITCMD_ILI9486[] = {
|
||||||
ILI9XXX_SLPOUT, 0x80,
|
ILI9XXX_SLPOUT, 0x80,
|
||||||
ILI9XXX_PIXFMT, 1, 0x55,
|
ILI9XXX_PIXFMT, 1, 0x55,
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ def _notify_old_style(config):
|
|||||||
ARDUINO_VERSIONS = {
|
ARDUINO_VERSIONS = {
|
||||||
"dev": (cv.Version(0, 0, 0), "https://github.com/libretiny-eu/libretiny.git"),
|
"dev": (cv.Version(0, 0, 0), "https://github.com/libretiny-eu/libretiny.git"),
|
||||||
"latest": (cv.Version(0, 0, 0), None),
|
"latest": (cv.Version(0, 0, 0), None),
|
||||||
"recommended": (cv.Version(1, 4, 0), None),
|
"recommended": (cv.Version(1, 4, 1), None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ CONF_COLUMNS = "columns"
|
|||||||
CONF_KEYS = "keys"
|
CONF_KEYS = "keys"
|
||||||
CONF_DEBOUNCE_TIME = "debounce_time"
|
CONF_DEBOUNCE_TIME = "debounce_time"
|
||||||
CONF_HAS_DIODES = "has_diodes"
|
CONF_HAS_DIODES = "has_diodes"
|
||||||
|
CONF_HAS_PULLDOWNS = "has_pulldowns"
|
||||||
|
|
||||||
|
|
||||||
def check_keys(obj):
|
def check_keys(obj):
|
||||||
@@ -45,6 +46,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Optional(CONF_KEYS): cv.string,
|
cv.Optional(CONF_KEYS): cv.string,
|
||||||
cv.Optional(CONF_DEBOUNCE_TIME, default=1): cv.int_range(min=1, max=100),
|
cv.Optional(CONF_DEBOUNCE_TIME, default=1): cv.int_range(min=1, max=100),
|
||||||
cv.Optional(CONF_HAS_DIODES): cv.boolean,
|
cv.Optional(CONF_HAS_DIODES): cv.boolean,
|
||||||
|
cv.Optional(CONF_HAS_PULLDOWNS): cv.boolean,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
check_keys,
|
check_keys,
|
||||||
@@ -69,3 +71,5 @@ async def to_code(config):
|
|||||||
cg.add(var.set_debounce_time(config[CONF_DEBOUNCE_TIME]))
|
cg.add(var.set_debounce_time(config[CONF_DEBOUNCE_TIME]))
|
||||||
if CONF_HAS_DIODES in config:
|
if CONF_HAS_DIODES in config:
|
||||||
cg.add(var.set_has_diodes(config[CONF_HAS_DIODES]))
|
cg.add(var.set_has_diodes(config[CONF_HAS_DIODES]))
|
||||||
|
if CONF_HAS_PULLDOWNS in config:
|
||||||
|
cg.add(var.set_has_pulldowns(config[CONF_HAS_PULLDOWNS]))
|
||||||
|
|||||||
@@ -11,11 +11,16 @@ void MatrixKeypad::setup() {
|
|||||||
if (!has_diodes_) {
|
if (!has_diodes_) {
|
||||||
pin->pin_mode(gpio::FLAG_INPUT);
|
pin->pin_mode(gpio::FLAG_INPUT);
|
||||||
} else {
|
} else {
|
||||||
pin->digital_write(true);
|
pin->digital_write(!has_pulldowns_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto *pin : this->columns_) {
|
||||||
|
if (has_pulldowns_) {
|
||||||
|
pin->pin_mode(gpio::FLAG_INPUT);
|
||||||
|
} else {
|
||||||
|
pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto *pin : this->columns_)
|
|
||||||
pin->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatrixKeypad::loop() {
|
void MatrixKeypad::loop() {
|
||||||
@@ -28,9 +33,9 @@ void MatrixKeypad::loop() {
|
|||||||
for (auto *row : this->rows_) {
|
for (auto *row : this->rows_) {
|
||||||
if (!has_diodes_)
|
if (!has_diodes_)
|
||||||
row->pin_mode(gpio::FLAG_OUTPUT);
|
row->pin_mode(gpio::FLAG_OUTPUT);
|
||||||
row->digital_write(false);
|
row->digital_write(has_pulldowns_);
|
||||||
for (auto *col : this->columns_) {
|
for (auto *col : this->columns_) {
|
||||||
if (!col->digital_read()) {
|
if (col->digital_read() == has_pulldowns_) {
|
||||||
if (key != -1) {
|
if (key != -1) {
|
||||||
error = true;
|
error = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -39,7 +44,7 @@ void MatrixKeypad::loop() {
|
|||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
row->digital_write(true);
|
row->digital_write(!has_pulldowns_);
|
||||||
if (!has_diodes_)
|
if (!has_diodes_)
|
||||||
row->pin_mode(gpio::FLAG_INPUT);
|
row->pin_mode(gpio::FLAG_INPUT);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component {
|
|||||||
void set_keys(std::string keys) { keys_ = std::move(keys); };
|
void set_keys(std::string keys) { keys_ = std::move(keys); };
|
||||||
void set_debounce_time(int debounce_time) { debounce_time_ = debounce_time; };
|
void set_debounce_time(int debounce_time) { debounce_time_ = debounce_time; };
|
||||||
void set_has_diodes(int has_diodes) { has_diodes_ = has_diodes; };
|
void set_has_diodes(int has_diodes) { has_diodes_ = has_diodes; };
|
||||||
|
void set_has_pulldowns(int has_pulldowns) { has_pulldowns_ = has_pulldowns; };
|
||||||
|
|
||||||
void register_listener(MatrixKeypadListener *listener);
|
void register_listener(MatrixKeypadListener *listener);
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component {
|
|||||||
std::string keys_;
|
std::string keys_;
|
||||||
int debounce_time_ = 0;
|
int debounce_time_ = 0;
|
||||||
bool has_diodes_{false};
|
bool has_diodes_{false};
|
||||||
|
bool has_pulldowns_{false};
|
||||||
int pressed_key_ = -1;
|
int pressed_key_ = -1;
|
||||||
|
|
||||||
std::vector<MatrixKeypadListener *> listeners_{};
|
std::vector<MatrixKeypadListener *> listeners_{};
|
||||||
|
|||||||
@@ -217,10 +217,7 @@ uint8_t MAX7219Component::printf(const char *format, ...) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void MAX7219Component::set_writer(max7219_writer_t &&writer) { this->writer_ = writer; }
|
void MAX7219Component::set_writer(max7219_writer_t &&writer) { this->writer_ = writer; }
|
||||||
void MAX7219Component::set_intensity(uint8_t intensity) {
|
void MAX7219Component::set_intensity(uint8_t intensity) { this->intensity_ = intensity; }
|
||||||
this->intensity_ = intensity;
|
|
||||||
this->send_to_all_(MAX7219_REGISTER_INTENSITY, this->intensity_);
|
|
||||||
}
|
|
||||||
void MAX7219Component::set_num_chips(uint8_t num_chips) { this->num_chips_ = num_chips; }
|
void MAX7219Component::set_num_chips(uint8_t num_chips) { this->num_chips_ = num_chips; }
|
||||||
|
|
||||||
uint8_t MAX7219Component::strftime(uint8_t pos, const char *format, ESPTime time) {
|
uint8_t MAX7219Component::strftime(uint8_t pos, const char *format, ESPTime time) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ from esphome.components.climate import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
CODEOWNERS = ["@dudanov"]
|
CODEOWNERS = ["@dudanov"]
|
||||||
DEPENDENCIES = ["climate", "uart", "wifi"]
|
DEPENDENCIES = ["climate", "uart"]
|
||||||
AUTO_LOAD = ["sensor"]
|
AUTO_LOAD = ["sensor"]
|
||||||
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
|
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
|
||||||
CONF_POWER_USAGE = "power_usage"
|
CONF_POWER_USAGE = "power_usage"
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
|||||||
const auto *mopeka_data = (const mopeka_std_package *) manu_data.data.data();
|
const auto *mopeka_data = (const mopeka_std_package *) manu_data.data.data();
|
||||||
|
|
||||||
const u_int8_t hardware_id = mopeka_data->data_1 & 0xCF;
|
const u_int8_t hardware_id = mopeka_data->data_1 & 0xCF;
|
||||||
if (static_cast<SensorType>(hardware_id) != STANDARD && static_cast<SensorType>(hardware_id) != XL) {
|
if (static_cast<SensorType>(hardware_id) != STANDARD && static_cast<SensorType>(hardware_id) != XL &&
|
||||||
|
static_cast<SensorType>(hardware_id) != ETRAILER) {
|
||||||
ESP_LOGE(TAG, "[%s] Unsupported Sensor Type (0x%X)", device.address_str().c_str(), hardware_id);
|
ESP_LOGE(TAG, "[%s] Unsupported Sensor Type (0x%X)", device.address_str().c_str(), hardware_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace mopeka_std_check {
|
|||||||
enum SensorType {
|
enum SensorType {
|
||||||
STANDARD = 0x02,
|
STANDARD = 0x02,
|
||||||
XL = 0x03,
|
XL = 0x03,
|
||||||
|
ETRAILER = 0x46,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 4 values in one struct so it aligns to 8 byte. One `mopeka_std_values` is 40 bit long.
|
// 4 values in one struct so it aligns to 8 byte. One `mopeka_std_values` is 40 bit long.
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
validate_config,
|
validate_config,
|
||||||
cv.only_on(["esp32", "esp8266"]),
|
cv.only_on(["esp32", "esp8266", "bk72xx"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -271,10 +271,10 @@ def exp_mqtt_message(config):
|
|||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
# Add required libraries for ESP8266
|
# Add required libraries for ESP8266 and LibreTiny
|
||||||
if CORE.is_esp8266:
|
if CORE.is_esp8266 or CORE.is_libretiny:
|
||||||
# https://github.com/heman/async-mqtt-client/blob/master/library.json
|
# https://github.com/heman/async-mqtt-client/blob/master/library.json
|
||||||
cg.add_library("heman/AsyncMqttClient-esphome", "1.0.0")
|
cg.add_library("heman/AsyncMqttClient-esphome", "2.0.0")
|
||||||
|
|
||||||
cg.add_define("USE_MQTT")
|
cg.add_define("USE_MQTT")
|
||||||
cg.add_global(mqtt_ns.using)
|
cg.add_global(mqtt_ns.using)
|
||||||
|
|||||||
74
esphome/components/mqtt/mqtt_backend_libretiny.h
Normal file
74
esphome/components/mqtt/mqtt_backend_libretiny.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef USE_LIBRETINY
|
||||||
|
|
||||||
|
#include "mqtt_backend.h"
|
||||||
|
#include <AsyncMqttClient.h>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace mqtt {
|
||||||
|
|
||||||
|
class MQTTBackendLibreTiny final : public MQTTBackend {
|
||||||
|
public:
|
||||||
|
void set_keep_alive(uint16_t keep_alive) final { mqtt_client_.setKeepAlive(keep_alive); }
|
||||||
|
void set_client_id(const char *client_id) final { mqtt_client_.setClientId(client_id); }
|
||||||
|
void set_clean_session(bool clean_session) final { mqtt_client_.setCleanSession(clean_session); }
|
||||||
|
void set_credentials(const char *username, const char *password) final {
|
||||||
|
mqtt_client_.setCredentials(username, password);
|
||||||
|
}
|
||||||
|
void set_will(const char *topic, uint8_t qos, bool retain, const char *payload) final {
|
||||||
|
mqtt_client_.setWill(topic, qos, retain, payload);
|
||||||
|
}
|
||||||
|
void set_server(network::IPAddress ip, uint16_t port) final {
|
||||||
|
mqtt_client_.setServer(IPAddress(static_cast<uint32_t>(ip)), port);
|
||||||
|
}
|
||||||
|
void set_server(const char *host, uint16_t port) final { mqtt_client_.setServer(host, port); }
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
void set_secure(bool secure) { mqtt_client.setSecure(secure); }
|
||||||
|
void add_server_fingerprint(const uint8_t *fingerprint) { mqtt_client.addServerFingerprint(fingerprint); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void set_on_connect(std::function<on_connect_callback_t> &&callback) final {
|
||||||
|
this->mqtt_client_.onConnect(std::move(callback));
|
||||||
|
}
|
||||||
|
void set_on_disconnect(std::function<on_disconnect_callback_t> &&callback) final {
|
||||||
|
auto async_callback = [callback](AsyncMqttClientDisconnectReason reason) {
|
||||||
|
// int based enum so casting isn't a problem
|
||||||
|
callback(static_cast<MQTTClientDisconnectReason>(reason));
|
||||||
|
};
|
||||||
|
this->mqtt_client_.onDisconnect(std::move(async_callback));
|
||||||
|
}
|
||||||
|
void set_on_subscribe(std::function<on_subscribe_callback_t> &&callback) final {
|
||||||
|
this->mqtt_client_.onSubscribe(std::move(callback));
|
||||||
|
}
|
||||||
|
void set_on_unsubscribe(std::function<on_unsubscribe_callback_t> &&callback) final {
|
||||||
|
this->mqtt_client_.onUnsubscribe(std::move(callback));
|
||||||
|
}
|
||||||
|
void set_on_message(std::function<on_message_callback_t> &&callback) final {
|
||||||
|
auto async_callback = [callback](const char *topic, const char *payload,
|
||||||
|
AsyncMqttClientMessageProperties async_properties, size_t len, size_t index,
|
||||||
|
size_t total) { callback(topic, payload, len, index, total); };
|
||||||
|
mqtt_client_.onMessage(std::move(async_callback));
|
||||||
|
}
|
||||||
|
void set_on_publish(std::function<on_publish_user_callback_t> &&callback) final {
|
||||||
|
this->mqtt_client_.onPublish(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool connected() const final { return mqtt_client_.connected(); }
|
||||||
|
void connect() final { mqtt_client_.connect(); }
|
||||||
|
void disconnect() final { mqtt_client_.disconnect(true); }
|
||||||
|
bool subscribe(const char *topic, uint8_t qos) final { return mqtt_client_.subscribe(topic, qos) != 0; }
|
||||||
|
bool unsubscribe(const char *topic) final { return mqtt_client_.unsubscribe(topic) != 0; }
|
||||||
|
bool publish(const char *topic, const char *payload, size_t length, uint8_t qos, bool retain) final {
|
||||||
|
return mqtt_client_.publish(topic, qos, retain, payload, length, false, 0) != 0;
|
||||||
|
}
|
||||||
|
using MQTTBackend::publish;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AsyncMqttClient mqtt_client_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mqtt
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // defined(USE_LIBRETINY)
|
||||||
@@ -106,6 +106,9 @@ void MQTTClientComponent::send_device_info_() {
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
root["platform"] = "ESP32";
|
root["platform"] = "ESP32";
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_LIBRETINY
|
||||||
|
root["platform"] = lt_cpu_get_model_name();
|
||||||
|
#endif
|
||||||
|
|
||||||
root["board"] = ESPHOME_BOARD;
|
root["board"] = ESPHOME_BOARD;
|
||||||
#if defined(USE_WIFI)
|
#if defined(USE_WIFI)
|
||||||
@@ -156,7 +159,7 @@ void MQTTClientComponent::start_dnslookup_() {
|
|||||||
this->dns_resolve_error_ = false;
|
this->dns_resolve_error_ = false;
|
||||||
this->dns_resolved_ = false;
|
this->dns_resolved_ = false;
|
||||||
ip_addr_t addr;
|
ip_addr_t addr;
|
||||||
#ifdef USE_ESP32
|
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||||
err_t err = dns_gethostbyname_addrtype(this->credentials_.address.c_str(), &addr,
|
err_t err = dns_gethostbyname_addrtype(this->credentials_.address.c_str(), &addr,
|
||||||
MQTTClientComponent::dns_found_callback, this, LWIP_DNS_ADDRTYPE_IPV4);
|
MQTTClientComponent::dns_found_callback, this, LWIP_DNS_ADDRTYPE_IPV4);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include "mqtt_backend_esp32.h"
|
#include "mqtt_backend_esp32.h"
|
||||||
#elif defined(USE_ESP8266)
|
#elif defined(USE_ESP8266)
|
||||||
#include "mqtt_backend_esp8266.h"
|
#include "mqtt_backend_esp8266.h"
|
||||||
|
#elif defined(USE_LIBRETINY)
|
||||||
|
#include "mqtt_backend_libretiny.h"
|
||||||
#endif
|
#endif
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
@@ -300,6 +302,8 @@ class MQTTClientComponent : public Component {
|
|||||||
MQTTBackendESP32 mqtt_backend_;
|
MQTTBackendESP32 mqtt_backend_;
|
||||||
#elif defined(USE_ESP8266)
|
#elif defined(USE_ESP8266)
|
||||||
MQTTBackendESP8266 mqtt_backend_;
|
MQTTBackendESP8266 mqtt_backend_;
|
||||||
|
#elif defined(USE_LIBRETINY)
|
||||||
|
MQTTBackendLibreTiny mqtt_backend_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MQTTClientState state_{MQTT_CLIENT_DISCONNECTED};
|
MQTTClientState state_{MQTT_CLIENT_DISCONNECTED};
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ void PulseMeterSensor::setup() {
|
|||||||
this->pin_->setup();
|
this->pin_->setup();
|
||||||
this->isr_pin_ = pin_->to_isr();
|
this->isr_pin_ = pin_->to_isr();
|
||||||
|
|
||||||
|
// Set the last processed edge to now for the first timeout
|
||||||
|
this->last_processed_edge_us_ = micros();
|
||||||
|
|
||||||
if (this->filter_mode_ == FILTER_EDGE) {
|
if (this->filter_mode_ == FILTER_EDGE) {
|
||||||
this->pin_->attach_interrupt(PulseMeterSensor::edge_intr, this, gpio::INTERRUPT_RISING_EDGE);
|
this->pin_->attach_interrupt(PulseMeterSensor::edge_intr, this, gpio::INTERRUPT_RISING_EDGE);
|
||||||
} else if (this->filter_mode_ == FILTER_PULSE) {
|
} else if (this->filter_mode_ == FILTER_PULSE) {
|
||||||
@@ -38,12 +41,16 @@ void PulseMeterSensor::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We need to detect at least two edges to have a valid pulse width
|
// We need to detect at least two edges to have a valid pulse width
|
||||||
if (!this->initialized_) {
|
switch (this->meter_state_) {
|
||||||
this->initialized_ = true;
|
case MeterState::INITIAL:
|
||||||
} else {
|
case MeterState::TIMED_OUT: {
|
||||||
uint32_t delta_us = this->get_->last_detected_edge_us_ - this->last_processed_edge_us_;
|
this->meter_state_ = MeterState::RUNNING;
|
||||||
float pulse_width_us = delta_us / float(this->get_->count_);
|
} break;
|
||||||
this->publish_state((60.0f * 1000000.0f) / pulse_width_us);
|
case MeterState::RUNNING: {
|
||||||
|
uint32_t delta_us = this->get_->last_detected_edge_us_ - this->last_processed_edge_us_;
|
||||||
|
float pulse_width_us = delta_us / float(this->get_->count_);
|
||||||
|
this->publish_state((60.0f * 1000000.0f) / pulse_width_us);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->last_processed_edge_us_ = this->get_->last_detected_edge_us_;
|
this->last_processed_edge_us_ = this->get_->last_detected_edge_us_;
|
||||||
@@ -53,10 +60,18 @@ void PulseMeterSensor::loop() {
|
|||||||
const uint32_t now = micros();
|
const uint32_t now = micros();
|
||||||
const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_;
|
const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_;
|
||||||
|
|
||||||
if (this->initialized_ && time_since_valid_edge_us > this->timeout_us_) {
|
switch (this->meter_state_) {
|
||||||
ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000);
|
// Running and initial states can timeout
|
||||||
this->initialized_ = false;
|
case MeterState::INITIAL:
|
||||||
this->publish_state(0.0f);
|
case MeterState::RUNNING: {
|
||||||
|
if (time_since_valid_edge_us > this->timeout_us_) {
|
||||||
|
this->meter_state_ = MeterState::TIMED_OUT;
|
||||||
|
ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000);
|
||||||
|
this->publish_state(0.0f);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ class PulseMeterSensor : public sensor::Sensor, public Component {
|
|||||||
InternalFilterMode filter_mode_{FILTER_EDGE};
|
InternalFilterMode filter_mode_{FILTER_EDGE};
|
||||||
|
|
||||||
// Variables used in the loop
|
// Variables used in the loop
|
||||||
bool initialized_ = false;
|
enum class MeterState { INITIAL, RUNNING, TIMED_OUT };
|
||||||
|
MeterState meter_state_ = MeterState::INITIAL;
|
||||||
uint32_t total_pulses_ = 0;
|
uint32_t total_pulses_ = 0;
|
||||||
uint32_t last_processed_edge_us_ = 0;
|
uint32_t last_processed_edge_us_ = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ static const char *const TAG = "radon_eye_ble";
|
|||||||
|
|
||||||
bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
|
bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
|
||||||
if (not device.get_name().empty()) {
|
if (not device.get_name().empty()) {
|
||||||
if (device.get_name().rfind("FR:R20:SN", 0) == 0) {
|
if (device.get_name().rfind("FR:R", 0) == 0) {
|
||||||
// This is an RD200, I think
|
// This is an RD200, I think
|
||||||
ESP_LOGD(TAG, "Found Radon Eye RD200 device Name: %s (MAC: %s)", device.get_name().c_str(),
|
ESP_LOGD(TAG, "Found Radon Eye RD200 device Name: %s (MAC: %s)", device.get_name().c_str(),
|
||||||
device.address_str().c_str());
|
device.address_str().c_str());
|
||||||
|
|||||||
@@ -152,6 +152,9 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
cg.add(rp2040_ns.setup_preferences())
|
cg.add(rp2040_ns.setup_preferences())
|
||||||
|
|
||||||
|
# Allow LDF to properly discover dependency including those in preprocessor
|
||||||
|
# conditionals
|
||||||
|
cg.add_platformio_option("lib_ldf_mode", "chain+")
|
||||||
cg.add_platformio_option("board", config[CONF_BOARD])
|
cg.add_platformio_option("board", config[CONF_BOARD])
|
||||||
cg.add_build_flag("-DUSE_RP2040")
|
cg.add_build_flag("-DUSE_RP2040")
|
||||||
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
|
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ KNOWN_FIRMWARE = {
|
|||||||
"https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.6/shelly-dimmer-stm32_v51.6.bin",
|
"https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.6/shelly-dimmer-stm32_v51.6.bin",
|
||||||
"eda483e111c914723a33f5088f1397d5c0b19333db4a88dc965636b976c16c36",
|
"eda483e111c914723a33f5088f1397d5c0b19333db4a88dc965636b976c16c36",
|
||||||
),
|
),
|
||||||
|
"51.7": (
|
||||||
|
"https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.7/shelly-dimmer-stm32_v51.7.bin",
|
||||||
|
"7a20f1c967c469917368a79bc56498009045237080408cef7190743e08031889",
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ from esphome.const import (
|
|||||||
)
|
)
|
||||||
from esphome.core import coroutine_with_priority, CORE
|
from esphome.core import coroutine_with_priority, CORE
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core", "@clydebarrow"]
|
||||||
spi_ns = cg.esphome_ns.namespace("spi")
|
spi_ns = cg.esphome_ns.namespace("spi")
|
||||||
SPIComponent = spi_ns.class_("SPIComponent", cg.Component)
|
SPIComponent = spi_ns.class_("SPIComponent", cg.Component)
|
||||||
SPIDevice = spi_ns.class_("SPIDevice")
|
SPIDevice = spi_ns.class_("SPIDevice")
|
||||||
@@ -54,6 +54,21 @@ CONF_FORCE_SW = "force_sw"
|
|||||||
CONF_INTERFACE = "interface"
|
CONF_INTERFACE = "interface"
|
||||||
CONF_INTERFACE_INDEX = "interface_index"
|
CONF_INTERFACE_INDEX = "interface_index"
|
||||||
|
|
||||||
|
# RP2040 SPI pin assignments are complicated. Refer to https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
|
||||||
|
|
||||||
|
RP_SPI_PINSETS = [
|
||||||
|
{
|
||||||
|
CONF_MISO_PIN: [0, 4, 16, 20, -1],
|
||||||
|
CONF_CLK_PIN: [2, 6, 18, 22],
|
||||||
|
CONF_MOSI_PIN: [3, 7, 19, 23, -1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CONF_MISO_PIN: [8, 12, 24, 28, -1],
|
||||||
|
CONF_CLK_PIN: [10, 14, 26],
|
||||||
|
CONF_MOSI_PIN: [11, 23, 27, -1],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_target_platform():
|
def get_target_platform():
|
||||||
return (
|
return (
|
||||||
@@ -85,7 +100,7 @@ def get_hw_interface_list():
|
|||||||
return [["spi", "spi2"]]
|
return [["spi", "spi2"]]
|
||||||
return [["spi", "spi2"], ["spi3"]]
|
return [["spi", "spi2"], ["spi3"]]
|
||||||
if target_platform == "rp2040":
|
if target_platform == "rp2040":
|
||||||
return [["spi"]]
|
return [["spi"], ["spi1"]]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
@@ -99,8 +114,10 @@ def get_spi_index(name):
|
|||||||
|
|
||||||
|
|
||||||
# Check that pins are suitable for HW spi
|
# Check that pins are suitable for HW spi
|
||||||
|
# \param spi the config data for the spi instance
|
||||||
|
# \param index the selected hw interface number, -1 if not yet known
|
||||||
# TODO verify that the pins are internal
|
# TODO verify that the pins are internal
|
||||||
def validate_hw_pins(spi):
|
def validate_hw_pins(spi, index=-1):
|
||||||
clk_pin = spi[CONF_CLK_PIN]
|
clk_pin = spi[CONF_CLK_PIN]
|
||||||
if clk_pin[CONF_INVERTED]:
|
if clk_pin[CONF_INVERTED]:
|
||||||
return False
|
return False
|
||||||
@@ -129,9 +146,30 @@ def validate_hw_pins(spi):
|
|||||||
if target_platform == "esp32":
|
if target_platform == "esp32":
|
||||||
return clk_pin_no >= 0
|
return clk_pin_no >= 0
|
||||||
|
|
||||||
|
if target_platform == "rp2040":
|
||||||
|
pin_set = (
|
||||||
|
list(filter(lambda s: clk_pin_no in s[CONF_CLK_PIN], RP_SPI_PINSETS))[0]
|
||||||
|
if index == -1
|
||||||
|
else RP_SPI_PINSETS[index]
|
||||||
|
)
|
||||||
|
if pin_set is None:
|
||||||
|
return False
|
||||||
|
if sdo_pin_no not in pin_set[CONF_MOSI_PIN]:
|
||||||
|
return False
|
||||||
|
if sdi_pin_no not in pin_set[CONF_MISO_PIN]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_hw_spi(config, available):
|
||||||
|
"""Get an available hardware spi interface suitable for this config"""
|
||||||
|
matching = list(filter(lambda idx: validate_hw_pins(config, idx), available))
|
||||||
|
if len(matching) != 0:
|
||||||
|
return matching[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def validate_spi_config(config):
|
def validate_spi_config(config):
|
||||||
available = list(range(len(get_hw_interface_list())))
|
available = list(range(len(get_hw_interface_list())))
|
||||||
for spi in config:
|
for spi in config:
|
||||||
@@ -147,9 +185,10 @@ def validate_spi_config(config):
|
|||||||
if not validate_hw_pins(spi):
|
if not validate_hw_pins(spi):
|
||||||
spi[CONF_INTERFACE] = "software"
|
spi[CONF_INTERFACE] = "software"
|
||||||
elif interface == "hardware":
|
elif interface == "hardware":
|
||||||
if len(available) == 0:
|
index = get_hw_spi(spi, available)
|
||||||
raise cv.Invalid("No hardware interface available")
|
if index is None:
|
||||||
index = spi[CONF_INTERFACE_INDEX] = available[0]
|
raise cv.Invalid("No suitable hardware interface available")
|
||||||
|
spi[CONF_INTERFACE_INDEX] = index
|
||||||
available.remove(index)
|
available.remove(index)
|
||||||
else:
|
else:
|
||||||
# Must be a specific name
|
# Must be a specific name
|
||||||
@@ -164,11 +203,14 @@ def validate_spi_config(config):
|
|||||||
# Any specific names and any 'hardware' requests will have already been filled,
|
# Any specific names and any 'hardware' requests will have already been filled,
|
||||||
# so just need to assign remaining hardware to 'any' requests.
|
# so just need to assign remaining hardware to 'any' requests.
|
||||||
for spi in config:
|
for spi in config:
|
||||||
if spi[CONF_INTERFACE] == "any" and len(available) != 0:
|
if spi[CONF_INTERFACE] == "any":
|
||||||
index = available[0]
|
index = get_hw_spi(spi, available)
|
||||||
spi[CONF_INTERFACE_INDEX] = index
|
if index is not None:
|
||||||
available.remove(index)
|
spi[CONF_INTERFACE_INDEX] = index
|
||||||
if CONF_INTERFACE_INDEX in spi and not validate_hw_pins(spi):
|
available.remove(index)
|
||||||
|
if CONF_INTERFACE_INDEX in spi and not validate_hw_pins(
|
||||||
|
spi, spi[CONF_INTERFACE_INDEX]
|
||||||
|
):
|
||||||
raise cv.Invalid("Invalid pin selections for hardware SPI interface")
|
raise cv.Invalid("Invalid pin selections for hardware SPI interface")
|
||||||
|
|
||||||
return config
|
return config
|
||||||
@@ -181,13 +223,13 @@ def get_spi_interface(index):
|
|||||||
# Arduino code follows
|
# Arduino code follows
|
||||||
platform = get_target_platform()
|
platform = get_target_platform()
|
||||||
if platform == "rp2040":
|
if platform == "rp2040":
|
||||||
return "&spi1"
|
return ["&SPI", "&SPI1"][index]
|
||||||
if index == 0:
|
if index == 0:
|
||||||
return "&SPI"
|
return "&SPI"
|
||||||
# Following code can't apply to C2, H2 or 8266 since they have only one SPI
|
# Following code can't apply to C2, H2 or 8266 since they have only one SPI
|
||||||
if get_target_variant() in (VARIANT_ESP32S3, VARIANT_ESP32S2):
|
if get_target_variant() in (VARIANT_ESP32S3, VARIANT_ESP32S2):
|
||||||
return "new SPIClass(FSPI)"
|
return "new SPIClass(FSPI)"
|
||||||
return "return new SPIClass(HSPI)"
|
return "new SPIClass(HSPI)"
|
||||||
|
|
||||||
|
|
||||||
SPI_SCHEMA = cv.All(
|
SPI_SCHEMA = cv.All(
|
||||||
|
|||||||
@@ -248,6 +248,7 @@ class SPIDelegateDummy : public SPIDelegate {
|
|||||||
SPIDelegateDummy() = default;
|
SPIDelegateDummy() = default;
|
||||||
|
|
||||||
uint8_t transfer(uint8_t data) override { return 0; }
|
uint8_t transfer(uint8_t data) override { return 0; }
|
||||||
|
void end_transaction() override{};
|
||||||
|
|
||||||
void begin_transaction() override;
|
void begin_transaction() override;
|
||||||
};
|
};
|
||||||
@@ -351,6 +352,7 @@ class SPIClient {
|
|||||||
: bit_order_(bit_order), mode_(mode), data_rate_(data_rate) {}
|
: bit_order_(bit_order), mode_(mode), data_rate_(data_rate) {}
|
||||||
|
|
||||||
virtual void spi_setup() {
|
virtual void spi_setup() {
|
||||||
|
esph_log_d("spi_device", "mode %u, data_rate %ukHz", (unsigned) this->mode_, (unsigned) (this->data_rate_ / 1000));
|
||||||
this->delegate_ = this->parent_->register_device(this, this->mode_, this->bit_order_, this->data_rate_, this->cs_);
|
this->delegate_ = this->parent_->register_device(this, this->mode_, this->bit_order_, this->data_rate_, this->cs_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,10 +400,7 @@ class SPIDevice : public SPIClient {
|
|||||||
|
|
||||||
void set_data_rate(uint32_t data_rate) { this->data_rate_ = data_rate; }
|
void set_data_rate(uint32_t data_rate) { this->data_rate_ = data_rate; }
|
||||||
|
|
||||||
void set_bit_order(SPIBitOrder order) {
|
void set_bit_order(SPIBitOrder order) { this->bit_order_ = order; }
|
||||||
this->bit_order_ = order;
|
|
||||||
esph_log_d("spi.h", "bit order set to %d", order);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_mode(SPIMode mode) { this->mode_ = mode; }
|
void set_mode(SPIMode mode) { this->mode_ = mode; }
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ class SPIDelegateHw : public SPIDelegate {
|
|||||||
void begin_transaction() override {
|
void begin_transaction() override {
|
||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
SPISettings const settings(this->data_rate_, static_cast<BitOrder>(this->bit_order_), this->mode_);
|
SPISettings const settings(this->data_rate_, static_cast<BitOrder>(this->bit_order_), this->mode_);
|
||||||
|
#elif defined(ESP8266)
|
||||||
|
// Arduino ESP8266 library has mangled values for SPI modes :-(
|
||||||
|
auto mode = (this->mode_ & 0x01) + ((this->mode_ & 0x02) << 3);
|
||||||
|
ESP_LOGV(TAG, "8266 mangled SPI mode 0x%X", mode);
|
||||||
|
SPISettings const settings(this->data_rate_, this->bit_order_, mode);
|
||||||
#else
|
#else
|
||||||
SPISettings const settings(this->data_rate_, this->bit_order_, this->mode_);
|
SPISettings const settings(this->data_rate_, this->bit_order_, this->mode_);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -986,6 +986,7 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) {
|
|||||||
// Fire any preset changed trigger if defined
|
// Fire any preset changed trigger if defined
|
||||||
Trigger<> *trig = this->preset_change_trigger_;
|
Trigger<> *trig = this->preset_change_trigger_;
|
||||||
assert(trig != nullptr);
|
assert(trig != nullptr);
|
||||||
|
this->preset = preset;
|
||||||
trig->trigger();
|
trig->trigger();
|
||||||
|
|
||||||
this->refresh();
|
this->refresh();
|
||||||
@@ -1010,6 +1011,7 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset)
|
|||||||
// Fire any preset changed trigger if defined
|
// Fire any preset changed trigger if defined
|
||||||
Trigger<> *trig = this->preset_change_trigger_;
|
Trigger<> *trig = this->preset_change_trigger_;
|
||||||
assert(trig != nullptr);
|
assert(trig != nullptr);
|
||||||
|
this->custom_preset = custom_preset;
|
||||||
trig->trigger();
|
trig->trigger();
|
||||||
|
|
||||||
this->refresh();
|
this->refresh();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from esphome.const import (
|
|||||||
CONF_NUMBER_DATAPOINT,
|
CONF_NUMBER_DATAPOINT,
|
||||||
CONF_MAX_VALUE,
|
CONF_MAX_VALUE,
|
||||||
CONF_MIN_VALUE,
|
CONF_MIN_VALUE,
|
||||||
|
CONF_MULTIPLY,
|
||||||
CONF_STEP,
|
CONF_STEP,
|
||||||
)
|
)
|
||||||
from .. import tuya_ns, CONF_TUYA_ID, Tuya
|
from .. import tuya_ns, CONF_TUYA_ID, Tuya
|
||||||
@@ -31,6 +32,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Required(CONF_MAX_VALUE): cv.float_,
|
cv.Required(CONF_MAX_VALUE): cv.float_,
|
||||||
cv.Required(CONF_MIN_VALUE): cv.float_,
|
cv.Required(CONF_MIN_VALUE): cv.float_,
|
||||||
cv.Required(CONF_STEP): cv.positive_float,
|
cv.Required(CONF_STEP): cv.positive_float,
|
||||||
|
cv.Optional(CONF_MULTIPLY, default=1.0): cv.float_,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.COMPONENT_SCHEMA),
|
.extend(cv.COMPONENT_SCHEMA),
|
||||||
@@ -49,7 +51,8 @@ async def to_code(config):
|
|||||||
step=config[CONF_STEP],
|
step=config[CONF_STEP],
|
||||||
)
|
)
|
||||||
|
|
||||||
paren = await cg.get_variable(config[CONF_TUYA_ID])
|
cg.add(var.set_write_multiply(config[CONF_MULTIPLY]))
|
||||||
cg.add(var.set_tuya_parent(paren))
|
parent = await cg.get_variable(config[CONF_TUYA_ID])
|
||||||
|
cg.add(var.set_tuya_parent(parent))
|
||||||
|
|
||||||
cg.add(var.set_number_id(config[CONF_NUMBER_DATAPOINT]))
|
cg.add(var.set_number_id(config[CONF_NUMBER_DATAPOINT]))
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ void TuyaNumber::setup() {
|
|||||||
this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) {
|
this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) {
|
||||||
if (datapoint.type == TuyaDatapointType::INTEGER) {
|
if (datapoint.type == TuyaDatapointType::INTEGER) {
|
||||||
ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int);
|
ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int);
|
||||||
this->publish_state(datapoint.value_int);
|
this->publish_state(datapoint.value_int / multiply_by_);
|
||||||
} else if (datapoint.type == TuyaDatapointType::ENUM) {
|
} else if (datapoint.type == TuyaDatapointType::ENUM) {
|
||||||
ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum);
|
ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum);
|
||||||
this->publish_state(datapoint.value_enum);
|
this->publish_state(datapoint.value_enum);
|
||||||
@@ -22,7 +22,8 @@ void TuyaNumber::setup() {
|
|||||||
void TuyaNumber::control(float value) {
|
void TuyaNumber::control(float value) {
|
||||||
ESP_LOGV(TAG, "Setting number %u: %f", this->number_id_, value);
|
ESP_LOGV(TAG, "Setting number %u: %f", this->number_id_, value);
|
||||||
if (this->type_ == TuyaDatapointType::INTEGER) {
|
if (this->type_ == TuyaDatapointType::INTEGER) {
|
||||||
this->parent_->set_integer_datapoint_value(this->number_id_, value);
|
int integer_value = lround(value * multiply_by_);
|
||||||
|
this->parent_->set_integer_datapoint_value(this->number_id_, integer_value);
|
||||||
} else if (this->type_ == TuyaDatapointType::ENUM) {
|
} else if (this->type_ == TuyaDatapointType::ENUM) {
|
||||||
this->parent_->set_enum_datapoint_value(this->number_id_, value);
|
this->parent_->set_enum_datapoint_value(this->number_id_, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class TuyaNumber : public number::Number, public Component {
|
|||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
void set_number_id(uint8_t number_id) { this->number_id_ = number_id; }
|
void set_number_id(uint8_t number_id) { this->number_id_ = number_id; }
|
||||||
|
void set_write_multiply(float factor) { multiply_by_ = factor; }
|
||||||
|
|
||||||
void set_tuya_parent(Tuya *parent) { this->parent_ = parent; }
|
void set_tuya_parent(Tuya *parent) { this->parent_ = parent; }
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ class TuyaNumber : public number::Number, public Component {
|
|||||||
|
|
||||||
Tuya *parent_;
|
Tuya *parent_;
|
||||||
uint8_t number_id_{0};
|
uint8_t number_id_{0};
|
||||||
|
float multiply_by_{1.0};
|
||||||
TuyaDatapointType type_{};
|
TuyaDatapointType type_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1561,6 +1561,23 @@ void WaveshareEPaper7P5In::dump_config() {
|
|||||||
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
bool WaveshareEPaper7P5InV2::wait_until_idle_() {
|
||||||
|
if (this->busy_pin_ == nullptr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t start = millis();
|
||||||
|
while (this->busy_pin_->digital_read()) {
|
||||||
|
this->command(0x71);
|
||||||
|
if (millis() - start > this->idle_timeout_()) {
|
||||||
|
ESP_LOGE(TAG, "Timeout while displaying image!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
App.feed_wdt();
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
void WaveshareEPaper7P5InV2::initialize() {
|
void WaveshareEPaper7P5InV2::initialize() {
|
||||||
// COMMAND POWER SETTING
|
// COMMAND POWER SETTING
|
||||||
this->command(0x01);
|
this->command(0x01);
|
||||||
@@ -1568,10 +1585,21 @@ void WaveshareEPaper7P5InV2::initialize() {
|
|||||||
this->data(0x07);
|
this->data(0x07);
|
||||||
this->data(0x3f);
|
this->data(0x3f);
|
||||||
this->data(0x3f);
|
this->data(0x3f);
|
||||||
this->command(0x04);
|
|
||||||
|
// We don't want the display to be powered at this point
|
||||||
|
|
||||||
delay(100); // NOLINT
|
delay(100); // NOLINT
|
||||||
this->wait_until_idle_();
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// COMMAND VCOM AND DATA INTERVAL SETTING
|
||||||
|
this->command(0x50);
|
||||||
|
this->data(0x10);
|
||||||
|
this->data(0x07);
|
||||||
|
|
||||||
|
// COMMAND TCON SETTING
|
||||||
|
this->command(0x60);
|
||||||
|
this->data(0x22);
|
||||||
|
|
||||||
// COMMAND PANEL SETTING
|
// COMMAND PANEL SETTING
|
||||||
this->command(0x00);
|
this->command(0x00);
|
||||||
this->data(0x1F);
|
this->data(0x1F);
|
||||||
@@ -1582,19 +1610,30 @@ void WaveshareEPaper7P5InV2::initialize() {
|
|||||||
this->data(0x20);
|
this->data(0x20);
|
||||||
this->data(0x01);
|
this->data(0x01);
|
||||||
this->data(0xE0);
|
this->data(0xE0);
|
||||||
// COMMAND ...?
|
|
||||||
|
// COMMAND DUAL SPI MM_EN, DUSPI_EN
|
||||||
this->command(0x15);
|
this->command(0x15);
|
||||||
this->data(0x00);
|
this->data(0x00);
|
||||||
// COMMAND VCOM AND DATA INTERVAL SETTING
|
|
||||||
this->command(0x50);
|
// COMMAND POWER DRIVER HAT DOWN
|
||||||
this->data(0x10);
|
// This command will turn off booster, controller, source driver, gate driver, VCOM, and
|
||||||
this->data(0x07);
|
// temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode.
|
||||||
// COMMAND TCON SETTING
|
// Source/Gate/Border/VCOM will be released to floating.
|
||||||
this->command(0x60);
|
this->command(0x02);
|
||||||
this->data(0x22);
|
|
||||||
}
|
}
|
||||||
void HOT WaveshareEPaper7P5InV2::display() {
|
void HOT WaveshareEPaper7P5InV2::display() {
|
||||||
uint32_t buf_len = this->get_buffer_length_();
|
uint32_t buf_len = this->get_buffer_length_();
|
||||||
|
|
||||||
|
// COMMAND POWER ON
|
||||||
|
ESP_LOGI(TAG, "Power on the display and hat");
|
||||||
|
|
||||||
|
// This command will turn on booster, controller, regulators, and temperature sensor will be
|
||||||
|
// activated for one-time sensing before enabling booster. When all voltages are ready, the
|
||||||
|
// BUSY_N signal will return to high.
|
||||||
|
this->command(0x04);
|
||||||
|
delay(200); // NOLINT
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
// COMMAND DATA START TRANSMISSION NEW DATA
|
// COMMAND DATA START TRANSMISSION NEW DATA
|
||||||
this->command(0x13);
|
this->command(0x13);
|
||||||
delay(2);
|
delay(2);
|
||||||
@@ -1602,14 +1641,23 @@ void HOT WaveshareEPaper7P5InV2::display() {
|
|||||||
this->data(~(this->buffer_[i]));
|
this->data(~(this->buffer_[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delay(100); // NOLINT
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
// COMMAND DISPLAY REFRESH
|
// COMMAND DISPLAY REFRESH
|
||||||
this->command(0x12);
|
this->command(0x12);
|
||||||
delay(100); // NOLINT
|
delay(100); // NOLINT
|
||||||
this->wait_until_idle_();
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
|
||||||
|
this->command(0x02);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
ESP_LOGV(TAG, "After command(0x02) (>> power off)");
|
||||||
}
|
}
|
||||||
|
|
||||||
int WaveshareEPaper7P5InV2::get_width_internal() { return 800; }
|
int WaveshareEPaper7P5InV2::get_width_internal() { return 800; }
|
||||||
int WaveshareEPaper7P5InV2::get_height_internal() { return 480; }
|
int WaveshareEPaper7P5InV2::get_height_internal() { return 480; }
|
||||||
|
uint32_t WaveshareEPaper7P5InV2::idle_timeout_() { return 10000; }
|
||||||
void WaveshareEPaper7P5InV2::dump_config() {
|
void WaveshareEPaper7P5InV2::dump_config() {
|
||||||
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
||||||
ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");
|
ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");
|
||||||
|
|||||||
@@ -472,6 +472,8 @@ class WaveshareEPaper7P5InBC : public WaveshareEPaper {
|
|||||||
|
|
||||||
class WaveshareEPaper7P5InV2 : public WaveshareEPaper {
|
class WaveshareEPaper7P5InV2 : public WaveshareEPaper {
|
||||||
public:
|
public:
|
||||||
|
bool wait_until_idle_();
|
||||||
|
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
|
|
||||||
void display() override;
|
void display() override;
|
||||||
@@ -491,6 +493,8 @@ class WaveshareEPaper7P5InV2 : public WaveshareEPaper {
|
|||||||
int get_width_internal() override;
|
int get_width_internal() override;
|
||||||
|
|
||||||
int get_height_internal() override;
|
int get_height_internal() override;
|
||||||
|
|
||||||
|
uint32_t idle_timeout_() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WaveshareEPaper7P5InV2alt : public WaveshareEPaper7P5InV2 {
|
class WaveshareEPaper7P5InV2alt : public WaveshareEPaper7P5InV2 {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(WebServer),
|
cv.GenerateID(): cv.declare_id(WebServer),
|
||||||
cv.Optional(CONF_PORT, default=80): cv.port,
|
cv.Optional(CONF_PORT, default=80): cv.port,
|
||||||
cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2),
|
cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True),
|
||||||
cv.Optional(CONF_CSS_URL): cv.string,
|
cv.Optional(CONF_CSS_URL): cv.string,
|
||||||
cv.Optional(CONF_CSS_INCLUDE): cv.file_,
|
cv.Optional(CONF_CSS_INCLUDE): cv.file_,
|
||||||
cv.Optional(CONF_JS_URL): cv.string,
|
cv.Optional(CONF_JS_URL): cv.string,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const uint8_t WHIRLPOOL_SWING_MASK = 128;
|
|||||||
const uint8_t WHIRLPOOL_POWER = 0x04;
|
const uint8_t WHIRLPOOL_POWER = 0x04;
|
||||||
|
|
||||||
void WhirlpoolClimate::transmit_state() {
|
void WhirlpoolClimate::transmit_state() {
|
||||||
|
this->last_transmit_time_ = millis(); // setting the time of the last transmission.
|
||||||
uint8_t remote_state[WHIRLPOOL_STATE_LENGTH] = {0};
|
uint8_t remote_state[WHIRLPOOL_STATE_LENGTH] = {0};
|
||||||
remote_state[0] = 0x83;
|
remote_state[0] = 0x83;
|
||||||
remote_state[1] = 0x06;
|
remote_state[1] = 0x06;
|
||||||
@@ -149,6 +150,12 @@ void WhirlpoolClimate::transmit_state() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) {
|
bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||||
|
// Check if the esp isn't currently transmitting.
|
||||||
|
if (millis() - this->last_transmit_time_ < 500) {
|
||||||
|
ESP_LOGV(TAG, "Blocked receive because of current trasmittion");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Validate header
|
// Validate header
|
||||||
if (!data.expect_item(WHIRLPOOL_HEADER_MARK, WHIRLPOOL_HEADER_SPACE)) {
|
if (!data.expect_item(WHIRLPOOL_HEADER_MARK, WHIRLPOOL_HEADER_SPACE)) {
|
||||||
ESP_LOGV(TAG, "Header fail");
|
ESP_LOGV(TAG, "Header fail");
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ class WhirlpoolClimate : public climate_ir::ClimateIR {
|
|||||||
void transmit_state() override;
|
void transmit_state() override;
|
||||||
/// Handle received IR Buffer
|
/// Handle received IR Buffer
|
||||||
bool on_receive(remote_base::RemoteReceiveData data) override;
|
bool on_receive(remote_base::RemoteReceiveData data) override;
|
||||||
|
/// Set the time of the last transmission.
|
||||||
|
int32_t last_transmit_time_{};
|
||||||
|
|
||||||
bool send_swing_cmd_{false};
|
bool send_swing_cmd_{false};
|
||||||
Model model_;
|
Model model_;
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ bool WiFiComponent::wifi_apply_power_save_() {
|
|||||||
power_save = NONE_SLEEP_T;
|
power_save = NONE_SLEEP_T;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
wifi_fpm_auto_sleep_set_in_null_mode(1);
|
||||||
return wifi_set_sleep_type(power_save);
|
return wifi_set_sleep_type(power_save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from esphome.const import (
|
|||||||
CONF_REBOOT_TIMEOUT,
|
CONF_REBOOT_TIMEOUT,
|
||||||
)
|
)
|
||||||
from esphome.components import time
|
from esphome.components import time
|
||||||
|
from esphome.core import TimePeriod
|
||||||
|
|
||||||
CONF_NETMASK = "netmask"
|
CONF_NETMASK = "netmask"
|
||||||
CONF_PRIVATE_KEY = "private_key"
|
CONF_PRIVATE_KEY = "private_key"
|
||||||
@@ -59,9 +60,9 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
cv.Optional(CONF_PEER_ALLOWED_IPS, default=["0.0.0.0/0"]): cv.ensure_list(
|
cv.Optional(CONF_PEER_ALLOWED_IPS, default=["0.0.0.0/0"]): cv.ensure_list(
|
||||||
_cidr_network
|
_cidr_network
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_PEER_PERSISTENT_KEEPALIVE, default=0): cv.Any(
|
cv.Optional(CONF_PEER_PERSISTENT_KEEPALIVE, default="0s"): cv.All(
|
||||||
cv.positive_time_period_seconds,
|
cv.positive_time_period_seconds,
|
||||||
cv.uint16_t,
|
cv.Range(max=TimePeriod(seconds=65535)),
|
||||||
),
|
),
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_REBOOT_TIMEOUT, default="15min"
|
CONF_REBOOT_TIMEOUT, default="15min"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
__version__ = "2023.9.0b1"
|
__version__ = "2023.9.3"
|
||||||
|
|
||||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class SimpleRegistry(dict):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def safe_print(message=""):
|
def safe_print(message="", end="\n"):
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
|
|
||||||
if CORE.dashboard:
|
if CORE.dashboard:
|
||||||
@@ -67,20 +67,26 @@ def safe_print(message=""):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(message)
|
print(message, end=end)
|
||||||
return
|
return
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(message.encode("utf-8", "backslashreplace"))
|
print(message.encode("utf-8", "backslashreplace"), end=end)
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
try:
|
try:
|
||||||
print(message.encode("ascii", "backslashreplace"))
|
print(message.encode("ascii", "backslashreplace"), end=end)
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
print("Cannot print line because of invalid locale!")
|
print("Cannot print line because of invalid locale!")
|
||||||
|
|
||||||
|
|
||||||
|
def safe_input(prompt=""):
|
||||||
|
if prompt:
|
||||||
|
safe_print(prompt, end="")
|
||||||
|
return input()
|
||||||
|
|
||||||
|
|
||||||
def shlex_quote(s):
|
def shlex_quote(s):
|
||||||
if not s:
|
if not s:
|
||||||
return "''"
|
return "''"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from esphome.core import CORE
|
|||||||
from esphome.helpers import get_bool_env, write_file
|
from esphome.helpers import get_bool_env, write_file
|
||||||
from esphome.log import Fore, color
|
from esphome.log import Fore, color
|
||||||
from esphome.storage_json import StorageJSON, ext_storage_path
|
from esphome.storage_json import StorageJSON, ext_storage_path
|
||||||
from esphome.util import safe_print
|
from esphome.util import safe_input, safe_print
|
||||||
|
|
||||||
CORE_BIG = r""" _____ ____ _____ ______
|
CORE_BIG = r""" _____ ____ _____ ______
|
||||||
/ ____/ __ \| __ \| ____|
|
/ ____/ __ \| __ \| ____|
|
||||||
@@ -252,7 +252,7 @@ def safe_print_step(step, big):
|
|||||||
def default_input(text, default):
|
def default_input(text, default):
|
||||||
safe_print()
|
safe_print()
|
||||||
safe_print(f"Press ENTER for default ({default})")
|
safe_print(f"Press ENTER for default ({default})")
|
||||||
return input(text.format(default)) or default
|
return safe_input(text.format(default)) or default
|
||||||
|
|
||||||
|
|
||||||
# From https://stackoverflow.com/a/518232/8924614
|
# From https://stackoverflow.com/a/518232/8924614
|
||||||
@@ -306,7 +306,7 @@ def wizard(path):
|
|||||||
)
|
)
|
||||||
safe_print()
|
safe_print()
|
||||||
sleep(1)
|
sleep(1)
|
||||||
name = input(color(Fore.BOLD_WHITE, "(name): "))
|
name = safe_input(color(Fore.BOLD_WHITE, "(name): "))
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@@ -343,7 +343,9 @@ def wizard(path):
|
|||||||
while True:
|
while True:
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
safe_print()
|
safe_print()
|
||||||
platform = input(color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): "))
|
platform = safe_input(
|
||||||
|
color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): ")
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
platform = vol.All(vol.Upper, vol.Any(*wizard_platforms))(platform.upper())
|
platform = vol.All(vol.Upper, vol.Any(*wizard_platforms))(platform.upper())
|
||||||
break
|
break
|
||||||
@@ -397,7 +399,7 @@ def wizard(path):
|
|||||||
boards.append(board_id)
|
boards.append(board_id)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
board = input(color(Fore.BOLD_WHITE, "(board): "))
|
board = safe_input(color(Fore.BOLD_WHITE, "(board): "))
|
||||||
try:
|
try:
|
||||||
board = vol.All(vol.Lower, vol.Any(*boards))(board)
|
board = vol.All(vol.Lower, vol.Any(*boards))(board)
|
||||||
break
|
break
|
||||||
@@ -423,7 +425,7 @@ def wizard(path):
|
|||||||
sleep(1.5)
|
sleep(1.5)
|
||||||
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".")
|
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".")
|
||||||
while True:
|
while True:
|
||||||
ssid = input(color(Fore.BOLD_WHITE, "(ssid): "))
|
ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): "))
|
||||||
try:
|
try:
|
||||||
ssid = cv.ssid(ssid)
|
ssid = cv.ssid(ssid)
|
||||||
break
|
break
|
||||||
@@ -449,7 +451,7 @@ def wizard(path):
|
|||||||
safe_print()
|
safe_print()
|
||||||
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"")
|
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"")
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
psk = input(color(Fore.BOLD_WHITE, "(PSK): "))
|
psk = safe_input(color(Fore.BOLD_WHITE, "(PSK): "))
|
||||||
safe_print(
|
safe_print(
|
||||||
"Perfect! WiFi is now set up (you can create static IPs and so on later)."
|
"Perfect! WiFi is now set up (you can create static IPs and so on later)."
|
||||||
)
|
)
|
||||||
@@ -466,7 +468,7 @@ def wizard(path):
|
|||||||
safe_print()
|
safe_print()
|
||||||
sleep(0.25)
|
sleep(0.25)
|
||||||
safe_print("Press ENTER for no password")
|
safe_print("Press ENTER for no password")
|
||||||
password = input(color(Fore.BOLD_WHITE, "(password): "))
|
password = safe_input(color(Fore.BOLD_WHITE, "(password): "))
|
||||||
|
|
||||||
if not wizard_write(
|
if not wizard_write(
|
||||||
path=path,
|
path=path,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ esptool==4.6.2
|
|||||||
click==8.1.7
|
click==8.1.7
|
||||||
esphome-dashboard==20230904.0
|
esphome-dashboard==20230904.0
|
||||||
aioesphomeapi==15.0.0
|
aioesphomeapi==15.0.0
|
||||||
zeroconf==0.108.0
|
zeroconf==0.115.1
|
||||||
|
|
||||||
# esp-idf requires this, but doesn't bundle it by default
|
# esp-idf requires this, but doesn't bundle it by default
|
||||||
# https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24
|
# https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24
|
||||||
|
|||||||
@@ -2972,6 +2972,7 @@ display:
|
|||||||
model: TFT 2.4
|
model: TFT 2.4
|
||||||
cs_pin: GPIO5
|
cs_pin: GPIO5
|
||||||
dc_pin: GPIO4
|
dc_pin: GPIO4
|
||||||
|
color_palette: GRAYSCALE
|
||||||
reset_pin: GPIO22
|
reset_pin: GPIO22
|
||||||
lambda: |-
|
lambda: |-
|
||||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|||||||
@@ -667,6 +667,7 @@ matrix_keypad:
|
|||||||
- pin: 17
|
- pin: 17
|
||||||
- pin: 16
|
- pin: 16
|
||||||
keys: "1234"
|
keys: "1234"
|
||||||
|
has_pulldowns: true
|
||||||
|
|
||||||
key_collector:
|
key_collector:
|
||||||
- id: reader
|
- id: reader
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ switch:
|
|||||||
output: pin_4
|
output: pin_4
|
||||||
id: pin_4_switch
|
id: pin_4_switch
|
||||||
|
|
||||||
|
|
||||||
|
spi: # Pins are for SPI1 on the RP2040 Pico-W
|
||||||
|
miso_pin: 8
|
||||||
|
clk_pin: 10
|
||||||
|
mosi_pin: 11
|
||||||
|
id: spi_0
|
||||||
|
interface: hardware
|
||||||
|
|
||||||
#light:
|
#light:
|
||||||
# - platform: rp2040_pio_led_strip
|
# - platform: rp2040_pio_led_strip
|
||||||
# id: led_strip
|
# id: led_strip
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ def test_wizard_accepts_default_answers_esp8266(tmpdir, monkeypatch, wizard_answ
|
|||||||
config_file = tmpdir.join("test.yaml")
|
config_file = tmpdir.join("test.yaml")
|
||||||
input_mock = MagicMock(side_effect=wizard_answers)
|
input_mock = MagicMock(side_effect=wizard_answers)
|
||||||
monkeypatch.setattr("builtins.input", input_mock)
|
monkeypatch.setattr("builtins.input", input_mock)
|
||||||
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0)
|
monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
|
||||||
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
||||||
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
||||||
|
|
||||||
@@ -341,7 +341,7 @@ def test_wizard_accepts_default_answers_esp32(tmpdir, monkeypatch, wizard_answer
|
|||||||
config_file = tmpdir.join("test.yaml")
|
config_file = tmpdir.join("test.yaml")
|
||||||
input_mock = MagicMock(side_effect=wizard_answers)
|
input_mock = MagicMock(side_effect=wizard_answers)
|
||||||
monkeypatch.setattr("builtins.input", input_mock)
|
monkeypatch.setattr("builtins.input", input_mock)
|
||||||
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0)
|
monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
|
||||||
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
||||||
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
||||||
|
|
||||||
@@ -371,7 +371,7 @@ def test_wizard_offers_better_node_name(tmpdir, monkeypatch, wizard_answers):
|
|||||||
config_file = tmpdir.join("test.yaml")
|
config_file = tmpdir.join("test.yaml")
|
||||||
input_mock = MagicMock(side_effect=wizard_answers)
|
input_mock = MagicMock(side_effect=wizard_answers)
|
||||||
monkeypatch.setattr("builtins.input", input_mock)
|
monkeypatch.setattr("builtins.input", input_mock)
|
||||||
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0)
|
monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
|
||||||
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
||||||
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
||||||
|
|
||||||
@@ -394,7 +394,7 @@ def test_wizard_requires_correct_platform(tmpdir, monkeypatch, wizard_answers):
|
|||||||
config_file = tmpdir.join("test.yaml")
|
config_file = tmpdir.join("test.yaml")
|
||||||
input_mock = MagicMock(side_effect=wizard_answers)
|
input_mock = MagicMock(side_effect=wizard_answers)
|
||||||
monkeypatch.setattr("builtins.input", input_mock)
|
monkeypatch.setattr("builtins.input", input_mock)
|
||||||
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0)
|
monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
|
||||||
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
||||||
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
||||||
|
|
||||||
@@ -416,7 +416,7 @@ def test_wizard_requires_correct_board(tmpdir, monkeypatch, wizard_answers):
|
|||||||
config_file = tmpdir.join("test.yaml")
|
config_file = tmpdir.join("test.yaml")
|
||||||
input_mock = MagicMock(side_effect=wizard_answers)
|
input_mock = MagicMock(side_effect=wizard_answers)
|
||||||
monkeypatch.setattr("builtins.input", input_mock)
|
monkeypatch.setattr("builtins.input", input_mock)
|
||||||
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0)
|
monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
|
||||||
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
||||||
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
||||||
|
|
||||||
@@ -438,7 +438,7 @@ def test_wizard_requires_valid_ssid(tmpdir, monkeypatch, wizard_answers):
|
|||||||
config_file = tmpdir.join("test.yaml")
|
config_file = tmpdir.join("test.yaml")
|
||||||
input_mock = MagicMock(side_effect=wizard_answers)
|
input_mock = MagicMock(side_effect=wizard_answers)
|
||||||
monkeypatch.setattr("builtins.input", input_mock)
|
monkeypatch.setattr("builtins.input", input_mock)
|
||||||
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0)
|
monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
|
||||||
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
monkeypatch.setattr(wz, "sleep", lambda _: 0)
|
||||||
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
monkeypatch.setattr(wz, "wizard_write", MagicMock())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user