mirror of
https://github.com/esphome/esphome.git
synced 2024-12-26 07:24:54 +01:00
add modem component
This commit is contained in:
parent
ab620acd4f
commit
348b2e42d6
9 changed files with 680 additions and 0 deletions
37
dependencies.lock
Normal file
37
dependencies.lock
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
dependencies:
|
||||||
|
esp-tflite-micro:
|
||||||
|
component_hash: 09acb9889f98d0e7b5d9d1aa7184d455cfd30268d627b43371b7593106d0fc4b
|
||||||
|
source:
|
||||||
|
git: https://github.com/espressif/esp-tflite-micro.git
|
||||||
|
path: .
|
||||||
|
type: git
|
||||||
|
version: c5d97c9577de0eb9b8f05078da84bbb9ff0f748f
|
||||||
|
esp32_camera:
|
||||||
|
component_hash: 659f1353ee3dd6db885667c61e45fad5574c6c4d832fbe6797ea224d6f61d1e3
|
||||||
|
source:
|
||||||
|
git: https://github.com/espressif/esp32-camera.git
|
||||||
|
path: .
|
||||||
|
type: git
|
||||||
|
version: 30aeeeed61e2b0182d673fe2cfedb1b7aa43b1b9
|
||||||
|
esp_modem:
|
||||||
|
component_hash: ece3d43c4541d88eba1484cce471e9c148052df49388dcd11bee8d453064af9a
|
||||||
|
source:
|
||||||
|
git: https://github.com/espressif/esp-protocols.git
|
||||||
|
path: components/esp_modem
|
||||||
|
type: git
|
||||||
|
version: 73c48307a367565f69e724df8641f8cbac45251d
|
||||||
|
espressif/esp-nn:
|
||||||
|
component_hash: b32869798bdb40dec6bc99caca48cd65d42f8a9f506b9ab9c598a076f891ede9
|
||||||
|
source:
|
||||||
|
pre_release: true
|
||||||
|
service_url: https://api.components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 1.0.2
|
||||||
|
idf:
|
||||||
|
component_hash: null
|
||||||
|
source:
|
||||||
|
type: idf
|
||||||
|
version: 4.4.7
|
||||||
|
manifest_hash: 9e758d00f6141ced5cecfa8032dab873feba457ffaf6cdc3fcb3337947a3c8ed
|
||||||
|
target: esp32
|
||||||
|
version: 1.0.0
|
147
esphome/components/modem/__init__.py
Normal file
147
esphome/components/modem/__init__.py
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
from esphome import pins
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_DOMAIN,
|
||||||
|
CONF_ID,
|
||||||
|
CONF_MANUAL_IP,
|
||||||
|
CONF_STATIC_IP,
|
||||||
|
CONF_TYPE,
|
||||||
|
CONF_USE_ADDRESS,
|
||||||
|
CONF_GATEWAY,
|
||||||
|
CONF_SUBNET,
|
||||||
|
CONF_DNS1,
|
||||||
|
CONF_DNS2,
|
||||||
|
)
|
||||||
|
from esphome.core import CORE, coroutine_with_priority
|
||||||
|
from esphome.components.esp32 import add_idf_component
|
||||||
|
from esphome.components.network import IPAddress
|
||||||
|
|
||||||
|
CONFLICTS_WITH = ["wifi"]
|
||||||
|
DEPENDENCIES = ["esp32"]
|
||||||
|
AUTO_LOAD = ["network"]
|
||||||
|
|
||||||
|
modem_ns = cg.esphome_ns.namespace("modem")
|
||||||
|
# CONF_PHY_ADDR = "phy_addr"
|
||||||
|
# CONF_MDC_PIN = "mdc_pin"
|
||||||
|
# CONF_MDIO_PIN = "mdio_pin"
|
||||||
|
# CONF_CLK_MODE = "clk_mode"
|
||||||
|
# CONF_POWER_PIN = "power_pin"
|
||||||
|
|
||||||
|
ModemType = modem_ns.enum("ModemType")
|
||||||
|
MODEM_TYPES = {
|
||||||
|
"BG96": ModemType.MODEM_TYPE_BG96,
|
||||||
|
"SIM800": ModemType.MODEM_TYPE_SIM800,
|
||||||
|
"SIM7000": ModemType.MODEM_TYPE_SIM7000,
|
||||||
|
"SIM7070": ModemType.MODEM_TYPE_SIM7070,
|
||||||
|
}
|
||||||
|
|
||||||
|
# emac_rmii_clock_mode_t = cg.global_ns.enum("emac_rmii_clock_mode_t")
|
||||||
|
# emac_rmii_clock_gpio_t = cg.global_ns.enum("emac_rmii_clock_gpio_t")
|
||||||
|
# CLK_MODES = {
|
||||||
|
# "GPIO0_IN": (
|
||||||
|
# emac_rmii_clock_mode_t.EMAC_CLK_EXT_IN,
|
||||||
|
# emac_rmii_clock_gpio_t.EMAC_CLK_IN_GPIO,
|
||||||
|
# ),
|
||||||
|
# "GPIO0_OUT": (
|
||||||
|
# emac_rmii_clock_mode_t.EMAC_CLK_OUT,
|
||||||
|
# emac_rmii_clock_gpio_t.EMAC_APPL_CLK_OUT_GPIO,
|
||||||
|
# ),
|
||||||
|
# "GPIO16_OUT": (
|
||||||
|
# emac_rmii_clock_mode_t.EMAC_CLK_OUT,
|
||||||
|
# emac_rmii_clock_gpio_t.EMAC_CLK_OUT_GPIO,
|
||||||
|
# ),
|
||||||
|
# "GPIO17_OUT": (
|
||||||
|
# emac_rmii_clock_mode_t.EMAC_CLK_OUT,
|
||||||
|
# emac_rmii_clock_gpio_t.EMAC_CLK_OUT_180_GPIO,
|
||||||
|
# ),
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
# MANUAL_IP_SCHEMA = cv.Schema(
|
||||||
|
# {
|
||||||
|
# cv.Required(CONF_STATIC_IP): cv.ipv4,
|
||||||
|
# cv.Required(CONF_GATEWAY): cv.ipv4,
|
||||||
|
# cv.Required(CONF_SUBNET): cv.ipv4,
|
||||||
|
# cv.Optional(CONF_DNS1, default="0.0.0.0"): cv.ipv4,
|
||||||
|
# cv.Optional(CONF_DNS2, default="0.0.0.0"): cv.ipv4,
|
||||||
|
# }
|
||||||
|
# )
|
||||||
|
|
||||||
|
ModemComponent = modem_ns.class_("ModemComponent", cg.Component)
|
||||||
|
#ManualIP = ethernet_ns.struct("ManualIP")
|
||||||
|
|
||||||
|
|
||||||
|
def _validate(config):
|
||||||
|
if CONF_USE_ADDRESS not in config:
|
||||||
|
use_address = CORE.name + config[CONF_DOMAIN]
|
||||||
|
config[CONF_USE_ADDRESS] = use_address
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(ModemComponent),
|
||||||
|
cv.Required(CONF_TYPE): cv.enum(MODEM_TYPES, upper=True),
|
||||||
|
#cv.Required(CONF_MDC_PIN): pins.internal_gpio_output_pin_number,
|
||||||
|
# cv.Required(CONF_MDIO_PIN): pins.internal_gpio_output_pin_number,
|
||||||
|
# cv.Optional(CONF_CLK_MODE, default="GPIO0_IN"): cv.enum(
|
||||||
|
# CLK_MODES, upper=True, space="_"
|
||||||
|
# ),
|
||||||
|
# cv.Optional(CONF_PHY_ADDR, default=0): cv.int_range(min=0, max=31),
|
||||||
|
# cv.Optional(CONF_POWER_PIN): pins.internal_gpio_output_pin_number,
|
||||||
|
# cv.Optional(CONF_MANUAL_IP): MANUAL_IP_SCHEMA,
|
||||||
|
cv.Optional(CONF_DOMAIN, default=".local"): cv.domain_name,
|
||||||
|
cv.Optional(CONF_USE_ADDRESS): cv.string_strict,
|
||||||
|
# cv.Optional("enable_mdns"): cv.invalid(
|
||||||
|
# "This option has been removed. Please use the [disabled] option under the "
|
||||||
|
# "new mdns component instead."
|
||||||
|
# ),
|
||||||
|
}
|
||||||
|
).extend(cv.COMPONENT_SCHEMA),
|
||||||
|
_validate,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# def manual_ip(config):
|
||||||
|
# return cg.StructInitializer(
|
||||||
|
# ManualIP,
|
||||||
|
# ("static_ip", IPAddress(*config[CONF_STATIC_IP].args)),
|
||||||
|
# ("gateway", IPAddress(*config[CONF_GATEWAY].args)),
|
||||||
|
# ("subnet", IPAddress(*config[CONF_SUBNET].args)),
|
||||||
|
# ("dns1", IPAddress(*config[CONF_DNS1].args)),
|
||||||
|
# ("dns2", IPAddress(*config[CONF_DNS2].args)),
|
||||||
|
# )
|
||||||
|
|
||||||
|
|
||||||
|
@coroutine_with_priority(60.0)
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
#cg.add(var.set_phy_addr(config[CONF_PHY_ADDR]))
|
||||||
|
#cg.add(var.set_mdc_pin(config[CONF_MDC_PIN]))
|
||||||
|
#cg.add(var.set_mdio_pin(config[CONF_MDIO_PIN]))
|
||||||
|
cg.add(var.set_type(config[CONF_TYPE]))
|
||||||
|
#cg.add(var.set_clk_mode(*CLK_MODES[config[CONF_CLK_MODE]]))
|
||||||
|
cg.add(var.set_use_address(config[CONF_USE_ADDRESS]))
|
||||||
|
|
||||||
|
# if CONF_POWER_PIN in config:
|
||||||
|
# cg.add(var.set_power_pin(config[CONF_POWER_PIN]))
|
||||||
|
|
||||||
|
# if CONF_MANUAL_IP in config:
|
||||||
|
# cg.add(var.set_manual_ip(manual_ip(config[CONF_MANUAL_IP])))
|
||||||
|
|
||||||
|
cg.add_define("USE_MODEM")
|
||||||
|
|
||||||
|
if CORE.using_arduino:
|
||||||
|
cg.add_library("WiFi", None)
|
||||||
|
|
||||||
|
if CORE.using_esp_idf:
|
||||||
|
add_idf_component(
|
||||||
|
name="esp_modem",
|
||||||
|
repo="https://github.com/espressif/esp-protocols.git",
|
||||||
|
ref="^1.1.0",
|
||||||
|
path="components/esp_modem",
|
||||||
|
)
|
403
esphome/components/modem/modem_component.cpp
Normal file
403
esphome/components/modem/modem_component.cpp
Normal file
|
@ -0,0 +1,403 @@
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_PPP_APN "internet"
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME "espressif"
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD "esp32"
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_TX_PIN 25
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_RX_PIN 26
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_RTS_PIN 27
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_CTS_PIN 23
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE 2048
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY 5
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE 30
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_PATTERN_QUEUE_SIZE 20
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE 512
|
||||||
|
#define CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
|
||||||
|
#include "esp_modem_c_api_types.h"
|
||||||
|
#include "esp_netif_ppp.h"
|
||||||
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
|
#include "cxx_include/esp_modem_dce.hpp"
|
||||||
|
|
||||||
|
#include "modem_component.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <lwip/dns.h>
|
||||||
|
#include "esp_event.h"
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<esp_modem::DTE> dte{nullptr};
|
||||||
|
std::unique_ptr<esp_modem::DCE> dce{nullptr};
|
||||||
|
|
||||||
|
uint32_t time_info_print = 0;
|
||||||
|
uint32_t time_hard_reset_modem = 0;
|
||||||
|
uint32_t time_check_rssi = 0;
|
||||||
|
|
||||||
|
#define TIME_TO_NEXT_HARD_RESET 30000
|
||||||
|
#define TIME_TO_START_MODEM 9000
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace modem {
|
||||||
|
|
||||||
|
static EventGroupHandle_t event_group = NULL;
|
||||||
|
static const int CONNECT_BIT = BIT0;
|
||||||
|
static const int GOT_DATA_BIT = BIT2;
|
||||||
|
static const int USB_DISCONNECTED_BIT = BIT3;
|
||||||
|
static const char *const TAG = "modem";
|
||||||
|
|
||||||
|
ModemComponent *global_modem_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; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemComponent::ModemComponent() { global_modem_component = this; }
|
||||||
|
void print_netif_flags(esp_netif_flags_t flags) {
|
||||||
|
// Check each flag and print its presecommand_lib%s", (flags & ESP_NETIF_DHCP_CLIENT) ? "true" : "false");
|
||||||
|
ESP_LOGI(TAG, "ESP_NETIF_DHCP_SERVER: %s", (flags & ESP_NETIF_DHCP_SERVER) ? "true" : "false");
|
||||||
|
ESP_LOGI(TAG, "ESP_NETIF_FLAG_AUTOUP: %s", (flags & ESP_NETIF_FLAG_AUTOUP) ? "true" : "false");
|
||||||
|
ESP_LOGI(TAG, "ESP_NETIF_FLAG_GARP: %s", (flags & ESP_NETIF_FLAG_GARP) ? "true" : "false");
|
||||||
|
ESP_LOGI(TAG, "ESP_NETIF_FLAG_EVENT_IP_MODIFIED: %s", (flags & ESP_NETIF_FLAG_EVENT_IP_MODIFIED) ? "true" : "false");
|
||||||
|
ESP_LOGI(TAG, "ESP_NETIF_FLAG_IS_PPP: %s", (flags & ESP_NETIF_FLAG_IS_PPP) ? "true" : "false");
|
||||||
|
ESP_LOGI(TAG, "ESP_NETIF_FLAG_IS_SLIP: %s", (flags & ESP_NETIF_FLAG_IS_SLIP) ? "true" : "false");
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
void esp_modem_hard_reset()
|
||||||
|
{
|
||||||
|
gpio_set_direction(GPIO_NUM_23, GPIO_MODE_OUTPUT);
|
||||||
|
//gpio_pullup_en(GPIO_NUM_23);
|
||||||
|
gpio_set_level(GPIO_NUM_23, 0);
|
||||||
|
ESP_LOGI(TAG, "GPIO_NUM_23 0");
|
||||||
|
vTaskDelay(50);
|
||||||
|
gpio_set_level(GPIO_NUM_23, 1);
|
||||||
|
ESP_LOGI(TAG, "GPIO_NUM_23 1");
|
||||||
|
vTaskDelay(2000);
|
||||||
|
time_hard_reset_modem = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_rssi(){
|
||||||
|
int rssi=0, ber=0;
|
||||||
|
esp_modem::command_result errr = dce->get_signal_quality(rssi, ber);
|
||||||
|
//esp_err_t err = esp_modem::esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||||
|
if (errr != esp_modem::command_result::OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_modem_get_signal_quality failed with");
|
||||||
|
}
|
||||||
|
return rssi;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_modem_voltage(){
|
||||||
|
int voltage=0, bcs=0, bcl=0;
|
||||||
|
dce->set_cmux();
|
||||||
|
esp_modem::command_result errr = dce->get_battery_status(voltage, bcs, bcl);
|
||||||
|
if (errr != esp_modem::command_result::OK) {
|
||||||
|
ESP_LOGE(TAG, "get_battery_status failed with");
|
||||||
|
}
|
||||||
|
return voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
//setup
|
||||||
|
void ModemComponent::setup() {
|
||||||
|
|
||||||
|
esp_log_level_set("esp-netif_lwip-ppp", ESP_LOG_VERBOSE);
|
||||||
|
esp_log_level_set("esp-netif_lwip", ESP_LOG_VERBOSE);
|
||||||
|
esp_log_level_set("modem", ESP_LOG_VERBOSE);
|
||||||
|
esp_log_level_set("mqtt", ESP_LOG_VERBOSE);
|
||||||
|
esp_log_level_set("command_lib", ESP_LOG_VERBOSE);
|
||||||
|
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up modem...");
|
||||||
|
esp_modem_hard_reset();
|
||||||
|
if (esp_reset_reason() != ESP_RST_DEEPSLEEP) {
|
||||||
|
// Delay here to allow power to stabilise before Modem is initialized.
|
||||||
|
delay(300); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t err;
|
||||||
|
err = esp_netif_init();
|
||||||
|
ESPHL_ERROR_CHECK(err, "modem netif init error");
|
||||||
|
err = esp_event_loop_create_default();
|
||||||
|
ESPHL_ERROR_CHECK(err, "modem event loop error");
|
||||||
|
ESP_LOGCONFIG(TAG, "Initing netif");
|
||||||
|
|
||||||
|
esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &ModemComponent::got_ip_event_handler, NULL);
|
||||||
|
//esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, NULL);
|
||||||
|
|
||||||
|
/* Configure the PPP netif */
|
||||||
|
|
||||||
|
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||||
|
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||||
|
this->modem_netif_ = esp_netif_new(&netif_ppp_config);
|
||||||
|
//esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
|
||||||
|
assert(this->modem_netif_);
|
||||||
|
ESP_LOGI(TAG, "netif create succes");
|
||||||
|
event_group = xEventGroupCreate();
|
||||||
|
|
||||||
|
/* Configure the DTE */
|
||||||
|
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||||
|
/* setup UART specific configuration based on kconfig options */
|
||||||
|
dte_config.uart_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
|
||||||
|
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
|
||||||
|
dte_config.uart_config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN;
|
||||||
|
dte_config.uart_config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN;
|
||||||
|
dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
|
||||||
|
dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
|
||||||
|
dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
|
||||||
|
dte_config.task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
|
||||||
|
dte_config.task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
|
||||||
|
dte_config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Initializing esp_modem for the SIM800 module...");
|
||||||
|
dte = esp_modem::create_uart_dte(&dte_config);
|
||||||
|
//esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM800, &dte_config, &dce_config, this->modem_netif_);
|
||||||
|
dce = esp_modem::create_SIM800_dce(&dce_config, dte, this->modem_netif_);
|
||||||
|
|
||||||
|
|
||||||
|
xEventGroupClearBits(event_group, CONNECT_BIT | GOT_DATA_BIT | USB_DISCONNECTED_BIT);
|
||||||
|
/* Run the modem demo app */
|
||||||
|
//return;
|
||||||
|
|
||||||
|
esp_netif_flags_t flags = esp_netif_get_flags(this->modem_netif_);
|
||||||
|
print_netif_flags(flags);
|
||||||
|
|
||||||
|
|
||||||
|
//set data mode
|
||||||
|
//dce->set_data();
|
||||||
|
|
||||||
|
//this->modem_netif_->
|
||||||
|
/* Wait for IP address */
|
||||||
|
//ESP_LOGI(TAG, "Waiting for IP address");
|
||||||
|
//xEventGroupWaitBits(event_group, CONNECT_BIT | USB_DISCONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||||
|
//vTaskDelay(15000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ModemComponent::loop() {
|
||||||
|
const uint32_t now = millis();
|
||||||
|
if (time_info_print < now){
|
||||||
|
|
||||||
|
//ESP_LOGI(TAG, "voltage %dV.", get_modem_voltage()/1000);
|
||||||
|
ESP_LOGI(TAG, "esp_netif_is_netif_UP");
|
||||||
|
if (esp_netif_is_netif_up(this->modem_netif_)){
|
||||||
|
ESP_LOGI(TAG, "esp_netif_is_netif_UP");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ESP_LOGI(TAG, "esp_netif_is_netif_DOWN");
|
||||||
|
}
|
||||||
|
time_info_print = now + 5000;
|
||||||
|
switch (this->state_)
|
||||||
|
{
|
||||||
|
case ModemComponentState::STOPPED:
|
||||||
|
ESP_LOGI(TAG, "modem STOPPED");
|
||||||
|
break;
|
||||||
|
case ModemComponentState::CONNECTING:
|
||||||
|
ESP_LOGI(TAG, "modem CONNECTING");
|
||||||
|
break;
|
||||||
|
case ModemComponentState::CONNECTED:
|
||||||
|
dce->set_data();
|
||||||
|
ESP_LOGI(TAG, "modem CONNECTED");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//ESP_LOGI(TAG, "SIgnal quality: rssi=%d", get_rssi());
|
||||||
|
}
|
||||||
|
|
||||||
|
this->started_ = true;
|
||||||
|
|
||||||
|
|
||||||
|
switch (this->state_) {
|
||||||
|
case ModemComponentState::STOPPED:
|
||||||
|
if (time_check_rssi + TIME_TO_START_MODEM < now){
|
||||||
|
time_check_rssi = now;
|
||||||
|
dce->set_command_mode();
|
||||||
|
if (get_rssi()) {
|
||||||
|
ESP_LOGI(TAG, "Starting modem connection");
|
||||||
|
ESP_LOGI(TAG, "SIgnal quality: rssi=%d", get_rssi());
|
||||||
|
this->state_ = ModemComponentState::CONNECTING;
|
||||||
|
dce->set_data();
|
||||||
|
//this->start_connect_();
|
||||||
|
}
|
||||||
|
if (time_hard_reset_modem + TIME_TO_NEXT_HARD_RESET < now){
|
||||||
|
time_hard_reset_modem = now;
|
||||||
|
esp_modem_hard_reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ModemComponentState::CONNECTING:
|
||||||
|
break;
|
||||||
|
case ModemComponentState::CONNECTED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
// if (!this->started_) {
|
||||||
|
// ESP_LOGI(TAG, "Stopped modem connection");
|
||||||
|
// this->state_ = ModemComponentState::STOPPED;
|
||||||
|
// } else if (this->connected_) {
|
||||||
|
// // connection established
|
||||||
|
// ESP_LOGI(TAG, "Connected via Modem!");
|
||||||
|
// this->state_ = ModemComponentState::CONNECTED;
|
||||||
|
|
||||||
|
// //this->dump_connect_params_();
|
||||||
|
// this->status_clear_warning();
|
||||||
|
// } else if (now - this->connect_begin_ > 40000) {
|
||||||
|
// ESP_LOGW(TAG, "Connecting via modem failed! Re-connecting...");
|
||||||
|
// this->start_connect_();
|
||||||
|
// dce->set_data_mode();
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case ModemComponentState::CONNECTED:
|
||||||
|
// if (!this->started_) {
|
||||||
|
// ESP_LOGI(TAG, "Stopped modem connection");
|
||||||
|
// this->state_ = ModemComponentState::STOPPED;
|
||||||
|
// } else if (!this->connected_) {
|
||||||
|
// ESP_LOGW(TAG, "Connection via Modem lost! Re-connecting...");
|
||||||
|
// this->state_ = ModemComponentState::CONNECTING;
|
||||||
|
// this->start_connect_();
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float ModemComponent::get_setup_priority() const { return setup_priority::WIFI; }
|
||||||
|
|
||||||
|
bool ModemComponent::can_proceed() { return this->is_connected(); }
|
||||||
|
|
||||||
|
network::IPAddress ModemComponent::get_ip_address() {
|
||||||
|
esp_netif_ip_info_t ip;
|
||||||
|
esp_netif_get_ip_info(this->modem_netif_, &ip);
|
||||||
|
return network::IPAddress(&ip.ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemComponent::modem_event_handler(void *arg, esp_event_base_t event_base, int32_t event, void *event_data) {
|
||||||
|
const char *event_name;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case ETHERNET_EVENT_START:
|
||||||
|
event_name = "ETH started";
|
||||||
|
global_modem_component->started_ = true;
|
||||||
|
break;
|
||||||
|
case ETHERNET_EVENT_STOP:
|
||||||
|
event_name = "ETH stopped";
|
||||||
|
global_modem_component->started_ = false;
|
||||||
|
global_modem_component->connected_ = false;
|
||||||
|
break;
|
||||||
|
case ETHERNET_EVENT_CONNECTED:
|
||||||
|
event_name = "ETH connected";
|
||||||
|
break;
|
||||||
|
case ETHERNET_EVENT_DISCONNECTED:
|
||||||
|
event_name = "ETH disconnected";
|
||||||
|
global_modem_component->connected_ = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGV(TAG, "[Modem event] %s (num=%" PRId32 ")", event_name, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemComponent::got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id,
|
||||||
|
void *event_data) {
|
||||||
|
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||||
|
global_modem_component->connected_ = true;
|
||||||
|
global_modem_component->state_ = ModemComponentState::CONNECTED;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "IP event! %" PRIu32, event_id);
|
||||||
|
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||||
|
esp_netif_dns_info_t dns_info;
|
||||||
|
|
||||||
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
|
esp_netif_t *netif = event->esp_netif;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||||
|
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
|
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||||
|
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||||
|
esp_netif_get_dns_info(netif, ESP_NETIF_DNS_MAIN, &dns_info);
|
||||||
|
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||||
|
esp_netif_get_dns_info(netif, ESP_NETIF_DNS_BACKUP, &dns_info);
|
||||||
|
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||||
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||||
|
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||||
|
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||||
|
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||||
|
global_modem_component->state_ = ModemComponentState::STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ModemComponent::start_connect_() {
|
||||||
|
this->connect_begin_ = millis();
|
||||||
|
this->status_set_warning();
|
||||||
|
esp_modem_hard_reset();
|
||||||
|
esp_err_t err;
|
||||||
|
err = esp_netif_set_hostname(this->modem_netif_, App.get_name().c_str());
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// esp_netif_dhcp_status_t status = ESP_NETIF_DHCP_INIT;
|
||||||
|
|
||||||
|
//restart ppp connection
|
||||||
|
dce->exit_data();
|
||||||
|
int rssi, ber;
|
||||||
|
esp_modem::command_result errr = dce->get_signal_quality(rssi, ber);
|
||||||
|
//esp_err_t err = esp_modem::esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||||
|
if (errr != esp_modem::command_result::OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_modem_get_signal_quality failed with");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
|
||||||
|
dce->set_data();
|
||||||
|
|
||||||
|
vTaskDelay(15000);
|
||||||
|
// this->status_set_warning();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModemComponent::is_connected() { return this->state_ == ModemComponentState::CONNECTED; }
|
||||||
|
|
||||||
|
void ModemComponent::set_power_pin(int power_pin) { this->power_pin_ = power_pin; }
|
||||||
|
void ModemComponent::set_type(ModemType type) { this->type_ = type; }
|
||||||
|
|
||||||
|
|
||||||
|
std::string ModemComponent::get_use_address() const {
|
||||||
|
if (this->use_address_.empty()) {
|
||||||
|
return App.get_name() + ".local";
|
||||||
|
}
|
||||||
|
return this->use_address_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemComponent::set_use_address(const std::string &use_address) { this->use_address_ = use_address; }
|
||||||
|
|
||||||
|
bool ModemComponent::powerdown() {
|
||||||
|
// ESP_LOGI(TAG, "Powering down modem PHY");
|
||||||
|
// if (this->phy_ == nullptr) {
|
||||||
|
// ESP_LOGE(TAG, "Modem PHY not assigned");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// this->connected_ = false;
|
||||||
|
// this->started_ = false;
|
||||||
|
// if (this->phy_->pwrctl(this->phy_, false) != ESP_OK) {
|
||||||
|
// ESP_LOGE(TAG, "Error powering down modem PHY");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace modem
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // USE_ESP32
|
83
esphome/components/modem/modem_component.h
Normal file
83
esphome/components/modem/modem_component.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/components/network/ip_address.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
#include "esp_netif.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace modem {
|
||||||
|
|
||||||
|
enum ModemType {
|
||||||
|
MODEM_TYPE_UNKNOWN = 0,
|
||||||
|
MODEM_TYPE_BG96,
|
||||||
|
MODEM_TYPE_SIM800,
|
||||||
|
MODEM_TYPE_SIM7000,
|
||||||
|
MODEM_TYPE_SIM7070,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ManualIP {
|
||||||
|
network::IPAddress static_ip;
|
||||||
|
network::IPAddress gateway;
|
||||||
|
network::IPAddress subnet;
|
||||||
|
network::IPAddress dns1; ///< The first DNS server. 0.0.0.0 for default.
|
||||||
|
network::IPAddress dns2; ///< The second DNS server. 0.0.0.0 for default.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ModemComponentState {
|
||||||
|
STOPPED,
|
||||||
|
CONNECTING,
|
||||||
|
CONNECTED,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ModemComponent : public Component {
|
||||||
|
public:
|
||||||
|
ModemComponent();
|
||||||
|
void setup() override;
|
||||||
|
void loop() override;
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
bool can_proceed() override;
|
||||||
|
void on_shutdown() override { powerdown(); }
|
||||||
|
bool is_connected();
|
||||||
|
|
||||||
|
void set_power_pin(int power_pin);
|
||||||
|
void set_type(ModemType type);
|
||||||
|
//void set_clk_mode(emac_rmii_clock_mode_t clk_mode, emac_rmii_clock_gpio_t clk_gpio);
|
||||||
|
//void set_manual_ip(const ManualIP &manual_ip);
|
||||||
|
|
||||||
|
network::IPAddress get_ip_address();
|
||||||
|
std::string get_use_address() const;
|
||||||
|
void set_use_address(const std::string &use_address);
|
||||||
|
bool powerdown();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void modem_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 start_connect_();
|
||||||
|
|
||||||
|
std::string use_address_;
|
||||||
|
int power_pin_{-1};
|
||||||
|
ModemType type_{MODEM_TYPE_UNKNOWN};
|
||||||
|
optional<ManualIP> manual_ip_{};
|
||||||
|
|
||||||
|
bool started_{false};
|
||||||
|
bool connected_{false};
|
||||||
|
|
||||||
|
ModemComponentState state_{ModemComponentState::STOPPED};
|
||||||
|
uint32_t connect_begin_;
|
||||||
|
esp_netif_t *modem_netif_{nullptr};
|
||||||
|
//esp_eth_phy_t *phy_{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
extern ModemComponent *global_modem_component;
|
||||||
|
|
||||||
|
} // namespace modem
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // USE_ESP32
|
|
@ -262,6 +262,7 @@ CONF_EQUATION = "equation"
|
||||||
CONF_ESP8266_DISABLE_SSL_SUPPORT = "esp8266_disable_ssl_support"
|
CONF_ESP8266_DISABLE_SSL_SUPPORT = "esp8266_disable_ssl_support"
|
||||||
CONF_ESPHOME = "esphome"
|
CONF_ESPHOME = "esphome"
|
||||||
CONF_ETHERNET = "ethernet"
|
CONF_ETHERNET = "ethernet"
|
||||||
|
CONF_MODEM = "modem"
|
||||||
CONF_EVENT = "event"
|
CONF_EVENT = "event"
|
||||||
CONF_EVENT_TYPE = "event_type"
|
CONF_EVENT_TYPE = "event_type"
|
||||||
CONF_EVENT_TYPES = "event_types"
|
CONF_EVENT_TYPES = "event_types"
|
||||||
|
|
|
@ -8,6 +8,7 @@ from esphome.const import (
|
||||||
CONF_COMMENT,
|
CONF_COMMENT,
|
||||||
CONF_ESPHOME,
|
CONF_ESPHOME,
|
||||||
CONF_ETHERNET,
|
CONF_ETHERNET,
|
||||||
|
CONF_MODEM,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
CONF_USE_ADDRESS,
|
CONF_USE_ADDRESS,
|
||||||
CONF_WEB_SERVER,
|
CONF_WEB_SERVER,
|
||||||
|
@ -565,6 +566,9 @@ class EsphomeCore:
|
||||||
if CONF_ETHERNET in self.config:
|
if CONF_ETHERNET in self.config:
|
||||||
return self.config[CONF_ETHERNET][CONF_USE_ADDRESS]
|
return self.config[CONF_ETHERNET][CONF_USE_ADDRESS]
|
||||||
|
|
||||||
|
if CONF_MODEM in self.config:
|
||||||
|
return self.config[CONF_MODEM][CONF_USE_ADDRESS]
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -22,6 +22,7 @@ const float BLUETOOTH = 350.0f;
|
||||||
const float AFTER_BLUETOOTH = 300.0f;
|
const float AFTER_BLUETOOTH = 300.0f;
|
||||||
const float WIFI = 250.0f;
|
const float WIFI = 250.0f;
|
||||||
const float ETHERNET = 250.0f;
|
const float ETHERNET = 250.0f;
|
||||||
|
const float MODEM = 250.0f;
|
||||||
const float BEFORE_CONNECTION = 220.0f;
|
const float BEFORE_CONNECTION = 220.0f;
|
||||||
const float AFTER_WIFI = 200.0f;
|
const float AFTER_WIFI = 200.0f;
|
||||||
const float AFTER_CONNECTION = 100.0f;
|
const float AFTER_CONNECTION = 100.0f;
|
||||||
|
|
|
@ -31,6 +31,7 @@ extern const float BLUETOOTH;
|
||||||
extern const float AFTER_BLUETOOTH;
|
extern const float AFTER_BLUETOOTH;
|
||||||
extern const float WIFI;
|
extern const float WIFI;
|
||||||
extern const float ETHERNET;
|
extern const float ETHERNET;
|
||||||
|
extern const float MODEM;
|
||||||
/// For components that should be initialized after WiFi and before API is connected.
|
/// For components that should be initialized after WiFi and before API is connected.
|
||||||
extern const float BEFORE_CONNECTION;
|
extern const float BEFORE_CONNECTION;
|
||||||
/// For components that should be initialized after WiFi is connected.
|
/// For components that should be initialized after WiFi is connected.
|
||||||
|
|
|
@ -11,3 +11,6 @@ dependencies:
|
||||||
path: components/mdns
|
path: components/mdns
|
||||||
rules:
|
rules:
|
||||||
- if: "idf_version >=5.0"
|
- if: "idf_version >=5.0"
|
||||||
|
esp_modem:
|
||||||
|
git: https://github.com/espressif/esp-protocols.git
|
||||||
|
path: components/esp_modem
|
Loading…
Reference in a new issue