mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	refactor
This commit is contained in:
		| @@ -51,15 +51,82 @@ ModemComponent::ModemComponent() { | ||||
|   global_modem_component = this; | ||||
| } | ||||
|  | ||||
| void ModemComponent::dump_config() { this->dump_connect_params_(); } | ||||
| std::string ModemComponent::send_at(const std::string &cmd) { | ||||
|   std::string result; | ||||
|   command_result status; | ||||
|   ESP_LOGV(TAG, "Sending command: %s", cmd.c_str()); | ||||
|   status = this->dce->at(cmd, result, this->command_delay_ * 5); | ||||
|   ESP_LOGV(TAG, "Result for command %s: %s (status %s)", cmd.c_str(), result.c_str(), | ||||
|            command_result_to_string(status).c_str()); | ||||
|   if (status != esp_modem::command_result::OK) { | ||||
|     result = "ERROR"; | ||||
|   } | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| float ModemComponent::get_setup_priority() const { return setup_priority::WIFI + 1; }  // just before WIFI | ||||
| bool ModemComponent::get_imei(std::string &result) { | ||||
|   // wrapper around this->dce->get_imei() that check that the result is valid | ||||
|   // (so it can be used to check if the modem is responding correctly (a simple 'AT' cmd is sometime not enough)) | ||||
|   command_result status; | ||||
|   status = this->dce->get_imei(result); | ||||
|   bool success = true; | ||||
|  | ||||
| bool ModemComponent::can_proceed() { | ||||
|   if (!this->enabled_) { | ||||
|   if (status == command_result::OK && result.length() == 15) { | ||||
|     for (char c : result) { | ||||
|       if (!isdigit(static_cast<unsigned char>(c))) { | ||||
|         success = false; | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } else { | ||||
|     success = false; | ||||
|   } | ||||
|  | ||||
|   if (!success) { | ||||
|     result = "UNAVAILABLE"; | ||||
|   } | ||||
|   return success; | ||||
| } | ||||
|  | ||||
| bool ModemComponent::get_power_status() { | ||||
| #ifdef USE_MODEM_STATUS | ||||
|   // This code is not fully checked. The status pin seems to be flickering on Lilygo T-SIM7600 | ||||
|   return this->status_pin_->digital_read(); | ||||
| #else | ||||
|   if (!this->cmux_ && this->internal_state_.connected) { | ||||
|     // Data mode, connected:  assume power is OK | ||||
|     return true; | ||||
|   } | ||||
|   return this->is_connected(); | ||||
|   return this->modem_ready(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool ModemComponent::modem_ready() { | ||||
|   // check if the modem is ready to answer AT commands | ||||
|   std::string imei; | ||||
|   if (this->dce && this->get_imei(imei)) { | ||||
|     // we are sure that the modem is on | ||||
|     this->internal_state_.powered_on = true; | ||||
|     return true; | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| void ModemComponent::enable() { | ||||
|   ESP_LOGD(TAG, "Enabling modem"); | ||||
|   if (this->component_state_ == ModemComponentState::DISABLED) { | ||||
|     this->component_state_ = ModemComponentState::DISCONNECTED; | ||||
|   } | ||||
|   this->internal_state_.start = true; | ||||
|   this->internal_state_.enabled = true; | ||||
| } | ||||
|  | ||||
| void ModemComponent::disable() { | ||||
|   ESP_LOGD(TAG, "Disabling modem"); | ||||
|   this->internal_state_.enabled = false; | ||||
|   if (this->component_state_ != ModemComponentState::CONNECTED) { | ||||
|     this->component_state_ = ModemComponentState::DISCONNECTED; | ||||
|   } | ||||
| } | ||||
|  | ||||
| network::IPAddresses ModemComponent::get_ip_addresses() { | ||||
| @@ -78,9 +145,80 @@ std::string ModemComponent::get_use_address() const { | ||||
|   return this->use_address_; | ||||
| } | ||||
|  | ||||
| void ModemComponent::set_use_address(const std::string &use_address) { this->use_address_ = use_address; } | ||||
| void ModemComponent::dump_dce_status() { | ||||
|   bool watchdog = false; | ||||
|   if (!this->watchdog_) { | ||||
|     this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); | ||||
|     watchdog = true; | ||||
|   } | ||||
|  | ||||
| bool ModemComponent::is_connected() { return this->state_ == ModemComponentState::CONNECTED; } | ||||
|   if (this->internal_state_.connected && !this->cmux_) { | ||||
|     if (!this->dce->set_mode(modem_mode::COMMAND_MODE)) { | ||||
|       ESP_LOGW(TAG, "Unable to enter temporary command mode"); | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
|   if (this->internal_state_.modem_synced && this->modem_ready()) { | ||||
|     ESP_LOGCONFIG(TAG, "Modem status:"); | ||||
|     command_result err; | ||||
|     std::string result; | ||||
|     // err = this->dce->get_module_name(result); | ||||
|     // if (err != command_result::OK) { | ||||
|     //   result = "command " + command_result_to_string(err); | ||||
|     // } | ||||
|     // ESP_LOGCONFIG(TAG, "  Module name        : %s", result.c_str()); | ||||
|     int rssi; | ||||
|     int ber; | ||||
|     err = this->dce->get_signal_quality(rssi, ber); | ||||
|     if (err != command_result::OK) { | ||||
|       result = "command " + command_result_to_string(err); | ||||
|     } else { | ||||
|       float ber_f; | ||||
|       if (ber != 99) { | ||||
|         ber_f = float(ber); | ||||
|       } else | ||||
|         ber_f = {}; | ||||
|       std::ostringstream oss; | ||||
|       oss << "rssi " << rssi << "(" << (rssi * 100) / 31 << "%), ber " << ber << "(" << (ber_f * 100) / 7 << "%)"; | ||||
|       result = oss.str(); | ||||
|     } | ||||
|     ESP_LOGCONFIG(TAG, "  Signal quality     : %s", result.c_str()); | ||||
|  | ||||
|     // int network_attachment_state; | ||||
|     // err = this->dce->get_network_attachment_state(network_attachment_state); | ||||
|     // if (err == command_result::OK) { | ||||
|     //   result = network_attachment_state ? "Yes" : "No"; | ||||
|     // } else { | ||||
|     //   result = "command " + command_result_to_string(err); | ||||
|     // } | ||||
|     // ESP_LOGCONFIG(TAG, "  Attached to network: %s", result.c_str()); | ||||
|     // | ||||
|     // err = this->dce->get_operator_name(result); | ||||
|     // if (err != command_result::OK) { | ||||
|     //   result = "command " + command_result_to_string(err); | ||||
|     // } | ||||
|     // ESP_LOGCONFIG(TAG, "  Operator           : %s", result.c_str()); | ||||
|     // | ||||
|     // int act; | ||||
|     // err = this->dce->get_network_system_mode(act); | ||||
|     // if (err != command_result::OK) { | ||||
|     //   result = "command " + command_result_to_string(err); | ||||
|     // } else { | ||||
|     //   std::ostringstream oss; | ||||
|     //   oss << act; | ||||
|     //   result = oss.str(); | ||||
|     // } | ||||
|     // ESP_LOGCONFIG(TAG, "  Access technology   : %s", result.c_str()); | ||||
|   } | ||||
|   if (this->internal_state_.connected && !this->cmux_) { | ||||
|     if (this->dce->resume_data_mode() != command_result::OK) { | ||||
|       ESP_LOGW(TAG, "Unable to resume data mode. Reconnecting..."); | ||||
|       this->internal_state_.connected = false; | ||||
|     } | ||||
|   } | ||||
|   if (watchdog) | ||||
|     this->watchdog_.reset(); | ||||
| } | ||||
|  | ||||
| void ModemComponent::setup() { | ||||
|   ESP_LOGI(TAG, "Setting up Modem..."); | ||||
| @@ -88,14 +226,14 @@ void ModemComponent::setup() { | ||||
|   if (this->power_pin_) { | ||||
|     this->power_pin_->setup(); | ||||
|     // as we have a power pin, we assume that the power is off | ||||
|     this->powered_on_ = false; | ||||
|     this->internal_state_.powered_on = false; | ||||
|  | ||||
|     if (this->enabled_) { | ||||
|     if (this->internal_state_.enabled) { | ||||
|       this->poweron_(); | ||||
|     } | ||||
|   } else { | ||||
|     // no status pin, we assume that the power is on | ||||
|     this->powered_on_ = true; | ||||
|     this->internal_state_.powered_on = true; | ||||
|   } | ||||
|  | ||||
|   if (this->status_pin_) { | ||||
| @@ -116,7 +254,7 @@ void ModemComponent::setup() { | ||||
|   } else { | ||||
|     ESP_LOGCONFIG(TAG, "  Status pin: Not defined"); | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  Enabled   : %s", this->enabled_ ? "Yes" : "No"); | ||||
|   ESP_LOGCONFIG(TAG, "  Enabled   : %s", this->internal_state_.enabled ? "Yes" : "No"); | ||||
|   ESP_LOGCONFIG(TAG, "  Use CMUX  : %s", this->cmux_ ? "Yes" : "No"); | ||||
|  | ||||
|   ESP_LOGV(TAG, "PPP netif setup"); | ||||
| @@ -147,6 +285,232 @@ void ModemComponent::setup() { | ||||
|   ESP_LOGV(TAG, "Setup finished"); | ||||
| } | ||||
|  | ||||
| void ModemComponent::loop() { | ||||
|   static ModemComponentState last_state = this->component_state_; | ||||
|   static uint32_t next_loop_millis = millis(); | ||||
|   static bool connecting = false; | ||||
|   static bool disconnecting = false; | ||||
|   static uint8_t network_attach_retry = 10; | ||||
|   static uint8_t ip_lost_retries = 10; | ||||
|  | ||||
|   if ((millis() < next_loop_millis)) { | ||||
|     // some commands need some delay | ||||
|     yield(); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
| #ifdef USE_MODEM_POWER | ||||
|   if (this->internal_state_.power_transition) { | ||||
|     if (!this->watchdog_) | ||||
|       this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); | ||||
|  | ||||
|     // A power state is used to handle long tonuart/toffuart delay | ||||
|     switch (this->internal_state_.power_state) { | ||||
|       case ModemPowerState::TON: | ||||
|         this->power_pin_->digital_write(false); | ||||
|         delay(USE_MODEM_POWER_TON); | ||||
|         this->power_pin_->digital_write(true); | ||||
|         next_loop_millis = millis() + USE_MODEM_POWER_TONUART;  // delay for next loop | ||||
|         this->internal_state_.power_state = ModemPowerState::TONUART; | ||||
|         ESP_LOGD(TAG, "Will check that the modem is on in %.1fs...", float(USE_MODEM_POWER_TONUART) / 1000); | ||||
|         break; | ||||
|       case ModemPowerState::TONUART: | ||||
|         this->internal_state_.power_transition = false; | ||||
|         if (!this->modem_sync_()) { | ||||
|           ESP_LOGE(TAG, "Unable to power on the modem"); | ||||
|           this->internal_state_.powered_on = false; | ||||
|         } else { | ||||
|           ESP_LOGI(TAG, "Modem powered ON"); | ||||
|           this->internal_state_.powered_on = true; | ||||
|           this->internal_state_.modem_synced = false; | ||||
|           this->watchdog_.reset(); | ||||
|         } | ||||
|         break; | ||||
|       case ModemPowerState::TOFF: | ||||
|         delay(10); | ||||
|         this->power_pin_->digital_write(false); | ||||
|         delay(USE_MODEM_POWER_TOFF); | ||||
|         this->power_pin_->digital_write(true); | ||||
|         this->internal_state_.power_state = ModemPowerState::TOFFUART; | ||||
|         ESP_LOGD(TAG, "Will check that the modem is off in %.1fs...", float(USE_MODEM_POWER_TOFFUART) / 1000); | ||||
|         next_loop_millis = millis() + USE_MODEM_POWER_TOFFUART;  // delay for next loop | ||||
|         break; | ||||
|       case ModemPowerState::TOFFUART: | ||||
|         this->internal_state_.power_transition = false; | ||||
|         if (this->modem_ready()) { | ||||
|           ESP_LOGE(TAG, "Unable to power off the modem"); | ||||
|           this->internal_state_.powered_on = true; | ||||
|         } else { | ||||
|           ESP_LOGI(TAG, "Modem powered OFF"); | ||||
|           this->internal_state_.powered_on = false; | ||||
|           this->internal_state_.modem_synced = false; | ||||
|           this->watchdog_.reset(); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|     yield(); | ||||
|     return; | ||||
|   } | ||||
| #endif  // USE_MODEM_POWER | ||||
|  | ||||
|   switch (this->component_state_) { | ||||
|     case ModemComponentState::NOT_RESPONDING: | ||||
|       if (this->internal_state_.start) { | ||||
|         if (this->modem_ready()) { | ||||
|           ESP_LOGI(TAG, "Modem recovered"); | ||||
|           this->status_clear_warning(); | ||||
|           this->component_state_ = ModemComponentState::DISCONNECTED; | ||||
|         } else { | ||||
|           if (!this->internal_state_.powered_on) { | ||||
|             this->poweron_(); | ||||
|           } else if (this->not_responding_cb_) { | ||||
|             if (!this->not_responding_cb_->is_action_running()) { | ||||
|               ESP_LOGD(TAG, "Calling 'on_not_responding' callback"); | ||||
|               this->not_responding_cb_->trigger(); | ||||
|             } | ||||
|           } else { | ||||
|             ESP_LOGW(TAG, "Modem not responding, and no 'on_not_responding' action defined"); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case ModemComponentState::DISCONNECTED: | ||||
|       if (this->internal_state_.enabled) { | ||||
|         // be sure the modem is on and synced | ||||
|         if (!this->internal_state_.powered_on) { | ||||
|           this->poweron_(); | ||||
|           break; | ||||
|         } else if (!this->internal_state_.modem_synced) { | ||||
|           if (!this->modem_sync_()) { | ||||
|             ESP_LOGE(TAG, "Modem not responding"); | ||||
|             this->component_state_ = ModemComponentState::NOT_RESPONDING; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (this->internal_state_.start) { | ||||
|           // want to connect | ||||
|           if (!connecting) { | ||||
|             // wait for the modem be attached to a network, start ppp, and set connecting=true | ||||
|             if (!this->watchdog_) | ||||
|               this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); | ||||
|             if (is_network_attached_()) { | ||||
|               network_attach_retry = 10; | ||||
|               if (this->start_ppp_()) { | ||||
|                 connecting = true; | ||||
|                 next_loop_millis = millis() + 2000;  // delay for next loop | ||||
|               } | ||||
|             } else { | ||||
|               ESP_LOGD(TAG, "Waiting for the modem to be attached to a network (left retries: %" PRIu8 ")", | ||||
|                        network_attach_retry); | ||||
|               network_attach_retry--; | ||||
|               if (network_attach_retry == 0) { | ||||
|                 ESP_LOGE(TAG, "modem is unable to attach to a network"); | ||||
|                 if (this->power_pin_) { | ||||
|                   this->poweroff_(); | ||||
|                 } else { | ||||
|                   this->component_state_ = ModemComponentState::NOT_RESPONDING; | ||||
|                 } | ||||
|               } | ||||
|               next_loop_millis = millis() + 1000;  // delay to retry | ||||
|             } | ||||
|           } else { | ||||
|             // connecting | ||||
|             if (!this->internal_state_.connected) { | ||||
|               // wait until this->internal_state_.connected set to true by IP_EVENT_PPP_GOT_IP | ||||
|               next_loop_millis = millis() + 1000;  // delay for next loop | ||||
|  | ||||
|               // connecting timeout | ||||
|               if (millis() - this->internal_state_.connect_begin > 15000) { | ||||
|                 ESP_LOGW(TAG, "Connecting via Modem failed! Re-connecting..."); | ||||
|                 // TODO: exit data/cmux without error check | ||||
|                 connecting = false; | ||||
|               } | ||||
|             } else { | ||||
|               connecting = false; | ||||
|               ESP_LOGI(TAG, "Connected via Modem"); | ||||
|               this->component_state_ = ModemComponentState::CONNECTED; | ||||
|  | ||||
|               this->dump_connect_params_(); | ||||
|               this->status_clear_warning(); | ||||
|               this->watchdog_.reset(); | ||||
|             } | ||||
|           } | ||||
|         } else { | ||||
|           this->internal_state_.start = true; | ||||
|         } | ||||
|       } else { | ||||
|         this->component_state_ = ModemComponentState::DISABLED; | ||||
|         this->watchdog_.reset(); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case ModemComponentState::CONNECTED: | ||||
|       if (this->internal_state_.enabled) { | ||||
|         if (!this->internal_state_.connected) { | ||||
|           this->status_set_warning("Connection via Modem lost!"); | ||||
|           this->component_state_ = ModemComponentState::DISCONNECTED; | ||||
|         } | ||||
|         disconnecting = false; | ||||
|       } else { | ||||
|         if (this->internal_state_.connected) { | ||||
|           // connected but disbled, so disconnect | ||||
|           if (!disconnecting) { | ||||
|             disconnecting = true; | ||||
|             ip_lost_retries = 10; | ||||
|             this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); | ||||
|             ESP_LOGD(TAG, "Disconnecting..."); | ||||
|             this->stop_ppp_(); | ||||
|             delay(200);  // NOLINT | ||||
|             ESP_LOGD(TAG, "Disconnected after %.1fmin", float(this->internal_state_.connect_begin) / (1000 * 60)); | ||||
|           } else { | ||||
|             // disconnecting | ||||
|             // Waiting for IP_EVENT_PPP_LOST_IP. | ||||
|             // This can take a long time, so we ckeck the IP addr, and trigger the event manualy if it's null. | ||||
|             esp_netif_ip_info_t ip_info; | ||||
|             esp_netif_get_ip_info(this->ppp_netif_, &ip_info); | ||||
|             if (ip_info.ip.addr == 0) { | ||||
|               // lost IP | ||||
|               esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0); | ||||
|             } else { | ||||
|               ESP_LOGD(TAG, "Waiting for lost IP... (retries %" PRIu8 ")", ip_lost_retries); | ||||
|               ip_lost_retries--; | ||||
|               if (ip_lost_retries == 0) { | ||||
|                 // Something goes wrong, we have still an IP | ||||
|                 ESP_LOGE(TAG, "No IP lost event recieved. Sending one manually"); | ||||
|                 esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0); | ||||
|               } | ||||
|             } | ||||
|             next_loop_millis = millis() + 2000;  // delay for next loop | ||||
|           } | ||||
|         } else {  // if (this->internal_state_.connected) | ||||
|           // ip lost as expected | ||||
|           ESP_LOGI(TAG, "PPPoS disconnected"); | ||||
|           this->component_state_ = ModemComponentState::DISCONNECTED; | ||||
|         } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case ModemComponentState::DISABLED: | ||||
|       if (this->internal_state_.enabled) { | ||||
|         this->component_state_ = ModemComponentState::DISCONNECTED; | ||||
|         ESP_LOGE(TAG, "here"); | ||||
|       } else if (this->internal_state_.powered_on) { | ||||
|         this->poweroff_(); | ||||
|       } | ||||
|       next_loop_millis = millis() + 2000;  // delay for next loop | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   if (this->component_state_ != last_state) { | ||||
|     ESP_LOGV(TAG, "State changed: %s -> %s", state_to_string(last_state).c_str(), | ||||
|              state_to_string(this->component_state_).c_str()); | ||||
|     this->on_state_callback_.call(last_state, this->component_state_); | ||||
|  | ||||
|     last_state = this->component_state_; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void ModemComponent::modem_lazy_init_() { | ||||
|   // destroy previous dte/dce, and recreate them. | ||||
|   // no communication is done with the modem. | ||||
| @@ -239,21 +603,22 @@ bool ModemComponent::modem_sync_() { | ||||
|  | ||||
|     if (!status) { | ||||
|       ESP_LOGW(TAG, "modem not responding after %" PRIu32 "ms.", elapsed_ms); | ||||
|       this->powered_on_ = false; | ||||
|       this->internal_state_.powered_on = false; | ||||
|     } | ||||
|   } | ||||
|   if (status) { | ||||
|     elapsed_ms = millis() - start_ms; | ||||
|     ESP_LOGD(TAG, "Connected to the modem in %" PRIu32 "ms", elapsed_ms); | ||||
|     this->send_init_at_(); | ||||
|  | ||||
|     if (!this->prepare_sim_()) { | ||||
|       // fatal error | ||||
|       this->disable(); | ||||
|       status = false; | ||||
|     } | ||||
|     this->send_init_at_(); | ||||
|   } | ||||
|  | ||||
|   this->modem_synced_ = status; | ||||
|   this->internal_state_.modem_synced = status; | ||||
|  | ||||
|   return status; | ||||
| } | ||||
| @@ -296,19 +661,27 @@ void ModemComponent::send_init_at_() { | ||||
|     } else { | ||||
|       ESP_LOGI(TAG, "'init_at' '%s' result: %s", cmd.c_str(), result.c_str()); | ||||
|     } | ||||
|     delay(this->command_delay_); | ||||
|     yield(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool ModemComponent::is_network_attached_() { | ||||
|   int network_attachment_state; | ||||
|   command_result err = this->dce->get_network_attachment_state(network_attachment_state); | ||||
|   if (err == command_result::OK) { | ||||
|     return network_attachment_state; | ||||
|   } else | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| bool ModemComponent::start_ppp_() { | ||||
|   this->connect_begin_ = millis(); | ||||
|   this->internal_state_.connect_begin = millis(); | ||||
|   this->status_set_warning("Starting connection"); | ||||
|   this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); | ||||
|  | ||||
|   // will be set to true on event IP_EVENT_PPP_GOT_IP | ||||
|   this->got_ipv4_address_ = false; | ||||
|  | ||||
|   this->dump_dce_status_(); | ||||
|   this->internal_state_.got_ipv4_address = false; | ||||
|  | ||||
|   ESP_LOGD(TAG, "Asking the modem to enter PPP"); | ||||
|  | ||||
| @@ -351,282 +724,25 @@ void ModemComponent::ip_event_handler(void *arg, esp_event_base_t event_base, in | ||||
|       event = (ip_event_got_ip_t *) event_data; | ||||
|       ip_info = &event->ip_info; | ||||
|       ESP_LOGD(TAG, "[IP event] Got IP " IPSTR, IP2STR(&ip_info->ip)); | ||||
|       global_modem_component->got_ipv4_address_ = true; | ||||
|       global_modem_component->connected_ = true; | ||||
|       global_modem_component->internal_state_.got_ipv4_address = true; | ||||
|       global_modem_component->internal_state_.connected = true; | ||||
|       break; | ||||
|  | ||||
|     case IP_EVENT_PPP_LOST_IP: | ||||
|       if (global_modem_component->connected_) { | ||||
|       if (global_modem_component->internal_state_.connected) { | ||||
|         // do not log message if we are not connected | ||||
|         ESP_LOGD(TAG, "[IP event] Lost IP"); | ||||
|       } | ||||
|       global_modem_component->got_ipv4_address_ = false; | ||||
|       global_modem_component->connected_ = false; | ||||
|       global_modem_component->internal_state_.got_ipv4_address = false; | ||||
|       global_modem_component->internal_state_.connected = false; | ||||
|       break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void ModemComponent::loop() { | ||||
|   static ModemComponentState last_state = this->state_; | ||||
|   static uint32_t next_loop_millis = millis(); | ||||
|   static bool connecting = false; | ||||
|   static bool disconnecting = false; | ||||
|   static uint8_t network_attach_retry = 10; | ||||
|   static uint8_t ip_lost_retries = 10; | ||||
|  | ||||
|   if ((millis() < next_loop_millis)) { | ||||
|     // some commands need some delay | ||||
|     yield(); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
| #ifdef USE_MODEM_POWER | ||||
|   if (this->power_transition_) { | ||||
|     if (!this->watchdog_) | ||||
|       this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); | ||||
|  | ||||
|     // A power state is used to handle long tonuart/toffuart delay | ||||
|     switch (this->power_state_) { | ||||
|       case ModemPowerState::TON: | ||||
|         this->power_pin_->digital_write(false); | ||||
|         delay(USE_MODEM_POWER_TON); | ||||
|         this->power_pin_->digital_write(true); | ||||
|         next_loop_millis = millis() + USE_MODEM_POWER_TONUART;  // delay for next loop | ||||
|         this->power_state_ = ModemPowerState::TONUART; | ||||
|         ESP_LOGD(TAG, "Will check that the modem is on in %.1fs...", float(USE_MODEM_POWER_TONUART) / 1000); | ||||
|         break; | ||||
|       case ModemPowerState::TONUART: | ||||
|         this->power_transition_ = false; | ||||
|         if (!this->modem_sync_()) { | ||||
|           ESP_LOGE(TAG, "Unable to power on the modem"); | ||||
|           this->powered_on_ = false; | ||||
|         } else { | ||||
|           ESP_LOGI(TAG, "Modem powered ON"); | ||||
|           this->powered_on_ = true; | ||||
|           this->modem_synced_ = false; | ||||
|           this->watchdog_.reset(); | ||||
|         } | ||||
|         break; | ||||
|       case ModemPowerState::TOFF: | ||||
|         delay(10); | ||||
|         this->power_pin_->digital_write(false); | ||||
|         delay(USE_MODEM_POWER_TOFF); | ||||
|         this->power_pin_->digital_write(true); | ||||
|         this->power_state_ = ModemPowerState::TOFFUART; | ||||
|         ESP_LOGD(TAG, "Will check that the modem is off in %.1fs...", float(USE_MODEM_POWER_TOFFUART) / 1000); | ||||
|         next_loop_millis = millis() + USE_MODEM_POWER_TOFFUART;  // delay for next loop | ||||
|         break; | ||||
|       case ModemPowerState::TOFFUART: | ||||
|         this->power_transition_ = false; | ||||
|         if (this->modem_ready()) { | ||||
|           ESP_LOGE(TAG, "Unable to power off the modem"); | ||||
|           this->powered_on_ = true; | ||||
|         } else { | ||||
|           ESP_LOGI(TAG, "Modem powered OFF"); | ||||
|           this->powered_on_ = false; | ||||
|           this->modem_synced_ = false; | ||||
|           this->watchdog_.reset(); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|     yield(); | ||||
|     return; | ||||
|   } | ||||
| #endif  // USE_MODEM_POWER | ||||
|  | ||||
|   switch (this->state_) { | ||||
|     case ModemComponentState::NOT_RESPONDING: | ||||
|       if (this->start_) { | ||||
|         if (this->modem_ready()) { | ||||
|           ESP_LOGI(TAG, "Modem recovered"); | ||||
|           this->status_clear_warning(); | ||||
|           this->state_ = ModemComponentState::DISCONNECTED; | ||||
|         } else { | ||||
|           if (!this->powered_on_) { | ||||
|             this->poweron_(); | ||||
|           } else if (this->not_responding_cb_) { | ||||
|             if (!this->not_responding_cb_->is_action_running()) { | ||||
|               ESP_LOGD(TAG, "Calling 'on_not_responding' callback"); | ||||
|               this->not_responding_cb_->trigger(); | ||||
|             } | ||||
|           } else { | ||||
|             ESP_LOGW(TAG, "Modem not responding, and no 'on_not_responding' action defined"); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case ModemComponentState::DISCONNECTED: | ||||
|       if (this->enabled_) { | ||||
|         // be sure the modem is on and synced | ||||
|         if (!this->powered_on_) { | ||||
|           this->poweron_(); | ||||
|           break; | ||||
|         } else if (!this->modem_synced_) { | ||||
|           if (!this->modem_sync_()) { | ||||
|             ESP_LOGE(TAG, "Modem not responding"); | ||||
|             this->state_ = ModemComponentState::NOT_RESPONDING; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (this->start_) { | ||||
|           // want to connect | ||||
|           if (!connecting) { | ||||
|             // wait for the modem be attached to a network, start ppp, and set connecting=true | ||||
|             if (!this->watchdog_) | ||||
|               this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); | ||||
|             if (is_network_attached_()) { | ||||
|               network_attach_retry = 10; | ||||
|               if (this->start_ppp_()) { | ||||
|                 connecting = true; | ||||
|                 next_loop_millis = millis() + 2000;  // delay for next loop | ||||
|               } | ||||
|             } else { | ||||
|               ESP_LOGD(TAG, "Waiting for the modem to be attached to a network (left retries: %" PRIu8 ")", | ||||
|                        network_attach_retry); | ||||
|               network_attach_retry--; | ||||
|               if (network_attach_retry == 0) { | ||||
|                 ESP_LOGE(TAG, "modem is unable to attach to a network"); | ||||
|                 if (this->power_pin_) { | ||||
|                   this->poweroff_(); | ||||
|                 } else { | ||||
|                   this->state_ = ModemComponentState::NOT_RESPONDING; | ||||
|                 } | ||||
|               } | ||||
|               next_loop_millis = millis() + 1000;  // delay to retry | ||||
|             } | ||||
|           } else { | ||||
|             // connecting | ||||
|             if (!this->connected_) { | ||||
|               // wait until this->connected_ set to true by IP_EVENT_PPP_GOT_IP | ||||
|               next_loop_millis = millis() + 1000;  // delay for next loop | ||||
|  | ||||
|               // connecting timeout | ||||
|               if (millis() - this->connect_begin_ > 15000) { | ||||
|                 ESP_LOGW(TAG, "Connecting via Modem failed! Re-connecting..."); | ||||
|                 // TODO: exit data/cmux without error check | ||||
|                 connecting = false; | ||||
|               } | ||||
|             } else { | ||||
|               connecting = false; | ||||
|               ESP_LOGI(TAG, "Connected via Modem"); | ||||
|               this->state_ = ModemComponentState::CONNECTED; | ||||
|  | ||||
|               this->dump_connect_params_(); | ||||
|               this->status_clear_warning(); | ||||
|               this->watchdog_.reset(); | ||||
|             } | ||||
|           } | ||||
|         } else { | ||||
|           this->start_ = true; | ||||
|         } | ||||
|       } else { | ||||
|         this->state_ = ModemComponentState::DISABLED; | ||||
|         this->watchdog_.reset(); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case ModemComponentState::CONNECTED: | ||||
|       if (this->enabled_) { | ||||
|         if (!this->connected_) { | ||||
|           this->status_set_warning("Connection via Modem lost!"); | ||||
|           this->state_ = ModemComponentState::DISCONNECTED; | ||||
|         } | ||||
|         disconnecting = false; | ||||
|       } else { | ||||
|         if (this->connected_) { | ||||
|           // connected but disbled, so disconnect | ||||
|           if (!disconnecting) { | ||||
|             disconnecting = true; | ||||
|             ip_lost_retries = 10; | ||||
|             this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); | ||||
|             ESP_LOGD(TAG, "Disconnecting..."); | ||||
|             this->stop_ppp_(); | ||||
|             delay(200);  // NOLINT | ||||
|             ESP_LOGD(TAG, "Disconnected after %.1fmin", float(this->connect_begin_) / (1000 * 60)); | ||||
|           } else { | ||||
|             // disconnecting | ||||
|             // Waiting for IP_EVENT_PPP_LOST_IP. | ||||
|             // This can take a long time, so we ckeck the IP addr, and trigger the event manualy if it's null. | ||||
|             esp_netif_ip_info_t ip_info; | ||||
|             esp_netif_get_ip_info(this->ppp_netif_, &ip_info); | ||||
|             if (ip_info.ip.addr == 0) { | ||||
|               // lost IP | ||||
|               esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0); | ||||
|             } else { | ||||
|               ESP_LOGD(TAG, "Waiting for lost IP... (retries %" PRIu8 ")", ip_lost_retries); | ||||
|               ip_lost_retries--; | ||||
|               if (ip_lost_retries == 0) { | ||||
|                 // Something goes wrong, we have still an IP | ||||
|                 ESP_LOGE(TAG, "No IP lost event recieved. Sending one manually"); | ||||
|                 esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0); | ||||
|               } | ||||
|             } | ||||
|             next_loop_millis = millis() + 2000;  // delay for next loop | ||||
|           } | ||||
|         } else {  // if (this->connected_) | ||||
|           // ip lost as expected | ||||
|           ESP_LOGI(TAG, "PPPoS disconnected"); | ||||
|           this->state_ = ModemComponentState::DISCONNECTED; | ||||
|         } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case ModemComponentState::DISABLED: | ||||
|       if (this->enabled_) { | ||||
|         this->state_ = ModemComponentState::DISCONNECTED; | ||||
|         ESP_LOGE(TAG, "here"); | ||||
|       } else if (this->powered_on_) { | ||||
|         this->poweroff_(); | ||||
|       } | ||||
|       next_loop_millis = millis() + 2000;  // delay for next loop | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   if (this->state_ != last_state) { | ||||
|     ESP_LOGV(TAG, "State changed: %s -> %s", state_to_string(last_state).c_str(), | ||||
|              state_to_string(this->state_).c_str()); | ||||
|     this->on_state_callback_.call(last_state, this->state_); | ||||
|  | ||||
|     last_state = this->state_; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void ModemComponent::enable() { | ||||
|   ESP_LOGD(TAG, "Enabling modem"); | ||||
|   if (this->state_ == ModemComponentState::DISABLED) { | ||||
|     this->state_ = ModemComponentState::DISCONNECTED; | ||||
|   } | ||||
|   this->start_ = true; | ||||
|   this->enabled_ = true; | ||||
| } | ||||
|  | ||||
| void ModemComponent::disable() { | ||||
|   ESP_LOGD(TAG, "Disabling modem"); | ||||
|   this->enabled_ = false; | ||||
|   if (this->state_ != ModemComponentState::CONNECTED) { | ||||
|     this->state_ = ModemComponentState::DISCONNECTED; | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool ModemComponent::get_power_status() { | ||||
| #ifdef USE_MODEM_STATUS | ||||
|   // This code is not fully checked. The status pin seems to be flickering on Lilygo T-SIM7600 | ||||
|   return this->status_pin_->digital_read(); | ||||
| #else | ||||
|   if (!this->cmux_ && this->connected_) { | ||||
|     // Data mode, connected:  assume power is OK | ||||
|     return true; | ||||
|   } | ||||
|   return this->modem_ready(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void ModemComponent::poweron_() { | ||||
| #ifdef USE_MODEM_POWER | ||||
|   this->power_state_ = ModemPowerState::TON; | ||||
|   this->power_transition_ = true; | ||||
|   return; | ||||
|   this->internal_state_.power_state = ModemPowerState::TON; | ||||
|   this->internal_state_.power_transition = true; | ||||
| #else | ||||
|   if (this->modem_ready()) { | ||||
|     ESP_LOGV(TAG, "Modem is already ON"); | ||||
| @@ -638,14 +754,13 @@ void ModemComponent::poweron_() { | ||||
|  | ||||
| void ModemComponent::poweroff_() { | ||||
| #ifdef USE_MODEM_POWER | ||||
|   this->power_state_ = ModemPowerState::TOFF; | ||||
|   this->power_transition_ = true; | ||||
|   return; | ||||
|   this->internal_state_.power_state = ModemPowerState::TOFF; | ||||
|   this->internal_state_.power_transition = true; | ||||
| #endif  // USE_MODEM_POWER | ||||
| } | ||||
|  | ||||
| void ModemComponent::dump_connect_params_() { | ||||
|   if (!this->connected_) { | ||||
|   if (!this->internal_state_.connected) { | ||||
|     ESP_LOGCONFIG(TAG, "Modem connection: Not connected"); | ||||
|     return; | ||||
|   } | ||||
| @@ -666,104 +781,6 @@ void ModemComponent::dump_connect_params_() { | ||||
|   ESP_LOGCONFIG(TAG, "  DNS fallback: %s", network::IPAddress(dns_fallback_ip).str().c_str()); | ||||
| } | ||||
|  | ||||
| bool ModemComponent::is_network_attached_() { | ||||
|   int network_attachment_state; | ||||
|   command_result err = this->dce->get_network_attachment_state(network_attachment_state); | ||||
|   if (err == command_result::OK) { | ||||
|     return network_attachment_state; | ||||
|   } else | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| void ModemComponent::dump_dce_status_() { | ||||
|   ESP_LOGCONFIG(TAG, "Modem status:"); | ||||
|   command_result err; | ||||
|   std::string result; | ||||
|   err = this->dce->get_module_name(result); | ||||
|   if (err != command_result::OK) { | ||||
|     result = "command " + command_result_to_string(err); | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  Module name        : %s", result.c_str()); | ||||
|  | ||||
|   int rssi; | ||||
|   int ber; | ||||
|   err = this->dce->get_signal_quality(rssi, ber); | ||||
|   if (err != command_result::OK) { | ||||
|     result = "command " + command_result_to_string(err); | ||||
|   } else { | ||||
|     float ber_f; | ||||
|     if (ber != 99) { | ||||
|       ber_f = float(ber); | ||||
|     } else | ||||
|       ber_f = {}; | ||||
|     std::ostringstream oss; | ||||
|     oss << "rssi " << rssi << "(" << (rssi * 100) / 31 << "%), ber " << ber << "(" << (ber_f * 100) / 7 << "%)"; | ||||
|     result = oss.str(); | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  Signal quality     : %s", result.c_str()); | ||||
|  | ||||
|   int network_attachment_state; | ||||
|   err = this->dce->get_network_attachment_state(network_attachment_state); | ||||
|   if (err == command_result::OK) { | ||||
|     result = network_attachment_state ? "Yes" : "No"; | ||||
|   } else { | ||||
|     result = "command " + command_result_to_string(err); | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  Attached to network: %s", result.c_str()); | ||||
| } | ||||
|  | ||||
| std::string ModemComponent::send_at(const std::string &cmd) { | ||||
|   std::string result; | ||||
|   command_result status; | ||||
|   ESP_LOGV(TAG, "Sending command: %s", cmd.c_str()); | ||||
|   status = this->dce->at(cmd, result, this->command_delay_); | ||||
|   ESP_LOGV(TAG, "Result for command %s: %s (status %s)", cmd.c_str(), result.c_str(), | ||||
|            command_result_to_string(status).c_str()); | ||||
|   if (status != esp_modem::command_result::OK) { | ||||
|     result = "ERROR"; | ||||
|   } | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| bool ModemComponent::get_imei(std::string &result) { | ||||
|   // wrapper around this->dce->get_imei() that check that the result is valid | ||||
|   // (so it can be used to check if the modem is responding correctly (a simple 'AT' cmd is sometime not enough)) | ||||
|   command_result status; | ||||
|   status = this->dce->get_imei(result); | ||||
|   bool success = true; | ||||
|  | ||||
|   if (status == command_result::OK && result.length() == 15) { | ||||
|     for (char c : result) { | ||||
|       if (!isdigit(static_cast<unsigned char>(c))) { | ||||
|         success = false; | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } else { | ||||
|     success = false; | ||||
|   } | ||||
|  | ||||
|   if (!success) { | ||||
|     result = "UNAVAILABLE"; | ||||
|   } | ||||
|   return success; | ||||
| } | ||||
|  | ||||
| bool ModemComponent::modem_ready() { | ||||
|   // check if the modem is ready to answer AT commands | ||||
|   std::string imei; | ||||
|   if (this->get_imei(imei)) { | ||||
|     // we are sure that the modem is on | ||||
|     this->powered_on_ = true; | ||||
|     return true; | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| void ModemComponent::add_on_state_callback(std::function<void(ModemComponentState, ModemComponentState)> &&callback) { | ||||
|   this->on_state_callback_.add(std::move(callback)); | ||||
| } | ||||
|  | ||||
| }  // namespace modem | ||||
| }  // namespace esphome | ||||
|  | ||||
|   | ||||
| @@ -49,16 +49,7 @@ enum class ModemPowerState { | ||||
|  | ||||
| class ModemComponent : public Component { | ||||
|  public: | ||||
|   ModemComponent(); | ||||
|   void setup() override; | ||||
|   void loop() override; | ||||
|   void dump_config() override; | ||||
|   bool is_connected(); | ||||
|   float get_setup_priority() const override; | ||||
|   bool can_proceed() override; | ||||
|   network::IPAddresses get_ip_addresses(); | ||||
|   std::string get_use_address() const; | ||||
|   void set_use_address(const std::string &use_address); | ||||
|   void set_use_address(const std::string &use_address) { this->use_address_ = use_address; } | ||||
|   void set_rx_pin(InternalGPIOPin *rx_pin) { this->rx_pin_ = rx_pin; } | ||||
|   void set_tx_pin(InternalGPIOPin *tx_pin) { this->tx_pin_ = tx_pin; } | ||||
|   void set_power_pin(GPIOPin *power_pin) { this->power_pin_ = power_pin; } | ||||
| @@ -70,13 +61,38 @@ class ModemComponent : public Component { | ||||
|   void set_not_responding_cb(Trigger<> *not_responding_cb) { this->not_responding_cb_ = not_responding_cb; } | ||||
|   void enable_cmux() { this->cmux_ = true; } | ||||
|   void add_init_at_command(const std::string &cmd) { this->init_at_commands_.push_back(cmd); } | ||||
|   bool is_connected() { return this->component_state_ == ModemComponentState::CONNECTED; } | ||||
|   std::string send_at(const std::string &cmd); | ||||
|   bool get_imei(std::string &result); | ||||
|   bool get_power_status(); | ||||
|   bool modem_ready(); | ||||
|   void enable(); | ||||
|   void disable(); | ||||
|   void add_on_state_callback(std::function<void(ModemComponentState, ModemComponentState)> &&callback); | ||||
|  | ||||
|   network::IPAddresses get_ip_addresses(); | ||||
|   std::string get_use_address() const; | ||||
|  | ||||
|   void dump_dce_status(); | ||||
|  | ||||
|   // ========== INTERNAL METHODS ========== | ||||
|   // (In most use cases you won't need these) | ||||
|  | ||||
|   ModemComponent(); | ||||
|   void setup() override; | ||||
|   void loop() override; | ||||
|   void dump_config() override { this->dump_connect_params_(); } | ||||
|   float get_setup_priority() const override { return setup_priority::WIFI + 1; }  // just before WIFI | ||||
|   bool can_proceed() override { | ||||
|     if (!this->internal_state_.enabled) { | ||||
|       return true; | ||||
|     } | ||||
|     return this->is_connected(); | ||||
|   }; | ||||
|   void add_on_state_callback(std::function<void(ModemComponentState, ModemComponentState)> &&callback) { | ||||
|     this->on_state_callback_.add(std::move(callback)); | ||||
|   } | ||||
|   // main esp_modem object | ||||
|   // https://docs.espressif.com/projects/esp-protocols/esp_modem/docs/latest/internal_docs.html#dce-internal-implementation | ||||
|   std::unique_ptr<DCE> dce{nullptr}; | ||||
|  | ||||
|  protected: | ||||
| @@ -91,7 +107,8 @@ class ModemComponent : public Component { | ||||
|   void poweroff_(); | ||||
|   static void ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); | ||||
|   void dump_connect_params_(); | ||||
|   void dump_dce_status_(); | ||||
|  | ||||
|   // Attributes from yaml config | ||||
|   InternalGPIOPin *tx_pin_; | ||||
|   InternalGPIOPin *rx_pin_; | ||||
|   GPIOPin *status_pin_{nullptr}; | ||||
| @@ -101,38 +118,50 @@ class ModemComponent : public Component { | ||||
|   std::string password_; | ||||
|   std::string apn_; | ||||
|   std::vector<std::string> init_at_commands_; | ||||
|   std::string use_address_; | ||||
|   bool cmux_{false}; | ||||
|   // separate handler for `on_not_responding` (we want to know when it's ended) | ||||
|   Trigger<> *not_responding_cb_{nullptr}; | ||||
|   CallbackManager<void(ModemComponentState, ModemComponentState)> on_state_callback_; | ||||
|  | ||||
|   // Allow changes from yaml ? | ||||
|   size_t uart_rx_buffer_size_ = 2048;         // 256-2048 | ||||
|   size_t uart_tx_buffer_size_ = 1024;         // 256-2048 | ||||
|   uint8_t uart_event_queue_size_ = 30;        // 10-40 | ||||
|   size_t uart_event_task_stack_size_ = 2048;  // 2000-6000 | ||||
|   uint8_t uart_event_task_priority_ = 5;      // 3-22 | ||||
|   uint32_t command_delay_ = 500;              // timeout for AT commands | ||||
|  | ||||
|   // Changes will trigger user callback | ||||
|   ModemComponentState component_state_{ModemComponentState::DISABLED}; | ||||
|  | ||||
|   // the uart DTE | ||||
|   // https://docs.espressif.com/projects/esp-protocols/esp_modem/docs/latest/internal_docs.html#_CPPv4N9esp_modem3DCEE | ||||
|   std::shared_ptr<DTE> dte_{nullptr}; | ||||
|   esp_netif_t *ppp_netif_{nullptr}; | ||||
|   ModemComponentState state_{ModemComponentState::DISABLED}; | ||||
|  | ||||
|   // Many operation blocks a long time. | ||||
|   std::shared_ptr<watchdog::WatchdogManager> watchdog_; | ||||
|   bool cmux_{false}; | ||||
|   bool start_{false}; | ||||
|   bool enabled_{false}; | ||||
|   bool connected_{false}; | ||||
|   bool got_ipv4_address_{false}; | ||||
|  | ||||
|   struct InternalState { | ||||
|     bool start{false}; | ||||
|     bool enabled{false}; | ||||
|     bool connected{false}; | ||||
|     bool got_ipv4_address{false}; | ||||
|     // true if modem_sync_ was sucessfull | ||||
|   bool modem_synced_{false}; | ||||
|     bool modem_synced{false}; | ||||
|     // date start (millis()) | ||||
|   uint32_t connect_begin_; | ||||
|   std::string use_address_; | ||||
|   // timeout for AT commands | ||||
|   uint32_t command_delay_ = 500; | ||||
|     uint32_t connect_begin; | ||||
|     // guess power state | ||||
|   bool powered_on_{false}; | ||||
|     bool powered_on{false}; | ||||
| #ifdef USE_MODEM_POWER | ||||
|     // Will be true when power transitionning | ||||
|   bool power_transition_{false}; | ||||
|     bool power_transition{false}; | ||||
|     // states for triggering on/off signals | ||||
|   ModemPowerState power_state_{ModemPowerState::TOFFUART}; | ||||
|     ModemPowerState power_state{ModemPowerState::TOFFUART}; | ||||
| #endif  // USE_MODEM_POWER | ||||
|   // separate handler for `on_not_responding` (we want to know when it's ended) | ||||
|   Trigger<> *not_responding_cb_{nullptr}; | ||||
|   CallbackManager<void(ModemComponentState, ModemComponentState)> on_state_callback_; | ||||
|   }; | ||||
|   InternalState internal_state_; | ||||
| }; | ||||
|  | ||||
| // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user