gsm component

This commit is contained in:
oarcher 2024-05-11 23:01:51 +02:00
parent af3fb615ea
commit 0a01d1ef32
5 changed files with 597 additions and 1 deletions

View file

@ -0,0 +1,113 @@
from esphome.const import (
CONF_ID,
CONF_USE_ADDRESS,
CONF_TX_PIN,
CONF_RX_PIN,
CONF_USERNAME,
CONF_PASSWORD,
CONF_MODEL,
)
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.core import coroutine_with_priority
from esphome.components.esp32 import add_idf_component, add_idf_sdkconfig_option
CODEOWNERS = ["@oarcher"]
DEPENDENCIES = ["esp32"]
AUTO_LOAD = ["network"]
CONF_POWER_PIN = "power_pin"
CONF_FLIGHT_PIN = "flight_pin"
CONF_PIN_CODE = "pin_code"
CONF_APN = "apn"
CONF_STATUS_PIN = "status_pin"
CONF_DTR_PIN = "dtr_pin"
gsm_ns = cg.esphome_ns.namespace("gsm")
GSMComponent = gsm_ns.class_("GSMComponent", cg.Component)
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.GenerateID(): cv.declare_id(GSMComponent),
cv.Required(CONF_TX_PIN): cv.positive_int,
cv.Required(CONF_RX_PIN): cv.positive_int,
cv.Required(CONF_MODEL): cv.string,
cv.Required(CONF_APN): cv.string,
cv.Optional(CONF_FLIGHT_PIN): cv.positive_int,
cv.Optional(CONF_POWER_PIN): cv.positive_int,
cv.Optional(CONF_STATUS_PIN): cv.positive_int,
cv.Optional(CONF_DTR_PIN): cv.positive_int,
cv.Optional(CONF_PIN_CODE): cv.string_strict,
cv.Optional(CONF_USERNAME): cv.string,
cv.Optional(CONF_PASSWORD): cv.string,
cv.Optional(CONF_USE_ADDRESS): cv.string,
}
).extend(cv.COMPONENT_SCHEMA),
cv.require_framework_version(
esp_idf=cv.Version(4, 0, 0), # 5.2.0 OK
),
)
@coroutine_with_priority(60.0)
async def to_code(config):
add_idf_component(
name="esp_modem",
repo="https://github.com/espressif/esp-protocols.git",
ref="modem-v1.1.0",
path="components/esp_modem",
)
add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False)
add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_TIMEOUT_S", 60)
add_idf_sdkconfig_option("CONFIG_PPP", True)
add_idf_sdkconfig_option("CONFIG_LWIP_PPP_SUPPORT", True)
add_idf_sdkconfig_option("CONFIG_PPP_PAP_SUPPORT", True)
add_idf_sdkconfig_option("CONFIG_LWIP_PPP_PAP_SUPPORT", True)
add_idf_sdkconfig_option("CONFIG_LOG_DEFAULT_LEVEL_VERBOSE", True)
# add_idf_sdkconfig_option("CONFIG_LOG_DEFAULT_LEVEL_DEBUG", True)
add_idf_sdkconfig_option("CONFIG_EXAMPLE_CLOSE_CMUX_AT_END", True)
add_idf_sdkconfig_option("CONFIG_ESP_MODEM_CMUX_DEFRAGMENT_PAYLOAD", True)
add_idf_sdkconfig_option("CONFIG_ESP_MODEM_CMUX_DELAY_AFTER_DLCI_SETUP", 0)
add_idf_sdkconfig_option("CONFIG_PPP_SUPPORT", True)
add_idf_sdkconfig_option("CONFIG_PPP_NOTIFY_PHASE_SUPPORT", True)
add_idf_sdkconfig_option("CONFIG_PPP_CHAP_SUPPORT", True)
add_idf_sdkconfig_option("CONFIG_LWIP_PPP_VJ_HEADER_COMPRESSION", True)
add_idf_sdkconfig_option("CONFIG_EXAMPLE_MODEM_PPP_APN", "orange")
add_idf_sdkconfig_option("CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT", True)
cg.add_define("USE_GSM")
var = cg.new_Pvariable(config[CONF_ID])
if use_address := config.get(CONF_USE_ADDRESS, None):
cg.add(var.set_use_address(use_address))
if username := config.get(CONF_USERNAME, None):
cg.add(var.set_username(username))
if password := config.get(CONF_PASSWORD, None):
cg.add(var.set_password(password))
if pin_code := config.get(CONF_PIN_CODE, None):
cg.add(var.set_pin_code(pin_code))
cg.add(var.set_model(config[CONF_MODEL]))
cg.add(var.set_apn(config[CONF_APN]))
gpio_num_t = cg.global_ns.enum("gpio_num_t")
cg.add(var.set_rx_pin(getattr(gpio_num_t, f"GPIO_NUM_{config[CONF_RX_PIN]}")))
cg.add(var.set_tx_pin(getattr(gpio_num_t, f"GPIO_NUM_{config[CONF_TX_PIN]}")))
if pwr_pin := config.get(CONF_POWER_PIN, None):
cg.add(var.set_power_pin(getattr(gpio_num_t, f"GPIO_NUM_{pwr_pin}")))
if flight_pin := config.get(CONF_FLIGHT_PIN, None):
cg.add(var.set_flight_pin(getattr(gpio_num_t, f"GPIO_NUM_{flight_pin}")))
if pin_status := config.get(CONF_STATUS_PIN, None):
cg.add(var.set_status_pin(getattr(gpio_num_t, f"GPIO_NUM_{pin_status}")))
if pin_dtr := config.get(CONF_DTR_PIN, None):
cg.add(var.set_dtr_pin(getattr(gpio_num_t, f"GPIO_NUM_{pin_dtr}")))
await cg.register_component(var, config)

View file

@ -0,0 +1,369 @@
#if defined(USE_ESP32) || defined(USE_ESP_IDF)
#include "gsm_component.h"
#include "esphome/core/log.h"
#include "esphome/core/application.h"
#include "esphome/core/defines.h"
#include "esphome/components/network/util.h"
#include <esp_netif.h>
#include <esp_netif_ppp.h>
#include <esp_log.h>
#include <esp_event.h>
#include <cxx_include/esp_modem_dte.hpp>
#include <esp_modem_config.h>
#include <cxx_include/esp_modem_api.hpp>
#include <driver/gpio.h>
#include <lwip/dns.h>
#include <cstring>
#include <iostream>
#include "sdkconfig.h"
#define CONFIG_MODEM_UART_RX_BUFFER_SIZE 1024
#define CONFIG_MODEM_UART_TX_BUFFER_SIZE 512
#define CONFIG_MODEM_UART_EVENT_QUEUE_SIZE 30
#define CONFIG_MODEM_UART_EVENT_TASK_STACK_SIZE 2048
#define CONFIG_MODEM_UART_EVENT_TASK_PRIORITY 5
namespace esphome {
namespace gsm {
GSMComponent *global_gsm_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
#define ESPHL_ERROR_CHECK(err, message) \
if ((err) != ESP_OK) { \
ESP_LOGE(TAG, message ": (%d) %s", err, esp_err_to_name(err)); \
this->mark_failed(); \
return; \
}
using namespace esp_modem;
GSMComponent::GSMComponent() { global_gsm_component = this; }
void GSMComponent::dump_config() { ESP_LOGCONFIG(TAG, "Config GSM:"); }
float GSMComponent::get_setup_priority() const { return setup_priority::WIFI; }
bool GSMComponent::can_proceed() { return this->is_connected(); }
network::IPAddresses GSMComponent::get_ip_addresses() {
network::IPAddresses addresses;
esp_netif_ip_info_t ip;
ESP_LOGV(TAG, "get_ip_addresses");
esp_err_t err = esp_netif_get_ip_info(this->ppp_netif, &ip);
if (err != ESP_OK) {
ESP_LOGV(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err));
// TODO: do something smarter
// return false;
} else {
addresses[0] = network::IPAddress(&ip.ip);
}
return addresses;
}
std::string GSMComponent::get_use_address() const {
if (this->use_address_.empty()) {
return App.get_name() + ".local";
}
return this->use_address_;
}
void GSMComponent::set_use_address(const std::string &use_address) { this->use_address_ = use_address; }
bool GSMComponent::is_connected() { return this->state_ == GSMComponentState::CONNECTED; }
void GSMComponent::setup() {
ESP_LOGI(TAG, "Setting up GSM...");
this->config_gpio_();
ESP_LOGI(TAG, "Status: %d", (int) this->get_status());
// to be sure the modem is not allready connected
// this->powerdown();
ESP_LOGV(TAG, "DTE setup");
esp_modem_dte_config_t dte_config_ = ESP_MODEM_DTE_DEFAULT_CONFIG();
this->dte_config = dte_config_;
// this->dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
this->dte_config.uart_config.tx_io_num = this->tx_pin_;
this->dte_config.uart_config.rx_io_num = this->rx_pin_;
// this->dte_config.uart_config.rts_io_num = static_cast<gpio_num_t>( CONFIG_EXAMPLE_MODEM_UART_RTS_PIN);
// this->dte_config.uart_config.cts_io_num = static_cast<gpio_num_t>( CONFIG_EXAMPLE_MODEM_UART_CTS_PIN);
this->dte_config.uart_config.rx_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE;
this->dte_config.uart_config.tx_buffer_size = CONFIG_MODEM_UART_TX_BUFFER_SIZE;
this->dte_config.uart_config.event_queue_size = CONFIG_MODEM_UART_EVENT_QUEUE_SIZE;
this->dte_config.task_stack_size = CONFIG_MODEM_UART_EVENT_TASK_STACK_SIZE * 2;
this->dte_config.task_priority = CONFIG_MODEM_UART_EVENT_TASK_PRIORITY;
this->dte_config.dte_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE / 2;
this->dte = esp_modem::create_uart_dte(&this->dte_config);
assert(this->dte);
ESP_LOGV(TAG, "Set APN: %s", this->apn_.c_str());
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(this->apn_.c_str());
ESP_LOGV(TAG, "PPP netif setup");
esp_err_t err;
err = esp_netif_init();
ESPHL_ERROR_CHECK(err, "PPP netif init error");
err = esp_event_loop_create_default();
ESPHL_ERROR_CHECK(err, "PPP event loop init error");
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
this->ppp_netif = esp_netif_new(&netif_ppp_config);
assert(this->ppp_netif);
if (!this->username_.empty()) {
ESP_LOGV(TAG, "Set auth: username: %s password: %s", this->username_.c_str(), this->password_.c_str());
ESPHL_ERROR_CHECK(esp_netif_ppp_set_auth(this->ppp_netif, NETIF_PPP_AUTHTYPE_PAP, this->username_.c_str(),
this->password_.c_str()),
"ppp set auth");
}
// dns setup not needed (perhaps fallback ?)
// esp_netif_dns_info_t dns_main = {};
// dns_main.ip.u_addr.ip4.addr = esp_ip4addr_aton("8.8.8.8");
// dns_main.ip.type = ESP_IPADDR_TYPE_V4;
// ESPHL_ERROR_CHECK(esp_netif_set_dns_info(this->ppp_netif, ESP_NETIF_DNS_MAIN, &dns_main), "dns_main");
// Register user defined event handers
err = esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, &GSMComponent::got_ip_event_handler, nullptr);
ESPHL_ERROR_CHECK(err, "GOT IP event handler register error");
ESP_LOGV(TAG, "DCE setup");
switch (this->model_) {
case GSMModel::BG96:
this->dce = create_BG96_dce(&dce_config, dte, this->ppp_netif);
break;
case GSMModel::SIM800:
this->dce = create_SIM800_dce(&dce_config, dte, this->ppp_netif);
break;
case GSMModel::SIM7000:
this->dce = create_SIM7000_dce(&dce_config, dte, this->ppp_netif);
break;
case GSMModel::SIM7600:
this->dce = create_SIM7600_dce(&dce_config, dte, this->ppp_netif);
break;
default:
ESP_LOGE(TAG, "Unknown model");
return;
break;
}
assert(this->dce);
this->started_ = true;
ESP_LOGV(TAG, "Setup finished");
}
void GSMComponent::start_connect_() {
this->connect_begin_ = millis();
this->status_set_warning();
ESP_LOGI(TAG, "Status: %d", (int) this->get_status());
this->poweron();
ESP_LOGI(TAG, "Status: %d", (int) this->get_status());
// 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_gsm_component->got_ipv4_address_ = false; // why not this ?
this->dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_COMMAND);
vTaskDelay(pdMS_TO_TICKS(2000));
command_result res = command_result::TIMEOUT;
int retry = 0;
while (res != command_result::OK) {
res = this->dce->sync();
if (res != command_result::OK) {
ESP_LOGW(TAG, "modem not responding");
ESP_LOGI(TAG, "Status: %d", (int) this->get_status());
this->dce->set_command_mode();
App.feed_wdt();
vTaskDelay(pdMS_TO_TICKS(7000));
}
retry++;
if (retry > 10)
break;
}
if (res != command_result::OK) {
ESP_LOGW(TAG, "Unable to sync modem. Will retry later");
this->powerdown();
return;
}
if (this->dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
if (command_result::OK != dce->set_flow_control(2, 2)) {
ESP_LOGE(TAG, "Failed to set the set_flow_control mode");
return;
}
ESP_LOGI(TAG, "set_flow_control OK");
} else {
ESP_LOGI(TAG, "not set_flow_control, because 2-wire mode active.");
}
/* Setup basic operation mode for the DCE (pin if used, CMUX mode) */
if (!this->pin_code_.empty()) {
bool pin_ok = true;
ESP_LOGV(TAG, "Set pin code: %s", this->pin_code_.c_str());
if (dce->read_pin(pin_ok) == command_result::OK && !pin_ok) {
ESP_MODEM_THROW_IF_FALSE(dce->set_pin(this->pin_code_) == command_result::OK, "Cannot set PIN!");
vTaskDelay(pdMS_TO_TICKS(2000)); // Need to wait for some time after unlocking the SIM
}
}
ESP_LOGD(TAG, "Entering CMUX mode");
vTaskDelay(pdMS_TO_TICKS(2000));
if (this->dce->set_mode(esp_modem::modem_mode::CMUX_MODE)) {
ESP_LOGD(TAG, "Modem has correctly entered multiplexed command/data mode");
} else {
ESP_LOGE(TAG, "Failed to configure multiplexed command mode... exiting");
return;
}
vTaskDelay(pdMS_TO_TICKS(2000));
}
void GSMComponent::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;
const esp_netif_ip_info_t *ip_info = &event->ip_info;
ESP_LOGW(TAG, "[IP event] Got IP " IPSTR, IP2STR(&ip_info->ip));
vTaskDelay(pdMS_TO_TICKS(1000)); // FIXME tmp
global_gsm_component->got_ipv4_address_ = true;
global_gsm_component->connected_ = true;
}
void GSMComponent::loop() {
const uint32_t now = millis();
switch (this->state_) {
case GSMComponentState::STOPPED:
if (this->started_) {
ESP_LOGI(TAG, "Starting gsm connection");
this->state_ = GSMComponentState::CONNECTING;
this->start_connect_();
}
break;
case GSMComponentState::CONNECTING:
if (!this->started_) {
ESP_LOGI(TAG, "Stopped ethernet connection");
this->state_ = GSMComponentState::STOPPED;
} else if (this->connected_) {
// connection established
ESP_LOGI(TAG, "Connected via GSM");
this->state_ = GSMComponentState::CONNECTED;
this->dump_connect_params_();
this->status_clear_warning();
} else if (now - this->connect_begin_ > 45000) {
ESP_LOGW(TAG, "Connecting via GSM failed! Re-connecting...");
this->start_connect_();
}
break;
case GSMComponentState::CONNECTED:
if (!this->started_) {
ESP_LOGI(TAG, "Stopped GSM connection");
this->state_ = GSMComponentState::STOPPED;
} else if (!this->connected_) {
ESP_LOGW(TAG, "Connection via GSM lost! Re-connecting...");
this->state_ = GSMComponentState::CONNECTING;
this->start_connect_();
}
break;
}
}
void GSMComponent::dump_connect_params_() {
esp_netif_ip_info_t ip;
esp_netif_get_ip_info(this->ppp_netif, &ip);
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, " Subnet: %s", network::IPAddress(&ip.netmask).str().c_str());
ESP_LOGCONFIG(TAG, " Gateway: %s", network::IPAddress(&ip.gw).str().c_str());
const ip_addr_t *dns_main_ip = dns_getserver(ESP_NETIF_DNS_MAIN);
const ip_addr_t *dns_backup_ip = dns_getserver(ESP_NETIF_DNS_BACKUP);
const ip_addr_t *dns_fallback_ip = dns_getserver(ESP_NETIF_DNS_FALLBACK);
ESP_LOGCONFIG(TAG, " DNS main: %s", network::IPAddress(dns_main_ip).str().c_str());
ESP_LOGCONFIG(TAG, " DNS backup: %s", network::IPAddress(dns_backup_ip).str().c_str());
ESP_LOGCONFIG(TAG, " DNS fallback: %s", network::IPAddress(dns_fallback_ip).str().c_str());
}
void GSMComponent::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 GSMComponent::poweron(void) {
/* Power on the modem */
ESP_LOGI(TAG, "Status: %d", (int) this->get_status());
ESP_LOGI(TAG, "Power on modem");
// 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
} 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");
}
vTaskDelay(pdMS_TO_TICKS(15000));
App.feed_wdt();
}
void GSMComponent::powerdown(void) {
ESP_LOGI(TAG, "Power down modem");
ESP_ERROR_CHECK(gpio_set_level(this->power_pin_, 1));
}
} // namespace gsm
} // namespace esphome
#endif

View file

@ -0,0 +1,99 @@
#pragma once
#include <memory>
#include "esphome/core/component.h"
#include "esphome/components/network/util.h"
#if defined(USE_ESP32) || defined(USE_ESP_IDF)
#include <esp_log.h>
#include <cxx_include/esp_modem_api.hpp>
#include <esp_modem_config.h>
#include <driver/gpio.h>
#include <unordered_map>
namespace esphome {
namespace gsm {
static const char *const TAG = "gsm";
enum class GSMComponentState {
STOPPED,
CONNECTING,
CONNECTED,
};
enum class GSMModel { BG96, SIM800, SIM7000, SIM7070, SIM7070_GNSS, SIM7600, UNKNOWN };
class GSMComponent : public Component {
public:
GSMComponent();
void dump_config() override;
void setup() override;
void loop() override;
bool is_connected();
float get_setup_priority() const override;
bool can_proceed() override;
void on_shutdown() override { powerdown(); }
network::IPAddresses get_ip_addresses();
std::string get_use_address() const;
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_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(std::string username) { this->username_ = username; }
void set_password(std::string password) { this->password_ = password; }
void set_pin_code(std::string pin_code) { this->pin_code_ = pin_code; }
void set_apn(std::string apn) { this->apn_ = 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(std::string model) {
this->model_ = this->gsm_model_map_.count(model) ? gsm_model_map_[model] : GSMModel::UNKNOWN;
}
bool get_status() { return gpio_get_level(this->status_pin_); }
protected:
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 power_pin_ = gpio_num_t::GPIO_NUM_NC;
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 username_;
std::string password_;
std::string apn_;
GSMModel model_;
std::unordered_map<std::string, GSMModel> gsm_model_map_ = {{"BG96", GSMModel::BG96},
{"SIM800", GSMModel::SIM800},
{"SIM7000", GSMModel::SIM7000},
{"SIM7070", GSMModel::SIM7070},
{"SIM7070_GNSS", GSMModel::SIM7070_GNSS},
{"SIM7600", GSMModel::SIM7600}};
std::shared_ptr<esp_modem::DTE> dte;
std::unique_ptr<esp_modem::DCE> dce; // public ?
esp_modem::esp_netif_t *ppp_netif{nullptr};
esp_modem_dte_config_t dte_config;
GSMComponentState state_{GSMComponentState::STOPPED};
void start_connect_();
bool started_{false};
bool connected_{false};
bool got_ipv4_address_{false};
uint32_t connect_begin_;
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_();
std::string use_address_;
void config_gpio_();
};
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
extern GSMComponent *global_gsm_component;
} // namespace gsm
} // namespace esphome
#endif

View file

@ -4,6 +4,7 @@
#include <cstdio>
#include <array>
#include "esphome/core/macros.h"
#include "esphome/core/helpers.h"
#if defined(USE_ESP_IDF) || defined(USE_LIBRETINY) || USE_ARDUINO_VERSION_CODE > VERSION_CODE(3, 0, 0)
#include <lwip/ip_addr.h>
@ -116,7 +117,7 @@ struct IPAddress {
bool is_set() { return !ip_addr_isany(&ip_addr_); }
bool is_ip4() { return IP_IS_V4(&ip_addr_); }
bool is_ip6() { return IP_IS_V6(&ip_addr_); }
std::string str() const { return ipaddr_ntoa(&ip_addr_); }
std::string str() const { return str_lower_case(ipaddr_ntoa(&ip_addr_)); }
bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); }
bool operator!=(const IPAddress &other) const { return !ip_addr_cmp(&ip_addr_, &other.ip_addr_); }
IPAddress &operator+=(uint8_t increase) {

View file

@ -9,6 +9,10 @@
#include "esphome/components/ethernet/ethernet_component.h"
#endif
#ifdef USE_GSM
#include "esphome/components/gsm/gsm_component.h"
#endif
namespace esphome {
namespace network {
@ -23,6 +27,11 @@ bool is_connected() {
return wifi::global_wifi_component->is_connected();
#endif
#ifdef USE_GSM
if (gsm::global_gsm_component != nullptr)
return gsm::global_gsm_component->is_connected();
#endif
#ifdef USE_HOST
return true; // Assume its connected
#endif
@ -46,6 +55,7 @@ network::IPAddresses get_ip_addresses() {
if (wifi::global_wifi_component != nullptr)
return wifi::global_wifi_component->get_ip_addresses();
#endif
return {};
}
@ -57,6 +67,10 @@ std::string get_use_address() {
#ifdef USE_WIFI
if (wifi::global_wifi_component != nullptr)
return wifi::global_wifi_component->get_use_address();
#endif
#ifdef USE_GSM
if (gsm::global_gsm_component != nullptr)
return gsm::global_gsm_component->get_use_address();
#endif
return "";
}