123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /*
- 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.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"
- #include "squeezelite-ota.h"
- #include "cJSON.h"
- /**
- * @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.
- */
- #define MAX_SSID_SIZE 32
- /**
- * @brief Defines the maximum size of a WPA2 passkey. 64 is IEEE standard.
- * @warning limit is also hard coded in wifi_config_t. Never extend this value.
- */
- #define MAX_PASSWORD_SIZE 64
- #define MAX_COMMAND_LINE_SIZE 201
- /**
- * @brief Defines the maximum number of access points that can be scanned.
- *
- * To save memory and avoid nasty out of memory errors,
- * we can limit the number of APs detected in a wifi scan.
- */
- #define MAX_AP_NUM 15
- /**
- * @brief Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up.
- * Setting it to 2 for instance means there will be 3 attempts in total (original request + 2 retries)
- */
- #define WIFI_MANAGER_MAX_RETRY CONFIG_WIFI_MANAGER_MAX_RETRY
- /** @brief Defines the task priority of the wifi_manager.
- *
- * Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1.
- * For this particular reason, minimum task priority is 1. It it highly not recommended to set
- * it to 1 though as the sub-tasks will now have a priority of 0 which is the priority
- * of freeRTOS' idle task.
- */
- #define WIFI_MANAGER_TASK_PRIORITY CONFIG_WIFI_MANAGER_TASK_PRIORITY
- /** @brief Defines the auth mode as an access point
- * Value must be of type wifi_auth_mode_t
- * @see esp_wifi_types.h
- * @warning if set to WIFI_AUTH_OPEN, passowrd me be empty. See DEFAULT_AP_PASSWORD.
- */
- #define AP_AUTHMODE WIFI_AUTH_WPA2_PSK
- /** @brief Defines visibility of the access point. 0: visible AP. 1: hidden */
- #define DEFAULT_AP_SSID_HIDDEN 0
- /** @brief Defines access point's name. Default value: esp32. Run 'make menuconfig' to setup your own value or replace here by a string */
- #define DEFAULT_AP_SSID CONFIG_DEFAULT_AP_SSID
- /** @brief Defines access point's password.
- * @warning In the case of an open access point, the password must be a null string "" or "\0" if you want to be verbose but waste one byte.
- * In addition, the AP_AUTHMODE must be WIFI_AUTH_OPEN
- */
- #define DEFAULT_AP_PASSWORD CONFIG_DEFAULT_AP_PASSWORD
- /** @brief Defines access point's bandwidth.
- * Value: WIFI_BW_HT20 for 20 MHz or WIFI_BW_HT40 for 40 MHz
- * 20 MHz minimize channel interference but is not suitable for
- * applications with high data speeds
- */
- #define DEFAULT_AP_BANDWIDTH WIFI_BW_HT20
- /** @brief Defines access point's channel.
- * Channel selection is only effective when not connected to another AP.
- * Good practice for minimal channel interference to use
- * For 20 MHz: 1, 6 or 11 in USA and 1, 5, 9 or 13 in most parts of the world
- * For 40 MHz: 3 in USA and 3 or 11 in most parts of the world
- */
- #define DEFAULT_AP_CHANNEL CONFIG_DEFAULT_AP_CHANNEL
- /** @brief Defines the access point's default IP address. Default: "10.10.0.1 */
- #define DEFAULT_AP_IP CONFIG_DEFAULT_AP_IP
- /** @brief Defines the access point's gateway. This should be the same as your IP. Default: "10.10.0.1" */
- #define DEFAULT_AP_GATEWAY CONFIG_DEFAULT_AP_GATEWAY
- /** @brief Defines the access point's netmask. Default: "255.255.255.0" */
- #define DEFAULT_AP_NETMASK CONFIG_DEFAULT_AP_NETMASK
- /** @brief Defines access point's maximum number of clients. Default: 4 */
- #define DEFAULT_AP_MAX_CONNECTIONS CONFIG_DEFAULT_AP_MAX_CONNECTIONS
- /** @brief Defines access point's beacon interval. 100ms is the recommended default. */
- #define DEFAULT_AP_BEACON_INTERVAL CONFIG_DEFAULT_AP_BEACON_INTERVAL
- /** @brief Defines if esp32 shall run both AP + STA when connected to another AP.
- * Value: 0 will have the own AP always on (APSTA mode)
- * Value: 1 will turn off own AP when connected to another AP (STA only mode when connected)
- * Turning off own AP when connected to another AP minimize channel interference and increase throughput
- */
- #define DEFAULT_STA_ONLY 1
- /** @brief Defines if wifi power save shall be enabled.
- * Value: WIFI_PS_NONE for full power (wifi modem always on)
- * Value: WIFI_PS_MODEM for power save (wifi modem sleep periodically)
- * Note: Power save is only effective when in STA only mode
- */
- #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_STA_GOT_IP = 14,
- ORDER_RESTART_OTA = 15,
- ORDER_RESTART_RECOVERY = 16,
- ORDER_RESTART_OTA_URL = 17,
- ORDER_RESTART = 18,
- ORDER_UPDATE_STATUS = 19,
- MESSAGE_CODE_COUNT = 20 /* important for the callback array */
- }message_code_t;
- typedef enum reboot_type_t{
- OTA,
- RECOVERY,
- RESTART,
- } reboot_type_t;
- void wifi_manager_reboot(reboot_type_t rtype);
- void wifi_manager_reboot_ota(char * url);
- void wifi_manager_update_status();
- /**
- * @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.
- */
- typedef enum update_reason_code_t {
- UPDATE_CONNECTION_OK = 0,
- UPDATE_FAILED_ATTEMPT = 1,
- UPDATE_USER_DISCONNECT = 2,
- UPDATE_LOST_CONNECTION = 3
- }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 = 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;
- /**
- * Allocate heap memory for the wifi manager and start the wifi_manager RTOS task
- */
- void wifi_manager_start();
- /**
- * Frees up all memory allocated by the wifi_manager and kill the task.
- */
- void wifi_manager_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 wifi_manager( void * pvParameters );
- char* wifi_manager_alloc_get_ap_list_json();
- char* wifi_manager_alloc_get_ip_info_json();
- cJSON * wifi_manager_clear_ap_list_json(cJSON **old);
- /**
- * @brief saves the current STA wifi config to flash ram storage.
- */
- esp_err_t wifi_manager_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();
- wifi_config_t* wifi_manager_get_wifi_sta_config();
- /**
- * @brief A standard wifi event handler as recommended by Espressif
- */
- esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event);
- /**
- * @brief Registers handler for wifi and ip events
- */
- void wifi_manager_register_handlers();
- /**
- * @brief requests a connection to an access point that will be process in the main task thread.
- */
- void wifi_manager_connect_async();
- /**
- * @brief requests a wifi scan
- */
- void wifi_manager_scan_async();
- /**
- * @brief requests to disconnect and forget about the access point.
- */
- void wifi_manager_disconnect_async();
- /**
- * @brief Tries to get access to json buffer mutex.
- *
- * The HTTP server can try to access the json to serve clients while the wifi manager thread can try
- * to update it. These two tasks are synchronized through a mutex.
- *
- * The mutex is used by both the access point list json and the connection status json.\n
- * These two resources should technically have their own mutex but we lose some flexibility to save
- * on memory.
- *
- * This is a simple wrapper around freeRTOS function xSemaphoreTake.
- *
- * @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);
- /**
- * @brief Releases the json buffer mutex.
- */
- void wifi_manager_unlock_json_buffer();
- /**
- * @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.
- */
- void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code);
- /**
- * @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.
- */
- cJSON * wifi_manager_clear_ip_info_json(cJSON **old);
- cJSON * wifi_manager_get_new_json(cJSON **old);
- /**
- * @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.
- */
- void wifi_manager_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.
- */
- void wifi_manager_clear_access_points_json();
- /**
- * @brief Start the mDNS service
- */
- void wifi_manager_initialise_mdns();
- bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait);
- void wifi_manager_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();
- /**
- * @brief thread safe char representation of the STA IP update
- */
- void wifi_manager_safe_update_sta_ip_string(struct ip4_addr * ip4);
- /**
- * @brief Register a callback to a custom function when specific event message_code happens.
- */
- void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) );
- BaseType_t wifi_manager_send_message(message_code_t code, void *param);
- BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param);
- #ifdef __cplusplus
- }
- #endif
- #endif /* WIFI_MANAGER_H_INCLUDED */
|