removed power management

This commit is contained in:
oarcher 2024-05-16 19:57:49 +02:00
parent c4cdea0a9f
commit ab88916988
3 changed files with 32 additions and 159 deletions

View file

@ -11,6 +11,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.core import coroutine_with_priority from esphome.core import coroutine_with_priority
from esphome.components.esp32 import add_idf_component, add_idf_sdkconfig_option from esphome.components.esp32 import add_idf_component, add_idf_sdkconfig_option
from esphome.components.binary_sensor import BinarySensor
CODEOWNERS = ["@oarcher"] CODEOWNERS = ["@oarcher"]
DEPENDENCIES = ["esp32"] DEPENDENCIES = ["esp32"]
@ -23,6 +24,7 @@ CONF_APN = "apn"
CONF_STATUS_PIN = "status_pin" CONF_STATUS_PIN = "status_pin"
CONF_DTR_PIN = "dtr_pin" CONF_DTR_PIN = "dtr_pin"
CONF_INIT_AT = "init_at" CONF_INIT_AT = "init_at"
CONF_READY = "ready"
modem_ns = cg.esphome_ns.namespace("modem") modem_ns = cg.esphome_ns.namespace("modem")
@ -37,6 +39,7 @@ CONFIG_SCHEMA = cv.All(
cv.Required(CONF_RX_PIN): cv.positive_int, cv.Required(CONF_RX_PIN): cv.positive_int,
cv.Required(CONF_MODEL): cv.string, cv.Required(CONF_MODEL): cv.string,
cv.Required(CONF_APN): cv.string, cv.Required(CONF_APN): cv.string,
cv.Optional(CONF_READY): cv.use_id(BinarySensor),
cv.Optional(CONF_FLIGHT_PIN): cv.positive_int, cv.Optional(CONF_FLIGHT_PIN): cv.positive_int,
cv.Optional(CONF_POWER_PIN): cv.positive_int, cv.Optional(CONF_POWER_PIN): cv.positive_int,
cv.Optional(CONF_STATUS_PIN): cv.positive_int, cv.Optional(CONF_STATUS_PIN): cv.positive_int,
@ -96,6 +99,10 @@ async def to_code(config):
for cmd in init_at: for cmd in init_at:
cg.add(var.add_init_at_command(cmd)) cg.add(var.add_init_at_command(cmd))
if modem_ready := config.get(CONF_READY, None):
modem_ready_sensor = await cg.get_variable(modem_ready)
cg.add(var.set_ready_bsensor(modem_ready_sensor))
cg.add(var.set_model(config[CONF_MODEL])) cg.add(var.set_model(config[CONF_MODEL]))
cg.add(var.set_apn(config[CONF_APN])) cg.add(var.set_apn(config[CONF_APN]))

View file

@ -74,13 +74,6 @@ 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...");
this->config_gpio_();
if (this->get_status()) {
// at setup, the modem must be down
this->powerdown();
}
ESP_LOGV(TAG, "DTE setup"); 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;
@ -152,30 +145,6 @@ void ModemComponent::setup() {
assert(this->dce); assert(this->dce);
this->poweron();
esp_modem::command_result res;
res = this->dce->sync();
int retry = 0;
while (res != command_result::OK) {
res = this->dce->sync();
if (res != command_result::OK) {
App.feed_wdt();
vTaskDelay(pdMS_TO_TICKS(1000));
}
retry++;
if (retry > 20)
break;
}
// send initial AT commands from yaml
for (const auto &cmd : this->init_at_commands_) {
std::string result;
command_result err = this->dce->at(cmd.c_str(), result, 1000);
delay(100);
ESP_LOGI(TAG, "Init AT command: %s (status %d) -> %s", cmd.c_str(), (int) err, result.c_str());
}
this->started_ = true; this->started_ = true;
ESP_LOGV(TAG, "Setup finished"); ESP_LOGV(TAG, "Setup finished");
} }
@ -184,19 +153,9 @@ void ModemComponent::start_connect_() {
this->connect_begin_ = millis(); this->connect_begin_ = millis();
this->status_set_warning("Starting connection"); this->status_set_warning("Starting connection");
if (!this->get_status()) {
this->poweron();
}
// esp_err_t err;
// err = esp_netif_set_hostname(this->ppp_netif_, App.get_name().c_str());
// if (err != ERR_OK) {
// ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
// }
global_modem_component->got_ipv4_address_ = false; // why not this ? global_modem_component->got_ipv4_address_ = false; // why not this ?
this->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND); this->dce->set_mode(modem_mode::COMMAND_MODE);
vTaskDelay(pdMS_TO_TICKS(2000)); vTaskDelay(pdMS_TO_TICKS(2000));
command_result res = command_result::TIMEOUT; command_result res = command_result::TIMEOUT;
@ -205,7 +164,6 @@ void ModemComponent::start_connect_() {
if (res != command_result::OK) { if (res != command_result::OK) {
ESP_LOGW(TAG, "Unable to sync modem. Will retry later"); ESP_LOGW(TAG, "Unable to sync modem. Will retry later");
this->powerdown();
return; return;
} }
@ -240,13 +198,20 @@ void ModemComponent::start_connect_() {
return; return;
} }
vTaskDelay(pdMS_TO_TICKS(2000)); vTaskDelay(pdMS_TO_TICKS(2000));
// send initial AT commands from yaml
for (const auto &cmd : this->init_at_commands_) {
std::string result;
command_result err = this->dce->at(cmd.c_str(), result, 1000);
delay(100);
ESP_LOGI(TAG, "Init AT command: %s (status %d) -> %s", cmd.c_str(), (int) err, result.c_str());
}
} }
void ModemComponent::got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { void ModemComponent::got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
const esp_netif_ip_info_t *ip_info = &event->ip_info; const esp_netif_ip_info_t *ip_info = &event->ip_info;
ESP_LOGW(TAG, "[IP event] Got IP " IPSTR, IP2STR(&ip_info->ip)); ESP_LOGW(TAG, "[IP event] Got IP " IPSTR, IP2STR(&ip_info->ip));
vTaskDelay(pdMS_TO_TICKS(1000)); // FIXME tmp
global_modem_component->got_ipv4_address_ = true; global_modem_component->got_ipv4_address_ = true;
global_modem_component->connected_ = true; global_modem_component->connected_ = true;
} }
@ -257,14 +222,18 @@ void ModemComponent::loop() {
switch (this->state_) { switch (this->state_) {
case ModemComponentState::STOPPED: case ModemComponentState::STOPPED:
if (this->started_) { if (this->started_) {
ESP_LOGI(TAG, "Starting modem connection"); if (!this->modem_ready()) {
this->state_ = ModemComponentState::CONNECTING; break;
this->start_connect_(); } else {
ESP_LOGI(TAG, "Starting modem connection");
this->state_ = ModemComponentState::CONNECTING;
this->start_connect_();
}
} }
break; break;
case ModemComponentState::CONNECTING: case ModemComponentState::CONNECTING:
if (!this->started_) { if (!this->started_) {
ESP_LOGI(TAG, "Stopped ethernet connection"); ESP_LOGI(TAG, "Stopped modem connection");
this->state_ = ModemComponentState::STOPPED; this->state_ = ModemComponentState::STOPPED;
} else if (this->connected_) { } else if (this->connected_) {
// connection established // connection established
@ -308,101 +277,6 @@ void ModemComponent::dump_connect_params_() {
ESP_LOGCONFIG(TAG, " DNS fallback: %s", network::IPAddress(dns_fallback_ip).str().c_str()); ESP_LOGCONFIG(TAG, " DNS fallback: %s", network::IPAddress(dns_fallback_ip).str().c_str());
} }
void ModemComponent::config_gpio_() {
ESP_LOGV(TAG, "Configuring GPIOs...");
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = 0ULL;
if (this->power_pin_ != gpio_num_t::GPIO_NUM_NC) {
io_conf.pin_bit_mask = io_conf.pin_bit_mask | (1ULL << this->power_pin_);
}
if (this->flight_pin_ != gpio_num_t::GPIO_NUM_NC) {
io_conf.pin_bit_mask = io_conf.pin_bit_mask | (1ULL << this->flight_pin_);
}
if (this->dtr_pin_ != gpio_num_t::GPIO_NUM_NC) {
io_conf.pin_bit_mask = io_conf.pin_bit_mask | (1ULL << this->dtr_pin_);
}
// io_conf.pin_bit_mask = ((1ULL << this->power_pin_) | (1ULL << this->flight_pin_));
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&io_conf);
io_conf.pin_bit_mask = 0ULL;
if (this->status_pin_ != gpio_num_t::GPIO_NUM_NC) {
io_conf.pin_bit_mask = io_conf.pin_bit_mask | (1ULL << this->status_pin_);
}
io_conf.mode = GPIO_MODE_INPUT;
gpio_config(&io_conf);
}
void ModemComponent::poweron() {
ESP_LOGI(TAG, "Power on modem");
if (this->get_status()) {
ESP_LOGW(TAG, "modem is already on");
} else {
// https://github.com/Xinyuan-LilyGO/LilyGO-T-SIM7000G/issues/251
if (this->power_pin_ != gpio_num_t::GPIO_NUM_NC) {
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_ERROR_CHECK(gpio_set_level(this->power_pin_, 0)); // low = on, high = off
vTaskDelay(pdMS_TO_TICKS(10));
ESP_ERROR_CHECK(gpio_set_level(this->power_pin_, 1));
vTaskDelay(pdMS_TO_TICKS(1010));
ESP_ERROR_CHECK(gpio_set_level(this->power_pin_, 0));
vTaskDelay(pdMS_TO_TICKS(4050)); // Ton uart 4.5sec but seems to need ~7sec after hard (button) reset
int retry = 0;
while (!this->get_status()) {
vTaskDelay(pdMS_TO_TICKS(1000));
retry++;
if (retry > 10) {
ESP_LOGW(TAG, "Unable to power on modem");
break;
}
}
} else {
ESP_LOGW(TAG, "No power pin defined. Trying to continue");
}
}
if (this->flight_pin_ != gpio_num_t::GPIO_NUM_NC) {
ESP_ERROR_CHECK(gpio_set_level(this->flight_pin_, 1)); // need to be high
} else {
ESP_LOGW(TAG, "No flight pin defined. Trying to continue");
}
if (this->dtr_pin_ != gpio_num_t::GPIO_NUM_NC) {
ESP_ERROR_CHECK(gpio_set_level(this->dtr_pin_, 1));
} else {
ESP_LOGW(TAG, "No dtr pin defined. Trying to continue");
}
vTaskDelay(pdMS_TO_TICKS(15000));
App.feed_wdt();
}
void ModemComponent::powerdown() {
ESP_LOGI(TAG, "Power down modem");
if (this->get_status()) {
// https://github.com/Xinyuan-LilyGO/T-SIM7600X/blob/master/examples/PowefOffModem/PowefOffModem.ino#L69-L71
ESP_ERROR_CHECK(gpio_set_level(this->power_pin_, 1));
vTaskDelay(pdMS_TO_TICKS(2600));
ESP_ERROR_CHECK(gpio_set_level(this->power_pin_, 0));
int retry = 0;
while (this->get_status()) {
vTaskDelay(pdMS_TO_TICKS(1000));
retry++;
if (retry > 20) {
ESP_LOGW(TAG, "Unable to power down modem");
break;
}
}
} else {
ESP_LOGW(TAG, "modem is already down");
}
}
} // namespace modem } // namespace modem
} // namespace esphome } // namespace esphome

View file

@ -4,11 +4,14 @@
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/components/network/util.h" #include "esphome/components/network/util.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/template/binary_sensor/template_binary_sensor.h"
#ifdef USE_ESP_IDF #ifdef USE_ESP_IDF
using esphome::esp_log_printf_; // esp_modem will use esphome logger (needed if other components include // esp_modem will use esphome logger (needed if other components include esphome/core/log.h)
// 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.
using esphome::esp_log_printf_;
#include <cxx_include/esp_modem_api.hpp> #include <cxx_include/esp_modem_api.hpp>
#include <driver/gpio.h> #include <driver/gpio.h>
#include <esp_modem_config.h> #include <esp_modem_config.h>
@ -39,37 +42,27 @@ class ModemComponent : public Component {
bool is_connected(); bool is_connected();
float get_setup_priority() const override; float get_setup_priority() const override;
bool can_proceed() override; bool can_proceed() override;
void on_shutdown() override { powerdown(); }
network::IPAddresses get_ip_addresses(); network::IPAddresses get_ip_addresses();
std::string get_use_address() const; std::string get_use_address() const;
void set_use_address(const std::string &use_address); void set_use_address(const std::string &use_address);
void poweron();
void powerdown();
void set_rx_pin(gpio_num_t rx_pin) { this->rx_pin_ = rx_pin; } void set_rx_pin(gpio_num_t rx_pin) { this->rx_pin_ = rx_pin; }
void set_tx_pin(gpio_num_t tx_pin) { this->tx_pin_ = tx_pin; } void set_tx_pin(gpio_num_t tx_pin) { this->tx_pin_ = tx_pin; }
void set_power_pin(gpio_num_t power_pin) { this->power_pin_ = power_pin; }
void set_flight_pin(gpio_num_t flight_pin) { this->flight_pin_ = flight_pin; }
void set_username(const std::string username) { this->username_ = std::move(username); } void set_username(const std::string username) { this->username_ = std::move(username); }
void set_password(const std::string password) { this->password_ = std::move(password); } void set_password(const std::string password) { this->password_ = std::move(password); }
void set_pin_code(const std::string pin_code) { this->pin_code_ = std::move(pin_code); } void set_pin_code(const std::string pin_code) { this->pin_code_ = std::move(pin_code); }
void set_apn(const std::string apn) { this->apn_ = std::move(apn); } void set_apn(const std::string apn) { this->apn_ = std::move(apn); }
void set_status_pin(gpio_num_t status_pin) { this->status_pin_ = status_pin; }
void set_dtr_pin(gpio_num_t dtr_pin) { this->dtr_pin_ = dtr_pin; }
void set_model(const std::string &model) { void set_model(const std::string &model) {
this->model_ = this->modem_model_map_.count(model) ? modem_model_map_[model] : ModemModel::UNKNOWN; this->model_ = this->modem_model_map_.count(model) ? modem_model_map_[model] : ModemModel::UNKNOWN;
} }
void set_ready_bsensor(binary_sensor::BinarySensor *modem_ready) { this->modem_ready_ = modem_ready; }
void add_init_at_command(const std::string &cmd) { this->init_at_commands_.push_back(cmd); } void add_init_at_command(const std::string &cmd) { this->init_at_commands_.push_back(cmd); }
bool get_status() { return gpio_get_level(this->status_pin_); } bool modem_ready() { return this->modem_ready_->state; }
std::unique_ptr<DCE> dce; std::unique_ptr<DCE> dce;
protected: protected:
gpio_num_t rx_pin_ = gpio_num_t::GPIO_NUM_NC; gpio_num_t rx_pin_ = gpio_num_t::GPIO_NUM_NC;
gpio_num_t tx_pin_ = gpio_num_t::GPIO_NUM_NC; gpio_num_t tx_pin_ = gpio_num_t::GPIO_NUM_NC;
gpio_num_t power_pin_ = gpio_num_t::GPIO_NUM_NC; binary_sensor::BinarySensor *modem_ready_;
gpio_num_t flight_pin_ = gpio_num_t::GPIO_NUM_NC;
gpio_num_t status_pin_ = gpio_num_t::GPIO_NUM_NC;
gpio_num_t dtr_pin_ = gpio_num_t::GPIO_NUM_NC;
std::string pin_code_; std::string pin_code_;
std::string username_; std::string username_;
std::string password_; std::string password_;
@ -94,7 +87,6 @@ class ModemComponent : public Component {
static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
void dump_connect_params_(); void dump_connect_params_();
std::string use_address_; std::string use_address_;
void config_gpio_();
}; };
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)