Merge pull request #7363 from esphome/bump-2024.8.1
Some checks failed
CI / Create common environment (push) Has been cancelled
YAML lint / yamllint (push) Has been cancelled
CI / Check black (push) Has been cancelled
CI / Check flake8 (push) Has been cancelled
CI / Check pylint (push) Has been cancelled
CI / Check pyupgrade (push) Has been cancelled
CI / Run script/ci-custom (push) Has been cancelled
CI / Run pytest (macOS-latest, 3.11) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.10) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.11) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.12) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.9) (push) Has been cancelled
CI / Run pytest (windows-latest, 3.11) (push) Has been cancelled
CI / Check clang-format (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 1/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 2/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 3/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 4/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 IDF (push) Has been cancelled
CI / Run script/clang-tidy for ESP8266 (push) Has been cancelled
CI / list-components (push) Has been cancelled
CI / Component test ${{ matrix.file }} (push) Has been cancelled
CI / Split components for testing into 20 groups maximum (push) Has been cancelled
CI / Test split components (push) Has been cancelled
CI / CI Status (push) Has been cancelled

2024.8.1
This commit is contained in:
Jesse Hills 2024-08-28 13:37:48 +12:00 committed by GitHub
commit 8b6c95f723
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 78 additions and 21 deletions

View file

@ -179,6 +179,7 @@ void APIConnection::loop() {
SubscribeHomeAssistantStateResponse resp; SubscribeHomeAssistantStateResponse resp;
resp.entity_id = it.entity_id; resp.entity_id = it.entity_id;
resp.attribute = it.attribute.value(); resp.attribute = it.attribute.value();
resp.once = it.once;
if (this->send_subscribe_home_assistant_state_response(resp)) { if (this->send_subscribe_home_assistant_state_response(resp)) {
state_subs_at_++; state_subs_at_++;
} }

View file

@ -266,7 +266,10 @@ async def to_code(config):
await add_top_layer(config) await add_top_layer(config)
await msgboxes_to_code(config) await msgboxes_to_code(config)
await disp_update(f"{lv_component}->get_disp()", config) await disp_update(f"{lv_component}->get_disp()", config)
Widget.set_completed() # At this point only the setup code should be generated
assert LvContext.added_lambda_count == 1
Widget.set_completed()
async with LvContext(lv_component):
await generate_triggers(lv_component) await generate_triggers(lv_component)
for conf in config.get(CONF_ON_IDLE, ()): for conf in config.get(CONF_ON_IDLE, ()):
templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32) templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32)

View file

@ -5,6 +5,7 @@ from esphome import automation
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_TIMEOUT from esphome.const import CONF_ID, CONF_TIMEOUT
from esphome.cpp_generator import RawExpression
from esphome.cpp_types import nullptr from esphome.cpp_types import nullptr
from .defines import ( from .defines import (
@ -26,6 +27,7 @@ from .lvcode import (
add_line_marks, add_line_marks,
lv, lv,
lv_add, lv_add,
lv_expr,
lv_obj, lv_obj,
lvgl_comp, lvgl_comp,
) )
@ -38,7 +40,13 @@ from .types import (
lv_disp_t, lv_disp_t,
lv_obj_t, lv_obj_t,
) )
from .widgets import Widget, get_widgets, lv_scr_act, set_obj_properties from .widgets import (
Widget,
get_widgets,
lv_scr_act,
set_obj_properties,
wait_for_widgets,
)
async def action_to_code( async def action_to_code(
@ -48,10 +56,12 @@ async def action_to_code(
template_arg, template_arg,
args, args,
): ):
await wait_for_widgets()
async with LambdaContext(parameters=args, where=action_id) as context: async with LambdaContext(parameters=args, where=action_id) as context:
with LvConditional(lv_expr.is_pre_initialise()):
context.add(RawExpression("return"))
for widget in widgets: for widget in widgets:
with LvConditional(widget.obj != nullptr): await action(widget)
await action(widget)
var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
return var return var

View file

@ -10,7 +10,7 @@ from ..defines import CONF_LVGL_ID, CONF_WIDGET
from ..lvcode import EVENT_ARG, LambdaContext, LvContext from ..lvcode import EVENT_ARG, LambdaContext, LvContext
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LV_EVENT, lv_pseudo_button_t from ..types import LV_EVENT, lv_pseudo_button_t
from ..widgets import Widget, get_widgets from ..widgets import Widget, get_widgets, wait_for_widgets
CONFIG_SCHEMA = ( CONFIG_SCHEMA = (
binary_sensor_schema(BinarySensor) binary_sensor_schema(BinarySensor)
@ -29,6 +29,7 @@ async def to_code(config):
widget = await get_widgets(config, CONF_WIDGET) widget = await get_widgets(config, CONF_WIDGET)
widget = widget[0] widget = widget[0]
assert isinstance(widget, Widget) assert isinstance(widget, Widget)
await wait_for_widgets()
async with LambdaContext(EVENT_ARG) as pressed_ctx: async with LambdaContext(EVENT_ARG) as pressed_ctx:
pressed_ctx.add(sensor.publish_state(widget.is_pressed())) pressed_ctx.add(sensor.publish_state(widget.is_pressed()))
async with LvContext(paren) as ctx: async with LvContext(paren) as ctx:

View file

@ -8,7 +8,7 @@ from ..defines import CONF_LVGL_ID
from ..lvcode import LvContext from ..lvcode import LvContext
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LvType, lvgl_ns from ..types import LvType, lvgl_ns
from ..widgets import get_widgets from ..widgets import get_widgets, wait_for_widgets
lv_led_t = LvType("lv_led_t") lv_led_t = LvType("lv_led_t")
LVLight = lvgl_ns.class_("LVLight", LightOutput) LVLight = lvgl_ns.class_("LVLight", LightOutput)
@ -28,5 +28,6 @@ async def to_code(config):
paren = await cg.get_variable(config[CONF_LVGL_ID]) paren = await cg.get_variable(config[CONF_LVGL_ID])
widget = await get_widgets(config, CONF_LED) widget = await get_widgets(config, CONF_LED)
widget = widget[0] widget = widget[0]
await wait_for_widgets()
async with LvContext(paren) as ctx: async with LvContext(paren) as ctx:
ctx.add(var.set_obj(widget.obj)) ctx.add(var.set_obj(widget.obj))

View file

@ -176,6 +176,8 @@ class LvContext(LambdaContext):
Code generation into the LVGL initialisation code (called in `setup()`) Code generation into the LVGL initialisation code (called in `setup()`)
""" """
added_lambda_count = 0
def __init__(self, lv_component, args=None): def __init__(self, lv_component, args=None):
self.args = args or LVGL_COMP_ARG self.args = args or LVGL_COMP_ARG
super().__init__(parameters=self.args) super().__init__(parameters=self.args)
@ -183,6 +185,7 @@ class LvContext(LambdaContext):
async def add_init_lambda(self): async def add_init_lambda(self):
cg.add(self.lv_component.add_init_lambda(await self.get_lambda())) cg.add(self.lv_component.add_init_lambda(await self.get_lambda()))
LvContext.added_lambda_count += 1
async def __aexit__(self, exc_type, exc_val, exc_tb): async def __aexit__(self, exc_type, exc_val, exc_tb):
await super().__aexit__(exc_type, exc_val, exc_tb) await super().__aexit__(exc_type, exc_val, exc_tb)

View file

@ -294,6 +294,13 @@ void LvglComponent::loop() {
} }
lv_timer_handler_run_in_period(5); lv_timer_handler_run_in_period(5);
} }
bool lv_is_pre_initialise() {
if (!lv_is_initialized()) {
ESP_LOGE(TAG, "LVGL call before component is initialised");
return true;
}
return false;
}
#ifdef USE_LVGL_IMAGE #ifdef USE_LVGL_IMAGE
lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc) { lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc) {

View file

@ -40,6 +40,7 @@ namespace lvgl {
extern lv_event_code_t lv_api_event; // NOLINT extern lv_event_code_t lv_api_event; // NOLINT
extern lv_event_code_t lv_update_event; // NOLINT extern lv_event_code_t lv_update_event; // NOLINT
extern bool lv_is_pre_initialise();
#ifdef USE_LVGL_COLOR #ifdef USE_LVGL_COLOR
inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); }
#endif // USE_LVGL_COLOR #endif // USE_LVGL_COLOR

View file

@ -16,7 +16,7 @@ from ..lvcode import (
) )
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LV_EVENT, LvNumber, lvgl_ns from ..types import LV_EVENT, LvNumber, lvgl_ns
from ..widgets import get_widgets from ..widgets import get_widgets, wait_for_widgets
LVGLNumber = lvgl_ns.class_("LVGLNumber", number.Number) LVGLNumber = lvgl_ns.class_("LVGLNumber", number.Number)
@ -44,6 +44,7 @@ async def to_code(config):
step=widget.get_step(), step=widget.get_step(),
) )
await wait_for_widgets()
async with LambdaContext([(cg.float_, "v")]) as control: async with LambdaContext([(cg.float_, "v")]) as control:
await widget.set_property( await widget.set_property(
"value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED] "value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED]

View file

@ -15,7 +15,7 @@ from ..lvcode import (
) )
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LV_EVENT, LvSelect, lvgl_ns from ..types import LV_EVENT, LvSelect, lvgl_ns
from ..widgets import get_widgets from ..widgets import get_widgets, wait_for_widgets
LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select) LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select)
@ -37,6 +37,7 @@ async def to_code(config):
options = widget.config.get(CONF_OPTIONS, []) options = widget.config.get(CONF_OPTIONS, [])
selector = await select.new_select(config, options=options) selector = await select.new_select(config, options=options)
paren = await cg.get_variable(config[CONF_LVGL_ID]) paren = await cg.get_variable(config[CONF_LVGL_ID])
await wait_for_widgets()
async with LambdaContext(EVENT_ARG) as pub_ctx: async with LambdaContext(EVENT_ARG) as pub_ctx:
pub_ctx.add(selector.publish_index(widget.get_value())) pub_ctx.add(selector.publish_index(widget.get_value()))
async with LambdaContext([(cg.uint16, "v")]) as control: async with LambdaContext([(cg.uint16, "v")]) as control:

View file

@ -14,7 +14,7 @@ from ..lvcode import (
) )
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LV_EVENT, LvNumber from ..types import LV_EVENT, LvNumber
from ..widgets import Widget, get_widgets from ..widgets import Widget, get_widgets, wait_for_widgets
CONFIG_SCHEMA = ( CONFIG_SCHEMA = (
sensor_schema(Sensor) sensor_schema(Sensor)
@ -33,6 +33,7 @@ async def to_code(config):
widget = await get_widgets(config, CONF_WIDGET) widget = await get_widgets(config, CONF_WIDGET)
widget = widget[0] widget = widget[0]
assert isinstance(widget, Widget) assert isinstance(widget, Widget)
await wait_for_widgets()
async with LambdaContext(EVENT_ARG) as lamb: async with LambdaContext(EVENT_ARG) as lamb:
lv_add(sensor.publish_state(widget.get_value())) lv_add(sensor.publish_state(widget.get_value()))
async with LvContext(paren, LVGL_COMP_ARG): async with LvContext(paren, LVGL_COMP_ARG):

View file

@ -16,7 +16,7 @@ from ..lvcode import (
) )
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LV_EVENT, LV_STATE, lv_pseudo_button_t, lvgl_ns from ..types import LV_EVENT, LV_STATE, lv_pseudo_button_t, lvgl_ns
from ..widgets import get_widgets from ..widgets import get_widgets, wait_for_widgets
LVGLSwitch = lvgl_ns.class_("LVGLSwitch", Switch) LVGLSwitch = lvgl_ns.class_("LVGLSwitch", Switch)
CONFIG_SCHEMA = ( CONFIG_SCHEMA = (
@ -35,6 +35,7 @@ async def to_code(config):
paren = await cg.get_variable(config[CONF_LVGL_ID]) paren = await cg.get_variable(config[CONF_LVGL_ID])
widget = await get_widgets(config, CONF_WIDGET) widget = await get_widgets(config, CONF_WIDGET)
widget = widget[0] widget = widget[0]
await wait_for_widgets()
async with LambdaContext(EVENT_ARG) as checked_ctx: async with LambdaContext(EVENT_ARG) as checked_ctx:
checked_ctx.add(switch.publish_state(widget.get_value())) checked_ctx.add(switch.publish_state(widget.get_value()))
async with LambdaContext([(cg.bool_, "v")]) as control: async with LambdaContext([(cg.bool_, "v")]) as control:

View file

@ -15,7 +15,7 @@ from ..lvcode import (
) )
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LV_EVENT, LvText, lvgl_ns from ..types import LV_EVENT, LvText, lvgl_ns
from ..widgets import get_widgets from ..widgets import get_widgets, wait_for_widgets
LVGLText = lvgl_ns.class_("LVGLText", text.Text) LVGLText = lvgl_ns.class_("LVGLText", text.Text)
@ -32,6 +32,7 @@ async def to_code(config):
paren = await cg.get_variable(config[CONF_LVGL_ID]) paren = await cg.get_variable(config[CONF_LVGL_ID])
widget = await get_widgets(config, CONF_WIDGET) widget = await get_widgets(config, CONF_WIDGET)
widget = widget[0] widget = widget[0]
await wait_for_widgets()
async with LambdaContext([(cg.std_string, "text_value")]) as control: async with LambdaContext([(cg.std_string, "text_value")]) as control:
await widget.set_property("text", "text_value.c_str())") await widget.set_property("text", "text_value.c_str())")
lv.event_send(widget.obj, API_EVENT, None) lv.event_send(widget.obj, API_EVENT, None)

View file

@ -10,7 +10,7 @@ from ..defines import CONF_LVGL_ID, CONF_WIDGET
from ..lvcode import API_EVENT, EVENT_ARG, UPDATE_EVENT, LambdaContext, LvContext from ..lvcode import API_EVENT, EVENT_ARG, UPDATE_EVENT, LambdaContext, LvContext
from ..schemas import LVGL_SCHEMA from ..schemas import LVGL_SCHEMA
from ..types import LV_EVENT, LvText from ..types import LV_EVENT, LvText
from ..widgets import get_widgets from ..widgets import get_widgets, wait_for_widgets
CONFIG_SCHEMA = ( CONFIG_SCHEMA = (
text_sensor_schema(TextSensor) text_sensor_schema(TextSensor)
@ -28,6 +28,7 @@ async def to_code(config):
paren = await cg.get_variable(config[CONF_LVGL_ID]) paren = await cg.get_variable(config[CONF_LVGL_ID])
widget = await get_widgets(config, CONF_WIDGET) widget = await get_widgets(config, CONF_WIDGET)
widget = widget[0] widget = widget[0]
await wait_for_widgets()
async with LambdaContext(EVENT_ARG) as pressed_ctx: async with LambdaContext(EVENT_ARG) as pressed_ctx:
pressed_ctx.add(sensor.publish_state(widget.get_value())) pressed_ctx.add(sensor.publish_state(widget.get_value()))
async with LvContext(paren) as ctx: async with LvContext(paren) as ctx:

View file

@ -223,6 +223,19 @@ async def get_widget_(wid: Widget):
return await FakeAwaitable(get_widget_generator(wid)) return await FakeAwaitable(get_widget_generator(wid))
def widgets_wait_generator():
while True:
if Widget.widgets_completed:
return
yield
async def wait_for_widgets():
if Widget.widgets_completed:
return
await FakeAwaitable(widgets_wait_generator())
async def get_widgets(config: Union[dict, list], id: str = CONF_ID) -> list[Widget]: async def get_widgets(config: Union[dict, list], id: str = CONF_ID) -> list[Widget]:
if not config: if not config:
return [] return []

View file

@ -3,7 +3,7 @@ import functools
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from ..defines import CONF_MAIN, literal from ..defines import CONF_MAIN
from ..lvcode import lv from ..lvcode import lv
from ..types import LvType from ..types import LvType
from . import Widget, WidgetType from . import Widget, WidgetType
@ -38,13 +38,15 @@ LINE_SCHEMA = {
class LineType(WidgetType): class LineType(WidgetType):
def __init__(self): def __init__(self):
super().__init__(CONF_LINE, LvType("lv_line_t"), (CONF_MAIN,), LINE_SCHEMA) super().__init__(
CONF_LINE, LvType("lv_line_t"), (CONF_MAIN,), LINE_SCHEMA, modify_schema={}
)
async def to_code(self, w: Widget, config): async def to_code(self, w: Widget, config):
"""For a line object, create and add the points""" """For a line object, create and add the points"""
data = literal(config[CONF_POINTS]) if data := config.get(CONF_POINTS):
points = cg.static_const_array(config[CONF_POINT_LIST_ID], data) points = cg.static_const_array(config[CONF_POINT_LIST_ID], data)
lv.line_set_points(w.obj, points, len(data)) lv.line_set_points(w.obj, points, len(data))
line_spec = LineType() line_spec = LineType()

View file

@ -13,7 +13,7 @@ from ..defines import (
TYPE_FLEX, TYPE_FLEX,
literal, literal,
) )
from ..helpers import add_lv_use from ..helpers import add_lv_use, lvgl_components_required
from ..lv_validation import lv_bool, lv_pct, lv_text from ..lv_validation import lv_bool, lv_pct, lv_text
from ..lvcode import ( from ..lvcode import (
EVENT_ARG, EVENT_ARG,
@ -72,6 +72,7 @@ async def msgbox_to_code(conf):
*buttonmatrix_spec.get_uses(), *buttonmatrix_spec.get_uses(),
*button_spec.get_uses(), *button_spec.get_uses(),
) )
lvgl_components_required.add("BUTTONMATRIX")
messagebox_id = conf[CONF_ID] messagebox_id = conf[CONF_ID]
outer = lv_Pvariable(lv_obj_t, messagebox_id.id) outer = lv_Pvariable(lv_obj_t, messagebox_id.id)
buttonmatrix = new_Pvariable( buttonmatrix = new_Pvariable(

View file

@ -1,6 +1,6 @@
"""Constants used by esphome.""" """Constants used by esphome."""
__version__ = "2024.8.0" __version__ = "2024.8.1"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = ( VALID_SUBSTITUTIONS_CHARACTERS = (

View file

@ -106,6 +106,8 @@ def storage_should_clean(old: StorageJSON, new: StorageJSON) -> bool:
return True return True
if old.build_path != new.build_path: if old.build_path != new.build_path:
return True return True
if old.loaded_integrations != new.loaded_integrations:
return True
return False return False
@ -117,7 +119,9 @@ def update_storage_json():
return return
if storage_should_clean(old, new): if storage_should_clean(old, new):
_LOGGER.info("Core config or version changed, cleaning build files...") _LOGGER.info(
"Core config, version or integrations changed, cleaning build files..."
)
clean_build() clean_build()
new.save(path) new.save(path)

View file

@ -379,6 +379,7 @@ lvgl:
format: "bar value %f" format: "bar value %f"
args: [x] args: [x]
- line: - line:
id: lv_line_id
align: center align: center
points: points:
- 5, 5 - 5, 5
@ -387,7 +388,10 @@ lvgl:
- 180, 60 - 180, 60
- 240, 10 - 240, 10
on_click: on_click:
lvgl.page.next: - lvgl.widget.update:
id: lv_line_id
line_color: 0xFFFF
- lvgl.page.next:
- switch: - switch:
align: right_mid align: right_mid
- checkbox: - checkbox: