ESPHome  2024.12.2
lvgl_esphome.cpp
Go to the documentation of this file.
1 #include "esphome/core/defines.h"
2 #include "esphome/core/log.h"
3 #include "esphome/core/helpers.h"
4 #include "esphome/core/hal.h"
5 #include "lvgl_hal.h"
6 #include "lvgl_esphome.h"
7 
8 #include <numeric>
9 
10 namespace esphome {
11 namespace lvgl {
12 static const char *const TAG = "lvgl";
13 
14 static const char *const EVENT_NAMES[] = {
15  "NONE",
16  "PRESSED",
17  "PRESSING",
18  "PRESS_LOST",
19  "SHORT_CLICKED",
20  "LONG_PRESSED",
21  "LONG_PRESSED_REPEAT",
22  "CLICKED",
23  "RELEASED",
24  "SCROLL_BEGIN",
25  "SCROLL_END",
26  "SCROLL",
27  "GESTURE",
28  "KEY",
29  "FOCUSED",
30  "DEFOCUSED",
31  "LEAVE",
32  "HIT_TEST",
33  "COVER_CHECK",
34  "REFR_EXT_DRAW_SIZE",
35  "DRAW_MAIN_BEGIN",
36  "DRAW_MAIN",
37  "DRAW_MAIN_END",
38  "DRAW_POST_BEGIN",
39  "DRAW_POST",
40  "DRAW_POST_END",
41  "DRAW_PART_BEGIN",
42  "DRAW_PART_END",
43  "VALUE_CHANGED",
44  "INSERT",
45  "REFRESH",
46  "READY",
47  "CANCEL",
48  "DELETE",
49  "CHILD_CHANGED",
50  "CHILD_CREATED",
51  "CHILD_DELETED",
52  "SCREEN_UNLOAD_START",
53  "SCREEN_LOAD_START",
54  "SCREEN_LOADED",
55  "SCREEN_UNLOADED",
56  "SIZE_CHANGED",
57  "STYLE_CHANGED",
58  "LAYOUT_CHANGED",
59  "GET_SELF_SIZE",
60 };
61 
62 std::string lv_event_code_name_for(uint8_t event_code) {
63  if (event_code < sizeof(EVENT_NAMES) / sizeof(EVENT_NAMES[0])) {
64  return EVENT_NAMES[event_code];
65  }
66  return str_sprintf("%2d", event_code);
67 }
68 
69 static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) {
70  // cater for display driver chips with special requirements for bounds of partial
71  // draw areas. Extend the draw area to satisfy:
72  // * Coordinates must be a multiple of draw_rounding
73  auto *comp = static_cast<LvglComponent *>(disp_drv->user_data);
74  auto draw_rounding = comp->draw_rounding;
75  // round down the start coordinates
76  area->x1 = area->x1 / draw_rounding * draw_rounding;
77  area->y1 = area->y1 / draw_rounding * draw_rounding;
78  // round up the end coordinates
79  area->x2 = (area->x2 + draw_rounding) / draw_rounding * draw_rounding - 1;
80  area->y2 = (area->y2 + draw_rounding) / draw_rounding * draw_rounding - 1;
81 }
82 
83 lv_event_code_t lv_api_event; // NOLINT
84 lv_event_code_t lv_update_event; // NOLINT
86  ESP_LOGCONFIG(TAG, "LVGL:");
87  ESP_LOGCONFIG(TAG, " Display width/height: %d x %d", this->disp_drv_.hor_res, this->disp_drv_.ver_res);
88  ESP_LOGCONFIG(TAG, " Rotation: %d", this->rotation);
89  ESP_LOGCONFIG(TAG, " Draw rounding: %d", (int) this->draw_rounding);
90 }
91 void LvglComponent::set_paused(bool paused, bool show_snow) {
92  this->paused_ = paused;
93  this->show_snow_ = show_snow;
94  if (!paused && lv_scr_act() != nullptr) {
95  lv_disp_trig_activity(this->disp_); // resets the inactivity time
96  lv_obj_invalidate(lv_scr_act());
97  }
98  this->pause_callbacks_.call(paused);
99 }
100 
102  lv_init();
103  lv_update_event = static_cast<lv_event_code_t>(lv_event_register_id());
104  lv_api_event = static_cast<lv_event_code_t>(lv_event_register_id());
105 }
106 void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event) {
107  lv_obj_add_event_cb(obj, callback, event, nullptr);
108 }
109 void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1,
110  lv_event_code_t event2) {
111  add_event_cb(obj, callback, event1);
112  add_event_cb(obj, callback, event2);
113 }
114 void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1,
115  lv_event_code_t event2, lv_event_code_t event3) {
116  add_event_cb(obj, callback, event1);
117  add_event_cb(obj, callback, event2);
118  add_event_cb(obj, callback, event3);
119 }
121  this->pages_.push_back(page);
122  page->setup(this->pages_.size() - 1);
123 }
124 void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time) {
125  if (index >= this->pages_.size())
126  return;
127  this->current_page_ = index;
128  lv_scr_load_anim(this->pages_[this->current_page_]->obj, anim, time, 0, false);
129 }
130 void LvglComponent::show_next_page(lv_scr_load_anim_t anim, uint32_t time) {
131  if (this->pages_.empty() || (this->current_page_ == this->pages_.size() - 1 && !this->page_wrap_))
132  return;
133  do {
134  this->current_page_ = (this->current_page_ + 1) % this->pages_.size();
135  } while (this->pages_[this->current_page_]->skip); // skip empty pages()
136  this->show_page(this->current_page_, anim, time);
137 }
138 void LvglComponent::show_prev_page(lv_scr_load_anim_t anim, uint32_t time) {
139  if (this->pages_.empty() || (this->current_page_ == 0 && !this->page_wrap_))
140  return;
141  do {
142  this->current_page_ = (this->current_page_ + this->pages_.size() - 1) % this->pages_.size();
143  } while (this->pages_[this->current_page_]->skip); // skip empty pages()
144  this->show_page(this->current_page_, anim, time);
145 }
146 void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) {
147  auto width = lv_area_get_width(area);
148  auto height = lv_area_get_height(area);
149  auto x1 = area->x1;
150  auto y1 = area->y1;
151  lv_color_t *dst = this->rotate_buf_;
152  switch (this->rotation) {
154  for (lv_coord_t x = height; x-- != 0;) {
155  for (lv_coord_t y = 0; y != width; y++) {
156  dst[y * height + x] = *ptr++;
157  }
158  }
159  y1 = x1;
160  x1 = this->disp_drv_.ver_res - area->y1 - height;
161  width = height;
162  height = lv_area_get_width(area);
163  break;
164 
166  for (lv_coord_t y = height; y-- != 0;) {
167  for (lv_coord_t x = width; x-- != 0;) {
168  dst[y * width + x] = *ptr++;
169  }
170  }
171  x1 = this->disp_drv_.hor_res - x1 - width;
172  y1 = this->disp_drv_.ver_res - y1 - height;
173  break;
174 
176  for (lv_coord_t x = 0; x != height; x++) {
177  for (lv_coord_t y = width; y-- != 0;) {
178  dst[y * height + x] = *ptr++;
179  }
180  }
181  x1 = y1;
182  y1 = this->disp_drv_.hor_res - area->x1 - width;
183  width = height;
184  height = lv_area_get_width(area);
185  break;
186 
187  default:
188  dst = ptr;
189  break;
190  }
191  for (auto *display : this->displays_) {
192  ESP_LOGV(TAG, "draw buffer x1=%d, y1=%d, width=%d, height=%d", x1, y1, width, height);
193  display->draw_pixels_at(x1, y1, width, height, (const uint8_t *) dst, display::COLOR_ORDER_RGB, LV_BITNESS,
194  LV_COLOR_16_SWAP);
195  }
196 }
197 
198 void LvglComponent::flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
199  if (!this->paused_) {
200  auto now = millis();
201  this->draw_buffer_(area, color_p);
202  ESP_LOGVV(TAG, "flush_cb, area=%d/%d, %d/%d took %dms", area->x1, area->y1, lv_area_get_width(area),
203  lv_area_get_height(area), (int) (millis() - now));
204  }
205  lv_disp_flush_ready(disp_drv);
206 }
207 IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableValue<uint32_t> timeout) : timeout_(std::move(timeout)) {
208  parent->add_on_idle_callback([this](uint32_t idle_time) {
209  if (!this->is_idle_ && idle_time > this->timeout_.value()) {
210  this->is_idle_ = true;
211  this->trigger();
212  } else if (this->is_idle_ && idle_time < this->timeout_.value()) {
213  this->is_idle_ = false;
214  }
215  });
216 }
217 
218 PauseTrigger::PauseTrigger(LvglComponent *parent, TemplatableValue<bool> paused) : paused_(std::move(paused)) {
219  parent->add_on_pause_callback([this](bool pausing) {
220  if (this->paused_.value() == pausing)
221  this->trigger();
222  });
223 }
224 
225 #ifdef USE_LVGL_TOUCHSCREEN
226 LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time, LvglComponent *parent) {
227  this->set_parent(parent);
228  lv_indev_drv_init(&this->drv_);
229  this->drv_.disp = parent->get_disp();
230  this->drv_.long_press_repeat_time = long_press_repeat_time;
231  this->drv_.long_press_time = long_press_time;
232  this->drv_.type = LV_INDEV_TYPE_POINTER;
233  this->drv_.user_data = this;
234  this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) {
235  auto *l = static_cast<LVTouchListener *>(d->user_data);
236  if (l->touch_pressed_) {
237  data->point.x = l->touch_point_.x;
238  data->point.y = l->touch_point_.y;
239  data->state = LV_INDEV_STATE_PRESSED;
240  } else {
241  data->state = LV_INDEV_STATE_RELEASED;
242  }
243  };
244 }
245 
247  this->touch_pressed_ = !this->parent_->is_paused() && !tpoints.empty();
248  if (this->touch_pressed_)
249  this->touch_point_ = tpoints[0];
250 }
251 #endif // USE_LVGL_TOUCHSCREEN
252 
253 #ifdef USE_LVGL_KEY_LISTENER
254 LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt) {
255  lv_indev_drv_init(&this->drv_);
256  this->drv_.type = type;
257  this->drv_.user_data = this;
258  this->drv_.long_press_time = lpt;
259  this->drv_.long_press_repeat_time = lprt;
260  this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) {
261  auto *l = static_cast<LVEncoderListener *>(d->user_data);
262  data->state = l->pressed_ ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
263  data->key = l->key_;
264  data->enc_diff = (int16_t) (l->count_ - l->last_count_);
265  l->last_count_ = l->count_;
266  data->continue_reading = false;
267  };
268 }
269 #endif // USE_LVGL_KEY_LISTENER
270 
271 #if defined(USE_LVGL_DROPDOWN) || defined(LV_USE_ROLLER)
273  auto selected = this->get_selected_index();
274  if (selected >= this->options_.size())
275  return "";
276  return this->options_[selected];
277 }
278 
279 static std::string join_string(std::vector<std::string> options) {
280  return std::accumulate(
281  options.begin(), options.end(), std::string(),
282  [](const std::string &a, const std::string &b) -> std::string { return a + (!a.empty() ? "\n" : "") + b; });
283 }
284 
285 void LvSelectable::set_selected_text(const std::string &text, lv_anim_enable_t anim) {
286  auto index = std::find(this->options_.begin(), this->options_.end(), text);
287  if (index != this->options_.end()) {
288  this->set_selected_index(index - this->options_.begin(), anim);
289  lv_event_send(this->obj, lv_api_event, nullptr);
290  }
291 }
292 
293 void LvSelectable::set_options(std::vector<std::string> options) {
294  auto index = this->get_selected_index();
295  if (index >= options.size())
296  index = options.size() - 1;
297  this->options_ = std::move(options);
298  this->set_option_string(join_string(this->options_).c_str());
299  lv_event_send(this->obj, LV_EVENT_REFRESH, nullptr);
300  this->set_selected_index(index, LV_ANIM_OFF);
301 }
302 #endif // USE_LVGL_DROPDOWN || LV_USE_ROLLER
303 
304 #ifdef USE_LVGL_BUTTONMATRIX
305 void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) {
306  LvCompound::set_obj(lv_obj);
307  lv_obj_add_event_cb(
308  lv_obj,
309  [](lv_event_t *event) {
310  auto *self = static_cast<LvButtonMatrixType *>(event->user_data);
311  if (self->key_callback_.size() == 0)
312  return;
313  auto key_idx = lv_btnmatrix_get_selected_btn(self->obj);
314  if (key_idx == LV_BTNMATRIX_BTN_NONE)
315  return;
316  if (self->key_map_.count(key_idx) != 0) {
317  self->send_key_(self->key_map_[key_idx]);
318  return;
319  }
320  const auto *str = lv_btnmatrix_get_btn_text(self->obj, key_idx);
321  auto len = strlen(str);
322  while (len--)
323  self->send_key_(*str++);
324  },
325  LV_EVENT_PRESSED, this);
326 }
327 #endif // USE_LVGL_BUTTONMATRIX
328 
329 #ifdef USE_LVGL_KEYBOARD
330 static const char *const KB_SPECIAL_KEYS[] = {
331  "abc", "ABC", "1#",
332  // maybe add other special keys here
333 };
334 
335 void LvKeyboardType::set_obj(lv_obj_t *lv_obj) {
336  LvCompound::set_obj(lv_obj);
337  lv_obj_add_event_cb(
338  lv_obj,
339  [](lv_event_t *event) {
340  auto *self = static_cast<LvKeyboardType *>(event->user_data);
341  if (self->key_callback_.size() == 0)
342  return;
343 
344  auto key_idx = lv_btnmatrix_get_selected_btn(self->obj);
345  if (key_idx == LV_BTNMATRIX_BTN_NONE)
346  return;
347  const char *txt = lv_btnmatrix_get_btn_text(self->obj, key_idx);
348  if (txt == nullptr)
349  return;
350  for (const auto *kb_special_key : KB_SPECIAL_KEYS) {
351  if (strcmp(txt, kb_special_key) == 0)
352  return;
353  }
354  while (*txt != 0)
355  self->send_key_(*txt++);
356  },
357  LV_EVENT_PRESSED, this);
358 }
359 #endif // USE_LVGL_KEYBOARD
360 
362  int iterations = 6 - lv_disp_get_inactive_time(this->disp_) / 60000;
363  if (iterations <= 0)
364  iterations = 1;
365  while (iterations-- != 0) {
366  auto col = random_uint32() % this->disp_drv_.hor_res;
367  col = col / this->draw_rounding * this->draw_rounding;
368  auto row = random_uint32() % this->disp_drv_.ver_res;
369  row = row / this->draw_rounding * this->draw_rounding;
370  auto size = (random_uint32() % 32) / this->draw_rounding * this->draw_rounding - 1;
371  lv_area_t area;
372  area.x1 = col;
373  area.y1 = row;
374  area.x2 = col + size;
375  area.y2 = row + size;
376  if (area.x2 >= this->disp_drv_.hor_res)
377  area.x2 = this->disp_drv_.hor_res - 1;
378  if (area.y2 >= this->disp_drv_.ver_res)
379  area.y2 = this->disp_drv_.ver_res - 1;
380 
381  size_t line_len = lv_area_get_width(&area) * lv_area_get_height(&area) / 2;
382  for (size_t i = 0; i != line_len; i++) {
383  ((uint32_t *) (this->draw_buf_.buf1))[i] = random_uint32();
384  }
385  this->draw_buffer_(&area, (lv_color_t *) this->draw_buf_.buf1);
386  }
387 }
388 
409 LvglComponent::LvglComponent(std::vector<display::Display *> displays, float buffer_frac, bool full_refresh,
410  int draw_rounding, bool resume_on_input)
411  : draw_rounding(draw_rounding),
412  displays_(std::move(displays)),
413  buffer_frac_(buffer_frac),
414  full_refresh_(full_refresh),
415  resume_on_input_(resume_on_input) {
416  auto *display = this->displays_[0];
417  size_t buffer_pixels = display->get_width() * display->get_height() / this->buffer_frac_;
418  auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8;
419  this->rotation = display->get_rotation();
421  this->rotate_buf_ = static_cast<lv_color_t *>(lv_custom_mem_alloc(buf_bytes)); // NOLINT
422  if (this->rotate_buf_ == nullptr)
423  return;
424  }
425  auto *buf = lv_custom_mem_alloc(buf_bytes); // NOLINT
426  if (buf == nullptr)
427  return;
428  lv_disp_draw_buf_init(&this->draw_buf_, buf, nullptr, buffer_pixels);
429  lv_disp_drv_init(&this->disp_drv_);
430  this->disp_drv_.draw_buf = &this->draw_buf_;
431  this->disp_drv_.user_data = this;
432  this->disp_drv_.full_refresh = this->full_refresh_;
433  this->disp_drv_.flush_cb = static_flush_cb;
434  this->disp_drv_.rounder_cb = rounder_cb;
435  this->disp_drv_.hor_res = (lv_coord_t) display->get_width();
436  this->disp_drv_.ver_res = (lv_coord_t) display->get_height();
437  this->disp_ = lv_disp_drv_register(&this->disp_drv_);
438 }
439 
441  if (this->draw_buf_.buf1 == nullptr) {
442  this->mark_failed();
443  this->status_set_error("Memory allocation failure");
444  return;
445  }
446  ESP_LOGCONFIG(TAG, "LVGL Setup starts");
447 #if LV_USE_LOG
448  lv_log_register_print_cb([](const char *buf) {
449  auto next = strchr(buf, ')');
450  if (next != nullptr)
451  buf = next + 1;
452  while (isspace(*buf))
453  buf++;
454  esp_log_printf_(LVGL_LOG_LEVEL, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf);
455  });
456 #endif
457  // Rotation will be handled by our drawing function, so reset the display rotation.
458  for (auto *display : this->displays_)
459  display->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);
460  this->show_page(0, LV_SCR_LOAD_ANIM_NONE, 0);
461  lv_disp_trig_activity(this->disp_);
462  ESP_LOGCONFIG(TAG, "LVGL Setup complete");
463 }
464 
466  // update indicators
467  if (this->paused_) {
468  return;
469  }
470  this->idle_callbacks_.call(lv_disp_get_inactive_time(this->disp_));
471 }
473  if (this->paused_) {
474  if (this->show_snow_)
475  this->write_random_();
476  }
477  lv_timer_handler_run_in_period(5);
478 }
479 
480 #ifdef USE_LVGL_ANIMIMG
481 void lv_animimg_stop(lv_obj_t *obj) {
482  auto *animg = (lv_animimg_t *) obj;
483  int32_t duration = animg->anim.time;
484  lv_animimg_set_duration(obj, 0);
485  lv_animimg_start(obj);
486  lv_animimg_set_duration(obj, duration);
487 }
488 #endif
489 void LvglComponent::static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
490  reinterpret_cast<LvglComponent *>(disp_drv->user_data)->flush_cb_(disp_drv, area, color_p);
491 }
492 } // namespace lvgl
493 } // namespace esphome
494 
495 size_t lv_millis(void) { return esphome::millis(); }
496 
497 #if defined(USE_HOST) || defined(USE_RP2040) || defined(USE_ESP8266)
498 void *lv_custom_mem_alloc(size_t size) {
499  auto *ptr = malloc(size); // NOLINT
500  if (ptr == nullptr) {
501 #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR
502  esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size);
503 #endif
504  }
505  return ptr;
506 }
507 void lv_custom_mem_free(void *ptr) { return free(ptr); } // NOLINT
508 void *lv_custom_mem_realloc(void *ptr, size_t size) { return realloc(ptr, size); } // NOLINT
509 #else
510 static unsigned cap_bits = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT; // NOLINT
511 
512 void *lv_custom_mem_alloc(size_t size) {
513  void *ptr;
514  ptr = heap_caps_malloc(size, cap_bits);
515  if (ptr == nullptr) {
516  cap_bits = MALLOC_CAP_8BIT;
517  ptr = heap_caps_malloc(size, cap_bits);
518  }
519  if (ptr == nullptr) {
520 #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR
521  esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size);
522 #endif
523  return nullptr;
524  }
525 #ifdef ESPHOME_LOG_HAS_VERBOSE
526  esphome::ESP_LOGV(esphome::lvgl::TAG, "allocate %zu - > %p", size, ptr);
527 #endif
528  return ptr;
529 }
530 
531 void lv_custom_mem_free(void *ptr) {
532 #ifdef ESPHOME_LOG_HAS_VERBOSE
533  esphome::ESP_LOGV(esphome::lvgl::TAG, "free %p", ptr);
534 #endif
535  if (ptr == nullptr)
536  return;
537  heap_caps_free(ptr);
538 }
539 
540 void *lv_custom_mem_realloc(void *ptr, size_t size) {
541 #ifdef ESPHOME_LOG_HAS_VERBOSE
542  esphome::ESP_LOGV(esphome::lvgl::TAG, "realloc %p: %zu", ptr, size);
543 #endif
544  return heap_caps_realloc(ptr, size, cap_bits);
545 }
546 #endif
static void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event)
std::string lv_event_code_name_for(uint8_t event_code)
void add_on_idle_callback(std::function< void(uint32_t)> &&callback)
Definition: lvgl_esphome.h:148
void set_paused(bool paused, bool show_snow)
void set_obj(lv_obj_t *lv_obj) override
std::vector< TouchPoint > TouchPoints_t
Definition: touchscreen.h:30
void * lv_custom_mem_alloc(size_t size)
void flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
uint32_t random_uint32()
Return a random 32-bit unsigned integer.
Definition: helpers.cpp:193
uint16_t x
Definition: tt21100.cpp:17
CallbackManager< void(bool)> pause_callbacks_
Definition: lvgl_esphome.h:214
STL namespace.
Component for rendering LVGL.
Definition: lvgl_esphome.h:136
LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt)
void draw_buffer_(const lv_area_t *area, lv_color_t *ptr)
void(_lv_event_t *) event_callback_t
Definition: lvgl_esphome.h:102
LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time, LvglComponent *parent)
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
Definition: automation.h:95
uint16_t y
Definition: tt21100.cpp:18
void set_selected_text(const std::string &text, lv_anim_enable_t anim)
TemplatableValue< bool > paused_
Definition: lvgl_esphome.h:232
void lv_custom_mem_free(void *ptr)
lv_event_code_t lv_update_event
lv_event_code_t lv_api_event
size_t lv_millis(void)
void update(const touchscreen::TouchPoints_t &tpoints) override
void setup(size_t index)
Definition: lvgl_esphome.h:91
virtual void set_obj(lv_obj_t *lv_obj)
Definition: lvgl_esphome.h:83
void status_set_error(const char *message="unspecified")
Definition: component.cpp:159
LvglComponent(std::vector< display::Display *> displays, float buffer_frac, bool full_refresh, int draw_rounding, bool resume_on_input)
void add_on_pause_callback(std::function< void(bool)> &&callback)
Definition: lvgl_esphome.h:151
std::string str_sprintf(const char *fmt,...)
Definition: helpers.cpp:320
static void esphome_lvgl_init()
Initialize the LVGL library and register custom events.
void add_page(LvPageType *page)
uint8_t type
void set_obj(lv_obj_t *lv_obj) override
static void static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
PauseTrigger(LvglComponent *parent, TemplatableValue< bool > paused)
display::DisplayRotation rotation
Definition: lvgl_esphome.h:191
uint8_t options
void HOT esp_log_printf_(int level, const char *tag, int line, const char *format,...)
Definition: log.cpp:11
IdleTrigger(LvglComponent *parent, TemplatableValue< uint32_t > timeout)
TemplatableValue< uint32_t > timeout_
Definition: lvgl_esphome.h:223
void set_options(std::vector< std::string > options)
uint8_t l
Definition: bl0906.h:207
std::string size_t len
Definition: helpers.h:293
std::vector< LvPageType * > pages_
Definition: lvgl_esphome.h:207
lv_disp_draw_buf_t draw_buf_
Definition: lvgl_esphome.h:203
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
void * lv_custom_mem_realloc(void *ptr, size_t size)
void show_next_page(lv_scr_load_anim_t anim, uint32_t time)
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
CallbackManager< void(uint32_t)> idle_callbacks_
Definition: lvgl_esphome.h:213
void show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time)
void show_prev_page(lv_scr_load_anim_t anim, uint32_t time)
void lv_animimg_stop(lv_obj_t *obj)
std::vector< display::Display * > displays_
Definition: lvgl_esphome.h:198