wifi_manager.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. Copyright (c) 2017-2019 Tony Pottier
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in all
  10. copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. SOFTWARE.
  18. @file wifi_manager.h
  19. @author Tony Pottier
  20. @brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
  21. Contains the freeRTOS task and all necessary support
  22. @see https://idyl.io
  23. @see https://github.com/tonyp7/esp32-wifi-manager
  24. */
  25. #ifndef WIFI_MANAGER_H_INCLUDED
  26. #define WIFI_MANAGER_H_INCLUDED
  27. #ifdef __cplusplus
  28. extern "C" {
  29. #endif
  30. #include "esp_system.h"
  31. #include "esp_wifi.h"
  32. #include "esp_wifi_types.h"
  33. #ifndef RECOVERY_APPLICATION
  34. #error "RECOVERY_APPLICATION not defined. Defaulting to squeezelite"
  35. #endif
  36. #if RECOVERY_APPLICATION==1
  37. #warning "compiling for recovery."
  38. #elif RECOVERY_APPLICATION==0
  39. #warning "compiling for squeezelite."
  40. #else
  41. #error "unknown configuration"
  42. #endif
  43. #define DEFAULT_COMMAND_LINE CONFIG_DEFAULT_COMMAND_LINE
  44. /**
  45. * @brief Defines the maximum size of a SSID name. 32 is IEEE standard.
  46. * @warning limit is also hard coded in wifi_config_t. Never extend this value.
  47. */
  48. #define MAX_SSID_SIZE 32
  49. /**
  50. * @brief Defines the maximum size of a WPA2 passkey. 64 is IEEE standard.
  51. * @warning limit is also hard coded in wifi_config_t. Never extend this value.
  52. */
  53. #define MAX_PASSWORD_SIZE 64
  54. #define MAX_COMMAND_LINE_SIZE 201
  55. /**
  56. * @brief Defines the maximum number of access points that can be scanned.
  57. *
  58. * To save memory and avoid nasty out of memory errors,
  59. * we can limit the number of APs detected in a wifi scan.
  60. */
  61. #define MAX_AP_NUM 15
  62. /**
  63. * @brief Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up.
  64. * Setting it to 2 for instance means there will be 3 attempts in total (original request + 2 retries)
  65. */
  66. #define WIFI_MANAGER_MAX_RETRY CONFIG_WIFI_MANAGER_MAX_RETRY
  67. /** @brief Defines the task priority of the wifi_manager.
  68. *
  69. * Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1.
  70. * For this particular reason, minimum task priority is 1. It it highly not recommended to set
  71. * it to 1 though as the sub-tasks will now have a priority of 0 which is the priority
  72. * of freeRTOS' idle task.
  73. */
  74. #define WIFI_MANAGER_TASK_PRIORITY CONFIG_WIFI_MANAGER_TASK_PRIORITY
  75. /** @brief Defines the auth mode as an access point
  76. * Value must be of type wifi_auth_mode_t
  77. * @see esp_wifi_types.h
  78. * @warning if set to WIFI_AUTH_OPEN, passowrd me be empty. See DEFAULT_AP_PASSWORD.
  79. */
  80. #define AP_AUTHMODE WIFI_AUTH_WPA2_PSK
  81. /** @brief Defines visibility of the access point. 0: visible AP. 1: hidden */
  82. #define DEFAULT_AP_SSID_HIDDEN 0
  83. /** @brief Defines access point's name. Default value: esp32. Run 'make menuconfig' to setup your own value or replace here by a string */
  84. #define DEFAULT_AP_SSID CONFIG_DEFAULT_AP_SSID
  85. /** @brief Defines access point's password.
  86. * @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.
  87. * In addition, the AP_AUTHMODE must be WIFI_AUTH_OPEN
  88. */
  89. #define DEFAULT_AP_PASSWORD CONFIG_DEFAULT_AP_PASSWORD
  90. /** @brief Defines the hostname broadcasted by mDNS */
  91. #define DEFAULT_HOSTNAME "esp32"
  92. /** @brief Defines access point's bandwidth.
  93. * Value: WIFI_BW_HT20 for 20 MHz or WIFI_BW_HT40 for 40 MHz
  94. * 20 MHz minimize channel interference but is not suitable for
  95. * applications with high data speeds
  96. */
  97. #define DEFAULT_AP_BANDWIDTH WIFI_BW_HT20
  98. /** @brief Defines access point's channel.
  99. * Channel selection is only effective when not connected to another AP.
  100. * Good practice for minimal channel interference to use
  101. * For 20 MHz: 1, 6 or 11 in USA and 1, 5, 9 or 13 in most parts of the world
  102. * For 40 MHz: 3 in USA and 3 or 11 in most parts of the world
  103. */
  104. #define DEFAULT_AP_CHANNEL CONFIG_DEFAULT_AP_CHANNEL
  105. /** @brief Defines the access point's default IP address. Default: "10.10.0.1 */
  106. #define DEFAULT_AP_IP CONFIG_DEFAULT_AP_IP
  107. /** @brief Defines the access point's gateway. This should be the same as your IP. Default: "10.10.0.1" */
  108. #define DEFAULT_AP_GATEWAY CONFIG_DEFAULT_AP_GATEWAY
  109. /** @brief Defines the access point's netmask. Default: "255.255.255.0" */
  110. #define DEFAULT_AP_NETMASK CONFIG_DEFAULT_AP_NETMASK
  111. /** @brief Defines access point's maximum number of clients. Default: 4 */
  112. #define DEFAULT_AP_MAX_CONNECTIONS CONFIG_DEFAULT_AP_MAX_CONNECTIONS
  113. /** @brief Defines access point's beacon interval. 100ms is the recommended default. */
  114. #define DEFAULT_AP_BEACON_INTERVAL CONFIG_DEFAULT_AP_BEACON_INTERVAL
  115. /** @brief Defines if esp32 shall run both AP + STA when connected to another AP.
  116. * Value: 0 will have the own AP always on (APSTA mode)
  117. * Value: 1 will turn off own AP when connected to another AP (STA only mode when connected)
  118. * Turning off own AP when connected to another AP minimize channel interference and increase throughput
  119. */
  120. #define DEFAULT_STA_ONLY 1
  121. /** @brief Defines if wifi power save shall be enabled.
  122. * Value: WIFI_PS_NONE for full power (wifi modem always on)
  123. * Value: WIFI_PS_MODEM for power save (wifi modem sleep periodically)
  124. * Note: Power save is only effective when in STA only mode
  125. */
  126. #define DEFAULT_STA_POWER_SAVE WIFI_PS_NONE
  127. /**
  128. * @brief Defines the maximum length in bytes of a JSON representation of an access point.
  129. *
  130. * maximum ap string length with full 32 char ssid: 75 + \\n + \0 = 77\n
  131. * example: {"ssid":"abcdefghijklmnopqrstuvwxyz012345","chan":12,"rssi":-100,"auth":4},\n
  132. * BUT: we need to escape JSON. Imagine a ssid full of \" ? so it's 32 more bytes hence 77 + 32 = 99.\n
  133. * this is an edge case but I don't think we should crash in a catastrophic manner just because
  134. * someone decided to have a funny wifi name.
  135. */
  136. #define JSON_ONE_APP_SIZE 99
  137. /**
  138. * @brief Defines the maximum length in bytes of a JSON representation of the IP information
  139. * assuming all ips are 4*3 digits, and all characters in the ssid require to be escaped.
  140. * example: {"ssid":"abcdefghijklmnopqrstuvwxyz012345","ip":"192.168.1.119","netmask":"255.255.255.0","gw":"192.168.1.1","urc":0, "ota_dsc":"Installing...", "ota_pct":100}
  141. */
  142. #if RECOVERY_APPLICATION
  143. // recovery has more resources available. Let's use them to include more details about the OTA process
  144. #define JSON_IP_INFO_SIZE 150+255
  145. #else
  146. // 40 chars for appname and version
  147. #define JSON_IP_INFO_SIZE 150+40
  148. #endif
  149. /**
  150. * @brief Defines the complete list of all messages that the wifi_manager can process.
  151. *
  152. * Some of these message are events ("EVENT"), and some of them are action ("ORDER")
  153. * Each of these messages can trigger a callback function and each callback function is stored
  154. * in a function pointer array for convenience. Because of this behavior, it is extremely important
  155. * to maintain a strict sequence and the top level special element 'MESSAGE_CODE_COUNT'
  156. *
  157. * @see wifi_manager_set_callback
  158. */
  159. typedef enum message_code_t {
  160. NONE = 0,
  161. ORDER_START_HTTP_SERVER = 1,
  162. ORDER_STOP_HTTP_SERVER = 2,
  163. ORDER_START_DNS_SERVICE = 3,
  164. ORDER_STOP_DNS_SERVICE = 4,
  165. ORDER_START_WIFI_SCAN = 5,
  166. ORDER_LOAD_AND_RESTORE_STA = 6,
  167. ORDER_CONNECT_STA = 7,
  168. ORDER_DISCONNECT_STA = 8,
  169. ORDER_START_AP = 9,
  170. ORDER_START_HTTP = 10,
  171. ORDER_START_DNS_HIJACK = 11,
  172. EVENT_STA_DISCONNECTED = 12,
  173. EVENT_SCAN_DONE = 13,
  174. EVENT_STA_GOT_IP = 14,
  175. MESSAGE_CODE_COUNT = 15 /* important for the callback array */
  176. }message_code_t;
  177. /**
  178. * @brief simplified reason codes for a lost connection.
  179. *
  180. * esp-idf maintains a big list of reason codes which in practice are useless for most typical application.
  181. */
  182. typedef enum update_reason_code_t {
  183. UPDATE_CONNECTION_OK = 0,
  184. UPDATE_FAILED_ATTEMPT = 1,
  185. UPDATE_USER_DISCONNECT = 2,
  186. UPDATE_LOST_CONNECTION = 3
  187. }update_reason_code_t;
  188. typedef enum connection_request_made_by_code_t{
  189. CONNECTION_REQUEST_NONE = 0,
  190. CONNECTION_REQUEST_USER = 1,
  191. CONNECTION_REQUEST_AUTO_RECONNECT = 2,
  192. CONNECTION_REQUEST_RESTORE_CONNECTION = 3,
  193. CONNECTION_REQUEST_MAX = 0x7fffffff /*force the creation of this enum as a 32 bit int */
  194. }connection_request_made_by_code_t;
  195. /**
  196. * The actual WiFi settings in use
  197. */
  198. struct wifi_settings_t{
  199. uint8_t ap_ssid[MAX_SSID_SIZE];
  200. uint8_t ap_pwd[MAX_PASSWORD_SIZE];
  201. uint8_t ap_channel;
  202. uint8_t ap_ssid_hidden;
  203. wifi_bandwidth_t ap_bandwidth;
  204. bool sta_only;
  205. wifi_ps_type_t sta_power_save;
  206. bool sta_static_ip;
  207. tcpip_adapter_ip_info_t sta_static_ip_config;
  208. };
  209. extern struct wifi_settings_t wifi_settings;
  210. /**
  211. * @brief Structure used to store one message in the queue.
  212. */
  213. typedef struct{
  214. message_code_t code;
  215. void *param;
  216. } queue_message;
  217. /**
  218. * Allocate heap memory for the wifi manager and start the wifi_manager RTOS task
  219. */
  220. void wifi_manager_start();
  221. /**
  222. * Frees up all memory allocated by the wifi_manager and kill the task.
  223. */
  224. void wifi_manager_destroy();
  225. /**
  226. * Filters the AP scan list to unique SSIDs
  227. */
  228. void filter_unique( wifi_ap_record_t * aplist, uint16_t * ap_num);
  229. /**
  230. * Main task for the wifi_manager
  231. */
  232. void wifi_manager( void * pvParameters );
  233. char* wifi_manager_get_ap_list_json();
  234. char* wifi_manager_get_ip_info_json();
  235. uint8_t wifi_manager_get_flag();
  236. char * wifi_manager_alloc_get_config(char * name, size_t * l);
  237. /**
  238. * @brief saves the current STA wifi config to flash ram storage.
  239. */
  240. esp_err_t wifi_manager_save_sta_config();
  241. /**
  242. * @brief saves the current configuration to flash ram storage
  243. */
  244. esp_err_t wifi_manager_save_autoexec_config(char * value, char * name, int len);
  245. esp_err_t wifi_manager_save_autoexec_flag(uint8_t flag);
  246. /**
  247. * @brief fetch a previously STA wifi config in the flash ram storage.
  248. * @return true if a previously saved config was found, false otherwise.
  249. */
  250. bool wifi_manager_fetch_wifi_sta_config();
  251. wifi_config_t* wifi_manager_get_wifi_sta_config();
  252. /**
  253. * @brief A standard wifi event handler as recommended by Espressif
  254. */
  255. esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event);
  256. /**
  257. * @brief requests a connection to an access point that will be process in the main task thread.
  258. */
  259. void wifi_manager_connect_async();
  260. /**
  261. * @brief requests a wifi scan
  262. */
  263. void wifi_manager_scan_async();
  264. /**
  265. * @brief requests to disconnect and forget about the access point.
  266. */
  267. void wifi_manager_disconnect_async();
  268. /**
  269. * @brief Tries to get access to json buffer mutex.
  270. *
  271. * The HTTP server can try to access the json to serve clients while the wifi manager thread can try
  272. * to update it. These two tasks are synchronized through a mutex.
  273. *
  274. * The mutex is used by both the access point list json and the connection status json.\n
  275. * These two resources should technically have their own mutex but we lose some flexibility to save
  276. * on memory.
  277. *
  278. * This is a simple wrapper around freeRTOS function xSemaphoreTake.
  279. *
  280. * @param xTicksToWait The time in ticks to wait for the semaphore to become available.
  281. * @return true in success, false otherwise.
  282. */
  283. bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait);
  284. /**
  285. * @brief Releases the json buffer mutex.
  286. */
  287. void wifi_manager_unlock_json_buffer();
  288. /**
  289. * @brief Generates the connection status json: ssid and IP addresses.
  290. * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
  291. */
  292. void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code);
  293. /**
  294. * @brief Clears the connection status json.
  295. * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
  296. */
  297. void wifi_manager_clear_ip_info_json();
  298. /**
  299. * @brief Generates the list of access points after a wifi scan.
  300. * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
  301. */
  302. void wifi_manager_generate_acess_points_json();
  303. /**
  304. * @brief Clear the list of access points.
  305. * @note This is not thread-safe and should be called only if wifi_manager_lock_json_buffer call is successful.
  306. */
  307. void wifi_manager_clear_access_points_json();
  308. /**
  309. * @brief Start the mDNS service
  310. */
  311. void wifi_manager_initialise_mdns();
  312. bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait);
  313. void wifi_manager_unlock_sta_ip_string();
  314. /**
  315. * @brief gets the string representation of the STA IP address, e.g.: "192.168.1.69"
  316. */
  317. char* wifi_manager_get_sta_ip_string();
  318. /**
  319. * @brief thread safe char representation of the STA IP update
  320. */
  321. void wifi_manager_safe_update_sta_ip_string(uint32_t ip);
  322. /**
  323. * @brief Register a callback to a custom function when specific event message_code happens.
  324. */
  325. void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) );
  326. BaseType_t wifi_manager_send_message(message_code_t code, void *param);
  327. BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param);
  328. #ifdef __cplusplus
  329. }
  330. #endif
  331. #endif /* WIFI_MANAGER_H_INCLUDED */