Merge branch 'dev' into 20240731-store-api-key-in-prefs

This commit is contained in:
Jesse Hills 2024-08-30 14:32:11 +12:00 committed by GitHub
commit cafc7578b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
74 changed files with 345 additions and 289 deletions

View file

@ -17,7 +17,7 @@ runs:
steps:
- name: Set up Python ${{ inputs.python-version }}
id: python
uses: actions/setup-python@v5.1.1
uses: actions/setup-python@v5.2.0
with:
python-version: ${{ inputs.python-version }}
- name: Restore Python virtual environment

View file

@ -23,7 +23,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4.1.7
- name: Set up Python
uses: actions/setup-python@v5.1.0
uses: actions/setup-python@v5.2.0
with:
python-version: "3.11"

View file

@ -42,7 +42,7 @@ jobs:
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Python
uses: actions/setup-python@v5.1.0
uses: actions/setup-python@v5.2.0
with:
python-version: "3.9"
- name: Set up Docker Buildx

View file

@ -41,7 +41,7 @@ jobs:
run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v5.1.0
uses: actions/setup-python@v5.2.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment

View file

@ -53,7 +53,7 @@ jobs:
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Python
uses: actions/setup-python@v5.1.0
uses: actions/setup-python@v5.2.0
with:
python-version: "3.x"
- name: Set up python environment
@ -85,7 +85,7 @@ jobs:
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Python
uses: actions/setup-python@v5.1.0
uses: actions/setup-python@v5.2.0
with:
python-version: "3.9"

View file

@ -22,7 +22,7 @@ jobs:
path: lib/home-assistant
- name: Setup Python
uses: actions/setup-python@v5.1.0
uses: actions/setup-python@v5.2.0
with:
python-version: 3.12

View file

@ -1,18 +1,23 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
import esphome.codegen as cg
from esphome.components import canbus
from esphome.const import CONF_ID, CONF_RX_PIN, CONF_TX_PIN
from esphome.components.canbus import CanbusComponent, CanSpeed, CONF_BIT_RATE
from esphome.components.canbus import CONF_BIT_RATE, CanbusComponent, CanSpeed
from esphome.components.esp32 import get_esp32_variant
from esphome.components.esp32.const import (
VARIANT_ESP32,
VARIANT_ESP32S2,
VARIANT_ESP32S3,
VARIANT_ESP32C3,
VARIANT_ESP32C6,
VARIANT_ESP32H2,
VARIANT_ESP32S2,
VARIANT_ESP32S3,
)
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_RX_PIN,
CONF_RX_QUEUE_LEN,
CONF_TX_PIN,
CONF_TX_QUEUE_LEN,
)
CODEOWNERS = ["@Sympatron"]
@ -77,6 +82,8 @@ CONFIG_SCHEMA = canbus.CANBUS_SCHEMA.extend(
cv.Optional(CONF_BIT_RATE, default="125KBPS"): validate_bit_rate,
cv.Required(CONF_RX_PIN): pins.internal_gpio_input_pin_number,
cv.Required(CONF_TX_PIN): pins.internal_gpio_output_pin_number,
cv.Optional(CONF_RX_QUEUE_LEN): cv.uint32_t,
cv.Optional(CONF_TX_QUEUE_LEN): cv.uint32_t,
}
)
@ -87,3 +94,7 @@ async def to_code(config):
cg.add(var.set_rx(config[CONF_RX_PIN]))
cg.add(var.set_tx(config[CONF_TX_PIN]))
if (rx_queue_len := config.get(CONF_RX_QUEUE_LEN)) is not None:
cg.add(var.set_rx_queue_len(rx_queue_len))
if (tx_queue_len := config.get(CONF_TX_QUEUE_LEN)) is not None:
cg.add(var.set_tx_queue_len(tx_queue_len))

View file

@ -69,6 +69,13 @@ static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config
bool ESP32Can::setup_internal() {
twai_general_config_t g_config =
TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, TWAI_MODE_NORMAL);
if (this->tx_queue_len_.has_value()) {
g_config.tx_queue_len = this->tx_queue_len_.value();
}
if (this->rx_queue_len_.has_value()) {
g_config.rx_queue_len = this->rx_queue_len_.value();
}
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
twai_timing_config_t t_config;

View file

@ -12,6 +12,8 @@ class ESP32Can : public canbus::Canbus {
public:
void set_rx(int rx) { rx_ = rx; }
void set_tx(int tx) { tx_ = tx; }
void set_tx_queue_len(uint32_t tx_queue_len) { this->tx_queue_len_ = tx_queue_len; }
void set_rx_queue_len(uint32_t rx_queue_len) { this->rx_queue_len_ = rx_queue_len; }
ESP32Can(){};
protected:
@ -21,6 +23,8 @@ class ESP32Can : public canbus::Canbus {
int rx_{-1};
int tx_{-1};
optional<uint32_t> tx_queue_len_{};
optional<uint32_t> rx_queue_len_{};
};
} // namespace esp32_can

View file

@ -1,11 +1,10 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
import esphome.codegen as cg
from esphome.components import i2c, touchscreen
from esphome.const import CONF_INTERRUPT_PIN, CONF_ID
from .. import gt911_ns
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN
from .. import gt911_ns
GT911ButtonListener = gt911_ns.class_("GT911ButtonListener")
GT911Touchscreen = gt911_ns.class_(
@ -18,6 +17,7 @@ CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(GT911Touchscreen),
cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
}
).extend(i2c.i2c_device_schema(0x5D))
@ -29,3 +29,5 @@ async def to_code(config):
if interrupt_pin := config.get(CONF_INTERRUPT_PIN):
cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin)))
if reset_pin := config.get(CONF_RESET_PIN):
cg.add(var.set_reset_pin(await cg.gpio_pin_expression(reset_pin)))

View file

@ -26,6 +26,23 @@ static const size_t MAX_BUTTONS = 4; // max number of buttons scanned
void GT911Touchscreen::setup() {
i2c::ErrorCode err;
ESP_LOGCONFIG(TAG, "Setting up GT911 Touchscreen...");
if (this->reset_pin_ != nullptr) {
this->reset_pin_->setup();
this->reset_pin_->digital_write(false);
if (this->interrupt_pin_ != nullptr) {
// The interrupt pin is used as an input during reset to select the I2C address.
this->interrupt_pin_->pin_mode(gpio::FLAG_OUTPUT);
this->interrupt_pin_->setup();
this->interrupt_pin_->digital_write(false);
}
delay(2);
this->reset_pin_->digital_write(true);
delay(50); // NOLINT
if (this->interrupt_pin_ != nullptr) {
this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT);
this->interrupt_pin_->setup();
}
}
// check the configuration of the int line.
uint8_t data[4];

View file

@ -19,12 +19,14 @@ class GT911Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
void dump_config() override;
void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; }
void register_button_listener(GT911ButtonListener *listener) { this->button_listeners_.push_back(listener); }
protected:
void update_touches() override;
InternalGPIOPin *interrupt_pin_{};
GPIOPin *reset_pin_{};
std::vector<GT911ButtonListener *> button_listeners_;
uint8_t button_state_{0xFF}; // last button state. Initial FF guarantees first update.
};

View file

@ -327,6 +327,8 @@ CONFIG_SCHEMA = (
{
cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments,
cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments,
cv.Optional(df.CONF_PAD_ROW): lvalid.pixels,
cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels,
}
)
),

View file

@ -52,9 +52,7 @@ opacity = LValidator(opacity_validator, uint32, retmapper=literal)
def color(value):
if value == SCHEMA_EXTRACT:
return ["hex color value", "color ID"]
if isinstance(value, int):
return value
return cv.use_id(ColorStruct)(value)
return cv.Any(cv.int_, cv.use_id(ColorStruct))(value)
def color_retmapper(value):
@ -82,10 +80,10 @@ def pixels_or_percent_validator(value):
"""A length in one axis - either a number (pixels) or a percentage"""
if value == SCHEMA_EXTRACT:
return ["pixels", "..%"]
value = cv.Any(cv.int_, cv.percentage)(value)
if isinstance(value, int):
return cv.int_(value)
# Will throw an exception if not a percentage.
return f"lv_pct({int(cv.percentage(value) * 100)})"
return value
return f"lv_pct({int(value * 100)})"
pixels_or_percent = LValidator(pixels_or_percent_validator, uint32, retmapper=literal)
@ -116,10 +114,7 @@ def size_validator(value):
if value.upper() == "SIZE_CONTENT":
return "LV_SIZE_CONTENT"
raise cv.Invalid("must be 'size_content', a percentage or an integer (pixels)")
if isinstance(value, int):
return cv.int_(value)
# Will throw an exception if not a percentage.
return f"lv_pct({int(cv.percentage(value) * 100)})"
return pixels_or_percent_validator(value)
size = LValidator(size_validator, uint32, retmapper=literal)

View file

@ -359,7 +359,13 @@ LVGL_SCHEMA = cv.Schema(
}
)
ALL_STYLES = {**STYLE_PROPS, **GRID_CELL_SCHEMA, **FLEX_OBJ_SCHEMA}
ALL_STYLES = {
**STYLE_PROPS,
**GRID_CELL_SCHEMA,
**FLEX_OBJ_SCHEMA,
cv.Optional(df.CONF_PAD_ROW): lvalid.pixels,
cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels,
}
def container_validator(schema, widget_type: WidgetType):

View file

@ -13,11 +13,13 @@ from ..defines import (
CONF_KEY_CODE,
CONF_MAIN,
CONF_ONE_CHECKED,
CONF_PAD_COLUMN,
CONF_PAD_ROW,
CONF_ROWS,
CONF_SELECTED,
)
from ..helpers import lvgl_components_required
from ..lv_validation import key_code, lv_bool
from ..lv_validation import key_code, lv_bool, pixels
from ..lvcode import lv, lv_add, lv_expr
from ..schemas import automation_schema
from ..types import (
@ -57,6 +59,8 @@ BUTTONMATRIX_BUTTON_SCHEMA = cv.Schema(
BUTTONMATRIX_SCHEMA = cv.Schema(
{
cv.Optional(CONF_ONE_CHECKED, default=False): lv_bool,
cv.Optional(CONF_PAD_ROW): pixels,
cv.Optional(CONF_PAD_COLUMN): pixels,
cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr),
cv.Required(CONF_ROWS): cv.ensure_list(
cv.Schema(

View file

@ -1,7 +1,8 @@
from esphome.config_validation import Optional
from esphome.const import CONF_TEXT
from ..defines import CONF_INDICATOR, CONF_MAIN
from ..lv_validation import lv_text
from ..defines import CONF_INDICATOR, CONF_MAIN, CONF_PAD_COLUMN
from ..lv_validation import lv_text, pixels
from ..lvcode import lv
from ..schemas import TEXT_SCHEMA
from ..types import LvBoolean
@ -16,7 +17,11 @@ class CheckboxType(WidgetType):
CONF_CHECKBOX,
LvBoolean("lv_checkbox_t"),
(CONF_MAIN, CONF_INDICATOR),
TEXT_SCHEMA,
TEXT_SCHEMA.extend(
{
Optional(CONF_PAD_COLUMN): pixels,
}
),
)
async def to_code(self, w: Widget, config):

View file

@ -1,7 +1,7 @@
from esphome import automation
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_ON_VALUE, CONF_ROW, CONF_TRIGGER_ID
from esphome.const import CONF_ID, CONF_ROW
from ..automation import action_to_code
from ..defines import (
@ -29,6 +29,7 @@ lv_tileview_t = LvType(
"lv_tileview_t",
largs=[(lv_obj_t_ptr, "tile")],
lvalue=lambda w: w.get_property("tile_act"),
has_on_value=True,
)
tile_spec = WidgetType("lv_tileview_tile_t", lv_tile_t, (CONF_MAIN,), {})
@ -46,13 +47,6 @@ TILEVIEW_SCHEMA = cv.Schema(
},
)
),
cv.Optional(CONF_ON_VALUE): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
automation.Trigger.template(lv_obj_t_ptr)
)
}
),
}
)

View file

@ -70,72 +70,62 @@ void MICS4514Component::update() {
if (this->carbon_monoxide_sensor_ != nullptr) {
float co = 0.0f;
if (red_f <= 0.425f) {
co = (0.425f - red_f) / 0.000405f;
if (co < 1.0f)
co = 0.0f;
if (co > 1000.0f)
co = 1000.0f;
if (red_f > 3.4f) {
co = 0.0;
} else if (red_f < 0.01) {
co = 1000.0;
} else {
co = 4.2 / pow(red_f, 1.2);
}
this->carbon_monoxide_sensor_->publish_state(co);
}
if (this->nitrogen_dioxide_sensor_ != nullptr) {
float nitrogendioxide = 0.0f;
if (ox_f >= 1.1f) {
nitrogendioxide = (ox_f - 0.045f) / 6.13f;
if (nitrogendioxide < 0.1f)
nitrogendioxide = 0.0f;
if (nitrogendioxide > 10.0f)
nitrogendioxide = 10.0f;
if (ox_f < 0.3f) {
nitrogendioxide = 0.0;
} else {
nitrogendioxide = 0.164 * pow(ox_f, 0.975);
}
this->nitrogen_dioxide_sensor_->publish_state(nitrogendioxide);
}
if (this->methane_sensor_ != nullptr) {
float methane = 0.0f;
if (red_f <= 0.786f) {
methane = (0.786f - red_f) / 0.000023f;
if (methane < 1000.0f)
methane = 0.0f;
if (methane > 25000.0f)
methane = 25000.0f;
if (red_f > 0.9f || red_f < 0.5) { // outside the range->unlikely
methane = 0.0;
} else {
methane = 630 / pow(red_f, 4.4);
}
this->methane_sensor_->publish_state(methane);
}
if (this->ethanol_sensor_ != nullptr) {
float ethanol = 0.0f;
if (red_f <= 0.306f) {
ethanol = (0.306f - red_f) / 0.00057f;
if (ethanol < 10.0f)
ethanol = 0.0f;
if (ethanol > 500.0f)
ethanol = 500.0f;
if (red_f > 1.0f || red_f < 0.02) { // outside the range->unlikely
ethanol = 0.0;
} else {
ethanol = 1.52 / pow(red_f, 1.55);
}
this->ethanol_sensor_->publish_state(ethanol);
}
if (this->hydrogen_sensor_ != nullptr) {
float hydrogen = 0.0f;
if (red_f <= 0.279f) {
hydrogen = (0.279f - red_f) / 0.00026f;
if (hydrogen < 1.0f)
hydrogen = 0.0f;
if (hydrogen > 1000.0f)
hydrogen = 1000.0f;
if (red_f > 0.9f || red_f < 0.02) { // outside the range->unlikely
hydrogen = 0.0;
} else {
hydrogen = 0.85 / pow(red_f, 1.75);
}
this->hydrogen_sensor_->publish_state(hydrogen);
}
if (this->ammonia_sensor_ != nullptr) {
float ammonia = 0.0f;
if (red_f <= 0.8f) {
ammonia = (0.8f - red_f) / 0.0015f;
if (ammonia < 1.0f)
ammonia = 0.0f;
if (ammonia > 500.0f)
ammonia = 500.0f;
if (red_f > 0.98f || red_f < 0.2532) { // outside the ammonia range->unlikely
ammonia = 0.0;
} else {
ammonia = 0.9 / pow(red_f, 4.6);
}
this->ammonia_sensor_->publish_state(ammonia);
}

View file

@ -1,47 +1,39 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
from esphome.components import (
spi,
display,
)
from esphome.const import (
CONF_DC_PIN,
CONF_HSYNC_PIN,
CONF_RESET_PIN,
CONF_DATA_PINS,
CONF_ID,
CONF_DIMENSIONS,
CONF_VSYNC_PIN,
CONF_WIDTH,
CONF_HEIGHT,
CONF_LAMBDA,
CONF_MIRROR_X,
CONF_MIRROR_Y,
CONF_COLOR_ORDER,
CONF_TRANSFORM,
CONF_OFFSET_HEIGHT,
CONF_OFFSET_WIDTH,
CONF_INVERT_COLORS,
CONF_RED,
CONF_GREEN,
CONF_BLUE,
CONF_NUMBER,
CONF_IGNORE_STRAPPING_WARNING,
)
from esphome.components.esp32 import (
only_on_variant,
const,
)
import esphome.codegen as cg
from esphome.components import display, spi
from esphome.components.esp32 import const, only_on_variant
from esphome.components.rpi_dpi_rgb.display import (
CONF_PCLK_FREQUENCY,
CONF_PCLK_INVERTED,
)
from .init_sequences import (
ST7701S_INITS,
cmd,
import esphome.config_validation as cv
from esphome.const import (
CONF_BLUE,
CONF_COLOR_ORDER,
CONF_DATA_PINS,
CONF_DC_PIN,
CONF_DIMENSIONS,
CONF_GREEN,
CONF_HEIGHT,
CONF_HSYNC_PIN,
CONF_ID,
CONF_IGNORE_STRAPPING_WARNING,
CONF_INVERT_COLORS,
CONF_LAMBDA,
CONF_MIRROR_X,
CONF_MIRROR_Y,
CONF_NUMBER,
CONF_OFFSET_HEIGHT,
CONF_OFFSET_WIDTH,
CONF_RED,
CONF_RESET_PIN,
CONF_TRANSFORM,
CONF_VSYNC_PIN,
CONF_WIDTH,
)
from esphome.core import TimePeriod
from .init_sequences import ST7701S_INITS, cmd
CONF_INIT_SEQUENCE = "init_sequence"
CONF_DE_PIN = "de_pin"
@ -59,6 +51,7 @@ DEPENDENCIES = ["spi", "esp32"]
st7701s_ns = cg.esphome_ns.namespace("st7701s")
ST7701S = st7701s_ns.class_("ST7701S", display.Display, cg.Component, spi.SPIDevice)
ColorOrder = display.display_ns.enum("ColorMode")
ST7701S_DELAY_FLAG = 0xFF
COLOR_ORDERS = {
"RGB": ColorOrder.COLOR_ORDER_RGB,
@ -93,18 +86,23 @@ def map_sequence(value):
"""
An initialisation sequence can be selected from one of the pre-defined sequences in init_sequences.py,
or can be a literal array of data bytes.
The format is a repeated sequence of [CMD, LEN, <data>] where <data> is LEN bytes.
The format is a repeated sequence of [CMD, <data>] where <data> is s a sequence of bytes. The length is inferred
from the length of the sequence and should not be explicit.
A delay can be inserted by specifying "- delay N" where N is in ms
"""
if isinstance(value, str) and value.lower().startswith("delay "):
value = value.lower()[6:]
delay = cv.All(
cv.positive_time_period_milliseconds,
cv.Range(TimePeriod(milliseconds=1), TimePeriod(milliseconds=255)),
)(value)
return [delay, ST7701S_DELAY_FLAG]
if not isinstance(value, list):
value = cv.int_(value)
value = cv.one_of(*ST7701S_INITS)(value)
return ST7701S_INITS[value]
# value = cv.ensure_list(cv.uint8_t)(value)
data_length = len(value)
if data_length == 0:
raise cv.Invalid("Empty sequence")
value = cmd(*value)
return value
value = cv.Length(min=1, max=254)(value)
return cmd(*value)
CONFIG_SCHEMA = cv.All(

View file

@ -138,11 +138,16 @@ void ST7701S::write_init_sequence_() {
for (size_t i = 0; i != this->init_sequence_.size();) {
uint8_t cmd = this->init_sequence_[i++];
size_t len = this->init_sequence_[i++];
this->write_sequence_(cmd, len, &this->init_sequence_[i]);
i += len;
esph_log_v(TAG, "Command %X, %d bytes", cmd, len);
if (cmd == SW_RESET_CMD)
delay(6);
if (len == ST7701S_DELAY_FLAG) {
ESP_LOGV(TAG, "Delay %dms", cmd);
delay(cmd);
} else {
this->write_sequence_(cmd, len, &this->init_sequence_[i]);
i += len;
ESP_LOGV(TAG, "Command %X, %d bytes", cmd, len);
if (cmd == SW_RESET_CMD)
delay(6);
}
}
// st7701 does not appear to support axis swapping
this->write_sequence_(CMD2_BKSEL, sizeof(CMD2_BK0), CMD2_BK0);
@ -153,7 +158,7 @@ void ST7701S::write_init_sequence_() {
val |= 0x10;
this->write_command_(MADCTL_CMD);
this->write_data_(val);
esph_log_d(TAG, "write MADCTL %X", val);
ESP_LOGD(TAG, "write MADCTL %X", val);
this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF);
this->set_timeout(120, [this] {
this->write_command_(SLEEP_OUT);

View file

@ -25,6 +25,7 @@ const uint8_t INVERT_ON = 0x21;
const uint8_t DISPLAY_ON = 0x29;
const uint8_t CMD2_BKSEL = 0xFF;
const uint8_t CMD2_BK0[5] = {0x77, 0x01, 0x00, 0x00, 0x10};
const uint8_t ST7701S_DELAY_FLAG = 0xFF;
class ST7701S : public display::Display,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,

View file

@ -9,6 +9,7 @@ from esphome.const import (
CONF_MULTIPLY,
CONF_STEP,
CONF_INITIAL_VALUE,
CONF_RESTORE_VALUE,
)
from .. import tuya_ns, CONF_TUYA_ID, Tuya, TuyaDatapointType
@ -58,6 +59,7 @@ CONFIG_SCHEMA = cv.All(
DATAPOINT_TYPES, lower=True
),
cv.Optional(CONF_INITIAL_VALUE): cv.float_,
cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean,
}
)
),
@ -90,3 +92,4 @@ async def to_code(config):
hidden_init_value := hidden_config.get(CONF_INITIAL_VALUE, None)
) is not None:
cg.add(var.set_datapoint_initial_value(hidden_init_value))
cg.add(var.set_restore_value(hidden_config[CONF_RESTORE_VALUE]))

View file

@ -7,14 +7,28 @@ namespace tuya {
static const char *const TAG = "tuya.number";
void TuyaNumber::setup() {
if (this->restore_value_) {
this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
}
this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) {
if (datapoint.type == TuyaDatapointType::INTEGER) {
ESP_LOGV(TAG, "MCU reported number %u is: %d", datapoint.id, datapoint.value_int);
this->publish_state(datapoint.value_int / multiply_by_);
float value = datapoint.value_int / multiply_by_;
this->publish_state(value);
if (this->restore_value_)
this->pref_.save(&value);
} else if (datapoint.type == TuyaDatapointType::ENUM) {
ESP_LOGV(TAG, "MCU reported number %u is: %u", datapoint.id, datapoint.value_enum);
this->publish_state(datapoint.value_enum);
float value = datapoint.value_enum;
this->publish_state(value);
if (this->restore_value_)
this->pref_.save(&value);
} else {
ESP_LOGW(TAG, "Reported type (%d) is not a number!", static_cast<int>(datapoint.type));
return;
}
if ((this->type_) && (this->type_ != datapoint.type)) {
ESP_LOGW(TAG, "Reported type (%d) different than previously set (%d)!", static_cast<int>(datapoint.type),
static_cast<int>(*this->type_));
@ -23,8 +37,26 @@ void TuyaNumber::setup() {
});
this->parent_->add_on_initialized_callback([this] {
if ((this->initial_value_) && (this->type_)) {
this->control(*this->initial_value_);
if (this->type_) {
float value;
if (!this->restore_value_) {
if (this->initial_value_) {
value = *this->initial_value_;
} else {
return;
}
} else {
if (!this->pref_.load(&value)) {
if (this->initial_value_) {
value = *this->initial_value_;
} else {
value = this->traits.get_min_value();
ESP_LOGW(TAG, "Failed to restore and there is no initial value defined. Setting min_value (%f)", value);
}
}
}
this->control(value);
}
});
}
@ -38,6 +70,9 @@ void TuyaNumber::control(float value) {
this->parent_->set_enum_datapoint_value(this->number_id_, value);
}
this->publish_state(value);
if (this->restore_value_)
this->pref_.save(&value);
}
void TuyaNumber::dump_config() {
@ -52,6 +87,8 @@ void TuyaNumber::dump_config() {
if (this->initial_value_) {
ESP_LOGCONFIG(TAG, " Initial Value: %f", *this->initial_value_);
}
ESP_LOGCONFIG(TAG, " Restore Value: %s", YESNO(this->restore_value_));
}
} // namespace tuya

View file

@ -1,9 +1,10 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/tuya/tuya.h"
#include "esphome/components/number/number.h"
#include "esphome/components/tuya/tuya.h"
#include "esphome/core/component.h"
#include "esphome/core/optional.h"
#include "esphome/core/preferences.h"
namespace esphome {
namespace tuya {
@ -16,6 +17,7 @@ class TuyaNumber : public number::Number, public Component {
void set_write_multiply(float factor) { multiply_by_ = factor; }
void set_datapoint_type(TuyaDatapointType type) { type_ = type; }
void set_datapoint_initial_value(float value) { this->initial_value_ = value; }
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
void set_tuya_parent(Tuya *parent) { this->parent_ = parent; }
@ -27,6 +29,9 @@ class TuyaNumber : public number::Number, public Component {
float multiply_by_{1.0};
optional<TuyaDatapointType> type_{};
optional<float> initial_value_{};
bool restore_value_{false};
ESPPreferenceObject pref_;
};
} // namespace tuya

View file

@ -1,35 +1,36 @@
from __future__ import annotations
import gzip
import esphome.codegen as cg
import esphome.config_validation as cv
import esphome.final_validate as fv
from esphome.components import web_server_base
from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID
import esphome.config_validation as cv
from esphome.const import (
CONF_AUTH,
CONF_CSS_INCLUDE,
CONF_CSS_URL,
CONF_ENABLE_PRIVATE_NETWORK_ACCESS,
CONF_ID,
CONF_INCLUDE_INTERNAL,
CONF_JS_INCLUDE,
CONF_JS_URL,
CONF_ENABLE_PRIVATE_NETWORK_ACCESS,
CONF_PORT,
CONF_AUTH,
CONF_USERNAME,
CONF_PASSWORD,
CONF_INCLUDE_INTERNAL,
CONF_OTA,
CONF_LOG,
CONF_VERSION,
CONF_LOCAL,
CONF_LOG,
CONF_OTA,
CONF_PASSWORD,
CONF_PORT,
CONF_USERNAME,
CONF_VERSION,
CONF_WEB_SERVER_ID,
CONF_WEB_SERVER_SORTING_WEIGHT,
PLATFORM_BK72XX,
PLATFORM_ESP32,
PLATFORM_ESP8266,
PLATFORM_BK72XX,
PLATFORM_RTL87XX,
)
from esphome.core import CORE, coroutine_with_priority
import esphome.final_validate as fv
AUTO_LOAD = ["json", "web_server_base"]
@ -208,7 +209,6 @@ async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], paren)
await cg.register_component(var, config)
cg.add_define("USE_WEBSERVER")
version = config[CONF_VERSION]
cg.add(paren.set_port(config[CONF_PORT]))

View file

@ -1,4 +1,5 @@
#include "list_entities.h"
#ifdef USE_WEBSERVER
#include "esphome/core/application.h"
#include "esphome/core/log.h"
#include "esphome/core/util.h"
@ -188,3 +189,4 @@ bool ListEntitiesIterator::on_update(update::UpdateEntity *update) {
} // namespace web_server
} // namespace esphome
#endif

View file

@ -1,8 +1,9 @@
#pragma once
#include "esphome/core/defines.h"
#ifdef USE_WEBSERVER
#include "esphome/core/component.h"
#include "esphome/core/component_iterator.h"
#include "esphome/core/defines.h"
namespace esphome {
namespace web_server {
@ -78,3 +79,4 @@ class ListEntitiesIterator : public ComponentIterator {
} // namespace web_server
} // namespace esphome
#endif

View file

@ -1,5 +1,5 @@
#include "web_server.h"
#ifdef USE_WEBSERVER
#include "esphome/components/json/json_util.h"
#include "esphome/components/network/util.h"
#include "esphome/core/application.h"
@ -1659,3 +1659,4 @@ void WebServer::schedule_(std::function<void()> &&f) {
} // namespace web_server
} // namespace esphome
#endif

View file

@ -3,6 +3,7 @@
#include "list_entities.h"
#include "esphome/components/web_server_base/web_server_base.h"
#ifdef USE_WEBSERVER
#include "esphome/core/component.h"
#include "esphome/core/controller.h"
#include "esphome/core/entity_base.h"
@ -366,3 +367,4 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
} // namespace web_server
} // namespace esphome
#endif

View file

@ -1,4 +1,5 @@
#include "web_server_base.h"
#ifdef USE_NETWORK
#include "esphome/core/log.h"
#include "esphome/core/application.h"
#include "esphome/core/helpers.h"
@ -121,3 +122,4 @@ float WebServerBase::get_setup_priority() const {
} // namespace web_server_base
} // namespace esphome
#endif

View file

@ -1,5 +1,6 @@
#pragma once
#include "esphome/core/defines.h"
#ifdef USE_NETWORK
#include <memory>
#include <utility>
#include <vector>
@ -145,3 +146,4 @@ class OTARequestHandler : public AsyncWebHandler {
} // namespace web_server_base
} // namespace esphome
#endif

View file

@ -730,6 +730,7 @@ CONF_RW_PIN = "rw_pin"
CONF_RX_BUFFER_SIZE = "rx_buffer_size"
CONF_RX_ONLY = "rx_only"
CONF_RX_PIN = "rx_pin"
CONF_RX_QUEUE_LEN = "rx_queue_len"
CONF_SAFE_MODE = "safe_mode"
CONF_SAMPLE_RATE = "sample_rate"
CONF_SAMSUNG = "samsung"
@ -881,6 +882,7 @@ CONF_TVOC = "tvoc"
CONF_TX_BUFFER_SIZE = "tx_buffer_size"
CONF_TX_PIN = "tx_pin"
CONF_TX_POWER = "tx_power"
CONF_TX_QUEUE_LEN = "tx_queue_len"
CONF_TYPE = "type"
CONF_TYPE_ID = "type_id"
CONF_UART_ID = "uart_id"

View file

@ -1,6 +1,9 @@
#include "bytebuffer.h"
#include <cassert>
#include <cstring>
#include "esphome/core/helpers.h"
#include <list>
#include <vector>
namespace esphome {
@ -110,18 +113,13 @@ uint32_t ByteBuffer::get_int24() {
}
float ByteBuffer::get_float() {
assert(this->get_remaining() >= sizeof(float));
auto ui_value = this->get_uint32();
float value;
memcpy(&value, &ui_value, sizeof(float));
return value;
return bit_cast<float>(this->get_uint32());
}
double ByteBuffer::get_double() {
assert(this->get_remaining() >= sizeof(double));
auto ui_value = this->get_uint64();
double value;
memcpy(&value, &ui_value, sizeof(double));
return value;
return bit_cast<double>(this->get_uint64());
}
std::vector<uint8_t> ByteBuffer::get_vector(size_t length) {
assert(this->get_remaining() >= length);
auto start = this->data_.begin() + this->position_;
@ -154,16 +152,12 @@ void ByteBuffer::put_uint(uint64_t value, size_t length) {
void ByteBuffer::put_float(float value) {
static_assert(sizeof(float) == sizeof(uint32_t), "Float sizes other than 32 bit not supported");
assert(this->get_remaining() >= sizeof(float));
uint32_t ui_value;
memcpy(&ui_value, &value, sizeof(float)); // this work-around required to silence compiler warnings
this->put_uint32(ui_value);
this->put_uint32(bit_cast<uint32_t>(value));
}
void ByteBuffer::put_double(double value) {
static_assert(sizeof(double) == sizeof(uint64_t), "Double sizes other than 64 bit not supported");
assert(this->get_remaining() >= sizeof(double));
uint64_t ui_value;
memcpy(&ui_value, &value, sizeof(double));
this->put_uint64(ui_value);
this->put_uint64(bit_cast<uint64_t>(value));
}
void ByteBuffer::put_vector(const std::vector<uint8_t> &value) {
assert(this->get_remaining() >= value.size());

View file

@ -11,6 +11,7 @@ display:
cs_pin: 12
dc_pin: 13
reset_pin: 21
invert_colors: false
# Purposely test that `animation:` does auto-load `image:`
# Keep the `image:` undefined.

View file

@ -11,6 +11,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: false
# Purposely test that `animation:` does auto-load `image:`
# Keep the `image:` undefined.

View file

@ -11,6 +11,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: false
# Purposely test that `animation:` does auto-load `image:`
# Keep the `image:` undefined.

View file

@ -11,6 +11,7 @@ display:
cs_pin: 12
dc_pin: 13
reset_pin: 21
invert_colors: false
# Purposely test that `animation:` does auto-load `image:`
# Keep the `image:` undefined.

View file

@ -11,6 +11,7 @@ display:
cs_pin: 5
dc_pin: 15
reset_pin: 16
invert_colors: false
# Purposely test that `animation:` does auto-load `image:`
# Keep the `image:` undefined.

View file

@ -11,6 +11,7 @@ display:
cs_pin: 20
dc_pin: 21
reset_pin: 22
invert_colors: false
# Purposely test that `animation:` does auto-load `image:`
# Keep the `image:` undefined.

View file

@ -12,6 +12,7 @@ display:
dc_pin: GPIO4
reset_pin:
number: GPIO21
invert_colors: false
i2c:
scl: GPIO18

View file

@ -26,6 +26,7 @@ display:
mirror_x: true
mirror_y: true
auto_clear_enabled: false
invert_colors: false
spi:
clk_pin: 14

View file

@ -11,6 +11,7 @@ display:
cs_pin: 12
dc_pin: 13
reset_pin: 21
invert_colors: false
lambda: |-
// Draw an analog clock in the center of the screen
int centerX = it.get_width() / 2;

View file

@ -19,6 +19,7 @@ display:
mirror_x: true
mirror_y: true
auto_clear_enabled: false
invert_colors: false
touchscreen:
- platform: ft63x6

View file

@ -0,0 +1,25 @@
i2c:
- id: i2c_gt911
scl: 5
sda: 4
display:
- platform: ssd1306_i2c
id: ssd1306_display
model: SSD1306_128X64
reset_pin: 10
pages:
- id: page1
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());
touchscreen:
- platform: gt911
display: ssd1306_display
interrupt_pin: 20
reset_pin: 21
binary_sensor:
- platform: gt911
id: touch_key_911
index: 0

View file

@ -1,24 +1 @@
i2c:
- id: i2c_gt911
scl: 16
sda: 17
display:
- platform: ssd1306_i2c
id: ssd1306_display
model: SSD1306_128X64
reset_pin: 13
pages:
- id: page1
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());
touchscreen:
- platform: gt911
display: ssd1306_display
interrupt_pin: 14
binary_sensor:
- platform: gt911
id: touch_key_911
index: 0
<<: !include common.yaml

View file

@ -1,24 +1 @@
i2c:
- id: i2c_gt911
scl: 5
sda: 4
display:
- platform: ssd1306_i2c
id: ssd1306_display
model: SSD1306_128X64
reset_pin: 3
pages:
- id: page1
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());
touchscreen:
- platform: gt911
display: ssd1306_display
interrupt_pin: 6
binary_sensor:
- platform: gt911
id: touch_key_911
index: 0
<<: !include common.yaml

View file

@ -1,24 +1 @@
i2c:
- id: i2c_gt911
scl: 5
sda: 4
display:
- platform: ssd1306_i2c
id: ssd1306_display
model: SSD1306_128X64
reset_pin: 3
pages:
- id: page1
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());
touchscreen:
- platform: gt911
display: ssd1306_display
interrupt_pin: 6
binary_sensor:
- platform: gt911
id: touch_key_911
index: 0
<<: !include common.yaml

View file

@ -1,24 +1 @@
i2c:
- id: i2c_gt911
scl: 16
sda: 17
display:
- platform: ssd1306_i2c
id: ssd1306_display
model: SSD1306_128X64
reset_pin: 13
pages:
- id: page1
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());
touchscreen:
- platform: gt911
display: ssd1306_display
interrupt_pin: 14
binary_sensor:
- platform: gt911
id: touch_key_911
index: 0
<<: !include common.yaml

View file

@ -1,24 +1 @@
i2c:
- id: i2c_gt911
scl: 5
sda: 4
display:
- platform: ssd1306_i2c
id: ssd1306_display
model: SSD1306_128X64
reset_pin: 3
pages:
- id: page1
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());
touchscreen:
- platform: gt911
display: ssd1306_display
interrupt_pin: 6
binary_sensor:
- platform: gt911
id: touch_key_911
index: 0
<<: !include common.yaml

View file

@ -11,6 +11,7 @@ display:
cs_pin: 12
dc_pin: 13
reset_pin: 21
invert_colors: true
image:
- id: binary_image

View file

@ -11,6 +11,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: true
image:
- id: binary_image

View file

@ -11,6 +11,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: true
image:
- id: binary_image

View file

@ -11,6 +11,7 @@ display:
cs_pin: 12
dc_pin: 13
reset_pin: 21
invert_colors: true
image:
- id: binary_image

View file

@ -11,6 +11,7 @@ display:
cs_pin: 5
dc_pin: 15
reset_pin: 16
invert_colors: true
image:
- id: binary_image

View file

@ -11,6 +11,7 @@ display:
cs_pin: 20
dc_pin: 21
reset_pin: 22
invert_colors: true
image:
- id: binary_image

View file

@ -337,11 +337,25 @@ lvgl:
- tileview:
id: tileview_id
scrollbar_mode: active
on_value:
then:
- if:
condition:
lambda: return tile == id(tile_1);
then:
- logger.log: "tile 1 is now showing"
tiles:
- id: page_1
- id: tile_1
row: 0
column: 0
dir: HOR
dir: ALL
widgets:
- obj:
bg_color: 0x000000
- id: tile_2
row: 1
column: 0
dir: [VER, HOR]
widgets:
- obj:
bg_color: 0x000000

View file

@ -13,6 +13,7 @@ display:
cs_pin: 12
dc_pin: 13
reset_pin: 21
invert_colors: true
lambda: |-
it.fill(Color(0, 0, 0));
it.image(0, 0, id(online_rgba_image));

View file

@ -13,6 +13,7 @@ display:
cs_pin: 15
dc_pin: 3
reset_pin: 1
invert_colors: true
lambda: |-
it.fill(Color(0, 0, 0));
it.image(0, 0, id(online_rgba_image));

View file

@ -11,6 +11,7 @@ display:
cs_pin: 12
dc_pin: 13
reset_pin: 21
invert_colors: false
lambda: |-
// Draw a QR code in the center of the screen
auto scale = 2;

View file

@ -11,6 +11,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: false
lambda: |-
// Draw a QR code in the center of the screen
auto scale = 2;

View file

@ -11,6 +11,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: false
lambda: |-
// Draw a QR code in the center of the screen
auto scale = 2;

View file

@ -11,6 +11,7 @@ display:
cs_pin: 12
dc_pin: 13
reset_pin: 21
invert_colors: false
lambda: |-
// Draw a QR code in the center of the screen
auto scale = 2;

View file

@ -11,6 +11,7 @@ display:
cs_pin: 5
dc_pin: 15
reset_pin: 16
invert_colors: false
lambda: |-
// Draw a QR code in the center of the screen
auto scale = 2;

View file

@ -11,6 +11,7 @@ display:
cs_pin: 20
dc_pin: 21
reset_pin: 22
invert_colors: false
lambda: |-
// Draw a QR code in the center of the screen
auto scale = 2;

View file

@ -38,7 +38,12 @@ display:
hsync_pin: 16
vsync_pin: 17
pclk_pin: 21
init_sequence: 1
init_sequence:
- 1
- [0x23, 0xA, 0xB]
- delay 20ms
- [0x23, 0xA, 0xB]
- delay 0.2s
data_pins:
- number: 0
ignore_strapping_warning: true

View file

@ -18,6 +18,7 @@ display:
data_rate: 40MHz
dimensions: 320x240
update_interval: never
invert_colors: false
transform:
mirror_y: false
mirror_x: false

View file

@ -12,6 +12,7 @@ display:
cs_pin: 13
dc_pin: 14
reset_pin: 21
invert_colors: false
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());

View file

@ -12,6 +12,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: false
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());

View file

@ -12,6 +12,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: false
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());

View file

@ -12,6 +12,7 @@ display:
cs_pin: 13
dc_pin: 14
reset_pin: 21
invert_colors: false
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());

View file

@ -14,6 +14,7 @@ display:
data_rate: 40MHz
dimensions: 320x240
update_interval: never
invert_colors: false
transform:
mirror_y: false
mirror_x: false

View file

@ -12,6 +12,7 @@ display:
cs_pin: 15
dc_pin: 4
reset_pin: 5
invert_colors: false
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());

View file

@ -12,6 +12,7 @@ display:
cs_pin: 8
dc_pin: 9
reset_pin: 10
invert_colors: false
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());