3#include "soc/soc_caps.h"
4#include <driver/uart.h>
15#include <esp_netif_ppp.h>
24using esp_modem::command_result;
25using esp_modem::create_uart_dte;
27using esp_modem::modem_mode;
32static constexpr int HP_UART_COUNT = SOC_UART_HP_NUM;
34static constexpr int HP_UART_COUNT = UART_NUM_MAX;
39static constexpr uint32_t WAIT_IP_TIMEOUT_MS = 50000;
40static constexpr uint32_t PROBE_TIMEOUT_MS = 100;
42static constexpr uint32_t PROBE_RETRY_DELAY_MS = 5000;
43static constexpr uint32_t PROBE_RETRY_MAX_MS = 60000;
45static constexpr uint32_t SYNC_ACK_TIMEOUT_MS = 5000;
47static constexpr uint32_t TASK_STACK_SIZE = 5120;
48#ifdef USE_MODEM_PIN_CODE
50static constexpr uint32_t PIN_TIMEOUT_MS = 5000;
51static constexpr uint32_t PIN_UNLOCK_WAIT_MS = 10000;
53static constexpr uint8_t PIN_MAX_UNCONFIRMED_SENDS = 2;
56static constexpr uint32_t ATTACH_POLL_MS = 4000;
57static constexpr uint8_t ATTACH_DIAG_EVERY = 4;
58static constexpr int RADIO_STATE_RF_OFF = 4;
59static constexpr uint8_t UART_EVENT_QUEUE_SIZE = 10;
60static constexpr uint32_t BAUD_PREF_HASH = 76007670UL;
61static constexpr uint32_t PIN_PREF_HASH = 76007671UL;
62static constexpr int FALLBACK_BAUD_RATE = 115200;
65PROGMEM_STRING_TABLE(ModemStateStrings,
"DISABLED",
"ENABLING",
"SYNCED",
"CONNECTING",
"WAIT_IP",
"CONNECTED",
66 "DISCONNECTING",
"UNKNOWN");
68 return ModemStateStrings::get_log_str(
static_cast<uint8_t
>(
state), ModemStateStrings::LAST_INDEX);
73 "init_at command failed",
"SIM not ready",
"SIM locked",
"SIM PIN not sent; check pin_code",
74 "PIN record not saved",
"APN or radio setup failed",
"No network attachment",
"PPP link failed",
75 "Modem teardown failed");
79static const LogString *result_to_str(command_result result) {
80 return CommandResultStrings::get_log_str(
static_cast<uint8_t
>(result), CommandResultStrings::LAST_INDEX);
85 : tx_pin_(tx_pin), rx_pin_(rx_pin), model_(model), dce_factory_(factory), apn_(apn) {
90 ESP_LOGI(TAG,
"Setting modem target state to CONNECTED");
101 ESP_LOGI(TAG,
"Setting modem target state to DISABLED");
126 ESP_LOGE(TAG,
"Modem was not able to connect (timeout), rebooting");
138 esp_netif_ip_info_t ip;
158 this->
pending_.fetch_or(pending, std::memory_order_release);
168 if (this->
fault_.load(std::memory_order_relaxed) != fault) {
169 this->
fault_.store(fault, std::memory_order_relaxed);
182 if (this->
config_fault_.load(std::memory_order_relaxed) == fault) {
190#ifdef USE_MODEM_PIN_CODE
203 const LogString *
message = ModemFaultStrings::get_log_str(
static_cast<uint8_t
>(fault), ModemFaultStrings::LAST_INDEX);
216 const uint32_t pending = this->
pending_.exchange(0, std::memory_order_acquire);
220 const bool disconnect_first =
222 if (disconnect_first) {
227 this->
sync_acked_.store(1, std::memory_order_release);
249 ESP_LOGW(TAG,
"Failed to save the baud rate");
251#ifdef USE_MODEM_PIN_CODE
257 ESP_LOGE(TAG,
"Failed to save the PIN record");
269 if (this->
urc_pending_.load(std::memory_order_acquire)) {
275 if (this->
pending_.load(std::memory_order_acquire) == 0) {
283#ifdef USE_MODEM_PIN_CODE
287 ESP_LOGD(TAG,
"No PIN record stored");
294 ESP_LOGW(TAG,
"Failed to clear the PIN record");
302 if (pin_pref.load(&record) && record.hash != 0) {
304 if (!pin_pref.save(&record)) {
305 ESP_LOGW(TAG,
"Failed to clear the PIN record");
313 for (
int p = HP_UART_COUNT - 1; p > UART_NUM_0; p--) {
314 if (!uart_is_driver_installed(
static_cast<uart_port_t
>(p))) {
320 this->
mark_failed(LOG_STR(
"No free UART port for modem"));
324 esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
325 this->
ppp_netif_ = esp_netif_new(&netif_ppp_config);
327 this->
fail_setup_(LOG_STR(
"PPP netif creation failed"));
331 auto ip_event = [](
void *arg, esp_event_base_t, int32_t
event_id,
void *event_data) {
332 const bool got_ip =
event_id == IP_EVENT_PPP_GOT_IP;
333 if (!got_ip &&
event_id != IP_EVENT_PPP_LOST_IP) {
337 ESP_LOGD(TAG,
"PPP IP event: Got IP " IPSTR, IP2STR(&
static_cast<ip_event_got_ip_t *
>(event_data)->ip_info.ip));
339 ESP_LOGD(TAG,
"PPP IP event: Lost IP");
342 self->
got_ip_.store(got_ip, std::memory_order_release);
347 auto ppp_status = [](
void *arg, esp_event_base_t, int32_t
event_id,
void *) {
349 ESP_LOGW(TAG,
"PPP error %d",
static_cast<int>(
event_id));
352 self->got_ip_.store(0, std::memory_order_release);
356 if (esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, ip_event,
this) != ESP_OK ||
357 esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, ppp_status,
this) != ESP_OK) {
358 this->
fail_setup_(LOG_STR(
"Event handler register failed"));
363 esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
368 dte_config.uart_config.event_queue_size = UART_EVENT_QUEUE_SIZE;
369 dte_config.uart_config.port_num =
static_cast<uart_port_t
>(this->
uart_port_);
373 if (start_baud != 0) {
374 dte_config.uart_config.baud_rate = start_baud;
379 dte_config.uart_config.flow_control = ESP_MODEM_FLOW_CONTROL_HW;
383 this->
dte_ = create_uart_dte(&dte_config);
384 esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(this->
apn_);
389 this->
fail_setup_(LOG_STR(
"Modem DTE/DCE creation failed"));
395 invert |= UART_SIGNAL_TXD_INV;
398 invert |= UART_SIGNAL_RXD_INV;
402 invert |= UART_SIGNAL_RTS_INV;
405 invert |= UART_SIGNAL_CTS_INV;
408 if (invert != 0 && uart_set_line_inverse(
static_cast<uart_port_t
>(this->
uart_port_), invert) != ESP_OK) {
409 this->
fail_setup_(LOG_STR(
"UART line inversion failed"));
415 this->
dce_->set_enhanced_urc([
this](
const DTE::UrcBufferInfo &buffer_info) {
418 if (buffer_info.is_command_active) {
420 return DTE::UrcConsumeInfo{DTE::UrcConsumeResult::CONSUME_NONE, 0};
422 bool dropped =
false;
423 for (
size_t i = 0; i < buffer_info.new_data_size; i++) {
424 const uint8_t c = buffer_info.new_data_start[i];
425 if (this->
urc_pending_.load(std::memory_order_acquire)) {
427 dropped |= c !=
'\r' && c !=
'\n';
432 if (line !=
nullptr && line[0] !=
'\0') {
439 ESP_LOGW(TAG,
"URC dropped; the previous one is not published yet");
441 return DTE::UrcConsumeInfo{DTE::UrcConsumeResult::CONSUME_ALL, 0};
445 this->
fail_setup_(LOG_STR(
"Task creation failed"));
450#ifdef USE_MODEM_PIN_CODE
451 const char *pin_code = LOG_STR_LITERAL(
"Yes (not shown)");
453 const char *pin_code = LOG_STR_LITERAL(
"No");
464 " TX buffer size: %u\n"
465 " RX buffer size: %u\n"
466 " DTE buffer size: %u\n"
467 " Reboot timeout: %" PRIu32
" ms\n"
470 static_cast<int>(this->uart_port_), this->current_baud_rate_, this->tx_buffer_size_,
471 this->rx_buffer_size_, this->dte_buffer_size_, this->timeout_, YESNO(this->
is_enabled()));
479#ifdef USE_MODEM_SEND_AT
481 if (this->
at_pending_.load(std::memory_order_acquire)) {
483 this->
at_pending_.store(0, std::memory_order_release);
490 ulTaskNotifyTake(pdTRUE, parked ? portMAX_DELAY : pdMS_TO_TICKS(this->
step_delay_ms_));
495 const uint8_t backoff = this->
probe_backoff_.load(std::memory_order_relaxed);
496 const uint32_t delay_ms = std::min(PROBE_RETRY_DELAY_MS << backoff, PROBE_RETRY_MAX_MS);
497 if (delay_ms < PROBE_RETRY_MAX_MS) {
498 this->
probe_backoff_.store(backoff + 1, std::memory_order_relaxed);
521#ifdef USE_MODEM_PIN_CODE
537 if (this->
got_ip_.load(std::memory_order_acquire)) {
540 ESP_LOGW(TAG,
"Lost IP; PPP error %u", this->
ppp_error_.load(std::memory_order_acquire));
541 this->
ppp_error_.store(0, std::memory_order_release);
552 if (!this->
dce_->set_mode(modem_mode::AUTODETECT)) {
554 this->
dce_->set_mode(modem_mode::UNDEF);
557 ESP_LOGD(TAG,
"Autodetect mode: %d",
static_cast<int>(
mode));
562 case modem_mode::CMUX_MANUAL_MODE:
564 ESP_LOGD(TAG,
"Modem warm reboot. Exiting CMUX");
565 if (!this->
dce_->set_mode(modem_mode::CMUX_MANUAL_EXIT)) {
566 ESP_LOGW(TAG,
"Failed to exit CMUX");
570 case modem_mode::UNDEF: {
577 bool rejected =
false;
578 for (
size_t i = 0; i != std::size(bauds) && !found; i++) {
579 const int baud = bauds[i];
580 if (baud == 0 || baud == detected || std::find(bauds, bauds + i, baud) != bauds + i) {
583 if (uart_set_baudrate(
static_cast<uart_port_t
>(this->
uart_port_), baud) != ESP_OK) {
584 ESP_LOGW(TAG,
"UART rejected baud rate %d", baud);
592 found = this->
dce_->at(
"AT", output, PROBE_TIMEOUT_MS) == command_result::OK;
599 if (!probed && !rejected) {
608 case modem_mode::COMMAND_MODE:
612 case modem_mode::DATA_MODE:
614 ESP_LOGW(TAG,
"Exiting DATA_MODE");
615 if (!this->
dce_->set_mode(modem_mode::COMMAND_MODE)) {
616 ESP_LOGW(TAG,
"Failed to leave data mode");
621 ESP_LOGW(TAG,
"Modem in unexpected mode %d. Switching to COMMAND mode.",
static_cast<int>(
mode));
622 if (!this->
dce_->set_mode(modem_mode::COMMAND_MODE)) {
623 ESP_LOGW(TAG,
"Failed to switch to command mode");
625 this->
dce_->set_mode(modem_mode::UNDEF);
629 if (exited && this->
dce_->sync() != command_result::OK) {
632 ESP_LOGW(TAG,
"Modem did not return to command mode");
638 if (this->
dce_->set_echo(
false) != command_result::OK) {
639 ESP_LOGW(TAG,
"Failed to disable command echo");
643 if (this->
dce_->get_radio_state(radio_state) != command_result::OK) {
644 ESP_LOGW(TAG,
"Failed to read the radio state; skipping the radio off step");
645 }
else if (radio_state != RADIO_STATE_RF_OFF) {
648 if (this->
dce_->set_radio_state(RADIO_STATE_RF_OFF) != command_result::OK) {
649 ESP_LOGW(TAG,
"Failed to turn the radio off");
655 if (this->
dce_->set_baud(this->baud_rate_) == command_result::OK) {
657 if (uart_set_baudrate(
static_cast<uart_port_t
>(this->
uart_port_), this->
baud_rate_) != ESP_OK) {
658 ESP_LOGE(TAG,
"UART rejected baud rate %d", this->
baud_rate_);
663 if (this->
dce_->sync() != command_result::OK) {
664 ESP_LOGE(TAG,
"Failed to sync modem at baud rate %d.", this->
baud_rate_);
686 if (this->
rts_pin_ !=
nullptr && this->
dce_->set_flow_control(2, 2) != command_result::OK) {
687 ESP_LOGW(TAG,
"Modem refused hardware flow control; UART overruns are possible");
713 if (this->
dce_->sync() != command_result::OK) {
714 ESP_LOGW(TAG,
"Modem not synced during network init");
737 esp_modem::PdpContext pdp(this->
apn_);
738 if (this->
dce_->set_pdp_context(pdp) != command_result::OK) {
739 ESP_LOGW(TAG,
"Failed to set the APN");
743 if (this->
dce_->set_radio_state(1) != command_result::OK) {
744 ESP_LOGW(TAG,
"Failed to turn the radio on");
754 if (this->
dce_->set_network_attachment_state(1) != command_result::OK) {
755 ESP_LOGD(TAG,
"Network attachment request refused");
761 if (this->
dce_->get_network_attachment_state(attached) != command_result::OK) {
762 ESP_LOGW(TAG,
"Failed to read the network attachment state");
770 int rssi = 99, ber = 99, registration = -1,
mode = -1;
771 this->
dce_->get_network_registration_state(registration);
772 this->
dce_->get_signal_quality(rssi, ber);
773 this->
dce_->get_network_system_mode(
mode);
774 ESP_LOGW(TAG,
"Modem not attached yet: registration %d, network type %d, CSQ %d, BER %d", registration,
mode,
782 ESP_LOGI(TAG,
"Modem initialized and ready, starting PPP");
784 this->
got_ip_.store(0, std::memory_order_release);
785 this->
ppp_error_.store(0, std::memory_order_release);
786 if (!this->
dce_->set_mode(modem_mode::CMUX_MODE)) {
787 ESP_LOGE(TAG,
"Failed to enter PPP. Resetting modem.");
796 if (this->
got_ip_.load(std::memory_order_acquire)) {
801 if (this->
ppp_error_.load(std::memory_order_acquire) != 0) {
802 this->
ppp_error_.store(0, std::memory_order_release);
807 if (elapsed < WAIT_IP_TIMEOUT_MS) {
811 ESP_LOGE(TAG,
"Unable to get IP address");
823 if (this->
dce_->get_mode() != modem_mode::COMMAND_MODE && !this->dce_->set_mode(modem_mode::COMMAND_MODE)) {
825 ESP_LOGW(TAG,
"Failed to leave data mode");
831 if (this->
dce_->set_radio_state(reconnect ? RADIO_STATE_RF_OFF : 0) == command_result::OK) {
832 ESP_LOGI(TAG,
"Radio off");
834 ESP_LOGW(TAG,
"Radio off failed");
842 if (next_state ==
state) {
846 ESP_LOGD(TAG,
"State change: %s -> %s", LOG_STR_ARG(state_to_str(
state)), LOG_STR_ARG(state_to_str(next_state)));
852 this->
sync_acked_.store(0, std::memory_order_release);
855 while (this->
sync_acked_.load(std::memory_order_acquire) == 0) {
857 if (elapsed >= SYNC_ACK_TIMEOUT_MS) {
858 ESP_LOGW(TAG,
"on_sync did not run within %u ms; continuing",
static_cast<unsigned>(SYNC_ACK_TIMEOUT_MS));
861 ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(SYNC_ACK_TIMEOUT_MS - elapsed));
867 this->
got_ip_.store(0, std::memory_order_release);
878 ESP_LOGW(TAG,
"Modem not responding at %d baud. Check power, PWRKEY and TX/RX wiring.", baud);
882#ifdef USE_MODEM_SEND_AT
887 ESP_LOGW(TAG,
"Modem not ready, cannot send AT command: %s", cmd);
890 if (this->
at_pending_.load(std::memory_order_acquire)) {
891 ESP_LOGW(TAG,
"AT command '%s' dropped; the previous one is not sent yet", cmd);
894 const size_t len = strlen(cmd);
896 ESP_LOGW(TAG,
"AT command longer than %u bytes dropped",
static_cast<unsigned>(
sizeof(this->
at_command_) - 1));
901 this->
at_pending_.store(1, std::memory_order_release);
910 const command_result result = this->
dce_->at(cmd, output, timeout);
911 if (result == command_result::OK) {
912 ESP_LOGI(TAG,
"AT '%s' -> OK: %s", cmd, output.c_str());
914 ESP_LOGW(TAG,
"AT '%s' -> %s: %s", cmd, LOG_STR_ARG(result_to_str(result)), output.c_str());
921#ifdef USE_MODEM_PIN_CODE
930 ESP_LOGD(TAG,
"SIM status not readable yet: %s", output.c_str());
935 const char *found = strstr(output.c_str(),
"+CPIN:");
936 if (found !=
nullptr) {
937 found +=
sizeof(
"+CPIN:") - 1;
938 while (*found ==
' ') {
944 ESP_LOGD(TAG,
"SIM status not reported yet: %s", output.c_str());
948 ESP_LOGD(TAG,
"SIM: %s",
status.c_str());
951 if (
status.starts_with(
"READY")) {
952#ifdef USE_MODEM_PIN_CODE
961 if (strstr(
status.c_str(),
"PUK") !=
nullptr) {
962 ESP_LOGE(TAG,
"SIM is PUK locked; unlock it in a phone");
968 if (strstr(
status.c_str(),
"PIN") !=
nullptr) {
969 ESP_LOGE(TAG,
"SIM lock %s needs a credential pin_code cannot provide",
status.c_str());
973 ESP_LOGW(TAG,
"SIM not ready: %s",
status.c_str());
977#ifdef USE_MODEM_PIN_CODE
980 ESP_LOGE(TAG,
"SIM requires a PIN but pin_code is not set");
986#ifdef USE_MODEM_PIN_CODE
998 ESP_LOGE(TAG,
"The SIM never confirmed this pin_code; not sending it again");
1010 ESP_LOGE(TAG,
"The PIN attempt could not be recorded; not sending it");
1018 std::string cmd =
"AT+CPIN=\"";
1021 if (this->
at_(cmd.c_str(), PIN_TIMEOUT_MS) == command_result::FAIL) {
1023 ESP_LOGE(TAG,
"The SIM refused the PIN; check pin_code");
1037 ESP_LOGE(TAG,
"SIM still locked after sending the PIN; check the SIM");
1051 esp_netif_ip_info_t ip;
1052 if (!this->
got_ip_.load(std::memory_order_acquire) || esp_netif_get_ip_info(this->
ppp_netif_, &ip) != ESP_OK) {
1053 ESP_LOGCONFIG(TAG,
" Connection: not connected");
1056 auto dns_str = [
this](esp_netif_dns_type_t
type,
char *buf) ->
const char * {
1057 esp_netif_dns_info_t dns{};
1058 if (esp_netif_get_dns_info(this->
ppp_netif_, type, &dns) != ESP_OK) {
1059 return LOG_STR_LITERAL(
"unavailable");
1063 char ip_buf[network::IP_ADDRESS_BUFFER_SIZE];
1064 char netmask_buf[network::IP_ADDRESS_BUFFER_SIZE];
1065 char gw_buf[network::IP_ADDRESS_BUFFER_SIZE];
1066 char dns_main_buf[network::IP_ADDRESS_BUFFER_SIZE];
1067 char dns_backup_buf[network::IP_ADDRESS_BUFFER_SIZE];
1078 dns_str(ESP_NETIF_DNS_MAIN, dns_main_buf), dns_str(ESP_NETIF_DNS_BACKUP, dns_backup_buf));
BedjetMode mode
BedJet operating mode.
const StringRef & get_name() const
Get the name of this Application set by pre_setup().
void mark_failed()
Mark this component as failed.
void status_set_warning()
void status_clear_error()
void enable_loop_soon_any_context()
Thread and ISR-safe version of enable_loop() that can be called from any context.
void disable_loop()
Disable this component's loop.
void status_clear_warning()
char * feed(uint8_t c)
Feed one byte; returns the completed line (empty lines included), valid until the next call,...
void reset()
Forget the partial line and start a new one with the next byte.
void log_if_overflowed(const char *tag) const
Log the shared "line dropped" warning when the last feed() overflowed.
void discard_line()
Drop everything up to and including the next terminator.
bool is_created() const
Check if the task has been created and not yet destroyed.
TaskHandle_t get_handle() const
Get the FreeRTOS task handle.
bool create(TaskFunction_t fn, const char *name, uint32_t stack_size, void *param, UBaseType_t priority, bool use_psram, BaseType_t core_id=tskNO_AFFINITY)
Allocate the TCB (always internal RAM) and the stack, then create the task.
StringRef is a reference to a string owned by something else.
constexpr const char * c_str() const
bool starts_with(const StringRef &prefix) const
True if the view begins with the given prefix (std::string::starts_with-like)
InternalGPIOPin * rts_pin_
std::shared_ptr< esp_modem::DTE > dte_
std::atomic< ModemState > component_state_
std::atomic< uint8_t > ppp_error_
bool send_at(const char *cmd, uint32_t timeout=COMMAND_TIMEOUT_MS)
Queue an AT command for the modem task, which sends it at its next pass and logs the result and respo...
char at_command_[AT_COMMAND_SIZE]
network::IPAddresses get_ip_addresses()
InternalGPIOPin * rx_pin_
bool is_connected() const
void hand_over_(uint32_t pending)
std::atomic< ModemFault > fault_
uint16_t dte_buffer_size_
std::atomic< ModemFault > config_fault_
@ PENDING_CONNECT_TIMEOUT
ModemState handle_state_connecting_()
ModemComponent(InternalGPIOPin *tx_pin, InternalGPIOPin *rx_pin, const char *model, DceFactory factory, const char *apn)
void cancel_connect_timeout_()
InternalGPIOPin * cts_pin_
InternalGPIOPin * tx_pin_
ConnectStep connect_step_
LineReader< URC_LINE_SIZE > urc_reader_
const char *const * init_at_commands_
uint32_t next_probe_delay_()
Pause the task before the next pass, then go to state.
ModemState handle_state_wait_ip_()
ESPPreferenceObject pin_pref_
void dump_connect_params_()
std::atomic< uint8_t > at_pending_
std::unique_ptr< esp_modem::DCE > dce_
std::atomic< ModemState > target_state_
std::atomic< uint8_t > urc_pending_
LazyCallbackManager< void(ModemState)> on_state_callback_
bool connect_timeout_armed_
void transition_to_(ModemState next_state)
void set_teardown_fault_()
void clear_config_fault_(ModemFault fault)
static void task_entry(void *arg)
void not_responding_(int baud)
ModemState compute_next_state_()
void arm_connect_timeout_()
std::atomic< uint8_t > got_ip_
void set_fault_(ModemFault fault)
ModemState handle_state_disconnecting_()
void dump_config() override
uint32_t state_started_ms_
std::atomic< uint8_t > sync_acked_
ModemState handle_state_enabling_()
std::atomic< PinSave > pin_save_state_
void fail_setup_(const LogString *reason)
std::atomic< uint32_t > pending_
ModemState handle_state_synced_()
esp_modem::command_result at_(const char *cmd, uint32_t timeout=COMMAND_TIMEOUT_MS)
Send an AT command from the task and log the result; blocks for up to the timeout.
ESPPreferenceObject pref_
ModemState retry_(ModemState state, uint32_t delay_ms=RETRY_DELAY_MS)
text_sensor::TextSensor * urc_text_sensor_
std::atomic< uint8_t > probe_backoff_
static constexpr uint32_t COMMAND_TIMEOUT_MS
void publish_state(const std::string &state)
const LogString * message
@ MODEM_FAULT_PIN_NOT_SENT
@ MODEM_FAULT_NOT_ATTACHED
@ MODEM_FAULT_NO_RESPONSE
@ MODEM_FAULT_SIM_NOT_READY
@ MODEM_STATE_DISCONNECTING
ModemComponent * global_modem_component
PROGMEM_STRING_TABLE(ModemStateStrings, "DISABLED", "ENABLING", "SYNCED", "CONNECTING", "WAIT_IP", "CONNECTED", "DISCONNECTING", "UNKNOWN")
@ CONNECT_STEP_ATTACH_REQUESTED
std::unique_ptr< esp_modem::DCE >(*)(const esp_modem::dce_config *, std::shared_ptr< esp_modem::DTE >, esp_netif_t *) DceFactory
ESPHOME_LOG_TAG(TAG, "modem")
std::array< IPAddress, 5 > IPAddresses
void fill_ip6_addresses(esp_netif_t *netif, IPAddresses &addresses)
Copies the IPv6 addresses of an esp_netif into addresses[1..], warning once when some do not fit.
ESPPreferences * global_preferences
uint32_t fnv1_hash(const char *str)
Calculate a FNV-1 hash of str.
void HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.
ESPPreferenceObject make_preference(size_t, uint32_t, bool)
bool sync()
Commit pending writes to flash.
char * str_to(char *buf) const