mirror of
https://github.com/esphome/esphome.git
synced 2026-09-24 13:34:07 +00:00
Merge upstream/dev into integration
This commit is contained in:
@@ -58,7 +58,7 @@ void Alpha3::handle_geni_response_(const uint8_t *response, uint16_t length) {
|
||||
if (this->response_offset_ >= this->response_length_) {
|
||||
ESP_LOGD(TAG, "[%s] GENI response begin", this->parent_->address_str());
|
||||
if (length < GENI_RESPONSE_HEADER_LENGTH) {
|
||||
ESP_LOGW(TAG, "[%s] response to short", this->parent_->address_str());
|
||||
ESP_LOGW(TAG, "[%s] response too short", this->parent_->address_str());
|
||||
return;
|
||||
}
|
||||
if (response[0] != 36 || response[2] != 248 || response[3] != 231 || response[4] != 10) {
|
||||
|
||||
@@ -854,6 +854,10 @@ def _configure_lwip_max_sockets(conf: dict) -> None:
|
||||
async def to_code(config):
|
||||
cg.add_platformio_option("board", config[CONF_BOARD])
|
||||
cg.add_platformio_option("board_upload.flash_size", config[CONF_FLASH_SIZE])
|
||||
cg.add_platformio_option(
|
||||
"board_upload.maximum_size",
|
||||
int(config[CONF_FLASH_SIZE].removesuffix("MB")) * 1024 * 1024,
|
||||
)
|
||||
cg.set_cpp_standard("gnu++20")
|
||||
cg.add_build_flag("-DUSE_ESP32")
|
||||
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
extern const uint8_t ESPHOME_ESP8266_GPIO_INITIAL_MODE[16];
|
||||
extern const uint8_t ESPHOME_ESP8266_GPIO_INITIAL_LEVEL[16];
|
||||
|
||||
namespace esphome {
|
||||
namespace esp8266 {} // namespace esp8266
|
||||
} // namespace esphome
|
||||
namespace esphome::esp8266 {} // namespace esphome::esp8266
|
||||
|
||||
#endif // USE_ESP8266
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
#include "gpio.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace esp8266 {
|
||||
namespace esphome::esp8266 {
|
||||
|
||||
static const char *const TAG = "esp8266";
|
||||
|
||||
@@ -110,9 +109,11 @@ void ESP8266GPIOPin::digital_write(bool value) {
|
||||
}
|
||||
void ESP8266GPIOPin::detach_interrupt() const { detachInterrupt(pin_); }
|
||||
|
||||
} // namespace esp8266
|
||||
} // namespace esphome::esp8266
|
||||
|
||||
using namespace esp8266;
|
||||
namespace esphome {
|
||||
|
||||
using esp8266::ISRPinArg;
|
||||
|
||||
bool IRAM_ATTR ISRInternalGPIOPin::digital_read() {
|
||||
auto *arg = reinterpret_cast<ISRPinArg *>(this->arg_);
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
#include "esphome/core/hal.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace esp8266 {
|
||||
namespace esphome::esp8266 {
|
||||
|
||||
class ESP8266GPIOPin : public InternalGPIOPin {
|
||||
public:
|
||||
@@ -33,7 +32,6 @@ class ESP8266GPIOPin : public InternalGPIOPin {
|
||||
gpio::Flags flags_{};
|
||||
};
|
||||
|
||||
} // namespace esp8266
|
||||
} // namespace esphome
|
||||
} // namespace esphome::esp8266
|
||||
|
||||
#endif // USE_ESP8266
|
||||
|
||||
@@ -15,24 +15,24 @@ extern "C" {
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
namespace esphome {
|
||||
namespace esp8266 {
|
||||
namespace esphome::esp8266 {
|
||||
|
||||
static const char *const TAG = "esp8266.preferences";
|
||||
|
||||
static bool s_prevent_write = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static uint32_t *s_flash_storage = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static bool s_prevent_write = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static bool s_flash_dirty = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
static const uint32_t ESP_RTC_USER_MEM_START = 0x60001200;
|
||||
static constexpr uint32_t ESP_RTC_USER_MEM_START = 0x60001200;
|
||||
static constexpr uint32_t ESP_RTC_USER_MEM_SIZE_WORDS = 128;
|
||||
static constexpr uint32_t ESP_RTC_USER_MEM_SIZE_BYTES = ESP_RTC_USER_MEM_SIZE_WORDS * 4;
|
||||
|
||||
#define ESP_RTC_USER_MEM ((uint32_t *) ESP_RTC_USER_MEM_START)
|
||||
static const uint32_t ESP_RTC_USER_MEM_SIZE_WORDS = 128;
|
||||
static const uint32_t ESP_RTC_USER_MEM_SIZE_BYTES = ESP_RTC_USER_MEM_SIZE_WORDS * 4;
|
||||
|
||||
#ifdef USE_ESP8266_PREFERENCES_FLASH
|
||||
static const uint32_t ESP8266_FLASH_STORAGE_SIZE = 128;
|
||||
static constexpr uint32_t ESP8266_FLASH_STORAGE_SIZE = 128;
|
||||
#else
|
||||
static const uint32_t ESP8266_FLASH_STORAGE_SIZE = 64;
|
||||
static constexpr uint32_t ESP8266_FLASH_STORAGE_SIZE = 64;
|
||||
#endif
|
||||
|
||||
static inline bool esp_rtc_user_mem_read(uint32_t index, uint32_t *dest) {
|
||||
@@ -284,10 +284,10 @@ void setup_preferences() {
|
||||
}
|
||||
void preferences_prevent_write(bool prevent) { s_prevent_write = prevent; }
|
||||
|
||||
} // namespace esp8266
|
||||
} // namespace esphome::esp8266
|
||||
|
||||
namespace esphome {
|
||||
ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ESP8266
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
|
||||
namespace esphome {
|
||||
namespace esp8266 {
|
||||
namespace esphome::esp8266 {
|
||||
|
||||
void setup_preferences();
|
||||
void preferences_prevent_write(bool prevent);
|
||||
|
||||
} // namespace esp8266
|
||||
} // namespace esphome
|
||||
} // namespace esphome::esp8266
|
||||
|
||||
#endif // USE_ESP8266
|
||||
|
||||
@@ -279,6 +279,8 @@ KEYBOARD_MODES = LvConstant(
|
||||
)
|
||||
ROLLER_MODES = LvConstant("LV_ROLLER_MODE_", "NORMAL", "INFINITE")
|
||||
TILE_DIRECTIONS = DIRECTIONS.extend("HOR", "VER", "ALL")
|
||||
SCROLL_DIRECTIONS = TILE_DIRECTIONS.extend("NONE")
|
||||
SNAP_DIRECTIONS = LvConstant("LV_SCROLL_SNAP_", "NONE", "START", "END", "CENTER")
|
||||
CHILD_ALIGNMENTS = LvConstant(
|
||||
"LV_ALIGN_",
|
||||
"TOP_LEFT",
|
||||
@@ -511,6 +513,9 @@ CONF_ROLLOVER = "rollover"
|
||||
CONF_ROOT_BACK_BTN = "root_back_btn"
|
||||
CONF_SCALE_LINES = "scale_lines"
|
||||
CONF_SCROLLBAR_MODE = "scrollbar_mode"
|
||||
CONF_SCROLL_DIR = "scroll_dir"
|
||||
CONF_SCROLL_SNAP_X = "scroll_snap_x"
|
||||
CONF_SCROLL_SNAP_Y = "scroll_snap_y"
|
||||
CONF_SELECTED_INDEX = "selected_index"
|
||||
CONF_SELECTED_TEXT = "selected_text"
|
||||
CONF_SHOW_SNOW = "show_snow"
|
||||
|
||||
@@ -36,6 +36,8 @@ from .defines import (
|
||||
)
|
||||
from .lv_validation import padding, size
|
||||
|
||||
CONF_MULTIPLE_WIDGETS_PER_CELL = "multiple_widgets_per_cell"
|
||||
|
||||
cell_alignments = LV_CELL_ALIGNMENTS.one_of
|
||||
grid_alignments = LV_GRID_ALIGNMENTS.one_of
|
||||
flex_alignments = LV_FLEX_ALIGNMENTS.one_of
|
||||
@@ -170,10 +172,14 @@ class DirectionalLayout(FlexLayout):
|
||||
|
||||
def validate(self, config):
|
||||
assert config[CONF_LAYOUT].lower() == self.direction
|
||||
config[CONF_LAYOUT] = {
|
||||
layout = {
|
||||
**FLEX_HV_STYLE,
|
||||
CONF_FLEX_FLOW: "LV_FLEX_FLOW_" + self.flow.upper(),
|
||||
}
|
||||
if pad_all := config.get("pad_all"):
|
||||
layout[CONF_PAD_ROW] = pad_all
|
||||
layout[CONF_PAD_COLUMN] = pad_all
|
||||
config[CONF_LAYOUT] = layout
|
||||
return config
|
||||
|
||||
|
||||
@@ -220,6 +226,7 @@ class GridLayout(Layout):
|
||||
cv.Optional(CONF_GRID_ROW_ALIGN): grid_alignments,
|
||||
cv.Optional(CONF_PAD_ROW): padding,
|
||||
cv.Optional(CONF_PAD_COLUMN): padding,
|
||||
cv.Optional(CONF_MULTIPLE_WIDGETS_PER_CELL, default=False): cv.boolean,
|
||||
},
|
||||
{
|
||||
cv.Optional(CONF_GRID_CELL_ROW_POS): cv.positive_int,
|
||||
@@ -263,6 +270,7 @@ class GridLayout(Layout):
|
||||
# should be guaranteed to be a dict at this point
|
||||
assert isinstance(layout, dict)
|
||||
assert layout.get(CONF_TYPE).lower() == TYPE_GRID
|
||||
allow_multiple = layout.get(CONF_MULTIPLE_WIDGETS_PER_CELL, False)
|
||||
rows = len(layout[CONF_GRID_ROWS])
|
||||
columns = len(layout[CONF_GRID_COLUMNS])
|
||||
used_cells = [[None] * columns for _ in range(rows)]
|
||||
@@ -299,7 +307,10 @@ class GridLayout(Layout):
|
||||
f"exceeds grid size {rows}x{columns}",
|
||||
[CONF_WIDGETS, index],
|
||||
)
|
||||
if used_cells[row + i][column + j] is not None:
|
||||
if (
|
||||
not allow_multiple
|
||||
and used_cells[row + i][column + j] is not None
|
||||
):
|
||||
raise cv.Invalid(
|
||||
f"Cell span {row + i}/{column + j} already occupied by widget at index {used_cells[row + i][column + j]}",
|
||||
[CONF_WIDGETS, index],
|
||||
|
||||
@@ -40,7 +40,7 @@ from .helpers import (
|
||||
lv_fonts_used,
|
||||
requires_component,
|
||||
)
|
||||
from .types import lv_font_t, lv_gradient_t
|
||||
from .types import lv_gradient_t
|
||||
|
||||
opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER")
|
||||
|
||||
@@ -498,7 +498,9 @@ class LvFont(LValidator):
|
||||
esphome_fonts_used.add(fontval)
|
||||
return requires_component("font")(fontval)
|
||||
|
||||
super().__init__(validator, lv_font_t)
|
||||
# Use font::Font* as return type for lambdas returning ESPHome fonts
|
||||
# The inline overloads in lvgl_esphome.h handle conversion to lv_font_t*
|
||||
super().__init__(validator, Font.operator("ptr"))
|
||||
|
||||
async def process(self, value, args=()):
|
||||
if is_lv_font(value):
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from esphome import config_validation as cv
|
||||
from esphome.automation import Trigger, validate_automation
|
||||
from esphome.components.time import RealTimeClock
|
||||
from esphome.config_validation import prepend_path
|
||||
from esphome.const import (
|
||||
CONF_ARGS,
|
||||
CONF_FORMAT,
|
||||
@@ -19,7 +20,14 @@ from esphome.core import TimePeriod
|
||||
from esphome.core.config import StartupTrigger
|
||||
|
||||
from . import defines as df, lv_validation as lvalid
|
||||
from .defines import CONF_TIME_FORMAT, LV_GRAD_DIR
|
||||
from .defines import (
|
||||
CONF_SCROLL_DIR,
|
||||
CONF_SCROLL_SNAP_X,
|
||||
CONF_SCROLL_SNAP_Y,
|
||||
CONF_SCROLLBAR_MODE,
|
||||
CONF_TIME_FORMAT,
|
||||
LV_GRAD_DIR,
|
||||
)
|
||||
from .helpers import CONF_IF_NAN, requires_component, validate_printf
|
||||
from .layout import (
|
||||
FLEX_OBJ_SCHEMA,
|
||||
@@ -233,9 +241,19 @@ STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).ex
|
||||
cv.Optional(df.CONF_SCROLLBAR_MODE): df.LvConstant(
|
||||
"LV_SCROLLBAR_MODE_", "OFF", "ON", "ACTIVE", "AUTO"
|
||||
).one_of,
|
||||
cv.Optional(CONF_SCROLL_DIR): df.SCROLL_DIRECTIONS.one_of,
|
||||
cv.Optional(CONF_SCROLL_SNAP_X): df.SNAP_DIRECTIONS.one_of,
|
||||
cv.Optional(CONF_SCROLL_SNAP_Y): df.SNAP_DIRECTIONS.one_of,
|
||||
}
|
||||
)
|
||||
|
||||
OBJ_PROPERTIES = {
|
||||
CONF_SCROLL_SNAP_X,
|
||||
CONF_SCROLL_SNAP_Y,
|
||||
CONF_SCROLL_DIR,
|
||||
CONF_SCROLLBAR_MODE,
|
||||
}
|
||||
|
||||
# Also allow widget specific properties for use in style definitions
|
||||
FULL_STYLE_SCHEMA = STYLE_SCHEMA.extend(
|
||||
{
|
||||
@@ -422,7 +440,10 @@ def any_widget_schema(extras=None):
|
||||
def validator(value):
|
||||
if isinstance(value, dict):
|
||||
# Convert to list
|
||||
is_dict = True
|
||||
value = [{k: v} for k, v in value.items()]
|
||||
else:
|
||||
is_dict = False
|
||||
if not isinstance(value, list):
|
||||
raise cv.Invalid("Expected a list of widgets")
|
||||
result = []
|
||||
@@ -443,7 +464,9 @@ def any_widget_schema(extras=None):
|
||||
)
|
||||
# Apply custom validation
|
||||
value = widget_type.validate(value or {})
|
||||
result.append({key: container_validator(value)})
|
||||
path = [key] if is_dict else [index, key]
|
||||
with prepend_path(path):
|
||||
result.append({key: container_validator(value)})
|
||||
return result
|
||||
|
||||
return validator
|
||||
|
||||
@@ -21,7 +21,6 @@ from ..defines import (
|
||||
CONF_MAIN,
|
||||
CONF_PAD_COLUMN,
|
||||
CONF_PAD_ROW,
|
||||
CONF_SCROLLBAR_MODE,
|
||||
CONF_STYLES,
|
||||
CONF_WIDGETS,
|
||||
OBJ_FLAGS,
|
||||
@@ -45,7 +44,7 @@ from ..lvcode import (
|
||||
lv_obj,
|
||||
lv_Pvariable,
|
||||
)
|
||||
from ..schemas import ALL_STYLES, STYLE_REMAP, WIDGET_TYPES
|
||||
from ..schemas import ALL_STYLES, OBJ_PROPERTIES, STYLE_REMAP, WIDGET_TYPES
|
||||
from ..types import LV_STATE, LvType, WidgetType, lv_coord_t, lv_obj_t, lv_obj_t_ptr
|
||||
|
||||
EVENT_LAMB = "event_lamb__"
|
||||
@@ -414,7 +413,8 @@ async def set_obj_properties(w: Widget, config):
|
||||
w.add_state(state)
|
||||
cond.else_()
|
||||
w.clear_state(state)
|
||||
await w.set_property(CONF_SCROLLBAR_MODE, config, lv_name="obj")
|
||||
for property in OBJ_PROPERTIES:
|
||||
await w.set_property(property, config, lv_name="obj")
|
||||
|
||||
|
||||
async def add_widgets(parent: Widget, config: dict):
|
||||
|
||||
@@ -20,7 +20,13 @@ from ..defines import (
|
||||
CONF_START_ANGLE,
|
||||
literal,
|
||||
)
|
||||
from ..lv_validation import get_start_value, lv_angle_degrees, lv_float, lv_int
|
||||
from ..lv_validation import (
|
||||
get_start_value,
|
||||
lv_angle_degrees,
|
||||
lv_float,
|
||||
lv_int,
|
||||
lv_positive_int,
|
||||
)
|
||||
from ..lvcode import lv, lv_expr, lv_obj
|
||||
from ..types import LvNumber, NumberType
|
||||
from . import Widget
|
||||
@@ -36,13 +42,20 @@ ARC_SCHEMA = cv.Schema(
|
||||
cv.Optional(CONF_ROTATION, default=0.0): lv_angle_degrees,
|
||||
cv.Optional(CONF_ADJUSTABLE, default=False): bool,
|
||||
cv.Optional(CONF_MODE, default="NORMAL"): ARC_MODES.one_of,
|
||||
cv.Optional(CONF_CHANGE_RATE, default=720): cv.uint16_t,
|
||||
cv.Optional(CONF_CHANGE_RATE, default=720): lv_positive_int,
|
||||
}
|
||||
)
|
||||
|
||||
ARC_MODIFY_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_VALUE): lv_float,
|
||||
cv.Optional(CONF_MIN_VALUE): lv_int,
|
||||
cv.Optional(CONF_MAX_VALUE): lv_int,
|
||||
cv.Optional(CONF_START_ANGLE): lv_angle_degrees,
|
||||
cv.Optional(CONF_END_ANGLE): lv_angle_degrees,
|
||||
cv.Optional(CONF_ROTATION): lv_angle_degrees,
|
||||
cv.Optional(CONF_MODE): ARC_MODES.one_of,
|
||||
cv.Optional(CONF_CHANGE_RATE): lv_positive_int,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -58,17 +71,34 @@ class ArcType(NumberType):
|
||||
)
|
||||
|
||||
async def to_code(self, w: Widget, config):
|
||||
if CONF_MIN_VALUE in config:
|
||||
if CONF_MIN_VALUE in config and CONF_MAX_VALUE in config:
|
||||
max_value = await lv_int.process(config[CONF_MAX_VALUE])
|
||||
min_value = await lv_int.process(config[CONF_MIN_VALUE])
|
||||
lv.arc_set_range(w.obj, min_value, max_value)
|
||||
start = await lv_angle_degrees.process(config[CONF_START_ANGLE])
|
||||
end = await lv_angle_degrees.process(config[CONF_END_ANGLE])
|
||||
rotation = await lv_angle_degrees.process(config[CONF_ROTATION])
|
||||
lv.arc_set_bg_angles(w.obj, start, end)
|
||||
lv.arc_set_rotation(w.obj, rotation)
|
||||
lv.arc_set_mode(w.obj, literal(config[CONF_MODE]))
|
||||
lv.arc_set_change_rate(w.obj, config[CONF_CHANGE_RATE])
|
||||
elif CONF_MIN_VALUE in config:
|
||||
max_value = w.get_property(CONF_MAX_VALUE)
|
||||
min_value = await lv_int.process(config[CONF_MIN_VALUE])
|
||||
lv.arc_set_range(w.obj, min_value, max_value)
|
||||
elif CONF_MAX_VALUE in config:
|
||||
max_value = await lv_int.process(config[CONF_MAX_VALUE])
|
||||
min_value = w.get_property(CONF_MIN_VALUE)
|
||||
lv.arc_set_range(w.obj, min_value, max_value)
|
||||
|
||||
await w.set_property(
|
||||
CONF_START_ANGLE,
|
||||
await lv_angle_degrees.process(config.get(CONF_START_ANGLE)),
|
||||
)
|
||||
await w.set_property(
|
||||
CONF_END_ANGLE, await lv_angle_degrees.process(config.get(CONF_END_ANGLE))
|
||||
)
|
||||
await w.set_property(
|
||||
CONF_ROTATION, await lv_angle_degrees.process(config.get(CONF_ROTATION))
|
||||
)
|
||||
await w.set_property(CONF_MODE, config)
|
||||
await w.set_property(
|
||||
CONF_CHANGE_RATE,
|
||||
await lv_positive_int.process(config.get(CONF_CHANGE_RATE)),
|
||||
)
|
||||
|
||||
if CONF_ADJUSTABLE in config:
|
||||
if not config[CONF_ADJUSTABLE]:
|
||||
@@ -78,9 +108,7 @@ class ArcType(NumberType):
|
||||
# For some reason arc does not get automatically added to the default group
|
||||
lv.group_add_obj(lv_expr.group_get_default(), w.obj)
|
||||
|
||||
value = await get_start_value(config)
|
||||
if value is not None:
|
||||
lv.arc_set_value(w.obj, value)
|
||||
await w.set_property(CONF_VALUE, await get_start_value(config))
|
||||
|
||||
|
||||
arc_spec = ArcType()
|
||||
|
||||
@@ -6,7 +6,7 @@ from esphome.core import Lambda
|
||||
from ..defines import CONF_MAIN, call_lambda
|
||||
from ..lvcode import lv_add
|
||||
from ..schemas import point_schema
|
||||
from ..types import LvCompound, LvType
|
||||
from ..types import LvCompound, LvType, lv_coord_t
|
||||
from . import Widget, WidgetType
|
||||
|
||||
CONF_LINE = "line"
|
||||
@@ -23,9 +23,7 @@ LINE_SCHEMA = {
|
||||
|
||||
async def process_coord(coord):
|
||||
if isinstance(coord, Lambda):
|
||||
coord = call_lambda(
|
||||
await cg.process_lambda(coord, [], return_type="lv_coord_t")
|
||||
)
|
||||
coord = call_lambda(await cg.process_lambda(coord, [], return_type=lv_coord_t))
|
||||
if not coord.endswith("()"):
|
||||
coord = f"static_cast<lv_coord_t>({coord})"
|
||||
return cg.RawExpression(coord)
|
||||
|
||||
@@ -174,6 +174,9 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
|
||||
// Check if baud rate is supported
|
||||
this->original_baud_rate_ = this->parent_->get_baud_rate();
|
||||
if (baud_rate <= 0) {
|
||||
baud_rate = this->original_baud_rate_;
|
||||
}
|
||||
ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate);
|
||||
|
||||
// Define the configuration for the HTTP client
|
||||
|
||||
@@ -177,6 +177,9 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
|
||||
// Check if baud rate is supported
|
||||
this->original_baud_rate_ = this->parent_->get_baud_rate();
|
||||
if (baud_rate <= 0) {
|
||||
baud_rate = this->original_baud_rate_;
|
||||
}
|
||||
ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate);
|
||||
|
||||
// Define the configuration for the HTTP client
|
||||
|
||||
@@ -278,7 +278,12 @@ template<class C, typename... Ts> class ScriptWaitAction : public Action<Ts...>,
|
||||
|
||||
void setup() override {
|
||||
// Start with loop disabled - only enable when there's work to do
|
||||
this->disable_loop();
|
||||
// IMPORTANT: Only disable if num_running_ is 0, otherwise play_complex() was already
|
||||
// called before our setup() (e.g., from on_boot trigger at same priority level)
|
||||
// and we must not undo its enable_loop() call
|
||||
if (this->num_running_ == 0) {
|
||||
this->disable_loop();
|
||||
}
|
||||
}
|
||||
|
||||
void play_complex(const Ts &...x) override {
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace sht4x {
|
||||
static const char *const TAG = "sht4x";
|
||||
|
||||
static const uint8_t MEASURECOMMANDS[] = {0xFD, 0xF6, 0xE0};
|
||||
static const uint8_t SERIAL_NUMBER_COMMAND = 0x89;
|
||||
|
||||
void SHT4XComponent::start_heater_() {
|
||||
uint8_t cmd[] = {MEASURECOMMANDS[this->heater_command_]};
|
||||
@@ -17,6 +18,17 @@ void SHT4XComponent::start_heater_() {
|
||||
}
|
||||
}
|
||||
|
||||
void SHT4XComponent::read_serial_number_() {
|
||||
uint16_t buffer[2];
|
||||
if (!this->get_8bit_register(SERIAL_NUMBER_COMMAND, buffer, 2, 1)) {
|
||||
ESP_LOGE(TAG, "Get serial number failed");
|
||||
this->serial_number_ = 0;
|
||||
return;
|
||||
}
|
||||
this->serial_number_ = (uint32_t(buffer[0]) << 16) | (uint32_t(buffer[1]));
|
||||
ESP_LOGD(TAG, "Serial number: %08" PRIx32, this->serial_number_);
|
||||
}
|
||||
|
||||
void SHT4XComponent::setup() {
|
||||
auto err = this->write(nullptr, 0);
|
||||
if (err != i2c::ERROR_OK) {
|
||||
@@ -24,6 +36,8 @@ void SHT4XComponent::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
this->read_serial_number_();
|
||||
|
||||
if (std::isfinite(this->duty_cycle_) && this->duty_cycle_ > 0.0f) {
|
||||
uint32_t heater_interval = static_cast<uint32_t>(static_cast<uint16_t>(this->heater_time_) / this->duty_cycle_);
|
||||
ESP_LOGD(TAG, "Heater interval: %" PRIu32, heater_interval);
|
||||
@@ -54,11 +68,18 @@ void SHT4XComponent::setup() {
|
||||
}
|
||||
|
||||
void SHT4XComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "SHT4x:");
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"SHT4x:\n"
|
||||
" Serial number: %08" PRIx32,
|
||||
this->serial_number_);
|
||||
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
}
|
||||
if (this->serial_number_ == 0) {
|
||||
ESP_LOGW(TAG, "Get serial number failed");
|
||||
}
|
||||
}
|
||||
|
||||
void SHT4XComponent::update() {
|
||||
|
||||
@@ -36,7 +36,9 @@ class SHT4XComponent : public PollingComponent, public sensirion_common::Sensiri
|
||||
float duty_cycle_;
|
||||
|
||||
void start_heater_();
|
||||
void read_serial_number_();
|
||||
uint8_t heater_command_;
|
||||
uint32_t serial_number_;
|
||||
|
||||
sensor::Sensor *temp_sensor_{nullptr};
|
||||
sensor::Sensor *humidity_sensor_{nullptr};
|
||||
|
||||
@@ -14,7 +14,7 @@ static constexpr size_t MAX_STATE_LENGTH = 255;
|
||||
|
||||
void IPAddressWiFiInfo::setup() {
|
||||
wifi::global_wifi_component->add_on_ip_state_callback(
|
||||
[this](network::IPAddresses ips, network::IPAddress dns1_ip, network::IPAddress dns2_ip) {
|
||||
[this](const network::IPAddresses &ips, const network::IPAddress &dns1_ip, const network::IPAddress &dns2_ip) {
|
||||
this->state_callback_(ips);
|
||||
});
|
||||
}
|
||||
@@ -24,7 +24,7 @@ void IPAddressWiFiInfo::dump_config() { LOG_TEXT_SENSOR("", "IP Address", this);
|
||||
void IPAddressWiFiInfo::state_callback_(const network::IPAddresses &ips) {
|
||||
this->publish_state(ips[0].str());
|
||||
uint8_t sensor = 0;
|
||||
for (auto &ip : ips) {
|
||||
for (const auto &ip : ips) {
|
||||
if (ip.is_set()) {
|
||||
if (this->ip_sensors_[sensor] != nullptr) {
|
||||
this->ip_sensors_[sensor]->publish_state(ip.str());
|
||||
@@ -40,14 +40,14 @@ void IPAddressWiFiInfo::state_callback_(const network::IPAddresses &ips) {
|
||||
|
||||
void DNSAddressWifiInfo::setup() {
|
||||
wifi::global_wifi_component->add_on_ip_state_callback(
|
||||
[this](network::IPAddresses ips, network::IPAddress dns1_ip, network::IPAddress dns2_ip) {
|
||||
[this](const network::IPAddresses &ips, const network::IPAddress &dns1_ip, const network::IPAddress &dns2_ip) {
|
||||
this->state_callback_(dns1_ip, dns2_ip);
|
||||
});
|
||||
}
|
||||
|
||||
void DNSAddressWifiInfo::dump_config() { LOG_TEXT_SENSOR("", "DNS Address", this); }
|
||||
|
||||
void DNSAddressWifiInfo::state_callback_(network::IPAddress dns1_ip, network::IPAddress dns2_ip) {
|
||||
void DNSAddressWifiInfo::state_callback_(const network::IPAddress &dns1_ip, const network::IPAddress &dns2_ip) {
|
||||
std::string dns_results = dns1_ip.str() + " " + dns2_ip.str();
|
||||
this->publish_state(dns_results);
|
||||
}
|
||||
@@ -87,7 +87,7 @@ void ScanResultsWiFiInfo::state_callback_(const wifi::wifi_scan_vector_t<wifi::W
|
||||
|
||||
void SSIDWiFiInfo::setup() {
|
||||
wifi::global_wifi_component->add_on_wifi_connect_state_callback(
|
||||
[this](const std::string &ssid, wifi::bssid_t bssid) { this->state_callback_(ssid); });
|
||||
[this](const std::string &ssid, const wifi::bssid_t &bssid) { this->state_callback_(ssid); });
|
||||
}
|
||||
|
||||
void SSIDWiFiInfo::dump_config() { LOG_TEXT_SENSOR("", "SSID", this); }
|
||||
@@ -100,12 +100,12 @@ void SSIDWiFiInfo::state_callback_(const std::string &ssid) { this->publish_stat
|
||||
|
||||
void BSSIDWiFiInfo::setup() {
|
||||
wifi::global_wifi_component->add_on_wifi_connect_state_callback(
|
||||
[this](const std::string &ssid, wifi::bssid_t bssid) { this->state_callback_(bssid); });
|
||||
[this](const std::string &ssid, const wifi::bssid_t &bssid) { this->state_callback_(bssid); });
|
||||
}
|
||||
|
||||
void BSSIDWiFiInfo::dump_config() { LOG_TEXT_SENSOR("", "BSSID", this); }
|
||||
|
||||
void BSSIDWiFiInfo::state_callback_(wifi::bssid_t bssid) {
|
||||
void BSSIDWiFiInfo::state_callback_(const wifi::bssid_t &bssid) {
|
||||
char buf[18] = "unknown";
|
||||
if (mac_address_is_valid(bssid.data())) {
|
||||
format_mac_addr_upper(bssid.data(), buf);
|
||||
|
||||
@@ -26,7 +26,7 @@ class DNSAddressWifiInfo : public Component, public text_sensor::TextSensor {
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
void state_callback_(network::IPAddress dns1_ip, network::IPAddress dns2_ip);
|
||||
void state_callback_(const network::IPAddress &dns1_ip, const network::IPAddress &dns2_ip);
|
||||
};
|
||||
|
||||
class ScanResultsWiFiInfo : public Component, public text_sensor::TextSensor {
|
||||
@@ -54,7 +54,7 @@ class BSSIDWiFiInfo : public Component, public text_sensor::TextSensor {
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
void state_callback_(wifi::bssid_t bssid);
|
||||
void state_callback_(const wifi::bssid_t &bssid);
|
||||
};
|
||||
|
||||
class MacAddressWifiInfo : public Component, public text_sensor::TextSensor {
|
||||
|
||||
Reference in New Issue
Block a user