mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
[lvgl] Fix compile error when using encoder with buttons only. (#7203)
This commit is contained in:
parent
8667f51cf0
commit
eccc5a3ea3
9 changed files with 68 additions and 58 deletions
|
@ -23,9 +23,9 @@ from esphome.helpers import write_file_if_changed
|
||||||
from . import defines as df, helpers, lv_validation as lvalid
|
from . import defines as df, helpers, lv_validation as lvalid
|
||||||
from .automation import disp_update, update_to_code
|
from .automation import disp_update, update_to_code
|
||||||
from .defines import CONF_SKIP
|
from .defines import CONF_SKIP
|
||||||
|
from .encoders import ENCODERS_CONFIG, encoders_to_code
|
||||||
from .lv_validation import lv_bool, lv_images_used
|
from .lv_validation import lv_bool, lv_images_used
|
||||||
from .lvcode import LvContext, LvglComponent
|
from .lvcode import LvContext, LvglComponent
|
||||||
from .rotary_encoders import ROTARY_ENCODER_CONFIG, rotary_encoders_to_code
|
|
||||||
from .schemas import (
|
from .schemas import (
|
||||||
DISP_BG_SCHEMA,
|
DISP_BG_SCHEMA,
|
||||||
FLEX_OBJ_SCHEMA,
|
FLEX_OBJ_SCHEMA,
|
||||||
|
@ -256,7 +256,7 @@ async def to_code(config):
|
||||||
|
|
||||||
async with LvContext(lv_component):
|
async with LvContext(lv_component):
|
||||||
await touchscreens_to_code(lv_component, config)
|
await touchscreens_to_code(lv_component, config)
|
||||||
await rotary_encoders_to_code(lv_component, config)
|
await encoders_to_code(lv_component, config)
|
||||||
await theme_to_code(config)
|
await theme_to_code(config)
|
||||||
await styles_to_code(config)
|
await styles_to_code(config)
|
||||||
await set_obj_properties(lv_scr_act, config)
|
await set_obj_properties(lv_scr_act, config)
|
||||||
|
@ -336,7 +336,7 @@ CONFIG_SCHEMA = (
|
||||||
{cv.Optional(name): obj_schema(w) for name, w in WIDGET_TYPES.items()}
|
{cv.Optional(name): obj_schema(w) for name, w in WIDGET_TYPES.items()}
|
||||||
),
|
),
|
||||||
cv.GenerateID(df.CONF_TOUCHSCREENS): touchscreen_schema,
|
cv.GenerateID(df.CONF_TOUCHSCREENS): touchscreen_schema,
|
||||||
cv.GenerateID(df.CONF_ROTARY_ENCODERS): ROTARY_ENCODER_CONFIG,
|
cv.GenerateID(df.CONF_ENCODERS): ENCODERS_CONFIG,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(DISP_BG_SCHEMA)
|
.extend(DISP_BG_SCHEMA)
|
||||||
|
|
|
@ -388,6 +388,7 @@ CONF_DEFAULT = "default"
|
||||||
CONF_DEFAULT_FONT = "default_font"
|
CONF_DEFAULT_FONT = "default_font"
|
||||||
CONF_DIR = "dir"
|
CONF_DIR = "dir"
|
||||||
CONF_DISPLAYS = "displays"
|
CONF_DISPLAYS = "displays"
|
||||||
|
CONF_ENCODERS = "encoders"
|
||||||
CONF_END_ANGLE = "end_angle"
|
CONF_END_ANGLE = "end_angle"
|
||||||
CONF_END_VALUE = "end_value"
|
CONF_END_VALUE = "end_value"
|
||||||
CONF_ENTER_BUTTON = "enter_button"
|
CONF_ENTER_BUTTON = "enter_button"
|
||||||
|
@ -441,7 +442,6 @@ CONF_RECOLOR = "recolor"
|
||||||
CONF_RIGHT_BUTTON = "right_button"
|
CONF_RIGHT_BUTTON = "right_button"
|
||||||
CONF_ROLLOVER = "rollover"
|
CONF_ROLLOVER = "rollover"
|
||||||
CONF_ROOT_BACK_BTN = "root_back_btn"
|
CONF_ROOT_BACK_BTN = "root_back_btn"
|
||||||
CONF_ROTARY_ENCODERS = "rotary_encoders"
|
|
||||||
CONF_ROWS = "rows"
|
CONF_ROWS = "rows"
|
||||||
CONF_SCALE_LINES = "scale_lines"
|
CONF_SCALE_LINES = "scale_lines"
|
||||||
CONF_SCROLLBAR_MODE = "scrollbar_mode"
|
CONF_SCROLLBAR_MODE = "scrollbar_mode"
|
||||||
|
|
|
@ -5,25 +5,26 @@ import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_GROUP, CONF_ID, CONF_SENSOR
|
from esphome.const import CONF_GROUP, CONF_ID, CONF_SENSOR
|
||||||
|
|
||||||
from .defines import (
|
from .defines import (
|
||||||
|
CONF_ENCODERS,
|
||||||
CONF_ENTER_BUTTON,
|
CONF_ENTER_BUTTON,
|
||||||
CONF_LEFT_BUTTON,
|
CONF_LEFT_BUTTON,
|
||||||
CONF_LONG_PRESS_REPEAT_TIME,
|
CONF_LONG_PRESS_REPEAT_TIME,
|
||||||
CONF_LONG_PRESS_TIME,
|
CONF_LONG_PRESS_TIME,
|
||||||
CONF_RIGHT_BUTTON,
|
CONF_RIGHT_BUTTON,
|
||||||
CONF_ROTARY_ENCODERS,
|
|
||||||
)
|
)
|
||||||
from .helpers import lvgl_components_required
|
from .helpers import lvgl_components_required, requires_component
|
||||||
from .lvcode import lv, lv_add, lv_expr
|
from .lvcode import lv, lv_add, lv_assign, lv_expr, lv_Pvariable
|
||||||
from .schemas import ENCODER_SCHEMA
|
from .schemas import ENCODER_SCHEMA
|
||||||
from .types import lv_indev_type_t
|
from .types import lv_group_t, lv_indev_type_t
|
||||||
from .widgets import add_group
|
|
||||||
|
|
||||||
ROTARY_ENCODER_CONFIG = cv.ensure_list(
|
ENCODERS_CONFIG = cv.ensure_list(
|
||||||
ENCODER_SCHEMA.extend(
|
ENCODER_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_ENTER_BUTTON): cv.use_id(BinarySensor),
|
cv.Required(CONF_ENTER_BUTTON): cv.use_id(BinarySensor),
|
||||||
cv.Required(CONF_SENSOR): cv.Any(
|
cv.Required(CONF_SENSOR): cv.Any(
|
||||||
cv.use_id(RotaryEncoderSensor),
|
cv.All(
|
||||||
|
cv.use_id(RotaryEncoderSensor), requires_component("rotary_encoder")
|
||||||
|
),
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_LEFT_BUTTON): cv.use_id(BinarySensor),
|
cv.Required(CONF_LEFT_BUTTON): cv.use_id(BinarySensor),
|
||||||
|
@ -36,10 +37,9 @@ ROTARY_ENCODER_CONFIG = cv.ensure_list(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def rotary_encoders_to_code(var, config):
|
async def encoders_to_code(var, config):
|
||||||
for enc_conf in config.get(CONF_ROTARY_ENCODERS, ()):
|
for enc_conf in config.get(CONF_ENCODERS, ()):
|
||||||
lvgl_components_required.add("KEY_LISTENER")
|
lvgl_components_required.add("KEY_LISTENER")
|
||||||
lvgl_components_required.add("ROTARY_ENCODER")
|
|
||||||
lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds
|
lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds
|
||||||
lprt = enc_conf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds
|
lprt = enc_conf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds
|
||||||
listener = cg.new_Pvariable(
|
listener = cg.new_Pvariable(
|
||||||
|
@ -57,7 +57,9 @@ async def rotary_encoders_to_code(var, config):
|
||||||
lv_add(listener.set_sensor(sensor_config))
|
lv_add(listener.set_sensor(sensor_config))
|
||||||
b_sensor = await cg.get_variable(enc_conf[CONF_ENTER_BUTTON])
|
b_sensor = await cg.get_variable(enc_conf[CONF_ENTER_BUTTON])
|
||||||
cg.add(listener.set_enter_button(b_sensor))
|
cg.add(listener.set_enter_button(b_sensor))
|
||||||
if group := add_group(enc_conf.get(CONF_GROUP)):
|
if group := enc_conf.get(CONF_GROUP):
|
||||||
|
group = lv_Pvariable(lv_group_t, group)
|
||||||
|
lv_assign(group, lv_expr.group_create())
|
||||||
lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group)
|
lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group)
|
||||||
else:
|
else:
|
||||||
lv.indev_drv_register(listener.get_drv())
|
lv.indev_drv_register(listener.get_drv())
|
|
@ -127,7 +127,7 @@ void LVTouchListener::update(const touchscreen::TouchPoints_t &tpoints) {
|
||||||
}
|
}
|
||||||
#endif // USE_LVGL_TOUCHSCREEN
|
#endif // USE_LVGL_TOUCHSCREEN
|
||||||
|
|
||||||
#ifdef USE_LVGL_ROTARY_ENCODER
|
#ifdef USE_LVGL_KEY_LISTENER
|
||||||
LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt) {
|
LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt) {
|
||||||
lv_indev_drv_init(&this->drv_);
|
lv_indev_drv_init(&this->drv_);
|
||||||
this->drv_.type = type;
|
this->drv_.type = type;
|
||||||
|
@ -143,7 +143,7 @@ LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_
|
||||||
data->continue_reading = false;
|
data->continue_reading = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // USE_LVGL_ROTARY_ENCODER
|
#endif // USE_LVGL_KEY_LISTENER
|
||||||
|
|
||||||
#ifdef USE_LVGL_BUTTONMATRIX
|
#ifdef USE_LVGL_BUTTONMATRIX
|
||||||
void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) {
|
void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) {
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
|
|
||||||
|
#ifdef USE_LVGL_BINARY_SENSOR
|
||||||
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
|
#endif // USE_LVGL_BINARY_SENSOR
|
||||||
|
#ifdef USE_LVGL_ROTARY_ENCODER
|
||||||
|
#include "esphome/components/rotary_encoder/rotary_encoder.h"
|
||||||
|
#endif // USE_LVGL_ROTARY_ENCODER
|
||||||
|
|
||||||
// required for clang-tidy
|
// required for clang-tidy
|
||||||
#ifndef LV_CONF_H
|
#ifndef LV_CONF_H
|
||||||
#define LV_CONF_SKIP 1 // NOLINT
|
#define LV_CONF_SKIP 1 // NOLINT
|
||||||
|
@ -12,12 +19,7 @@
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
#ifdef USE_LVGL_ROTARY_ENCODER
|
|
||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
|
||||||
#include "esphome/components/rotary_encoder/rotary_encoder.h"
|
|
||||||
#endif // USE_LVGL_ROTARY_ENCODER
|
|
||||||
|
|
||||||
#ifdef USE_LVGL_IMAGE
|
#ifdef USE_LVGL_IMAGE
|
||||||
#include "esphome/components/image/image.h"
|
#include "esphome/components/image/image.h"
|
||||||
#endif // USE_LVGL_IMAGE
|
#endif // USE_LVGL_IMAGE
|
||||||
|
@ -202,7 +204,7 @@ class LVTouchListener : public touchscreen::TouchListener, public Parented<LvglC
|
||||||
};
|
};
|
||||||
#endif // USE_LVGL_TOUCHSCREEN
|
#endif // USE_LVGL_TOUCHSCREEN
|
||||||
|
|
||||||
#ifdef USE_LVGL_ROTARY_ENCODER
|
#ifdef USE_LVGL_KEY_LISTENER
|
||||||
class LVEncoderListener : public Parented<LvglComponent> {
|
class LVEncoderListener : public Parented<LvglComponent> {
|
||||||
public:
|
public:
|
||||||
LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt);
|
LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt);
|
||||||
|
@ -218,9 +220,11 @@ class LVEncoderListener : public Parented<LvglComponent> {
|
||||||
enter_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_ENTER, state); });
|
enter_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_ENTER, state); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_LVGL_ROTARY_ENCODER
|
||||||
void set_sensor(rotary_encoder::RotaryEncoderSensor *sensor) {
|
void set_sensor(rotary_encoder::RotaryEncoderSensor *sensor) {
|
||||||
sensor->register_listener([this](int32_t count) { this->set_count(count); });
|
sensor->register_listener([this](int32_t count) { this->set_count(count); });
|
||||||
}
|
}
|
||||||
|
#endif // USE_LVGL_ROTARY_ENCODER
|
||||||
|
|
||||||
void event(int key, bool pressed) {
|
void event(int key, bool pressed) {
|
||||||
if (!this->parent_->is_paused()) {
|
if (!this->parent_->is_paused()) {
|
||||||
|
@ -243,7 +247,8 @@ class LVEncoderListener : public Parented<LvglComponent> {
|
||||||
int32_t last_count_{};
|
int32_t last_count_{};
|
||||||
int key_{};
|
int key_{};
|
||||||
};
|
};
|
||||||
#endif // USE_LVGL_ROTARY_ENCODER
|
#endif // USE_LVGL_KEY_LISTENER
|
||||||
|
|
||||||
#ifdef USE_LVGL_BUTTONMATRIX
|
#ifdef USE_LVGL_BUTTONMATRIX
|
||||||
class LvButtonMatrixType : public key_provider::KeyProvider, public LvCompound {
|
class LvButtonMatrixType : public key_provider::KeyProvider, public LvCompound {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -16,9 +16,9 @@ from esphome.schema_extractors import SCHEMA_EXTRACT
|
||||||
|
|
||||||
from . import defines as df, lv_validation as lvalid, types as ty
|
from . import defines as df, lv_validation as lvalid, types as ty
|
||||||
from .helpers import add_lv_use, requires_component, validate_printf
|
from .helpers import add_lv_use, requires_component, validate_printf
|
||||||
from .lv_validation import id_name, lv_color, lv_font, lv_image
|
from .lv_validation import lv_color, lv_font, lv_image
|
||||||
from .lvcode import LvglComponent
|
from .lvcode import LvglComponent
|
||||||
from .types import WidgetType
|
from .types import WidgetType, lv_group_t
|
||||||
|
|
||||||
# this will be populated later, in __init__.py to avoid circular imports.
|
# this will be populated later, in __init__.py to avoid circular imports.
|
||||||
WIDGET_TYPES: dict = {}
|
WIDGET_TYPES: dict = {}
|
||||||
|
@ -61,7 +61,7 @@ ENCODER_SCHEMA = cv.Schema(
|
||||||
cv.GenerateID(): cv.All(
|
cv.GenerateID(): cv.All(
|
||||||
cv.declare_id(ty.LVEncoderListener), requires_component("binary_sensor")
|
cv.declare_id(ty.LVEncoderListener), requires_component("binary_sensor")
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_GROUP): lvalid.id_name,
|
cv.Optional(CONF_GROUP): cv.declare_id(lv_group_t),
|
||||||
cv.Optional(df.CONF_LONG_PRESS_TIME, default="400ms"): PRESS_TIME,
|
cv.Optional(df.CONF_LONG_PRESS_TIME, default="400ms"): PRESS_TIME,
|
||||||
cv.Optional(df.CONF_LONG_PRESS_REPEAT_TIME, default="100ms"): PRESS_TIME,
|
cv.Optional(df.CONF_LONG_PRESS_REPEAT_TIME, default="100ms"): PRESS_TIME,
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ def obj_schema(widget_type: WidgetType):
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Optional(CONF_STATE): SET_STATE_SCHEMA,
|
cv.Optional(CONF_STATE): SET_STATE_SCHEMA,
|
||||||
cv.Optional(CONF_GROUP): id_name,
|
cv.Optional(CONF_GROUP): cv.use_id(lv_group_t),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,7 +6,7 @@ from esphome.config_validation import Invalid
|
||||||
from esphome.const import CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE
|
from esphome.const import CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE
|
||||||
from esphome.core import ID, TimePeriod
|
from esphome.core import ID, TimePeriod
|
||||||
from esphome.coroutine import FakeAwaitable
|
from esphome.coroutine import FakeAwaitable
|
||||||
from esphome.cpp_generator import AssignmentExpression, CallExpression, MockObj
|
from esphome.cpp_generator import CallExpression, MockObj
|
||||||
|
|
||||||
from ..defines import (
|
from ..defines import (
|
||||||
CONF_DEFAULT,
|
CONF_DEFAULT,
|
||||||
|
@ -44,15 +44,7 @@ from ..lvcode import (
|
||||||
lv_Pvariable,
|
lv_Pvariable,
|
||||||
)
|
)
|
||||||
from ..schemas import ALL_STYLES, STYLE_REMAP, WIDGET_TYPES
|
from ..schemas import ALL_STYLES, STYLE_REMAP, WIDGET_TYPES
|
||||||
from ..types import (
|
from ..types import LV_STATE, LvType, WidgetType, lv_coord_t, lv_obj_t, lv_obj_t_ptr
|
||||||
LV_STATE,
|
|
||||||
LvType,
|
|
||||||
WidgetType,
|
|
||||||
lv_coord_t,
|
|
||||||
lv_group_t,
|
|
||||||
lv_obj_t,
|
|
||||||
lv_obj_t_ptr,
|
|
||||||
)
|
|
||||||
|
|
||||||
EVENT_LAMB = "event_lamb__"
|
EVENT_LAMB = "event_lamb__"
|
||||||
|
|
||||||
|
@ -317,7 +309,8 @@ async def set_obj_properties(w: Widget, config):
|
||||||
value = await ALL_STYLES[prop].process(value)
|
value = await ALL_STYLES[prop].process(value)
|
||||||
prop_r = STYLE_REMAP.get(prop, prop)
|
prop_r = STYLE_REMAP.get(prop, prop)
|
||||||
w.set_style(prop_r, value, lv_state)
|
w.set_style(prop_r, value, lv_state)
|
||||||
if group := add_group(config.get(CONF_GROUP)):
|
if group := config.get(CONF_GROUP):
|
||||||
|
group = await cg.get_variable(group)
|
||||||
lv.group_add_obj(group, w.obj)
|
lv.group_add_obj(group, w.obj)
|
||||||
flag_clr = set()
|
flag_clr = set()
|
||||||
flag_set = set()
|
flag_set = set()
|
||||||
|
@ -404,20 +397,3 @@ async def widget_to_code(w_cnfig, w_type: WidgetType, parent):
|
||||||
|
|
||||||
lv_scr_act_spec = LvScrActType()
|
lv_scr_act_spec = LvScrActType()
|
||||||
lv_scr_act = Widget.create(None, literal("lv_scr_act()"), lv_scr_act_spec, {})
|
lv_scr_act = Widget.create(None, literal("lv_scr_act()"), lv_scr_act_spec, {})
|
||||||
|
|
||||||
lv_groups = {} # Widget group names
|
|
||||||
|
|
||||||
|
|
||||||
def add_group(name):
|
|
||||||
if name is None:
|
|
||||||
return None
|
|
||||||
fullname = f"lv_esp_group_{name}"
|
|
||||||
if name not in lv_groups:
|
|
||||||
gid = ID(fullname, True, type=lv_group_t.operator("ptr"))
|
|
||||||
lv_add(
|
|
||||||
AssignmentExpression(
|
|
||||||
type_=gid.type, modifier="", name=fullname, rhs=lv_expr.group_create()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
lv_groups[name] = literal(fullname)
|
|
||||||
return lv_groups[name]
|
|
||||||
|
|
|
@ -24,6 +24,33 @@ display:
|
||||||
invert_colors: false
|
invert_colors: false
|
||||||
update_interval: never
|
update_interval: never
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
internal: true
|
||||||
|
id: up_button
|
||||||
|
pin:
|
||||||
|
number: GPIO38
|
||||||
|
inverted: true
|
||||||
|
- platform: gpio
|
||||||
|
internal: true
|
||||||
|
id: down_button
|
||||||
|
pin:
|
||||||
|
number: GPIO37
|
||||||
|
inverted: true
|
||||||
|
- platform: gpio
|
||||||
|
internal: true
|
||||||
|
id: select_button
|
||||||
|
pin:
|
||||||
|
number: GPIO39
|
||||||
|
inverted: true
|
||||||
|
lvgl:
|
||||||
|
encoders:
|
||||||
|
group: switches
|
||||||
|
enter_button: select_button
|
||||||
|
sensor:
|
||||||
|
left_button: up_button
|
||||||
|
right_button: down_button
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
lvgl: !include lvgl-package.yaml
|
lvgl: !include lvgl-package.yaml
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ lvgl:
|
||||||
displays:
|
displays:
|
||||||
- tft_display
|
- tft_display
|
||||||
- second_display
|
- second_display
|
||||||
rotary_encoders:
|
encoders:
|
||||||
sensor: encoder
|
sensor: encoder
|
||||||
enter_button: pushbutton
|
enter_button: pushbutton
|
||||||
group: general
|
group: general
|
||||||
|
|
Loading…
Reference in a new issue