power & status WIP

This commit is contained in:
oarcher 2024-07-22 18:49:17 +02:00
parent ca55ed7b4b
commit 7b5fe70cf6
3 changed files with 104 additions and 0 deletions

View file

@ -26,6 +26,9 @@ CONFLICTS_WITH = ["wifi", "captive_portal", "ethernet"]
CONF_PIN_CODE = "pin_code" CONF_PIN_CODE = "pin_code"
CONF_APN = "apn" CONF_APN = "apn"
CONF_DTR_PIN = "dtr_pin" CONF_DTR_PIN = "dtr_pin"
CONF_STATUS_PIN = "status_pin"
CONF_POWER_PIN = "power_pin"
CONF_FLIGTH_PIN = "flight_pin"
CONF_INIT_AT = "init_at" CONF_INIT_AT = "init_at"
CONF_ON_NOT_RESPONDING = "on_not_responding" CONF_ON_NOT_RESPONDING = "on_not_responding"
@ -51,6 +54,8 @@ CONFIG_SCHEMA = cv.All(
cv.Required(CONF_RX_PIN): pins.internal_gpio_output_pin_schema, cv.Required(CONF_RX_PIN): pins.internal_gpio_output_pin_schema,
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_STATUS_PIN): pins.internal_gpio_input_pin_schema,
cv.Optional(CONF_POWER_PIN): pins.internal_gpio_output_pin_schema,
cv.Optional(CONF_DTR_PIN): pins.internal_gpio_output_pin_schema, cv.Optional(CONF_DTR_PIN): pins.internal_gpio_output_pin_schema,
cv.Optional(CONF_PIN_CODE): cv.string_strict, cv.Optional(CONF_PIN_CODE): cv.string_strict,
cv.Optional(CONF_USERNAME): cv.string, cv.Optional(CONF_USERNAME): cv.string,
@ -140,6 +145,14 @@ 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 status_pin := config.get(CONF_STATUS_PIN, None):
pin = await cg.gpio_pin_expression(status_pin)
cg.add(var.set_status_pin(pin))
if power_pin := config.get(CONF_POWER_PIN, None):
pin = await cg.gpio_pin_expression(power_pin)
cg.add(var.set_power_pin(pin))
for conf in config.get(CONF_ON_NOT_RESPONDING, []): for conf in config.get(CONF_ON_NOT_RESPONDING, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf) await automation.build_automation(trigger, [], conf)

View file

@ -113,6 +113,31 @@ void ModemComponent::setup() {
this->reset_(); this->reset_();
if (this->power_pin_) {
this->power_pin_->setup();
delay(100); // NOLINT
// this->power_pin_->digital_write(false);
}
if (this->status_pin_) {
this->status_pin_->setup();
delay(100); // NOLINT
if (this->get_power_status()) {
ESP_LOGI(TAG, "Modem is ON");
this->poweroff();
} else {
ESP_LOGI(TAG, "Modem is OFF");
this->poweron();
}
}
if (this->modem_ready()) {
ESP_LOGD(TAG, "modem ready at setup");
} else {
ESP_LOGD(TAG, "modem not ready at setup");
}
ESP_LOGV(TAG, "Setup finished"); ESP_LOGV(TAG, "Setup finished");
} }
@ -168,6 +193,7 @@ void ModemComponent::reset_() {
assert(this->dce); assert(this->dce);
// flow control not fully implemented, but kept here for future work
if (this->dte_config_.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { if (this->dte_config_.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
if (command_result::OK != this->dce->set_flow_control(2, 2)) { if (command_result::OK != this->dce->set_flow_control(2, 2)) {
ESP_LOGE(TAG, "Failed to set the set_flow_control mode"); ESP_LOGE(TAG, "Failed to set the set_flow_control mode");
@ -180,6 +206,7 @@ void ModemComponent::reset_() {
if (this->enabled_ && !this->modem_ready()) { if (this->enabled_ && !this->modem_ready()) {
ESP_LOGW(TAG, "Here..."); ESP_LOGW(TAG, "Here...");
// if the esp has rebooted, but the modem not, it is still in cmux mode // if the esp has rebooted, but the modem not, it is still in cmux mode
// So we close cmux. // So we close cmux.
// The drawback is that if the modem is poweroff, those commands will take some time to execute. // The drawback is that if the modem is poweroff, those commands will take some time to execute.
@ -424,6 +451,63 @@ void ModemComponent::disable() {
} }
} }
bool ModemComponent::get_power_status() {
if (!this->status_pin_) {
ESP_LOGV(TAG, "No status pin, assuming the modem is ON");
return true;
}
bool init_status = this->status_pin_->digital_read();
// The status pin might be floating when supposed to be low, at least on lilygo tsim7600
// 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);
}
ESP_LOGV(TAG, "power status: %d", final_status);
return final_status;
}
void ModemComponent::poweron() {
if (this->power_pin_) {
Watchdog wdt(60);
this->power_pin_->digital_write(0);
delay(10);
this->power_pin_->digital_write(1);
delay(1010);
this->power_pin_->digital_write(0);
while (!this->get_power_status()) {
delay(this->command_delay_);
ESP_LOGV(TAG, "Waiting for modem to poweron");
}
while (!this->modem_ready()) {
delay(500); // NOLINT
ESP_LOGV(TAG, "Waiting for modem to be ready after poweron");
}
}
}
void ModemComponent::poweroff() {
if (this->get_power_status()) {
if (this->power_pin_) {
ESP_LOGV(TAG, "Modem poweroff with power pin");
Watchdog wdt(60);
this->power_pin_->digital_write(false);
delay(2600); // NOLINT
this->power_pin_->digital_write(true);
while (this->get_power_status()) {
delay(this->command_delay_);
ESP_LOGV(TAG, "Waiting for modem to poweroff");
}
} else {
ESP_LOGD(TAG, "Modem poweroff with AT command (TODO)");
}
}
}
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);

View file

@ -56,6 +56,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_status_pin(InternalGPIOPin *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; }
@ -67,6 +69,9 @@ class ModemComponent : public Component {
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); }
std::string send_at(const std::string &cmd); std::string send_at(const std::string &cmd);
bool get_imei(std::string &result); bool get_imei(std::string &result);
bool get_power_status();
void poweron();
void poweroff();
bool modem_ready(); bool modem_ready();
void enable(); void enable();
void disable(); void disable();
@ -77,6 +82,8 @@ class ModemComponent : public Component {
void reset_(); // (re)create dte and dce void reset_(); // (re)create dte and dce
InternalGPIOPin *tx_pin_; InternalGPIOPin *tx_pin_;
InternalGPIOPin *rx_pin_; InternalGPIOPin *rx_pin_;
InternalGPIOPin *status_pin_{nullptr};
InternalGPIOPin *power_pin_{nullptr};
std::string pin_code_; std::string pin_code_;
std::string username_; std::string username_;
std::string password_; std::string password_;