mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 17:27:59 +01:00
baud rate
This commit is contained in:
parent
def2be4b83
commit
8681a5b302
4 changed files with 155 additions and 102 deletions
|
@ -7,6 +7,7 @@ from esphome.components.esp32 import add_idf_component, add_idf_sdkconfig_option
|
||||||
# from esphome.components.wifi import wifi_has_sta # uncomment after PR#4091 merged
|
# from esphome.components.wifi import wifi_has_sta # uncomment after PR#4091 merged
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
|
CONF_BAUD_RATE,
|
||||||
CONF_DEBUG,
|
CONF_DEBUG,
|
||||||
CONF_ENABLE_ON_BOOT,
|
CONF_ENABLE_ON_BOOT,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
|
@ -79,6 +80,7 @@ CONFIG_SCHEMA = cv.All(
|
||||||
cv.GenerateID(CONF_ID): cv.declare_id(ModemComponent),
|
cv.GenerateID(CONF_ID): cv.declare_id(ModemComponent),
|
||||||
cv.Required(CONF_TX_PIN): pins.internal_gpio_output_pin_schema,
|
cv.Required(CONF_TX_PIN): pins.internal_gpio_output_pin_schema,
|
||||||
cv.Required(CONF_RX_PIN): pins.internal_gpio_output_pin_schema,
|
cv.Required(CONF_RX_PIN): pins.internal_gpio_output_pin_schema,
|
||||||
|
cv.Optional(CONF_BAUD_RATE): cv.positive_int,
|
||||||
cv.Required(CONF_MODEL): cv.one_of(*MODEM_MODELS, upper=True),
|
cv.Required(CONF_MODEL): cv.one_of(*MODEM_MODELS, upper=True),
|
||||||
cv.Required(CONF_APN): cv.string,
|
cv.Required(CONF_APN): cv.string,
|
||||||
cv.Optional(CONF_STATUS_PIN): pins.gpio_input_pin_schema,
|
cv.Optional(CONF_STATUS_PIN): pins.gpio_input_pin_schema,
|
||||||
|
@ -166,8 +168,8 @@ async def to_code(config):
|
||||||
# If Uart queue full message ( A7672 ), those config option might be changed
|
# If Uart queue full message ( A7672 ), those config option might be changed
|
||||||
# https://github.com/espressif/esp-protocols/issues/272#issuecomment-1558682967
|
# https://github.com/espressif/esp-protocols/issues/272#issuecomment-1558682967
|
||||||
add_idf_sdkconfig_option("CONFIG_ESP_MODEM_CMUX_DEFRAGMENT_PAYLOAD", True)
|
add_idf_sdkconfig_option("CONFIG_ESP_MODEM_CMUX_DEFRAGMENT_PAYLOAD", True)
|
||||||
add_idf_sdkconfig_option("ESP_MODEM_USE_INFLATABLE_BUFFER_IF_NEEDED", True)
|
add_idf_sdkconfig_option("CONFIG_ESP_MODEM_USE_INFLATABLE_BUFFER_IF_NEEDED", True)
|
||||||
add_idf_sdkconfig_option("ESP_MODEM_CMUX_USE_SHORT_PAYLOADS_ONLY", False)
|
add_idf_sdkconfig_option("CONFIG_ESP_MODEM_CMUX_USE_SHORT_PAYLOADS_ONLY", False)
|
||||||
|
|
||||||
cg.add_define("USE_MODEM")
|
cg.add_define("USE_MODEM")
|
||||||
|
|
||||||
|
@ -218,6 +220,9 @@ async def to_code(config):
|
||||||
rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN])
|
rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN])
|
||||||
cg.add(var.set_rx_pin(rx_pin))
|
cg.add(var.set_rx_pin(rx_pin))
|
||||||
|
|
||||||
|
if baud_rate := config.get(CONF_BAUD_RATE, None):
|
||||||
|
cg.add(var.set_baud_rate(baud_rate))
|
||||||
|
|
||||||
if status_pin := config.get(CONF_STATUS_PIN, None):
|
if status_pin := config.get(CONF_STATUS_PIN, None):
|
||||||
pin = await cg.gpio_pin_expression(status_pin)
|
pin = await cg.gpio_pin_expression(status_pin)
|
||||||
cg.add(var.set_status_pin(pin))
|
cg.add(var.set_status_pin(pin))
|
||||||
|
|
|
@ -48,11 +48,7 @@ ModemComponent::ModemComponent() {
|
||||||
global_modem_component = this;
|
global_modem_component = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemComponent::enable_debug() {
|
void ModemComponent::enable_debug() { esp_log_level_set("command_lib", ESP_LOG_VERBOSE); }
|
||||||
esp_log_level_set("command_lib", ESP_LOG_VERBOSE);
|
|
||||||
// esp_log_level_set("CMUX", ESP_LOG_VERBOSE);
|
|
||||||
// esp_log_level_set("CMUX Received", ESP_LOG_VERBOSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModemComponent::is_modem_connected(bool verbose) {
|
bool ModemComponent::is_modem_connected(bool verbose) {
|
||||||
float rssi, ber;
|
float rssi, ber;
|
||||||
|
@ -98,6 +94,8 @@ AtCommandResult ModemComponent::get_imei() {
|
||||||
} else {
|
} else {
|
||||||
at_command_result.success = false;
|
at_command_result.success = false;
|
||||||
}
|
}
|
||||||
|
ESP_LOGV(TAG, "imei: %s (status: %s)", at_command_result.c_str(),
|
||||||
|
command_result_to_string(at_command_result.esp_modem_command_result).c_str());
|
||||||
return at_command_result;
|
return at_command_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,25 +112,28 @@ bool ModemComponent::get_power_status() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ModemComponent::sync() {
|
||||||
|
this->internal_state_.modem_synced = this->get_imei();
|
||||||
|
if (this->internal_state_.modem_synced)
|
||||||
|
this->internal_state_.powered_on = true;
|
||||||
|
return this->internal_state_.modem_synced;
|
||||||
|
}
|
||||||
|
|
||||||
bool ModemComponent::modem_ready(bool force_check) {
|
bool ModemComponent::modem_ready(bool force_check) {
|
||||||
// check if the modem is ready to answer AT commands
|
// check if the modem is ready to answer AT commands
|
||||||
// We first try to check flags, and then really send an AT command if force_check
|
// We first try to check flags, and then really send an AT command if force_check
|
||||||
|
|
||||||
if (!this->dce)
|
|
||||||
return false;
|
|
||||||
if (!this->internal_state_.modem_synced)
|
if (!this->internal_state_.modem_synced)
|
||||||
return false;
|
return false;
|
||||||
if (!this->cmux_ && this->internal_state_.connected)
|
if (!this->cmux_ && this->internal_state_.connected)
|
||||||
return false;
|
return false;
|
||||||
if (!this->internal_state_.powered_on)
|
if (!this->internal_state_.powered_on)
|
||||||
return false;
|
return false;
|
||||||
#ifdef USE_MODEM_POWER
|
|
||||||
if (this->internal_state_.power_transition)
|
if (this->internal_state_.power_transition)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (force_check) {
|
if (force_check) {
|
||||||
if (this->get_imei()) {
|
if (this->sync()) {
|
||||||
// we are sure that the modem is on
|
// we are sure that the modem is on
|
||||||
this->internal_state_.powered_on = true;
|
this->internal_state_.powered_on = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -142,8 +143,6 @@ bool ModemComponent::modem_ready(bool force_check) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModemComponent::modem_ready() { return this->modem_ready(false); }
|
|
||||||
|
|
||||||
void ModemComponent::enable() {
|
void ModemComponent::enable() {
|
||||||
ESP_LOGD(TAG, "Enabling modem");
|
ESP_LOGD(TAG, "Enabling modem");
|
||||||
if (this->component_state_ == ModemComponentState::DISABLED) {
|
if (this->component_state_ == ModemComponentState::DISABLED) {
|
||||||
|
@ -259,7 +258,7 @@ void ModemComponent::setup() {
|
||||||
nullptr);
|
nullptr);
|
||||||
ESPHL_ERROR_CHECK(err, "IP event handler register error");
|
ESPHL_ERROR_CHECK(err, "IP event handler register error");
|
||||||
|
|
||||||
this->modem_lazy_init_();
|
this->modem_create_dce_dte_(); // real init will be done by enable
|
||||||
|
|
||||||
ESP_LOGV(TAG, "Setup finished");
|
ESP_LOGV(TAG, "Setup finished");
|
||||||
}
|
}
|
||||||
|
@ -291,7 +290,7 @@ void ModemComponent::loop() {
|
||||||
break;
|
break;
|
||||||
case ModemPowerState::TONUART:
|
case ModemPowerState::TONUART:
|
||||||
ESP_LOGD(TAG, "TONUART check sync");
|
ESP_LOGD(TAG, "TONUART check sync");
|
||||||
if (!this->modem_sync_()) {
|
if (!this->modem_init_()) {
|
||||||
ESP_LOGE(TAG, "Unable to power on the modem");
|
ESP_LOGE(TAG, "Unable to power on the modem");
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "Modem powered ON");
|
ESP_LOGI(TAG, "Modem powered ON");
|
||||||
|
@ -329,8 +328,8 @@ void ModemComponent::loop() {
|
||||||
if (this->internal_state_.starting) {
|
if (this->internal_state_.starting) {
|
||||||
ESP_LOGW(TAG, "Modem not responding, resetting...");
|
ESP_LOGW(TAG, "Modem not responding, resetting...");
|
||||||
this->internal_state_.connected = false;
|
this->internal_state_.connected = false;
|
||||||
// this->modem_lazy_init_();
|
// this->modem_create_dce_dte_();
|
||||||
if (!this->modem_sync_()) {
|
if (!this->modem_init_()) {
|
||||||
ESP_LOGE(TAG, "Unable to recover modem");
|
ESP_LOGE(TAG, "Unable to recover modem");
|
||||||
} else {
|
} else {
|
||||||
this->component_state_ = ModemComponentState::DISCONNECTED;
|
this->component_state_ = ModemComponentState::DISCONNECTED;
|
||||||
|
@ -345,7 +344,7 @@ void ModemComponent::loop() {
|
||||||
this->poweron_();
|
this->poweron_();
|
||||||
break;
|
break;
|
||||||
} else if (!this->internal_state_.modem_synced) {
|
} else if (!this->internal_state_.modem_synced) {
|
||||||
if (!this->modem_sync_()) {
|
if (!this->modem_init_()) {
|
||||||
this->component_state_ = ModemComponentState::NOT_RESPONDING;
|
this->component_state_ = ModemComponentState::NOT_RESPONDING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,15 +442,12 @@ void ModemComponent::loop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemComponent::modem_lazy_init_() {
|
void ModemComponent::modem_create_dce_dte_(int baud_rate) {
|
||||||
// destroy previous dte/dce, and recreate them.
|
// create or recreate dte and dce.
|
||||||
// no communication is done with the modem.
|
// no communication is done with the modem.
|
||||||
|
|
||||||
this->internal_state_.modem_synced = false;
|
this->internal_state_.modem_synced = false;
|
||||||
|
|
||||||
this->dte_.reset();
|
|
||||||
this->dce.reset();
|
|
||||||
|
|
||||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||||
|
|
||||||
dte_config.uart_config.tx_io_num = this->tx_pin_->get_pin();
|
dte_config.uart_config.tx_io_num = this->tx_pin_->get_pin();
|
||||||
|
@ -459,10 +455,16 @@ void ModemComponent::modem_lazy_init_() {
|
||||||
dte_config.uart_config.rx_buffer_size = this->uart_rx_buffer_size_;
|
dte_config.uart_config.rx_buffer_size = this->uart_rx_buffer_size_;
|
||||||
dte_config.uart_config.tx_buffer_size = this->uart_tx_buffer_size_;
|
dte_config.uart_config.tx_buffer_size = this->uart_tx_buffer_size_;
|
||||||
dte_config.uart_config.event_queue_size = this->uart_event_queue_size_;
|
dte_config.uart_config.event_queue_size = this->uart_event_queue_size_;
|
||||||
|
if (baud_rate != 0) {
|
||||||
|
dte_config.uart_config.baud_rate = baud_rate;
|
||||||
|
this->internal_state_.baud_rate_changed = true;
|
||||||
|
}
|
||||||
dte_config.task_stack_size = this->uart_event_task_stack_size_;
|
dte_config.task_stack_size = this->uart_event_task_stack_size_;
|
||||||
dte_config.task_priority = this->uart_event_task_priority_;
|
dte_config.task_priority = this->uart_event_task_priority_;
|
||||||
dte_config.dte_buffer_size = this->uart_rx_buffer_size_ / 2;
|
dte_config.dte_buffer_size = this->uart_rx_buffer_size_ / 2;
|
||||||
|
|
||||||
|
this->dce.reset();
|
||||||
|
this->dte_.reset();
|
||||||
this->dte_ = create_uart_dte(&dte_config);
|
this->dte_ = create_uart_dte(&dte_config);
|
||||||
|
|
||||||
if (!this->dte_->set_mode(modem_mode::COMMAND_MODE)) {
|
if (!this->dte_->set_mode(modem_mode::COMMAND_MODE)) {
|
||||||
|
@ -497,104 +499,132 @@ void ModemComponent::modem_lazy_init_() {
|
||||||
ESP_LOGV(TAG, "DTE and CDE created");
|
ESP_LOGV(TAG, "DTE and CDE created");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModemComponent::modem_sync_() {
|
bool ModemComponent::modem_preinit_() {
|
||||||
// force command mode, check sim, and send init_at commands
|
// init the modem to get command mode.
|
||||||
// close cmux/data if needed, and may reboot the modem.
|
// if baud_rate != 0, will also set the baud rate.
|
||||||
|
|
||||||
uint32_t start_ms = millis();
|
// std::string result;
|
||||||
uint32_t elapsed_ms;
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "Checking if the modem is synced...");
|
ESP_LOGV(TAG, "Checking if the modem is reachable...");
|
||||||
|
|
||||||
this->flush_uart_();
|
this->flush_uart_();
|
||||||
|
|
||||||
bool status = this->get_imei();
|
bool success = this->sync();
|
||||||
if (!status) {
|
if (!success) {
|
||||||
|
// the modem is not responding. possible causes are:
|
||||||
|
// - warm reboot, it's still in data or cmux mode.
|
||||||
|
// - has a non default baud rate
|
||||||
|
// - power off
|
||||||
|
|
||||||
|
uint32_t start_ms = millis();
|
||||||
|
uint32_t elapsed_ms;
|
||||||
|
|
||||||
// Try to exit CMUX_MANUAL_DATA or DATA_MODE, if any
|
// Try to exit CMUX_MANUAL_DATA or DATA_MODE, if any
|
||||||
ESP_LOGD(TAG, "Connecting to the the modem...");
|
ESP_LOGD(TAG, "Connecting to the the modem...");
|
||||||
watchdog::WatchdogManager wdt(30000);
|
// huge watchdog, because some commands are blocking for a very long time.
|
||||||
|
watchdog::WatchdogManager wdt(60000);
|
||||||
|
|
||||||
auto command_mode = [this]() -> bool {
|
auto command_mode = [this]() -> bool {
|
||||||
ESP_LOGVV(TAG, "trying command mode");
|
ESP_LOGV(TAG, "trying command mode");
|
||||||
this->dce->set_mode(modem_mode::UNDEF);
|
this->dce->set_mode(modem_mode::UNDEF);
|
||||||
return this->dce->set_mode(modem_mode::COMMAND_MODE) && this->get_imei();
|
return this->dce->set_mode(modem_mode::COMMAND_MODE) && this->sync();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto cmux_command_mode = [this]() -> bool {
|
auto cmux_command_mode = [this]() -> bool {
|
||||||
ESP_LOGVV(TAG, "trying cmux command mode");
|
ESP_LOGV(TAG, "trying cmux command mode");
|
||||||
return this->dce->set_mode(modem_mode::CMUX_MANUAL_MODE) &&
|
return this->dce->set_mode(modem_mode::CMUX_MANUAL_MODE) &&
|
||||||
this->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND) && this->get_imei();
|
this->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND) && this->sync();
|
||||||
};
|
};
|
||||||
|
|
||||||
// The cmux state is supposed to be the same before the reboot. But if it has changed (new firwmare), we will try
|
// The cmux state is supposed to be the same before the reboot. But if it has changed (new firwmare), we will try
|
||||||
// to fallback to inverted cmux state.
|
// to fallback to inverted cmux state.
|
||||||
if (this->cmux_) {
|
if (this->cmux_) {
|
||||||
status = cmux_command_mode() || (command_mode() && cmux_command_mode());
|
success = cmux_command_mode() || (command_mode() && cmux_command_mode());
|
||||||
} else {
|
} else {
|
||||||
status = command_mode() || (cmux_command_mode() && command_mode());
|
success = command_mode() || (cmux_command_mode() && command_mode());
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed_ms = millis() - start_ms;
|
elapsed_ms = millis() - start_ms;
|
||||||
|
|
||||||
if (!status) {
|
if (success) {
|
||||||
ESP_LOGW(TAG, "modem not responding after %" PRIu32 "ms.", elapsed_ms);
|
|
||||||
// assume the modem is OFF
|
|
||||||
this->internal_state_.powered_on = false;
|
|
||||||
} else {
|
|
||||||
ESP_LOGD(TAG, "Connected to the modem in %" PRIu32 "ms", elapsed_ms);
|
ESP_LOGD(TAG, "Connected to the modem in %" PRIu32 "ms", elapsed_ms);
|
||||||
this->internal_state_.powered_on = true;
|
} else if ((this->baud_rate_ != 0) && !this->internal_state_.baud_rate_changed) {
|
||||||
}
|
ESP_LOGD(TAG, "Failed to connected to the modem in %" PRIu32 "ms", elapsed_ms);
|
||||||
} else {
|
ESP_LOGD(TAG, "Retrying with baud rate %d", this->baud_rate_);
|
||||||
// modem responded without need to recover command mode
|
this->modem_create_dce_dte_(this->baud_rate_);
|
||||||
ESP_LOGD(TAG, "Modem already synced");
|
return this->modem_preinit_(); // recursive call, but only 1 depth
|
||||||
this->internal_state_.powered_on = true;
|
} else {
|
||||||
}
|
ESP_LOGE(TAG, "Fatal: modem not responding during init");
|
||||||
|
|
||||||
if (status && !this->internal_state_.modem_synced) {
|
|
||||||
this->internal_state_.modem_synced = true;
|
|
||||||
|
|
||||||
// First time the modem is synced, or modem recovered
|
|
||||||
App.feed_wdt();
|
|
||||||
watchdog::WatchdogManager wdt(30000);
|
|
||||||
delay(2000); // NOLINT
|
|
||||||
if (!this->get_imei()) {
|
|
||||||
ESP_LOGW(TAG, "Unable to sync modem");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->send_init_at_();
|
|
||||||
|
|
||||||
if (!this->pin_code_.empty()) {
|
|
||||||
if (!this->prepare_sim_()) {
|
|
||||||
// fatal error
|
|
||||||
this->disable();
|
|
||||||
status = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG, "No pin_code, so no pin check");
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Modem infos:");
|
|
||||||
std::string result;
|
|
||||||
ESPMODEM_ERROR_CHECK(this->dce->get_module_name(result), "get_module_name");
|
|
||||||
ESP_LOGI(TAG, " Module name: %s", result.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->internal_state_.modem_synced = status;
|
// modem synced
|
||||||
|
|
||||||
ESP_LOGVV(TAG, "Sync end status: %d", this->internal_state_.modem_synced);
|
if ((this->baud_rate_ != 0) && !this->internal_state_.baud_rate_changed) {
|
||||||
|
ESP_LOGD(TAG, "Setting baud rate: %d", this->baud_rate_);
|
||||||
|
this->dce->set_baud(this->baud_rate_);
|
||||||
|
delay(1000);
|
||||||
|
this->flush_uart_();
|
||||||
|
// need to recreate dte/dce with new baud rate
|
||||||
|
this->modem_create_dce_dte_(this->baud_rate_);
|
||||||
|
this->flush_uart_();
|
||||||
|
if (this->sync()) {
|
||||||
|
ESP_LOGI(TAG, "Modem baud rate set to %d", this->baud_rate_);
|
||||||
|
success = true;
|
||||||
|
} else {
|
||||||
|
// not able to switch to new baud rate. reset to default
|
||||||
|
this->internal_state_.baud_rate_changed = false;
|
||||||
|
this->modem_create_dce_dte_();
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->internal_state_.modem_synced = success;
|
||||||
|
this->internal_state_.powered_on = success;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
bool ModemComponent::modem_init_() {
|
||||||
|
// force command mode, check sim, and send init_at commands
|
||||||
|
// close cmux/data if needed, and may reboot the modem.
|
||||||
|
|
||||||
|
bool success = this->modem_preinit_() && this->sync();
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
ESP_LOGE(TAG, "Fatal: modem not responding");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->send_init_at_();
|
||||||
|
|
||||||
|
if (!this->pin_code_.empty()) {
|
||||||
|
if (!this->prepare_sim_()) {
|
||||||
|
ESP_LOGE(TAG, "Fatal: Sim error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "No pin_code, so no pin check");
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Modem infos:");
|
||||||
|
std::string result;
|
||||||
|
ESPMODEM_ERROR_CHECK(this->dce->get_module_name(result), "get_module_name");
|
||||||
|
ESP_LOGI(TAG, " Module name: %s", result.c_str());
|
||||||
|
|
||||||
|
success = this->sync();
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
ESP_LOGE(TAG, "Fatal: unable to init modem");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModemComponent::prepare_sim_() {
|
bool ModemComponent::prepare_sim_() {
|
||||||
command_result modem_status;
|
|
||||||
|
|
||||||
std::string output;
|
std::string output;
|
||||||
|
|
||||||
// this->dce->read_pin(pin_ok) // not used, because we can't know the cause of the error.
|
// this->dce->read_pin(pin_ok) // not used, because we can't know the cause of the error.
|
||||||
modem_status = this->dce->command(
|
this->dce->command(
|
||||||
"AT+CPIN?\r",
|
"AT+CPIN?\r",
|
||||||
[&](uint8_t *data, size_t len) {
|
[&](uint8_t *data, size_t len) {
|
||||||
output.assign(reinterpret_cast<char *>(data), len);
|
output.assign(reinterpret_cast<char *>(data), len);
|
||||||
|
@ -605,11 +635,11 @@ bool ModemComponent::prepare_sim_() {
|
||||||
|
|
||||||
ESP_LOGD(TAG, "SIM: %s", output.c_str());
|
ESP_LOGD(TAG, "SIM: %s", output.c_str());
|
||||||
|
|
||||||
if (output.find("+CPIN: READY") != std::string::npos) {
|
if ((output.find("+CPIN: READY") != std::string::npos) || (output.find("+CPIN: SIM PIN") != std::string::npos)) {
|
||||||
return true; // pin not needed or already unlocked
|
return true; // pin not needed or already unlocked
|
||||||
} else {
|
} else {
|
||||||
if (output.find("SIM not inserted") != std::string::npos) {
|
if (output.find("SIM not inserted") != std::string::npos) {
|
||||||
this->abort_("Sim card not inserted.");
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,14 +655,22 @@ void ModemComponent::send_init_at_() {
|
||||||
// send initial AT commands from yaml
|
// send initial AT commands from yaml
|
||||||
for (const auto &cmd : this->init_at_commands_) {
|
for (const auto &cmd : this->init_at_commands_) {
|
||||||
App.feed_wdt();
|
App.feed_wdt();
|
||||||
auto at_command_result = this->send_at(cmd);
|
|
||||||
if (!at_command_result) {
|
std::string output;
|
||||||
ESP_LOGE(TAG, "Error while executing 'init_at' '%s' command", cmd.c_str());
|
|
||||||
} else {
|
ESPMODEM_ERROR_CHECK(this->dce->command(
|
||||||
ESP_LOGI(TAG, "'init_at' '%s' output: %s", cmd.c_str(), at_command_result.output.c_str());
|
cmd + "\r",
|
||||||
}
|
[&](uint8_t *data, size_t len) {
|
||||||
delay(2000); // NOLINT
|
output.assign(reinterpret_cast<char *>(data), len);
|
||||||
|
std::replace(output.begin(), output.end(), '\n', ' ');
|
||||||
|
return command_result::OK;
|
||||||
|
},
|
||||||
|
2000),
|
||||||
|
"init_at");
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "init_at %s: %s", cmd.c_str(), output.c_str());
|
||||||
}
|
}
|
||||||
|
this->flush_uart_();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModemComponent::is_network_attached_() {
|
bool ModemComponent::is_network_attached_() {
|
||||||
|
@ -739,7 +777,7 @@ void ModemComponent::poweroff_() {
|
||||||
|
|
||||||
void ModemComponent::abort_(const std::string &message) {
|
void ModemComponent::abort_(const std::string &message) {
|
||||||
ESP_LOGE(TAG, "Aborting: %s", message.c_str());
|
ESP_LOGE(TAG, "Aborting: %s", message.c_str());
|
||||||
this->send_at("AT+CFUN=1,1");
|
// this->send_at("AT+CFUN=1,1");
|
||||||
App.reboot();
|
App.reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,18 +805,21 @@ void ModemComponent::dump_connect_params_() {
|
||||||
|
|
||||||
bool ModemComponent::flush_uart_() {
|
bool ModemComponent::flush_uart_() {
|
||||||
size_t cleaned = 0;
|
size_t cleaned = 0;
|
||||||
|
std::string output;
|
||||||
this->dce->command(
|
this->dce->command(
|
||||||
"",
|
"",
|
||||||
[&](uint8_t *data, size_t len) {
|
[&](uint8_t *data, size_t len) {
|
||||||
cleaned = len;
|
cleaned = len;
|
||||||
|
output.assign(reinterpret_cast<char *>(data), len);
|
||||||
|
std::replace(output.begin(), output.end(), '\n', ' ');
|
||||||
return command_result::OK;
|
return command_result::OK;
|
||||||
},
|
},
|
||||||
1000) == command_result::OK;
|
2000);
|
||||||
|
|
||||||
if (cleaned != 0) {
|
if (cleaned != 0) {
|
||||||
ESP_LOGW(TAG, "Cleaned %d modem buffer data", cleaned);
|
ESP_LOGW(TAG, "Cleaned %d modem buffer data: %s", cleaned, output.c_str());
|
||||||
}
|
}
|
||||||
|
return cleaned != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *AtCommandResult::c_str() const {
|
const char *AtCommandResult::c_str() const {
|
||||||
|
|
|
@ -58,6 +58,7 @@ class ModemComponent : public Component {
|
||||||
void set_use_address(const std::string &use_address) { this->use_address_ = 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_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_baud_rate(int baud_rate) { this->baud_rate_ = baud_rate; }
|
||||||
void set_model(const std::string &model) { this->model_ = model; }
|
void set_model(const std::string &model) { this->model_ = model; }
|
||||||
void set_power_pin(GPIOPin *power_pin) { this->power_pin_ = power_pin; }
|
void set_power_pin(GPIOPin *power_pin) { this->power_pin_ = power_pin; }
|
||||||
void set_power_ton(int ton) { this->power_ton_ = ton; }
|
void set_power_ton(int ton) { this->power_ton_ = ton; }
|
||||||
|
@ -78,7 +79,8 @@ class ModemComponent : public Component {
|
||||||
AtCommandResult send_at(const std::string &cmd, uint32_t timeout);
|
AtCommandResult send_at(const std::string &cmd, uint32_t timeout);
|
||||||
AtCommandResult get_imei();
|
AtCommandResult get_imei();
|
||||||
bool get_power_status();
|
bool get_power_status();
|
||||||
bool modem_ready();
|
bool sync();
|
||||||
|
bool modem_ready() { return this->modem_ready(false); }
|
||||||
bool modem_ready(bool force_check);
|
bool modem_ready(bool force_check);
|
||||||
void enable();
|
void enable();
|
||||||
void disable();
|
void disable();
|
||||||
|
@ -105,8 +107,10 @@ class ModemComponent : public Component {
|
||||||
std::unique_ptr<DCE> dce{nullptr};
|
std::unique_ptr<DCE> dce{nullptr};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void modem_lazy_init_();
|
void modem_create_dce_dte_(int baud_rate);
|
||||||
bool modem_sync_();
|
void modem_create_dce_dte_() { this->modem_create_dce_dte_(0); }
|
||||||
|
bool modem_preinit_();
|
||||||
|
bool modem_init_();
|
||||||
bool prepare_sim_();
|
bool prepare_sim_();
|
||||||
void send_init_at_();
|
void send_init_at_();
|
||||||
bool is_network_attached_();
|
bool is_network_attached_();
|
||||||
|
@ -147,6 +151,7 @@ class ModemComponent : public Component {
|
||||||
uint8_t uart_event_task_priority_ = 5; // 3-22
|
uint8_t uart_event_task_priority_ = 5; // 3-22
|
||||||
uint32_t command_delay_ = 1000; // timeout for AT commands
|
uint32_t command_delay_ = 1000; // timeout for AT commands
|
||||||
uint32_t reconnect_grace_period_ = 30000; // let some time to mqtt or api to reconnect before retry
|
uint32_t reconnect_grace_period_ = 30000; // let some time to mqtt or api to reconnect before retry
|
||||||
|
int baud_rate_ = 0;
|
||||||
|
|
||||||
// Changes will trigger user callback
|
// Changes will trigger user callback
|
||||||
ModemComponentState component_state_{ModemComponentState::DISABLED};
|
ModemComponentState component_state_{ModemComponentState::DISABLED};
|
||||||
|
@ -163,7 +168,7 @@ class ModemComponent : public Component {
|
||||||
bool enabled{false};
|
bool enabled{false};
|
||||||
bool connected{false};
|
bool connected{false};
|
||||||
bool got_ipv4_address{false};
|
bool got_ipv4_address{false};
|
||||||
// true if modem_sync_ was sucessfull
|
// true if modem_init_ was sucessfull
|
||||||
bool modem_synced{false};
|
bool modem_synced{false};
|
||||||
// date start (millis())
|
// date start (millis())
|
||||||
uint32_t connect_begin;
|
uint32_t connect_begin;
|
||||||
|
@ -175,6 +180,7 @@ class ModemComponent : public Component {
|
||||||
ModemPowerState power_state{ModemPowerState::TOFFUART};
|
ModemPowerState power_state{ModemPowerState::TOFFUART};
|
||||||
// ask the modem to reconnect
|
// ask the modem to reconnect
|
||||||
bool reconnect{false};
|
bool reconnect{false};
|
||||||
|
bool baud_rate_changed{false};
|
||||||
};
|
};
|
||||||
InternalState internal_state_;
|
InternalState internal_state_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ modem:
|
||||||
id: atmodem
|
id: atmodem
|
||||||
rx_pin: GPIO26
|
rx_pin: GPIO26
|
||||||
tx_pin: GPIO27
|
tx_pin: GPIO27
|
||||||
|
baud_rate: 115200
|
||||||
power_pin:
|
power_pin:
|
||||||
number: GPIO04
|
number: GPIO04
|
||||||
inverted: True
|
inverted: True
|
||||||
|
|
Loading…
Reference in a new issue