mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-01-29 13:50:48 +03:00
Network manager implemented and relatively stable
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
|
||||
set( WEBPACK_DIR webapp/webpack/dist )
|
||||
idf_component_register( SRC_DIRS . webapp
|
||||
INCLUDE_DIRS . webapp ${IDF_PATH}/components/esp_http_server/src ${IDF_PATH}/components/esp_http_server/src/port/esp32 ${IDF_PATH}/components/esp_http_server/src/util ${IDF_PATH}/components/esp_http_server/src/
|
||||
idf_component_register( SRC_DIRS . webapp UML-State-Machine-in-C/src
|
||||
INCLUDE_DIRS . webapp UML-State-Machine-in-C/src ${IDF_PATH}/components/esp_http_server/src ${IDF_PATH}/components/esp_http_server/src/port/esp32 ${IDF_PATH}/components/esp_http_server/src/util ${IDF_PATH}/components/esp_http_server/src/
|
||||
REQUIRES squeezelite-ota json mdns
|
||||
PRIV_REQUIRES tools cpp-stateless services platform_config esp_common json newlib freertos spi_flash nvs_flash mdns pthread wpa_supplicant platform_console esp_http_server console driver_bt
|
||||
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 driver_bt
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# What is esp32-wifi-manager?
|
||||
*esp32-wifi-manager* is an esp32 program that enables easy management of wifi networks through a web application.
|
||||
|
||||
*esp32-wifi-manager* is **lightweight** (8KB of task stack in total) and barely uses any CPU power through a completely event driven architecture. It's an all in one wifi scanner, http server & dns daemon living in the least amount of RAM possible.
|
||||
|
||||
For real time constrained applications, *esp32-wifi-manager* can live entirely on PRO CPU, leaving the entire APP CPU untouched for your own needs.
|
||||
|
||||
*esp32-wifi-manager* will automatically attempt to re-connect to a previously saved network on boot, and it will start its own wifi access point through which you can manage wifi networks if a saved network cannot be found and/or if the connection is lost.
|
||||
|
||||
*esp32-wifi-manager* is an esp-idf project that compiles successfully with the esp-idf 3.2 release. You can simply copy the project and start adding your own code to it.
|
||||
|
||||
# Demo
|
||||
[](http://www.youtube.com/watch?v=hxlZi15bym4)
|
||||
|
||||
# Look and Feel
|
||||
 
|
||||
|
||||
# Adding esp32-wifi-manager to your code
|
||||
Ther are effectively three different ways you can embed esp32-wifi-manager with your code:
|
||||
* Just forget about it and poll in your code for wifi connectivity status
|
||||
* Use event callbacks
|
||||
* Modify esp32-wifi-manager code directly to fit your needs
|
||||
|
||||
**Event callbacks** are the cleanest way to use the wifi manager and that's the recommended way to do it. A typical use-case would be to get notified when wifi manager finally gets a connection an access point. In order to do this you can simply define a callback function:
|
||||
|
||||
```c
|
||||
void cb_connection_ok(void *pvParameter){
|
||||
ESP_LOGI(TAG, "I have a connection!");
|
||||
}
|
||||
```
|
||||
|
||||
Then just register it by calling:
|
||||
|
||||
```c
|
||||
wifi_manager_set_callback(EVENT_STA_GOT_IP, &cb_connection_ok);
|
||||
```
|
||||
|
||||
That's it! Now everytime the event is triggered it will call this function.
|
||||
|
||||
# License
|
||||
*esp32-wifi-manager* is MIT licensed. As such, it can be included in any project, commercial or not, as long as you retain original copyright. Please make sure to read the license file.
|
||||
1
components/wifi-manager/UML-State-Machine-in-C
Submodule
1
components/wifi-manager/UML-State-Machine-in-C
Submodule
Submodule components/wifi-manager/UML-State-Machine-in-C added at 96264241ad
@@ -24,6 +24,7 @@
|
||||
#include <_esp_http_server.h>
|
||||
#include "esp_httpd_priv.h"
|
||||
#include "ctrl_sock.h"
|
||||
#include "globdefs.h"
|
||||
|
||||
static const char *TAG = "_httpd";
|
||||
|
||||
@@ -269,18 +270,18 @@ static void _httpd_thread(void *arg)
|
||||
static struct httpd_data *__httpd_create(const httpd_config_t *config)
|
||||
{
|
||||
/* Allocate memory for httpd instance data */
|
||||
struct httpd_data *hd = calloc(1, sizeof(struct httpd_data));
|
||||
struct httpd_data *hd = malloc_init_external(sizeof(struct httpd_data));
|
||||
if (!hd) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP server instance"));
|
||||
return NULL;
|
||||
}
|
||||
hd->hd_calls = calloc(config->max_uri_handlers, sizeof(httpd_uri_t *));
|
||||
hd->hd_calls = malloc_init_external(config->max_uri_handlers* sizeof(httpd_uri_t *));
|
||||
if (!hd->hd_calls) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP URI handlers"));
|
||||
free(hd);
|
||||
return NULL;
|
||||
}
|
||||
hd->hd_sd = calloc(config->max_open_sockets, sizeof(struct sock_db));
|
||||
hd->hd_sd = malloc_init_external(config->max_open_sockets* sizeof(struct sock_db));
|
||||
if (!hd->hd_sd) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP session data"));
|
||||
free(hd->hd_calls);
|
||||
@@ -288,7 +289,7 @@ static struct httpd_data *__httpd_create(const httpd_config_t *config)
|
||||
return NULL;
|
||||
}
|
||||
struct httpd_req_aux *ra = &hd->hd_req_aux;
|
||||
ra->resp_hdrs = calloc(config->max_resp_headers, sizeof(struct resp_hdr));
|
||||
ra->resp_hdrs = malloc_init_external(config->max_resp_headers* sizeof(struct resp_hdr));
|
||||
if (!ra->resp_hdrs) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP response headers"));
|
||||
free(hd->hd_sd);
|
||||
@@ -296,7 +297,7 @@ static struct httpd_data *__httpd_create(const httpd_config_t *config)
|
||||
free(hd);
|
||||
return NULL;
|
||||
}
|
||||
hd->err_handler_fns = calloc(HTTPD_ERR_CODE_MAX, sizeof(httpd_err_handler_func_t));
|
||||
hd->err_handler_fns = malloc_init_external(HTTPD_ERR_CODE_MAX* sizeof(httpd_err_handler_func_t));
|
||||
if (!hd->err_handler_fns) {
|
||||
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP error handlers"));
|
||||
free(ra->resp_hdrs);
|
||||
|
||||
@@ -59,8 +59,8 @@ static const char TAG[] = "dns_server";
|
||||
static TaskHandle_t task_dns_server = NULL;
|
||||
int socket_fd;
|
||||
|
||||
void dns_server_start() {
|
||||
xTaskCreate(&dns_server, "dns_server", 3072, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_dns_server);
|
||||
void dns_server_start(esp_netif_t * netif) {
|
||||
xTaskCreate(&dns_server, "dns_server", 3072, (void *)netif, WIFI_MANAGER_TASK_PRIORITY-1, &task_dns_server);
|
||||
}
|
||||
|
||||
void dns_server_stop(){
|
||||
@@ -75,7 +75,8 @@ void dns_server_stop(){
|
||||
|
||||
void dns_server(void *pvParameters) {
|
||||
struct sockaddr_in sa, ra;
|
||||
|
||||
esp_err_t esp_err = ESP_OK;
|
||||
esp_netif_t * netif = (esp_netif_t * )pvParameters;
|
||||
/* Set redirection DNS hijack to the access point IP */
|
||||
ip4_addr_t ip_resolved;
|
||||
inet_pton(AF_INET, DEFAULT_AP_IP, &ip_resolved);
|
||||
@@ -90,10 +91,14 @@ void dns_server(void *pvParameters) {
|
||||
memset(&sa, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
/* Bind to port 53 (typical DNS Server port) */
|
||||
tcpip_adapter_ip_info_t ip;
|
||||
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip);
|
||||
esp_netif_ip_info_t ip_info;
|
||||
esp_err = esp_netif_get_ip_info(netif,&ip_info);
|
||||
if(esp_err!=ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to get adapter info for udp: %s", esp_err_to_name(esp_err));
|
||||
exit(1);
|
||||
}
|
||||
ra.sin_family = AF_INET;
|
||||
ra.sin_addr.s_addr = ip.ip.addr;
|
||||
ra.sin_addr.s_addr = ip_info.ip.addr;
|
||||
ra.sin_port = htons(53);
|
||||
if (bind(socket_fd, (struct sockaddr *)&ra, sizeof(struct sockaddr_in)) == -1) {
|
||||
ESP_LOGE(TAG, "Failed to bind to 53/udp");
|
||||
@@ -149,7 +154,7 @@ void dns_server(void *pvParameters) {
|
||||
for(char* c=domain; *c != '\0'; c++){
|
||||
if(*c < ' ' || *c > 'z') *c = '.'; /* technically we should test if the first two bits are 00 (e.g. if( (*c & 0xC0) == 0x00) *c = '.') but this makes the code a lot more readable */
|
||||
}
|
||||
ESP_LOGI(TAG, "Replying to DNS request for %s from %s", domain, ip_address);
|
||||
ESP_LOGD(TAG, "Replying to DNS request for %s from %s", domain, ip_address);
|
||||
|
||||
|
||||
/* create DNS answer at the end of the query*/
|
||||
|
||||
@@ -35,6 +35,7 @@ Contains the freeRTOS task for the DNS server that processes the requests.
|
||||
#include <esp_system.h>
|
||||
#include <stdbool.h>
|
||||
#include "squeezelite-ota.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -128,7 +129,7 @@ typedef struct __attribute__((__packed__)) dns_answer_t{
|
||||
}dns_answer_t;
|
||||
|
||||
void dns_server(void *pvParameters);
|
||||
void dns_server_start();
|
||||
void dns_server_start(esp_netif_t * netif);
|
||||
void dns_server_stop();
|
||||
|
||||
|
||||
|
||||
@@ -1,34 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2017-2019 Tony Pottier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@file http_server.c
|
||||
@author Tony Pottier
|
||||
@brief Defines all functions necessary for the HTTP server to run.
|
||||
|
||||
Contains the freeRTOS task for the HTTP listener and all necessary support
|
||||
function to process requests, decode URLs, serve files, etc. etc.
|
||||
|
||||
@note http_server task cannot run without the wifi_manager task!
|
||||
@see https://idyl.io
|
||||
@see https://github.com/tonyp7/esp32-wifi-manager
|
||||
Copyright (c) 2017-2021 Sebastien L
|
||||
*/
|
||||
|
||||
#include "http_server_handlers.h"
|
||||
@@ -57,7 +28,8 @@ function to process requests, decode URLs, serve files, etc. etc.
|
||||
#include "webapp/webpack.h"
|
||||
#include "network_wifi.h"
|
||||
#include "network_status.h"
|
||||
|
||||
#include "globdefs.h"
|
||||
|
||||
#define HTTP_STACK_SIZE (5*1024)
|
||||
const char str_na[]="N/A";
|
||||
#define STR_OR_NA(s) s?s:str_na
|
||||
@@ -104,7 +76,7 @@ char * alloc_get_http_header(httpd_req_t * req, const char * key){
|
||||
* extra byte for null termination */
|
||||
buf_len = httpd_req_get_hdr_value_len(req, key) + 1;
|
||||
if (buf_len > 1) {
|
||||
buf = malloc(buf_len);
|
||||
buf = malloc_init_external(buf_len);
|
||||
/* Copy null terminated value string into buffer */
|
||||
if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK) {
|
||||
ESP_LOGD_LOC(TAG, "Found header => %s: %s",key, buf);
|
||||
@@ -120,16 +92,14 @@ char * http_alloc_get_socket_address(httpd_req_t *req, u8_t local, in_port_t * p
|
||||
union sockaddr_aligned addr;
|
||||
len = sizeof(addr);
|
||||
ip_addr_t * ip_addr=NULL;
|
||||
char * ipstr = malloc(INET6_ADDRSTRLEN);
|
||||
memset(ipstr,0x0,INET6_ADDRSTRLEN);
|
||||
|
||||
char * ipstr = malloc_init_external(INET6_ADDRSTRLEN);
|
||||
typedef int (*getaddrname_fn_t)(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
getaddrname_fn_t get_addr = NULL;
|
||||
|
||||
int s = httpd_req_to_sockfd(req);
|
||||
if(s == -1) {
|
||||
free(ipstr);
|
||||
return strdup("httpd_req_to_sockfd error");
|
||||
return strdup_psram("httpd_req_to_sockfd error");
|
||||
}
|
||||
ESP_LOGV_LOC(TAG,"httpd socket descriptor: %u", s);
|
||||
|
||||
@@ -192,7 +162,7 @@ bool is_captive_portal_host_name(httpd_req_t *req){
|
||||
ESP_LOGD_LOC(TAG, "Soft AP Host name is %s",ap_host_name);
|
||||
}
|
||||
|
||||
ap_ip_address = malloc(IP4ADDR_STRLEN_MAX);
|
||||
ap_ip_address = malloc_init_external(IP4ADDR_STRLEN_MAX);
|
||||
memset(ap_ip_address, 0x00, IP4ADDR_STRLEN_MAX);
|
||||
if(ap_ip_address){
|
||||
ESP_LOGD_LOC(TAG, "Converting soft ip address to string");
|
||||
@@ -233,8 +203,7 @@ session_context_t* get_session_context(httpd_req_t *req){
|
||||
bool newConnection=false;
|
||||
if (! req->sess_ctx) {
|
||||
ESP_LOGD(TAG,"New connection context. Allocating session buffer");
|
||||
req->sess_ctx = malloc(sizeof(session_context_t));
|
||||
memset(req->sess_ctx,0x00,sizeof(session_context_t));
|
||||
req->sess_ctx = malloc_init_external(sizeof(session_context_t));
|
||||
req->free_ctx = free_ctx_func;
|
||||
newConnection = true;
|
||||
// get the remote IP address only once per session
|
||||
@@ -256,11 +225,13 @@ bool is_user_authenticated(httpd_req_t *req){
|
||||
return true;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG,"Heap internal:%zu (min:%zu) external:%zu (min:%zu)",
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM));
|
||||
ESP_LOGD(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu) dma:%zu (min:%zu)",
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_free_size(MALLOC_CAP_DMA),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_DMA));
|
||||
|
||||
// todo: ask for user to authenticate
|
||||
return false;
|
||||
@@ -439,7 +410,7 @@ esp_err_t ap_scan_handler(httpd_req_t *req){
|
||||
// todo: redirect to login page
|
||||
// return ESP_OK;
|
||||
}
|
||||
network_manager_async_scan();
|
||||
network_async_scan();
|
||||
esp_err_t err = set_content_type_from_req(req);
|
||||
if(err == ESP_OK){
|
||||
httpd_resp_send(req, (const char *)empty, HTTPD_RESP_USE_STRLEN);
|
||||
@@ -529,9 +500,9 @@ esp_err_t ap_get_handler(httpd_req_t *req){
|
||||
}
|
||||
/* if we can get the mutex, write the last version of the AP list */
|
||||
esp_err_t err = set_content_type_from_req(req);
|
||||
if( err == ESP_OK && wifi_manager_lock_json_buffer(( TickType_t ) 200/portTICK_PERIOD_MS)){
|
||||
char *buff = wifi_manager_alloc_get_ap_list_json();
|
||||
wifi_manager_unlock_json_buffer();
|
||||
if( err == ESP_OK && network_status_lock_json_buffer(( TickType_t ) 200/portTICK_PERIOD_MS)){
|
||||
char *buff = network_status_alloc_get_ap_list_json();
|
||||
network_status_unlock_json_buffer();
|
||||
if(buff!=NULL){
|
||||
httpd_resp_send(req, (const char *)buff, HTTPD_RESP_USE_STRLEN);
|
||||
free(buff);
|
||||
@@ -683,7 +654,7 @@ esp_err_t config_post_handler(httpd_req_t *req){
|
||||
else {
|
||||
// we're getting a request to do an OTA from that URL
|
||||
ESP_LOGW_LOC(TAG, "Found OTA request!");
|
||||
otaURL=strdup(val);
|
||||
otaURL=strdup_psram(val);
|
||||
bOTA=true;
|
||||
}
|
||||
}
|
||||
@@ -730,7 +701,7 @@ esp_err_t config_post_handler(httpd_req_t *req){
|
||||
ESP_LOGW_LOC(TAG, "Restarting system to process OTA for url %s",otaURL);
|
||||
}
|
||||
|
||||
network_manager_reboot_ota(otaURL);
|
||||
network_reboot_ota(otaURL);
|
||||
free(otaURL);
|
||||
}
|
||||
return err;
|
||||
@@ -766,15 +737,15 @@ esp_err_t connect_post_handler(httpd_req_t *req){
|
||||
|
||||
cJSON * ssid_object = cJSON_GetObjectItem(root, "ssid");
|
||||
if(ssid_object !=NULL){
|
||||
ssid = strdup(ssid_object->valuestring);
|
||||
ssid = strdup_psram(ssid_object->valuestring);
|
||||
}
|
||||
cJSON * password_object = cJSON_GetObjectItem(root, "pwd");
|
||||
if(password_object !=NULL){
|
||||
password = strdup(password_object->valuestring);
|
||||
password = strdup_psram(password_object->valuestring);
|
||||
}
|
||||
cJSON * host_name_object = cJSON_GetObjectItem(root, "host_name");
|
||||
if(host_name_object !=NULL){
|
||||
host_name = strdup(host_name_object->valuestring);
|
||||
host_name = strdup_psram(host_name_object->valuestring);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
|
||||
@@ -785,14 +756,7 @@ esp_err_t connect_post_handler(httpd_req_t *req){
|
||||
}
|
||||
|
||||
if(ssid !=NULL && strlen(ssid) <= MAX_SSID_SIZE && strlen(password) <= MAX_PASSWORD_SIZE ){
|
||||
wifi_config_t* config = wifi_manager_get_wifi_sta_config();
|
||||
memset(config, 0x00, sizeof(wifi_config_t));
|
||||
strlcpy((char *)config->sta.ssid, ssid, sizeof(config->sta.ssid)+1);
|
||||
if(password){
|
||||
strlcpy((char *)config->sta.password, password, sizeof(config->sta.password)+1);
|
||||
}
|
||||
ESP_LOGD_LOC(TAG, "http_server_netconn_serve: network_manager_async_scan() call, with ssid: %s, password: %s", config->sta.ssid, config->sta.password);
|
||||
network_manager_async_scan();
|
||||
network_async_connect(ssid, password);
|
||||
httpd_resp_send(req, (const char *)success, strlen(success));
|
||||
}
|
||||
else {
|
||||
@@ -816,7 +780,7 @@ esp_err_t connect_delete_handler(httpd_req_t *req){
|
||||
return err;
|
||||
}
|
||||
httpd_resp_send(req, (const char *)success, strlen(success));
|
||||
network_manager_async_disconnect();
|
||||
network_async_delete();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -833,7 +797,7 @@ esp_err_t reboot_ota_post_handler(httpd_req_t *req){
|
||||
}
|
||||
|
||||
httpd_resp_send(req, (const char *)success, strlen(success));
|
||||
network_manager_async_reboot(OTA);
|
||||
network_async_reboot(OTA);
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_err_t reboot_post_handler(httpd_req_t *req){
|
||||
@@ -848,7 +812,7 @@ esp_err_t reboot_post_handler(httpd_req_t *req){
|
||||
return err;
|
||||
}
|
||||
httpd_resp_send(req, (const char *)success, strlen(success));
|
||||
network_manager_async_reboot(RESTART);
|
||||
network_async_reboot(RESTART);
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_err_t recovery_post_handler(httpd_req_t *req){
|
||||
@@ -863,7 +827,7 @@ esp_err_t recovery_post_handler(httpd_req_t *req){
|
||||
return err;
|
||||
}
|
||||
httpd_resp_send(req, (const char *)success, strlen(success));
|
||||
network_manager_async_reboot(RECOVERY);
|
||||
network_async_reboot(RECOVERY);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -881,7 +845,7 @@ esp_err_t flash_post_handler(httpd_req_t *req){
|
||||
if(err != ESP_OK){
|
||||
return err;
|
||||
}
|
||||
char * binary_buffer = malloc(req->content_len);
|
||||
char * binary_buffer = malloc_init_external(req->content_len);
|
||||
if(binary_buffer == NULL){
|
||||
ESP_LOGE(TAG, "File too large : %d bytes", req->content_len);
|
||||
/* Respond with 400 Bad Request */
|
||||
@@ -981,11 +945,11 @@ esp_err_t process_redirect(httpd_req_t *req, const char * status){
|
||||
remote_ip = http_alloc_get_socket_address(req,0, &port);
|
||||
|
||||
size_t buf_size = strlen(redirect_payload1) +strlen(redirect_payload2) + strlen(redirect_payload3) +2*(strlen(location_prefix)+strlen(ap_ip_address))+1;
|
||||
char * redirect=malloc(buf_size);
|
||||
char * redirect=malloc_init_external(buf_size);
|
||||
|
||||
if(strcasestr(status,"302")){
|
||||
size_t url_buf_size = strlen(location_prefix) + strlen(ap_ip_address)+1;
|
||||
redirect_url = malloc(url_buf_size);
|
||||
redirect_url = malloc_init_external(url_buf_size);
|
||||
memset(redirect_url,0x00,url_buf_size);
|
||||
snprintf(redirect_url, buf_size,"%s%s/",location_prefix, ap_ip_address);
|
||||
ESP_LOGW_LOC(TAG, "Redirecting host [%s] to %s (from uri %s)",remote_ip, redirect_url,req->uri);
|
||||
@@ -1034,9 +998,9 @@ esp_err_t redirect_processor(httpd_req_t *req, httpd_err_code_t error){
|
||||
remote_ip = http_alloc_get_socket_address(req,0, &port);
|
||||
|
||||
ESP_LOGW_LOC(TAG, "%s requested invalid URL: [%s]",remote_ip, req->uri);
|
||||
if(wifi_manager_lock_sta_ip_string(portMAX_DELAY)){
|
||||
sta_ip_address = strdup(wifi_manager_get_sta_ip_string());
|
||||
wifi_manager_unlock_sta_ip_string();
|
||||
if(network_status_lock_sta_ip_string(portMAX_DELAY)){
|
||||
sta_ip_address = strdup_psram(network_status_get_sta_ip_string());
|
||||
network_status_unlock_sta_ip_string();
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Unable to obtain local IP address from WiFi Manager.");
|
||||
@@ -1149,9 +1113,9 @@ esp_err_t status_get_handler(httpd_req_t *req){
|
||||
return err;
|
||||
}
|
||||
|
||||
if(wifi_manager_lock_json_buffer(( TickType_t ) 200/portTICK_PERIOD_MS)) {
|
||||
char *buff = wifi_manager_alloc_get_ip_info_json();
|
||||
wifi_manager_unlock_json_buffer();
|
||||
if(network_status_lock_json_buffer(( TickType_t ) 200/portTICK_PERIOD_MS)) {
|
||||
char *buff = network_status_alloc_get_ip_info_json();
|
||||
network_status_unlock_json_buffer();
|
||||
if(buff) {
|
||||
httpd_resp_send(req, (const char *)buff, strlen(buff));
|
||||
free(buff);
|
||||
@@ -1164,7 +1128,7 @@ esp_err_t status_get_handler(httpd_req_t *req){
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR , "Error retrieving status object");
|
||||
}
|
||||
// update status for next status call
|
||||
network_manager_async_update_status();
|
||||
network_async_update_status();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -1,34 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2017-2019 Tony Pottier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@file http_server.h
|
||||
@author Tony Pottier
|
||||
@brief Defines all functions necessary for the HTTP server to run.
|
||||
|
||||
Contains the freeRTOS task for the HTTP listener and all necessary support
|
||||
function to process requests, decode URLs, serve files, etc. etc.
|
||||
|
||||
@note http_server task cannot run without the wifi_manager task!
|
||||
@see https://idyl.io
|
||||
@see https://github.com/tonyp7/esp32-wifi-manager
|
||||
Copyright (c) 2017-2021 Sebastien L
|
||||
*/
|
||||
|
||||
#ifndef HTTP_SERVER_H_INCLUDED
|
||||
|
||||
@@ -1,38 +1,40 @@
|
||||
#include "esp_eth.h"
|
||||
#include "network_ethernet.h"
|
||||
|
||||
static esp_eth_mac_t* mac_new(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
|
||||
static EXT_RAM_ATTR network_ethernet_driver_t DM9051;
|
||||
static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* 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;
|
||||
return esp_eth_mac_new_dm9051(ð_config, &mac_config);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
static esp_eth_phy_t* phy_new(eth_config_t* ethernet_config) {
|
||||
#ifdef CONFIG_ETH_SPI_ETHERNET_DM9051
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
phy_config.phy_addr = 1;
|
||||
phy_config.phy_addr = -1;
|
||||
phy_config.reset_gpio_num = ethernet_config->rst;
|
||||
return esp_eth_phy_new_dm9051(&phy_config);
|
||||
|
||||
esp_eth_mac_t* mac = esp_eth_mac_new_dm9051(ð_config, &mac_config);
|
||||
esp_eth_phy_t* phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
return esp_eth_driver_install(&config, &DM9051.handle);
|
||||
#else
|
||||
return NULL;
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
static void init_config(eth_config_t* ethernet_config) {
|
||||
}
|
||||
|
||||
static network_ethernet_driver_t DM9051 = {
|
||||
.mac_new = mac_new,
|
||||
.phy_new = phy_new,
|
||||
.init_config = init_config,
|
||||
.valid = true,
|
||||
};
|
||||
static void init_config(eth_config_t* ethernet_config) {
|
||||
DM9051.start = start;
|
||||
DM9051.rmii = true;
|
||||
DM9051.spi = false;
|
||||
DM9051.valid = true;
|
||||
}
|
||||
|
||||
network_ethernet_driver_t* DM9051_Detect(char* Driver) {
|
||||
if (!strcasestr(Driver, "DM9051"))
|
||||
return NULL;
|
||||
#ifdef CONFIG_ETH_SPI_ETHERNET_DM9051
|
||||
DM9051.valid = true;
|
||||
#else
|
||||
DM9051.valid = false;
|
||||
#endif
|
||||
DM9051.init_config = init_config;
|
||||
return &DM9051;
|
||||
}
|
||||
|
||||
@@ -1,47 +1,40 @@
|
||||
#include "esp_eth.h"
|
||||
#include "network_ethernet.h"
|
||||
|
||||
static esp_eth_mac_t* mac_new(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
|
||||
static EXT_RAM_ATTR network_ethernet_driver_t LAN8720;
|
||||
static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* 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.sw_reset_timeout_ms = 400;
|
||||
return esp_eth_mac_new_esp32(&mac_config);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
static esp_eth_phy_t* phy_new(eth_config_t* ethernet_config) {
|
||||
#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
phy_config.phy_addr = 1;
|
||||
phy_config.reset_gpio_num = ethernet_config->rst;
|
||||
return esp_eth_phy_new_lan8720(&phy_config);
|
||||
|
||||
esp_eth_mac_t* mac = esp_eth_mac_new_esp32(&mac_config);
|
||||
esp_eth_phy_t* phy = esp_eth_phy_new_lan8720(&phy_config);
|
||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
return esp_eth_driver_install(&config, &LAN8720.handle);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void init_config(eth_config_t* ethernet_config) {
|
||||
#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
LAN8720.start = start;
|
||||
LAN8720.rmii = true;
|
||||
LAN8720.spi = false;
|
||||
}
|
||||
|
||||
static network_ethernet_driver_t LAN8720 = {
|
||||
|
||||
.mac_new = mac_new,
|
||||
.phy_new = phy_new,
|
||||
.init_config = init_config,
|
||||
#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
|
||||
.valid = true,
|
||||
#else
|
||||
.valid = false,
|
||||
#endif
|
||||
};
|
||||
network_ethernet_driver_t* LAN8720_Detect(char* Driver) {
|
||||
if (!strcasestr(Driver, "LAN8720"))
|
||||
return NULL;
|
||||
#ifdef CONFIG_ETH_PHY_INTERFACE_RMII
|
||||
LAN8720.valid = true;
|
||||
#else
|
||||
LAN8720.valid = false;
|
||||
#endif
|
||||
LAN8720.init_config = init_config;
|
||||
return &LAN8720;
|
||||
}
|
||||
|
||||
@@ -1,43 +1,55 @@
|
||||
#include "esp_eth.h"
|
||||
#include "globdefs.h"
|
||||
#include "network_ethernet.h"
|
||||
static EXT_RAM_ATTR network_ethernet_driver_t W5500;
|
||||
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_eth_mac_t* mac_new(spi_device_handle_t spi_handle, eth_config_t* ethernet_config) {
|
||||
static esp_err_t start(spi_device_handle_t spi_handle, eth_config_t* 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();
|
||||
// we assume that isr has been installed already
|
||||
eth_config.int_gpio_num = ethernet_config->intr;
|
||||
return esp_eth_mac_new_w5500(ð_config, &mac_config);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
static esp_eth_phy_t* phy_new(eth_config_t* ethernet_config) {
|
||||
#ifdef CONFIG_ETH_SPI_ETHERNET_W5500
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
phy_config.phy_addr = 1;
|
||||
|
||||
eth_config.int_gpio_num = ethernet_config->intr;
|
||||
phy_config.phy_addr = -1; // let the system automatically find out the phy address
|
||||
phy_config.reset_gpio_num = ethernet_config->rst;
|
||||
return esp_eth_phy_new_w5500(&phy_config);
|
||||
|
||||
esp_eth_mac_t* mac = esp_eth_mac_new_w5500(ð_config, &mac_config);
|
||||
esp_eth_phy_t* phy = esp_eth_phy_new_w5500(&phy_config);
|
||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
return esp_eth_driver_install(&config, &W5500.handle);
|
||||
#else
|
||||
return NULL;
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void init_config(eth_config_t* ethernet_config) {
|
||||
}
|
||||
esp_netif_inherent_config_t loc_esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
|
||||
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.queue_size = 20;
|
||||
devcfg.spics_io_num = ethernet_config->cs;
|
||||
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;
|
||||
W5500.cfg_netif = &cfg_spi;
|
||||
W5500.devcfg = &devcfg;
|
||||
W5500.start = start;
|
||||
W5500.spi = true;
|
||||
W5500.rmii = false;
|
||||
|
||||
static network_ethernet_driver_t W5500 = {
|
||||
.mac_new = mac_new,
|
||||
.phy_new = phy_new,
|
||||
.init_config = init_config,
|
||||
#ifdef CONFIG_ETH_SPI_ETHERNET_W5500
|
||||
.valid = true,
|
||||
#else
|
||||
.valid = false,
|
||||
#endif
|
||||
};
|
||||
}
|
||||
network_ethernet_driver_t* W5500_Detect(char* Driver, network_ethernet_driver_t* Device) {
|
||||
if (!strcasestr(Driver, "W5500"))
|
||||
return NULL;
|
||||
W5500.init_config = init_config;
|
||||
#ifdef CONFIG_ETH_SPI_ETHERNET_W5500
|
||||
W5500.valid = true;
|
||||
#else
|
||||
W5500.valid = false;
|
||||
#endif
|
||||
return &W5500;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifdef NETWORK_ETHERNET_LOG_LEVEL
|
||||
#define LOG_LOCAL_LEVEL NETWORK_ETHERNET_LOG_LEVEL
|
||||
#endif
|
||||
#include "network_ethernet.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "globdefs.h"
|
||||
@@ -5,14 +8,13 @@
|
||||
#include "network_status.h"
|
||||
#include "platform_config.h"
|
||||
#include "trace.h"
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "accessors.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
//#include "dnserver.h"
|
||||
|
||||
static char TAG[] = "network_ethernet";
|
||||
TimerHandle_t ETH_timer;
|
||||
esp_eth_handle_t eth_handle = NULL;
|
||||
esp_netif_t* eth_netif = NULL;
|
||||
EventGroupHandle_t ethernet_event_group;
|
||||
const int LINK_UP_BIT = BIT0;
|
||||
@@ -22,7 +24,6 @@ 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};
|
||||
#define ETH_TIMEOUT_MS (30 * 1000)
|
||||
static void network_manager_ethernet_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
|
||||
|
||||
/****************************************************************************************
|
||||
*
|
||||
@@ -67,7 +68,7 @@ bool network_ethernet_is_up() {
|
||||
return (xEventGroupGetBits(ethernet_event_group) & LINK_UP_BIT)!=0;
|
||||
}
|
||||
bool network_ethernet_enabled() {
|
||||
return eth_handle != NULL;
|
||||
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;
|
||||
@@ -89,75 +90,33 @@ bool network_ethernet_wait_for_link(uint16_t max_wait_ms){
|
||||
static void ETH_Timeout(void* timer_id);
|
||||
void destroy_network_ethernet() {
|
||||
}
|
||||
static void set_host_name() {
|
||||
ESP_LOGE(TAG, "TODO: Find a way to set the host name here!");
|
||||
// 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) {
|
||||
// ESP_LOGE(TAG, "Could not retrieve host name from nvs");
|
||||
// } else {
|
||||
// if (!network_ethernet_enabled()) {
|
||||
// ESP_LOGE(TAG, "Cannot set name on a disabled interface");
|
||||
// } else {
|
||||
// ESP_LOGD(TAG, "Setting host name to : %s", host_name);
|
||||
// if ((err = esp_netif_set_hostname(eth_handle, host_name)) != ESP_OK) {
|
||||
// ESP_LOGE(TAG, "Unable to set host name. Error: %s", esp_err_to_name(err));
|
||||
// }
|
||||
// ESP_LOGD(TAG, "Done setting host name to : %s", host_name);
|
||||
// }
|
||||
|
||||
// FREE_AND_NULL(host_name);
|
||||
// }
|
||||
}
|
||||
static void network_ethernet_print_config(const eth_config_t* eth_config) {
|
||||
// #if defined(CONFIG_ETH_PHY_INTERFACE_RMII)
|
||||
// if(eth_config->)
|
||||
// ESP_LOGI(TAG,
|
||||
// "Model: %s, rst=%d, mdc=%d, mdio=%d, host=%d, cs=%d, mosi=%d, miso=%d, intr=%d, clk=%d, speed=%d, tx_en=%d, tx0=%d, tx1=%d, rx0=%d, rx1=%d, crs_dv=%d",
|
||||
// eth_config->model, eth_config->rst, eth_config->mdc, eth_config->mdio, eth_config->host, eth_config->cs,
|
||||
// eth_config->mosi, eth_config->miso, eth_config->intr, eth_config->clk, eth_config->speed,
|
||||
// eth_config->tx_en, eth_config->tx0, eth_config->tx1, eth_config->rx0, eth_config->rx1, eth_config->crs_dv);
|
||||
// #else
|
||||
// ESP_LOGI(TAG, "Model: %s, rst=%d, mdc=%d, mdio=%d, host=%d, cs=%d, mosi=%d, miso=%d, intr=%d, clk=%d, speed=%d ",
|
||||
// eth_config->model, eth_config->rst, eth_config->mdc, eth_config->mdio, eth_config->host, eth_config->cs,
|
||||
// eth_config->mosi, eth_config->miso, eth_config->intr, eth_config->clk, eth_config->speed);
|
||||
// :
|
||||
// #endif
|
||||
ESP_LOGI(TAG,"Ethernet config: \n model: %s, valid: %s, type: %s, mdc:%d, mdio:%d, rst:%d, mosi:%d, miso:%d, intr:%d, cs:%d, speed:%d, clk:%d, host:%s(%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->mosi, eth_config->miso, eth_config->intr, eth_config->cs, eth_config->speed, eth_config->clk, eth_config->host==0?"SPI1":eth_config->host==1?"SPI2":eth_config->host==2?"SPI3":"",eth_config->host);
|
||||
}
|
||||
|
||||
|
||||
void init_network_ethernet() {
|
||||
esp_err_t err = ESP_OK;
|
||||
esp_eth_mac_t* mac;
|
||||
esp_eth_phy_t* phy;
|
||||
eth_config_t eth;
|
||||
ESP_LOGI(TAG, "Attempting to initialize Ethernet");
|
||||
config_eth_init(ð);
|
||||
ESP_LOGD(TAG, "Attempting to initialize Ethernet");
|
||||
// quick check if we have a valid ethernet configuration
|
||||
if (!eth.valid) {
|
||||
ESP_LOGI(TAG, "No ethernet");
|
||||
return;
|
||||
}
|
||||
network_driver = network_ethernet_driver_autodetect(eth.model);
|
||||
if (!network_driver) {
|
||||
messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Invalid ethernet Ethernet chip %s", eth.model);
|
||||
return;
|
||||
}
|
||||
if (!network_driver->valid) {
|
||||
messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Code not compiled for Ethernet chip %s", eth.model);
|
||||
if(!eth.valid){
|
||||
ESP_LOGI(TAG,"No Ethernet configuration, or configuration invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
network_driver->init_config(ð);
|
||||
network_ethernet_print_config(ð);
|
||||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
|
||||
eth_netif = esp_netif_new(&cfg);
|
||||
|
||||
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, ð_event_handler, NULL);
|
||||
esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL);
|
||||
ethernet_event_group = xEventGroupCreate();
|
||||
xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT);
|
||||
spi_device_handle_t spi_handle = NULL;
|
||||
if (network_driver->eth_config.spi) {
|
||||
if (network_driver->spi) {
|
||||
spi_host_device_t host = SPI3_HOST;
|
||||
|
||||
if (eth.host != -1) {
|
||||
@@ -169,12 +128,18 @@ void init_network_ethernet() {
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
};
|
||||
|
||||
|
||||
// can't use SPI0
|
||||
if (eth.host == 1)
|
||||
if (eth.host == 0)
|
||||
{
|
||||
ESP_LOGW(TAG,"Cannot use SPI1 host. Defaulting to SPI2");
|
||||
host = SPI2_HOST;
|
||||
ESP_LOGI(TAG, "Initializing SPI bus on host %d with mosi %d and miso %d", host, eth.mosi, eth.miso);
|
||||
err = spi_bus_initialize(host, &buscfg, 1);
|
||||
}
|
||||
else {
|
||||
host = eth.host;
|
||||
}
|
||||
ESP_LOGI(TAG, "Initializing SPI bus on host %d (SPI%d) with mosi %d and miso %d", host,host+1, eth.mosi, eth.miso);
|
||||
err = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "SPI bus init failed : %s", esp_err_to_name(err));
|
||||
}
|
||||
@@ -184,38 +149,39 @@ void init_network_ethernet() {
|
||||
host = spi_system_host;
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 1,
|
||||
.address_bits = 7,
|
||||
.mode = 0,
|
||||
.clock_speed_hz = eth.speed,
|
||||
.spics_io_num = eth.cs,
|
||||
.queue_size = 20};
|
||||
ESP_LOGI(TAG, "Adding ethernet SPI on host %d with mosi %d and miso %d", host, eth.mosi, eth.miso);
|
||||
err = spi_bus_add_device(host, &devcfg, &spi_handle);
|
||||
ESP_LOGI(TAG, "Adding ethernet SPI on host %d (SPI%d) with mosi %d and miso %d", host,host+1, eth.mosi, eth.miso);
|
||||
err = spi_bus_add_device(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) {
|
||||
ESP_LOGD(TAG, "Setting up ethernet driver");
|
||||
mac = network_driver->mac_new(spi_handle, ð);
|
||||
phy = network_driver->phy_new(ð);
|
||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
err = esp_eth_driver_install(&config, ð_handle);
|
||||
err = network_driver->start(spi_handle,ð);
|
||||
}
|
||||
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));
|
||||
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(eth_handle));
|
||||
err = esp_netif_attach(eth_netif, esp_eth_new_netif_glue(network_driver->handle));
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Starting ethernet network");
|
||||
err = esp_eth_start(eth_handle);
|
||||
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));
|
||||
eth_handle = NULL;
|
||||
if(spi_handle) {
|
||||
spi_bus_remove_device(spi_handle);
|
||||
}
|
||||
network_driver->handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,18 +201,17 @@ static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t ev
|
||||
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]);
|
||||
ESP_LOGD(TAG, "Sending EVENT_ETH_LINK_UP message to network manager");
|
||||
network_manager_async_link_up();
|
||||
network_async_link_up();
|
||||
break;
|
||||
case ETHERNET_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "Ethernet Link Down");
|
||||
xEventGroupClearBits(ethernet_event_group, LINK_UP_BIT);
|
||||
ESP_LOGD(TAG, "Sending EVENT_ETH_LINK_DOWN message to network manager");
|
||||
network_manager_async_link_down();
|
||||
network_async_link_down();
|
||||
break;
|
||||
case ETHERNET_EVENT_START:
|
||||
ESP_LOGI(TAG, "Ethernet Started. Setting host name");
|
||||
set_host_name();
|
||||
network_set_hostname(eth_netif);
|
||||
network_async_success();
|
||||
break;
|
||||
case ETHERNET_EVENT_STOP:
|
||||
ESP_LOGI(TAG, "Ethernet Stopped");
|
||||
@@ -254,30 +219,10 @@ static void eth_event_handler(void* arg, esp_event_base_t event_base, int32_t ev
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_ETH_GOT_IP) {
|
||||
network_manager_ethernet_ip_event_handler(arg, event_base, event_id, event_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ETH_Timeout(void* timer_id) {
|
||||
network_manager_async_fail();
|
||||
network_async_fail();
|
||||
}
|
||||
|
||||
static void network_manager_ethernet_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
|
||||
if (event_base != IP_EVENT)
|
||||
return;
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
|
||||
ip_event_got_ip_t* s = event_data;
|
||||
tcpip_adapter_if_t index = s->if_index;
|
||||
esp_netif_ip_info_t* ip_info = &s->ip_info;
|
||||
|
||||
ESP_LOGI(TAG, "Got an IP address from Ethernet interface #%i. IP=" IPSTR ", Gateway=" IPSTR ", NetMask=" IPSTR ", %s",
|
||||
index,
|
||||
IP2STR(&ip_info->ip),
|
||||
IP2STR(&ip_info->gw),
|
||||
IP2STR(&ip_info->netmask),
|
||||
s->ip_changed ? "Address was changed" : "Address unchanged");
|
||||
ip_event_got_ip_t* parm = malloc(sizeof(ip_event_got_ip_t));
|
||||
memcpy(parm, event_data, sizeof(ip_event_got_ip_t));
|
||||
network_manager_async_got_ip(parm);
|
||||
}
|
||||
@@ -3,19 +3,26 @@
|
||||
#include "network_manager.h"
|
||||
#include "accessors.h"
|
||||
#include <string.h>
|
||||
#include "esp_netif_defaults.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
bool valid;
|
||||
eth_config_t eth_config;
|
||||
esp_eth_mac_t* (*mac_new)(spi_device_handle_t spi_handle, eth_config_t * eth_config);
|
||||
esp_eth_phy_t *(*phy_new)( eth_config_t* eth_config);
|
||||
bool rmii;
|
||||
bool spi;
|
||||
esp_eth_handle_t handle;
|
||||
esp_netif_config_t * cfg_netif;
|
||||
spi_device_interface_config_t * devcfg;
|
||||
// esp_eth_mac_t* (*mac_new)(spi_device_handle_t spi_handle, eth_config_t * eth_config);
|
||||
// esp_eth_phy_t *(*phy_new)( eth_config_t* eth_config);
|
||||
esp_err_t (*start)(spi_device_handle_t spi_handle,eth_config_t *ethernet_config);
|
||||
void (*init_config)(eth_config_t * 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);
|
||||
void destroy_network_ethernet();
|
||||
void init_network_ethernet();
|
||||
bool network_ethernet_wait_for_link(uint16_t max_wait_ms);
|
||||
|
||||
@@ -1,34 +1,10 @@
|
||||
/*
|
||||
Copyright (c) 2017-2019 Tony Pottier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@file wifi_manager.c
|
||||
@author Tony Pottier
|
||||
@brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
|
||||
|
||||
Contains the freeRTOS task and all necessary support
|
||||
|
||||
@see https://idyl.io
|
||||
@see https://github.com/tonyp7/esp32-wifi-manager
|
||||
Copyright (c) 2017-2021 Sebastien L
|
||||
*/
|
||||
|
||||
#ifdef NETWORK_MANAGER_LOG_LEVEL
|
||||
#define LOG_LOCAL_LEVEL NETWORK_MANAGER_LOG_LEVEL
|
||||
#endif
|
||||
#include "network_manager.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -37,16 +13,15 @@ Contains the freeRTOS task and all necessary support
|
||||
#include "network_ethernet.h"
|
||||
#include "network_status.h"
|
||||
#include "network_wifi.h"
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
|
||||
#include "dns_server.h"
|
||||
#include "esp_log.h"
|
||||
#include "platform_esp32.h"
|
||||
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "platform_esp32.h"
|
||||
|
||||
#include "freertos/task.h"
|
||||
#include "esp_netif.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "cmd_system.h"
|
||||
@@ -62,59 +37,696 @@ Contains the freeRTOS task and all necessary support
|
||||
#include "lwip/netdb.h"
|
||||
#include "mdns.h"
|
||||
#include "messaging.h"
|
||||
#include "state_machine.h"
|
||||
|
||||
#include "platform_config.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "accessors.h"
|
||||
#include "esp_err.h"
|
||||
#include "globdefs.h"
|
||||
#include "http_server_handlers.h"
|
||||
#include "network_manager.h"
|
||||
|
||||
QueueHandle_t network_queue;
|
||||
BaseType_t network_task_handle;
|
||||
static const char TAG[] = "network";
|
||||
static TaskHandle_t task_network_manager = NULL;
|
||||
RTC_NOINIT_ATTR static bool s_wifi_prioritized = false;
|
||||
extern esp_reset_reason_t xReason;
|
||||
typedef struct network_callback {
|
||||
network_status_reached_cb cb;
|
||||
nm_state_t state;
|
||||
int sub_state;
|
||||
const char* from;
|
||||
SLIST_ENTRY(network_callback)
|
||||
next; //!< next callback
|
||||
} network_callback_t;
|
||||
|
||||
/** linked list of command structures */
|
||||
static SLIST_HEAD(cb_list, network_callback) s_cb_list;
|
||||
|
||||
network_t NM;
|
||||
|
||||
|
||||
//! Create and initialize the array of state machines.
|
||||
state_machine_t* const SM[] = {(state_machine_t*)&NM};
|
||||
static void network_timer_cb(void* timer_id);
|
||||
int get_root_id(const state_t * state);
|
||||
const state_t* get_root( const state_t* const state);
|
||||
static void network_task(void* pvParameters);
|
||||
|
||||
void network_start_stop_dhcp(esp_netif_t* netif, bool start) {
|
||||
tcpip_adapter_dhcp_status_t status;
|
||||
esp_err_t err = ESP_OK;
|
||||
ESP_LOGD(TAG, "Checking if DHCP client for STA interface is running");
|
||||
if (!netif) {
|
||||
ESP_LOGE(TAG, "Invalid adapter. Cannot start/stop dhcp. ");
|
||||
return;
|
||||
}
|
||||
if((err=esp_netif_dhcpc_get_status(netif, &status))!=ESP_OK){
|
||||
ESP_LOGE(TAG,"Error retrieving dhcp status : %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
switch (status)
|
||||
{
|
||||
case ESP_NETIF_DHCP_STARTED:
|
||||
if(start){
|
||||
ESP_LOGD(TAG, "DHCP client already started");
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG, "Stopping DHCP client");
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcpc_stop(netif));
|
||||
}
|
||||
break;
|
||||
case ESP_NETIF_DHCP_STOPPED:
|
||||
if(start){
|
||||
ESP_LOGI(TAG, "Starting DHCP client");
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcpc_start(netif));
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG, "DHCP client already started");
|
||||
}
|
||||
break;
|
||||
case ESP_NETIF_DHCP_INIT:
|
||||
if(start){
|
||||
ESP_LOGI(TAG, "Starting DHCP client");
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcpc_start(netif));
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG, "Stopping DHCP client");
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcpc_stop(netif));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGW(TAG,"Unknown DHCP status");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void network_start_stop_dhcps(esp_netif_t* netif, bool start) {
|
||||
tcpip_adapter_dhcp_status_t status;
|
||||
esp_err_t err = ESP_OK;
|
||||
ESP_LOGD(TAG, "Checking if DHCP server is running");
|
||||
if (!netif) {
|
||||
ESP_LOGE(TAG, "Invalid adapter. Cannot start/stop dhcp server. ");
|
||||
return;
|
||||
}
|
||||
if((err=esp_netif_dhcps_get_status(netif, &status))!=ESP_OK){
|
||||
ESP_LOGE(TAG,"Error retrieving dhcp server status : %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
switch (status)
|
||||
{
|
||||
case ESP_NETIF_DHCP_STARTED:
|
||||
if(start){
|
||||
ESP_LOGD(TAG, "DHCP server already started");
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG, "Stopping DHCP server");
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_stop(netif));
|
||||
}
|
||||
break;
|
||||
case ESP_NETIF_DHCP_STOPPED:
|
||||
if(start){
|
||||
ESP_LOGI(TAG, "Starting DHCP server");
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_start(netif));
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG, "DHCP server already stopped");
|
||||
}
|
||||
break;
|
||||
case ESP_NETIF_DHCP_INIT:
|
||||
if(start){
|
||||
ESP_LOGI(TAG, "Starting DHCP server");
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_start(netif));
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG, "Stopping DHCP server");
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_stop(netif));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGW(TAG,"Unknown DHCP status");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*********************************************************************************************
|
||||
* String conversion routines
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef STR_OR_BLANK
|
||||
#define STR_OR_BLANK(p) p == NULL ? "" : p
|
||||
#endif
|
||||
#define ADD_ROOT(name,...) CASE_TO_STR(name);
|
||||
#define ADD_ROOT_LEAF(name,...) CASE_TO_STR(name);
|
||||
#define ADD_LEAF(name,...) CASE_TO_STR(name);
|
||||
#define ADD_EVENT(name) CASE_TO_STR(name);
|
||||
#define ADD_FIRST_EVENT(name) CASE_TO_STR(name);
|
||||
static const char* state_to_string(const state_t * state) {
|
||||
if(!state) {
|
||||
return "";
|
||||
}
|
||||
switch (state->Parent?state->Parent->Id:state->Id) {
|
||||
ALL_NM_STATE
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
static const char* wifi_state_to_string(mn_wifi_active_state_t state) {
|
||||
switch (state) {
|
||||
ALL_WIFI_STATE(,)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
static const char* eth_state_to_string(mn_eth_active_state_t state) {
|
||||
switch (state) {
|
||||
ALL_ETH_STATE(,)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
static const char* wifi_configuring_state_to_string(mn_wifi_configuring_state_t state) {
|
||||
switch (state) {
|
||||
ALL_WIFI_CONFIGURING_STATE(,)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
static const char* sub_state_to_string(const state_t * state) {
|
||||
if(!state) {
|
||||
return "N/A";
|
||||
}
|
||||
int root_id = get_root_id(state);
|
||||
switch (root_id)
|
||||
{
|
||||
case NETWORK_ETH_ACTIVE_STATE:
|
||||
return eth_state_to_string(state->Id);
|
||||
break;
|
||||
case NETWORK_WIFI_ACTIVE_STATE:
|
||||
return wifi_state_to_string(state->Id);
|
||||
case NETWORK_WIFI_CONFIGURING_ACTIVE_STATE:
|
||||
return wifi_configuring_state_to_string(state->Id);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "*";
|
||||
}
|
||||
|
||||
//EventGroupHandle_t wifi_manager_event_group;
|
||||
void (**cb_ptr_arr)(void*) = NULL;
|
||||
static const char* event_to_string(network_event_t state) {
|
||||
switch (state) {
|
||||
ALL_NM_EVENTS
|
||||
|
||||
/* @brief tag used for ESP serial console messages */
|
||||
//static const char TAG[] = "network_manager";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
/* @brief indicate that the ESP32 is currently connected. */
|
||||
const int WIFI_MANAGER_WIFI_CONNECTED_BIT = BIT0;
|
||||
const int WIFI_MANAGER_AP_STA_CONNECTED_BIT = BIT1;
|
||||
/* @brief Set automatically once the SoftAP is started */
|
||||
const int WIFI_MANAGER_AP_STARTED_BIT = BIT2;
|
||||
/* @brief When set, means a client requested to connect to an access point.*/
|
||||
const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT = BIT3;
|
||||
/* @brief This bit is set automatically as soon as a connection was lost */
|
||||
const int WIFI_MANAGER_STA_DISCONNECT_BIT = BIT4;
|
||||
/* @brief When set, means the wifi manager attempts to restore a previously saved connection at startup. */
|
||||
const int WIFI_MANAGER_REQUEST_RESTORE_STA_BIT = BIT5;
|
||||
/* @brief When set, means a client requested to disconnect from currently connected AP. */
|
||||
const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT = BIT6;
|
||||
/* @brief When set, means a scan is in progress */
|
||||
const int WIFI_MANAGER_SCAN_BIT = BIT7;
|
||||
/* @brief When set, means user requested for a disconnect */
|
||||
const int WIFI_MANAGER_REQUEST_DISCONNECT_BIT = BIT8;
|
||||
/* @brief When set, means user requested connecting to a new network and it failed */
|
||||
const int WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT = BIT9;
|
||||
#undef ADD_EVENT
|
||||
#undef ADD_FIRST_EVENT
|
||||
#undef ADD_ROOT
|
||||
#undef ADD_ROOT_LEAF
|
||||
#undef ADD_LEAF
|
||||
|
||||
/* @brief task handle for the main wifi_manager task */
|
||||
typedef struct {
|
||||
int parent_state;
|
||||
int sub_state_last ;
|
||||
} max_sub_states_t;
|
||||
static const max_sub_states_t state_max[] = {
|
||||
{ .parent_state = NETWORK_INSTANTIATED_STATE, .sub_state_last = 0 },
|
||||
{.parent_state = NETWORK_ETH_ACTIVE_STATE, .sub_state_last = TOTAL_ETH_ACTIVE_STATE-1 },
|
||||
{.parent_state = NETWORK_WIFI_ACTIVE_STATE, .sub_state_last = TOTAL_WIFI_ACTIVE_STATE-1 },
|
||||
{.parent_state = WIFI_CONFIGURING_STATE, .sub_state_last = TOTAL_WIFI_CONFIGURING_STATE-1 },
|
||||
{.parent_state = WIFI_CONFIGURING_STATE, .sub_state_last = TOTAL_WIFI_CONFIGURING_STATE-1 },
|
||||
{.parent_state =-1}
|
||||
};
|
||||
|
||||
|
||||
|
||||
void network_start() {
|
||||
|
||||
if(xReason == ESP_RST_POWERON ){
|
||||
ESP_LOGD(TAG, "Power on reset, initializing wifi priotitized to false");
|
||||
s_wifi_prioritized = false;
|
||||
}
|
||||
ESP_LOGD(TAG, " Creating message queue");
|
||||
network_queue = xQueueCreate(3, sizeof(queue_message));
|
||||
ESP_LOGD(TAG, " Creating network manager task");
|
||||
network_task_handle = xTaskCreate(&network_task, "network", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_network_manager);
|
||||
}
|
||||
|
||||
static void event_logger(uint32_t state_machine, uint32_t state, uint32_t event) {
|
||||
ESP_LOGI(TAG, "Handling network manager event state Id %d->[%s]", state, event_to_string(event));
|
||||
}
|
||||
static const char * get_state_machine_result_string(state_machine_result_t result) {
|
||||
switch(result) {
|
||||
case EVENT_HANDLED:
|
||||
return "EVENT_HANDLED";
|
||||
case EVENT_UN_HANDLED:
|
||||
return "EVENT_UN_HANDLED";
|
||||
case TRIGGERED_TO_SELF:
|
||||
return "TRIGGERED_TO_SELF";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
static void result_logger(uint32_t state, state_machine_result_t result) {
|
||||
ESP_LOGD(TAG, "Network Manager Result: %s, New State id: %d", get_state_machine_result_string(result) , state);
|
||||
}
|
||||
|
||||
static void network_task(void* pvParameters) {
|
||||
queue_message msg;
|
||||
BaseType_t xStatus;
|
||||
initialize_network_handlers((state_machine_t*)&NM);
|
||||
network_async(EN_START);
|
||||
|
||||
/* main processing loop */
|
||||
for (;;) {
|
||||
xStatus = xQueueReceive(network_queue, &msg, portMAX_DELAY);
|
||||
|
||||
if (xStatus == pdPASS) {
|
||||
// pass the event to the sync processor
|
||||
NM.event_parameters = &msg;
|
||||
NM.Machine.Event = msg.trigger;
|
||||
if (dispatch_event(SM, 1, event_logger, result_logger) == EVENT_UN_HANDLED) {
|
||||
network_manager_format_from_to_states(ESP_LOG_ERROR,"Unhandled Event",NULL,NM.Machine.State,msg.trigger,false,"network manager");
|
||||
}
|
||||
} /* end of if status=pdPASS */
|
||||
} /* end of for loop */
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int get_max_substate(nm_state_t state){
|
||||
for(int i=0;state_max[i].parent_state!=-1;i++){
|
||||
if(state_max[i].parent_state == state){
|
||||
return state_max[i].sub_state_last;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
esp_err_t network_register_state_callback(nm_state_t state,int sub_state, const char* from, network_status_reached_cb cb) {
|
||||
network_callback_t* item = NULL;
|
||||
if (!cb) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
item = calloc(1, sizeof(*item));
|
||||
if (item == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
if(sub_state != -1 && sub_state>get_max_substate(state)){
|
||||
// sub state has to be valid
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
item->state = state;
|
||||
item->cb = cb;
|
||||
item->from = from;
|
||||
item->sub_state=sub_state;
|
||||
network_callback_t* last = SLIST_FIRST(&s_cb_list);
|
||||
if (last == NULL) {
|
||||
SLIST_INSERT_HEAD(&s_cb_list, item, next);
|
||||
} else {
|
||||
network_callback_t* it;
|
||||
while ((it = SLIST_NEXT(last, next)) != NULL) {
|
||||
last = it;
|
||||
}
|
||||
SLIST_INSERT_AFTER(last, item, next);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
const state_t* get_root( const state_t* const state){
|
||||
if(!state) return NULL;
|
||||
return state->Parent==NULL?state: get_root(state->Parent);
|
||||
}
|
||||
int get_root_id(const state_t * state){
|
||||
if(!state) return -1;
|
||||
return state->Parent==NULL?state->Id: get_root_id(state->Parent);
|
||||
}
|
||||
|
||||
void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*)) {
|
||||
if (cb_ptr_arr && message_code < MESSAGE_CODE_COUNT) {
|
||||
cb_ptr_arr[message_code] = func_ptr;
|
||||
static bool is_root_state(const state_t * state){
|
||||
return state->Parent==NULL;
|
||||
}
|
||||
static bool is_current_state(const state_t* state, nm_state_t state_id, int sub_state_id){
|
||||
return get_root(state)->Id == state_id && (sub_state_id==-1 || (!is_root_state(state) && state->Id == sub_state_id) );
|
||||
}
|
||||
void network_execute_cb(state_machine_t* const state_machine, const char * caller) {
|
||||
network_callback_t* it;
|
||||
SLIST_FOREACH(it, &s_cb_list, next) {
|
||||
if (is_current_state(state_machine->State,it->state, it->sub_state)) {
|
||||
char * cb_prefix= messaging_alloc_format_string("BEGIN Executing Callback %s", it->from) ;
|
||||
NETWORK_DEBUG_STATE_MACHINE(true,STR_OR_BLANK(cb_prefix),state_machine,false, STR_OR_BLANK(caller));
|
||||
FREE_AND_NULL(cb_prefix);
|
||||
it->cb((nm_state_t)get_root(state_machine->State)->Id, is_root_state(state_machine->State)?-1:state_machine->State->Id);
|
||||
cb_prefix= messaging_alloc_format_string("END Executing Callback %s", it->from) ;
|
||||
NETWORK_DEBUG_STATE_MACHINE(false,STR_OR_BLANK(cb_prefix),state_machine,false, STR_OR_BLANK(caller));
|
||||
FREE_AND_NULL(cb_prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool network_is_wifi_prioritized() {
|
||||
eth_config_t eth_config;
|
||||
config_eth_init(ð_config);
|
||||
// char* prioritize = (char*)config_alloc_get_default(NVS_TYPE_STR, "prio_wifi", "N", 0);
|
||||
// bool result = strcasecmp("N", prioritize);
|
||||
bool result = s_wifi_prioritized;
|
||||
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");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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");
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void network_manager_format_state_machine(esp_log_level_t level, const char* prefix, state_machine_t* state_machine, bool show_source, const char * caller) {
|
||||
state_t const* source_state = NULL;
|
||||
state_t const* current_state = NULL;
|
||||
network_event_t event = -1;
|
||||
MEMTRACE_PRINT_DELTA();
|
||||
if (state_machine) {
|
||||
source_state = ((network_t *)state_machine)->source_state;
|
||||
current_state = state_machine->State;
|
||||
event = state_machine->Event;
|
||||
network_manager_format_from_to_states(level, prefix, source_state, current_state, event, show_source,caller);
|
||||
}
|
||||
else {
|
||||
ESP_LOG_LEVEL(level, TAG, "%s - %s -> [%s]",
|
||||
STR_OR_BLANK(caller),
|
||||
prefix,
|
||||
event_to_string(event));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
void network_manager_format_from_to_states(esp_log_level_t level, const char* prefix, const state_t * from_state,const state_t * current_state, network_event_t event,bool show_source, const char * caller) {
|
||||
const char* source_state = "";
|
||||
const char* source_sub_state = "";
|
||||
const char* state = "N/A";
|
||||
const char* sub_state = "N/A";
|
||||
|
||||
if (current_state) {
|
||||
state = state_to_string(current_state);
|
||||
sub_state = sub_state_to_string(current_state);
|
||||
}
|
||||
if (!from_state) {
|
||||
source_state = "N/A";
|
||||
} else {
|
||||
source_state = state_to_string(from_state);
|
||||
source_sub_state = sub_state_to_string(from_state);
|
||||
}
|
||||
if (show_source) {
|
||||
ESP_LOG_LEVEL(level, TAG, "%s %s %s(%s)->%s(%s) [%s]",
|
||||
STR_OR_BLANK(caller),
|
||||
prefix,
|
||||
source_state,
|
||||
source_sub_state,
|
||||
state,
|
||||
sub_state,
|
||||
event_to_string(event));
|
||||
} else {
|
||||
ESP_LOG_LEVEL(level, TAG, "%s %s %s(%s) [%s]",
|
||||
STR_OR_BLANK(caller),
|
||||
prefix,
|
||||
state,
|
||||
sub_state,
|
||||
event_to_string(event));
|
||||
}
|
||||
}
|
||||
void network_async(network_event_t trigger) {
|
||||
queue_message msg;
|
||||
memset(&msg,0x00,sizeof(msg));
|
||||
msg.trigger = trigger;
|
||||
ESP_LOGD(TAG, "Posting event %s directly", event_to_string(trigger));
|
||||
xQueueSendToBack(network_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
void network_async_fail() {
|
||||
network_async(EN_FAIL);
|
||||
}
|
||||
void network_async_success() {
|
||||
network_async(EN_SUCCESS);
|
||||
}
|
||||
void network_async_connected(){
|
||||
network_async(EN_CONNECTED);
|
||||
}
|
||||
void network_async_link_up() {
|
||||
network_async(EN_LINK_UP);
|
||||
}
|
||||
void network_async_link_down() {
|
||||
network_async(EN_LINK_DOWN);
|
||||
}
|
||||
void network_async_configure() {
|
||||
network_async(EN_CONFIGURE);
|
||||
}
|
||||
void network_async_got_ip() {
|
||||
network_async(EN_GOT_IP);
|
||||
}
|
||||
void network_async_eth_got_ip() {
|
||||
network_async(EN_ETH_GOT_IP);
|
||||
}
|
||||
void network_async_timer() {
|
||||
network_async(EN_TIMER);
|
||||
}
|
||||
void network_async_start() {
|
||||
network_async(EN_START);
|
||||
}
|
||||
void network_async_scan() {
|
||||
network_async(EN_SCAN);
|
||||
}
|
||||
|
||||
void network_async_update_status() {
|
||||
network_async(EN_UPDATE_STATUS);
|
||||
}
|
||||
|
||||
void network_async_delete() {
|
||||
network_async(EN_DELETE);
|
||||
}
|
||||
|
||||
void network_async_scan_done() {
|
||||
network_async(EN_SCAN_DONE);
|
||||
}
|
||||
void network_async_connect(const char * ssid, const char * password) {
|
||||
queue_message msg;
|
||||
memset(&msg,0x00,sizeof(msg));
|
||||
msg.trigger = EN_CONNECT_NEW;
|
||||
msg.ssid = strdup_psram(ssid);
|
||||
if(password && strlen(password) >0){
|
||||
msg.password = strdup_psram(password);
|
||||
}
|
||||
ESP_LOGD(TAG, "Posting event %s", event_to_string(msg.trigger));
|
||||
xQueueSendToBack(network_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
void network_async_lost_connection(wifi_event_sta_disconnected_t* disconnected_event) {
|
||||
queue_message msg;
|
||||
memset(&msg,0x00,sizeof(msg));
|
||||
msg.trigger = EN_LOST_CONNECTION;
|
||||
ESP_LOGD(TAG, "Posting event %s", event_to_string(msg.trigger));
|
||||
msg.disconnected_event = malloc_init_external(sizeof(wifi_event_sta_disconnected_t));
|
||||
if(msg.disconnected_event){
|
||||
memcpy(msg.disconnected_event, disconnected_event,sizeof(wifi_event_sta_disconnected_t));
|
||||
xQueueSendToBack(network_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Unable to post lost connection event.");
|
||||
}
|
||||
}
|
||||
void network_async_reboot(reboot_type_t rtype) {
|
||||
queue_message msg;
|
||||
memset(&msg,0x00,sizeof(msg));
|
||||
msg.trigger = EN_REBOOT;
|
||||
msg.rtype = rtype;
|
||||
ESP_LOGD(TAG, "Posting event %s - type %d", event_to_string(msg.trigger),rtype);
|
||||
xQueueSendToBack(network_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void network_reboot_ota(char* url) {
|
||||
queue_message msg;
|
||||
memset(&msg,0x00,sizeof(msg));
|
||||
|
||||
if (url == NULL) {
|
||||
msg.trigger = EN_REBOOT;
|
||||
msg.rtype = OTA;
|
||||
ESP_LOGD(TAG, "Posting event %s - type %d", event_to_string(msg.trigger),msg.rtype);
|
||||
} else {
|
||||
msg.trigger = EN_REBOOT_URL;
|
||||
ESP_LOGD(TAG, "Posting event %s - type reboot URL", event_to_string(msg.trigger));
|
||||
msg.strval = strdup_psram(url);
|
||||
}
|
||||
|
||||
xQueueSendToBack(network_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
|
||||
network_t* network_get_state_machine() {
|
||||
return &NM;
|
||||
}
|
||||
|
||||
static void network_timer_cb(void* timer_id) {
|
||||
network_async_timer();
|
||||
}
|
||||
esp_netif_t* network_get_active_interface() {
|
||||
if (NM.wifi_ap_netif && (network_wifi_is_ap_mode() || network_wifi_is_ap_sta_mode())) {
|
||||
return NM.wifi_ap_netif;
|
||||
} else if (NM.wifi_netif && network_wifi_is_sta_mode()) {
|
||||
return NM.wifi_netif;
|
||||
}
|
||||
return NM.eth_netif;
|
||||
}
|
||||
bool network_is_interface_connected(esp_netif_t* interface) {
|
||||
esp_err_t err = ESP_OK;
|
||||
tcpip_adapter_ip_info_t ipInfo;
|
||||
if(!interface){
|
||||
return false;
|
||||
}
|
||||
err = network_get_ip_info_for_netif(interface, &ipInfo);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGD(TAG,"network_get_ip_info_for_netif returned %s", esp_err_to_name(err));
|
||||
}
|
||||
return ((err == ESP_OK) && (ipInfo.ip.addr != IPADDR_ANY));
|
||||
}
|
||||
static esp_netif_t* get_connected_interface() {
|
||||
esp_netif_t* interface = NULL;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
// try the active interface
|
||||
interface = network_get_active_interface();
|
||||
break;
|
||||
case 1:
|
||||
interface = NM.wifi_ap_netif;
|
||||
break;
|
||||
case 2:
|
||||
interface = NM.wifi_netif;
|
||||
break;
|
||||
case 3:
|
||||
interface = NM.eth_netif;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (interface && network_is_interface_connected(interface)) {
|
||||
ESP_LOGD(TAG,"Found connected interface in iteration #%d",i);
|
||||
return interface;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG,"No connected interface found");
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t network_get_ip_info_for_netif(esp_netif_t* netif, tcpip_adapter_ip_info_t* ipInfo) {
|
||||
esp_netif_ip_info_t loc_ip_info;
|
||||
if (!ipInfo ) {
|
||||
ESP_LOGE(TAG, "Invalid pointer for ipInfo");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!netif) {
|
||||
ESP_LOGE(TAG, "Invalid pointer for netif");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
memset(ipInfo,0x00,sizeof(tcpip_adapter_ip_info_t));
|
||||
esp_err_t err= esp_netif_get_ip_info(netif, &loc_ip_info);
|
||||
if(err==ESP_OK){
|
||||
ip4_addr_set(&(ipInfo->ip),&loc_ip_info.ip);
|
||||
ip4_addr_set(&(ipInfo->gw),&loc_ip_info.gw);
|
||||
ip4_addr_set(&(ipInfo->netmask),&loc_ip_info.netmask);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
esp_err_t network_get_ip_info(tcpip_adapter_ip_info_t* ipInfo) {
|
||||
esp_netif_t* netif= get_connected_interface();
|
||||
if(netif){
|
||||
return network_get_ip_info_for_netif(netif,ipInfo);
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t network_get_hostname(const char** hostname) {
|
||||
return esp_netif_get_hostname(get_connected_interface(), hostname);
|
||||
}
|
||||
|
||||
void network_set_timer(uint16_t duration) {
|
||||
if (duration > 0) {
|
||||
if (!NM.state_timer) {
|
||||
ESP_LOGD(TAG, "Starting new pulse check timer with period of %u ms.", duration);
|
||||
NM.state_timer = xTimerCreate("background STA", pdMS_TO_TICKS(duration), pdFALSE, NULL, network_timer_cb);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Changing the pulse timer period to %u ms.", duration);
|
||||
xTimerChangePeriod(NM.state_timer, pdMS_TO_TICKS(duration), portMAX_DELAY);
|
||||
}
|
||||
xTimerStart(NM.state_timer, portMAX_DELAY);
|
||||
} else if (NM.state_timer) {
|
||||
ESP_LOGD(TAG, "Stopping timer");
|
||||
xTimerStop(NM.state_timer, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
|
||||
ip_event_got_ip_t* s = NULL;
|
||||
esp_netif_ip_info_t* ip_info = NULL;
|
||||
|
||||
if (event_base != IP_EVENT)
|
||||
return;
|
||||
switch (event_id) {
|
||||
case IP_EVENT_ETH_GOT_IP:
|
||||
case IP_EVENT_STA_GOT_IP:
|
||||
s = (ip_event_got_ip_t*)event_data;
|
||||
ip_info = &s->ip_info;
|
||||
ESP_LOGI(TAG, "Got an IP address from interface %s. IP=" IPSTR ", Gateway=" IPSTR ", NetMask=" IPSTR ", %s",
|
||||
event_id == IP_EVENT_ETH_GOT_IP ? "Eth" : event_id == IP_EVENT_STA_GOT_IP ? "Wifi"
|
||||
: "Unknown",
|
||||
IP2STR(&ip_info->ip),
|
||||
IP2STR(&ip_info->gw),
|
||||
IP2STR(&ip_info->netmask),
|
||||
s->ip_changed ? "Address was changed" : "Address unchanged");
|
||||
network_async(event_id == IP_EVENT_ETH_GOT_IP ? EN_ETH_GOT_IP : EN_GOT_IP);
|
||||
break;
|
||||
case IP_EVENT_STA_LOST_IP:
|
||||
ESP_LOGD(TAG, "IP_EVENT_STA_LOST_IP");
|
||||
break;
|
||||
case IP_EVENT_AP_STAIPASSIGNED:
|
||||
ESP_LOGD(TAG, "IP_EVENT_AP_STAIPASSIGNED");
|
||||
break;
|
||||
case IP_EVENT_GOT_IP6:
|
||||
ESP_LOGD(TAG, "IP_EVENT_GOT_IP6");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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_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]) {
|
||||
char* macStr = malloc_init_external(LOCAL_MAC_SIZE);
|
||||
if(macStr){
|
||||
snprintf(macStr, LOCAL_MAC_SIZE, MACSTR, MAC2STR(mac));
|
||||
}
|
||||
return macStr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2017-2019 Tony Pottier
|
||||
#pragma once
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@file network_manager.h
|
||||
@author Tony Pottier
|
||||
@brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
|
||||
|
||||
Contains the freeRTOS task and all necessary support
|
||||
|
||||
@see https://idyl.io
|
||||
@see https://github.com/tonyp7/esp32-wifi-manager
|
||||
*/
|
||||
|
||||
#ifndef WIFI_MANAGER_H_INCLUDED
|
||||
#define WIFI_MANAGER_H_INCLUDED
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wifi_types.h"
|
||||
@@ -43,8 +7,192 @@ extern "C" {
|
||||
#include "cJSON.h"
|
||||
#include "esp_eth.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "state_machine.h"
|
||||
#include "state_machine.h"
|
||||
#include "hsm.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define STA_POLLING_MIN (15 * 1000)
|
||||
#define STA_POLLING_MAX (10 * 60 * 1000)
|
||||
#define ETH_LINK_DOWN_REBOOT (2 * 1000)
|
||||
#define ETH_DHCP_FAIL (6 * 1000)
|
||||
#define WIFI_DHCP_FAIL (6 * 1000)
|
||||
|
||||
/*
|
||||
* --------------------- ENUMERATION ---------------------
|
||||
*/
|
||||
//#define ADD_ROOT(NAME, HANDLER, ENTRY, EXIT, CHILD)
|
||||
//#define ADD_ROOT(NAME, HANDLER, ENTRY, EXIT, CHILD)
|
||||
//#define ADD_LEAF(NAME, HANDLER, ENTRY, EXIT, PARENT, LEVEL)
|
||||
|
||||
#define ALL_NM_STATE \
|
||||
ADD_ROOT_LEAF(NETWORK_INSTANTIATED_STATE)\
|
||||
ADD_ROOT_LEAF(NETWORK_INITIALIZING_STATE)\
|
||||
ADD_ROOT(NETWORK_ETH_ACTIVE_STATE, Eth_Active_State)\
|
||||
ADD_ROOT(NETWORK_WIFI_ACTIVE_STATE, Wifi_Active_State)\
|
||||
ADD_ROOT(NETWORK_WIFI_CONFIGURING_ACTIVE_STATE, Wifi_Configuring_State)
|
||||
|
||||
#define ALL_ETH_STATE(PARENT, LEVEL)\
|
||||
ADD_LEAF(ETH_STARTING_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(ETH_ACTIVE_LINKUP_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(ETH_ACTIVE_LINKDOWN_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(ETH_ACTIVE_CONNECTED_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(ETH_CONNECTING_NEW_STATE,PARENT,LEVEL)
|
||||
|
||||
#define ALL_WIFI_STATE(PARENT, LEVEL)\
|
||||
ADD_LEAF(WIFI_INITIALIZING_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_CONNECTING_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_CONNECTING_NEW_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_CONNECTING_NEW_FAILED_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_CONNECTED_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_USER_DISCONNECTED_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_LOST_CONNECTION_STATE,PARENT,LEVEL)
|
||||
|
||||
#define ALL_WIFI_CONFIGURING_STATE(PARENT, LEVEL)\
|
||||
ADD_LEAF(WIFI_CONFIGURING_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_CONFIGURING_CONNECT_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_CONFIGURING_CONNECT_SUCCESS_STATE,PARENT,LEVEL)\
|
||||
ADD_LEAF(WIFI_CONFIGURING_CONNECT_SUCCESS_GOTOSTA_STATE,PARENT,LEVEL)
|
||||
|
||||
|
||||
#define ADD_ROOT(name, ...) name,
|
||||
#define ADD_ROOT_LEAF(name, ...) name,
|
||||
#define ADD_LEAF(name, ...) name,
|
||||
typedef enum {
|
||||
ALL_NM_STATE
|
||||
TOTAL_NM_STATE
|
||||
} nm_state_t;
|
||||
typedef enum {
|
||||
ALL_WIFI_STATE(,)
|
||||
TOTAL_WIFI_ACTIVE_STATE
|
||||
} mn_wifi_active_state_t;
|
||||
typedef enum {
|
||||
ALL_ETH_STATE(,)
|
||||
TOTAL_ETH_ACTIVE_STATE
|
||||
} mn_eth_active_state_t;
|
||||
typedef enum {
|
||||
ALL_WIFI_CONFIGURING_STATE(,)
|
||||
TOTAL_WIFI_CONFIGURING_STATE
|
||||
} mn_wifi_configuring_state_t;
|
||||
|
||||
#undef ADD_STATE
|
||||
#undef ADD_ROOT
|
||||
#undef ADD_ROOT_LEAF
|
||||
#undef ADD_LEAF
|
||||
|
||||
typedef void (*network_status_reached_cb)(nm_state_t state_id, int sub_state );
|
||||
//! List of oven events
|
||||
#define ALL_NM_EVENTS \
|
||||
ADD_FIRST_EVENT(EN_LINK_UP) \
|
||||
ADD_EVENT(EN_LINK_DOWN)\
|
||||
ADD_EVENT(EN_CONFIGURE)\
|
||||
ADD_EVENT(EN_GOT_IP)\
|
||||
ADD_EVENT(EN_ETH_GOT_IP)\
|
||||
ADD_EVENT(EN_DELETE)\
|
||||
ADD_EVENT(EN_TIMER)\
|
||||
ADD_EVENT(EN_START)\
|
||||
ADD_EVENT(EN_SCAN)\
|
||||
ADD_EVENT(EN_FAIL)\
|
||||
ADD_EVENT(EN_SUCCESS)\
|
||||
ADD_EVENT(EN_SCAN_DONE)\
|
||||
ADD_EVENT(EN_CONNECT)\
|
||||
ADD_EVENT(EN_CONNECT_NEW)\
|
||||
ADD_EVENT(EN_REBOOT)\
|
||||
ADD_EVENT(EN_REBOOT_URL)\
|
||||
ADD_EVENT(EN_LOST_CONNECTION)\
|
||||
ADD_EVENT(EN_ETHERNET_FALLBACK)\
|
||||
ADD_EVENT(EN_UPDATE_STATUS)\
|
||||
ADD_EVENT(EN_CONNECTED)
|
||||
#define ADD_EVENT(name) name,
|
||||
#define ADD_FIRST_EVENT(name) name=1,
|
||||
typedef enum {
|
||||
ALL_NM_EVENTS
|
||||
} network_event_t;
|
||||
#undef ADD_EVENT
|
||||
#undef ADD_FIRST_EVENT
|
||||
|
||||
typedef enum {
|
||||
OTA,
|
||||
RECOVERY,
|
||||
RESTART,
|
||||
} reboot_type_t;
|
||||
|
||||
typedef struct {
|
||||
network_event_t trigger;
|
||||
char * ssid;
|
||||
char * password;
|
||||
reboot_type_t rtype;
|
||||
char* strval;
|
||||
wifi_event_sta_disconnected_t* disconnected_event;
|
||||
esp_netif_t *netif;
|
||||
} queue_message;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
state_machine_t Machine; //!< Abstract state machine
|
||||
const state_t* source_state;
|
||||
bool ethernet_connected;
|
||||
TimerHandle_t state_timer;
|
||||
uint32_t STA_duration;
|
||||
int32_t total_connected_time;
|
||||
int64_t last_connected;
|
||||
uint16_t num_disconnect;
|
||||
uint16_t retries;
|
||||
bool wifi_connected;
|
||||
esp_netif_t *wifi_netif;
|
||||
esp_netif_t *eth_netif;
|
||||
esp_netif_t *wifi_ap_netif;
|
||||
queue_message * event_parameters;
|
||||
} network_t;
|
||||
|
||||
|
||||
/*
|
||||
* --------------------- External function prototype ---------------------
|
||||
*/
|
||||
|
||||
void network_start();
|
||||
network_t * network_get_state_machine();
|
||||
void network_event_simple(network_event_t trigger);
|
||||
void network_event(network_event_t trigger, void* param);
|
||||
void network_async_event(network_event_t trigger, void* param);
|
||||
void network_async(network_event_t trigger);
|
||||
void network_async_fail();
|
||||
void network_async_success();
|
||||
void network_async_link_up();
|
||||
void network_async_link_down();
|
||||
void network_async_configure();
|
||||
void network_async_got_ip();
|
||||
void network_async_timer();
|
||||
void network_async_start();
|
||||
void network_async_scan();
|
||||
void network_async_scan_done();
|
||||
void network_async_connect(const char * ssid, const char * password);
|
||||
void network_async_lost_connection(wifi_event_sta_disconnected_t * disconnected_event);
|
||||
void network_async_reboot(reboot_type_t rtype);
|
||||
void network_reboot_ota(char* url);
|
||||
void network_async_delete();
|
||||
void network_async_update_status();
|
||||
void network_async_eth_got_ip();
|
||||
void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
|
||||
bool network_is_interface_connected(esp_netif_t * interface);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* --------------------- Inline functions ---------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Defines the maximum size of a SSID name. 32 is IEEE standard.
|
||||
* @warning limit is also hard coded in wifi_config_t. Never extend this value.
|
||||
@@ -149,96 +297,23 @@ extern "C" {
|
||||
*/
|
||||
#define DEFAULT_STA_POWER_SAVE WIFI_PS_MIN_MODEM
|
||||
|
||||
/**
|
||||
* @brief Defines the maximum length in bytes of a JSON representation of an access point.
|
||||
*
|
||||
* maximum ap string length with full 32 char ssid: 75 + \\n + \0 = 77\n
|
||||
* example: {"ssid":"abcdefghijklmnopqrstuvwxyz012345","chan":12,"rssi":-100,"auth":4},\n
|
||||
* BUT: we need to escape JSON. Imagine a ssid full of \" ? so it's 32 more bytes hence 77 + 32 = 99.\n
|
||||
* this is an edge case but I don't think we should crash in a catastrophic manner just because
|
||||
* someone decided to have a funny wifi name.
|
||||
*/
|
||||
#define JSON_ONE_APP_SIZE 99
|
||||
|
||||
/**
|
||||
* @brief Defines the complete list of all messages that the wifi_manager can process.
|
||||
*
|
||||
* Some of these message are events ("EVENT"), and some of them are action ("ORDER")
|
||||
* Each of these messages can trigger a callback function and each callback function is stored
|
||||
* in a function pointer array for convenience. Because of this behavior, it is extremely important
|
||||
* to maintain a strict sequence and the top level special element 'MESSAGE_CODE_COUNT'
|
||||
*
|
||||
* @see wifi_manager_set_callback
|
||||
*/
|
||||
typedef enum message_code_t {
|
||||
NONE = 0,
|
||||
ORDER_START_HTTP_SERVER = 1,
|
||||
ORDER_STOP_HTTP_SERVER = 2,
|
||||
ORDER_START_DNS_SERVICE = 3,
|
||||
ORDER_STOP_DNS_SERVICE = 4,
|
||||
ORDER_START_WIFI_SCAN = 5,
|
||||
ORDER_LOAD_AND_RESTORE_STA = 6,
|
||||
ORDER_CONNECT_STA = 7,
|
||||
ORDER_DISCONNECT_STA = 8,
|
||||
ORDER_START_AP = 9,
|
||||
ORDER_START_HTTP = 10,
|
||||
ORDER_START_DNS_HIJACK = 11,
|
||||
EVENT_STA_DISCONNECTED = 12,
|
||||
EVENT_SCAN_DONE = 13,
|
||||
EVENT_GOT_IP = 14,
|
||||
ORDER_RESTART_OTA = 15,
|
||||
ORDER_RESTART_RECOVERY = 16,
|
||||
ORDER_RESTART_OTA_URL = 17,
|
||||
ORDER_RESTART = 18,
|
||||
ORDER_UPDATE_STATUS = 19,
|
||||
EVENT_ETH_GOT_IP = 20,
|
||||
EVENT_ETH_TIMEOUT = 21,
|
||||
EVENT_ETH_LINK_UP = 22,
|
||||
EVENT_ETH_LINK_DOWN = 23,
|
||||
MESSAGE_CODE_COUNT = 24 /* important for the callback array */
|
||||
}message_code_t;
|
||||
|
||||
|
||||
|
||||
/* @brief indicate that the ESP32 is currently connected. */
|
||||
extern const int WIFI_MANAGER_WIFI_CONNECTED_BIT;
|
||||
|
||||
extern const int WIFI_MANAGER_AP_STA_CONNECTED_BIT;
|
||||
|
||||
/* @brief Set automatically once the SoftAP is started */
|
||||
extern const int WIFI_MANAGER_AP_STARTED_BIT;
|
||||
|
||||
/* @brief When set, means a client requested to connect to an access point.*/
|
||||
extern const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT;
|
||||
|
||||
/* @brief This bit is set automatically as soon as a connection was lost */
|
||||
extern const int WIFI_MANAGER_STA_DISCONNECT_BIT ;
|
||||
|
||||
/* @brief When set, means the wifi manager attempts to restore a previously saved connection at startup. */
|
||||
extern const int WIFI_MANAGER_REQUEST_RESTORE_STA_BIT ;
|
||||
|
||||
/* @brief When set, means a client requested to disconnect from currently connected AP. */
|
||||
extern const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT ;
|
||||
|
||||
/* @brief When set, means a scan is in progress */
|
||||
extern const int WIFI_MANAGER_SCAN_BIT ;
|
||||
|
||||
/* @brief When set, means user requested for a disconnect */
|
||||
extern const int WIFI_MANAGER_REQUEST_DISCONNECT_BIT ;
|
||||
|
||||
/* @brief When set, means user requested connecting to a new network and it failed */
|
||||
extern const int WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT ;
|
||||
|
||||
void network_manager_reboot_ota(char * url);
|
||||
void network_reboot_ota(char * url);
|
||||
|
||||
|
||||
/**
|
||||
* @brief simplified reason codes for a lost connection.
|
||||
*
|
||||
* esp-idf maintains a big list of reason codes which in practice are useless for most typical application.
|
||||
* UPDATE_CONNECTION_OK - Web UI expects this when attempting to connect to a new access point succeeds
|
||||
* UPDATE_FAILED_ATTEMPT - Web UI expects this when attempting to connect to a new access point fails
|
||||
* UPDATE_USER_DISCONNECT = 2,
|
||||
* UPDATE_LOST_CONNECTION = 3,
|
||||
* 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,
|
||||
UPDATE_CONNECTION_OK = 0, // expected when
|
||||
UPDATE_FAILED_ATTEMPT = 1,
|
||||
UPDATE_USER_DISCONNECT = 2,
|
||||
UPDATE_LOST_CONNECTION = 3,
|
||||
@@ -247,33 +322,6 @@ typedef enum update_reason_code_t {
|
||||
|
||||
}update_reason_code_t;
|
||||
|
||||
typedef enum connection_request_made_by_code_t{
|
||||
CONNECTION_REQUEST_NONE = 0,
|
||||
CONNECTION_REQUEST_USER = 1,
|
||||
CONNECTION_REQUEST_AUTO_RECONNECT = 2,
|
||||
CONNECTION_REQUEST_RESTORE_CONNECTION = 3,
|
||||
CONNECTION_REQUEST_MAX_FAILED = 4,
|
||||
CONNECTION_REQUEST_MAX = 0x7fffffff /*force the creation of this enum as a 32 bit int */
|
||||
}connection_request_made_by_code_t;
|
||||
|
||||
/**
|
||||
* The wifi manager settings in use
|
||||
*/
|
||||
//struct wifi_settings_t{
|
||||
// bool sta_only;
|
||||
// bool sta_static_ip;
|
||||
// wifi_ps_type_t sta_power_save;
|
||||
// tcpip_adapter_ip_info_t sta_static_ip_config;
|
||||
//};
|
||||
//extern struct wifi_settings_t wifi_settings;
|
||||
|
||||
// /**
|
||||
// * @brief Structure used to store one message in the queue.
|
||||
// */
|
||||
// typedef struct{
|
||||
// message_code_t code;
|
||||
// void *param;
|
||||
// } queue_message;
|
||||
|
||||
|
||||
|
||||
@@ -284,59 +332,95 @@ typedef enum connection_request_made_by_code_t{
|
||||
/**
|
||||
* Frees up all memory allocated by the wifi_manager and kill the task.
|
||||
*/
|
||||
void network_manager_destroy();
|
||||
void network_destroy();
|
||||
|
||||
/**
|
||||
* Filters the AP scan list to unique SSIDs
|
||||
*/
|
||||
void filter_unique( wifi_ap_record_t * aplist, uint16_t * ap_num);
|
||||
|
||||
/**
|
||||
* Main task for the wifi_manager
|
||||
*/
|
||||
void network_manager( void * pvParameters );
|
||||
|
||||
|
||||
char* wifi_manager_alloc_get_ap_list_json();
|
||||
cJSON * wifi_manager_clear_ap_list_json(cJSON **old);
|
||||
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
|
||||
*/
|
||||
esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event);
|
||||
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 wifi_manager_lock_json_buffer call is successful.
|
||||
* @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
|
||||
*/
|
||||
cJSON * wifi_manager_clear_ip_info_json(cJSON **old);
|
||||
cJSON * wifi_manager_get_new_json(cJSON **old);
|
||||
cJSON * network_status_clear_ip_info_json(cJSON **old);
|
||||
cJSON * network_status_get_new_json(cJSON **old);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start the mDNS service
|
||||
*/
|
||||
void wifi_manager_initialise_mdns();
|
||||
void network_manager_initialise_mdns();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Register a callback to a custom function when specific event message_code happens.
|
||||
* @brief Register a callback to a custom function when specific network manager states are reached.
|
||||
*/
|
||||
void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) );
|
||||
esp_err_t network_register_state_callback(nm_state_t state, int sub_state, const char* from, network_status_reached_cb cb);
|
||||
bool network_is_wifi_prioritized();
|
||||
esp_netif_t * network_get_active_interface();
|
||||
esp_err_t network_get_hostname( const char **hostname);
|
||||
esp_err_t network_get_ip_info(tcpip_adapter_ip_info_t* ipInfo);
|
||||
void network_set_timer(uint16_t duration);
|
||||
void network_set_hostname(esp_netif_t * netif);
|
||||
esp_err_t network_get_ip_info_for_netif(esp_netif_t* netif, tcpip_adapter_ip_info_t* ipInfo);
|
||||
void network_start_stop_dhcp(esp_netif_t* netif, bool start);
|
||||
void network_start_stop_dhcps(esp_netif_t* netif, bool start);
|
||||
void network_prioritize_wifi(bool activate);
|
||||
#define ADD_ROOT_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name)
|
||||
#define ADD_ROOT_LEAF_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name)
|
||||
#define ADD_LEAF_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name)
|
||||
#define ADD_STATE_FORWARD_DECLARATION_(name) \
|
||||
static state_machine_result_t name##_handler(state_machine_t* const State_Machine); \
|
||||
static state_machine_result_t name##_entry_handler(state_machine_t* const State_Machine); \
|
||||
static state_machine_result_t name##_exit_handler(state_machine_t* const State_Machine);
|
||||
|
||||
void initialize_network_handlers(state_machine_t* state_machine);
|
||||
void network_manager_format_from_to_states(esp_log_level_t level, const char* prefix, state_t const * from_state, state_t const* current_state, network_event_t event,bool show_source, const char * caller );
|
||||
void network_manager_format_state_machine(esp_log_level_t level, const char* prefix, state_machine_t * state_machine, bool show_source, const char * caller) ;
|
||||
char* network_manager_alloc_get_mac_string(uint8_t mac[6]);
|
||||
|
||||
bool network_manager_is_flag_set(EventBits_t bit);
|
||||
void network_manager_set_flag(EventBits_t bit);
|
||||
void network_manager_clear_flag(EventBits_t bit);
|
||||
#if defined(LOG_LOCAL_LEVEL) && LOG_LOCAL_LEVEL >=ESP_LOG_VERBOSE
|
||||
#define NETWORK_PRINT_TRANSITION(begin, prefix, source,target, event, print_source,caller ) network_manager_format_from_to_states(ESP_LOG_VERBOSE, prefix, source,target, event, print_source,caller )
|
||||
#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix,state_machine,print_from,caller) network_manager_format_state_machine(ESP_LOG_DEBUG,cb_prefix,state_machine,print_from,caller)
|
||||
#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,__FUNCTION__);
|
||||
#define network_handler_entry_print(State_Machine, begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"ENTRY START":"ENTRY END",State_Machine,false,__FUNCTION__)
|
||||
#define network_exit_handler_print(State_Machine, begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"EXIT START":"END END",State_Machine,false,__FUNCTION__)
|
||||
#define network_handler_print(State_Machine, begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"HANDLER START":"HANDLER END",State_Machine,false,__FUNCTION__)
|
||||
|
||||
#elif defined(LOG_LOCAL_LEVEL) && LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG
|
||||
#define network_handler_entry_print(State_Machine, begin) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"BEGIN ENTRY":"END ENTRY",State_Machine,false,__FUNCTION__)
|
||||
#define network_exit_handler_print(State_Machine, begin) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"BEGIN EXIT":"END EXIT",State_Machine,false,__FUNCTION__)
|
||||
#define network_handler_print(State_Machine, begin) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"HANDLER START":"HANDLER END",State_Machine,false,__FUNCTION__)
|
||||
|
||||
#define NETWORK_PRINT_TRANSITION(begin, prefix, source,target, event, print_source,caller ) if(begin) network_manager_format_from_to_states(ESP_LOG_DEBUG, prefix, source,target, event, print_source,caller )#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,__FUNCTION__);
|
||||
#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix,state_machine,print_from,caller) if(begin) network_manager_format_state_machine(ESP_LOG_DEBUG,cb_prefix,state_machine,print_from,caller)
|
||||
#else
|
||||
#define network_exit_handler_print(nm, begin)
|
||||
#define network_handler_entry_print(State_Machine, begin)
|
||||
#define network_handler_print(State_Machine, begin)
|
||||
#define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,NULL)
|
||||
#define NETWORK_PRINT_TRANSITION(prefix, source,target, event, print_source,caller )
|
||||
#define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix,state_machine,print_from,caller)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIFI_MANAGER_H_INCLUDED */
|
||||
|
||||
|
||||
1155
components/wifi-manager/network_manager_handlers.c
Normal file
1155
components/wifi-manager/network_manager_handlers.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
#ifdef NETWORK_STATUS_LOG_LEVEL
|
||||
#define LOG_LOCAL_LEVEL NETWORK_STATUS_LOG_LEVEL
|
||||
#endif
|
||||
|
||||
#include "network_status.h"
|
||||
#include <string.h>
|
||||
#include "bt_app_core.h"
|
||||
@@ -16,10 +20,12 @@
|
||||
#define CONFIG_SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
|
||||
#endif
|
||||
static const char TAG[] = "network_status";
|
||||
SemaphoreHandle_t wifi_manager_json_mutex = NULL;
|
||||
SemaphoreHandle_t wifi_manager_sta_ip_mutex = NULL;
|
||||
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* wifi_manager_sta_ip = 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};
|
||||
@@ -33,11 +39,11 @@ void init_network_status() {
|
||||
chained_notify = server_notify;
|
||||
server_notify = connect_notify;
|
||||
ESP_LOGD(TAG, "init_network_status. Creating mutexes");
|
||||
wifi_manager_json_mutex = xSemaphoreCreateMutex();
|
||||
wifi_manager_sta_ip_mutex = xSemaphoreCreateMutex();
|
||||
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 = wifi_manager_clear_ip_info_json(&ip_info_cjson);
|
||||
ip_info_cjson = network_status_clear_ip_info_json(&ip_info_cjson);
|
||||
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) {
|
||||
@@ -46,57 +52,73 @@ void init_network_status() {
|
||||
ESP_LOGD(TAG, "Found release url %s", release_url);
|
||||
}
|
||||
ESP_LOGD(TAG, "About to set the STA IP String to 0.0.0.0");
|
||||
wifi_manager_sta_ip = (char*)malloc(STA_IP_LEN);
|
||||
wifi_manager_safe_update_sta_ip_string(NULL);
|
||||
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(wifi_manager_sta_ip);
|
||||
FREE_AND_NULL(network_status_ip_address);
|
||||
cJSON_Delete(ip_info_cjson);
|
||||
vSemaphoreDelete(wifi_manager_json_mutex);
|
||||
wifi_manager_json_mutex = NULL;
|
||||
vSemaphoreDelete(wifi_manager_sta_ip_mutex);
|
||||
wifi_manager_sta_ip_mutex = NULL;
|
||||
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* wifi_manager_get_new_json(cJSON** old) {
|
||||
ESP_LOGV(TAG, "wifi_manager_get_new_json called");
|
||||
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, "wifi_manager_get_new_json done");
|
||||
ESP_LOGV(TAG, "network_status_get_new_json done");
|
||||
return cJSON_CreateObject();
|
||||
}
|
||||
|
||||
cJSON* wifi_manager_clear_ip_info_json(cJSON** old) {
|
||||
ESP_LOGV(TAG, "wifi_manager_clear_ip_info_json called");
|
||||
cJSON* root = wifi_manager_get_basic_info(old);
|
||||
ESP_LOGV(TAG, "wifi_manager_clear_ip_info_json done");
|
||||
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 (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
|
||||
ip_info_cjson = wifi_manager_clear_ip_info_json(&ip_info_cjson);
|
||||
wifi_manager_unlock_json_buffer();
|
||||
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* wifi_manager_alloc_get_ip_info_json() {
|
||||
char* network_status_alloc_get_ip_info_json() {
|
||||
return cJSON_PrintUnformatted(ip_info_cjson);
|
||||
}
|
||||
|
||||
void wifi_manager_unlock_json_buffer() {
|
||||
void network_status_unlock_json_buffer() {
|
||||
ESP_LOGV(TAG, "Unlocking json buffer!");
|
||||
xSemaphoreGive(wifi_manager_json_mutex);
|
||||
network_json_locked_task = NULL;
|
||||
xSemaphoreGive(network_status_json_mutex);
|
||||
}
|
||||
|
||||
bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait) {
|
||||
bool network_status_lock_json_buffer(TickType_t xTicksToWait) {
|
||||
ESP_LOGV(TAG, "Locking json buffer");
|
||||
if (wifi_manager_json_mutex) {
|
||||
if (xSemaphoreTake(wifi_manager_json_mutex, xTicksToWait) == pdTRUE) {
|
||||
|
||||
TaskHandle_t calling_task = xTaskGetCurrentTaskHandle();
|
||||
if (calling_task == network_json_locked_task) {
|
||||
ESP_LOGV(TAG, "json 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;
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Semaphore take failed. Unable to lock json buffer mutex");
|
||||
@@ -108,9 +130,15 @@ bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait) {
|
||||
}
|
||||
}
|
||||
|
||||
bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait) {
|
||||
if (wifi_manager_sta_ip_mutex) {
|
||||
if (xSemaphoreTake(wifi_manager_sta_ip_mutex, xTicksToWait) == pdTRUE) {
|
||||
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;
|
||||
@@ -120,26 +148,27 @@ bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait) {
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_manager_unlock_sta_ip_string() {
|
||||
xSemaphoreGive(wifi_manager_sta_ip_mutex);
|
||||
void network_status_unlock_sta_ip_string() {
|
||||
network_status_ip_address_locked_task = NULL;
|
||||
xSemaphoreGive(network_status_ip_address_mutex);
|
||||
}
|
||||
|
||||
void wifi_manager_safe_update_sta_ip_string(esp_ip4_addr_t* ip4) {
|
||||
if (wifi_manager_lock_sta_ip_string(portMAX_DELAY)) {
|
||||
strcpy(wifi_manager_sta_ip, ip4 != NULL ? ip4addr_ntoa(ip4) : "0.0.0.0");
|
||||
ESP_LOGD(TAG, "Set STA IP String to: %s", wifi_manager_sta_ip);
|
||||
wifi_manager_unlock_sta_ip_string();
|
||||
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 wifi_manager_safe_reset_sta_ip_string() {
|
||||
if (wifi_manager_lock_sta_ip_string(portMAX_DELAY)) {
|
||||
strcpy(wifi_manager_sta_ip, "0.0.0.0");
|
||||
ESP_LOGD(TAG, "Set STA IP String to: %s", wifi_manager_sta_ip);
|
||||
wifi_manager_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* wifi_manager_get_sta_ip_string() {
|
||||
return wifi_manager_sta_ip;
|
||||
char* network_status_get_sta_ip_string() {
|
||||
return network_status_ip_address;
|
||||
}
|
||||
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));
|
||||
@@ -152,98 +181,47 @@ static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) {
|
||||
set_lms_server_details(ip, hport, cport);
|
||||
if (chained_notify)
|
||||
(*chained_notify)(ip, hport, cport);
|
||||
network_manager_async_update_status();
|
||||
network_async_update_status();
|
||||
}
|
||||
void wifi_manager_update_basic_info() {
|
||||
int32_t total_connected_time = 0;
|
||||
int64_t last_connected = 0;
|
||||
uint16_t num_disconnect = 0;
|
||||
network_wifi_get_stats(&total_connected_time, &last_connected, &num_disconnect);
|
||||
if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
|
||||
monitor_gpio_t* mgpio = get_jack_insertion_gpio();
|
||||
|
||||
cJSON* voltage = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "Voltage");
|
||||
if (voltage) {
|
||||
cJSON_SetNumberValue(voltage, battery_value_svc());
|
||||
}
|
||||
cJSON* bt_status = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "bt_status");
|
||||
if (bt_status) {
|
||||
cJSON_SetNumberValue(bt_status, bt_app_source_get_a2d_state());
|
||||
}
|
||||
cJSON* bt_sub_status = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "bt_sub_status");
|
||||
if (bt_sub_status) {
|
||||
cJSON_SetNumberValue(bt_sub_status, bt_app_source_get_media_state());
|
||||
}
|
||||
cJSON* jack = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "Jack");
|
||||
if (jack) {
|
||||
jack->type = mgpio->gpio >= 0 && jack_inserted_svc() ? cJSON_True : cJSON_False;
|
||||
}
|
||||
cJSON* disconnect_count = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "disconnect_count");
|
||||
if (disconnect_count) {
|
||||
cJSON_SetNumberValue(disconnect_count, num_disconnect);
|
||||
}
|
||||
cJSON* avg_conn_time = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "avg_conn_time");
|
||||
if (avg_conn_time) {
|
||||
cJSON_SetNumberValue(avg_conn_time, num_disconnect > 0 ? (total_connected_time / num_disconnect) : 0);
|
||||
}
|
||||
if (lms_server_cport > 0) {
|
||||
cJSON* value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_cport");
|
||||
if (value) {
|
||||
cJSON_SetNumberValue(value, lms_server_cport);
|
||||
} else {
|
||||
cJSON_AddNumberToObject(ip_info_cjson, "lms_cport", lms_server_cport);
|
||||
}
|
||||
}
|
||||
|
||||
if (lms_server_port > 0) {
|
||||
cJSON* value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_port");
|
||||
if (value) {
|
||||
cJSON_SetNumberValue(value, lms_server_port);
|
||||
} else {
|
||||
cJSON_AddNumberToObject(ip_info_cjson, "lms_port", lms_server_port);
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(lms_server_ip) > 0) {
|
||||
cJSON* value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_ip");
|
||||
if (!value) {
|
||||
// only create if it does not exist. Since we're creating a reference
|
||||
// to a char buffer, updates to cJSON aren't needed
|
||||
cJSON_AddItemToObject(ip_info_cjson, "lms_ip", cJSON_CreateStringReference(lms_server_ip));
|
||||
}
|
||||
}
|
||||
if (network_ethernet_enabled()) {
|
||||
cJSON* eth = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "eth_up");
|
||||
if (eth) {
|
||||
eth->type = network_ethernet_is_up() ? cJSON_True : cJSON_False;
|
||||
}
|
||||
}
|
||||
wifi_manager_unlock_json_buffer();
|
||||
}
|
||||
void network_status_update_basic_info() {
|
||||
// locking happens below this level
|
||||
network_status_get_basic_info(&ip_info_cjson);
|
||||
}
|
||||
cJSON* network_status_update_string(cJSON** root, const char* key, const char* value) {
|
||||
if (*root == NULL) {
|
||||
*root = cJSON_CreateObject();
|
||||
}
|
||||
if (network_status_lock_json_buffer(portMAX_DELAY)) {
|
||||
if (*root == NULL) {
|
||||
*root = cJSON_CreateObject();
|
||||
if (*root == NULL) {
|
||||
ESP_LOGE(TAG, "Error creating cJSON object!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!key || !value || strlen(key) == 0)
|
||||
return *root;
|
||||
cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
|
||||
if (cjsonvalue && strcasecmp(cJSON_GetStringValue(cjsonvalue), value) != 0) {
|
||||
ESP_LOGD(TAG, "Value %s changed from %s to %s", key, cJSON_GetStringValue(cjsonvalue), value);
|
||||
cJSON_SetValuestring(cjsonvalue, value);
|
||||
if (!key || !value || strlen(key) == 0) {
|
||||
ESP_LOGE(TAG, "network_status_update_string. Invalid key or value passed! key: %s, value: %s", STR_OR_ALT(key, ""), STR_OR_ALT(value, ""));
|
||||
network_status_unlock_json_buffer();
|
||||
return *root;
|
||||
}
|
||||
cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
|
||||
if (cjsonvalue && strcasecmp(cJSON_GetStringValue(cjsonvalue), value) != 0) {
|
||||
ESP_LOGD(TAG, "Value %s changed from %s to %s", key, cJSON_GetStringValue(cjsonvalue), value);
|
||||
cJSON_SetValuestring(cjsonvalue, value);
|
||||
} else {
|
||||
cJSON_AddItemToObject(*root, key, cJSON_CreateString(value));
|
||||
}
|
||||
network_status_unlock_json_buffer();
|
||||
} else {
|
||||
cJSON_AddItemToObject(*root, key, cJSON_CreateString(value));
|
||||
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
|
||||
}
|
||||
return *root;
|
||||
}
|
||||
cJSON* network_status_update_number(cJSON** root, const char* key, int value) {
|
||||
if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
|
||||
if (network_status_lock_json_buffer(portMAX_DELAY)) {
|
||||
if (*root == NULL) {
|
||||
*root = cJSON_CreateObject();
|
||||
}
|
||||
|
||||
if (key && value && strlen(key) != 0) {
|
||||
if (key && strlen(key) != 0) {
|
||||
cJSON* cjsonvalue = cJSON_GetObjectItemCaseSensitive(*root, key);
|
||||
if (cjsonvalue) {
|
||||
cJSON_SetNumberValue(cjsonvalue, value);
|
||||
@@ -251,14 +229,14 @@ cJSON* network_status_update_number(cJSON** root, const char* key, int value) {
|
||||
cJSON_AddNumberToObject(*root, key, value);
|
||||
}
|
||||
}
|
||||
wifi_manager_unlock_json_buffer();
|
||||
network_status_unlock_json_buffer();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
|
||||
}
|
||||
return *root;
|
||||
}
|
||||
cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
|
||||
if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
|
||||
if (network_status_lock_json_buffer(portMAX_DELAY)) {
|
||||
if (*root == NULL) {
|
||||
*root = cJSON_CreateObject();
|
||||
}
|
||||
@@ -271,14 +249,14 @@ cJSON* network_status_update_float(cJSON** root, const char* key, float value) {
|
||||
cJSON_AddNumberToObject(*root, key, value);
|
||||
}
|
||||
}
|
||||
wifi_manager_unlock_json_buffer();
|
||||
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 (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
|
||||
if (network_status_lock_json_buffer(portMAX_DELAY)) {
|
||||
if (*root == NULL) {
|
||||
*root = cJSON_CreateObject();
|
||||
}
|
||||
@@ -291,91 +269,110 @@ cJSON* network_status_update_bool(cJSON** root, const char* key, bool value) {
|
||||
cJSON_AddBoolToObject(*root, key, value);
|
||||
}
|
||||
}
|
||||
wifi_manager_unlock_json_buffer();
|
||||
network_status_unlock_json_buffer();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
|
||||
}
|
||||
return *root;
|
||||
}
|
||||
cJSON* wifi_manager_get_basic_info(cJSON** old) {
|
||||
int32_t total_connected_time = 0;
|
||||
int64_t last_connected = 0;
|
||||
uint16_t num_disconnect = 0;
|
||||
network_wifi_get_stats(&total_connected_time, &last_connected, &num_disconnect);
|
||||
cJSON* network_status_get_basic_info(cJSON** old) {
|
||||
if (network_status_lock_json_buffer(portMAX_DELAY)) {
|
||||
network_t* nm = network_get_state_machine();
|
||||
monitor_gpio_t* mgpio = get_jack_insertion_gpio();
|
||||
const esp_app_desc_t* desc = esp_ota_get_app_description();
|
||||
|
||||
monitor_gpio_t* mgpio = get_jack_insertion_gpio();
|
||||
const esp_app_desc_t* desc = esp_ota_get_app_description();
|
||||
ESP_LOGV(TAG, "wifi_manager_get_basic_info called");
|
||||
cJSON* root = network_status_update_string(&root, "project_name", desc->project_name);
|
||||
*old = network_status_update_string(old, "project_name", desc->project_name);
|
||||
#ifdef CONFIG_FW_PLATFORM_NAME
|
||||
root = network_status_update_string(&root, "platform_name", CONFIG_FW_PLATFORM_NAME);
|
||||
*old = network_status_update_string(old, "platform_name", CONFIG_FW_PLATFORM_NAME);
|
||||
#endif
|
||||
root = network_status_update_string(&root, "version", desc->version);
|
||||
if (release_url != NULL)
|
||||
root = network_status_update_string(&root, "release_url", release_url);
|
||||
root = network_status_update_number(&root, "recovery", is_recovery_running ? 1 : 0);
|
||||
root = network_status_update_bool(&root, "Jack", mgpio->gpio >= 0 && jack_inserted_svc());
|
||||
root = network_status_update_float(&root, "Voltage", battery_value_svc());
|
||||
root = network_status_update_number(&root, "disconnect_count", num_disconnect);
|
||||
root = network_status_update_float(&root, "avg_conn_time", num_disconnect > 0 ? (total_connected_time / num_disconnect) : 0);
|
||||
root = network_status_update_number(&root, "bt_status", bt_app_source_get_a2d_state());
|
||||
root = network_status_update_number(&root, "bt_sub_status", bt_app_source_get_media_state());
|
||||
|
||||
*old = network_status_update_string(old, "version", desc->version);
|
||||
if (release_url != NULL)
|
||||
*old = network_status_update_string(old, "release_url", release_url);
|
||||
*old = network_status_update_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_status_update_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);
|
||||
*old = network_status_update_number(old, "bt_status", bt_app_source_get_a2d_state());
|
||||
*old = network_status_update_number(old, "bt_sub_status", bt_app_source_get_media_state());
|
||||
#if CONFIG_I2C_LOCKED
|
||||
root = network_status_update_bool(&root, "is_i2c_locked", true);
|
||||
*old = network_status_update_bool(old, "is_i2c_locked", true);
|
||||
#else
|
||||
root = network_status_update_bool(&root, "is_i2c_locked", false);
|
||||
*old = network_status_update_bool(old, "is_i2c_locked", false);
|
||||
#endif
|
||||
if (network_ethernet_enabled()) {
|
||||
root = network_status_update_bool(&root, "eth_up", network_ethernet_is_up());
|
||||
}
|
||||
ESP_LOGV(TAG, "wifi_manager_get_basic_info done");
|
||||
return root;
|
||||
}
|
||||
if (network_ethernet_enabled()) {
|
||||
*old = network_status_update_bool(old, "eth_up", network_ethernet_is_up());
|
||||
}
|
||||
if (lms_server_cport > 0) {
|
||||
*old = network_status_update_number(old, "lms_cport", lms_server_cport);
|
||||
}
|
||||
|
||||
void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code) {
|
||||
ESP_LOGD(TAG, "wifi_manager_generate_ip_info_json called");
|
||||
if (lms_server_port > 0) {
|
||||
*old = network_status_update_number(old, "lms_port", lms_server_port);
|
||||
}
|
||||
|
||||
if (wifi_manager_lock_json_buffer(portMAX_DELAY)) {
|
||||
/* generate the connection info with success */
|
||||
|
||||
ip_info_cjson = wifi_manager_get_basic_info(&ip_info_cjson);
|
||||
wifi_manager_unlock_json_buffer();
|
||||
if (strlen(lms_server_ip) > 0) {
|
||||
*old = network_status_update_string(old, "lms_ip", lms_server_ip);
|
||||
}
|
||||
ESP_LOGV(TAG, "network_status_get_basic_info done");
|
||||
network_status_unlock_json_buffer();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
|
||||
}
|
||||
ip_info_cjson = network_status_update_number(&ip_info_cjson, "urc", update_reason_code);
|
||||
if (update_reason_code == UPDATE_CONNECTION_OK || update_reason_code == UPDATE_ETHERNET_CONNECTED) {
|
||||
/* rest of the information is copied after the ssid */
|
||||
tcpip_adapter_ip_info_t ip_info;
|
||||
esp_netif_get_ip_info(network_wifi_get_interface(), &ip_info);
|
||||
|
||||
network_status_update_string(&ip_info_cjson, "ip", ip4addr_ntoa((ip4_addr_t*)&ip_info.ip));
|
||||
network_status_update_string(&ip_info_cjson, "netmask", ip4addr_ntoa((ip4_addr_t*)&ip_info.netmask));
|
||||
network_status_update_string(&ip_info_cjson, "gw", ip4addr_ntoa((ip4_addr_t*)&ip_info.gw));
|
||||
wifi_mode_t mode;
|
||||
if (esp_wifi_get_mode(&mode) == ESP_OK && (mode == WIFI_MODE_STA || mode == WIFI_MODE_APSTA)) {
|
||||
/* wifi is active, and associated to an AP */
|
||||
wifi_ap_record_t ap;
|
||||
esp_wifi_sta_get_ap_info(&ap);
|
||||
network_status_update_string(&ip_info_cjson, "ssid", ((char*)ap.ssid));
|
||||
network_status_update_number(&ip_info_cjson, "rssi", ap.rssi);
|
||||
}
|
||||
if (network_ethernet_is_up()) {
|
||||
esp_netif_get_ip_info(network_ethernet_get_interface(), &ip_info);
|
||||
cJSON* ethernet_ip = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(ethernet_ip, "ip", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t*)&ip_info.ip)));
|
||||
cJSON_AddItemToObject(ethernet_ip, "netmask", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t*)&ip_info.netmask)));
|
||||
cJSON_AddItemToObject(ethernet_ip, "gw", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t*)&ip_info.gw)));
|
||||
cJSON_AddItemToObject(ip_info_cjson, "eth", ethernet_ip);
|
||||
}
|
||||
} else {
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "ip");
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "netmask");
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "gw");
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "rssi");
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "ssid");
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "eth");
|
||||
}
|
||||
ESP_LOGV(TAG, "wifi_manager_generate_ip_info_json done");
|
||||
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_status_update_string(&root, "ip", ip4addr_ntoa((ip4_addr_t*)&ip_info->ip));
|
||||
network_status_update_string(&root, "netmask", ip4addr_ntoa((ip4_addr_t*)&ip_info->netmask));
|
||||
network_status_update_string(&root, "gw", ip4addr_ntoa((ip4_addr_t*)&ip_info->gw));
|
||||
}
|
||||
void network_status_update_ip_info(update_reason_code_t 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)) {
|
||||
/* generate the connection info with success */
|
||||
|
||||
ip_info_cjson = network_status_get_basic_info(&ip_info_cjson);
|
||||
ip_info_cjson = network_status_update_number(&ip_info_cjson, "urc", update_reason_code);
|
||||
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())) {
|
||||
|
||||
esp_netif_get_ip_info(network_wifi_get_interface(), &ip_info);
|
||||
network_status_update_address(ip_info_cjson, &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_status_update_string(&ip_info_cjson, "ssid", ((char*)ap.ssid));
|
||||
network_status_update_number(&ip_info_cjson, "rssi", ap.rssi);
|
||||
}
|
||||
|
||||
} else {
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "ip");
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "netmask");
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "gw");
|
||||
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())) {
|
||||
cJSON* ethernet_ip = cJSON_GetObjectItem(ip_info_cjson, "eth");
|
||||
if (!ethernet_ip) {
|
||||
ethernet_ip = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(ip_info_cjson, "eth", ethernet_ip);
|
||||
}
|
||||
esp_netif_get_ip_info(network_ethernet_get_interface(), &ip_info);
|
||||
network_status_update_address(ethernet_ip, &ip_info);
|
||||
} else {
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(ip_info_cjson, "eth");
|
||||
}
|
||||
network_status_unlock_json_buffer();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unable to lock status json buffer. ");
|
||||
}
|
||||
ESP_LOGV(TAG, "wifi_status_generate_ip_info_json done");
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
extern "C" {
|
||||
|
||||
#endif
|
||||
char* wifi_manager_alloc_get_ip_info_json();
|
||||
char* network_status_alloc_get_ip_info_json();
|
||||
/**
|
||||
* @brief Tries to get access to json buffer mutex.
|
||||
*
|
||||
@@ -21,39 +21,39 @@ char* wifi_manager_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 wifi_manager_lock_json_buffer(TickType_t xTicksToWait);
|
||||
bool network_status_lock_json_buffer(TickType_t xTicksToWait);
|
||||
|
||||
/**
|
||||
* @brief Releases the json buffer mutex.
|
||||
*/
|
||||
void wifi_manager_unlock_json_buffer();
|
||||
void network_status_unlock_json_buffer();
|
||||
|
||||
bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait);
|
||||
void wifi_manager_unlock_sta_ip_string();
|
||||
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* wifi_manager_get_sta_ip_string();
|
||||
char* network_status_get_sta_ip_string();
|
||||
|
||||
/**
|
||||
* @brief thread safe char representation of the STA IP update
|
||||
*/
|
||||
void wifi_manager_safe_update_sta_ip_string(esp_ip4_addr_t * ip4);
|
||||
void network_status_safe_update_sta_ip_string(esp_ip4_addr_t * ip4);
|
||||
|
||||
/**
|
||||
* @brief Generates the connection status json: ssid and IP addresses.
|
||||
* @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
|
||||
* @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
|
||||
*/
|
||||
void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code);
|
||||
void network_status_update_ip_info(update_reason_code_t update_reason_code);
|
||||
|
||||
void init_network_status();
|
||||
void destroy_network_status();
|
||||
cJSON* wifi_manager_get_basic_info(cJSON** old);
|
||||
cJSON* network_status_get_basic_info(cJSON** old);
|
||||
|
||||
void wifi_manager_update_basic_info();
|
||||
void network_status_update_basic_info();
|
||||
void network_status_clear_ip();
|
||||
void wifi_manager_safe_reset_sta_ip_string();
|
||||
void network_status_safe_reset_sta_ip_string();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
extern "C" {
|
||||
|
||||
#endif
|
||||
void init_network_wifi();
|
||||
esp_netif_t * network_wifi_start();
|
||||
void destroy_network_wifi();
|
||||
/**
|
||||
* @brief saves the current STA wifi config to flash ram storage.
|
||||
@@ -16,46 +16,59 @@ 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 wifi_manager_fetch_wifi_sta_config();
|
||||
bool network_wifi_load_wifi_sta_config();
|
||||
|
||||
wifi_config_t* wifi_manager_get_wifi_sta_config();
|
||||
|
||||
/**
|
||||
* @brief Registers handler for wifi and ip events
|
||||
*/
|
||||
void wifi_manager_register_handlers();
|
||||
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 wifi_manager_lock_json_buffer call is successful.
|
||||
* @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
|
||||
*/
|
||||
void wifi_manager_generate_access_points_json(cJSON ** ap_list);
|
||||
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 wifi_manager_lock_json_buffer call is successful.
|
||||
* @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
|
||||
*/
|
||||
void wifi_manager_clear_access_points_json();
|
||||
void network_wifi_clear_access_points_json();
|
||||
|
||||
|
||||
void wifi_manager_config_ap();
|
||||
esp_netif_t * network_wifi_config_ap();
|
||||
|
||||
void wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps);
|
||||
esp_err_t wifi_scan_done(queue_message *msg);
|
||||
esp_err_t network_wifi_start_scan(queue_message *msg);
|
||||
void network_wifi_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps);
|
||||
esp_err_t wifi_scan_done();
|
||||
esp_err_t network_wifi_start_scan();
|
||||
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 wifi_manager_load_wifi_sta_config(wifi_config_t* config );
|
||||
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);
|
||||
esp_err_t network_wifi_connect(wifi_config_t * cfg);
|
||||
bool is_wifi_up();
|
||||
wifi_config_t* network_wifi_set_wifi_sta_config(const char * ssid, const char * password) ;
|
||||
void network_wifi_clear_config();
|
||||
esp_netif_t *network_wifi_get_interface();
|
||||
esp_netif_t *network_wifi_get_ap_interface();
|
||||
bool network_wifi_is_ap_sta_mode();
|
||||
bool network_wifi_is_sta_mode();
|
||||
bool network_wifi_is_ap_mode();
|
||||
bool network_wifi_sta_config_changed();
|
||||
void network_wifi_get_stats( int32_t * ret_total_connected_time, int64_t * ret_last_connected, uint16_t * ret_num_disconnect);
|
||||
void network_wifi_global_init();
|
||||
bool network_wifi_is_known_ap(const char * ssid);
|
||||
esp_err_t network_wifi_connect(const char * ssid, const char * password);
|
||||
esp_err_t network_wifi_erase_legacy();
|
||||
esp_err_t network_wifi_connect_ssid(const char * ssid);
|
||||
esp_err_t network_wifi_connect_active_ssid();
|
||||
esp_err_t network_wifi_erase_known_ap();
|
||||
esp_err_t network_wifi_set_sta_mode();
|
||||
size_t network_wifi_get_known_count();
|
||||
esp_err_t network_wifi_built_known_ap_list();
|
||||
|
||||
const wifi_sta_config_t* network_wifi_load_active_config();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 901 B |
@@ -1,793 +0,0 @@
|
||||
#include <state_machine.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "cmd_system.h"
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi_types.h"
|
||||
#include "http_server_handlers.h"
|
||||
#include "messaging.h"
|
||||
#include "network_ethernet.h"
|
||||
#include "network_status.h"
|
||||
#include "network_wifi.h"
|
||||
#include "state_machine.h"
|
||||
#include "trace.h"
|
||||
#include "dns_server.h"
|
||||
BaseType_t network_manager_task;
|
||||
/* objects used to manipulate the main queue of events */
|
||||
QueueHandle_t network_manager_queue;
|
||||
|
||||
using namespace stateless;
|
||||
using namespace std::placeholders;
|
||||
static const char TAG[] = "network_manager";
|
||||
static TaskHandle_t task_network_manager = NULL;
|
||||
TimerHandle_t STA_timer = NULL;
|
||||
uint32_t STA_duration;
|
||||
|
||||
static int32_t total_connected_time = 0;
|
||||
static int64_t last_connected = 0;
|
||||
static uint16_t num_disconnect = 0;
|
||||
void network_wifi_get_stats(int32_t* ret_total_connected_time, int64_t* ret_last_connected, uint16_t* ret_num_disconnect) {
|
||||
*ret_total_connected_time = total_connected_time;
|
||||
*ret_last_connected = last_connected;
|
||||
*ret_num_disconnect = num_disconnect;
|
||||
}
|
||||
namespace {
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const state_t s) {
|
||||
//static const char* name[] = { "idle", "stopped", "started", "running" };
|
||||
static const char* name[] = {
|
||||
|
||||
"initializing",
|
||||
"global",
|
||||
"eth_starting",
|
||||
"eth_active",
|
||||
"eth_active_linkup",
|
||||
"eth_active_connected",
|
||||
"eth_active_linkdown",
|
||||
"wifi_up",
|
||||
"wifi_initializing",
|
||||
"network_manager_async",
|
||||
"wifi_connecting_scanning",
|
||||
"wifi_connecting",
|
||||
"wifi_connected",
|
||||
"wifi_disconnecting",
|
||||
"wifi_user_disconnected",
|
||||
"wifi_connected_waiting_for_ip",
|
||||
"wifi_connected_scanning",
|
||||
"wifi_lost_connection",
|
||||
"wifi_ap_mode",
|
||||
"wifi_ap_mode_scanning",
|
||||
"wifi_ap_mode_scan_done",
|
||||
"wifi_ap_mode_connecting",
|
||||
"wifi_ap_mode_connected",
|
||||
"system_rebooting"};
|
||||
os << name[(int)s];
|
||||
return os;
|
||||
}
|
||||
|
||||
const char* trigger_to_string(trig_t trigger) {
|
||||
switch (trigger) {
|
||||
ENUM_TO_STRING(t_link_up);
|
||||
ENUM_TO_STRING(t_link_down);
|
||||
ENUM_TO_STRING(t_configure);
|
||||
ENUM_TO_STRING(t_got_ip);
|
||||
ENUM_TO_STRING(t_next);
|
||||
ENUM_TO_STRING(t_start);
|
||||
ENUM_TO_STRING(t_scan);
|
||||
ENUM_TO_STRING(t_fail);
|
||||
ENUM_TO_STRING(t_success);
|
||||
ENUM_TO_STRING(t_scan_done);
|
||||
ENUM_TO_STRING(t_connect);
|
||||
ENUM_TO_STRING(t_reboot);
|
||||
ENUM_TO_STRING(t_reboot_url);
|
||||
ENUM_TO_STRING(t_lost_connection);
|
||||
ENUM_TO_STRING(t_update_status);
|
||||
ENUM_TO_STRING(t_disconnect);
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
return "Unknown trigger";
|
||||
}
|
||||
std::ostream& operator<<(std::ostream& os, const trig_t & t) {
|
||||
//static const char* name[] = { "start", "stop", "set_speed", "halt" };
|
||||
os << trigger_to_string(t);
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// namespace stateless
|
||||
// {
|
||||
|
||||
// template<> void print_state<state>(std::ostream& os, const state& s)
|
||||
// { os << s; }
|
||||
|
||||
// template<> void print_trigger<trigger_t_t(std::ostream& os, const trigger& t)
|
||||
// { os << t; }
|
||||
|
||||
// }
|
||||
|
||||
// namespace
|
||||
// {
|
||||
|
||||
// class network_manager
|
||||
// {
|
||||
// public:
|
||||
// network_manager()
|
||||
// : sm_(state_t::initializing)
|
||||
// ,
|
||||
// {
|
||||
|
||||
//}
|
||||
|
||||
// sm_.configure(state_t::idle)
|
||||
// .permit(trig_t::t_start, state_t::started);
|
||||
|
||||
// sm_.configure(state_t::stopped)
|
||||
// .on_entry([=](const TTransition&) { speed_ = 0; })
|
||||
// .permit(trig_t::t_halt, state_t::idle);
|
||||
|
||||
// sm_.configure(state_t::started)
|
||||
// .permit(trig_t::t_set_speed, state_t::running)
|
||||
// .permit(trig_t::t_stop, state_t::stopped);
|
||||
|
||||
// sm_.configure(state_t::running)
|
||||
// .on_entry_from(
|
||||
// set_speed_trigger_,
|
||||
// [=](const TTransition& t, int speed) { speed_ = speed; })
|
||||
// .permit(trig_t::t_stop, state_t::stopped)
|
||||
// .permit_reentry(trig_t::t_set_speed);
|
||||
|
||||
// void start(int speed)
|
||||
// {
|
||||
// sm_.fire(trig_t::t_start);
|
||||
// set_speed(speed);
|
||||
// }
|
||||
|
||||
// void stop()
|
||||
// {
|
||||
// sm_.fire(trig_t::t_stop);
|
||||
// sm_.fire(trig_t::t_halt);
|
||||
// }
|
||||
|
||||
// void set_speed(int speed)
|
||||
// {
|
||||
// sm_.fire(set_speed_trigger_, speed);
|
||||
// }
|
||||
|
||||
// std::string print() const
|
||||
// {
|
||||
// std::ostringstream oss;
|
||||
// print(oss);
|
||||
// return oss.str();
|
||||
// }
|
||||
|
||||
// void print(std::ostream& os) const
|
||||
// {
|
||||
// os << "Motor " << sm_ << " speed = " << speed_;
|
||||
// }
|
||||
|
||||
// private:
|
||||
|
||||
// //typedef std::shared_ptr<stateless::trigger_with_parameters<trigger_t, int>> TSetSpeedTrigger;
|
||||
|
||||
// wifi_config_t * wifi_config;
|
||||
// TStateMachine sm_;
|
||||
// ;
|
||||
// ;
|
||||
// };
|
||||
|
||||
// std::ostream& operator<<(std::ostream& os, const motor& m)
|
||||
// {
|
||||
// m.print(os);
|
||||
// return os;
|
||||
// }
|
||||
|
||||
//}
|
||||
namespace {
|
||||
|
||||
typedef state_machine<state_t, trig_t> TStateMachine;
|
||||
typedef TStateMachine::TTransition TTransition;
|
||||
typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, wifi_config_t*>> TConnectTrigger;
|
||||
typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, reboot_type_t>> TRebootTrigger;
|
||||
typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, char*>> TRebootOTATrigger;
|
||||
typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, wifi_event_sta_disconnected_t*>> TDisconnectTrigger;
|
||||
|
||||
}; // namespace
|
||||
|
||||
class NetworkManager {
|
||||
public:
|
||||
NetworkManager()
|
||||
: sm_(state_t::instantiated),
|
||||
connect_trigger_(sm_.set_trigger_parameters<wifi_config_t*>(trig_t::t_connect)),
|
||||
reboot_trigger_(sm_.set_trigger_parameters<reboot_type_t>(trig_t::t_reboot)),
|
||||
reboot_ota_(sm_.set_trigger_parameters<char*>(trig_t::t_reboot)),
|
||||
disconnected_(sm_.set_trigger_parameters<wifi_event_sta_disconnected_t*>(trig_t::t_lost_connection)) {
|
||||
sm_.configure(state_t::instantiated)
|
||||
.permit(trig_t::t_start, state_t::initializing);
|
||||
sm_.configure(state_t::global)
|
||||
.permit(trig_t::t_reboot, state_t::system_rebooting)
|
||||
.permit(trig_t::t_reboot_url, state_t::system_rebooting)
|
||||
.permit_reentry(trig_t::t_update_status)
|
||||
.on_entry_from(trig_t::t_update_status,
|
||||
[=](const TTransition& t) {
|
||||
wifi_manager_update_basic_info();
|
||||
});
|
||||
sm_.configure(state_t::system_rebooting)
|
||||
.on_entry_from(reboot_ota_, [=](const TTransition& t, char* url) {
|
||||
if (url) {
|
||||
start_ota(url, NULL, 0);
|
||||
free(url);
|
||||
}
|
||||
})
|
||||
.on_entry_from(reboot_trigger_, [=](const TTransition& t, reboot_type_t reboot_type) {
|
||||
switch (reboot_type) {
|
||||
case reboot_type_t::OTA:
|
||||
ESP_LOGD(TAG, "Calling guided_restart_ota.");
|
||||
guided_restart_ota();
|
||||
break;
|
||||
case reboot_type_t::RECOVERY:
|
||||
ESP_LOGD(TAG, "Calling guided_factory.");
|
||||
guided_factory();
|
||||
break;
|
||||
case reboot_type_t::RESTART:
|
||||
ESP_LOGD(TAG, "Calling simple_restart.");
|
||||
simple_restart();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
sm_.configure(state_t::initializing)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
/* memory allocation */
|
||||
ESP_LOGD(TAG, "network_manager_start. Creating message queue");
|
||||
network_manager_queue = xQueueCreate(3, sizeof(queue_message));
|
||||
ESP_LOGD(TAG, "network_manager_start. Allocating memory for callback functions registration");
|
||||
// todo: allow registration of event callbacks
|
||||
ESP_LOGD(TAG, "Initializing tcp_ip adapter");
|
||||
esp_netif_init();
|
||||
ESP_LOGD(TAG, "Creating the default event loop");
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
init_network_status();
|
||||
ESP_LOGD(TAG, "Initializing network. done");
|
||||
|
||||
/* start wifi manager task */
|
||||
ESP_LOGD(TAG, "Creating network manager task");
|
||||
network_manager_task = xTaskCreate(&network_manager, "network_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_network_manager);
|
||||
// send a message to start the connections
|
||||
})
|
||||
.permit(trig_t::t_start, state_t::eth_starting);
|
||||
sm_.configure(state_t::eth_starting)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
/* start http server */
|
||||
http_server_start();
|
||||
ESP_LOGD(TAG, "network_manager task started. Configuring Network Interface");
|
||||
init_network_ethernet();
|
||||
})
|
||||
.permit(trig_t::t_fail, state_t::wifi_initializing)
|
||||
.permit(trig_t::t_success, state_t::eth_active);
|
||||
|
||||
sm_.configure(state_t::eth_active)
|
||||
.permit(trig_t::t_link_up, state_t::eth_active_linkup)
|
||||
.permit(trig_t::t_got_ip, state_t::eth_active_connected)
|
||||
.permit(trig_t::t_link_down, state_t::eth_active_linkdown)
|
||||
.permit(trig_t::t_fail, state_t::wifi_initializing);
|
||||
|
||||
sm_.configure(state_t::eth_active_linkup)
|
||||
.sub_state_of(state_t::eth_active)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
// Anything we need to do on link becoming active?
|
||||
});
|
||||
sm_.configure(state_t::eth_active_linkdown)
|
||||
.sub_state_of(state_t::eth_active)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
// If not connected after a certain time, start
|
||||
// wifi
|
||||
});
|
||||
sm_.configure(state_t::eth_active_connected)
|
||||
.sub_state_of(state_t::eth_active)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
|
||||
})
|
||||
.on_exit([=](const TTransition& t) {
|
||||
|
||||
});
|
||||
sm_.configure(state_t::wifi_up)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
|
||||
})
|
||||
.on_exit([=](const TTransition& t) {
|
||||
|
||||
});
|
||||
|
||||
sm_.configure(state_t::wifi_initializing)
|
||||
.sub_state_of(state_t::wifi_up)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
esp_err_t err = ESP_OK;
|
||||
ESP_LOGD(TAG, "network_wifi_load_restore");
|
||||
if (!is_wifi_up()) {
|
||||
messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Load Configuration");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (wifi_manager_fetch_wifi_sta_config()) {
|
||||
ESP_LOGI(TAG, "Saved wifi found on startup. Will attempt to connect.");
|
||||
network_manager_async_connect(wifi_manager_get_wifi_sta_config());
|
||||
} else {
|
||||
/* no wifi saved: start soft AP! This is what should happen during a first run */
|
||||
ESP_LOGD(TAG, "No saved wifi. Starting AP.");
|
||||
network_manager_async_configure();
|
||||
}
|
||||
return err;
|
||||
})
|
||||
.permit(trig_t::t_configure, state_t::wifi_ap_mode)
|
||||
.permit(trig_t::t_connect, state_t::wifi_connecting_scanning);
|
||||
|
||||
sm_.configure(state_t::wifi_connecting_scanning)
|
||||
.sub_state_of(state_t::wifi_up)
|
||||
.on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
|
||||
if (network_wifi_connect(wifi_config) == ESP_OK) {
|
||||
network_manager_async_connect(wifi_config);
|
||||
} else {
|
||||
network_manager_async_fail();
|
||||
}
|
||||
|
||||
// STA_duration = STA_POLLING_MIN;
|
||||
// /* create timer for background STA connection */
|
||||
// if (!STA_timer) {
|
||||
// STA_timer = xTimerCreate("background STA", pdMS_TO_TICKS(STA_duration), pdFALSE, NULL, polling_STA);
|
||||
// }
|
||||
|
||||
// setup a timeout here. On timeout,
|
||||
// check reconnect_attempts and
|
||||
// fire trig_t::t_scan if we have more attempts to try
|
||||
// fire trig_t::t_fail otherwise
|
||||
})
|
||||
.permit_reentry_if(trig_t::t_scan, [&]() {
|
||||
return ++reconnect_attempt < 3;
|
||||
})
|
||||
.permit(trig_t::t_connect, state_t::wifi_connecting)
|
||||
.permit(trig_t::t_fail, state_t::wifi_lost_connection);
|
||||
|
||||
sm_.configure(state_t::wifi_connecting)
|
||||
.on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
|
||||
// setup a timeout here. On timeout,
|
||||
// check reconnect_attempts and
|
||||
// fire trig_t::t_wifi_connecting_existing if we have more attempts to try
|
||||
// fire trig_t::t_fail otherwise
|
||||
})
|
||||
.permit(trig_t::t_success, state_t::wifi_connected_waiting_for_ip)
|
||||
.permit(trig_t::t_got_ip, state_t::wifi_connected)
|
||||
.permit(trig_t::t_lost_connection, state_t::wifi_ap_mode);
|
||||
sm_.configure(state_t::wifi_connected_waiting_for_ip)
|
||||
.permit(trig_t::t_got_ip, state_t::wifi_connected);
|
||||
|
||||
sm_.configure(state_t::wifi_ap_mode)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
wifi_manager_config_ap();
|
||||
ESP_LOGD(TAG, "AP Starting, requesting wifi scan.");
|
||||
network_manager_async_scan();
|
||||
})
|
||||
.on_entry_from(disconnected_, [=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
|
||||
if(disconnected_event){
|
||||
free(disconnected_event);
|
||||
}
|
||||
})
|
||||
.permit(trig_t::t_scan, state_t::wifi_ap_mode_scanning);
|
||||
|
||||
sm_.configure(state_t::wifi_ap_mode_scanning)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
// build a list of found AP
|
||||
})
|
||||
.permit(trig_t::t_scan_done, state_t::wifi_ap_mode_scan_done);
|
||||
|
||||
sm_.configure(state_t::wifi_ap_mode_scan_done)
|
||||
.permit(trig_t::t_connect, state_t::wifi_ap_mode_connecting);
|
||||
sm_.configure(state_t::wifi_ap_mode_connecting)
|
||||
.on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
|
||||
|
||||
})
|
||||
.permit(trig_t::t_got_ip, state_t::wifi_ap_mode_connected)
|
||||
.permit(trig_t::t_fail, state_t::wifi_ap_mode);
|
||||
|
||||
sm_.configure(state_t::wifi_ap_mode_connected)
|
||||
.on_entry([=](const TTransition& t) {
|
||||
|
||||
})
|
||||
.permit(trig_t::t_success, state_t::wifi_connected);
|
||||
|
||||
sm_.configure(state_t::wifi_connected)
|
||||
.on_entry([&](const TTransition& t) {
|
||||
last_connected = esp_timer_get_time();
|
||||
/* bring down DNS hijack */
|
||||
ESP_LOGD(TAG, "Stopping DNS.");
|
||||
dns_server_stop();
|
||||
if (network_wifi_sta_config_changed()) {
|
||||
network_wifi_save_sta_config();
|
||||
}
|
||||
|
||||
/* stop AP mode */
|
||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
})
|
||||
.permit_reentry(trig_t::t_scan_done)
|
||||
.permit(trig_t::t_lost_connection, state_t::wifi_lost_connection)
|
||||
.permit(trig_t::t_scan, state_t::wifi_connected_scanning)
|
||||
.permit(trig_t::t_disconnect, state_t::wifi_disconnecting)
|
||||
.permit(trig_t::t_connect, state_t::wifi_connecting);
|
||||
|
||||
sm_.configure(state_t::wifi_disconnecting)
|
||||
.permit(trig_t::t_lost_connection, state_t::wifi_user_disconnected);
|
||||
sm_.configure(state_t::wifi_user_disconnected)
|
||||
.on_entry_from(disconnected_,
|
||||
[=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
|
||||
ESP_LOGD(TAG, "WiFi disconnected by user");
|
||||
network_wifi_clear_config();
|
||||
wifi_manager_generate_ip_info_json(UPDATE_USER_DISCONNECT);
|
||||
network_manager_async_configure();
|
||||
if (disconnected_event) {
|
||||
free(disconnected_event);
|
||||
}
|
||||
})
|
||||
.permit(trig_t::t_configure, state_t::wifi_ap_mode);
|
||||
sm_.configure(state_t::wifi_lost_connection)
|
||||
.on_entry_from(disconnected_,
|
||||
[=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
|
||||
ESP_LOGE(TAG, "WiFi Connection lost.");
|
||||
messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "WiFi Connection lost");
|
||||
wifi_manager_generate_ip_info_json(UPDATE_LOST_CONNECTION);
|
||||
if (last_connected > 0)
|
||||
total_connected_time += ((esp_timer_get_time() - last_connected) / (1000 * 1000));
|
||||
last_connected = 0;
|
||||
num_disconnect++;
|
||||
ESP_LOGW(TAG, "Wifi disconnected. Number of disconnects: %d, Average time connected: %d", num_disconnect, num_disconnect > 0 ? (total_connected_time / num_disconnect) : 0);
|
||||
//network_manager_async_connect(wifi_manager_get_wifi_sta_config());
|
||||
if (retries < WIFI_MANAGER_MAX_RETRY) {
|
||||
ESP_LOGD(TAG, "Issuing ORDER_CONNECT_STA to retry connection.");
|
||||
retries++;
|
||||
network_manager_async_connect(wifi_manager_get_wifi_sta_config());
|
||||
free(disconnected_event);
|
||||
} else {
|
||||
/* In this scenario the connection was lost beyond repair: kick start the AP! */
|
||||
retries = 0;
|
||||
wifi_mode_t mode;
|
||||
ESP_LOGW(TAG, "All connect retry attempts failed.");
|
||||
|
||||
/* put us in softAP mode first */
|
||||
esp_wifi_get_mode(&mode);
|
||||
if (WIFI_MODE_APSTA != mode) {
|
||||
STA_duration = STA_POLLING_MIN;
|
||||
network_manager_async_lost_connection(disconnected_event);
|
||||
} else if (STA_duration < STA_POLLING_MAX) {
|
||||
STA_duration *= 1.25;
|
||||
free(disconnected_event);
|
||||
}
|
||||
/* keep polling for existing connection */
|
||||
xTimerChangePeriod(STA_timer, pdMS_TO_TICKS(STA_duration), portMAX_DELAY);
|
||||
xTimerStart(STA_timer, portMAX_DELAY);
|
||||
ESP_LOGD(TAG, "STA search slow polling of %d", STA_duration);
|
||||
}
|
||||
})
|
||||
.on_entry([=](const TTransition& t) {
|
||||
wifi_manager_safe_reset_sta_ip_string();
|
||||
})
|
||||
.permit(trig_t::t_connect, state_t::wifi_connecting)
|
||||
.permit(trig_t::t_lost_connection, state_t::wifi_ap_mode);
|
||||
// Register a callback for state transitions (the default does nothing).
|
||||
sm_.on_transition([](const TTransition& t) {
|
||||
std::cout << "transition from [" << t.source() << "] to ["
|
||||
<< t.destination() << "] via trigger [" << t.trigger() << "]"
|
||||
<< std::endl;
|
||||
});
|
||||
|
||||
// Override the default behaviour of throwing when a trigger is unhandled.
|
||||
sm_.on_unhandled_trigger([](const state_t s, const trig_t t) {
|
||||
std::cerr << "ignore unhandled trigger [" << t << "] in state [" << s
|
||||
<< "]" << std::endl;
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
bool
|
||||
Allowed(trig_t trigger) {
|
||||
if (!sm_.can_fire(trigger)) {
|
||||
ESP_LOGW(TAG, "Network manager might not be able to process trigger %s", trigger_to_string(trigger));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Fire(trig_t trigger) {
|
||||
try {
|
||||
sm_.fire(trigger);
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Event(queue_message& msg) {
|
||||
trig_t trigger = msg.trigger;
|
||||
try {
|
||||
if (trigger == trig_t::t_connect) {
|
||||
sm_.fire(connect_trigger_, msg.wifi_config);
|
||||
} else if (trigger == trig_t::t_reboot) {
|
||||
sm_.fire(reboot_trigger_, msg.rtype);
|
||||
} else if (trigger == trig_t::t_reboot_url) {
|
||||
sm_.fire(reboot_ota_, msg.strval);
|
||||
} else if (trigger == trig_t::t_lost_connection) {
|
||||
sm_.fire(disconnected_, msg.disconnected_event);
|
||||
} else {
|
||||
sm_.fire(trigger);
|
||||
}
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << '\n';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t reconnect_attempt = 0;
|
||||
bool existing_connection = false;
|
||||
uint8_t retries = 0;
|
||||
TStateMachine sm_;
|
||||
TConnectTrigger connect_trigger_;
|
||||
TRebootTrigger reboot_trigger_;
|
||||
TRebootOTATrigger reboot_ota_;
|
||||
TDisconnectTrigger disconnected_;
|
||||
};
|
||||
|
||||
NetworkManager nm;
|
||||
void network_manager_start() {
|
||||
nm.Fire(trig_t::t_start);
|
||||
}
|
||||
|
||||
bool network_manager_async(trig_t trigger) {
|
||||
queue_message msg;
|
||||
msg.trigger = trigger;
|
||||
if (nm.Allowed(trigger)) {
|
||||
return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool network_manager_async_fail() {
|
||||
return network_manager_async(trig_t::t_fail);
|
||||
}
|
||||
bool network_manager_async_success() {
|
||||
return network_manager_async(trig_t::t_success);
|
||||
}
|
||||
|
||||
bool network_manager_async_link_up() {
|
||||
return network_manager_async(trig_t::t_link_up);
|
||||
}
|
||||
bool network_manager_async_link_down() {
|
||||
return network_manager_async(trig_t::t_link_down);
|
||||
}
|
||||
bool network_manager_async_configure() {
|
||||
return network_manager_async(trig_t::t_configure);
|
||||
}
|
||||
bool network_manager_async_got_ip() {
|
||||
return network_manager_async(trig_t::t_got_ip);
|
||||
}
|
||||
bool network_manager_async_next() {
|
||||
return network_manager_async(trig_t::t_next);
|
||||
}
|
||||
bool network_manager_async_start() {
|
||||
return network_manager_async(trig_t::t_start);
|
||||
}
|
||||
bool network_manager_async_scan() {
|
||||
return network_manager_async(trig_t::t_scan);
|
||||
}
|
||||
|
||||
bool network_manager_async_update_status() {
|
||||
return network_manager_async(trig_t::t_update_status);
|
||||
}
|
||||
|
||||
bool network_manager_async_disconnect() {
|
||||
return network_manager_async(trig_t::t_disconnect);
|
||||
}
|
||||
|
||||
bool network_manager_async_scan_done() {
|
||||
return network_manager_async(trig_t::t_scan_done);
|
||||
}
|
||||
bool network_manager_async_connect(wifi_config_t* wifi_config) {
|
||||
queue_message msg;
|
||||
msg.trigger = trig_t::t_connect;
|
||||
msg.wifi_config = wifi_config;
|
||||
if (nm.Allowed(msg.trigger)) {
|
||||
return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool network_manager_async_lost_connection(wifi_event_sta_disconnected_t* disconnected_event) {
|
||||
queue_message msg;
|
||||
msg.trigger = trig_t::t_lost_connection;
|
||||
msg.disconnected_event = disconnected_event;
|
||||
if (nm.Allowed(msg.trigger)) {
|
||||
return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool network_manager_async_reboot(reboot_type_t rtype) {
|
||||
queue_message msg;
|
||||
msg.trigger = trig_t::t_reboot;
|
||||
msg.rtype = rtype;
|
||||
if (nm.Allowed(msg.trigger)) {
|
||||
return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void network_manager_reboot_ota(char* url) {
|
||||
queue_message msg;
|
||||
|
||||
if (url == NULL) {
|
||||
msg.trigger = trig_t::t_reboot;
|
||||
msg.rtype = reboot_type_t::OTA;
|
||||
} else {
|
||||
msg.trigger = trig_t::t_reboot_url;
|
||||
msg.strval = strdup(url);
|
||||
}
|
||||
if (nm.Allowed(msg.trigger)) {
|
||||
xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// switch (msg.code) {
|
||||
// case EVENT_SCAN_DONE:
|
||||
// err = wifi_scan_done(&msg);
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code]) {
|
||||
// ESP_LOGD(TAG, "Invoking SCAN DONE callback");
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
// ESP_LOGD(TAG, "Done Invoking SCAN DONE callback");
|
||||
// }
|
||||
// break;
|
||||
// case ORDER_START_WIFI_SCAN:
|
||||
// err = network_wifi_start_scan(&msg);
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
// break;
|
||||
|
||||
// case ORDER_LOAD_AND_RESTORE_STA:
|
||||
// err = network_wifi_load_restore(&msg);
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
|
||||
// break;
|
||||
|
||||
// case ORDER_CONNECT_STA:
|
||||
// err = network_wifi_order_connect(&msg);
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
|
||||
// break;
|
||||
|
||||
// case EVENT_STA_DISCONNECTED:
|
||||
// err = network_wifi_disconnected(&msg);
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
// break;
|
||||
|
||||
// case ORDER_START_AP:
|
||||
// err = network_wifi_start_ap(&msg);
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
// break;
|
||||
|
||||
// case EVENT_GOT_IP:
|
||||
// ESP_LOGD(TAG, "MESSAGE: EVENT_GOT_IP");
|
||||
// /* save IP as a string for the HTTP server host */
|
||||
// //s->ip_info.ip.addr
|
||||
// ip_event_got_ip_t* event = (ip_event_got_ip_t*)msg.param;
|
||||
// wifi_manager_safe_update_sta_ip_string(&(event->ip_info.ip));
|
||||
// wifi_manager_generate_ip_info_json(network_manager_is_flag_set(WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT)? UPDATE_FAILED_ATTEMPT_AND_RESTORE : UPDATE_CONNECTION_OK, event->esp_netif, event->ip_changed);
|
||||
// free(msg.param);
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
// break;
|
||||
// case UPDATE_CONNECTION_OK:
|
||||
// messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "UPDATE_CONNECTION_OK not implemented");
|
||||
// break;
|
||||
// case ORDER_DISCONNECT_STA:
|
||||
// ESP_LOGD(TAG, "MESSAGE: ORDER_DISCONNECT_STA. Calling esp_wifi_disconnect()");
|
||||
|
||||
// /* precise this is coming from a user request */
|
||||
// xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT);
|
||||
|
||||
// /* order wifi discconect */
|
||||
// ESP_ERROR_CHECK(esp_wifi_disconnect());
|
||||
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
|
||||
// break;
|
||||
|
||||
// case ORDER_RESTART_OTA_URL:
|
||||
// ESP_LOGD(TAG, "Calling start_ota.");
|
||||
// start_ota(msg.param, NULL, 0);
|
||||
// free(msg.param);
|
||||
// break;
|
||||
|
||||
// case ORDER_RESTART_RECOVERY:
|
||||
|
||||
// break;
|
||||
// case ORDER_RESTART:
|
||||
// ESP_LOGD(TAG, "Calling simple_restart.");
|
||||
// simple_restart();
|
||||
// break;
|
||||
// case ORDER_UPDATE_STATUS:
|
||||
// ;
|
||||
// break;
|
||||
// case EVENT_ETH_TIMEOUT:
|
||||
// ESP_LOGW(TAG, "Ethernet connection timeout. Rebooting with WiFi Active");
|
||||
// network_manager_reboot(RESTART);
|
||||
// break;
|
||||
// case EVENT_ETH_LINK_UP:
|
||||
// /* callback */
|
||||
// ESP_LOGD(TAG,"EVENT_ETH_LINK_UP message received");
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
// break;
|
||||
// case EVENT_ETH_LINK_DOWN:
|
||||
// /* callback */
|
||||
// if (cb_ptr_arr[msg.code])
|
||||
// (*cb_ptr_arr[msg.code])(NULL);
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
|
||||
// } /* end of switch/case */
|
||||
|
||||
// if (!network_ethernet_wait_for_link(500)) {
|
||||
// if(network_ethernet_enabled()){
|
||||
// ESP_LOGW(TAG, "Ethernet not connected. Starting Wifi");
|
||||
// }
|
||||
// init_network_wifi();
|
||||
// wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL);
|
||||
// }
|
||||
|
||||
void network_manager(void* pvParameters) {
|
||||
queue_message msg;
|
||||
esp_err_t err = ESP_OK;
|
||||
BaseType_t xStatus;
|
||||
network_manager_async(trig_t::t_start);
|
||||
|
||||
/* main processing loop */
|
||||
for (;;) {
|
||||
xStatus = xQueueReceive(network_manager_queue, &msg, portMAX_DELAY);
|
||||
|
||||
if (xStatus == pdPASS) {
|
||||
// pass the event to the sync processor
|
||||
nm.Event(msg);
|
||||
} /* end of if status=pdPASS */
|
||||
} /* end of for loop */
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void network_manager_destroy() {
|
||||
vTaskDelete(task_network_manager);
|
||||
task_network_manager = NULL;
|
||||
/* heap buffers */
|
||||
destroy_network_status();
|
||||
destroy_network_wifi();
|
||||
destroy_network_status();
|
||||
/* RTOS objects */
|
||||
vQueueDelete(network_manager_queue);
|
||||
network_manager_queue = NULL;
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
#endif
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wifi_types.h"
|
||||
|
||||
|
||||
#define STA_POLLING_MIN (15 * 1000)
|
||||
#define STA_POLLING_MAX (10 * 60 * 1000)
|
||||
|
||||
//enum class state { idle, stopped, started, running };
|
||||
|
||||
//enum class trigger { start, stop, set_speed, halt };
|
||||
typedef enum {
|
||||
t_link_up,
|
||||
t_link_down,
|
||||
t_configure,
|
||||
t_got_ip,
|
||||
t_disconnect,
|
||||
t_next,
|
||||
t_start,
|
||||
t_scan,
|
||||
t_fail,
|
||||
t_success,
|
||||
t_scan_done,
|
||||
t_connect,
|
||||
t_reboot,
|
||||
t_reboot_url,
|
||||
t_lost_connection,
|
||||
t_update_status
|
||||
} trig_t;
|
||||
|
||||
typedef enum {
|
||||
instantiated,
|
||||
initializing,
|
||||
global,
|
||||
eth_starting,
|
||||
eth_active,
|
||||
eth_active_linkup,
|
||||
eth_active_connected,
|
||||
eth_active_linkdown,
|
||||
wifi_up,
|
||||
wifi_initializing,
|
||||
wifi_connecting_scanning,
|
||||
wifi_connecting,
|
||||
wifi_connected,
|
||||
wifi_disconnecting,
|
||||
wifi_user_disconnected,
|
||||
wifi_connected_waiting_for_ip,
|
||||
wifi_connected_scanning,
|
||||
wifi_lost_connection,
|
||||
wifi_ap_mode,
|
||||
wifi_ap_mode_scanning,
|
||||
wifi_ap_mode_scan_done,
|
||||
wifi_ap_mode_connecting,
|
||||
wifi_ap_mode_connected,
|
||||
system_rebooting
|
||||
} state_t;
|
||||
typedef enum {
|
||||
OTA,
|
||||
RECOVERY,
|
||||
RESTART,
|
||||
} reboot_type_t;
|
||||
typedef struct {
|
||||
trig_t trigger;
|
||||
union
|
||||
{
|
||||
wifi_config_t* wifi_config;
|
||||
reboot_type_t rtype;
|
||||
char * strval;
|
||||
wifi_event_sta_disconnected_t * disconnected_event;
|
||||
} ;
|
||||
|
||||
|
||||
} queue_message;
|
||||
|
||||
bool network_manager_event_simple(trig_t trigger);
|
||||
bool network_manager_event(trig_t trigger, void* param);
|
||||
bool network_t_connect_event(wifi_config_t* wifi_config);
|
||||
bool network_t_link_event(bool link_up);
|
||||
bool network_manager_async_event(trig_t trigger, void* param);
|
||||
bool network_manager_async(trig_t trigger);
|
||||
bool network_manager_async_fail();
|
||||
bool network_manager_async_success();
|
||||
bool network_manager_async_link_up();
|
||||
bool network_manager_async_link_down();
|
||||
bool network_manager_async_configure();
|
||||
bool network_manager_async_got_ip();
|
||||
bool network_manager_async_next();
|
||||
bool network_manager_async_start();
|
||||
bool network_manager_async_scan();
|
||||
bool network_manager_async_scan_done();
|
||||
bool network_manager_async_connect(wifi_config_t* wifi_config);
|
||||
bool network_manager_async_lost_connection(wifi_event_sta_disconnected_t * disconnected_event);
|
||||
bool network_manager_async_reboot(reboot_type_t rtype);
|
||||
void network_manager_reboot_ota(char* url);
|
||||
bool network_manager_async_disconnect();
|
||||
bool network_manager_async_update_status();
|
||||
/**
|
||||
* Allocate heap memory for the wifi manager and start the wifi_manager RTOS task
|
||||
*/
|
||||
void network_manager_start();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,13 +1,13 @@
|
||||
[
|
||||
{"ssid":"Pantum-AP-A6D49F","chan":11,"rssi":-55,"auth":4},
|
||||
{"ssid":"a0308","chan":1,"rssi":-56,"auth":3},
|
||||
{"ssid":"dlink-D9D8","chan":11,"rssi":-82,"auth":4},
|
||||
{"ssid":"Linksys06730","chan":7,"rssi":-85,"auth":3},
|
||||
{"ssid":"SINGTEL-5171","chan":9,"rssi":-88,"auth":4},
|
||||
{"ssid":"1126-1","chan":11,"rssi":-89,"auth":4},
|
||||
{"ssid":"The Shah 5GHz-2","chan":1,"rssi":-90,"auth":3},
|
||||
{"ssid":"SINGTEL-1D28 (2G)","chan":11,"rssi":-91,"auth":3},
|
||||
{"ssid":"dlink-F864","chan":1,"rssi":-92,"auth":4},
|
||||
{"ssid":"dlink-74F0","chan":1,"rssi":-93,"auth":4},
|
||||
{"ssid":"MyTestSSID","chan":2,"rssi":-53,"auth":4}
|
||||
{"ssid":"Pantum-AP-A6D49F","chan":11,"rssi":-55,"auth":4, "known":false},
|
||||
{"ssid":"a0308","chan":1,"rssi":-56,"auth":3, "known":false},
|
||||
{"ssid":"dlink-D9D8","chan":11,"rssi":-82,"auth":4, "known":false},
|
||||
{"ssid":"Linksys06730","chan":7,"rssi":-85,"auth":3, "known":false},
|
||||
{"ssid":"SINGTEL-5171","chan":9,"rssi":-88,"auth":4, "known":false},
|
||||
{"ssid":"1126-1","chan":11,"rssi":-89,"auth":4, "known":false},
|
||||
{"ssid":"The Shah 5GHz-2","chan":1,"rssi":-90,"auth":3, "known":false},
|
||||
{"ssid":"SINGTEL-1D28 (2G)","chan":11,"rssi":-91,"auth":3, "known":false},
|
||||
{"ssid":"dlink-F864","chan":1,"rssi":-92,"auth":4, "known":false},
|
||||
{"ssid":"dlink-74F0","chan":1,"rssi":-93,"auth":4, "known":false},
|
||||
{"ssid":"MyTestSSID","chan":2,"rssi":-53,"auth":4, "known":true}
|
||||
]
|
||||
@@ -54,7 +54,7 @@
|
||||
"current_time": 147319
|
||||
},
|
||||
{
|
||||
"message": "Wifi connected",
|
||||
"message": "Network connected",
|
||||
"type": "MESSAGING_INFO",
|
||||
"class": "MESSAGING_CLASS_SYSTEM",
|
||||
"sent_time": 141256,
|
||||
|
||||
@@ -1098,7 +1098,7 @@ function rssiToIcon(rssi) {
|
||||
}
|
||||
|
||||
function refreshAP() {
|
||||
$.getJSON('/scan.json', async function() {
|
||||
$.getJSON('/scan.json', async function() {
|
||||
await sleep(2000);
|
||||
$.getJSON('/ap.json', function(data) {
|
||||
if (data.length > 0) {
|
||||
@@ -1335,6 +1335,7 @@ function handleRecoveryMode(data) {
|
||||
$('#boot-form').attr('action', '/recovery.json');
|
||||
}
|
||||
}
|
||||
|
||||
function hasConnectionChanged(data){
|
||||
// gw: "192.168.10.1"
|
||||
// ip: "192.168.10.225"
|
||||
@@ -1366,10 +1367,10 @@ function handleWifiDialog(data){
|
||||
$('.connecting-status').show();
|
||||
}
|
||||
if(SystemConfig.ap_ssid){
|
||||
$('#apName').text(SystemConfig.ap_ssid);
|
||||
$('#apName').text(SystemConfig.ap_ssid.value);
|
||||
}
|
||||
if(SystemConfig.ap_pwd){
|
||||
$('#apPass').text(SystemConfig.ap_pwd);
|
||||
$('#apPass').text(SystemConfig.ap_pwd.value);
|
||||
}
|
||||
if(!data)
|
||||
{
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 605 B |
Binary file not shown.
|
Before Width: | Height: | Size: 613 B |
Binary file not shown.
|
Before Width: | Height: | Size: 615 B |
Binary file not shown.
|
Before Width: | Height: | Size: 605 B |
Binary file not shown.
|
Before Width: | Height: | Size: 656 B |
@@ -31,11 +31,13 @@
|
||||
#include "freertos/task.h"
|
||||
#include "messaging.h"
|
||||
#include "platform_esp32.h"
|
||||
#include "globdefs.h"
|
||||
#include "trace.h"
|
||||
static const char TAG[] = "http_server";
|
||||
|
||||
static httpd_handle_t _server = NULL;
|
||||
rest_server_context_t *rest_context = NULL;
|
||||
RingbufHandle_t messaging=NULL;
|
||||
EXT_RAM_ATTR static httpd_handle_t _server = NULL;
|
||||
EXT_RAM_ATTR rest_server_context_t *rest_context = NULL;
|
||||
EXT_RAM_ATTR RingbufHandle_t messaging=NULL;
|
||||
|
||||
void register_common_handlers(httpd_handle_t server){
|
||||
httpd_uri_t css_get = { .uri = "/css/*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context };
|
||||
@@ -46,7 +48,6 @@ void register_common_handlers(httpd_handle_t server){
|
||||
httpd_register_uri_handler(server, &icon_get);
|
||||
httpd_uri_t png_get = { .uri = "/favicon*", .method = HTTP_GET, .handler = resource_filehandler, .user_ctx = rest_context };
|
||||
httpd_register_uri_handler(server, &png_get);
|
||||
|
||||
}
|
||||
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 };
|
||||
@@ -124,13 +125,17 @@ void register_regular_handlers(httpd_handle_t server){
|
||||
|
||||
esp_err_t http_server_start()
|
||||
{
|
||||
|
||||
ESP_LOGI(TAG, "Initializing HTTP Server");
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("Registering messaging subscriber");
|
||||
messaging = messaging_register_subscriber(10, "http_server");
|
||||
rest_context = calloc(1, sizeof(rest_server_context_t));
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("Allocating RAM for server context");
|
||||
rest_context = malloc_init_external( sizeof(rest_server_context_t));
|
||||
if(rest_context==NULL){
|
||||
ESP_LOGE(TAG,"No memory for http context");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
strlcpy(rest_context->base_path, "/res/", sizeof(rest_context->base_path));
|
||||
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
@@ -141,15 +146,17 @@ esp_err_t http_server_start()
|
||||
//todo: use the endpoint below to configure session token?
|
||||
// config.open_fn
|
||||
|
||||
ESP_LOGD(TAG, "Starting HTTP Server");
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE( "Starting HTTP Server");
|
||||
esp_err_t err= __httpd_start(&_server, &config);
|
||||
if(err != ESP_OK){
|
||||
ESP_LOGE_LOC(TAG,"Start server failed");
|
||||
}
|
||||
else {
|
||||
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE( "HTTP Server started. Registering common handlers");
|
||||
register_common_handlers(_server);
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("Registering regular handlers");
|
||||
register_regular_handlers(_server);
|
||||
MEMTRACE_PRINT_DELTA_MESSAGE("HTTP Server regular handlers registered");
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user