common exit_cmux_

This commit is contained in:
oarcher 2024-07-23 00:26:23 +02:00
parent 971fbd6d26
commit adad7469e5
2 changed files with 35 additions and 43 deletions

View file

@ -120,6 +120,10 @@ void ModemComponent::setup() {
} }
this->reset_(); this->reset_();
// 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");
} }
@ -127,6 +131,7 @@ void ModemComponent::setup() {
void ModemComponent::reset_() { void ModemComponent::reset_() {
// 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();
@ -186,21 +191,6 @@ void ModemComponent::reset_() {
} else { } else {
ESP_LOGI(TAG, "not set_flow_control, because 2-wire mode active."); ESP_LOGI(TAG, "not set_flow_control, because 2-wire mode active.");
} }
if (this->enabled_ && this->get_power_status() && !this->modem_ready()) {
// if the esp has rebooted, but the modem not, it is still in cmux mode
// So we close cmux.
// The drawback is that if the modem is poweroff, those commands will take some time to execute.
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::prepare_sim_() { bool ModemComponent::prepare_sim_() {
@ -379,23 +369,12 @@ void ModemComponent::loop() {
ESP_LOGE(TAG, "modem not ready after hang up"); ESP_LOGE(TAG, "modem not ready after hang up");
} }
this->set_timeout("wait_lost_ip", 60000, [this]() { this->set_timeout("wait_lost_ip", 60000, [this]() {
this->dump_connect_params_(); this->status_set_error("No lost ip event received. Forcing disconnect state");
this->status_set_error("No lost ip event received");
this->state_ = ModemComponentState::DISCONNECTED; this->state_ = ModemComponentState::DISCONNECTED;
// This seems to be the only way to exit CMUX
this->reset_(); // reset dce/dte this->reset_(); // reset dce/dte
if (!(this->dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_MODE) && this->exit_cmux_();
this->dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_EXIT))) {
this->status_set_error("Unable to exit CMUX.");
}
if (!this->modem_ready()) {
ESP_LOGE(TAG, "modem not ready after reset");
}
///////////////////////////
}); });
} }
this->start_ = false; this->start_ = false;
@ -406,14 +385,7 @@ void ModemComponent::loop() {
// This seems to be the only way to exit CMUX // This seems to be the only way to exit CMUX
this->reset_(); // reset dce/dte this->reset_(); // reset dce/dte
if (!(this->dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_MODE) && this->exit_cmux_();
this->dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_EXIT))) {
this->status_set_error("Unable to exit CMUX.");
}
if (!this->modem_ready()) {
ESP_LOGE(TAG, "modem not ready after reset");
}
} }
break; break;
@ -455,6 +427,25 @@ 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() {
if (!this->status_pin_) { if (!this->status_pin_) {
ESP_LOGV(TAG, "No status pin, assuming the modem is ON"); ESP_LOGV(TAG, "No status pin, assuming the modem is ON");

View file

@ -78,6 +78,14 @@ class ModemComponent : public Component {
protected: protected:
void reset_(); // (re)create dte and dce void reset_(); // (re)create dte and dce
bool prepare_sim_();
void send_init_at_();
void start_connect_();
void poweron_();
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 exit_cmux_();
InternalGPIOPin *tx_pin_; InternalGPIOPin *tx_pin_;
InternalGPIOPin *rx_pin_; InternalGPIOPin *rx_pin_;
InternalGPIOPin *status_pin_{nullptr}; InternalGPIOPin *status_pin_{nullptr};
@ -98,19 +106,12 @@ 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 prepare_sim_();
void send_init_at_();
void start_connect_();
void poweron_();
void poweroff_();
bool start_{false}; bool start_{false};
bool enabled_{false}; bool enabled_{false};
bool connected_{false}; bool connected_{false};
bool got_ipv4_address_{false}; bool got_ipv4_address_{false};
// date start (millis()) // date start (millis())
uint32_t connect_begin_; uint32_t connect_begin_;
static void ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
void dump_connect_params_();
std::string use_address_; std::string use_address_;
// timeout for AT commands // timeout for AT commands
uint32_t command_delay_ = 500; uint32_t command_delay_ = 500;