ESPHome 2025.5.0
Loading...
Searching...
No Matches
nextion.cpp
Go to the documentation of this file.
1#include "nextion.h"
2#include "esphome/core/util.h"
3#include "esphome/core/log.h"
5#include <cinttypes>
6
7namespace esphome {
8namespace nextion {
9
10static const char *const TAG = "nextion";
11
13 this->is_setup_ = false;
14 this->ignore_is_setup_ = true;
15
16 // Wake up the nextion
17 this->send_command_("bkcmd=0");
18 this->send_command_("sleep=0");
19
20 this->send_command_("bkcmd=0");
21 this->send_command_("sleep=0");
22
23 // Reboot it
24 this->send_command_("rest");
25
26 this->ignore_is_setup_ = false;
27}
28
29bool Nextion::send_command_(const std::string &command) {
30 if (!this->ignore_is_setup_ && !this->is_setup()) {
31 return false;
32 }
33
34#ifdef USE_NEXTION_COMMAND_SPACING
35 if (!this->ignore_is_setup_ && !this->command_pacer_.can_send()) {
36 return false;
37 }
38#endif // USE_NEXTION_COMMAND_SPACING
39
40 ESP_LOGN(TAG, "send_command %s", command.c_str());
41
42 this->write_str(command.c_str());
43 const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF};
44 this->write_array(to_send, sizeof(to_send));
45
46#ifdef USE_NEXTION_COMMAND_SPACING
48#endif // USE_NEXTION_COMMAND_SPACING
49
50 return true;
51}
52
54 if (this->is_connected_)
55 return true;
56
57 // Check if the handshake should be skipped for the Nextion connection
59 // Log the connection status without handshake
60 ESP_LOGW(TAG, "Nextion display set as connected without performing handshake");
61 // Set the connection status to true
62 this->is_connected_ = true;
63 // Return true indicating the connection is set
64 return true;
65 }
66
67 if (this->comok_sent_ == 0) {
68 this->reset_(false);
69
70 this->ignore_is_setup_ = true;
71 this->send_command_("boguscommand=0"); // bogus command. needed sometimes after updating
72 if (this->exit_reparse_on_start_) {
73 this->send_command_("DRAKJHSUYDGBNCJHGJKSHBDN");
74 }
75 this->send_command_("connect");
76
77 this->comok_sent_ = millis();
78 this->ignore_is_setup_ = false;
79
80 return false;
81 }
82
83 if (millis() - this->comok_sent_ <= 500) // Wait 500 ms
84 return false;
85
86 std::string response;
87
88 this->recv_ret_string_(response, 0, false);
89 if (!response.empty() && response[0] == 0x1A) {
90 // Swallow invalid variable name responses that may be caused by the above commands
91 ESP_LOGD(TAG, "0x1A error ignored during setup");
92 return false;
93 }
94 if (response.empty() || response.find("comok") == std::string::npos) {
95#ifdef NEXTION_PROTOCOL_LOG
96 ESP_LOGN(TAG, "Bad connect request %s", response.c_str());
97 for (size_t i = 0; i < response.length(); i++) {
98 ESP_LOGN(TAG, "response %s %d %d %c", response.c_str(), i, response[i], response[i]);
99 }
100#endif
101
102 ESP_LOGW(TAG, "Nextion is not connected! ");
103 comok_sent_ = 0;
104 return false;
105 }
106
107 this->ignore_is_setup_ = true;
108 ESP_LOGI(TAG, "Nextion is connected");
109 this->is_connected_ = true;
110
111 ESP_LOGN(TAG, "connect request %s", response.c_str());
112
113 size_t start;
114 size_t end = 0;
115 std::vector<std::string> connect_info;
116 while ((start = response.find_first_not_of(',', end)) != std::string::npos) {
117 end = response.find(',', start);
118 connect_info.push_back(response.substr(start, end - start));
119 }
120
121 this->is_detected_ = (connect_info.size() == 7);
122 if (this->is_detected_) {
123 ESP_LOGN(TAG, "Received connect_info %zu", connect_info.size());
124
125 this->device_model_ = connect_info[2];
126 this->firmware_version_ = connect_info[3];
127 this->serial_number_ = connect_info[5];
128 this->flash_size_ = connect_info[6];
129 } else {
130 ESP_LOGE(TAG, "Nextion returned bad connect value \"%s\"", response.c_str());
131 }
132
133 this->ignore_is_setup_ = false;
134 this->dump_config();
135 return true;
136}
137
138void Nextion::reset_(bool reset_nextion) {
139 uint8_t d;
140
141 while (this->available()) { // Clear receive buffer
142 this->read_byte(&d);
143 };
144 this->nextion_queue_.clear();
145 this->waveform_queue_.clear();
146}
147
149 ESP_LOGCONFIG(TAG, "Nextion:");
150 if (this->skip_connection_handshake_) {
151 ESP_LOGCONFIG(TAG, " Skip handshake: %s", YESNO(this->skip_connection_handshake_));
152 } else {
153 ESP_LOGCONFIG(TAG, " Device Model: %s", this->device_model_.c_str());
154 ESP_LOGCONFIG(TAG, " Firmware Version: %s", this->firmware_version_.c_str());
155 ESP_LOGCONFIG(TAG, " Serial Number: %s", this->serial_number_.c_str());
156 ESP_LOGCONFIG(TAG, " Flash Size: %s", this->flash_size_.c_str());
157 }
158 ESP_LOGCONFIG(TAG, " Wake On Touch: %s", YESNO(this->auto_wake_on_touch_));
159 ESP_LOGCONFIG(TAG, " Exit reparse: %s", YESNO(this->exit_reparse_on_start_));
160
161 if (this->touch_sleep_timeout_ != 0) {
162 ESP_LOGCONFIG(TAG, " Touch Timeout: %" PRIu32, this->touch_sleep_timeout_);
163 }
164
165 if (this->wake_up_page_ != -1) {
166 ESP_LOGCONFIG(TAG, " Wake Up Page: %" PRId16, this->wake_up_page_);
167 }
168
169 if (this->start_up_page_ != -1) {
170 ESP_LOGCONFIG(TAG, " Start Up Page: %" PRId16, this->start_up_page_);
171 }
172
173#ifdef USE_NEXTION_COMMAND_SPACING
174 ESP_LOGCONFIG(TAG, " Command spacing: %" PRIu8 "ms", this->command_pacer_.get_spacing());
175#endif // USE_NEXTION_COMMAND_SPACING
176}
177
180 if (!this->is_setup()) {
181 return;
182 }
183 if (this->writer_.has_value()) {
184 (*this->writer_)(*this);
185 }
186}
187
188void Nextion::add_sleep_state_callback(std::function<void()> &&callback) {
189 this->sleep_callback_.add(std::move(callback));
190}
191
192void Nextion::add_wake_state_callback(std::function<void()> &&callback) {
193 this->wake_callback_.add(std::move(callback));
194}
195
196void Nextion::add_setup_state_callback(std::function<void()> &&callback) {
197 this->setup_callback_.add(std::move(callback));
198}
199
200void Nextion::add_new_page_callback(std::function<void(uint8_t)> &&callback) {
201 this->page_callback_.add(std::move(callback));
202}
203
204void Nextion::add_touch_event_callback(std::function<void(uint8_t, uint8_t, bool)> &&callback) {
205 this->touch_callback_.add(std::move(callback));
206}
207
208void Nextion::add_buffer_overflow_event_callback(std::function<void()> &&callback) {
209 this->buffer_overflow_callback_.add(std::move(callback));
210}
211
213 if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
214 return;
215
216 for (auto *binarysensortype : this->binarysensortype_) {
217 binarysensortype->update_component();
218 }
219 for (auto *sensortype : this->sensortype_) {
220 sensortype->update_component();
221 }
222 for (auto *switchtype : this->switchtype_) {
223 switchtype->update_component();
224 }
225 for (auto *textsensortype : this->textsensortype_) {
226 textsensortype->update_component();
227 }
228}
229
230bool Nextion::send_command(const char *command) {
231 if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
232 return false;
233
234 if (this->send_command_(command)) {
235 this->add_no_result_to_queue_("send_command");
236 return true;
237 }
238 return false;
239}
240
241bool Nextion::send_command_printf(const char *format, ...) {
242 if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
243 return false;
244
245 char buffer[256];
246 va_list arg;
247 va_start(arg, format);
248 int ret = vsnprintf(buffer, sizeof(buffer), format, arg);
249 va_end(arg);
250 if (ret <= 0) {
251 ESP_LOGW(TAG, "Building command for format '%s' failed!", format);
252 return false;
253 }
254
255 if (this->send_command_(buffer)) {
256 this->add_no_result_to_queue_("send_command_printf");
257 return true;
258 }
259 return false;
260}
261
262#ifdef NEXTION_PROTOCOL_LOG
264 ESP_LOGN(TAG, "print_queue_members_ (top 10) size %zu", this->nextion_queue_.size());
265 ESP_LOGN(TAG, "*******************************************");
266 int count = 0;
267 for (auto *i : this->nextion_queue_) {
268 if (count++ == 10)
269 break;
270
271 if (i == nullptr) {
272 ESP_LOGN(TAG, "Nextion queue is null");
273 } else {
274 ESP_LOGN(TAG, "Nextion queue type: %d:%s , name: %s", i->component->get_queue_type(),
275 i->component->get_queue_type_string().c_str(), i->component->get_variable_name().c_str());
276 }
277 }
278 ESP_LOGN(TAG, "*******************************************");
279}
280#endif
281
283 if (!this->check_connect_() || this->is_updating_)
284 return;
285
287 this->ignore_is_setup_ = true;
288 this->sent_setup_commands_ = true;
289 this->send_command_("bkcmd=3"); // Always, returns 0x00 to 0x23 result of serial command.
290
291 if (this->brightness_.has_value()) {
293 }
294
295 // Check if a startup page has been set and send the command
296 if (this->start_up_page_ != -1) {
297 this->goto_page(this->start_up_page_);
298 }
299
300 if (this->wake_up_page_ != -1) {
301 this->set_wake_up_page(this->wake_up_page_);
302 }
303
304 this->ignore_is_setup_ = false;
305 }
306
307 this->process_serial_(); // Receive serial data
308 this->process_nextion_commands_(); // Process nextion return commands
309
310 if (!this->nextion_reports_is_setup_) {
311 if (this->started_ms_ == 0)
312 this->started_ms_ = millis();
313
314 if (this->started_ms_ + this->startup_override_ms_ < millis()) {
315 ESP_LOGD(TAG, "Manually set nextion report ready");
316 this->nextion_reports_is_setup_ = true;
317 }
318 }
319}
320
321bool Nextion::remove_from_q_(bool report_empty) {
322 if (this->nextion_queue_.empty()) {
323 if (report_empty) {
324 ESP_LOGE(TAG, "Nextion queue is empty!");
325 }
326 return false;
327 }
328
329 NextionQueue *nb = this->nextion_queue_.front();
330 if (!nb || !nb->component) {
331 ESP_LOGE(TAG, "Invalid queue entry!");
332 this->nextion_queue_.pop_front();
333 return false;
334 }
335 NextionComponentBase *component = nb->component;
336
337 ESP_LOGN(TAG, "Removing %s from the queue", component->get_variable_name().c_str());
338
339 if (component->get_queue_type() == NextionQueueType::NO_RESULT) {
340 if (component->get_variable_name() == "sleep_wake") {
341 this->is_sleeping_ = false;
342 }
343 delete component; // NOLINT(cppcoreguidelines-owning-memory)
344 }
345 delete nb; // NOLINT(cppcoreguidelines-owning-memory)
346 this->nextion_queue_.pop_front();
347 return true;
348}
349
351 uint8_t d;
352
353 while (this->available()) {
354 read_byte(&d);
355 this->command_data_ += d;
356 }
357}
358// nextion.tech/instruction-set/
360 if (this->command_data_.empty()) {
361 return;
362 }
363
364#ifdef USE_NEXTION_COMMAND_SPACING
365 if (!this->command_pacer_.can_send()) {
366 return; // Will try again in next loop iteration
367 }
368#endif
369
370 size_t to_process_length = 0;
371 std::string to_process;
372
373 ESP_LOGN(TAG, "this->command_data_ %s length %d", this->command_data_.c_str(), this->command_data_.length());
374#ifdef NEXTION_PROTOCOL_LOG
375 this->print_queue_members_();
376#endif
377 while ((to_process_length = this->command_data_.find(COMMAND_DELIMITER)) != std::string::npos) {
378 ESP_LOGN(TAG, "print_queue_members_ size %zu", this->nextion_queue_.size());
379 while (to_process_length + COMMAND_DELIMITER.length() < this->command_data_.length() &&
380 static_cast<uint8_t>(this->command_data_[to_process_length + COMMAND_DELIMITER.length()]) == 0xFF) {
381 ++to_process_length;
382 ESP_LOGN(TAG, "Add extra 0xFF to process");
383 }
384
385 this->nextion_event_ = this->command_data_[0];
386
387 to_process_length -= 1;
388 to_process = this->command_data_.substr(1, to_process_length);
389
390 switch (this->nextion_event_) {
391 case 0x00: // instruction sent by user has failed
392 ESP_LOGW(TAG, "Nextion reported invalid instruction!");
393 this->remove_from_q_();
394
395 break;
396 case 0x01: // instruction sent by user was successful
397
398 ESP_LOGVV(TAG, "instruction sent by user was successful");
399 ESP_LOGN(TAG, "this->nextion_queue_.empty() %s", this->nextion_queue_.empty() ? "True" : "False");
400
401 this->remove_from_q_();
402 if (!this->is_setup_) {
403 if (this->nextion_queue_.empty()) {
404 ESP_LOGD(TAG, "Nextion is setup");
405 this->is_setup_ = true;
406 this->setup_callback_.call();
407 }
408 }
409#ifdef USE_NEXTION_COMMAND_SPACING
410 this->command_pacer_.mark_sent(); // Here is where we should mark the command as sent
411#endif
412 break;
413 case 0x02: // invalid Component ID or name was used
414 ESP_LOGW(TAG, "Nextion reported component ID or name invalid!");
415 this->remove_from_q_();
416 break;
417 case 0x03: // invalid Page ID or name was used
418 ESP_LOGW(TAG, "Nextion reported page ID invalid!");
419 this->remove_from_q_();
420 break;
421 case 0x04: // invalid Picture ID was used
422 ESP_LOGW(TAG, "Nextion reported picture ID invalid!");
423 this->remove_from_q_();
424 break;
425 case 0x05: // invalid Font ID was used
426 ESP_LOGW(TAG, "Nextion reported font ID invalid!");
427 this->remove_from_q_();
428 break;
429 case 0x06: // File operation fails
430 ESP_LOGW(TAG, "Nextion File operation fail!");
431 break;
432 case 0x09: // Instructions with CRC validation fails their CRC check
433 ESP_LOGW(TAG, "Nextion Instructions with CRC validation fails their CRC check!");
434 break;
435 case 0x11: // invalid Baud rate was used
436 ESP_LOGW(TAG, "Nextion reported baud rate invalid!");
437 break;
438 case 0x12: // invalid Waveform ID or Channel # was used
439 if (this->waveform_queue_.empty()) {
440 ESP_LOGW(TAG,
441 "Nextion reported invalid Waveform ID or Channel # was used but no waveform sensor in queue found!");
442 } else {
443 auto &nb = this->waveform_queue_.front();
444 NextionComponentBase *component = nb->component;
445
446 ESP_LOGW(TAG, "Nextion reported invalid Waveform ID %d or Channel # %d was used!",
447 component->get_component_id(), component->get_wave_channel_id());
448
449 ESP_LOGN(TAG, "Removing waveform from queue with component id %d and waveform id %d",
450 component->get_component_id(), component->get_wave_channel_id());
451
452 delete nb; // NOLINT(cppcoreguidelines-owning-memory)
453 this->waveform_queue_.pop_front();
454 }
455 break;
456 case 0x1A: // variable name invalid
457 ESP_LOGW(TAG, "Nextion reported variable name invalid!");
458 this->remove_from_q_();
459 break;
460 case 0x1B: // variable operation invalid
461 ESP_LOGW(TAG, "Nextion reported variable operation invalid!");
462 this->remove_from_q_();
463 break;
464 case 0x1C: // failed to assign
465 ESP_LOGW(TAG, "Nextion reported failed to assign variable!");
466 this->remove_from_q_();
467 break;
468 case 0x1D: // operate EEPROM failed
469 ESP_LOGW(TAG, "Nextion reported operating EEPROM failed!");
470 break;
471 case 0x1E: // parameter quantity invalid
472 ESP_LOGW(TAG, "Nextion reported parameter quantity invalid!");
473 this->remove_from_q_();
474 break;
475 case 0x1F: // IO operation failed
476 ESP_LOGW(TAG, "Nextion reported component I/O operation invalid!");
477 break;
478 case 0x20: // undefined escape characters
479 ESP_LOGW(TAG, "Nextion reported undefined escape characters!");
480 this->remove_from_q_();
481 break;
482 case 0x23: // too long variable name
483 ESP_LOGW(TAG, "Nextion reported too long variable name!");
484 this->remove_from_q_();
485 break;
486 case 0x24: // Serial Buffer overflow occurs
487 // Buffer will continue to receive the current instruction, all previous instructions are lost.
488 ESP_LOGE(TAG, "Nextion reported Serial Buffer overflow!");
489 this->buffer_overflow_callback_.call();
490 break;
491 case 0x65: { // touch event return data
492 if (to_process_length != 3) {
493 ESP_LOGW(TAG, "Touch event data is expecting 3, received %zu", to_process_length);
494 break;
495 }
496
497 uint8_t page_id = to_process[0];
498 uint8_t component_id = to_process[1];
499 uint8_t touch_event = to_process[2]; // 0 -> release, 1 -> press
500 ESP_LOGD(TAG, "Got touch event:");
501 ESP_LOGD(TAG, " page_id: %u", page_id);
502 ESP_LOGD(TAG, " component_id: %u", component_id);
503 ESP_LOGD(TAG, " event type: %s", touch_event ? "PRESS" : "RELEASE");
504 for (auto *touch : this->touch_) {
505 touch->process_touch(page_id, component_id, touch_event != 0);
506 }
507 this->touch_callback_.call(page_id, component_id, touch_event != 0);
508 break;
509 }
510 case 0x66: { // Nextion initiated new page event return data.
511 // Also is used for sendme command which we never explicitly initiate
512 if (to_process_length != 1) {
513 ESP_LOGW(TAG, "New page event data is expecting 1, received %zu", to_process_length);
514 break;
515 }
516
517 uint8_t page_id = to_process[0];
518 ESP_LOGD(TAG, "Got new page: %u", page_id);
519 this->page_callback_.call(page_id);
520 break;
521 }
522 case 0x67: { // Touch Coordinate (awake)
523 break;
524 }
525 case 0x68: { // touch coordinate data (sleep)
526
527 if (to_process_length != 5) {
528 ESP_LOGW(TAG, "Touch coordinate data is expecting 5, received %zu", to_process_length);
529 ESP_LOGW(TAG, "%s", to_process.c_str());
530 break;
531 }
532
533 uint16_t x = (uint16_t(to_process[0]) << 8) | to_process[1];
534 uint16_t y = (uint16_t(to_process[2]) << 8) | to_process[3];
535 uint8_t touch_event = to_process[4]; // 0 -> release, 1 -> press
536 ESP_LOGD(TAG, "Got touch event:");
537 ESP_LOGD(TAG, " x: %u", x);
538 ESP_LOGD(TAG, " y: %u", y);
539 ESP_LOGD(TAG, " type: %s", touch_event ? "PRESS" : "RELEASE");
540 break;
541 }
542
543 // 0x70 0x61 0x62 0x31 0x32 0x33 0xFF 0xFF 0xFF
544 // Returned when using get command for a string.
545 // Each byte is converted to char.
546 // data: ab123
547 case 0x70: // string variable data return
548 {
549 if (this->nextion_queue_.empty()) {
550 ESP_LOGW(TAG, "ERROR: Received string return but the queue is empty");
551 break;
552 }
553
554 NextionQueue *nb = this->nextion_queue_.front();
555 if (!nb || !nb->component) {
556 ESP_LOGE(TAG, "Invalid queue entry!");
557 this->nextion_queue_.pop_front();
558 return;
559 }
560 NextionComponentBase *component = nb->component;
561
562 if (component->get_queue_type() != NextionQueueType::TEXT_SENSOR) {
563 ESP_LOGE(TAG, "ERROR: Received string return but next in queue \"%s\" is not a text sensor",
564 component->get_variable_name().c_str());
565 } else {
566 ESP_LOGN(TAG, "Received get_string response: \"%s\" for component id: %s, type: %s", to_process.c_str(),
567 component->get_variable_name().c_str(), component->get_queue_type_string().c_str());
568 component->set_state_from_string(to_process, true, false);
569 }
570
571 delete nb; // NOLINT(cppcoreguidelines-owning-memory)
572 this->nextion_queue_.pop_front();
573
574 break;
575 }
576 // 0x71 0x01 0x02 0x03 0x04 0xFF 0xFF 0xFF
577 // Returned when get command to return a number
578 // 4 byte 32-bit value in little endian order.
579 // (0x01+0x02*256+0x03*65536+0x04*16777216)
580 // data: 67305985
581 case 0x71: // numeric variable data return
582 {
583 if (this->nextion_queue_.empty()) {
584 ESP_LOGE(TAG, "ERROR: Received numeric return but the queue is empty");
585 break;
586 }
587
588 if (to_process_length == 0) {
589 ESP_LOGE(TAG, "ERROR: Received numeric return but no data!");
590 break;
591 }
592
593 int value = 0;
594
595 for (int i = 0; i < 4; ++i) {
596 value += to_process[i] << (8 * i);
597 }
598
599 NextionQueue *nb = this->nextion_queue_.front();
600 if (!nb || !nb->component) {
601 ESP_LOGE(TAG, "Invalid queue entry!");
602 this->nextion_queue_.pop_front();
603 return;
604 }
605 NextionComponentBase *component = nb->component;
606
607 if (component->get_queue_type() != NextionQueueType::SENSOR &&
610 ESP_LOGE(TAG, "ERROR: Received numeric return but next in queue \"%s\" is not a valid sensor type %d",
611 component->get_variable_name().c_str(), component->get_queue_type());
612 } else {
613 ESP_LOGN(TAG, "Received numeric return for variable %s, queue type %d:%s, value %d",
614 component->get_variable_name().c_str(), component->get_queue_type(),
615 component->get_queue_type_string().c_str(), value);
616 component->set_state_from_int(value, true, false);
617 }
618
619 delete nb; // NOLINT(cppcoreguidelines-owning-memory)
620 this->nextion_queue_.pop_front();
621
622 break;
623 }
624
625 case 0x86: { // device automatically enters into sleep mode
626 ESP_LOGVV(TAG, "Received Nextion entering sleep automatically");
627 this->is_sleeping_ = true;
628 this->sleep_callback_.call();
629 break;
630 }
631 case 0x87: // device automatically wakes up
632 {
633 ESP_LOGVV(TAG, "Received Nextion leaves sleep automatically");
634 this->is_sleeping_ = false;
635 this->wake_callback_.call();
636 this->all_components_send_state_(false);
637 break;
638 }
639 case 0x88: // system successful start up
640 {
641 ESP_LOGD(TAG, "system successful start up %zu", to_process_length);
642 this->nextion_reports_is_setup_ = true;
643 break;
644 }
645 case 0x89: { // start SD card upgrade
646 break;
647 }
648 // Data from nextion is
649 // 0x90 - Start
650 // variable length of 0x70 return formatted data (bytes) that contain the variable name: prints "temp1",0
651 // 00 - NULL
652 // 00/01 - Single byte for on/off
653 // FF FF FF - End
654 case 0x90: { // Switched component
655 std::string variable_name;
656
657 // Get variable name
658 auto index = to_process.find('\0');
659 if (index == std::string::npos || (to_process_length - index - 1) < 1) {
660 ESP_LOGE(TAG, "Bad switch component data received for 0x90 event!");
661 ESP_LOGN(TAG, "to_process %s %zu %d", to_process.c_str(), to_process_length, index);
662 break;
663 }
664
665 variable_name = to_process.substr(0, index);
666 ++index;
667
668 ESP_LOGN(TAG, "Got Switch:");
669 ESP_LOGN(TAG, " variable_name: %s", variable_name.c_str());
670 ESP_LOGN(TAG, " value: %d", to_process[0] != 0);
671
672 for (auto *switchtype : this->switchtype_) {
673 switchtype->process_bool(variable_name, to_process[index] != 0);
674 }
675 break;
676 }
677 // Data from nextion is
678 // 0x91 - Start
679 // variable length of 0x70 return formatted data (bytes) that contain the variable name: prints "temp1",0
680 // 00 - NULL
681 // variable length of 0x71 return data: prints temp1.val,0
682 // FF FF FF - End
683 case 0x91: { // Sensor component
684 std::string variable_name;
685
686 auto index = to_process.find('\0');
687 if (index == std::string::npos || (to_process_length - index - 1) != 4) {
688 ESP_LOGE(TAG, "Bad sensor component data received for 0x91 event!");
689 ESP_LOGN(TAG, "to_process %s %zu %d", to_process.c_str(), to_process_length, index);
690 break;
691 }
692
693 index = to_process.find('\0');
694 variable_name = to_process.substr(0, index);
695 // // Get variable name
696 int value = 0;
697 for (int i = 0; i < 4; ++i) {
698 value += to_process[i + index + 1] << (8 * i);
699 }
700
701 ESP_LOGN(TAG, "Got sensor:");
702 ESP_LOGN(TAG, " variable_name: %s", variable_name.c_str());
703 ESP_LOGN(TAG, " value: %d", value);
704
705 for (auto *sensor : this->sensortype_) {
706 sensor->process_sensor(variable_name, value);
707 }
708 break;
709 }
710
711 // Data from nextion is
712 // 0x92 - Start
713 // variable length of 0x70 return formatted data (bytes) that contain the variable name: prints "temp1",0
714 // 00 - NULL
715 // variable length of 0x70 return formatted data (bytes) that contain the text prints temp1.txt,0
716 // 00 - NULL
717 // FF FF FF - End
718 case 0x92: { // Text Sensor Component
719 std::string variable_name;
720 std::string text_value;
721
722 // Get variable name
723 auto index = to_process.find('\0');
724 if (index == std::string::npos || (to_process_length - index - 1) < 1) {
725 ESP_LOGE(TAG, "Bad text sensor component data received for 0x92 event!");
726 ESP_LOGN(TAG, "to_process %s %zu %d", to_process.c_str(), to_process_length, index);
727 break;
728 }
729
730 variable_name = to_process.substr(0, index);
731 ++index;
732
733 text_value = to_process.substr(index);
734
735 ESP_LOGN(TAG, "Got Text Sensor:");
736 ESP_LOGN(TAG, " variable_name: %s", variable_name.c_str());
737 ESP_LOGN(TAG, " value: %s", text_value.c_str());
738
739 // NextionTextSensorResponseQueue *nq = new NextionTextSensorResponseQueue;
740 // nq->variable_name = variable_name;
741 // nq->state = text_value;
742 // this->textsensorq_.push_back(nq);
743 for (auto *textsensortype : this->textsensortype_) {
744 textsensortype->process_text(variable_name, text_value);
745 }
746 break;
747 }
748 // Data from nextion is
749 // 0x93 - Start
750 // variable length of 0x70 return formatted data (bytes) that contain the variable name: prints "temp1",0
751 // 00 - NULL
752 // 00/01 - Single byte for on/off
753 // FF FF FF - End
754 case 0x93: { // Binary Sensor component
755 std::string variable_name;
756
757 // Get variable name
758 auto index = to_process.find('\0');
759 if (index == std::string::npos || (to_process_length - index - 1) < 1) {
760 ESP_LOGE(TAG, "Bad binary sensor component data received for 0x92 event!");
761 ESP_LOGN(TAG, "to_process %s %zu %d", to_process.c_str(), to_process_length, index);
762 break;
763 }
764
765 variable_name = to_process.substr(0, index);
766 ++index;
767
768 ESP_LOGN(TAG, "Got Binary Sensor:");
769 ESP_LOGN(TAG, " variable_name: %s", variable_name.c_str());
770 ESP_LOGN(TAG, " value: %d", to_process[index] != 0);
771
772 for (auto *binarysensortype : this->binarysensortype_) {
773 binarysensortype->process_bool(&variable_name[0], to_process[index] != 0);
774 }
775 break;
776 }
777 case 0xFD: { // data transparent transmit finished
778 ESP_LOGVV(TAG, "Nextion reported data transmit finished!");
780 break;
781 }
782 case 0xFE: { // data transparent transmit ready
783 ESP_LOGVV(TAG, "Nextion reported ready for transmit!");
784 if (this->waveform_queue_.empty()) {
785 ESP_LOGE(TAG, "No waveforms in queue to send data!");
786 break;
787 }
788
789 auto &nb = this->waveform_queue_.front();
790 auto *component = nb->component;
791 size_t buffer_to_send = component->get_wave_buffer_size() < 255 ? component->get_wave_buffer_size()
792 : 255; // ADDT command can only send 255
793
794 this->write_array(component->get_wave_buffer().data(), static_cast<int>(buffer_to_send));
795
796 ESP_LOGN(TAG, "Nextion sending waveform data for component id %d and waveform id %d, size %zu",
797 component->get_component_id(), component->get_wave_channel_id(), buffer_to_send);
798
799 component->clear_wave_buffer(buffer_to_send);
800 delete nb; // NOLINT(cppcoreguidelines-owning-memory)
801 this->waveform_queue_.pop_front();
802 break;
803 }
804 default:
805 ESP_LOGW(TAG, "Received unknown event from nextion: 0x%02X", this->nextion_event_);
806 break;
807 }
808
809 // ESP_LOGN(TAG, "nextion_event_ deleting from 0 to %d", to_process_length + COMMAND_DELIMITER.length() + 1);
810 this->command_data_.erase(0, to_process_length + COMMAND_DELIMITER.length() + 1);
811 // App.feed_wdt(); Remove before master merge
812 this->process_serial_();
813 }
814
815 uint32_t ms = millis();
816
817 if (!this->nextion_queue_.empty() && this->nextion_queue_.front()->queue_time + this->max_q_age_ms_ < ms) {
818 for (size_t i = 0; i < this->nextion_queue_.size(); i++) {
819 NextionComponentBase *component = this->nextion_queue_[i]->component;
820 if (this->nextion_queue_[i]->queue_time + this->max_q_age_ms_ < ms) {
821 if (this->nextion_queue_[i]->queue_time == 0) {
822 ESP_LOGD(TAG, "Removing old queue type \"%s\" name \"%s\" queue_time 0",
823 component->get_queue_type_string().c_str(), component->get_variable_name().c_str());
824 }
825
826 if (component->get_variable_name() == "sleep_wake") {
827 this->is_sleeping_ = false;
828 }
829
830 ESP_LOGD(TAG, "Removing old queue type \"%s\" name \"%s\"", component->get_queue_type_string().c_str(),
831 component->get_variable_name().c_str());
832
833 if (component->get_queue_type() == NextionQueueType::NO_RESULT) {
834 if (component->get_variable_name() == "sleep_wake") {
835 this->is_sleeping_ = false;
836 }
837 delete component; // NOLINT(cppcoreguidelines-owning-memory)
838 }
839
840 delete this->nextion_queue_[i]; // NOLINT(cppcoreguidelines-owning-memory)
841
842 this->nextion_queue_.erase(this->nextion_queue_.begin() + i);
843 i--;
844
845 } else {
846 break;
847 }
848 }
849 }
850 ESP_LOGN(TAG, "Loop End");
851 // App.feed_wdt(); Remove before master merge
852 this->process_serial_();
853} // namespace nextion
854
855void Nextion::set_nextion_sensor_state(int queue_type, const std::string &name, float state) {
856 this->set_nextion_sensor_state(static_cast<NextionQueueType>(queue_type), name, state);
857}
858
859void Nextion::set_nextion_sensor_state(NextionQueueType queue_type, const std::string &name, float state) {
860 ESP_LOGN(TAG, "Received state:");
861 ESP_LOGN(TAG, " variable: %s", name.c_str());
862 ESP_LOGN(TAG, " state: %lf", state);
863 ESP_LOGN(TAG, " queue type: %d", queue_type);
864
865 switch (queue_type) {
867 for (auto *sensor : this->sensortype_) {
868 if (name == sensor->get_variable_name()) {
869 sensor->set_state(state, true, true);
870 break;
871 }
872 }
873 break;
874 }
876 for (auto *sensor : this->binarysensortype_) {
877 if (name == sensor->get_variable_name()) {
878 sensor->set_state(state != 0, true, true);
879 break;
880 }
881 }
882 break;
883 }
885 for (auto *sensor : this->switchtype_) {
886 if (name == sensor->get_variable_name()) {
887 sensor->set_state(state != 0, true, true);
888 break;
889 }
890 }
891 break;
892 }
893 default: {
894 ESP_LOGW(TAG, "set_nextion_sensor_state does not support a queue type %d", queue_type);
895 }
896 }
897}
898
899void Nextion::set_nextion_text_state(const std::string &name, const std::string &state) {
900 ESP_LOGD(TAG, "Received state:");
901 ESP_LOGD(TAG, " variable: %s", name.c_str());
902 ESP_LOGD(TAG, " state: %s", state.c_str());
903
904 for (auto *sensor : this->textsensortype_) {
905 if (name == sensor->get_variable_name()) {
906 sensor->set_state(state, true, true);
907 break;
908 }
909 }
910}
911
912void Nextion::all_components_send_state_(bool force_update) {
913 ESP_LOGD(TAG, "all_components_send_state_ ");
914 for (auto *binarysensortype : this->binarysensortype_) {
915 if (force_update || binarysensortype->get_needs_to_send_update())
916 binarysensortype->send_state_to_nextion();
917 }
918 for (auto *sensortype : this->sensortype_) {
919 if ((force_update || sensortype->get_needs_to_send_update()) && sensortype->get_wave_chan_id() == 0)
920 sensortype->send_state_to_nextion();
921 }
922 for (auto *switchtype : this->switchtype_) {
923 if (force_update || switchtype->get_needs_to_send_update())
924 switchtype->send_state_to_nextion();
925 }
926 for (auto *textsensortype : this->textsensortype_) {
927 if (force_update || textsensortype->get_needs_to_send_update())
928 textsensortype->send_state_to_nextion();
929 }
930}
931
932void Nextion::update_components_by_prefix(const std::string &prefix) {
933 for (auto *binarysensortype : this->binarysensortype_) {
934 if (binarysensortype->get_variable_name().find(prefix, 0) != std::string::npos)
935 binarysensortype->update_component_settings(true);
936 }
937 for (auto *sensortype : this->sensortype_) {
938 if (sensortype->get_variable_name().find(prefix, 0) != std::string::npos)
939 sensortype->update_component_settings(true);
940 }
941 for (auto *switchtype : this->switchtype_) {
942 if (switchtype->get_variable_name().find(prefix, 0) != std::string::npos)
943 switchtype->update_component_settings(true);
944 }
945 for (auto *textsensortype : this->textsensortype_) {
946 if (textsensortype->get_variable_name().find(prefix, 0) != std::string::npos)
947 textsensortype->update_component_settings(true);
948 }
949}
950
951uint16_t Nextion::recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag) {
952 uint16_t ret = 0;
953 uint8_t c = 0;
954 uint8_t nr_of_ff_bytes = 0;
955 uint64_t start;
956 bool exit_flag = false;
957 bool ff_flag = false;
958
959 start = millis();
960
961 while ((timeout == 0 && this->available()) || millis() - start <= timeout) {
962 if (!this->available()) {
963 App.feed_wdt();
964 delay(1);
965 continue;
966 }
967
968 this->read_byte(&c);
969 if (c == 0xFF) {
970 nr_of_ff_bytes++;
971 } else {
972 nr_of_ff_bytes = 0;
973 ff_flag = false;
974 }
975
976 if (nr_of_ff_bytes >= 3)
977 ff_flag = true;
978
979 response += (char) c;
980 if (recv_flag) {
981 if (response.find(0x05) != std::string::npos) {
982 exit_flag = true;
983 }
984 }
985 App.feed_wdt();
986 delay(2);
987
988 if (exit_flag || ff_flag) {
989 break;
990 }
991 }
992
993 if (ff_flag)
994 response = response.substr(0, response.length() - 3); // Remove last 3 0xFF
995
996 ret = response.length();
997 return ret;
998}
999
1005void Nextion::add_no_result_to_queue_(const std::string &variable_name) {
1006 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
1007 nextion::NextionQueue *nextion_queue = new nextion::NextionQueue;
1008
1009 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
1010 nextion_queue->component = new nextion::NextionComponentBase;
1011 nextion_queue->component->set_variable_name(variable_name);
1012
1013 nextion_queue->queue_time = millis();
1014
1015 this->nextion_queue_.push_back(nextion_queue);
1016
1017 ESP_LOGN(TAG, "Add to queue type: NORESULT component %s", nextion_queue->component->get_variable_name().c_str());
1018}
1019
1026void Nextion::add_no_result_to_queue_with_command_(const std::string &variable_name, const std::string &command) {
1027 if ((!this->is_setup() && !this->ignore_is_setup_) || command.empty())
1028 return;
1029
1030 if (this->send_command_(command)) {
1031 this->add_no_result_to_queue_(variable_name);
1032 }
1033}
1034
1035bool Nextion::add_no_result_to_queue_with_ignore_sleep_printf_(const std::string &variable_name, const char *format,
1036 ...) {
1037 if ((!this->is_setup() && !this->ignore_is_setup_))
1038 return false;
1039
1040 char buffer[256];
1041 va_list arg;
1042 va_start(arg, format);
1043 int ret = vsnprintf(buffer, sizeof(buffer), format, arg);
1044 va_end(arg);
1045 if (ret <= 0) {
1046 ESP_LOGW(TAG, "Building command for format '%s' failed!", format);
1047 return false;
1048 }
1049
1050 this->add_no_result_to_queue_with_command_(variable_name, buffer);
1051 return true;
1052}
1053
1061bool Nextion::add_no_result_to_queue_with_printf_(const std::string &variable_name, const char *format, ...) {
1062 if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
1063 return false;
1064
1065 char buffer[256];
1066 va_list arg;
1067 va_start(arg, format);
1068 int ret = vsnprintf(buffer, sizeof(buffer), format, arg);
1069 va_end(arg);
1070 if (ret <= 0) {
1071 ESP_LOGW(TAG, "Building command for format '%s' failed!", format);
1072 return false;
1073 }
1074
1075 this->add_no_result_to_queue_with_command_(variable_name, buffer);
1076 return true;
1077}
1078
1090 state_value);
1091}
1092
1093void Nextion::add_no_result_to_queue_with_set(const std::string &variable_name,
1094 const std::string &variable_name_to_send, int32_t state_value) {
1095 this->add_no_result_to_queue_with_set_internal_(variable_name, variable_name_to_send, state_value);
1096}
1097
1098void Nextion::add_no_result_to_queue_with_set_internal_(const std::string &variable_name,
1099 const std::string &variable_name_to_send, int32_t state_value,
1100 bool is_sleep_safe) {
1101 if ((!this->is_setup() && !this->ignore_is_setup_) || (!is_sleep_safe && this->is_sleeping()))
1102 return;
1103
1104 this->add_no_result_to_queue_with_ignore_sleep_printf_(variable_name, "%s=%" PRId32, variable_name_to_send.c_str(),
1105 state_value);
1106}
1107
1116void Nextion::add_no_result_to_queue_with_set(NextionComponentBase *component, const std::string &state_value) {
1118 state_value);
1119}
1120void Nextion::add_no_result_to_queue_with_set(const std::string &variable_name,
1121 const std::string &variable_name_to_send,
1122 const std::string &state_value) {
1123 this->add_no_result_to_queue_with_set_internal_(variable_name, variable_name_to_send, state_value);
1124}
1125
1126void Nextion::add_no_result_to_queue_with_set_internal_(const std::string &variable_name,
1127 const std::string &variable_name_to_send,
1128 const std::string &state_value, bool is_sleep_safe) {
1129 if ((!this->is_setup() && !this->ignore_is_setup_) || (!is_sleep_safe && this->is_sleeping()))
1130 return;
1131
1132 this->add_no_result_to_queue_with_printf_(variable_name, "%s=\"%s\"", variable_name_to_send.c_str(),
1133 state_value.c_str());
1134}
1135
1137 if ((!this->is_setup() && !this->ignore_is_setup_))
1138 return;
1139
1140 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
1141 nextion::NextionQueue *nextion_queue = new nextion::NextionQueue;
1142
1143 nextion_queue->component = component;
1144 nextion_queue->queue_time = millis();
1145
1146 ESP_LOGN(TAG, "Add to queue type: %s component %s", component->get_queue_type_string().c_str(),
1147 component->get_variable_name().c_str());
1148
1149 std::string command = "get " + component->get_variable_name_to_send();
1150
1151 if (this->send_command_(command)) {
1152 this->nextion_queue_.push_back(nextion_queue);
1153 }
1154}
1155
1165 if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
1166 return;
1167
1168 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
1169 nextion::NextionQueue *nextion_queue = new nextion::NextionQueue;
1170
1171 nextion_queue->component = component;
1172 nextion_queue->queue_time = millis();
1173
1174 this->waveform_queue_.push_back(nextion_queue);
1175 if (this->waveform_queue_.size() == 1)
1177}
1178
1180 if (this->waveform_queue_.empty())
1181 return;
1182
1183 auto *nb = this->waveform_queue_.front();
1184 auto *component = nb->component;
1185 size_t buffer_to_send = component->get_wave_buffer_size() < 255 ? component->get_wave_buffer_size()
1186 : 255; // ADDT command can only send 255
1187
1188 std::string command = "addt " + to_string(component->get_component_id()) + "," +
1189 to_string(component->get_wave_channel_id()) + "," + to_string(buffer_to_send);
1190 if (!this->send_command_(command)) {
1191 delete nb; // NOLINT(cppcoreguidelines-owning-memory)
1192 this->waveform_queue_.pop_front();
1193 }
1194}
1195
1196void Nextion::set_writer(const nextion_writer_t &writer) { this->writer_ = writer; }
1197
1198ESPDEPRECATED("set_wait_for_ack(bool) is deprecated and has no effect", "v1.20")
1199void Nextion::set_wait_for_ack(bool wait_for_ack) { ESP_LOGE(TAG, "This command is deprecated"); }
1200
1201bool Nextion::is_updating() { return this->is_updating_; }
1202
1203} // namespace nextion
1204} // namespace esphome
void feed_wdt(uint32_t time=0)
uint8_t get_spacing() const
Get current command spacing.
Definition nextion.h:57
bool can_send() const
Check if enough time has passed to send next command.
Definition nextion.h:63
void mark_sent()
Mark a command as sent, updating the timing.
Definition nextion.h:68
virtual void set_state_from_int(int state_value, bool publish, bool send_to_nextion)
void set_variable_name(const std::string &variable_name, const std::string &variable_name_to_send="")
virtual void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion)
void add_setup_state_callback(std::function< void()> &&callback)
Add a callback to be notified when the nextion completes its initialize setup.
Definition nextion.cpp:196
std::vector< NextionComponentBase * > touch_
Definition nextion.h:1378
std::vector< NextionComponentBase * > switchtype_
Definition nextion.h:1379
void add_buffer_overflow_event_callback(std::function< void()> &&callback)
Add a callback to be notified when the nextion reports a buffer overflow.
Definition nextion.cpp:208
std::vector< NextionComponentBase * > binarysensortype_
Definition nextion.h:1382
const uint16_t max_q_age_ms_
Definition nextion.h:1408
const uint16_t startup_override_ms_
Definition nextion.h:1407
bool send_command_(const std::string &command)
Manually send a raw command to the display and don't wait for an acknowledgement packet.
Definition nextion.cpp:29
std::vector< NextionComponentBase * > textsensortype_
Definition nextion.h:1381
CallbackManager< void(uint8_t)> page_callback_
Definition nextion.h:1386
void set_wake_up_page(uint8_t wake_up_page=255)
Sets which page Nextion loads when exiting sleep mode.
optional< nextion_writer_t > writer_
Definition nextion.h:1390
std::string device_model_
Definition nextion.h:1393
void all_components_send_state_(bool force_update=false)
Definition nextion.cpp:912
std::string firmware_version_
Definition nextion.h:1394
void set_nextion_sensor_state(int queue_type, const std::string &name, float state)
Set the nextion sensor state object.
Definition nextion.cpp:855
void add_addt_command_to_queue(NextionComponentBase *component) override
Add addt command to the queue.
Definition nextion.cpp:1164
bool ignore_is_setup_
Sends commands ignoring of the Nextion has been setup.
Definition nextion.h:1290
void add_new_page_callback(std::function< void(uint8_t)> &&callback)
Add a callback to be notified when the nextion changes pages.
Definition nextion.cpp:200
void add_to_get_queue(NextionComponentBase *component) override
Definition nextion.cpp:1136
bool send_command_printf(const char *format,...) __attribute__((format(printf
Manually send a raw formatted command to the display.
Definition nextion.cpp:241
void setup() override
Definition nextion.cpp:12
std::deque< NextionQueue * > nextion_queue_
Definition nextion.h:1279
void loop() override
Definition nextion.cpp:282
bool remove_from_q_(bool report_empty=true)
Definition nextion.cpp:321
std::vector< NextionComponentBase * > sensortype_
Definition nextion.h:1380
bool void add_no_result_to_queue_with_set_internal_(const std::string &variable_name, const std::string &variable_name_to_send, int32_t state_value, bool is_sleep_safe=false)
Definition nextion.cpp:1098
bool add_no_result_to_queue_with_printf_(const std::string &variable_name, const char *format,...) __attribute__((format(printf
Sends a formatted command to the nextion.
Definition nextion.cpp:1061
CallbackManager< void()> setup_callback_
Definition nextion.h:1383
std::string command_data_
Definition nextion.h:1405
optional< float > brightness_
Definition nextion.h:1391
CallbackManager< void()> wake_callback_
Definition nextion.h:1385
void add_sleep_state_callback(std::function< void()> &&callback)
Add a callback to be notified of sleep state changes.
Definition nextion.cpp:188
bool is_updating() override
Check if the TFT update process is currently running.
Definition nextion.cpp:1201
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag)
Definition nextion.cpp:951
void goto_page(const char *page)
Show the page with a given name.
bool send_command(const char *command)
Manually send a raw command to the display.
Definition nextion.cpp:230
std::string serial_number_
Definition nextion.h:1395
CallbackManager< void()> sleep_callback_
Definition nextion.h:1384
float get_setup_priority() const override
Definition nextion.cpp:178
bool void add_no_result_to_queue_with_command_(const std::string &variable_name, const std::string &command)
Definition nextion.cpp:1026
void reset_(bool reset_nextion=true)
Definition nextion.cpp:138
void add_no_result_to_queue_(const std::string &variable_name)
Definition nextion.cpp:1005
CallbackManager< void(uint8_t, uint8_t, bool)> touch_callback_
Definition nextion.h:1387
void dump_config() override
Definition nextion.cpp:148
NextionCommandPacer command_pacer_
Definition nextion.h:1277
void set_nextion_text_state(const std::string &name, const std::string &state)
Definition nextion.cpp:899
std::deque< NextionQueue * > waveform_queue_
Definition nextion.h:1280
bool add_no_result_to_queue_with_ignore_sleep_printf_(const std::string &variable_name, const char *format,...) __attribute__((format(printf
Definition nextion.cpp:1035
void update() override
Definition nextion.cpp:179
void add_wake_state_callback(std::function< void()> &&callback)
Add a callback to be notified of wake state changes.
Definition nextion.cpp:192
CallbackManager< void()> buffer_overflow_callback_
Definition nextion.h:1388
void set_writer(const nextion_writer_t &writer)
Definition nextion.cpp:1196
void add_no_result_to_queue_with_set(NextionComponentBase *component, int32_t state_value) override
Definition nextion.cpp:1088
void add_touch_event_callback(std::function< void(uint8_t, uint8_t, bool)> &&callback)
Add a callback to be notified when Nextion has a touch event.
Definition nextion.cpp:204
void update_components_by_prefix(const std::string &prefix)
Definition nextion.cpp:932
void set_backlight_brightness(float brightness)
Set the brightness of the backlight.
bool has_value() const
Definition optional.h:87
value_type const & value() const
Definition optional.h:89
void write_str(const char *str)
Definition uart.h:27
bool read_byte(uint8_t *data)
Definition uart.h:29
void write_array(const uint8_t *data, size_t len)
Definition uart.h:21
bool state
Definition fan.h:0
std::function< void(Nextion &)> nextion_writer_t
Definition nextion.h:34
ESPDEPRECATED("set_wait_for_ack(bool) is deprecated and has no effect", "v1.20") void Nextion
Definition nextion.cpp:1198
const float DATA
For components that import data from directly connected sensors like DHT.
Definition component.cpp:19
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string to_string(int value)
Definition helpers.cpp:82
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:28
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27
Application App
Global storage of Application pointer - only one Application can exist.
uint8_t end[39]
Definition sun_gtil2.cpp:17
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6