Network manager implemented and relatively stable

This commit is contained in:
Sebastien L
2021-12-10 13:07:27 -05:00
parent 81756a7649
commit 63fbc2f645
66 changed files with 4528 additions and 2679 deletions

View File

@@ -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(&eth_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;
}