initial refactoring

This commit is contained in:
Sebastien L
2023-12-04 23:25:57 -05:00
parent d03678ea81
commit c0ddf0a997
331 changed files with 29663 additions and 16553 deletions

View File

@@ -5,10 +5,43 @@ if(IDF_TARGET STREQUAL "esp32")
set(target_requires "driver_bt")
endif()
idf_component_register( SRC_DIRS . webapp UML-State-Machine-in-C/src
INCLUDE_DIRS . webapp UML-State-Machine-in-C/src
idf_component_register( SRC_DIRS . UML-State-Machine-in-C/src
INCLUDE_DIRS . UML-State-Machine-in-C/src
REQUIRES squeezelite-ota json mdns
PRIV_REQUIRES tools services platform_config esp_common json newlib freertos spi_flash nvs_flash mdns pthread wpa_supplicant platform_console esp_http_server console ${target_requires}
)
include(webapp/webapp.cmake)
# Define the source and destination directories
set(WEBAPP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/webapp/dist")
set(WEBAPP_DEST_DIR "${CMAKE_SOURCE_DIR}/spiffs/www")
# Collect all .gz and .png files in the source directory
file(GLOB_RECURSE WEBAPP_FILES
"${WEBAPP_SOURCE_DIR}/*.gz"
"${WEBAPP_SOURCE_DIR}/*.png")
# # Custom command to copy files, preserving the directory structure
# foreach(FILE_PATH ${WEBAPP_FILES})
# # Get the relative path from the source directory
# file(RELATIVE_PATH REL_PATH "${WEBAPP_SOURCE_DIR}" "${FILE_PATH}")
# # Compute the destination file path
# set(DEST_PATH "${WEBAPP_DEST_DIR}/${REL_PATH}")
# # Create a custom command to copy each file
# add_custom_command(
# OUTPUT "${DEST_PATH}"
# COMMAND ${CMAKE_COMMAND} -E copy "${FILE_PATH}" "${DEST_PATH}"
# DEPENDS "${FILE_PATH}"
# )
# # Add the destination path to a list of outputs
# list(APPEND WEBAPP_OUTPUT_FILES "${DEST_PATH}")
# endforeach()
# # Custom target that depends on all copied files
# add_custom_target(copy_webapp DEPENDS ${WEBAPP_OUTPUT_FILES} )
# # Ensure the destination directory exists
# add_custom_command(TARGET copy_webapp PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${WEBAPP_DEST_DIR}" )
# add_dependencies(${COMPONENT_LIB} copy_webapp)

View File

@@ -0,0 +1,285 @@
#include "esp32_improv.h"
namespace esp32_improv {
static const char *const TAG = "esp32_improv.component";
static const char *const ESPHOME_MY_LINK = "https://my.home-assistant.io/redirect/config_flow_start?domain=esphome";
namespace esp32_improv {
void ESP32Improv::setup() {
this->service_ = global_ble_server->create_service(improv::SERVICE_UUID, true);
this->setup_characteristics();
}
void ESP32Improv::setup_characteristics() {
this->status_ = this->service_->create_characteristic(
improv::STATUS_UUID,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor *status_descriptor = new BLE2902();
this->status_->add_descriptor(status_descriptor);
this->error_ = this->service_->create_characteristic(
improv::ERROR_UUID,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor *error_descriptor = new BLE2902();
this->error_->add_descriptor(error_descriptor);
this->rpc_ = this->service_->create_characteristic(
improv::RPC_COMMAND_UUID,
BLECharacteristic::PROPERTY_WRITE);
this->rpc_->on_write([this](const std::vector<uint8_t> &data) {
if (!data.empty()) {
this->incoming_data_.insert(this->incoming_data_.end(), data.begin(), data.end());
}
});
BLEDescriptor *rpc_descriptor = new BLE2902();
this->rpc_->add_descriptor(rpc_descriptor);
this->rpc_response_ = this->service_->create_characteristic(
improv::RPC_RESULT_UUID,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor *rpc_response_descriptor = new BLE2902();
this->rpc_response_->add_descriptor(rpc_response_descriptor);
this->capabilities_ =
this->service_->create_characteristic(
improv::CAPABILITIES_UUID,
BLECharacteristic::PROPERTY_READ);
BLEDescriptor *capabilities_descriptor = new BLE2902();
this->capabilities_->add_descriptor(capabilities_descriptor);
uint8_t capabilities = 0x00;
if (this->status_indicator_ != nullptr)
capabilities |= improv::CAPABILITY_IDENTIFY;
this->capabilities_->set_value(capabilities);
this->setup_complete_ = true;
}
void ESP32Improv::loop() {
if (!this->incoming_data_.empty())
this->process_incoming_data_();
uint32_t now = gettime_ms();
switch (this->state_) {
case improv::STATE_STOPPED:
if (this->status_indicator_ != nullptr)
this->status_indicator_->turn_off();
if (this->service_->is_created() && this->should_start_ && this->setup_complete_) {
if (this->service_->is_running()) {
esp32_ble::global_ble->get_advertising()->start();
this->set_state_(improv::STATE_AWAITING_AUTHORIZATION);
this->set_error_(improv::ERROR_NONE);
this->should_start_ = false;
ESP_LOGD(TAG, "Service started!");
} else {
this->service_->start();
}
}
break;
case improv::STATE_AWAITING_AUTHORIZATION: {
if (this->authorizer_ == nullptr || this->authorizer_->state) {
this->set_state_(improv::STATE_AUTHORIZED);
this->authorized_start_ = now;
} else {
if (this->status_indicator_ != nullptr) {
if (!this->check_identify_())
this->status_indicator_->turn_on();
}
}
break;
}
case improv::STATE_AUTHORIZED: {
if (this->authorizer_ != nullptr) {
if (now - this->authorized_start_ > this->authorized_duration_) {
ESP_LOGD(TAG, "Authorization timeout");
this->set_state_(improv::STATE_AWAITING_AUTHORIZATION);
return;
}
}
if (this->status_indicator_ != nullptr) {
if (!this->check_identify_()) {
if ((now % 1000) < 500) {
this->status_indicator_->turn_on();
} else {
this->status_indicator_->turn_off();
}
}
}
break;
}
case improv::STATE_PROVISIONING: {
if (this->status_indicator_ != nullptr) {
if ((now % 200) < 100) {
this->status_indicator_->turn_on();
} else {
this->status_indicator_->turn_off();
}
}
if (wifi::global_wifi_component->is_connected()) {
wifi::global_wifi_component->save_wifi_sta(this->connecting_sta_.get_ssid(),
this->connecting_sta_.get_password());
this->connecting_sta_ = {};
this->cancel_timeout("wifi-connect-timeout");
this->set_state_(improv::STATE_PROVISIONED);
std::vector<std::string> urls = {ESPHOME_MY_LINK};
#ifdef USE_WEBSERVER
auto ip = wifi::global_wifi_component->wifi_sta_ip();
std::string webserver_url = "http://" + ip.str() + ":" + to_string(USE_WEBSERVER_PORT);
urls.push_back(webserver_url);
#endif
std::vector<uint8_t> data = improv::build_rpc_response(improv::WIFI_SETTINGS, urls);
this->send_response_(data);
this->set_timeout("end-service", 1000, [this] {
this->service_->stop();
this->set_state_(improv::STATE_STOPPED);
});
}
break;
}
case improv::STATE_PROVISIONED: {
this->incoming_data_.clear();
if (this->status_indicator_ != nullptr)
this->status_indicator_->turn_off();
break;
}
}
}
bool ESP32Improv::check_identify_() {
uint32_t now = gettime_ms();
bool identify = this->identify_start_ != 0 && now - this->identify_start_ <= this->identify_duration_;
if (identify) {
uint32_t time = now % 1000;
if (time < 600 && time % 200 < 100) {
this->status_indicator_->turn_on();
} else {
this->status_indicator_->turn_off();
}
}
return identify;
}
void ESP32Improv::set_state_(improv::State state) {
ESP_LOGV(TAG, "Setting state: %d", state);
this->state_ = state;
if (this->status_->get_value().empty() || this->status_->get_value()[0] != state) {
uint8_t data[1]{state};
this->status_->set_value(data, 1);
if (state != improv::STATE_STOPPED)
this->status_->notify();
}
}
void ESP32Improv::set_error_(improv::Error error) {
if (error != improv::ERROR_NONE)
ESP_LOGE(TAG, "Error: %d", error);
if (this->error_->get_value().empty() || this->error_->get_value()[0] != error) {
uint8_t data[1]{error};
this->error_->set_value(data, 1);
if (this->state_ != improv::STATE_STOPPED)
this->error_->notify();
}
}
void ESP32Improv::send_response_(std::vector<uint8_t> &response) {
this->rpc_response_->set_value(response);
if (this->state_ != improv::STATE_STOPPED)
this->rpc_response_->notify();
}
void ESP32Improv::start() {
if (this->state_ != improv::STATE_STOPPED)
return;
ESP_LOGD(TAG, "Setting Improv to start");
this->should_start_ = true;
}
void ESP32Improv::stop() {
this->set_timeout("end-service", 1000, [this] {
this->service_->stop();
this->set_state_(improv::STATE_STOPPED);
});
}
float ESP32Improv::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; }
void ESP32Improv::dump_config() {
ESP_LOGCONFIG(TAG, "ESP32 Improv:");
LOG_BINARY_SENSOR(" ", "Authorizer", this->authorizer_);
ESP_LOGCONFIG(TAG, " Status Indicator: '%s'", YESNO(this->status_indicator_ != nullptr));
}
void ESP32Improv::process_incoming_data_() {
uint8_t length = this->incoming_data_[1];
ESP_LOGD(TAG, "Processing bytes - %s", format_hex_pretty(this->incoming_data_).c_str());
if (this->incoming_data_.size() - 3 == length) {
this->set_error_(improv::ERROR_NONE);
improv::ImprovCommand command = improv::parse_improv_data(this->incoming_data_);
switch (command.command) {
case improv::BAD_CHECKSUM:
ESP_LOGW(TAG, "Error decoding Improv payload");
this->set_error_(improv::ERROR_INVALID_RPC);
this->incoming_data_.clear();
break;
case improv::WIFI_SETTINGS: {
if (this->state_ != improv::STATE_AUTHORIZED) {
ESP_LOGW(TAG, "Settings received, but not authorized");
this->set_error_(improv::ERROR_NOT_AUTHORIZED);
this->incoming_data_.clear();
return;
}
wifi::WiFiAP sta{};
sta.set_ssid(command.ssid);
sta.set_password(command.password);
this->connecting_sta_ = sta;
wifi::global_wifi_component->set_sta(sta);
wifi::global_wifi_component->start_scanning();
this->set_state_(improv::STATE_PROVISIONING);
ESP_LOGD(TAG, "Received Improv wifi settings ssid=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(),
command.password.c_str());
auto f = std::bind(&ESP32Improv::on_wifi_connect_timeout_, this);
this->set_timeout("wifi-connect-timeout", 30000, f);
this->incoming_data_.clear();
break;
}
case improv::IDENTIFY:
this->incoming_data_.clear();
this->identify_start_ = gettime_ms();
break;
default:
ESP_LOGW(TAG, "Unknown Improv payload");
this->set_error_(improv::ERROR_UNKNOWN_RPC);
this->incoming_data_.clear();
}
} else if (this->incoming_data_.size() - 2 > length) {
ESP_LOGV(TAG, "Too much data came in, or malformed resetting buffer...");
this->incoming_data_.clear();
} else {
ESP_LOGV(TAG, "Waiting for split data packets...");
}
}
void ESP32Improv::on_wifi_connect_timeout_() {
this->set_error_(improv::ERROR_UNABLE_TO_CONNECT);
this->set_state_(improv::STATE_AUTHORIZED);
if (this->authorizer_ != nullptr)
this->authorized_start_ = gettime_ms();
ESP_LOGW(TAG, "Timed out trying to connect to given WiFi network");
wifi::global_wifi_component->clear_sta();
}
void ESP32Improv::on_client_disconnect() { this->set_error_(improv::ERROR_NONE); };
ESP32Improv *global_improv_component = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
} // namespace esp32_improv

View File

@@ -0,0 +1,71 @@
#pragma once
#include <improv.h>
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_gap_bt_api.h"
#include "bt_app_core.h"
#include "BLECharacteristic.h"
//#include "esphome/components/esp32_ble_server/ble_server.h"
namespace esp32_improv {
class ESP32Improv {
public:
ESP32Improv();
void dump_config() ;
void loop() ;
void setup() ;
void setup_characteristics();
void on_client_disconnect() ;
float get_setup_priority() ;
void start() ;
void stop() ;
bool is_active() const { return this->state_ != improv::STATE_STOPPED; }
void set_authorizer(binary_sensor::BinarySensor *authorizer) { this->authorizer_ = authorizer; }
void set_status_indicator(output::BinaryOutput *status_indicator) { this->status_indicator_ = status_indicator; }
void set_identify_duration(uint32_t identify_duration) { this->identify_duration_ = identify_duration; }
void set_authorized_duration(uint32_t authorized_duration) { this->authorized_duration_ = authorized_duration; }
protected:
bool should_start_{false};
bool setup_complete_{false};
uint32_t identify_start_{0};
uint32_t identify_duration_;
uint32_t authorized_start_{0};
uint32_t authorized_duration_;
std::vector<uint8_t> incoming_data_;
wifi::WiFiAP connecting_sta_;
std::shared_ptr<BLEService> service_;
BLECharacteristic *status_;
BLECharacteristic *error_;
BLECharacteristic *rpc_;
BLECharacteristic *rpc_response_;
BLECharacteristic *capabilities_;
binary_sensor::BinarySensor *authorizer_{nullptr};
output::BinaryOutput *status_indicator_{nullptr};
improv::State state_{improv::STATE_STOPPED};
improv::Error error_state_{improv::ERROR_NONE};
void set_state_(improv::State state);
void set_error_(improv::Error error);
void send_response_(std::vector<uint8_t> &response);
void process_incoming_data_();
void on_wifi_connect_timeout_();
bool check_identify_();
};
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
extern ESP32ImprovComponent *global_improv_component;
} // namespace esp32_improv

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,6 @@ Copyright (c) 2017-2021 Sebastien L
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include <esp_event.h>
#include "nvs_flash.h"
#include "esp_log.h"
#include "driver/gpio.h"
@@ -47,7 +46,6 @@ extern "C" {
esp_err_t root_get_handler(httpd_req_t *req);
esp_err_t resource_filehandler(httpd_req_t *req);
esp_err_t ap_get_handler(httpd_req_t *req);
esp_err_t config_get_handler(httpd_req_t *req);
esp_err_t config_post_handler(httpd_req_t *req);
esp_err_t connect_post_handler(httpd_req_t *req);
@@ -63,7 +61,8 @@ esp_err_t console_cmd_post_handler(httpd_req_t *req);
esp_err_t ap_scan_handler(httpd_req_t *req);
esp_err_t redirect_ev_handler(httpd_req_t *req);
esp_err_t redirect_200_ev_handler(httpd_req_t *req);
esp_err_t configurator_post_handler(httpd_req_t *req);
esp_err_t configurator_get_handler(httpd_req_t *req);
esp_err_t err_handler(httpd_req_t *req, httpd_err_code_t error);
#define SCRATCH_BUFSIZE (10240)

View File

@@ -6,15 +6,15 @@ static EXT_RAM_ATTR spi_device_interface_config_t devcfg;
static EXT_RAM_ATTR esp_netif_config_t cfg_spi;
static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config;
static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
static esp_err_t start(spi_device_handle_t spi_handle, sys_Eth* ethernet_config) {
#ifdef CONFIG_ETH_SPI_ETHERNET_DM9051
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_dm9051_config_t eth_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
// we assume that isr has been installed already
eth_config.int_gpio_num = ethernet_config->intr;
eth_config.int_gpio_num = ethernet_config->ethType.spi.has_intr?ethernet_config->ethType.spi.intr.pin:-1;
phy_config.phy_addr = -1;
phy_config.reset_gpio_num = ethernet_config->rst;
phy_config.reset_gpio_num = ethernet_config->common.has_rst?ethernet_config->common.rst.pin:-1;
esp_eth_mac_t* mac = esp_eth_mac_new_dm9051(&eth_config, &mac_config);
esp_eth_phy_t* phy = esp_eth_phy_new_dm9051(&phy_config);
@@ -25,14 +25,14 @@ static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* ethernet_co
#endif
}
static void init_config(eth_config_t* ethernet_config) {
static void init_config(sys_Eth* ethernet_config) {
esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
devcfg.command_bits = 1;
devcfg.address_bits = 7;
devcfg.mode = 0;
devcfg.clock_speed_hz = ethernet_config->speed > 0 ? ethernet_config->speed : SPI_MASTER_FREQ_20M; // default speed
devcfg.clock_speed_hz = ethernet_config->ethType.spi.speed > 0 ? ethernet_config->ethType.spi.speed : SPI_MASTER_FREQ_20M; // default speed
devcfg.queue_size = 20;
devcfg.spics_io_num = ethernet_config->cs;
devcfg.spics_io_num = ethernet_config->ethType.spi.has_cs?ethernet_config->ethType.spi.cs.pin:-1;
memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config));
cfg_spi.base = &esp_netif_config,
cfg_spi.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH;
@@ -41,8 +41,9 @@ static void init_config(eth_config_t* ethernet_config) {
DM9051.start = start;
}
network_ethernet_driver_t* DM9051_Detect(char* Driver) {
if (!strcasestr(Driver, "DM9051"))
network_ethernet_driver_t* DM9051_Detect(sys_Eth* ethernet_config) {
if (ethernet_config->common.model != sys_EthModelEnum_DM9051 ||
ethernet_config->which_ethType != sys_Eth_spi_tag )
return NULL;
DM9051.rmii = false;
DM9051.spi = true;
@@ -52,5 +53,6 @@ network_ethernet_driver_t* DM9051_Detect(char* Driver) {
DM9051.valid = false;
#endif
DM9051.init_config = init_config;
DM9051.model = ethernet_config->common.model;
return &DM9051;
}

View File

@@ -5,15 +5,15 @@ static EXT_RAM_ATTR network_ethernet_driver_t LAN8720;
static EXT_RAM_ATTR esp_netif_config_t cfg_rmii;
static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config;
static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
static esp_err_t start(spi_device_handle_t spi_handle, sys_Eth * ethernet_config) {
#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
mac_config.smi_mdc_gpio_num = ethernet_config->mdc;
mac_config.smi_mdio_gpio_num = ethernet_config->mdio;
mac_config.smi_mdc_gpio_num = ethernet_config->ethType.rmii.has_mdc?ethernet_config->ethType.rmii.mdc.pin:-1;
mac_config.smi_mdio_gpio_num = ethernet_config->ethType.rmii.has_mdio?ethernet_config->ethType.rmii.mdio.pin:-1;
phy_config.phy_addr = 1;
phy_config.reset_gpio_num = ethernet_config->rst;
phy_config.reset_gpio_num = ethernet_config->common.has_rst?ethernet_config->common.rst.pin:-1;
esp_eth_mac_t* mac = esp_eth_mac_new_esp32(&mac_config);
esp_eth_phy_t* phy = esp_eth_phy_new_lan8720(&phy_config);
@@ -24,7 +24,7 @@ static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* ethernet_co
#endif
}
static void init_config(eth_config_t* ethernet_config) {
static void init_config(sys_Eth * ethernet_config) {
esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config));
@@ -35,8 +35,9 @@ static void init_config(eth_config_t* ethernet_config) {
LAN8720.start = start;
}
network_ethernet_driver_t* LAN8720_Detect(char* Driver) {
if (!strcasestr(Driver, "LAN8720"))
network_ethernet_driver_t* LAN8720_Detect(sys_Eth * ethernet_config) {
if (ethernet_config->common.model != sys_EthModelEnum_LAN8720 ||
ethernet_config->which_ethType != sys_Eth_rmii_tag)
return NULL;
#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
LAN8720.valid = true;
@@ -45,6 +46,7 @@ network_ethernet_driver_t* LAN8720_Detect(char* Driver) {
#endif
LAN8720.rmii = true;
LAN8720.spi = false;
LAN8720.model = ethernet_config->common.model;
LAN8720.init_config = init_config;
return &LAN8720;
}

View File

@@ -6,15 +6,15 @@ static EXT_RAM_ATTR spi_device_interface_config_t devcfg;
static EXT_RAM_ATTR esp_netif_config_t cfg_spi;
static EXT_RAM_ATTR esp_netif_inherent_config_t esp_netif_config;
static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
static esp_err_t start(spi_device_handle_t spi_handle, sys_Eth * ethernet_config) {
#ifdef CONFIG_ETH_SPI_ETHERNET_W5500
eth_w5500_config_t eth_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
eth_config.int_gpio_num = ethernet_config->intr;
eth_config.int_gpio_num = ethernet_config->ethType.spi.has_intr?ethernet_config->ethType.spi.intr.pin:-1;
phy_config.phy_addr = -1; // let the system automatically find out the phy address
phy_config.reset_gpio_num = ethernet_config->rst;
phy_config.reset_gpio_num = ethernet_config->common.has_rst?ethernet_config->common.rst.pin:-1;
esp_eth_mac_t* mac = esp_eth_mac_new_w5500(&eth_config, &mac_config);
esp_eth_phy_t* phy = esp_eth_phy_new_w5500(&phy_config);
@@ -24,7 +24,7 @@ static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* ethernet_co
return ESP_ERR_NOT_SUPPORTED;
#endif
}
static void init_config(eth_config_t* ethernet_config) {
static void init_config(sys_Eth * ethernet_config) {
// This function is called when the network interface is started
// and performs any initialization that requires a valid ethernet
// configuration .
@@ -32,9 +32,9 @@ static void init_config(eth_config_t* ethernet_config) {
devcfg.command_bits = 16; // Actually it's the address phase in W5500 SPI frame
devcfg.address_bits = 8; // Actually it's the control phase in W5500 SPI frame
devcfg.mode = 0;
devcfg.clock_speed_hz = ethernet_config->speed > 0 ? ethernet_config->speed : SPI_MASTER_FREQ_20M; // default speed
devcfg.clock_speed_hz = ethernet_config->ethType.spi.speed > 0 ? ethernet_config->ethType.spi.speed : SPI_MASTER_FREQ_20M; // default speed
devcfg.queue_size = 20;
devcfg.spics_io_num = ethernet_config->cs;
devcfg.spics_io_num = ethernet_config->ethType.spi.has_cs?ethernet_config->ethType.spi.cs.pin:-1;
memcpy(&esp_netif_config, &loc_esp_netif_config, sizeof(loc_esp_netif_config));
cfg_spi.base = &esp_netif_config,
cfg_spi.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH;
@@ -43,12 +43,14 @@ static void init_config(eth_config_t* ethernet_config) {
W5500.start = start;
}
network_ethernet_driver_t* W5500_Detect(char* Driver, network_ethernet_driver_t* Device) {
if (!strcasestr(Driver, "W5500"))
network_ethernet_driver_t* W5500_Detect(sys_Eth * ethernet_config) {
if (ethernet_config->common.model != sys_EthModelEnum_W5500 ||
ethernet_config->which_ethType != sys_Eth_spi_tag )
return NULL;
W5500.init_config = init_config;
W5500.spi = true;
W5500.rmii = false;
W5500.model = ethernet_config->common.model;
#ifdef CONFIG_ETH_SPI_ETHERNET_W5500
W5500.valid = true;
#else

View File

@@ -5,11 +5,12 @@
#include "freertos/timers.h"
#include "messaging.h"
#include "network_status.h"
#include "platform_config.h"
#include "tools.h"
// #include "Configurator.h"
#pragma message("fixme: search for TODO below")
#include "accessors.h"
#include "esp_log.h"
#include "globdefs.h"
#include "tools.h"
static char TAG[] = "network_ethernet";
TimerHandle_t ETH_timer;
@@ -17,39 +18,24 @@ esp_netif_t* eth_netif = NULL;
EventGroupHandle_t ethernet_event_group;
const int LINK_UP_BIT = BIT0;
static const char* known_drivers[] = {"DM9051", "W5500", "LAN8720", NULL};
static network_ethernet_driver_t* network_driver = NULL;
extern network_ethernet_detect_func_t DM9051_Detect, W5500_Detect, LAN8720_Detect;
static network_ethernet_detect_func_t* drivers[] = {DM9051_Detect, W5500_Detect, LAN8720_Detect, NULL};
static network_ethernet_detect_func_t* drivers[] = {
DM9051_Detect, W5500_Detect, LAN8720_Detect, NULL};
#define ETH_TIMEOUT_MS (30 * 1000)
/****************************************************************************************
*
*/
const char* network_ethernet_conf_get_driver_name(const char* driver) {
for (uint8_t i = 0; known_drivers[i] != NULL && strlen(known_drivers[i]) > 0; i++) {
if (strcasestr(driver, known_drivers[i])) {
return known_drivers[i];
}
}
return NULL;
}
/****************************************************************************************
*
*/
bool network_ethernet_is_valid_driver(const char* driver) {
return network_ethernet_conf_get_driver_name(driver) != NULL;
}
network_ethernet_driver_t* network_ethernet_driver_autodetect() {
sys_Eth* eth_config;
sys_EthCommon* eth_common;
network_ethernet_driver_t* network_ethernet_driver_autodetect(const char* Driver) {
if (!Driver)
if (!SYS_ETH(eth_config) || !SYS_ETH_COMMON(eth_common)) {
ESP_LOGD(TAG, "Ethernet not configured");
return NULL;
for (int i = 0; drivers[i]; i++) {
network_ethernet_driver_t* found_driver = drivers[i](Driver);
}
for (uint8_t i = _sys_EthModelEnum_MIN; i < _sys_EthModelEnum_MAX; i++) {
network_ethernet_driver_t* found_driver = drivers[i](eth_config);
if (found_driver) {
ESP_LOGI(TAG, "Detected driver %s ", Driver);
ESP_LOGI(TAG, "Detected driver %s ", sys_EthModelEnum_name(eth_common->model));
network_driver = found_driver;
return found_driver;
}
@@ -57,82 +43,107 @@ network_ethernet_driver_t* network_ethernet_driver_autodetect(const char* Driver
return NULL;
}
static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
esp_netif_t *network_ethernet_get_interface(){
return eth_netif;
}
static void eth_event_handler(
void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
esp_netif_t* network_ethernet_get_interface() { return eth_netif; }
bool network_ethernet_is_up() {
return (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT)!=0;
return (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT) != 0;
}
bool network_ethernet_enabled() {
return network_driver !=NULL && network_driver->handle != NULL;
}
bool network_ethernet_wait_for_link(uint16_t max_wait_ms){
if(!network_ethernet_enabled()) return false;
bool link_up=(xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT)!=0;
if(!link_up){
ESP_LOGD(TAG,"Waiting for Ethernet link to be established...");
link_up = (xEventGroupWaitBits(ethernet_event_group, LINK_UP_BIT,pdFALSE, pdTRUE, max_wait_ms / portTICK_PERIOD_MS)& LINK_UP_BIT)!=0;
if(!link_up){
ESP_LOGW(TAG,"Ethernet Link timeout.");
}
else
{
ESP_LOGI(TAG,"Ethernet Link Up!");
}
}
bool network_ethernet_enabled() { return network_driver != NULL && network_driver->handle != NULL; }
bool network_ethernet_wait_for_link(uint16_t max_wait_ms) {
if (!network_ethernet_enabled()) return false;
bool link_up = (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT) != 0;
if (!link_up) {
ESP_LOGD(TAG, "Waiting for Ethernet link to be established...");
link_up = (xEventGroupWaitBits(ethernet_event_group, LINK_UP_BIT, pdFALSE, pdTRUE,
max_wait_ms / portTICK_PERIOD_MS) &
LINK_UP_BIT) != 0;
if (!link_up) {
ESP_LOGW(TAG, "Ethernet Link timeout.");
} else {
ESP_LOGI(TAG, "Ethernet Link Up!");
}
}
return link_up;
}
static void ETH_Timeout(void* timer_id);
void destroy_network_ethernet() {
}
void destroy_network_ethernet() {}
static void network_ethernet_print_config(const eth_config_t* eth_config) {
ESP_LOGI(TAG,"Ethernet config => model: %s, valid: %s, type: %s, mdc:%d, mdio:%d, rst:%d, intr:%d, cs:%d, speed:%d, host:%d",
eth_config->model, eth_config->valid ? "YES" : "NO", eth_config->spi ? "SPI" : "RMII",
eth_config->mdc, eth_config->mdio,
eth_config->rst, eth_config->intr, eth_config->cs, eth_config->speed, eth_config->host);
}
static void network_ethernet_print_config(const network_ethernet_driver_t* eth_config) {
sys_Eth* sys_eth;
int mdc = -1, mdio = -1, rst = -1, intr = -1, cs = -1;
int16_t speed = 0;
int8_t host = 0;
if (SYS_ETH(sys_eth)) {
if (sys_eth->which_ethType == sys_Eth_spi_tag) {
if (sys_eth->ethType.spi.has_cs) {
cs = sys_eth->ethType.spi.cs.pin;
}
if (sys_eth->ethType.spi.has_intr) {
intr = sys_eth->ethType.spi.intr.pin;
}
speed = sys_eth->ethType.spi.speed;
host = sys_eth->ethType.spi.host;
} else if (sys_eth->which_ethType == sys_Eth_rmii_tag) {
if (sys_eth->ethType.rmii.has_mdc) {
mdc = sys_eth->ethType.rmii.mdc.pin;
}
if (sys_eth->ethType.rmii.has_mdio) {
mdio = sys_eth->ethType.rmii.mdio.pin;
}
}
}
ESP_LOGI(TAG,
"Ethernet config => model: %s, valid: %s, type: %s, mdc:%d, mdio:%d, rst:%d, intr:%d, "
"cs:%d, speed:%d, host:%d",
sys_EthModelEnum_name(eth_config->model), eth_config->valid ? "YES" : "NO",
eth_config->spi ? "SPI" : "RMII", mdc, mdio, rst, intr, cs, speed, host);
}
void init_network_ethernet() {
esp_err_t err = ESP_OK;
eth_config_t eth;
ESP_LOGI(TAG, "Attempting to initialize Ethernet");
config_eth_init(&eth);
if(!eth.valid){
ESP_LOGI(TAG,"No Ethernet configuration, or configuration invalid");
sys_Eth* sys_eth;
if(!SYS_ETH(sys_eth)){
ESP_LOGD(TAG,"No ethernet configured");
return;
}
network_ethernet_driver_t*driver= network_ethernet_driver_autodetect();
if (!driver || !driver->valid) {
ESP_LOGI(TAG, "No Ethernet configuration, or configuration invalid");
return;
}
network_driver->init_config(&eth);
network_ethernet_print_config(&eth);
network_driver->init_config(&platform->dev.eth);
network_ethernet_print_config(driver);
eth_netif = esp_netif_new(network_driver->cfg_netif);
esp_eth_set_default_handlers(eth_netif);
esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL);
ethernet_event_group = xEventGroupCreate();
xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT);
xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT);
spi_device_handle_t spi_handle = NULL;
if (network_driver->spi) {
err = spi_bus_add_device(eth.host, network_driver->devcfg, &spi_handle);
if (sys_eth->which_ethType == sys_Eth_spi_tag) {
err = spi_bus_add_device(sys_eth->ethType.spi.host, network_driver->devcfg, &spi_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "SPI host failed : %s", esp_err_to_name(err));
}
}
if (err == ESP_OK) {
err = network_driver->start(spi_handle,&eth);
err = network_driver->start(spi_handle, sys_eth);
}
if(err == ESP_OK){
if (err == ESP_OK) {
uint8_t mac_address[6];
esp_read_mac(mac_address,ESP_MAC_ETH);
char * mac_string=network_manager_alloc_get_mac_string(mac_address);
ESP_LOGD(TAG,"Assigning mac address %s to ethernet interface", STR_OR_BLANK(mac_string));
esp_read_mac(mac_address, ESP_MAC_ETH);
char* mac_string = network_manager_alloc_get_mac_string(mac_address);
ESP_LOGD(TAG, "Assigning mac address %s to ethernet interface", STR_OR_BLANK(mac_string));
FREE_AND_NULL(mac_string);
esp_eth_ioctl(network_driver->handle, ETH_CMD_S_MAC_ADDR, mac_address);
}
}
if (err == ESP_OK) {
ESP_LOGD(TAG, "Attaching ethernet to network interface");
err = esp_netif_attach(eth_netif, esp_eth_new_netif_glue(network_driver->handle));
@@ -140,11 +151,11 @@ void init_network_ethernet() {
if (err == ESP_OK) {
ESP_LOGI(TAG, "Starting ethernet network");
err = esp_eth_start(network_driver->handle);
}
if (err != ESP_OK) {
messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Configuring Ethernet failed: %s", esp_err_to_name(err));
if(spi_handle) {
messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM,
"Configuring Ethernet failed: %s", esp_err_to_name(err));
if (spi_handle) {
spi_bus_remove_device(spi_handle);
}
network_driver->handle = NULL;
@@ -152,43 +163,43 @@ void init_network_ethernet() {
}
void network_ethernet_start_timer() {
ETH_timer = xTimerCreate("ETH check", pdMS_TO_TICKS(ETH_TIMEOUT_MS), pdFALSE, NULL, ETH_Timeout);
ETH_timer =
xTimerCreate("ETH check", pdMS_TO_TICKS(ETH_TIMEOUT_MS), pdFALSE, NULL, ETH_Timeout);
}
/** Event handler for Ethernet events */
static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
static void eth_event_handler(
void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
uint8_t mac_addr[6] = {0};
/* we can get the ethernet driver handle from event data */
if (event_base == ETH_EVENT) {
esp_eth_handle_t eth_handle = *(esp_eth_handle_t*)event_data;
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
xEventGroupSetBits(ethernet_event_group, LINK_UP_BIT);
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ESP_LOGI(TAG, "");
ESP_LOGI(TAG, "Ethernet Link Up, HW Addr %02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
network_async_link_up();
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "Ethernet Link Down");
xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT);
network_async_link_down();
break;
case ETHERNET_EVENT_START:
ESP_LOGI(TAG, "Ethernet Started. Setting host name");
network_set_hostname(eth_netif);
network_async_success();
break;
case ETHERNET_EVENT_STOP:
ESP_LOGI(TAG, "Ethernet Stopped");
break;
default:
break;
case ETHERNET_EVENT_CONNECTED:
xEventGroupSetBits(ethernet_event_group, LINK_UP_BIT);
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ESP_LOGI(TAG, "");
ESP_LOGI(TAG, "Ethernet Link Up, HW Addr %02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0],
mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
network_async_link_up();
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "Ethernet Link Down");
xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT);
network_async_link_down();
break;
case ETHERNET_EVENT_START:
ESP_LOGI(TAG, "Ethernet Started. Setting host name");
network_set_hostname(eth_netif);
network_async_success();
break;
case ETHERNET_EVENT_STOP:
ESP_LOGI(TAG, "Ethernet Stopped");
break;
default:
break;
}
}
}
static void ETH_Timeout(void* timer_id) {
network_async_fail();
}
}
static void ETH_Timeout(void* timer_id) { network_async_fail(); }

View File

@@ -4,6 +4,7 @@
#include "accessors.h"
#include <string.h>
#include "esp_netif_defaults.h"
#include "Configurator.h"
#ifdef __cplusplus
extern "C" {
@@ -13,17 +14,18 @@ typedef struct {
bool valid;
bool rmii;
bool spi;
sys_EthModelEnum model;
esp_eth_handle_t handle;
esp_netif_config_t * cfg_netif;
spi_device_interface_config_t * devcfg;
// This function is called when the network interface is started
// and performs any initialization that requires a valid ethernet
// configuration .
void (*init_config)(eth_config_t * eth_config);
esp_err_t (*start)(spi_device_handle_t spi_handle,eth_config_t *ethernet_config);
void (*init_config)(sys_Eth * config);
esp_err_t (*start)(spi_device_handle_t spi_handle,sys_Eth * config);
} network_ethernet_driver_t;
typedef network_ethernet_driver_t* network_ethernet_detect_func_t(const char* Driver);
network_ethernet_driver_t* network_ethernet_driver_autodetect(const char* Driver);
typedef network_ethernet_driver_t* network_ethernet_detect_func_t(sys_Eth * config);
network_ethernet_driver_t* network_ethernet_driver_autodetect();
void destroy_network_ethernet();
void init_network_ethernet();
bool network_ethernet_wait_for_link(uint16_t max_wait_ms);

View File

@@ -38,7 +38,8 @@ Copyright (c) 2017-2021 Sebastien L
#include "mdns.h"
#include "messaging.h"
#include "platform_config.h"
// #include "Configurator.h"
#pragma message("fixme: look for TODO below")
#include "tools.h"
#include "trace.h"
@@ -46,6 +47,7 @@ Copyright (c) 2017-2021 Sebastien L
#include "esp_err.h"
#include "http_server_handlers.h"
#include "network_manager.h"
#include "Configurator.h"
QueueHandle_t network_queue;
BaseType_t network_task_handle;
@@ -405,14 +407,14 @@ void network_execute_cb(state_machine_t* const state_machine, const char * calle
}
bool network_is_wifi_prioritized() {
eth_config_t eth_config;
config_eth_init(&eth_config);
// char* prioritize = (char*)config_alloc_get_default(NVS_TYPE_STR, "prio_wifi", "N", 0);
// bool result = strcasecmp("N", prioritize);
sys_EthCommon * common = NULL;
bool result = s_wifi_prioritized;
bool valid_model = SYS_ETH_COMMON(common) && common->model == sys_EthModelEnum_UNSPECIFIED_ETHMODEL;
if(result){
result = network_wifi_get_known_count()>0 || !eth_config.valid;
ESP_LOGD(TAG,"Wifi is prioritized with %d known access points.%s %s",network_wifi_get_known_count(),eth_config.valid?" And a valid ethernet adapter":"",result?"Wifi prioritized":"Ethernet prioritized");
result = network_wifi_get_known_count()>0 || !valid_model;
ESP_LOGD(TAG,"Wifi is prioritized with %d known access points.%s %s",
network_wifi_get_known_count(),
valid_model?" And a valid ethernet adapter":"",result?"Wifi prioritized":"Ethernet prioritized");
}
return result;
}
@@ -421,10 +423,6 @@ void network_prioritize_wifi(bool activate) {
if(s_wifi_prioritized == activate) return;
s_wifi_prioritized = activate;
ESP_LOGI(TAG,"Wifi is %s prioritized",activate?"":"not");
// if (network_is_wifi_prioritized() != activate) {
// ESP_LOGW(TAG, "Wifi will %s be prioritized on next boot", activate ? "" : "NOT");
// config_set_value(NVS_TYPE_STR, "prio_wifi", activate ? "Y" : "N");
// }
}
@@ -727,16 +725,15 @@ void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t ev
void network_set_hostname(esp_netif_t* interface) {
esp_err_t err;
ESP_LOGD(TAG, "Retrieving host name from nvs");
char* host_name = (char*)config_alloc_get(NVS_TYPE_STR, "host_name");
if (host_name == NULL) {
if (!platform->has_names || strlen(platform->names.device) == 0 ) {
ESP_LOGE(TAG, "Could not retrieve host name from nvs");
} else {
ESP_LOGD(TAG, "Setting host name to : %s", host_name);
if ((err = esp_netif_set_hostname(interface, host_name)) != ESP_OK) {
ESP_LOGD(TAG, "Setting host name to : %s", platform->names.device);
if ((err = esp_netif_set_hostname(interface, platform->names.device)) != ESP_OK) {
ESP_LOGE(TAG, "Unable to set host name. Error: %s", esp_err_to_name(err));
}
free(host_name);
}
}
#define LOCAL_MAC_SIZE 20
char* network_manager_alloc_get_mac_string(uint8_t mac[6]) {

View File

@@ -4,7 +4,6 @@
#include "esp_wifi.h"
#include "esp_wifi_types.h"
#include "squeezelite-ota.h"
#include "cJSON.h"
#include "esp_eth.h"
#include "freertos/event_groups.h"
#include "hsm.h"
@@ -250,17 +249,6 @@ void network_reboot_ota(char * url);
* UPDATE_FAILED_ATTEMPT_AND_RESTORE - Web UI expects this when attempting to connect to a new access point fails and previous connection is restored
* UPDATE_ETHERNET_CONNECTED = 5
*/
typedef enum update_reason_code_t {
UPDATE_CONNECTION_OK = 0, // expected when
UPDATE_FAILED_ATTEMPT = 1,
UPDATE_USER_DISCONNECT = 2,
UPDATE_LOST_CONNECTION = 3,
UPDATE_FAILED_ATTEMPT_AND_RESTORE = 4,
UPDATE_ETHERNET_CONNECTED = 5
}update_reason_code_t;
@@ -278,10 +266,6 @@ void network_destroy();
void filter_unique( wifi_ap_record_t * aplist, uint16_t * ap_num);
char* network_status_alloc_get_ap_list_json();
cJSON * network_manager_clear_ap_list_json(cJSON **old);
/**
* @brief A standard wifi event handler as recommended by Espressif
@@ -290,14 +274,6 @@ esp_err_t network_manager_event_handler(void *ctx, system_event_t *event);
/**
* @brief Clears the connection status json.
* @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
*/
cJSON * network_status_clear_ip_info_json(cJSON **old);
cJSON * network_status_get_new_json(cJSON **old);
/**
* @brief Start the mDNS service

View File

@@ -34,7 +34,8 @@
#include "mdns.h"
#include "messaging.h"
#include "platform_config.h"
// #include "Configurator.h"
#pragma message("fixme: look for TODO below")
#include "trace.h"
#include "accessors.h"
@@ -166,7 +167,8 @@ static state_machine_result_t handle_global_event(state_machine_t* state_machine
case EN_UPDATE_STATUS:
// handle the event, but don't swicth
MEMTRACE_PRINT_DELTA_MESSAGE("handle EN_UPDATE_STATUS - start");
network_status_update_basic_info();
// todo: fix this
// network_status_update_basic_info();
MEMTRACE_PRINT_DELTA_MESSAGE("handle EN_UPDATE_STATUS - end");
return EVENT_HANDLED;
/* code */
@@ -224,16 +226,16 @@ static state_machine_result_t NETWORK_INSTANTIATED_STATE_handler(state_machine_t
network_t* const nm = (network_t *)State_Machine;
State_Machine->State = &network_states[NETWORK_INSTANTIATED_STATE];
State_Machine->Event = EN_START;
config_get_uint16t_from_str("pollmx",&nm->sta_polling_max_ms,600);
nm->sta_polling_max_ms = nm->sta_polling_max_ms * 1000;
config_get_uint16t_from_str("apdelay",&nm->ap_duration_ms,20);
nm->ap_duration_ms = nm->ap_duration_ms * 1000;
config_get_uint16t_from_str("pollmin",&nm->sta_polling_min_ms,15);
nm->sta_polling_min_ms = nm->sta_polling_min_ms*1000;
config_get_uint16t_from_str("ethtmout",&nm->eth_link_down_reboot_ms,30);
nm->eth_link_down_reboot_ms = nm->eth_link_down_reboot_ms*1000;
config_get_uint16t_from_str("dhcp_tmout",&nm->dhcp_timeout,30);
nm->dhcp_timeout = nm->dhcp_timeout*1000;
// config_get_uint16t_from_str("pollmx",&nm->sta_polling_max_ms,600);
// nm->sta_polling_max_ms = nm->sta_polling_max_ms * 1000;
// config_get_uint16t_from_str("apdelay",&nm->ap_duration_ms,20);
// nm->ap_duration_ms = nm->ap_duration_ms * 1000;
// config_get_uint16t_from_str("pollmin",&nm->sta_polling_min_ms,15);
// nm->sta_polling_min_ms = nm->sta_polling_min_ms*1000;
// config_get_uint16t_from_str("ethtmout",&nm->eth_link_down_reboot_ms,30);
// nm->eth_link_down_reboot_ms = nm->eth_link_down_reboot_ms*1000;
// config_get_uint16t_from_str("dhcp_tmout",&nm->dhcp_timeout,30);
// nm->dhcp_timeout = nm->dhcp_timeout*1000;
ESP_LOGI(TAG,"Network manager configuration: polling max %d, polling min %d, ap delay %d, dhcp timeout %d, eth timeout %d",
nm->sta_polling_max_ms,nm->sta_polling_min_ms,nm->ap_duration_ms,nm->dhcp_timeout, nm->eth_link_down_reboot_ms);
HANDLE_GLOBAL_EVENT(State_Machine);
@@ -386,13 +388,14 @@ static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_handler(state_machine_t*
break;
case EN_SCAN:
ESP_LOGW(TAG,"Wifi scan cannot be executed in this state");
network_wifi_built_known_ap_list();
//todo: fix this!
// network_wifi_built_known_ap_list();
result = EVENT_HANDLED;
break;
case EN_DELETE: {
ESP_LOGD(TAG, "WiFi disconnected by user");
network_wifi_clear_config();
network_status_update_ip_info(UPDATE_USER_DISCONNECT);
network_status_update_ip_info(sys_UPDATE_REASONS_R_USER_DISCONNECT);
result= EVENT_HANDLED;
} break;
default:
@@ -434,7 +437,7 @@ static state_machine_result_t ETH_CONNECTING_NEW_STATE_handler(state_machine_t*
result= local_traverse_state(State_Machine, &network_states[WIFI_CONNECTED_STATE],__FUNCTION__);
break;
case EN_LOST_CONNECTION:
network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT);
messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to connect to new WiFi access point.");
// no existing configuration, or wifi wasn't the active connection when connection
// attempt was made
@@ -528,7 +531,7 @@ static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_handler(state_machine_t*
network_interface_coexistence(State_Machine);
break;
case EN_GOT_IP:
network_status_update_ip_info(UPDATE_CONNECTION_OK);
network_status_update_ip_info(sys_UPDATE_REASONS_R_CONNECTION_OK);
result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
break;
case EN_SCAN:
@@ -715,7 +718,7 @@ static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_handler(state_machi
network_set_timer(nm->dhcp_timeout,"DHCP Timeout");
break;
case EN_GOT_IP:
network_status_update_ip_info(UPDATE_CONNECTION_OK);
network_status_update_ip_info(sys_UPDATE_REASONS_R_CONNECTION_OK);
result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_SUCCESS_STATE],__FUNCTION__);
break;
case EN_LOST_CONNECTION:
@@ -723,13 +726,13 @@ static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_handler(state_machi
ESP_LOGI(TAG,"Wifi was disconnected from previous access point. Waiting to connect.");
}
else {
network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT);
result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
}
break;
case EN_TIMER:
ESP_LOGW(TAG,"Connection timeout. (%s)",STR_OR_ALT(nm->timer_tag, "Unknown"));
network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT);
result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
break;
default:
@@ -752,9 +755,10 @@ static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_exit_handler(state_
*/
static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_entry_handler(state_machine_t* const State_Machine) {
network_handler_entry_print(State_Machine,true);
network_status_update_ip_info(UPDATE_CONNECTION_OK);
network_status_update_ip_info(sys_UPDATE_REASONS_R_CONNECTION_OK);
ESP_LOGD(TAG, "Saving wifi configuration.");
network_wifi_save_sta_config();
// todo: fix this!
// network_wifi_save_sta_config();
NETWORK_EXECUTE_CB(State_Machine);
network_handler_entry_print(State_Machine,false);
return EVENT_HANDLED;
@@ -765,11 +769,13 @@ static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_handler(sta
network_t* const nm = (network_t *)State_Machine;
switch (State_Machine->Event) {
case EN_UPDATE_STATUS:
network_status_update_basic_info();
// todo: fix this
// network_status_update_basic_info();
network_set_timer(nm->ap_duration_ms,"Access point teardown"); // set a timer to tear down the AP mode
break;
case EN_TIMER:
network_status_update_basic_info();
// todo: fix this
// network_status_update_basic_info();
result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
break;
default:
@@ -826,7 +832,7 @@ static state_machine_result_t WIFI_CONNECTING_STATE_handler(state_machine_t* con
ESP_LOGI(TAG,"Wifi was disconnected from previous access point. Waiting to connect.");
}
else if(nm->event_parameters->disconnected_event->reason != WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) {
network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT);
result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
}
break;
@@ -862,7 +868,7 @@ static state_machine_result_t WIFI_CONNECTING_NEW_STATE_handler(state_machine_t*
state_machine_result_t result = EVENT_HANDLED;
switch (State_Machine->Event) {
case EN_GOT_IP:
network_status_update_ip_info(UPDATE_CONNECTION_OK);
network_status_update_ip_info(sys_UPDATE_REASONS_R_CONNECTION_OK);
result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
break;
case EN_CONNECTED:
@@ -916,7 +922,7 @@ static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_handler(state_mac
state_machine_result_t result = EVENT_HANDLED;
switch (State_Machine->Event) {
case EN_GOT_IP:
network_status_update_ip_info(UPDATE_FAILED_ATTEMPT_AND_RESTORE);
network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT_AND_RESTORE);
result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
break;
case EN_CONNECTED:
@@ -924,7 +930,7 @@ static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_handler(state_mac
result = EVENT_HANDLED;
break;
case EN_LOST_CONNECTION:
network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
network_status_update_ip_info(sys_UPDATE_REASONS_R_FAILED_ATTEMPT);
messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to fall back to previous access point.");
result = EVENT_HANDLED;
break;
@@ -958,7 +964,7 @@ static state_machine_result_t WIFI_CONNECTED_STATE_entry_handler(state_machine_t
ESP_LOGD(TAG, "Checking if wifi config changed.");
if (network_wifi_sta_config_changed()) {
ESP_LOGD(TAG, "Wifi Config changed. Saving it.");
network_wifi_save_sta_config();
configurator_raise_changed();
}
ESP_LOGD(TAG, "Updating the ip info json.");
network_interface_coexistence(State_Machine);
@@ -997,7 +1003,7 @@ static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_entry_handler(state_m
network_handler_entry_print(State_Machine,true);
ESP_LOGD(TAG, " WiFi disconnected by user");
network_wifi_clear_config();
network_status_update_ip_info(UPDATE_USER_DISCONNECT);
network_status_update_ip_info(sys_UPDATE_REASONS_R_USER_DISCONNECT);
NETWORK_EXECUTE_CB(State_Machine);
network_handler_entry_print(State_Machine,false);
return EVENT_HANDLED;
@@ -1031,8 +1037,9 @@ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_mac
network_handler_entry_print(State_Machine,true);
ESP_LOGE(TAG, " WiFi Connection lost.");
messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "WiFi Connection lost");
network_status_update_ip_info(UPDATE_LOST_CONNECTION);
network_status_safe_reset_sta_ip_string();
network_status_update_ip_info(sys_UPDATE_REASONS_R_LOST_CONNECTION);
//todo: fix this!
// network_status_safe_reset_sta_ip_string();
if (nm->last_connected > 0)
nm->total_connected_time += ((esp_timer_get_time() - nm->last_connected) / (1000 * 1000));
nm->last_connected = 0;
@@ -1050,7 +1057,7 @@ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_mac
ESP_LOGW(TAG, "Cannot connect to Wifi. Falling back to Ethernet ");
network_async(EN_ETHERNET_FALLBACK);
} else {
network_status_update_ip_info(UPDATE_LOST_CONNECTION);
network_status_update_ip_info(sys_UPDATE_REASONS_R_LOST_CONNECTION);
wifi_mode_t mode;
ESP_LOGW(TAG, " All connect retry attempts failed.");
@@ -1109,7 +1116,7 @@ static state_machine_result_t WIFI_LOST_CONNECTION_STATE_exit_handler(state_mach
static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) {
network_t* const nm = (network_t *)State_Machine;
network_handler_entry_print(State_Machine,true);
network_status_update_ip_info(UPDATE_ETHERNET_CONNECTED);
network_status_update_ip_info(sys_UPDATE_REASONS_R_ETHERNET_CONNECTED);
nm->ethernet_connected = true;
// start a wifi Scan so web ui is populated with available entries
NETWORK_EXECUTE_CB(State_Machine);
@@ -1161,15 +1168,16 @@ static void network_interface_coexistence(state_machine_t* state_machine) {
// found to be active at the same time
network_t* nm = (network_t *)state_machine;
if (nm->wifi_connected && state_machine->Event == EN_ETH_GOT_IP) {
char* eth_reboot = config_alloc_get_default(NVS_TYPE_STR, "eth_boot", "N", 0);
network_prioritize_wifi(false);
if (strcasecmp(eth_reboot, "N")) {
ESP_LOGW(TAG, "Option eth_reboot set to reboot when ethernet is connected. Rebooting");
simple_restart();
} else {
ESP_LOGW(TAG, "Option eth_reboot set to not reboot when ethernet is connected. Using Wifi interface until next reboot");
}
FREE_AND_NULL(eth_reboot);
// char* eth_reboot = config_alloc_get_default(NVS_TYPE_STR, "eth_boot", "N", 0);
// network_prioritize_wifi(false);
// if (strcasecmp(eth_reboot, "N")) {
// ESP_LOGW(TAG, "Option eth_reboot set to reboot when ethernet is connected. Rebooting");
// simple_restart();
// } else {
// ESP_LOGW(TAG, "Option eth_reboot set to not reboot when ethernet is connected. Using Wifi interface until next reboot");
// }
// FREE_AND_NULL(eth_reboot);
// TODO: Add support for the commented code
} else if (get_root(state_machine->State)->Id == NETWORK_ETH_ACTIVE_STATE){
messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi Connected with Ethernet active. System reload needed");
simple_restart();

View File

@@ -12,7 +12,8 @@
#include "monitor.h"
#include "network_ethernet.h"
#include "network_wifi.h"
#include "platform_config.h"
// #include "Configurator.h"
#pragma message("fixme: search for TODO below")
#include "platform_esp32.h"
#include "tools.h"
#include "trace.h"
@@ -21,162 +22,69 @@
#define CONFIG_SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
#endif
static const char TAG[] = "network_status";
SemaphoreHandle_t network_status_json_mutex = NULL;
static TaskHandle_t network_json_locked_task = NULL;
SemaphoreHandle_t network_status_ip_address_mutex = NULL;
static TaskHandle_t network_status_ip_address_locked_task = NULL;
char* release_url = NULL;
char* network_status_ip_address = NULL;
char* ip_info_json = NULL;
cJSON* ip_info_cjson = NULL;
static char lms_server_ip[IP4ADDR_STRLEN_MAX] = {0};
static uint16_t lms_server_port = 0;
static uint16_t lms_server_cport = 0;
sys_Status status;
SemaphoreHandle_t network_status_structure_mutex = NULL;
static TaskHandle_t network_structure_locked_task = NULL;
static void (*chained_notify)(in_addr_t, u16_t, u16_t);
static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport);
#define STA_IP_LEN sizeof(char) * IP4ADDR_STRLEN_MAX
void init_network_status() {
chained_notify = server_notify;
server_notify = connect_notify;
ESP_LOGD(TAG, "init_network_status. Creating mutexes");
network_status_json_mutex = xSemaphoreCreateMutex();
network_status_ip_address_mutex = xSemaphoreCreateMutex();
ip_info_json = NULL;
ESP_LOGD(TAG, "init_network_status. Creating status json structure");
ip_info_cjson = network_status_clear_ip_info_json(&ip_info_cjson);
network_status_structure_mutex = xSemaphoreCreateMutex();
ESP_LOGD(TAG, "Getting release url ");
char* release_url = (char*)config_alloc_get_default(NVS_TYPE_STR, "release_url", QUOTE(CONFIG_SQUEEZELITE_ESP32_RELEASE_URL), 0);
if (release_url == NULL) {
ESP_LOGE(TAG, "Unable to retrieve the release url from nvs");
} else {
ESP_LOGD(TAG, "Found release url %s", release_url);
}
ESP_LOGD(TAG, "About to set the STA IP String to 0.0.0.0");
network_status_ip_address = (char*)malloc_init_external(STA_IP_LEN);
network_status_safe_update_sta_ip_string(NULL);
}
void destroy_network_status() {
FREE_AND_NULL(release_url);
FREE_AND_NULL(ip_info_json);
FREE_AND_NULL(network_status_ip_address);
cJSON_Delete(ip_info_cjson);
vSemaphoreDelete(network_status_json_mutex);
network_status_json_mutex = NULL;
vSemaphoreDelete(network_status_ip_address_mutex);
network_status_ip_address_mutex = NULL;
ip_info_cjson = NULL;
}
cJSON* network_status_get_new_json(cJSON** old) {
ESP_LOGV(TAG, "network_status_get_new_json called");
cJSON* root = *old;
if (root != NULL) {
cJSON_Delete(root);
*old = NULL;
}
ESP_LOGV(TAG, "network_status_get_new_json done");
return cJSON_CreateObject();
vSemaphoreDelete(network_status_structure_mutex);
network_status_structure_mutex = NULL;
}
cJSON* network_status_clear_ip_info_json(cJSON** old) {
ESP_LOGV(TAG, "network_status_clear_ip_info_json called");
cJSON* root = network_status_get_basic_info(old);
cJSON_DeleteItemFromObjectCaseSensitive(root, "ip");
cJSON_DeleteItemFromObjectCaseSensitive(root, "netmask");
cJSON_DeleteItemFromObjectCaseSensitive(root, "gw");
cJSON_DeleteItemFromObjectCaseSensitive(root, "rssi");
cJSON_DeleteItemFromObjectCaseSensitive(root, "ssid");
cJSON_DeleteItemFromObjectCaseSensitive(root, "eth");
ESP_LOGV(TAG, "network_status_clear_ip_info_json done");
return root;
}
void network_status_clear_ip() {
if (network_status_lock_json_buffer(portMAX_DELAY)) {
ip_info_cjson = network_status_clear_ip_info_json(&ip_info_cjson);
network_status_unlock_json_buffer();
}
}
char* network_status_alloc_get_ip_info_json() {
return cJSON_PrintUnformatted(ip_info_cjson);
}
void network_status_unlock_json_buffer() {
void network_status_unlock_structure() {
ESP_LOGV(TAG, "Unlocking json buffer!");
network_json_locked_task = NULL;
xSemaphoreGive(network_status_json_mutex);
network_structure_locked_task = NULL;
xSemaphoreGive(network_status_structure_mutex);
}
bool network_status_lock_json_buffer(TickType_t xTicksToWait) {
ESP_LOGV(TAG, "Locking json buffer");
bool network_status_lock_structure(TickType_t xTicksToWait) {
ESP_LOGV(TAG, "Locking structure buffer");
TaskHandle_t calling_task = xTaskGetCurrentTaskHandle();
if (calling_task == network_json_locked_task) {
ESP_LOGV(TAG, "json buffer already locked to current task");
if (calling_task == network_structure_locked_task) {
ESP_LOGV(TAG, "structure buffer already locked to current task");
return true;
}
if (network_status_json_mutex) {
if (xSemaphoreTake(network_status_json_mutex, xTicksToWait) == pdTRUE) {
ESP_LOGV(TAG, "Json buffer locked!");
network_json_locked_task = calling_task;
if (network_status_structure_mutex) {
if (xSemaphoreTake(network_status_structure_mutex, xTicksToWait) == pdTRUE) {
ESP_LOGV(TAG, "structure locked!");
network_structure_locked_task = calling_task;
return true;
} else {
ESP_LOGE(TAG, "Semaphore take failed. Unable to lock json buffer mutex");
ESP_LOGE(TAG, "Semaphore take failed. Unable to lock structure mutex");
return false;
}
} else {
ESP_LOGV(TAG, "Unable to lock json buffer mutex");
ESP_LOGV(TAG, "Unable to lock structure mutex");
return false;
}
}
bool network_status_lock_sta_ip_string(TickType_t xTicksToWait) {
TaskHandle_t calling_task = xTaskGetCurrentTaskHandle();
if (calling_task == network_status_ip_address_locked_task) {
ESP_LOGD(TAG, "json buffer already locked to current task ");
return true;
}
if (network_status_ip_address_mutex) {
if (xSemaphoreTake(network_status_ip_address_mutex, xTicksToWait) == pdTRUE) {
network_status_ip_address_locked_task = calling_task;
return true;
} else {
return false;
}
} else {
return false;
}
}
void network_status_unlock_sta_ip_string() {
network_status_ip_address_locked_task = NULL;
xSemaphoreGive(network_status_ip_address_mutex);
}
void network_status_safe_update_sta_ip_string(esp_ip4_addr_t* ip4) {
if (network_status_lock_sta_ip_string(portMAX_DELAY)) {
strcpy(network_status_ip_address, ip4 != NULL ? ip4addr_ntoa((ip4_addr_t*)ip4) : "0.0.0.0");
ESP_LOGD(TAG, "Set STA IP String to: %s", network_status_ip_address);
network_status_unlock_sta_ip_string();
}
}
void network_status_safe_reset_sta_ip_string() {
if (network_status_lock_sta_ip_string(portMAX_DELAY)) {
strcpy(network_status_ip_address, "0.0.0.0");
ESP_LOGD(TAG, "Set STA IP String to: %s", network_status_ip_address);
network_status_unlock_sta_ip_string();
}
}
char* network_status_get_sta_ip_string() {
return network_status_ip_address;
return status.has_net && status.net.has_ip?status.net.ip.ip:"0.0.0.0";
}
void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport) {
strncpy(lms_server_ip, inet_ntoa(ip), sizeof(lms_server_ip));
lms_server_ip[sizeof(lms_server_ip) - 1] = '\0';
ESP_LOGI(TAG, "LMS IP: %s, hport: %d, cport: %d", lms_server_ip, hport, cport);
lms_server_port = hport;
lms_server_cport = cport;
if (network_status_lock_structure(portMAX_DELAY)) {
status.has_LMS = true;
strncpy(status.LMS.ip, inet_ntoa(ip), sizeof(status.LMS.ip));
status.LMS.port = hport;
status.LMS.cport = cport;
ESP_LOGI(TAG, "LMS IP: %s, hport: %d, cport: %d", status.LMS.ip, status.LMS.port, status.LMS.cport);
network_status_unlock_structure();
}
}
static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) {
set_lms_server_details(ip, hport, cport);
@@ -185,163 +93,94 @@ static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) {
network_async_update_status();
}
void network_status_update_basic_info() {
// locking happens below this level
network_status_get_basic_info(&ip_info_cjson);
}
cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
if (network_status_lock_json_buffer(portMAX_DELAY)) {
if (*root == NULL) {
*root = cJSON_CreateObject();
}
if (key && strlen(key) != 0) {
cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
if (cjsonvalue) {
cJSON_SetNumberValue(cjsonvalue, value);
} else {
cJSON_AddNumberToObject(*root, key, value);
}
}
network_status_unlock_json_buffer();
} else {
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
}
return *root;
}
cJSON* network_status_update_bool(cJSON** root, const char* key, bool value) {
if (network_status_lock_json_buffer(portMAX_DELAY)) {
if (*root == NULL) {
*root = cJSON_CreateObject();
}
if (key && strlen(key) != 0) {
cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
if (cjsonvalue) {
cjsonvalue->type = value ? cJSON_True : cJSON_False;
} else {
cJSON_AddBoolToObject(*root, key, value);
}
}
network_status_unlock_json_buffer();
} else {
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
}
return *root;
}
cJSON * network_update_cjson_string(cJSON** root, const char* key, const char* value){
if (network_status_lock_json_buffer(portMAX_DELAY)) {
cjson_update_string(root, key, value);
network_status_unlock_json_buffer();
} else {
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
}
return *root;
}
cJSON * network_update_cjson_number(cJSON** root, const char* key, int value){
if (network_status_lock_json_buffer(portMAX_DELAY)) {
cjson_update_number(root, key, value);
network_status_unlock_json_buffer();
} else {
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
}
return *root;
}
cJSON* network_status_get_basic_info(cJSON** old) {
if (network_status_lock_json_buffer(portMAX_DELAY)) {
void network_status_set_basic_info() {
if (network_status_lock_structure(portMAX_DELAY)) {
network_t* nm = network_get_state_machine();
monitor_gpio_t* mgpio = get_jack_insertion_gpio();
sys_GPIO * gpio = NULL;
const esp_app_desc_t* desc = esp_ota_get_app_description();
*old = network_update_cjson_string(old, "project_name", desc->project_name);
status.has_platform = true;
strncpy(status.platform.project, desc->project_name, sizeof(status.platform.project));
#ifdef CONFIG_FW_PLATFORM_NAME
*old = network_update_cjson_string(old, "platform_name", CONFIG_FW_PLATFORM_NAME);
strncpy(status.platform.name, CONFIG_FW_PLATFORM_NAME, sizeof(status.platform.name));
#endif
*old = network_update_cjson_string(old, "version", desc->version);
if (release_url != NULL)
*old = network_update_cjson_string(old, "release_url", release_url);
*old = network_update_cjson_number(old, "recovery", is_recovery_running ? 1 : 0);
*old = network_status_update_bool(old, "Jack", mgpio->gpio >= 0 && jack_inserted_svc());
*old = network_status_update_float(old, "Voltage", battery_value_svc());
*old = network_update_cjson_number(old, "disconnect_count", nm->num_disconnect);
*old = network_status_update_float(old, "avg_conn_time", nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0);
strncpy(status.platform.version, desc->version, sizeof(status.platform.version));
strncpy(status.platform.version, desc->version, sizeof(status.platform.version));
status.platform.recovery = is_recovery_running;
status.platform.depth = 16;
#if DEPTH == 16 || DEPTH == 32
status.platform.depth = DEPTH;
#endif
status.has_hw = true;
status.hw.jack_inserted = jack_inserted_svc();
status.hw.has_jack_inserted = SYS_GPIOS_NAME(jack,gpio) && gpio->pin>=0;
status.hw.has_spk_fault = SYS_GPIOS_NAME(spkfault,gpio) && gpio->pin>=0;
status.hw.spk_fault = spkfault_svc();
status.hw.batt_voltage = battery_value_svc();
status.has_net = true;
status.net.has_wifi = true;
status.net.wifi.disconnect_count = nm->num_disconnect;
status.net.wifi.avg_conn_time = nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0;
#ifdef CONFIG_BT_ENABLED
*old = network_update_cjson_number(old, "bt_status", bt_app_source_get_a2d_state());
*old = network_update_cjson_number(old, "bt_sub_status", bt_app_source_get_media_state());
if(platform->has_services && platform->services.has_bt_sink && platform->services.bt_sink.enabled){
status.has_bt = true;
status.bt.bt_status = bt_app_source_get_a2d_state();
status.bt.bt_media_state = bt_app_source_get_media_state();
}
#endif
#if DEPTH == 16
*old = network_update_cjson_number(old, "depth", 16);
#elif DEPTH == 32
*old = network_update_cjson_number(old, "depth", 32);
#endif
#if CONFIG_I2C_LOCKED
*old = network_status_update_bool(old, "is_i2c_locked", true);
#else
*old = network_status_update_bool(old, "is_i2c_locked", false);
#endif
if (network_ethernet_enabled()) {
*old = network_status_update_bool(old, "eth_up", network_ethernet_is_up());
}
if (lms_server_cport > 0) {
*old = network_update_cjson_number(old, "lms_cport", lms_server_cport);
}
if (lms_server_port > 0) {
*old = network_update_cjson_number(old, "lms_port", lms_server_port);
}
if (strlen(lms_server_ip) > 0) {
*old = network_update_cjson_string(old, "lms_ip", lms_server_ip);
status.net.eth_up = network_ethernet_is_up();
}
ESP_LOGV(TAG, "network_status_get_basic_info done");
network_status_unlock_json_buffer();
network_status_unlock_structure();
} else {
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
}
return *old;
}
void network_status_update_address(cJSON* root, esp_netif_ip_info_t* ip_info) {
if (!root || !ip_info) {
ESP_LOGE(TAG, "Cannor update IP address. JSON structure or ip_info is null");
return;
}
network_update_cjson_string(&root, "ip", ip4addr_ntoa((ip4_addr_t*)&ip_info->ip));
network_update_cjson_string(&root, "netmask", ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask));
network_update_cjson_string(&root, "gw", ip4addr_ntoa((ip4_addr_t*)&ip_info->gw));
void network_status_update_address(esp_netif_ip_info_t* ip_info) {
status.has_net = true;
status.net.has_ip = true;
strncpy(status.net.ip.ip,ip4addr_ntoa((ip4_addr_t*)&ip_info->ip),sizeof(status.net.ip.ip));
strncpy(status.net.ip.netmask,ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask),sizeof(status.net.ip.netmask));
strncpy(status.net.ip.gw,ip4addr_ntoa((ip4_addr_t*)&ip_info->gw),sizeof(status.net.ip.gw));
}
void network_status_update_ip_info(update_reason_code_t update_reason_code) {
void network_status_update_ip_info(sys_UPDATE_REASONS update_reason_code) {
ESP_LOGV(TAG, "network_status_update_ip_info called");
esp_netif_ip_info_t ip_info;
if (network_status_lock_json_buffer(portMAX_DELAY)) {
if (network_status_lock_structure(portMAX_DELAY)) {
/* generate the connection info with success */
ip_info_cjson = network_status_get_basic_info(&ip_info_cjson);
ip_info_cjson = network_update_cjson_number(&ip_info_cjson, "urc", (int)update_reason_code);
network_status_set_basic_info();
status.net.updt_reason = update_reason_code;
status.net.wifi.has_connected_sta = false;
status.net.wifi.connected_sta.connected = false;
ESP_LOGD(TAG,"Updating ip info with reason code %d. Checking if Wifi interface is connected",update_reason_code);
if (network_is_interface_connected(network_wifi_get_interface()) || update_reason_code == UPDATE_FAILED_ATTEMPT ) {
network_update_cjson_string(&ip_info_cjson, "if", "wifi");
if (network_is_interface_connected(network_wifi_get_interface()) || update_reason_code == sys_UPDATE_REASONS_R_FAILED_ATTEMPT ) {
status.net.interface = sys_CONNECTED_IF_IF_WIFI;
esp_netif_get_ip_info(network_wifi_get_interface(), &ip_info);
network_status_update_address(ip_info_cjson, &ip_info);
network_status_update_address(&ip_info);
if (!network_wifi_is_ap_mode()) {
/* wifi is active, and associated to an AP */
wifi_ap_record_t ap;
esp_wifi_sta_get_ap_info(&ap);
network_update_cjson_string(&ip_info_cjson, "ssid", ((char*)ap.ssid));
network_update_cjson_number(&ip_info_cjson, "rssi", ap.rssi);
network_wifi_esp_sta_to_sta(&ap, &status.net.wifi.connected_sta);
status.net.wifi.connected_sta.connected = true;
status.net.has_wifi = true;
status.net.wifi.has_connected_sta = true;
}
} else {
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "rssi");
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "ssid");
}
}
ESP_LOGD(TAG,"Checking if ethernet interface is connected");
if (network_is_interface_connected(network_ethernet_get_interface())) {
network_update_cjson_string(&ip_info_cjson, "if", "eth");
status.net.interface = sys_CONNECTED_IF_IF_ETHERNET;
esp_netif_get_ip_info(network_ethernet_get_interface(), &ip_info);
network_status_update_address(ip_info_cjson, &ip_info);
network_status_update_address(&ip_info);
}
network_status_unlock_json_buffer();
network_status_unlock_structure();
} else {
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
}

View File

@@ -1,10 +1,12 @@
#pragma once
#include "network_manager.h"
#include "cJSON.h"
#include "Configurator.h"
#ifdef __cplusplus
extern "C" {
#endif
extern sys_Status status;
char* network_status_alloc_get_ip_info_json();
/**
* @brief Tries to get access to json buffer mutex.
@@ -21,39 +23,24 @@ char* network_status_alloc_get_ip_info_json();
* @param xTicksToWait The time in ticks to wait for the semaphore to become available.
* @return true in success, false otherwise.
*/
bool network_status_lock_json_buffer(TickType_t xTicksToWait);
bool network_status_lock_structure(TickType_t xTicksToWait);
/**
* @brief Releases the json buffer mutex.
*/
void network_status_unlock_json_buffer();
bool network_status_lock_sta_ip_string(TickType_t xTicksToWait);
void network_status_unlock_sta_ip_string();
/**
* @brief gets the string representation of the STA IP address, e.g.: "192.168.1.69"
*/
char* network_status_get_sta_ip_string();
/**
* @brief thread safe char representation of the STA IP update
*/
void network_status_safe_update_sta_ip_string(esp_ip4_addr_t * ip4);
void network_status_unlock_structure();
/**
* @brief Generates the connection status json: ssid and IP addresses.
* @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
*/
void network_status_update_ip_info(update_reason_code_t update_reason_code);
void network_status_update_ip_info(sys_UPDATE_REASONS update_reason_code);
void init_network_status();
void destroy_network_status();
cJSON* network_status_get_basic_info(cJSON** old);
void network_status_update_basic_info();
void network_status_clear_ip();
void network_status_safe_reset_sta_ip_string();
void network_status_safe_reset_sta_ip();
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +1,22 @@
#pragma once
#include "network_manager.h"
#include "Configurator.h"
#ifdef __cplusplus
extern "C" {
#endif
esp_netif_t * network_wifi_start();
void destroy_network_wifi();
/**
* @brief saves the current STA wifi config to flash ram storage.
*/
esp_err_t network_wifi_save_sta_config();
/**
* @brief fetch a previously STA wifi config in the flash ram storage.
* @return true if a previously saved config was found, false otherwise.
*/
bool network_wifi_load_wifi_sta_config();
/**
* @brief Registers handler for wifi and ip events
*/
void network_wifi_register_handlers();
/**
* @brief Generates the list of access points after a wifi scan.
* @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
*/
void network_wifi_generate_access_points_json(cJSON ** ap_list);
/**
* @brief Clear the list of access points.
* @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
* @note This is not thread-safe and should be called only if network_status_lock_structure call is successful.
*/
void network_wifi_clear_access_points_json();
@@ -46,7 +30,6 @@ esp_err_t network_wifi_load_restore(queue_message *msg);
esp_err_t network_wifi_order_connect(queue_message *msg);
esp_err_t network_wifi_disconnected(queue_message *msg);
esp_err_t network_wifi_start_ap(queue_message *msg);
bool network_wifi_get_config_for_ssid(wifi_config_t* config, const char * ssid);
esp_err_t network_wifi_handle_event(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
bool is_wifi_up();
wifi_config_t* network_wifi_set_wifi_sta_config(const char * ssid, const char * password) ;
@@ -67,9 +50,9 @@ esp_err_t network_wifi_erase_known_ap();
esp_err_t network_wifi_set_sta_mode();
size_t network_wifi_get_known_count();
size_t network_wifi_get_known_count_in_range();
esp_err_t network_wifi_built_known_ap_list();
esp_err_t network_wifi_connect_next_in_range();
const wifi_sta_config_t* network_wifi_load_active_config();
void network_wifi_esp_sta_to_sta(wifi_ap_record_t* scan_res, sys_WifiSTAEntry* sta_entry);
sys_WifiAuthTypeEnum network_wifi_get_auth_type(const wifi_auth_mode_t mode) ;
#ifdef __cplusplus
}
#endif

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +0,0 @@
declare function _exports(grunt: any): void;
export = _exports;

View File

@@ -1,2 +0,0 @@
declare function _exports(grunt: any): void;
export = _exports;

View File

@@ -1,2 +0,0 @@
declare function _exports(grunt: any): void;
export = _exports;

View File

@@ -1,688 +0,0 @@
/**
* Class definition
*/
export class Alert extends BaseComponent {
static get NAME(): string;
static jQueryInterface(config: any): any;
close(): void;
_destroyElement(): void;
}
/**
* Class definition
*/
export class Button extends BaseComponent {
static get NAME(): string;
static jQueryInterface(config: any): any;
toggle(): void;
}
/**
* Class definition
*/
export class Carousel extends BaseComponent {
static get Default(): {
interval: number;
keyboard: boolean;
pause: string;
ride: boolean;
touch: boolean;
wrap: boolean;
};
static get DefaultType(): {
interval: string;
keyboard: string;
pause: string;
ride: string;
touch: string;
wrap: string;
};
static get NAME(): string;
static jQueryInterface(config: any): any;
_interval: NodeJS.Timeout;
_activeElement: any;
_isSliding: boolean;
touchTimeout: NodeJS.Timeout;
_swipeHelper: Swipe;
_indicatorsElement: any;
next(): void;
nextWhenVisible(): void;
prev(): void;
pause(): void;
cycle(): void;
_maybeEnableCycle(): void;
to(index: any): void;
_addEventListeners(): void;
_addTouchEventListeners(): void;
_keydown(event: any): void;
_getItemIndex(element: any): number;
_setActiveIndicatorElement(index: any): void;
_updateInterval(): void;
_slide(order: any, element?: any): void;
_isAnimated(): any;
_getActive(): any;
_getItems(): any[];
_clearInterval(): void;
_directionToOrder(direction: any): "next" | "prev";
_orderToDirection(order: any): "right" | "left";
}
/**
* Class definition
*/
export class Collapse extends BaseComponent {
static get Default(): {
parent: any;
toggle: boolean;
};
static get DefaultType(): {
parent: string;
toggle: string;
};
static get NAME(): string;
static jQueryInterface(config: any): any;
_isTransitioning: boolean;
_triggerArray: any[];
toggle(): void;
show(): void;
hide(): void;
_isShown(element?: any): any;
_getDimension(): "width" | "height";
_initializeChildren(): void;
_getFirstLevelChildren(selector: any): any[];
_addAriaAndCollapsedClass(triggerArray: any, isOpen: any): void;
}
/**
* Class definition
*/
export class Dropdown extends BaseComponent {
static get Default(): {
autoClose: boolean;
boundary: string;
display: string;
offset: number[];
popperConfig: any;
reference: string;
};
static get DefaultType(): {
autoClose: string;
boundary: string;
display: string;
offset: string;
popperConfig: string;
reference: string;
};
static get NAME(): string;
static jQueryInterface(config: any): any;
static clearMenus(event: any): void;
static dataApiKeydownHandler(event: any): void;
_popper: Popper.Instance;
_parent: any;
_menu: any;
_inNavbar: boolean;
toggle(): void;
show(): void;
hide(): void;
update(): void;
_completeHide(relatedTarget: any): void;
_createPopper(): void;
_isShown(): any;
_getPlacement(): "top" | "bottom" | "top-end" | "top-start" | "bottom-end" | "bottom-start" | "left-start" | "right-start";
_detectNavbar(): boolean;
_getOffset(): any;
_getPopperConfig(): any;
_selectMenuItem({ key, target }: {
key: any;
target: any;
}): void;
}
/**
* Class definition
*/
export class Modal extends BaseComponent {
static get Default(): {
backdrop: boolean;
focus: boolean;
keyboard: boolean;
};
static get DefaultType(): {
backdrop: string;
focus: string;
keyboard: string;
};
static get NAME(): string;
static jQueryInterface(config: any, relatedTarget: any): any;
_dialog: any;
_backdrop: Backdrop;
_focustrap: FocusTrap;
_isShown: boolean;
_isTransitioning: boolean;
_scrollBar: ScrollBarHelper;
toggle(relatedTarget: any): void;
show(relatedTarget: any): void;
hide(): void;
handleUpdate(): void;
_initializeBackDrop(): Backdrop;
_initializeFocusTrap(): FocusTrap;
_showElement(relatedTarget: any): void;
_addEventListeners(): void;
_hideModal(): void;
_isAnimated(): any;
_triggerBackdropTransition(): void;
/**
* The following methods are used to handle overflowing modals
*/
_adjustDialog(): void;
_resetAdjustments(): void;
}
/**
* Class definition
*/
export class Offcanvas extends BaseComponent {
static get Default(): {
backdrop: boolean;
keyboard: boolean;
scroll: boolean;
};
static get DefaultType(): {
backdrop: string;
keyboard: string;
scroll: string;
};
static get NAME(): string;
static jQueryInterface(config: any): any;
_isShown: boolean;
_backdrop: Backdrop;
_focustrap: FocusTrap;
toggle(relatedTarget: any): void;
show(relatedTarget: any): void;
hide(): void;
_initializeBackDrop(): Backdrop;
_initializeFocusTrap(): FocusTrap;
_addEventListeners(): void;
}
/**
* Class definition
*/
export class Popover extends Tooltip {
static get Default(): {
content: string;
offset: number[];
placement: string;
template: string;
trigger: string;
allowList: {
'*': (string | RegExp)[];
a: string[];
area: any[];
b: any[];
br: any[];
col: any[];
code: any[];
div: any[];
em: any[];
hr: any[];
h1: any[];
h2: any[];
h3: any[];
h4: any[];
h5: any[];
h6: any[];
i: any[];
img: string[];
li: any[];
ol: any[];
p: any[];
pre: any[];
s: any[];
small: any[];
span: any[];
sub: any[];
sup: any[];
strong: any[];
u: any[];
ul: any[];
};
animation: boolean;
boundary: string;
container: boolean;
customClass: string;
delay: number;
fallbackPlacements: string[];
html: boolean;
popperConfig: any;
sanitize: boolean;
sanitizeFn: any;
selector: boolean;
title: string;
};
static get DefaultType(): {
content: string;
allowList: string;
animation: string;
boundary: string;
container: string;
customClass: string;
delay: string;
fallbackPlacements: string;
html: string;
offset: string;
placement: string;
popperConfig: string;
sanitize: string;
sanitizeFn: string;
selector: string;
template: string;
title: string;
trigger: string;
};
_isWithContent(): any;
_getContentForTemplate(): {
".popover-header": any;
".popover-body": any;
};
_getContent(): any;
}
/**
* Class definition
*/
export class ScrollSpy extends BaseComponent {
static get Default(): {
offset: any;
rootMargin: string;
smoothScroll: boolean;
target: any;
threshold: number[];
};
static get DefaultType(): {
offset: string;
rootMargin: string;
smoothScroll: string;
target: string;
threshold: string;
};
static get NAME(): string;
static jQueryInterface(config: any): any;
_targetLinks: Map<any, any>;
_observableSections: Map<any, any>;
_rootElement: any;
_activeTarget: any;
_observer: IntersectionObserver;
_previousScrollData: {
visibleEntryTop: number;
parentScrollTop: number;
};
refresh(): void;
_maybeEnableSmoothScroll(): void;
_getNewObserver(): IntersectionObserver;
_observerCallback(entries: any): void;
_initializeTargetsAndObservables(): void;
_process(target: any): void;
_activateParents(target: any): void;
_clearActiveClass(parent: any): void;
}
/**
* Class definition
*/
export class Tab extends BaseComponent {
static get NAME(): string;
static jQueryInterface(config: any): any;
constructor(element: any);
_parent: any;
show(): void;
_activate(element: any, relatedElem: any): void;
_deactivate(element: any, relatedElem: any): void;
_keydown(event: any): void;
_getChildren(): any[];
_getActiveElem(): any;
_setInitialAttributes(parent: any, children: any): void;
_setInitialAttributesOnChild(child: any): void;
_setInitialAttributesOnTargetPanel(child: any): void;
_toggleDropDown(element: any, open: any): void;
_setAttributeIfNotExists(element: any, attribute: any, value: any): void;
_elemIsActive(elem: any): any;
_getInnerElement(elem: any): any;
_getOuterElement(elem: any): any;
}
/**
* Class definition
*/
export class Toast extends BaseComponent {
static get Default(): {
animation: boolean;
autohide: boolean;
delay: number;
};
static get DefaultType(): {
animation: string;
autohide: string;
delay: string;
};
static get NAME(): string;
static jQueryInterface(config: any): any;
_timeout: NodeJS.Timeout;
_hasMouseInteraction: boolean;
_hasKeyboardInteraction: boolean;
show(): void;
hide(): void;
isShown(): any;
_maybeScheduleHide(): void;
_onInteraction(event: any, isInteracting: any): void;
_setListeners(): void;
_clearTimeout(): void;
}
/**
* Class definition
*/
export class Tooltip extends BaseComponent {
static get Default(): {
allowList: {
'*': (string | RegExp)[];
a: string[];
area: any[];
b: any[];
br: any[];
col: any[];
code: any[];
div: any[];
em: any[];
hr: any[];
h1: any[];
h2: any[];
h3: any[];
h4: any[];
h5: any[];
h6: any[];
i: any[];
img: string[];
li: any[];
ol: any[];
p: any[];
pre: any[];
s: any[];
small: any[];
span: any[];
sub: any[];
sup: any[];
strong: any[];
u: any[];
ul: any[];
};
animation: boolean;
boundary: string;
container: boolean;
customClass: string;
delay: number;
fallbackPlacements: string[];
html: boolean;
offset: number[];
placement: string;
popperConfig: any;
sanitize: boolean;
sanitizeFn: any;
selector: boolean;
template: string;
title: string;
trigger: string;
};
static get DefaultType(): {
allowList: string;
animation: string;
boundary: string;
container: string;
customClass: string;
delay: string;
fallbackPlacements: string;
html: string;
offset: string;
placement: string;
popperConfig: string;
sanitize: string;
sanitizeFn: string;
selector: string;
template: string;
title: string;
trigger: string;
};
static get NAME(): string;
static jQueryInterface(config: any): any;
_isEnabled: boolean;
_timeout: number;
_isHovered: boolean;
_activeTrigger: {};
_popper: Popper.Instance;
_templateFactory: TemplateFactory;
_newContent: any;
tip: Element;
enable(): void;
disable(): void;
toggleEnabled(): void;
toggle(): void;
show(): void;
hide(): void;
update(): void;
_isWithContent(): boolean;
_getTipElement(): Element;
_createTipElement(content: any): Element;
setContent(content: any): void;
_getTemplateFactory(content: any): TemplateFactory;
_getContentForTemplate(): {
".tooltip-inner": any;
};
_getTitle(): any;
_initializeOnDelegatedTarget(event: any): any;
_isAnimated(): any;
_isShown(): boolean;
_createPopper(tip: any): Popper.Instance;
_getOffset(): any;
_resolvePossibleFunction(arg: any): any;
_getPopperConfig(attachment: any): any;
_setListeners(): void;
_hideModalHandler: () => void;
_fixTitle(): void;
_enter(): void;
_leave(): void;
_setTimeout(handler: any, timeout: any): void;
_isWithActiveTrigger(): boolean;
_getDelegateConfig(): {
selector: boolean;
trigger: string;
};
_disposePopper(): void;
}
/**
* Class definition
*/
declare class BaseComponent extends Config {
static getInstance(element: any): any;
static getOrCreateInstance(element: any, config?: {}): any;
static get VERSION(): string;
static get DATA_KEY(): string;
static get EVENT_KEY(): string;
static eventName(name: any): string;
constructor(element: any, config: any);
_element: any;
_config: any;
dispose(): void;
_queueCallback(callback: any, element: any, isAnimated?: boolean): void;
}
/**
* Class definition
*/
declare class Swipe extends Config {
static get Default(): {
endCallback: any;
leftCallback: any;
rightCallback: any;
};
static get DefaultType(): {
endCallback: string;
leftCallback: string;
rightCallback: string;
};
static get NAME(): string;
static isSupported(): boolean;
constructor(element: any, config: any);
_element: any;
_config: any;
_deltaX: number;
_supportPointerEvents: boolean;
dispose(): void;
_start(event: any): void;
_end(event: any): void;
_move(event: any): void;
_handleSwipe(): void;
_initEvents(): void;
_eventIsPointerPenTouch(event: any): boolean;
}
import * as Popper from "@popperjs/core";
/**
* Class definition
*/
declare class Backdrop extends Config {
static get Default(): {
className: string;
clickCallback: any;
isAnimated: boolean;
isVisible: boolean;
rootElement: string;
};
static get DefaultType(): {
className: string;
clickCallback: string;
isAnimated: string;
isVisible: string;
rootElement: string;
};
static get NAME(): string;
constructor(config: any);
_config: any;
_isAppended: boolean;
_element: HTMLDivElement;
show(callback: any): void;
hide(callback: any): void;
dispose(): void;
_getElement(): HTMLDivElement;
_append(): void;
_emulateAnimation(callback: any): void;
}
/**
* Class definition
*/
declare class FocusTrap extends Config {
static get Default(): {
autofocus: boolean;
trapElement: any;
};
static get DefaultType(): {
autofocus: string;
trapElement: string;
};
static get NAME(): string;
constructor(config: any);
_config: any;
_isActive: boolean;
_lastTabNavDirection: string;
activate(): void;
deactivate(): void;
_handleFocusin(event: any): void;
_handleKeydown(event: any): void;
}
/**
* Class definition
*/
declare class ScrollBarHelper {
_element: HTMLElement;
getWidth(): number;
hide(): void;
reset(): void;
isOverflowing(): boolean;
_disableOverFlow(): void;
_setElementAttributes(selector: any, styleProperty: any, callback: any): void;
_saveInitialAttribute(element: any, styleProperty: any): void;
_resetElementAttributes(selector: any, styleProperty: any): void;
_applyManipulationCallback(selector: any, callBack: any): void;
}
/**
* Class definition
*/
declare class TemplateFactory extends Config {
static get Default(): {
allowList: {
'*': (string | RegExp)[];
a: string[];
area: any[];
b: any[];
br: any[];
col: any[];
code: any[];
div: any[];
em: any[];
hr: any[];
h1: any[];
h2: any[];
h3: any[];
h4: any[];
h5: any[];
h6: any[];
i: any[];
img: string[];
li: any[];
ol: any[];
p: any[];
pre: any[];
s: any[];
small: any[];
span: any[];
sub: any[];
sup: any[];
strong: any[];
u: any[];
ul: any[];
};
content: {};
extraClass: string;
html: boolean;
sanitize: boolean;
sanitizeFn: any;
template: string;
};
static get DefaultType(): {
allowList: string;
content: string;
extraClass: string;
html: string;
sanitize: string;
sanitizeFn: string;
template: string;
};
static get NAME(): string;
constructor(config: any);
_config: any;
getContent(): any[];
hasContent(): boolean;
changeContent(content: any): TemplateFactory;
toHtml(): Element;
_typeCheckConfig(config: any): void;
_checkContent(arg: any): void;
_setContent(template: any, content: any, selector: any): void;
_maybeSanitize(arg: any): any;
_resolvePossibleFunction(arg: any): any;
_putElementInTemplate(element: any, templateElement: any): void;
}
/**
* --------------------------------------------------------------------------
* Bootstrap util/config.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
/**
* Class definition
*/
declare class Config {
static get Default(): {};
static get DefaultType(): {};
static get NAME(): void;
_getConfig(config: any): any;
_configAfterMerge(config: any): any;
_mergeConfigObj(config: any, element: any): any;
_typeCheckConfig(config: any, configTypes?: any): void;
}
export {};

View File

@@ -1,93 +0,0 @@
/// <reference lib="webworker" />
export namespace languages {
export namespace markup {
namespace tag { }
}
import html = markup;
export { html };
import mathml = markup;
export { mathml };
import svg = markup;
export { svg };
export const xml: {
[x: string]: RegExp | GrammarToken | (RegExp | GrammarToken)[];
};
import ssml = xml;
export { ssml };
import atom = xml;
export { atom };
import rss = xml;
export { rss };
export const clike: {
comment: {
pattern: RegExp;
lookbehind: boolean;
greedy: boolean;
}[];
string: {
pattern: RegExp;
greedy: boolean;
};
'class-name': {
pattern: RegExp;
lookbehind: boolean;
inside: {
punctuation: RegExp;
};
};
keyword: RegExp;
boolean: RegExp;
function: RegExp;
number: RegExp;
operator: RegExp;
punctuation: RegExp;
};
export const javascript: {
[x: string]: RegExp | GrammarToken | (RegExp | GrammarToken)[];
};
import js = javascript;
export { js };
}
/**
* The expansion of a simple `RegExp` literal to support additional properties.
*/
export type GrammarToken = {
/**
* The regular expression of the token.
*/
pattern: RegExp;
/**
* If `true`, then the first capturing group of `pattern` will (effectively)
* behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token.
*/
lookbehind?: boolean;
/**
* Whether the token is greedy.
*/
greedy?: boolean;
/**
* An optional alias or list of aliases.
*/
alias?: string | string[];
/**
* The nested grammar of this token.
*
* The `inside` grammar will be used to tokenize the text value of each token of this kind.
*
* This can be used to make nested and even recursive language definitions.
*
* Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into
* each another.
*/
inside?: Grammar;
};
export type Grammar = {
[x: string]: RegExp | GrammarToken | Array<RegExp | GrammarToken>;
};
/**
* A function which will invoked after an element was successfully highlighted.
*/
export type HighlightCallback = (element: Element) => void;
export type HookCallback = (env: {
[x: string]: any;
}) => void;

View File

@@ -1,4 +1,4 @@
import 'bootstrap';
import './sass/main.scss';
import './assets/images/favicon-32x32.png';
import './js/custom.js';
import './js/custom.ts';

View File

@@ -1 +1,17 @@
declare global {
interface Window {
hideSurrounding: (obj: HTMLElement) => void;
hFlash: () => void;
handleReboot: (link: string) => void;
setURL: (button: HTMLButtonElement) => void;
runCommand: (button: HTMLButtonElement, reboot: boolean) => void;
}
interface String {
format(...args: any[]): string;
encodeHTML(): string;
}
interface Date {
toLocalShort(): string;
}
}
export {};

View File

@@ -1,204 +1,6 @@
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare let sd: {};
declare let rf: boolean;
declare function refreshStatus(): void;

View File

@@ -1,2 +0,0 @@
declare function _exports(env: any, options: any): {};
export = _exports;

View File

@@ -1,6 +0,0 @@
export const parser: string;
export const plugins: {
'postcss-import': {};
'postcss-cssnext': {};
cssnano: {};
};

View File

@@ -1,37 +0,0 @@
declare const PORT: 9100;
import HtmlWebPackPlugin = require("html-webpack-plugin");
export namespace entry {
const test: string;
}
export namespace devServer {
export namespace _static {
const directory: string;
const staticOptions: {};
const publicPath: string;
const serveIndex: boolean;
const watch: boolean;
}
export { _static as static };
export namespace devMiddleware {
const publicPath_1: string;
export { publicPath_1 as publicPath };
}
export const open: boolean;
export const compress: boolean;
export { PORT as port };
export const host: string;
export const allowedHosts: string;
export const headers: {
'Access-Control-Allow-Origin': string;
'Accept-Encoding': string;
};
export namespace client {
const logging: string;
const overlay: boolean;
const progress: boolean;
}
export function onListening(devServer: any): void;
export function onBeforeSetupMiddleware(devServer: any): void;
}
export const plugins: HtmlWebPackPlugin[];
export {};

View File

@@ -0,0 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6"
},
"include": ["src/**/*"]
}

View File

@@ -10,7 +10,8 @@
"build": "webpack --mode=production ",
"stats": "webpack --env ANALYZE_SIZE=1 --mode=production ",
"watch": "webpack --progress --watch --mode=development ",
"dev": "webpack serve --open --mode=development"
"dev": "webpack serve --open --mode=development",
"build:proto": "tsc ./webpack/GrpcToolsNodeProtocPlugin.ts"
},
"devDependencies": {
"@babel/core": "^7.16.12",
@@ -18,11 +19,14 @@
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.7",
"@squoosh/lib": "^0.4.0",
"@types/bootstrap": "^5.2.8",
"@types/he": "^1.2.2",
"@types/jquery": "^3.5.25",
"@types/js-cookie": "^3.0.5",
"autoprefixer": "^10.4.2",
"babel": "^6.23.0",
"babel-loader": "^8.2.3",
"babel-runtime": "^6.26.0",
"bootswatch": "file:src/bootswatch",
"clean-webpack-plugin": "^4.0.0",
"commander": "^8.3.0",
"compression-webpack-plugin": "^9.2.0",
@@ -35,6 +39,7 @@
"glob": "^7.2.0",
"glob-all": "^3.2.1",
"google-fonts-webpack-plugin": "^0.4.4",
"grpc-tools": "^1.12.4",
"html-loader": "^3.1.0",
"html-minimizer-webpack-plugin": "^3.5.0",
"html-webpack-plugin": "^5.5.0",
@@ -46,7 +51,7 @@
"imagemin-optipng": "^8.0.0",
"imagemin-pngquant": "^9.0.2",
"imagemin-svgo": "^10.0.1",
"js-cookie": "^3.0.1",
"js-cookie": "^3.0.5",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-webpack-plugin": "^0.11.6",
@@ -55,6 +60,7 @@
"open": "^9.1.0",
"postcss": "^8.4.5",
"postcss-loader": "^6.2.1",
"protobufjs-loader": "^2.0.2",
"purgecss-webpack-plugin": "^4.1.3",
"purgecss-whitelister": "^2.4.0",
"purify-css": "^1.2.5",
@@ -73,11 +79,16 @@
},
"dependencies": {
"@babel/runtime": "^7.16.7",
"@grpc/grpc-js": "^1.9.9",
"@grpc/proto-loader": "^0.7.10",
"async-mutex": "^0.3.2",
"bootstrap": "^5.1.3",
"google-protobuf": "^3.21.2",
"he": "^1.2.0",
"jquery": "^3.6.0",
"npm": "^10.1.0",
"popper.js": "^1.16.1",
"protobufjs": "^7.2.5",
"webpack-visualizer-plugin": "^0.1.11",
"webpack-visualizer-plugin2": "^1.0.0"
},

View File

@@ -2,5 +2,5 @@
import 'bootstrap';
import './sass/main.scss';
import './assets/images/favicon-32x32.png';
import './js/custom.js';
import './js/custom.ts';

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
@import "~bootswatch/dist/darkly/variables";
@import "utils/variables";
@import "~bootstrap/scss/bootstrap";
// @import "~bootstrap/scss/functions";
@@ -38,5 +36,4 @@
// // Utilities
// @import "~bootstrap/scss/utilities/api";
@import "~bootswatch/dist/darkly/bootswatch";
@import "utils/style";

View File

@@ -1,9 +1,7 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": [ "src/*"],
"@node_modules/*" : ["./node_modules/*"]},
"outDir": "./dist/",
"noImplicitAny": true,
"target": "es6",
@@ -11,11 +9,15 @@
"composite": true,
// "jsx": "react",
"allowJs": true,
// "checkJs": true,
"allowSyntheticDefaultImports" : true,
"esModuleInterop" : true
},
"include": [
"src/**/*" // Adjust the path to include your source files
],
"exclude": [
"./node_modules"
"node_modules"
]
}

View File

@@ -1,5 +0,0 @@
target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.1ab179394339385e0a02.css.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/favicon-32x32.png BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.1b8c7b.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.1b8c7b.bundle.js.gz BINARY)

View File

@@ -1,34 +0,0 @@
// Automatically generated. Do not edit manually!.
#include <inttypes.h>
extern const uint8_t _index_1ab179394339385e0a02_css_gz_start[] asm("_binary_index_1ab179394339385e0a02_css_gz_start");
extern const uint8_t _index_1ab179394339385e0a02_css_gz_end[] asm("_binary_index_1ab179394339385e0a02_css_gz_end");
extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_start");
extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
extern const uint8_t _index_1b8c7b_bundle_js_gz_start[] asm("_binary_index_1b8c7b_bundle_js_gz_start");
extern const uint8_t _index_1b8c7b_bundle_js_gz_end[] asm("_binary_index_1b8c7b_bundle_js_gz_end");
extern const uint8_t _node_vendors_1b8c7b_bundle_js_gz_start[] asm("_binary_node_vendors_1b8c7b_bundle_js_gz_start");
extern const uint8_t _node_vendors_1b8c7b_bundle_js_gz_end[] asm("_binary_node_vendors_1b8c7b_bundle_js_gz_end");
const char * resource_lookups[] = {
"/css/index.1ab179394339385e0a02.css.gz",
"/favicon-32x32.png",
"/index.html.gz",
"/js/index.1b8c7b.bundle.js.gz",
"/js/node_vendors.1b8c7b.bundle.js.gz",
""
};
const uint8_t * resource_map_start[] = {
_index_1ab179394339385e0a02_css_gz_start,
_favicon_32x32_png_start,
_index_html_gz_start,
_index_1b8c7b_bundle_js_gz_start,
_node_vendors_1b8c7b_bundle_js_gz_start
};
const uint8_t * resource_map_end[] = {
_index_1ab179394339385e0a02_css_gz_end,
_favicon_32x32_png_end,
_index_html_gz_end,
_index_1b8c7b_bundle_js_gz_end,
_node_vendors_1b8c7b_bundle_js_gz_end
};

View File

@@ -10,15 +10,19 @@ const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
const webpack = require("webpack");
const path = require("path");
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const globSync = require("glob").sync;
const glob = require('glob');
const { merge } = require('webpack-merge');
const devserver = require('./webpack/webpack.dev.js');
const fs = require('fs');
const zlib = require("zlib");
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const whitelister = require('purgecss-whitelister');
const GrpcToolsNodeProtocPlugin = require('./webpack/GrpcToolsNodeProtocPlugin.js');
const buildRootPath = path.join(process.cwd(), '..', '..', '..');
const wifiManagerPath = glob.sync(path.join(buildRootPath, 'components/**/wifi-manager*'))[0];
const ComponentsPath = glob.sync(path.join(buildRootPath, 'components/'))[0];
const buildCRootPath = glob.sync(buildRootPath)[0];
const SPIFFSPath = glob.sync(path.join(buildRootPath, 'SPIFFS'))[0];
const PATHS = {
@@ -39,22 +43,24 @@ class BuildEventsHook {
module.exports = (env, options) => (
merge(
env.WEBPACK_SERVE ? devserver : {},
env.ANALYZE_SIZE?{ plugins: [ new BundleAnalyzerPlugin(
{
analyzerMode: 'static',
generateStatsFile: true,
statsFilename: 'stats.json',
}
) ]}:{},
env.WEBPACK_SERVE ? devserver : {},
env.ANALYZE_SIZE ? {
plugins: [new BundleAnalyzerPlugin(
{
analyzerMode: 'static',
generateStatsFile: true,
statsFilename: 'stats.json',
}
)]
} : {},
// { stats: 'verbose', },
{
entry:
entry:
{
index: './src/index.ts'
index: './src/index.ts'
},
devtool:"source-map",
devtool: "source-map",
module: {
rules: [
{
@@ -62,10 +68,10 @@ module.exports = (env, options) => (
loader: 'ejs-loader',
options: {
variable: 'data',
interpolate : '\\{\\{(.+?)\\}\\}',
evaluate : '\\[\\[(.+?)\\]\\]'
interpolate: '\\{\\{(.+?)\\}\\}',
evaluate: '\\[\\[(.+?)\\]\\]'
}
},
},
{
test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
use: [
@@ -77,10 +83,10 @@ module.exports = (env, options) => (
}
}
]
},
},
// {
// test: /\.s[ac]ss$/i,
// use: [{
// loader: 'style-loader', // inject CSS to page
// },
@@ -105,42 +111,42 @@ module.exports = (env, options) => (
{
test: /\.(scss)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "../",
},
},
// {
// // inject CSS to page
// loader: 'style-loader'
// },
{
// translates CSS into CommonJS modules
loader: 'css-loader'
},
{
// Run postcss actions
loader: 'postcss-loader',
options: {
// `postcssOptions` is needed for postcss 8.x;
// if you use postcss 7.x skip the key
postcssOptions: {
// postcss plugins, can be exported to postcss.config.js
plugins: function () {
return [
require('autoprefixer')
];
// {
// // inject CSS to page
// loader: 'style-loader'
// },
{
// translates CSS into CommonJS modules
loader: 'css-loader'
},
{
// Run postcss actions
loader: 'postcss-loader',
options: {
// `postcssOptions` is needed for postcss 8.x;
// if you use postcss 7.x skip the key
postcssOptions: {
// postcss plugins, can be exported to postcss.config.js
plugins: function () {
return [
require('autoprefixer')
];
}
}
}
}
}, {
// compiles Sass to CSS
loader: 'sass-loader'
}]
},
}, {
// compiles Sass to CSS
loader: 'sass-loader'
}]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
@@ -156,62 +162,70 @@ module.exports = (env, options) => (
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: "asset",
},
},
// {
// test: /\.html$/i,
// type: "asset/resource",
// },
{
test: /\.html$/i,
loader: "html-loader",
options: {
minimize: true,
}
},
{
test: /\.html$/i,
loader: "html-loader",
options: {
minimize: true,
}
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
}
],
},
plugins: [
new GrpcToolsNodeProtocPlugin({
protoPaths: [`${path.join(ComponentsPath, 'spotify/cspot/bell/external/nanopb/generator/proto')}`,
`${path.join(buildCRootPath, 'protobuf')}`],
protoSources: [`${path.join(buildCRootPath, 'protobuf/*.proto')}`,
`${path.join(ComponentsPath, 'spotify/cspot/bell/external/nanopb/generator/proto/*.proto')}`],
outputDir: './src/js/proto'
}
),
new HtmlWebpackPlugin({
title: 'SqueezeESP32',
template: './src/index.ejs',
filename: 'index.html',
inject: 'body',
minify: {
html5 : true,
collapseWhitespace : true,
minifyCSS : true,
minifyJS : true,
minifyURLs : false,
removeAttributeQuotes : true,
removeComments : true, // false for Vue SSR to find app placeholder
removeEmptyAttributes : true,
removeOptionalTags : true,
removeRedundantAttributes : true,
removeScriptTypeAttributes : true,
removeStyleLinkTypeAttributese : true,
useShortDoctype : true
html5: true,
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true,
minifyURLs: false,
removeAttributeQuotes: true,
removeComments: true, // false for Vue SSR to find app placeholder
removeEmptyAttributes: true,
removeOptionalTags: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributese: true,
useShortDoctype: true
},
favicon: "./src/assets/images/favicon-32x32.png",
excludeChunks: ['test'],
}),
// new CompressionPlugin({
// test: /\.(js|css|html|svg)$/,
// //filename: '[path].br[query]',
// filename: "[path][base].br",
// algorithm: 'brotliCompress',
// compressionOptions: { level: 11 },
// threshold: 100,
// minRatio: 0.8,
// deleteOriginalAssets: false
// }),
}),
// new CompressionPlugin({
// test: /\.(js|css|html|svg)$/,
// //filename: '[path].br[query]',
// filename: "[path][base].br",
// algorithm: 'brotliCompress',
// compressionOptions: { level: 11 },
// threshold: 100,
// minRatio: 0.8,
// deleteOriginalAssets: false
// }),
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash].css",
}),
@@ -220,13 +234,14 @@ module.exports = (env, options) => (
paths: glob.sync(`${path.join(__dirname, 'src')}/**/*`, {
nodir: true
}),
whitelist: whitelister('bootstrap/dist/css/bootstrap.css')
}),
new webpack.ProvidePlugin({
$: "jquery",
// jQuery: "jquery",
// "window.jQuery": "jquery",
// Popper: ["popper.js", "default"],
// jQuery: "jquery",
// "window.jQuery": "jquery",
// Popper: ["popper.js", "default"],
// Util: "exports-loader?Util!bootstrap/js/dist/util",
// Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
}),
@@ -236,117 +251,26 @@ module.exports = (env, options) => (
filename: "[path][base].gz",
algorithm: 'gzip',
threshold: 100,
minRatio: 0.8,
}),
new BuildEventsHook('Update C App',
function (stats, arguments) {
}),
if (options.mode !== "production") return;
let buildRootPath = path.join(process.cwd(),'..','..','..');
let wifiManagerPath=glob.sync(path.join(buildRootPath,'components/**/wifi-manager*'))[0];
let buildCRootPath=glob.sync(buildRootPath)[0];
fs.appendFileSync('./dist/index.html.gz',
zlib.gzipSync(fs.readFileSync('./dist/index.html'),
{
chunckSize: 65536,
level: zlib.constants.Z_BEST_COMPRESSION
}));
var getDirectories = function (src, callback) {
var searchPath = path.posix.join(src, '/**/*(*.gz|favicon-32x32.png)');
console.log(`Post build: Getting file list from ${searchPath}`);
glob(searchPath, callback);
};
var cleanUpPath = path.posix.join(buildCRootPath, '/build/*.S');
console.log(`Post build: Cleaning up previous builds in ${cleanUpPath}`);
glob(cleanUpPath, function (err, list) {
if (err) {
console.error('Error', err);
} else {
list.forEach(fileName => {
try {
console.log(`Post build: Purging old binary file ${fileName} from C project.`);
fs.unlinkSync(fileName)
//file removed
} catch (ferr) {
console.error(ferr)
}
});
}
},
'afterEmit'
);
console.log('Generating C include files from webpack build output');
getDirectories('./dist', function (err, list) {
console.log(`Post build: found ${list.length} files. Relative path: ${wifiManagerPath}.`);
if (err) {
console.log('Error', err);
} else {
let exportDefHead =
`/***********************************
webpack_headers
${arguments[1]}
***********************************/
#pragma once
#include <inttypes.h>
extern const char * resource_lookups[];
extern const uint8_t * resource_map_start[];
extern const uint8_t * resource_map_end[];`;
let exportDef = '// Automatically generated. Do not edit manually!.\n' +
'#include <inttypes.h>\n';
let lookupDef = 'const char * resource_lookups[] = {\n';
let lookupMapStart = 'const uint8_t * resource_map_start[] = {\n';
let lookupMapEnd = 'const uint8_t * resource_map_end[] = {\n';
let cMake='';
list.forEach(foundFile => {
let exportName = path.basename(foundFile).replace(/[\. \-]/gm, '_');
//take the full path of the file and make it relative to the build directory
let cmakeFileName = path.posix.relative(wifiManagerPath,glob.sync(path.resolve(foundFile))[0]);
let httpRelativePath=path.posix.join('/',path.posix.relative('dist',foundFile));
exportDef += `extern const uint8_t _${exportName}_start[] asm("_binary_${exportName}_start");\nextern const uint8_t _${exportName}_end[] asm("_binary_${exportName}_end");\n`;
lookupDef += `\t"${httpRelativePath}",\n`;
lookupMapStart += '\t_' + exportName + '_start,\n';
lookupMapEnd += '\t_' + exportName + '_end,\n';
cMake += `target_add_binary_data( __idf_wifi-manager ${cmakeFileName} BINARY)\n`;
console.log(`Post build: adding cmake file reference to ${cmakeFileName} from C project, with web path ${httpRelativePath}.`);
});
lookupDef += '""\n};\n';
lookupMapStart = lookupMapStart.substring(0, lookupMapStart.length - 2) + '\n};\n';
lookupMapEnd = lookupMapEnd.substring(0, lookupMapEnd.length - 2) + '\n};\n';
try {
fs.writeFileSync('webapp.cmake', cMake);
fs.writeFileSync('webpack.c', exportDef + lookupDef + lookupMapStart + lookupMapEnd);
fs.writeFileSync('webpack.h', exportDefHead);
//file written successfully
} catch (e) {
console.error(e);
}
}
});
console.log('Post build completed.');
})
],
optimization: {
minimize: true,
providedExports: true,
usedExports: true,
minimizer: [
new TerserPlugin({
terserOptions: {
format: {
comments: false,
comments: false,
},
},
extractComments: false,
// enable parallel running
// enable parallel running
parallel: true,
}),
new HtmlMinimizerPlugin({
@@ -373,40 +297,40 @@ extern const uint8_t * resource_map_end[];`;
"svgo",
{
plugins: [
{
{
name: 'preset-default',
params: {
overrides: {
// customize default plugin options
inlineStyles: {
onlyMatchedOnce: false,
params: {
overrides: {
// customize default plugin options
inlineStyles: {
onlyMatchedOnce: false,
},
// or disable plugins
removeDoctype: false,
},
// or disable plugins
removeDoctype: false,
},
},
}
}
],
},
],
],
},
},
}),
}),
],
splitChunks: {
cacheGroups: {
vendor: {
name: "node_vendors",
test: /[\\/]node_modules[\\/]/,
chunks: "all",
}
vendor: {
name: "node_vendors",
test: /[\\/]node_modules[\\/]/,
chunks: "all",
}
}
}
}
},
// output: {
// filename: "[name].js",
@@ -414,11 +338,11 @@ extern const uint8_t * resource_map_end[];`;
// publicPath: "",
// },
resolve: {
extensions: ['.tsx', '.ts', '.js', '.ejs' ],
extensions: ['.tsx', '.ts', '.js', '.ejs'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './js/[name].[fullhash:6].bundle.js',
filename: './js/[name].[hash:6].bundle.js',
clean: true
},
}

View File

@@ -1,9 +0,0 @@
/***********************************
webpack_headers
dist/css/index.1ab179394339385e0a02.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.1b8c7b.bundle.js.gz,dist/js/node_vendors.1b8c7b.bundle.js.gz
***********************************/
#pragma once
#include <inttypes.h>
extern const char * resource_lookups[];
extern const uint8_t * resource_map_start[];
extern const uint8_t * resource_map_end[];

View File

@@ -0,0 +1,59 @@
"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var grpcTools = require('grpc-tools');
var execSync = require('child_process').execSync;
var path = require('path');
var fs = require('fs');
var glob = require('glob');
function clearOutputDirectory(directory) {
if (fs.existsSync(directory)) {
var files = fs.readdirSync(directory);
for (var _i = 0, files_1 = files; _i < files_1.length; _i++) {
var file = files_1[_i];
var filePath = path.join(directory, file);
fs.unlinkSync(filePath);
}
}
}
var GrpcToolsNodeProtocPlugin = /** @class */ (function () {
function GrpcToolsNodeProtocPlugin(options) {
this.protoPaths = options.protoPaths || []; // Array of proto_path directories
this.protoSources = options.protoSources || []; // Array of proto source files or directories
this.outputDir = options.outputDir || './'; // Output directory
}
GrpcToolsNodeProtocPlugin.prototype.apply = function (compiler) {
var _this = this;
compiler.hooks.environment.tap('GrpcToolsNodeProtocPlugin', function () {
try {
console.log("Cleaning existing files, if any");
clearOutputDirectory(_this.outputDir);
console.log("Writing protocol buffer files into ".concat(_this.outputDir));
// Resolve proto_path directories
var resolvedProtoPaths = _this.protoPaths.map(function (p) { return path.resolve(__dirname, p); });
var resolvedProtoSources = [];
_this.protoSources.forEach(function (s) {
var matches = glob.sync(path.resolve(__dirname, s));
resolvedProtoSources = resolvedProtoSources.concat(matches);
});
var protocArgs = __spreadArray(__spreadArray([
"--js_out=import_style=commonjs,binary:".concat(_this.outputDir)
], resolvedProtoPaths.map(function (p) { return "--proto_path=".concat(p); }), true), resolvedProtoSources, true);
var command = "npx grpc_tools_node_protoc ".concat(protocArgs.join(' '));
execSync(command, { stdio: 'inherit' });
}
catch (error) {
console.error('Error running grpc tools', error);
}
});
};
return GrpcToolsNodeProtocPlugin;
}());
module.exports = GrpcToolsNodeProtocPlugin;

View File

@@ -0,0 +1,70 @@
import { Compiler } from 'webpack';
const grpcTools = require('grpc-tools');
const { execSync } = require('child_process');
const path = require('path');
const fs = require('fs');
const glob = require('glob');
function clearOutputDirectory(directory:string) {
if (fs.existsSync(directory)) {
const files = fs.readdirSync(directory);
for (const file of files) {
const filePath = path.join(directory, file);
fs.unlinkSync(filePath);
}
}
}
export = GrpcToolsNodeProtocPlugin;
// Define the interface for the plugin options
interface GrpcToolsNodeProtocPluginOptions {
protoPaths?: string[];
protoSources?: string[];
outputDir?: string;
}
class GrpcToolsNodeProtocPlugin {
private protoPaths: string[];
private protoSources: string[];
private outputDir: string;
constructor(options: GrpcToolsNodeProtocPluginOptions) {
this.protoPaths = options.protoPaths || []; // Array of proto_path directories
this.protoSources = options.protoSources || []; // Array of proto source files or directories
this.outputDir = options.outputDir || './'; // Output directory
}
apply(compiler:Compiler) {
compiler.hooks.environment.tap('GrpcToolsNodeProtocPlugin', () => {
try {
console.log(`Cleaning existing files, if any`)
clearOutputDirectory(this.outputDir);
console.log(`Writing protocol buffer files into ${this.outputDir}`)
// Resolve proto_path directories
const resolvedProtoPaths = this.protoPaths.map(p => path.resolve(__dirname, p));
var resolvedProtoSources:string[] = [];
this.protoSources.forEach(function (s) {
var matches = glob.sync(path.resolve(__dirname, s));
resolvedProtoSources = resolvedProtoSources.concat(matches);
});
const protocArgs = [
`--js_out=import_style=commonjs,binary:${this.outputDir}`,
// `--grpc_out=generate_package_definition:${this.outputDir}`,
...resolvedProtoPaths.map(p => `--proto_path=${p}`),
...resolvedProtoSources
];
const command = `npx grpc_tools_node_protoc ${protocArgs.join(' ')}`;
execSync(command, { stdio: 'inherit' });
} catch (error) {
console.error('Error running grpc tools', error);
}
});
}
}

View File

@@ -0,0 +1,143 @@
import { Compiler } from 'webpack';
const path = require('path');
const fs = require('fs');
const zlib = require("zlib");
export = SPIFFSUpdate;
// Define the interface for the plugin options
interface SPIFFSUpdateOptions {
sourceFiles?: string[];
targetFiles?: string[];
compress?: boolean;
}
class SPIFFSUpdate {
private sourceFiles: string[];
private targetFiles: string[];
private compress: boolean;
constructor(options: SPIFFSUpdateOptions) {
this.sourceFiles = options.sourceFiles || []; // Array of proto_path directories
this.targetFiles = options.targetFiles || []; // Array of proto source files or directories
this.compress = options.compress || true; // Output directory
}
apply(compiler: Compiler) {
compiler.hooks.afterEmit.tapAsync('GrpcToolsNodeProtocPlugin', (compilation, callback) => {
try {
fs.appendFileSync('./dist/index.html.gz',
zlib.gzipSync(fs.readFileSync('./dist/index.html'),
{
chunckSize: 65536,
level: zlib.constants.Z_BEST_COMPRESSION
})
);
// if (options.mode !== "production") return;
// let buildRootPath = path.join(process.cwd(), '..', '..', '..');
// let wifiManagerPath = glob.sync(path.join(buildRootPath, 'components/**/wifi-manager*'))[0];
// let buildCRootPath = glob.sync(buildRootPath)[0];
// fs.appendFileSync('./dist/index.html.gz',
// zlib.gzipSync(fs.readFileSync('./dist/index.html'),
// {
// chunckSize: 65536,
// level: zlib.constants.Z_BEST_COMPRESSION
// }));
// var getDirectories = function (src, callback) {
// var searchPath = path.posix.join(src, '/**/*(*.gz|favicon-32x32.png)');
// console.log(`Post build: Getting file list from ${searchPath}`);
// glob(searchPath, callback);
// };
// var cleanUpPath = path.posix.join(buildCRootPath, '/build/*.S');
// console.log(`Post build: Cleaning up previous builds in ${cleanUpPath}`);
// glob(cleanUpPath, function (err, list) {
// if (err) {
// console.error('Error', err);
// } else {
// list.forEach(fileName => {
// try {
// console.log(`Post build: Purging old binary file ${fileName} from C project.`);
// fs.unlinkSync(fileName)
// //file removed
// } catch (ferr) {
// console.error(ferr)
// }
// });
// }
// },
// 'afterEmit'
// );
// console.log('Generating C include files from webpack build output');
// getDirectories('./dist', function (err, list) {
// console.log(`Post build: found ${list.length} files. Relative path: ${wifiManagerPath}.`);
// if (err) {
// console.log('Error', err);
// } else {
// let exportDefHead =
// `/***********************************
// webpack_headers
// ${arguments[1]}
// ***********************************/
// #pragma once
// #include <inttypes.h>
// extern const char * resource_lookups[];
// extern const uint8_t * resource_map_start[];
// extern const uint8_t * resource_map_end[];`;
// let exportDef = '// Automatically generated. Do not edit manually!.\n' +
// '#include <inttypes.h>\n';
// let lookupDef = 'const char * resource_lookups[] = {\n';
// let lookupMapStart = 'const uint8_t * resource_map_start[] = {\n';
// let lookupMapEnd = 'const uint8_t * resource_map_end[] = {\n';
// let cMake = '';
// list.forEach(foundFile => {
// let exportName = path.basename(foundFile).replace(/[\. \-]/gm, '_');
// //take the full path of the file and make it relative to the build directory
// let cmakeFileName = path.posix.relative(wifiManagerPath, glob.sync(path.resolve(foundFile))[0]);
// let httpRelativePath = path.posix.join('/', path.posix.relative('dist', foundFile));
// exportDef += `extern const uint8_t _${exportName}_start[] asm("_binary_${exportName}_start");\nextern const uint8_t _${exportName}_end[] asm("_binary_${exportName}_end");\n`;
// lookupDef += `\t"${httpRelativePath}",\n`;
// lookupMapStart += '\t_' + exportName + '_start,\n';
// lookupMapEnd += '\t_' + exportName + '_end,\n';
// cMake += `target_add_binary_data( __idf_wifi-manager ${cmakeFileName} BINARY)\n`;
// console.log(`Post build: adding cmake file reference to ${cmakeFileName} from C project, with web path ${httpRelativePath}.`);
// });
// lookupDef += '""\n};\n';
// lookupMapStart = lookupMapStart.substring(0, lookupMapStart.length - 2) + '\n};\n';
// lookupMapEnd = lookupMapEnd.substring(0, lookupMapEnd.length - 2) + '\n};\n';
// try {
// fs.writeFileSync('webapp.cmake', cMake);
// fs.writeFileSync('webpack.c', exportDef + lookupDef + lookupMapStart + lookupMapEnd);
// fs.writeFileSync('webpack.h', exportDefHead);
// //file written successfully
// } catch (e) {
// console.error(e);
// }
// }
// });
// console.log('Post build completed.');
// })
} catch (error) {
console.error('Error setting up grpc-tools protoc', error);
}
callback();
});
}
}

View File

@@ -60,9 +60,6 @@ void register_common_handlers(httpd_handle_t server){
void register_regular_handlers(httpd_handle_t server){
httpd_uri_t root_get = { .uri = "/", .method = HTTP_GET, .handler = root_get_handler, .user_ctx = rest_context };
httpd_register_uri_handler(server, &root_get);
httpd_uri_t ap_get = { .uri = "/ap.json", .method = HTTP_GET, .handler = ap_get_handler, .user_ctx = rest_context };
httpd_register_uri_handler(server, &ap_get);
httpd_uri_t scan_get = { .uri = "/scan.json", .method = HTTP_GET, .handler = ap_scan_handler, .user_ctx = rest_context };
httpd_register_uri_handler(server, &scan_get);
httpd_uri_t config_get = { .uri = "/config.json", .method = HTTP_GET, .handler = config_get_handler, .user_ctx = rest_context };
@@ -123,7 +120,11 @@ void register_regular_handlers(httpd_handle_t server){
httpd_uri_t connect_redirect_8 = { .uri = "/success.txt", .method = HTTP_GET, .handler = redirect_ev_handler, .user_ctx = rest_context }; // OSX
httpd_register_uri_handler(server, &connect_redirect_8);
httpd_uri_t configurator_post = { .uri = "/config.pro", .method = HTTP_POST, .handler = configurator_post_handler, .user_ctx = rest_context };
httpd_register_uri_handler(server, &configurator_post);
httpd_uri_t configurator_get = { .uri = "/config.pro", .method = HTTP_POST, .handler = configurator_get_handler, .user_ctx = rest_context };
httpd_register_uri_handler(server, &configurator_get);
ESP_LOGD(TAG,"Registering default error handler for 404");
httpd_register_err_handler(server, HTTPD_404_NOT_FOUND,&err_handler);