mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 06:33:51 +00:00 
			
		
		
		
	optionnal cmux WIP
This commit is contained in:
		| @@ -6,6 +6,7 @@ | |||||||
| #include "esphome/core/application.h" | #include "esphome/core/application.h" | ||||||
| #include "esphome/core/defines.h" | #include "esphome/core/defines.h" | ||||||
| #include "esphome/components/network/util.h" | #include "esphome/components/network/util.h" | ||||||
|  | // #include "esphome/components/gpio/binary_sensor/gpio_binary_sensor.h" | ||||||
|  |  | ||||||
| #include <esp_netif.h> | #include <esp_netif.h> | ||||||
| #include <esp_netif_ppp.h> | #include <esp_netif_ppp.h> | ||||||
| @@ -20,6 +21,10 @@ | |||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  |  | ||||||
|  | #ifndef USE_MODEM_MODEL | ||||||
|  | #define USE_MODEM_MODEL UNKNOWN | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #define ESPHL_ERROR_CHECK(err, message) \ | #define ESPHL_ERROR_CHECK(err, message) \ | ||||||
|   if ((err) != ESP_OK) { \ |   if ((err) != ESP_OK) { \ | ||||||
|     ESP_LOGE(TAG, message ": (%d) %s", err, esp_err_to_name(err)); \ |     ESP_LOGE(TAG, message ": (%d) %s", err, esp_err_to_name(err)); \ | ||||||
| @@ -50,24 +55,9 @@ ModemComponent::ModemComponent() { | |||||||
|   global_modem_component = this; |   global_modem_component = this; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ModemComponent::dump_config() { | void ModemComponent::dump_config() { this->dump_connect_params_(); } | ||||||
|   ESP_LOGCONFIG(TAG, "Config Modem:"); |  | ||||||
|   ESP_LOGCONFIG(TAG, "  Model     : %s", USE_MODEM_MODEL); |  | ||||||
|   ESP_LOGCONFIG(TAG, "  APN       : %s", this->apn_.c_str()); |  | ||||||
|   ESP_LOGCONFIG(TAG, "  PIN code  : %s", (this->pin_code_.empty()) ? "No" : "Yes (not shown)"); |  | ||||||
|   ESP_LOGCONFIG(TAG, "  Tx Pin    : GPIO%u", this->tx_pin_->get_pin()); |  | ||||||
|   ESP_LOGCONFIG(TAG, "  Rx Pin    : GPIO%u", this->rx_pin_->get_pin()); |  | ||||||
|   ESP_LOGCONFIG(TAG, "  Power pin : %s", |  | ||||||
|                 (this->power_pin_) ? ("GPIO" + std::to_string(this->power_pin_->get_pin())).c_str() : "Not defined"); |  | ||||||
|   if (this->status_pin_) { |  | ||||||
|     std::string current_status = this->get_power_status() ? "ON" : "OFF"; |  | ||||||
|     ESP_LOGCONFIG(TAG, "  Status pin: GPIO%u (current state %s)", this->status_pin_->get_pin(), current_status.c_str()); |  | ||||||
|   } else { |  | ||||||
|     ESP_LOGCONFIG(TAG, "  Status pin: Not defined"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| float ModemComponent::get_setup_priority() const { return setup_priority::WIFI; } | float ModemComponent::get_setup_priority() const { return setup_priority::WIFI; }  // FIXME AFTER_WIFI | ||||||
|  |  | ||||||
| bool ModemComponent::can_proceed() { return this->is_connected(); } | bool ModemComponent::can_proceed() { return this->is_connected(); } | ||||||
|  |  | ||||||
| @@ -99,6 +89,30 @@ bool ModemComponent::is_connected() { return this->state_ == ModemComponentState | |||||||
| void ModemComponent::setup() { | void ModemComponent::setup() { | ||||||
|   ESP_LOGI(TAG, "Setting up Modem..."); |   ESP_LOGI(TAG, "Setting up Modem..."); | ||||||
|  |  | ||||||
|  |   if (this->power_pin_) { | ||||||
|  |     this->power_pin_->setup(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (this->status_pin_) { | ||||||
|  |     this->status_pin_->setup(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ESP_LOGCONFIG(TAG, "Config Modem:"); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Model     : %s", USE_MODEM_MODEL); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  APN       : %s", this->apn_.c_str()); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  PIN code  : %s", (this->pin_code_.empty()) ? "No" : "Yes (not shown)"); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Tx Pin    : GPIO%u", this->tx_pin_->get_pin()); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Rx Pin    : GPIO%u", this->rx_pin_->get_pin()); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Power pin : %s", (this->power_pin_) ? this->power_pin_->dump_summary().c_str() : "Not defined"); | ||||||
|  |   if (this->status_pin_) { | ||||||
|  |     std::string current_status = this->get_power_status() ? "ON" : "OFF"; | ||||||
|  |     ESP_LOGCONFIG(TAG, "  Status pin: %s (current state %s)", this->status_pin_->dump_summary().c_str(), | ||||||
|  |                   current_status.c_str()); | ||||||
|  |   } else { | ||||||
|  |     ESP_LOGCONFIG(TAG, "  Status pin: Not defined"); | ||||||
|  |   } | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Enabled   : %s", this->enabled_ ? "Yes" : "No"); | ||||||
|  |  | ||||||
|   ESP_LOGV(TAG, "PPP netif setup"); |   ESP_LOGV(TAG, "PPP netif setup"); | ||||||
|   esp_err_t err; |   esp_err_t err; | ||||||
|   err = esp_netif_init(); |   err = esp_netif_init(); | ||||||
| @@ -126,32 +140,24 @@ void ModemComponent::setup() { | |||||||
|   err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &ModemComponent::ip_event_handler, nullptr); |   err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &ModemComponent::ip_event_handler, nullptr); | ||||||
|   ESPHL_ERROR_CHECK(err, "IP event handler register error"); |   ESPHL_ERROR_CHECK(err, "IP event handler register error"); | ||||||
|  |  | ||||||
|   if (this->power_pin_) { |   this->create_dte_dce_(); | ||||||
|     this->power_pin_->setup(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (this->status_pin_) { |   if (this->enabled_ && !this->get_power_status()) { | ||||||
|     this->status_pin_->setup(); |     ESP_LOGI(TAG, "Powering up modem"); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this->reset_(); |     this->poweron_(); | ||||||
|   // At boot time, if the modem power  is up, but the modem is not ready, it is probably still in cmux mode |  | ||||||
|   if (this->enabled_ && this->get_power_status() && !this->modem_ready()) { |  | ||||||
|     this->exit_cmux_(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ESP_LOGV(TAG, "Setup finished"); |   ESP_LOGV(TAG, "Setup finished"); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ModemComponent::reset_() { | void ModemComponent::create_dte_dce_() { | ||||||
|   // destroy previous dte/dce, and recreate them. |   // destroy previous dte/dce, and recreate them. | ||||||
|   // destroying them seems to be the only way to have a clear state after hang up, and be able to reconnect. |   // destroying them seems to be the only way to have a clear state after hang up, and be able to reconnect. | ||||||
|   // if the modem was previously in cmux mode, this->exit_cmux_(), will be needed after. |  | ||||||
|  |  | ||||||
|   this->dte_.reset(); |   this->dte_.reset(); | ||||||
|   this->dce.reset(); |   this->dce.reset(); | ||||||
|  |  | ||||||
|   ESP_LOGV(TAG, "DTE setup"); |  | ||||||
|   esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); |   esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG(); | ||||||
|   this->dte_config_ = dte_config; |   this->dte_config_ = dte_config; | ||||||
|  |  | ||||||
| @@ -168,7 +174,7 @@ void ModemComponent::reset_() { | |||||||
|  |  | ||||||
|   this->dte_ = create_uart_dte(&this->dte_config_); |   this->dte_ = create_uart_dte(&this->dte_config_); | ||||||
|  |  | ||||||
|   ESP_LOGV(TAG, "DCE setup"); |   // this->dte_->set_mode(modem_mode::COMMAND_MODE); | ||||||
|  |  | ||||||
| #if defined(USE_MODEM_MODEL_GENERIC) | #if defined(USE_MODEM_MODEL_GENERIC) | ||||||
|   this->dce = create_generic_dce(&this->dce_config_, this->dte_, this->ppp_netif_); |   this->dce = create_generic_dce(&this->dce_config_, this->dte_, this->ppp_netif_); | ||||||
| @@ -190,9 +196,22 @@ void ModemComponent::reset_() { | |||||||
|       ESP_LOGE(TAG, "Failed to set the set_flow_control mode"); |       ESP_LOGE(TAG, "Failed to set the set_flow_control mode"); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     ESP_LOGI(TAG, "set_flow_control OK"); |     ESP_LOGD(TAG, "set_flow_control OK"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Try to exit CMUX_MANUAL_DATA or DATA_MODE, if any | ||||||
|  |   Watchdog wdt(60); | ||||||
|  |   if (this->cmux_) { | ||||||
|  |     this->dce->set_mode(modem_mode::CMUX_MANUAL_MODE); | ||||||
|  |     this->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND); | ||||||
|  |   } else if (!this->modem_ready()) { | ||||||
|  |     this->dce->set_mode(modem_mode::COMMAND_MODE); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (this->modem_ready()) { | ||||||
|  |     ESP_LOGD(TAG, "modem ready after exiting cmux/data mode"); | ||||||
|   } else { |   } else { | ||||||
|     ESP_LOGI(TAG, "not set_flow_control, because 2-wire mode active."); |     ESP_LOGD(TAG, "modem *not* ready after exiting cmux/data mode"); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -227,6 +246,7 @@ bool ModemComponent::prepare_sim_() { | |||||||
|  |  | ||||||
| void ModemComponent::send_init_at_() { | void ModemComponent::send_init_at_() { | ||||||
|   // send initial AT commands from yaml |   // send initial AT commands from yaml | ||||||
|  |   Watchdog wdt(60); | ||||||
|   for (const auto &cmd : this->init_at_commands_) { |   for (const auto &cmd : this->init_at_commands_) { | ||||||
|     std::string result = this->send_at(cmd); |     std::string result = this->send_at(cmd); | ||||||
|     if (result == "ERROR") { |     if (result == "ERROR") { | ||||||
| @@ -243,13 +263,28 @@ void ModemComponent::start_connect_() { | |||||||
|   this->status_set_warning("Starting connection"); |   this->status_set_warning("Starting connection"); | ||||||
|  |  | ||||||
|   // will be set to true on event IP_EVENT_PPP_GOT_IP |   // will be set to true on event IP_EVENT_PPP_GOT_IP | ||||||
|   global_modem_component->got_ipv4_address_ = false; |   global_modem_component->got_ipv4_address_ = false;  // FIXME this | ||||||
|  |  | ||||||
|   ESP_LOGD(TAG, "Entering CMUX mode"); |   if (this->cmux_) { | ||||||
|   if (this->dce->set_mode(modem_mode::CMUX_MODE)) { |     ESP_LOGD(TAG, "Entering CMUX mode"); | ||||||
|     ESP_LOGD(TAG, "Modem has correctly entered multiplexed command/data mode"); |     this->dce->set_mode(modem_mode::CMUX_MANUAL_MODE); | ||||||
|  |     if (this->dce->set_mode(modem_mode::CMUX_MANUAL_DATA)) { | ||||||
|  |       ESP_LOGD(TAG, "Modem has correctly entered multiplexed command/data mode"); | ||||||
|  |  | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGD(TAG, "Unable to enter CMUX mode"); | ||||||
|  |       this->status_set_error("Unable to enter CMUX mode"); | ||||||
|  |     } | ||||||
|  |     assert(this->modem_ready()); | ||||||
|   } else { |   } else { | ||||||
|     this->status_set_error("Unable to enter CMUX mode"); |     ESP_LOGD(TAG, "Entering DATA mode"); | ||||||
|  |     if (this->dce->set_mode(modem_mode::DATA_MODE)) { | ||||||
|  |       ESP_LOGD(TAG, "Modem has correctly entered data mode"); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGD(TAG, "Unable to enter DATA mode"); | ||||||
|  |       this->status_set_error("Unable to enter DATA mode"); | ||||||
|  |     } | ||||||
|  |     assert(!this->modem_ready()); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -265,7 +300,7 @@ void ModemComponent::ip_event_handler(void *arg, esp_event_base_t event_base, in | |||||||
|       global_modem_component->connected_ = true; |       global_modem_component->connected_ = true; | ||||||
|       break; |       break; | ||||||
|     case IP_EVENT_PPP_LOST_IP: |     case IP_EVENT_PPP_LOST_IP: | ||||||
|       ESP_LOGV(TAG, "[IP event] Lost IP"); |       ESP_LOGD(TAG, "[IP event] Lost IP"); | ||||||
|       global_modem_component->got_ipv4_address_ = false; |       global_modem_component->got_ipv4_address_ = false; | ||||||
|       global_modem_component->connected_ = false; |       global_modem_component->connected_ = false; | ||||||
|       break; |       break; | ||||||
| @@ -285,6 +320,7 @@ void ModemComponent::loop() { | |||||||
|   switch (this->state_) { |   switch (this->state_) { | ||||||
|     case ModemComponentState::NOT_RESPONDING: |     case ModemComponentState::NOT_RESPONDING: | ||||||
|       if (this->start_) { |       if (this->start_) { | ||||||
|  |         Watchdog wdt(60); | ||||||
|         if (this->modem_ready()) { |         if (this->modem_ready()) { | ||||||
|           ESP_LOGI(TAG, "Modem recovered"); |           ESP_LOGI(TAG, "Modem recovered"); | ||||||
|           this->status_clear_warning(); |           this->status_clear_warning(); | ||||||
| @@ -309,6 +345,7 @@ void ModemComponent::loop() { | |||||||
|     case ModemComponentState::DISCONNECTED: |     case ModemComponentState::DISCONNECTED: | ||||||
|       if (this->enabled_) { |       if (this->enabled_) { | ||||||
|         if (this->start_) { |         if (this->start_) { | ||||||
|  |           Watchdog wdt(60); | ||||||
|           if (this->modem_ready()) { |           if (this->modem_ready()) { | ||||||
|             this->send_init_at_(); |             this->send_init_at_(); | ||||||
|             if (this->prepare_sim_()) { |             if (this->prepare_sim_()) { | ||||||
| @@ -319,13 +356,13 @@ void ModemComponent::loop() { | |||||||
|               this->disable(); |               this->disable(); | ||||||
|             } |             } | ||||||
|           } else if (!this->get_power_status()) { |           } else if (!this->get_power_status()) { | ||||||
|  |             ESP_LOGI(TAG, | ||||||
|  |                      "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); | ||||||
|             this->poweron_(); |             this->poweron_(); | ||||||
|           } else { |           } else { | ||||||
|             this->state_ = ModemComponentState::NOT_RESPONDING; |             this->state_ = ModemComponentState::NOT_RESPONDING; | ||||||
|           } |           } | ||||||
|         } else { |         } else { | ||||||
|           // when disconnected, we have to reset the dte and the dce |  | ||||||
|           this->reset_(); |  | ||||||
|           this->start_ = true; |           this->start_ = true; | ||||||
|         } |         } | ||||||
|       } else { |       } else { | ||||||
| @@ -362,29 +399,50 @@ void ModemComponent::loop() { | |||||||
|     case ModemComponentState::DISCONNECTING: |     case ModemComponentState::DISCONNECTING: | ||||||
|       if (this->start_) { |       if (this->start_) { | ||||||
|         if (this->connected_) { |         if (this->connected_) { | ||||||
|           ESP_LOGD(TAG, "Hanging up..."); |           Watchdog wdt(60); | ||||||
|           ESPMODEM_ERROR_CHECK(this->dce->hang_up(), "Unable to hang up"); |           ESP_LOGD(TAG, "Going to hang up..."); | ||||||
|           if (!this->modem_ready()) { |           this->dump_connect_params_(); | ||||||
|             ESP_LOGE(TAG, "modem not ready after hang up"); |           if (this->cmux_) { | ||||||
|  |             assert(this->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND)); | ||||||
|  |           } else { | ||||||
|  |             // assert(this->dce->set_mode(modem_mode::COMMAND_MODE)); // OK on 7600, nok on 7670... | ||||||
|  |             this->dce->set_mode(modem_mode::COMMAND_MODE); | ||||||
|           } |           } | ||||||
|           this->set_timeout("wait_lost_ip", 15000, [this]() { |           delay(500); | ||||||
|             // often reached on 7600, but not reached on 7670 |           ESP_LOGD(TAG, "Hanging up connection after %.1fmin", float(this->connect_begin_) / (1000 * 60)); | ||||||
|             ESP_LOGW(TAG, "No lost ip event received. Forcing disconnect state"); |           if (this->dce->hang_up() != command_result::OK) { | ||||||
|  |             ESP_LOGW(TAG, "Unable to hang up modem. Trying to continue anyway."); | ||||||
|             this->state_ = ModemComponentState::DISCONNECTED; |           } | ||||||
|  |           this->dump_connect_params_(); | ||||||
|             this->reset_();  // reset dce/dte |           // this->set_timeout("wait_lost_ip", 15000, [this]() { | ||||||
|             this->exit_cmux_(); |           //   // often reached on 7600, but not reached on 7670 | ||||||
|           }); |           //   // FIXME: don't wait for lost IP (ip is lost for 7600 several minutes after) | ||||||
|  |           //   ESP_LOGW(TAG, "No lost ip event received. Forcing disconnect state"); | ||||||
|  |           //   // esp_netif_action_stop(this->ppp_netif_, nullptr, 0, nullptr); | ||||||
|  |           //   this->dump_connect_params_(); | ||||||
|  |           //   // esp_netif_action_disconnected(this->ppp_netif_, nullptr, 0, nullptr); | ||||||
|  |           //   // esp_netif_action_stop(this->ppp_netif_, nullptr, 0, nullptr); | ||||||
|  |           //   esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0); | ||||||
|  |           //   // esp_netif_destroy(this->ppp_netif_); | ||||||
|  |           //   this->dump_connect_params_(); | ||||||
|  |           // }); | ||||||
|         } |         } | ||||||
|         this->start_ = false; |         this->start_ = false; | ||||||
|       } else if (!this->connected_) { |       } else if (!this->connected_) { | ||||||
|         // ip lost as expected |         // ip lost as expected | ||||||
|         this->cancel_timeout("wait_lost_ip"); |         this->cancel_timeout("wait_lost_ip"); | ||||||
|  |         ESP_LOGI(TAG, "Modem disconnected"); | ||||||
|  |         this->dump_connect_params_(); | ||||||
|         this->state_ = ModemComponentState::DISCONNECTED; |         this->state_ = ModemComponentState::DISCONNECTED; | ||||||
|  |       } else { | ||||||
|  |         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); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         this->reset_();  // reset dce/dte |         // waiting for lost IP | ||||||
|         this->exit_cmux_(); |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       break; |       break; | ||||||
| @@ -392,7 +450,7 @@ void ModemComponent::loop() { | |||||||
|     case ModemComponentState::DISABLED: |     case ModemComponentState::DISABLED: | ||||||
|       if (this->enabled_) { |       if (this->enabled_) { | ||||||
|         this->state_ = ModemComponentState::DISCONNECTED; |         this->state_ = ModemComponentState::DISCONNECTED; | ||||||
|       } else if (this->status_pin_ && this->get_power_status()) { |       } else if (this->get_power_status()) {  // FIXME long time in loop because of get_power_status | ||||||
|         this->poweroff_(); |         this->poweroff_(); | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
| @@ -426,42 +484,15 @@ void ModemComponent::disable() { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void ModemComponent::exit_cmux_() { |  | ||||||
|   // This must be called to gain command mode if: |  | ||||||
|   //   - if the esp has rebooted, but the modem not, it is still in cmux mode |  | ||||||
|   //   - after a dte/dce reset. |  | ||||||
|   // If the modem was previously ready, this will *HANG* de dte, and the modem will be unreachable, with no chances to |  | ||||||
|   // recover it. |  | ||||||
|   // We need this because we are not able to do a simple esp_modem::modem_mode::COMMAND_MODE (this is probably a bug in |  | ||||||
|   // esp_modem) |  | ||||||
|   Watchdog wdt(60); |  | ||||||
|   this->dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_MODE); |  | ||||||
|   this->dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_COMMAND); |  | ||||||
|   this->dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_EXIT); |  | ||||||
|   if (!this->modem_ready()) { |  | ||||||
|     ESP_LOGE(TAG, "Modem still not ready after reset"); |  | ||||||
|   } else { |  | ||||||
|     ESP_LOGD(TAG, "Modem exited previous CMUX session"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool ModemComponent::get_power_status() { | bool ModemComponent::get_power_status() { | ||||||
| #ifdef USE_MODEM_STATUS | #ifdef USE_MODEM_STATUS | ||||||
|   bool init_status = this->status_pin_->digital_read(); |   // This code is not fully checked. The status pin seems to be flickering on Lilygo T-SIM7600 | ||||||
|   // The status pin might be floating when supposed to be low, at least on lilygo tsim7600 |   return this->status_pin_->digital_read(); | ||||||
|   // as GPIO34 doesn't support pullup, we have to debounce it manually |  | ||||||
|   bool final_status = init_status; |  | ||||||
|   for (int i = 0; i < 5; i++) { |  | ||||||
|     delay(10); |  | ||||||
|     final_status = final_status && this->status_pin_->digital_read(); |  | ||||||
|   } |  | ||||||
|   if (final_status != init_status) { |  | ||||||
|     // ESP_LOGV(TAG, "Floating status pin detected for state %d", final_status); |  | ||||||
|   } |  | ||||||
|   return final_status; |  | ||||||
| #else | #else | ||||||
|   // No status pin, assuming the modem is ON |   // No status pin, assuming the modem is ON | ||||||
|   return true; |   // return true; | ||||||
|  |   // Watchdog wdt(60); | ||||||
|  |   return this->modem_ready(); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -479,11 +510,11 @@ void ModemComponent::poweron_() { | |||||||
|     ESP_LOGD(TAG, "Will check that the modem is on in %.1fs...", float(USE_MODEM_POWER_TONUART) / 1000); |     ESP_LOGD(TAG, "Will check that the modem is on in %.1fs...", float(USE_MODEM_POWER_TONUART) / 1000); | ||||||
|     this->set_timeout("wait_poweron", USE_MODEM_POWER_TONUART, [this]() { |     this->set_timeout("wait_poweron", USE_MODEM_POWER_TONUART, [this]() { | ||||||
|       Watchdog wdt(60); |       Watchdog wdt(60); | ||||||
|       while (!this->get_power_status()) { |       // while (!this->get_power_status()) { | ||||||
|         delay(this->command_delay_); |       //   delay(this->command_delay_); | ||||||
|         ESP_LOGV(TAG, "Waiting for modem to poweron..."); |       //   ESP_LOGV(TAG, "Waiting for modem to poweron..."); | ||||||
|       } |       // } | ||||||
|       ESP_LOGV(TAG, "Modem ON"); |       this->create_dte_dce_(); | ||||||
|       while (!this->modem_ready()) { |       while (!this->modem_ready()) { | ||||||
|         delay(500);  // NOLINT |         delay(500);  // NOLINT | ||||||
|         ESP_LOGV(TAG, "Waiting for modem to be ready after poweron..."); |         ESP_LOGV(TAG, "Waiting for modem to be ready after poweron..."); | ||||||
| @@ -497,35 +528,37 @@ void ModemComponent::poweron_() { | |||||||
|  |  | ||||||
| void ModemComponent::poweroff_() { | void ModemComponent::poweroff_() { | ||||||
| #ifdef USE_MODEM_POWER | #ifdef USE_MODEM_POWER | ||||||
|   if (this->get_power_status()) { |   // if (this->get_power_status()) { | ||||||
|     if (this->power_pin_) { |   if (this->power_pin_) { | ||||||
|       ESP_LOGV(TAG, "Powering off modem with power pin..."); |     ESP_LOGV(TAG, "Powering off modem with power pin..."); | ||||||
|       this->power_transition_ = true; |     this->power_transition_ = true; | ||||||
|  |     Watchdog wdt(60); | ||||||
|  |     this->power_pin_->digital_write(true); | ||||||
|  |     delay(10); | ||||||
|  |     this->power_pin_->digital_write(false); | ||||||
|  |     delay(USE_MODEM_POWER_TOFF); | ||||||
|  |     this->power_pin_->digital_write(true); | ||||||
|  |  | ||||||
|  |     ESP_LOGD(TAG, "Will check that the modem is off in %.1fs...", float(USE_MODEM_POWER_TOFFUART) / 1000); | ||||||
|  |     this->set_timeout("wait_poweroff", USE_MODEM_POWER_TOFFUART, [this]() { | ||||||
|       Watchdog wdt(60); |       Watchdog wdt(60); | ||||||
|       this->power_pin_->digital_write(true); |  | ||||||
|       delay(10); |  | ||||||
|       this->power_pin_->digital_write(false); |  | ||||||
|       delay(USE_MODEM_POWER_TOFF); |  | ||||||
|       this->power_pin_->digital_write(true); |  | ||||||
|  |  | ||||||
|       ESP_LOGD(TAG, "Will check that the modem is off in %.1fs...", float(USE_MODEM_POWER_TOFFUART) / 1000); |       // while (this->get_power_status()) { | ||||||
|       this->set_timeout("wait_poweron", USE_MODEM_POWER_TOFFUART, [this]() { |       //   delay(this->command_delay_); | ||||||
|         Watchdog wdt(60); |       // } | ||||||
|  |       assert(!this->modem_ready()); | ||||||
|         while (this->get_power_status()) { |       ESP_LOGV(TAG, "Modem OFF"); | ||||||
|           delay(this->command_delay_); |       this->power_transition_ = false; | ||||||
|         } |     }); | ||||||
|         ESP_LOGV(TAG, "Modem OFF"); |  | ||||||
|         this->power_transition_ = false; |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |   // } | ||||||
| #endif  // USE_MODEM_POWER | #endif  // USE_MODEM_POWER | ||||||
| } | } | ||||||
|  |  | ||||||
| void ModemComponent::dump_connect_params_() { | void ModemComponent::dump_connect_params_() { | ||||||
|   esp_netif_ip_info_t ip; |   esp_netif_ip_info_t ip; | ||||||
|   esp_netif_get_ip_info(this->ppp_netif_, &ip); |   esp_netif_get_ip_info(this->ppp_netif_, &ip); | ||||||
|  |   ESP_LOGCONFIG(TAG, "Modem connection:"); | ||||||
|   ESP_LOGCONFIG(TAG, "  IP Address: %s", network::IPAddress(&ip.ip).str().c_str()); |   ESP_LOGCONFIG(TAG, "  IP Address: %s", network::IPAddress(&ip.ip).str().c_str()); | ||||||
|   ESP_LOGCONFIG(TAG, "  Hostname: '%s'", App.get_name().c_str()); |   ESP_LOGCONFIG(TAG, "  Hostname: '%s'", App.get_name().c_str()); | ||||||
|   ESP_LOGCONFIG(TAG, "  Subnet: %s", network::IPAddress(&ip.netmask).str().c_str()); |   ESP_LOGCONFIG(TAG, "  Subnet: %s", network::IPAddress(&ip.netmask).str().c_str()); | ||||||
| @@ -580,13 +613,13 @@ bool ModemComponent::get_imei(std::string &result) { | |||||||
| bool ModemComponent::modem_ready() { | bool ModemComponent::modem_ready() { | ||||||
|   // check if the modem is ready to answer AT commands |   // check if the modem is ready to answer AT commands | ||||||
|   std::string imei; |   std::string imei; | ||||||
|   bool status; |   // bool status; | ||||||
|   { |   // { | ||||||
|     // Temp increase watchdog timout |   //   // Temp increase watchdog timout. // FIXME infinite loop if while(!this->modem_ready()) | ||||||
|     Watchdog wdt(60); |   //   Watchdog wdt(60); | ||||||
|     status = this->get_imei(imei); |   //   status = this->get_imei(imei); | ||||||
|   } |   // } | ||||||
|   return status; |   return this->get_imei(imei); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ModemComponent::add_on_state_callback(std::function<void(ModemComponentState)> &&callback) { | void ModemComponent::add_on_state_callback(std::function<void(ModemComponentState)> &&callback) { | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  | #ifdef USE_ESP_IDF | ||||||
|  |  | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "esphome/core/component.h" | #include "esphome/core/component.h" | ||||||
| @@ -7,8 +8,6 @@ | |||||||
| #include "esphome/core/automation.h" | #include "esphome/core/automation.h" | ||||||
| #include "esphome/components/network/util.h" | #include "esphome/components/network/util.h" | ||||||
|  |  | ||||||
| #ifdef USE_ESP_IDF |  | ||||||
|  |  | ||||||
| // esp_modem will use esphome logger (needed if other components include esphome/core/log.h) | // esp_modem will use esphome logger (needed if other components include esphome/core/log.h) | ||||||
| // We need to do this because "cxx_include/esp_modem_api.hpp" is not a pure C++ header, and use logging. | // We need to do this because "cxx_include/esp_modem_api.hpp" is not a pure C++ header, and use logging. | ||||||
| // FIXME: Find another workaround ?. | // FIXME: Find another workaround ?. | ||||||
| @@ -54,8 +53,8 @@ class ModemComponent : public Component { | |||||||
|   void set_use_address(const std::string &use_address); |   void set_use_address(const std::string &use_address); | ||||||
|   void set_rx_pin(InternalGPIOPin *rx_pin) { this->rx_pin_ = rx_pin; } |   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_tx_pin(InternalGPIOPin *tx_pin) { this->tx_pin_ = tx_pin; } | ||||||
|   void set_power_pin(InternalGPIOPin *power_pin) { this->power_pin_ = power_pin; } |   void set_power_pin(GPIOPin *power_pin) { this->power_pin_ = power_pin; } | ||||||
|   void set_status_pin(InternalGPIOPin *status_pin) { this->status_pin_ = status_pin; } |   void set_status_pin(GPIOPin *status_pin) { this->status_pin_ = status_pin; } | ||||||
|   void set_username(const std::string &username) { this->username_ = username; } |   void set_username(const std::string &username) { this->username_ = username; } | ||||||
|   void set_password(const std::string &password) { this->password_ = password; } |   void set_password(const std::string &password) { this->password_ = password; } | ||||||
|   void set_pin_code(const std::string &pin_code) { this->pin_code_ = pin_code; } |   void set_pin_code(const std::string &pin_code) { this->pin_code_ = pin_code; } | ||||||
| @@ -70,9 +69,10 @@ class ModemComponent : public Component { | |||||||
|   void disable(); |   void disable(); | ||||||
|   void add_on_state_callback(std::function<void(ModemComponentState)> &&callback); |   void add_on_state_callback(std::function<void(ModemComponentState)> &&callback); | ||||||
|   std::unique_ptr<DCE> dce{nullptr}; |   std::unique_ptr<DCE> dce{nullptr}; | ||||||
|  |   uint8_t get_cmux_vt_states(); | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   void reset_();  // (re)create dte and dce |   void create_dte_dce_();  // (re)create dte and dce | ||||||
|   bool prepare_sim_(); |   bool prepare_sim_(); | ||||||
|   void send_init_at_(); |   void send_init_at_(); | ||||||
|   void start_connect_(); |   void start_connect_(); | ||||||
| @@ -83,8 +83,8 @@ class ModemComponent : public Component { | |||||||
|   void exit_cmux_(); |   void exit_cmux_(); | ||||||
|   InternalGPIOPin *tx_pin_; |   InternalGPIOPin *tx_pin_; | ||||||
|   InternalGPIOPin *rx_pin_; |   InternalGPIOPin *rx_pin_; | ||||||
|   InternalGPIOPin *status_pin_{nullptr}; |   GPIOPin *status_pin_{nullptr}; | ||||||
|   InternalGPIOPin *power_pin_{nullptr}; |   GPIOPin *power_pin_{nullptr}; | ||||||
|   std::string pin_code_; |   std::string pin_code_; | ||||||
|   std::string username_; |   std::string username_; | ||||||
|   std::string password_; |   std::string password_; | ||||||
| @@ -95,6 +95,7 @@ class ModemComponent : public Component { | |||||||
|   esp_modem_dte_config_t dte_config_; |   esp_modem_dte_config_t dte_config_; | ||||||
|   esp_modem_dce_config_t dce_config_; |   esp_modem_dce_config_t dce_config_; | ||||||
|   ModemComponentState state_{ModemComponentState::DISABLED}; |   ModemComponentState state_{ModemComponentState::DISABLED}; | ||||||
|  |   bool cmux_{false}; | ||||||
|   bool start_{false}; |   bool start_{false}; | ||||||
|   bool enabled_{false}; |   bool enabled_{false}; | ||||||
|   bool connected_{false}; |   bool connected_{false}; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user