11static const char *
const TAG =
"nextion";
32#ifdef USE_NEXTION_COMMAND_SPACING
33 if (!this->
connection_state_.ignore_is_setup_ && !this->command_pacer_.can_send()) {
34 ESP_LOGN(TAG,
"Command spacing: delaying command '%s'", command.c_str());
39 ESP_LOGN(TAG,
"cmd: %s", command.c_str());
42 const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF};
52#ifdef USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE
53 ESP_LOGW(TAG,
"Connected (no handshake)");
62#ifdef USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START
79 if (!response.empty() && response[0] == 0x1A) {
81 ESP_LOGV(TAG,
"0x1A error ignored (setup)");
84 if (response.empty() || response.find(
"comok") == std::string::npos) {
85#ifdef NEXTION_PROTOCOL_LOG
86 ESP_LOGN(TAG,
"Bad connect: %s", response.c_str());
87 for (
size_t i = 0; i < response.length(); i++) {
88 ESP_LOGN(TAG,
"resp: %s %d %d %c", response.c_str(), i, response[i], response[i]);
92 ESP_LOGW(TAG,
"Not connected");
98 ESP_LOGI(TAG,
"Connected");
101 ESP_LOGN(TAG,
"connect: %s", response.c_str());
105 std::vector<std::string> connect_info;
106 while ((start = response.find_first_not_of(
',',
end)) != std::string::npos) {
107 end = response.find(
',', start);
108 connect_info.push_back(response.substr(start,
end - start));
113 ESP_LOGN(TAG,
"Connect info: %zu", connect_info.size());
114#ifdef USE_NEXTION_CONFIG_DUMP_DEVICE_INFO
121 " Device Model: %s\n"
123 " Serial Number: %s\n"
125 connect_info[2].c_str(), connect_info[3].c_str(), connect_info[5].c_str(), connect_info[6].c_str());
128 ESP_LOGE(TAG,
"Bad connect value: '%s'", response.c_str());
148 ESP_LOGCONFIG(TAG,
"Nextion:");
150#ifdef USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE
151 ESP_LOGCONFIG(TAG,
" Skip handshake: YES");
153#ifdef USE_NEXTION_CONFIG_DUMP_DEVICE_INFO
155 " Device Model: %s\n"
157 " Serial Number: %s\n"
159 " Max queue age: %u ms\n"
160 " Startup override: %u ms\n",
161 this->
device_model_.c_str(), this->firmware_version_.c_str(), this->serial_number_.c_str(),
162 this->flash_size_.c_str(), this->max_q_age_ms_, this->startup_override_ms_);
164#ifdef USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START
165 ESP_LOGCONFIG(TAG,
" Exit reparse: YES\n");
168 " Wake On Touch: %s\n"
169 " Touch Timeout: %" PRIu16,
173#ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP
178 ESP_LOGCONFIG(TAG,
" Wake Up Page: %u", this->
wake_up_page_);
181#ifdef USE_NEXTION_CONF_START_UP_PAGE
187#ifdef USE_NEXTION_COMMAND_SPACING
191#ifdef USE_NEXTION_MAX_QUEUE_SIZE
194#ifdef USE_NEXTION_TFT_UPLOAD
197 " TFT upload HTTP timeout: %" PRIu16
"ms\n"
198 " TFT upload HTTP retries: %u",
199 this->
tft_url_.c_str(), this->tft_upload_http_timeout_, this->tft_upload_http_retries_);
246 binarysensortype->update_component();
249 sensortype->update_component();
252 switchtype->update_component();
255 textsensortype->update_component();
277 int ret = vsnprintf(buffer,
sizeof(buffer),
format, arg);
280 ESP_LOGW(TAG,
"Bad cmd format: '%s'",
format);
291#ifdef NEXTION_PROTOCOL_LOG
293 ESP_LOGN(TAG,
"print_queue_members_ (top 10) size %zu", this->
nextion_queue_.size());
294 ESP_LOGN(TAG,
"*******************************************");
301 ESP_LOGN(TAG,
"Queue null");
303 ESP_LOGN(TAG,
"Queue type: %d:%s, name: %s", i->component->get_queue_type(),
304 i->component->get_queue_type_string().c_str(), i->component->get_variable_name().c_str());
307 ESP_LOGN(TAG,
"*******************************************");
315 if (this->
connection_state_.nextion_reports_is_setup_ && !this->connection_state_.sent_setup_commands_) {
324#ifdef USE_NEXTION_CONF_START_UP_PAGE
353 ESP_LOGV(TAG,
"Manual ready set");
358#ifdef USE_NEXTION_COMMAND_SPACING
364#ifdef USE_NEXTION_COMMAND_SPACING
366 if (this->
nextion_queue_.empty() || !this->command_pacer_.can_send()) {
372 if (front_item && !front_item->pending_command.empty()) {
375 front_item->pending_command.clear();
376 ESP_LOGVV(TAG,
"Pending command sent: %s", front_item->component->get_variable_name().c_str());
385 ESP_LOGE(TAG,
"Queue empty");
392 ESP_LOGE(TAG,
"Invalid queue");
398 ESP_LOGN(TAG,
"Removed: %s",
component->get_variable_name().c_str());
401 if (
component->get_variable_name() ==
"sleep_wake") {
416 size_t to_read = std::min(avail,
sizeof(buf));
422 this->
command_data_.append(
reinterpret_cast<const char *
>(buf), to_read);
431#ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP
432 size_t commands_processed = 0;
435 size_t to_process_length = 0;
436 std::string to_process;
438 ESP_LOGN(TAG,
"command_data_ %s len %d", this->
command_data_.c_str(), this->command_data_.length());
439#ifdef NEXTION_PROTOCOL_LOG
442 while ((to_process_length = this->
command_data_.find(COMMAND_DELIMITER)) != std::string::npos) {
443#ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP
445 ESP_LOGW(TAG,
"Command processing limit exceeded");
450 while (to_process_length + COMMAND_DELIMITER.length() < this->command_data_.length() &&
451 static_cast<uint8_t
>(this->command_data_[to_process_length + COMMAND_DELIMITER.length()]) == 0xFF) {
453 ESP_LOGN(TAG,
"Add 0xFF");
458 to_process_length -= 1;
459 to_process = this->
command_data_.substr(1, to_process_length);
461 switch (nextion_event) {
463 ESP_LOGW(TAG,
"Invalid instruction");
469 ESP_LOGVV(TAG,
"Cmd OK");
470 ESP_LOGN(TAG,
"this->nextion_queue_.empty() %s", YESNO(this->
nextion_queue_.empty()));
479#ifdef USE_NEXTION_COMMAND_SPACING
481 ESP_LOGN(TAG,
"Command spacing: marked command sent");
485 ESP_LOGW(TAG,
"Invalid component ID/name");
489 ESP_LOGW(TAG,
"Invalid page ID");
493 ESP_LOGW(TAG,
"Invalid picture ID");
497 ESP_LOGW(TAG,
"Invalid font ID");
501 ESP_LOGW(TAG,
"File operation failed");
504 ESP_LOGW(TAG,
"CRC validation failed");
507 ESP_LOGW(TAG,
"Invalid baud rate");
511 ESP_LOGW(TAG,
"Waveform ID/ch used but no sensor queued");
516 ESP_LOGW(TAG,
"Invalid waveform ID %d/ch %d",
component->get_component_id(),
519 ESP_LOGN(TAG,
"Remove waveform ID %d/ch %d",
component->get_component_id(),
component->get_wave_channel_id());
526 ESP_LOGW(TAG,
"Invalid variable name");
530 ESP_LOGW(TAG,
"Invalid variable operation");
534 ESP_LOGW(TAG,
"Variable assign failed");
538 ESP_LOGW(TAG,
"EEPROM operation failed");
541 ESP_LOGW(TAG,
"Invalid parameter count");
545 ESP_LOGW(TAG,
"Invalid component I/O");
548 ESP_LOGW(TAG,
"Undefined escape chars");
552 ESP_LOGW(TAG,
"Variable name too long");
557 ESP_LOGE(TAG,
"Serial buffer overflow");
561 if (to_process_length != 3) {
562 ESP_LOGW(TAG,
"Incorrect touch len: %zu (need 3)", to_process_length);
566 uint8_t page_id = to_process[0];
567 uint8_t component_id = to_process[1];
568 uint8_t touch_event = to_process[2];
569 ESP_LOGV(TAG,
"Touch %s: page %u comp %u", touch_event ?
"PRESS" :
"RELEASE", page_id, component_id);
570 for (
auto *touch : this->
touch_) {
571 touch->process_touch(page_id, component_id, touch_event != 0);
578 if (to_process_length != 1) {
579 ESP_LOGW(TAG,
"Page event: expect 1, got %zu", to_process_length);
583 uint8_t page_id = to_process[0];
584 ESP_LOGV(TAG,
"New page: %u", page_id);
593 if (to_process_length != 5) {
594 ESP_LOGW(TAG,
"Touch coordinate: expect 5, got %zu", to_process_length);
595 ESP_LOGW(TAG,
"%s", to_process.c_str());
599 const uint16_t
x = (uint16_t(to_process[0]) << 8) | to_process[1];
600 const uint16_t
y = (uint16_t(to_process[2]) << 8) | to_process[3];
601 const uint8_t touch_event = to_process[4];
602 ESP_LOGV(TAG,
"Touch %s at %u,%u", touch_event ?
"PRESS" :
"RELEASE",
x,
y);
613 ESP_LOGW(TAG,
"String return but queue is empty");
619 ESP_LOGE(TAG,
"Invalid queue entry");
626 ESP_LOGE(TAG,
"String return but '%s' not text sensor",
component->get_variable_name().c_str());
628 ESP_LOGN(TAG,
"String resp: '%s' id: %s type: %s", to_process.c_str(),
component->get_variable_name().c_str(),
629 component->get_queue_type_string().c_str());
645 ESP_LOGE(TAG,
"Numeric return but queue empty");
649 if (to_process_length < 4) {
650 ESP_LOGE(TAG,
"Numeric return but insufficient data (need 4, got %zu)", to_process_length);
654 int value =
static_cast<int>(
encode_uint32(to_process[3], to_process[2], to_process[1], to_process[0]));
658 ESP_LOGE(TAG,
"Invalid queue");
667 ESP_LOGE(TAG,
"Numeric return but '%s' invalid type %d",
component->get_variable_name().c_str(),
670 ESP_LOGN(TAG,
"Numeric: %s type %d:%s val %d",
component->get_variable_name().c_str(),
672 component->set_state_from_int(value,
true,
false);
682 ESP_LOGVV(TAG,
"Auto sleep");
689 ESP_LOGVV(TAG,
"Auto wake");
697 ESP_LOGV(TAG,
"System start: %zu", to_process_length);
711 std::string variable_name;
714 auto index = to_process.find(
'\0');
715 if (index == std::string::npos || (to_process_length - index - 1) < 1) {
716 ESP_LOGE(TAG,
"Bad switch data (0x90)");
717 ESP_LOGN(TAG,
"proc: %s %zu %d", to_process.c_str(), to_process_length, index);
721 variable_name = to_process.substr(0, index);
724 ESP_LOGN(TAG,
"Switch %s: %s", ONOFF(to_process[index] != 0), variable_name.c_str());
727 switchtype->process_bool(variable_name, to_process[index] != 0);
738 std::string variable_name;
740 auto index = to_process.find(
'\0');
741 if (index == std::string::npos || (to_process_length - index - 1) != 4) {
742 ESP_LOGE(TAG,
"Bad sensor data (0x91)");
743 ESP_LOGN(TAG,
"proc: %s %zu %d", to_process.c_str(), to_process_length, index);
747 index = to_process.find(
'\0');
748 variable_name = to_process.substr(0, index);
750 int value =
static_cast<int>(
751 encode_uint32(to_process[index + 4], to_process[index + 3], to_process[index + 2], to_process[index + 1]));
753 ESP_LOGN(TAG,
"Sensor: %s=%d", variable_name.c_str(), value);
756 sensor->process_sensor(variable_name, value);
769 std::string variable_name;
770 std::string text_value;
773 auto index = to_process.find(
'\0');
774 if (index == std::string::npos || (to_process_length - index - 1) < 1) {
775 ESP_LOGE(TAG,
"Bad text data (0x92)");
776 ESP_LOGN(TAG,
"proc: %s %zu %d", to_process.c_str(), to_process_length, index);
780 variable_name = to_process.substr(0, index);
784 text_value = to_process.substr(index, to_process_length - index - 1);
786 ESP_LOGN(TAG,
"Text sensor: %s='%s'", variable_name.c_str(), text_value.c_str());
793 textsensortype->process_text(variable_name, text_value);
804 std::string variable_name;
807 auto index = to_process.find(
'\0');
808 if (index == std::string::npos || (to_process_length - index - 1) < 1) {
809 ESP_LOGE(TAG,
"Bad binary data (0x92)");
810 ESP_LOGN(TAG,
"proc: %s %zu %d", to_process.c_str(), to_process_length, index);
814 variable_name = to_process.substr(0, index);
817 ESP_LOGN(TAG,
"Binary sensor: %s=%s", variable_name.c_str(), ONOFF(to_process[index] != 0));
820 binarysensortype->process_bool(&variable_name[0], to_process[index] != 0);
825 ESP_LOGVV(TAG,
"Data transmit done");
830 ESP_LOGVV(TAG,
"Ready for transmit");
832 ESP_LOGE(TAG,
"No waveforms queued");
838 size_t buffer_to_send =
component->get_wave_buffer_size() < 255 ?
component->get_wave_buffer_size()
843 ESP_LOGN(TAG,
"Send waveform: component id %d, waveform id %d, size %zu",
component->get_component_id(),
844 component->get_wave_channel_id(), buffer_to_send);
846 component->clear_wave_buffer(buffer_to_send);
852 ESP_LOGW(TAG,
"Unknown event: 0x%02X", nextion_event);
856 this->
command_data_.erase(0, to_process_length + COMMAND_DELIMITER.length() + 1);
862 ms - this->nextion_queue_.front()->queue_time > this->max_q_age_ms_) {
867 ESP_LOGD(TAG,
"Remove old queue '%s':'%s' (t=0)",
component->get_queue_type_string().c_str(),
871 if (
component->get_variable_name() ==
"sleep_wake") {
875 ESP_LOGD(TAG,
"Remove old queue '%s':'%s'",
component->get_queue_type_string().c_str(),
879 if (
component->get_variable_name() ==
"sleep_wake") {
895 ESP_LOGN(TAG,
"Loop end");
905 ESP_LOGN(TAG,
"State: %s=%lf (type %d)", name.c_str(),
state, queue_type);
907 switch (queue_type) {
910 if (name == sensor->get_variable_name()) {
911 sensor->set_state(
state,
true,
true);
919 if (name == sensor->get_variable_name()) {
920 sensor->set_state(
state != 0,
true,
true);
928 if (name == sensor->get_variable_name()) {
929 sensor->set_state(
state != 0,
true,
true);
936 ESP_LOGW(TAG,
"set_sensor_state: bad type %d", queue_type);
942 ESP_LOGV(TAG,
"State: %s='%s'", name.c_str(),
state.c_str());
945 if (name == sensor->get_variable_name()) {
946 sensor->set_state(
state,
true,
true);
953 ESP_LOGV(TAG,
"Send states");
955 if (force_update || binarysensortype->get_needs_to_send_update())
956 binarysensortype->send_state_to_nextion();
959 if ((force_update || sensortype->get_needs_to_send_update()) && sensortype->get_wave_chan_id() == 0)
960 sensortype->send_state_to_nextion();
963 if (force_update || switchtype->get_needs_to_send_update())
964 switchtype->send_state_to_nextion();
967 if (force_update || textsensortype->get_needs_to_send_update())
968 textsensortype->send_state_to_nextion();
974 if (binarysensortype->get_variable_name().find(prefix, 0) != std::string::npos)
975 binarysensortype->update_component_settings(
true);
978 if (sensortype->get_variable_name().find(prefix, 0) != std::string::npos)
979 sensortype->update_component_settings(
true);
982 if (switchtype->get_variable_name().find(prefix, 0) != std::string::npos)
983 switchtype->update_component_settings(
true);
986 if (textsensortype->get_variable_name().find(prefix, 0) != std::string::npos)
987 textsensortype->update_component_settings(
true);
993 uint8_t nr_of_ff_bytes = 0;
994 bool exit_flag =
false;
995 bool ff_flag =
false;
999 while ((timeout == 0 && this->
available()) ||
millis() - start <= timeout) {
1014 if (nr_of_ff_bytes >= 3)
1017 response += (char) c;
1019 if (response.find(0x05) != std::string::npos) {
1026 if (exit_flag || ff_flag) {
1032 response = response.substr(0, response.length() - 3);
1034 return response.length();
1048#ifdef USE_NEXTION_MAX_QUEUE_SIZE
1050 ESP_LOGW(TAG,
"Queue full (%zu), drop: %s", this->
nextion_queue_.size(), variable_name.c_str());
1057 if (nextion_queue ==
nullptr) {
1058 ESP_LOGW(TAG,
"Queue alloc failed");
1086#ifdef USE_NEXTION_COMMAND_SPACING
1094#ifdef USE_NEXTION_COMMAND_SPACING
1096 const std::string &command) {
1097#ifdef USE_NEXTION_MAX_QUEUE_SIZE
1099 ESP_LOGW(TAG,
"Queue full (%zu), drop: %s", this->
nextion_queue_.size(), variable_name.c_str());
1106 if (nextion_queue ==
nullptr) {
1107 ESP_LOGW(TAG,
"Queue alloc failed");
1118 ESP_LOGVV(TAG,
"Queue with pending command: %s", variable_name.c_str());
1130 int ret = vsnprintf(buffer,
sizeof(buffer),
format, arg);
1133 ESP_LOGW(TAG,
"Bad cmd format: '%s'",
format);
1155 int ret = vsnprintf(buffer,
sizeof(buffer),
format, arg);
1158 ESP_LOGW(TAG,
"Bad cmd format: '%s'",
format);
1181 const std::string &variable_name_to_send, int32_t state_value) {
1186 const std::string &variable_name_to_send, int32_t state_value,
1187 bool is_sleep_safe) {
1208 const std::string &variable_name_to_send,
1209 const std::string &state_value) {
1214 const std::string &variable_name_to_send,
1215 const std::string &state_value,
bool is_sleep_safe) {
1220 state_value.c_str());
1236#ifdef USE_NEXTION_MAX_QUEUE_SIZE
1238 ESP_LOGW(TAG,
"Queue full (%zu), drop GET: %s", this->
nextion_queue_.size(),
1246 if (nextion_queue ==
nullptr) {
1247 ESP_LOGW(TAG,
"Queue alloc failed");
1255 ESP_LOGN(TAG,
"Queue %s: %s",
component->get_queue_type_string().c_str(),
component->get_variable_name().c_str());
1257 std::string command =
"get " +
component->get_variable_name_to_send();
1278 if (nextion_queue ==
nullptr) {
1279 ESP_LOGW(TAG,
"Queue alloc failed");
1298 size_t buffer_to_send =
component->get_wave_buffer_size() < 255 ?
component->get_wave_buffer_size()
1302 buf_append_printf(command,
sizeof(command), 0,
"addt %u,%u,%zu",
component->get_component_id(),
1303 component->get_wave_channel_id(), buffer_to_send);
void feed_wdt(uint32_t time=0)
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
An STL allocator that uses SPI or internal RAM.
uint8_t get_spacing() const
Get current command spacing.
void mark_sent()
Mark a command as sent, updating the timing.
std::string get_variable_name()
void set_variable_name(const std::string &variable_name, const std::string &variable_name_to_send="")
void add_setup_state_callback(std::function< void()> &&callback)
Add a callback to be notified when the nextion completes its initialize setup.
std::vector< NextionComponentBase * > touch_
std::vector< NextionComponentBase * > switchtype_
void add_buffer_overflow_event_callback(std::function< void()> &&callback)
Add a callback to be notified when the nextion reports a buffer overflow.
std::vector< NextionComponentBase * > binarysensortype_
uint16_t max_q_age_ms_
Maximum age for queue items in ms.
bool send_command_(const std::string &command)
Manually send a raw command to the display and don't wait for an acknowledgement packet.
std::vector< NextionComponentBase * > textsensortype_
CallbackManager< void(uint8_t)> page_callback_
void check_pending_waveform_()
struct esphome::nextion::Nextion::@144 connection_state_
Status flags for Nextion display state management.
void set_wake_up_page(uint8_t wake_up_page=255)
Sets which page Nextion loads when exiting sleep mode.
std::string device_model_
void all_components_send_state_(bool force_update=false)
std::string firmware_version_
void set_nextion_sensor_state(int queue_type, const std::string &name, float state)
Set the nextion sensor state object.
void add_addt_command_to_queue(NextionComponentBase *component) override
Add addt command to the queue.
void add_new_page_callback(std::function< void(uint8_t)> &&callback)
Add a callback to be notified when the nextion changes pages.
uint16_t max_commands_per_loop_
uint16_t startup_override_ms_
Timeout before forcing setup complete.
void process_nextion_commands_()
void add_to_get_queue(NextionComponentBase *component) override
Queue a GET command for a component that expects a response from the Nextion display.
bool send_command_printf(const char *format,...) __attribute__((format(printf
Manually send a raw formatted command to the display.
std::deque< NextionQueue * > nextion_queue_
void set_auto_wake_on_touch(bool auto_wake_on_touch)
Sets if Nextion should auto-wake from sleep when touch press occurs.
bool remove_from_q_(bool report_empty=true)
std::vector< NextionComponentBase * > sensortype_
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)
uint16_t touch_sleep_timeout_
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.
void set_touch_sleep_timeout(uint16_t touch_sleep_timeout=0)
Set the touch sleep timeout of the display using the thsp command.
CallbackManager< void()> setup_callback_
std::string command_data_
optional< float > brightness_
CallbackManager< void()> wake_callback_
void add_sleep_state_callback(std::function< void()> &&callback)
Add a callback to be notified of sleep state changes.
bool is_updating() override
Check if the TFT update process is currently running.
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag)
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.
std::string serial_number_
CallbackManager< void()> sleep_callback_
bool void add_no_result_to_queue_with_command_(const std::string &variable_name, const std::string &command)
void reset_(bool reset_nextion=true)
void update_all_components()
void process_pending_in_queue_()
Process any commands in the queue that are pending due to command spacing.
void add_no_result_to_queue_(const std::string &variable_name)
Add a command to the Nextion queue that expects no response.
CallbackManager< void(uint8_t, uint8_t, bool)> touch_callback_
void print_queue_members_()
void dump_config() override
NextionCommandPacer command_pacer_
void set_nextion_text_state(const std::string &name, const std::string &state)
std::deque< NextionQueue * > waveform_queue_
bool add_no_result_to_queue_with_ignore_sleep_printf_(const std::string &variable_name, const char *format,...) __attribute__((format(printf
uint8_t is_connected_
Connection established with Nextion display.
void add_wake_state_callback(std::function< void()> &&callback)
Add a callback to be notified of wake state changes.
CallbackManager< void()> buffer_overflow_callback_
void set_writer(const nextion_writer_t &writer)
void add_no_result_to_queue_with_pending_command_(const std::string &variable_name, const std::string &command)
Add a command to the Nextion queue with a pending command for retry.
void add_no_result_to_queue_with_set(NextionComponentBase *component, int32_t state_value) override
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.
void update_components_by_prefix(const std::string &prefix)
uint32_t tft_upload_watchdog_timeout_
WDT timeout in ms (0 = no adjustment)
void set_backlight_brightness(float brightness)
Set the brightness of the backlight.
NextionComponentBase * component
std::string pending_command
optional< std::array< uint8_t, N > > read_array()
void write_str(const char *str)
bool read_byte(uint8_t *data)
void write_array(const uint8_t *data, size_t len)
const Component * component
Providing packet encoding functions for exchanging data with a remote host.
const char int const __FlashStringHelper * format
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
size_t size_t const char va_start(args, fmt)
void HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.