network_manager.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. #pragma once
  2. #include "esp_system.h"
  3. #include "esp_wifi.h"
  4. #include "esp_wifi_types.h"
  5. #include "squeezelite-ota.h"
  6. #include "cJSON.h"
  7. #include "esp_eth.h"
  8. #include "freertos/event_groups.h"
  9. #include "hsm.h"
  10. #include "esp_log.h"
  11. #ifdef __cplusplus
  12. extern "C" {
  13. #endif
  14. #define STA_POLLING_MIN (15 * 1000)
  15. #define STA_POLLING_MAX (10 * 60 * 1000)
  16. #define ETH_LINK_DOWN_REBOOT (4 * 1000)
  17. #define ETH_DHCP_FAIL (6 * 1000)
  18. #define WIFI_DHCP_FAIL (6 * 1000)
  19. /*
  20. * --------------------- ENUMERATION ---------------------
  21. */
  22. //#define ADD_ROOT(NAME, HANDLER, ENTRY, EXIT, CHILD)
  23. //#define ADD_ROOT(NAME, HANDLER, ENTRY, EXIT, CHILD)
  24. //#define ADD_LEAF(NAME, HANDLER, ENTRY, EXIT, PARENT, LEVEL)
  25. #define ALL_NM_STATE \
  26. ADD_ROOT_LEAF(NETWORK_INSTANTIATED_STATE)\
  27. ADD_ROOT_LEAF(NETWORK_INITIALIZING_STATE)\
  28. ADD_ROOT(NETWORK_ETH_ACTIVE_STATE, Eth_Active_State)\
  29. ADD_ROOT(NETWORK_WIFI_ACTIVE_STATE, Wifi_Active_State)\
  30. ADD_ROOT(NETWORK_WIFI_CONFIGURING_ACTIVE_STATE, Wifi_Configuring_State)
  31. #define ALL_ETH_STATE(PARENT, LEVEL)\
  32. ADD_LEAF(ETH_STARTING_STATE,PARENT,LEVEL)\
  33. ADD_LEAF(ETH_ACTIVE_LINKUP_STATE,PARENT,LEVEL)\
  34. ADD_LEAF(ETH_ACTIVE_LINKDOWN_STATE,PARENT,LEVEL)\
  35. ADD_LEAF(ETH_ACTIVE_CONNECTED_STATE,PARENT,LEVEL)\
  36. ADD_LEAF(ETH_CONNECTING_NEW_STATE,PARENT,LEVEL)
  37. #define ALL_WIFI_STATE(PARENT, LEVEL)\
  38. ADD_LEAF(WIFI_INITIALIZING_STATE,PARENT,LEVEL)\
  39. ADD_LEAF(WIFI_CONNECTING_STATE,PARENT,LEVEL)\
  40. ADD_LEAF(WIFI_CONNECTING_NEW_STATE,PARENT,LEVEL)\
  41. ADD_LEAF(WIFI_CONNECTING_NEW_FAILED_STATE,PARENT,LEVEL)\
  42. ADD_LEAF(WIFI_CONNECTED_STATE,PARENT,LEVEL)\
  43. ADD_LEAF(WIFI_USER_DISCONNECTED_STATE,PARENT,LEVEL)\
  44. ADD_LEAF(WIFI_LOST_CONNECTION_STATE,PARENT,LEVEL)
  45. #define ALL_WIFI_CONFIGURING_STATE(PARENT, LEVEL)\
  46. ADD_LEAF(WIFI_CONFIGURING_STATE,PARENT,LEVEL)\
  47. ADD_LEAF(WIFI_CONFIGURING_CONNECT_STATE,PARENT,LEVEL)\
  48. ADD_LEAF(WIFI_CONFIGURING_CONNECT_SUCCESS_STATE,PARENT,LEVEL)\
  49. ADD_LEAF(WIFI_CONFIGURING_CONNECT_SUCCESS_GOTOSTA_STATE,PARENT,LEVEL)
  50. #define ADD_ROOT(name, ...) name,
  51. #define ADD_ROOT_LEAF(name, ...) name,
  52. #define ADD_LEAF(name, ...) name,
  53. typedef enum {
  54. ALL_NM_STATE
  55. TOTAL_NM_STATE
  56. } nm_state_t;
  57. typedef enum {
  58. ALL_WIFI_STATE(,)
  59. TOTAL_WIFI_ACTIVE_STATE
  60. } mn_wifi_active_state_t;
  61. typedef enum {
  62. ALL_ETH_STATE(,)
  63. TOTAL_ETH_ACTIVE_STATE
  64. } mn_eth_active_state_t;
  65. typedef enum {
  66. ALL_WIFI_CONFIGURING_STATE(,)
  67. TOTAL_WIFI_CONFIGURING_STATE
  68. } mn_wifi_configuring_state_t;
  69. #undef ADD_STATE
  70. #undef ADD_ROOT
  71. #undef ADD_ROOT_LEAF
  72. #undef ADD_LEAF
  73. typedef void (*network_status_reached_cb)(nm_state_t state_id, int sub_state );
  74. //! List of oven events
  75. #define ALL_NM_EVENTS \
  76. ADD_FIRST_EVENT(EN_LINK_UP) \
  77. ADD_EVENT(EN_LINK_DOWN)\
  78. ADD_EVENT(EN_CONFIGURE)\
  79. ADD_EVENT(EN_GOT_IP)\
  80. ADD_EVENT(EN_ETH_GOT_IP)\
  81. ADD_EVENT(EN_DELETE)\
  82. ADD_EVENT(EN_TIMER)\
  83. ADD_EVENT(EN_START)\
  84. ADD_EVENT(EN_SCAN)\
  85. ADD_EVENT(EN_FAIL)\
  86. ADD_EVENT(EN_SUCCESS)\
  87. ADD_EVENT(EN_SCAN_DONE)\
  88. ADD_EVENT(EN_CONNECT)\
  89. ADD_EVENT(EN_CONNECT_NEW)\
  90. ADD_EVENT(EN_REBOOT)\
  91. ADD_EVENT(EN_REBOOT_URL)\
  92. ADD_EVENT(EN_LOST_CONNECTION)\
  93. ADD_EVENT(EN_ETHERNET_FALLBACK)\
  94. ADD_EVENT(EN_UPDATE_STATUS)\
  95. ADD_EVENT(EN_CONNECTED)
  96. #define ADD_EVENT(name) name,
  97. #define ADD_FIRST_EVENT(name) name=1,
  98. typedef enum {
  99. ALL_NM_EVENTS
  100. } network_event_t;
  101. #undef ADD_EVENT
  102. #undef ADD_FIRST_EVENT
  103. typedef enum {
  104. OTA,
  105. RECOVERY,
  106. RESTART,
  107. } reboot_type_t;
  108. typedef struct {
  109. network_event_t trigger;
  110. char * ssid;
  111. char * password;
  112. reboot_type_t rtype;
  113. char* strval;
  114. wifi_event_sta_disconnected_t* disconnected_event;
  115. esp_netif_t *netif;
  116. } queue_message;
  117. typedef struct
  118. {
  119. state_machine_t Machine; //!< Abstract state machine
  120. const state_t* source_state;
  121. bool ethernet_connected;
  122. TimerHandle_t state_timer;
  123. uint32_t STA_duration;
  124. int32_t total_connected_time;
  125. int64_t last_connected;
  126. uint16_t num_disconnect;
  127. uint16_t retries;
  128. bool wifi_connected;
  129. esp_netif_t *wifi_netif;
  130. esp_netif_t *eth_netif;
  131. esp_netif_t *wifi_ap_netif;
  132. queue_message * event_parameters;
  133. } network_t;
  134. /*
  135. * --------------------- External function prototype ---------------------
  136. */
  137. void network_start();
  138. network_t * network_get_state_machine();
  139. void network_event_simple(network_event_t trigger);
  140. void network_event(network_event_t trigger, void* param);
  141. void network_async_event(network_event_t trigger, void* param);
  142. void network_async(network_event_t trigger);
  143. void network_async_fail();
  144. void network_async_success();
  145. void network_async_link_up();
  146. void network_async_link_down();
  147. void network_async_configure();
  148. void network_async_got_ip();
  149. void network_async_timer();
  150. void network_async_start();
  151. void network_async_scan();
  152. void network_async_scan_done();
  153. void network_async_connect(const char * ssid, const char * password);
  154. void network_async_lost_connection(wifi_event_sta_disconnected_t * disconnected_event);
  155. void network_async_reboot(reboot_type_t rtype);
  156. void network_reboot_ota(char* url);
  157. void network_async_delete();
  158. void network_async_update_status();
  159. void network_async_eth_got_ip();
  160. void network_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
  161. bool network_is_interface_connected(esp_netif_t * interface);
  162. /*
  163. * --------------------- Inline functions ---------------------
  164. */
  165. /**
  166. * @brief Defines the maximum size of a SSID name. 32 is IEEE standard.
  167. * @warning limit is also hard coded in wifi_config_t. Never extend this value.
  168. */
  169. #define MAX_SSID_SIZE 32
  170. /**
  171. * @brief Defines the maximum size of a WPA2 passkey. 64 is IEEE standard.
  172. * @warning limit is also hard coded in wifi_config_t. Never extend this value.
  173. */
  174. #define MAX_PASSWORD_SIZE 64
  175. #define MAX_COMMAND_LINE_SIZE 201
  176. /**
  177. * @brief Defines the maximum number of access points that can be scanned.
  178. *
  179. * To save memory and avoid nasty out of memory errors,
  180. * we can limit the number of APs detected in a wifi scan.
  181. */
  182. #define MAX_AP_NUM 15
  183. /**
  184. * @brief Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up.
  185. * Setting it to 2 for instance means there will be 3 attempts in total (original request + 2 retries)
  186. */
  187. #define WIFI_MANAGER_MAX_RETRY CONFIG_WIFI_MANAGER_MAX_RETRY
  188. /** @brief Defines the task priority of the wifi_manager.
  189. *
  190. * Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1.
  191. * For this particular reason, minimum task priority is 1. It it highly not recommended to set
  192. * it to 1 though as the sub-tasks will now have a priority of 0 which is the priority
  193. * of freeRTOS' idle task.
  194. */
  195. #define WIFI_MANAGER_TASK_PRIORITY CONFIG_WIFI_MANAGER_TASK_PRIORITY
  196. /** @brief Defines the auth mode as an access point
  197. * Value must be of type wifi_auth_mode_t
  198. * @see esp_wifi_types.h
  199. * @warning if set to WIFI_AUTH_OPEN, passowrd me be empty. See DEFAULT_AP_PASSWORD.
  200. */
  201. #define AP_AUTHMODE WIFI_AUTH_WPA2_PSK
  202. /** @brief Defines visibility of the access point. 0: visible AP. 1: hidden */
  203. #define DEFAULT_AP_SSID_HIDDEN 0
  204. /** @brief Defines access point's name. Default value: esp32. Run 'make menuconfig' to setup your own value or replace here by a string */
  205. #define DEFAULT_AP_SSID CONFIG_DEFAULT_AP_SSID
  206. /** @brief Defines access point's password.
  207. * @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.
  208. * In addition, the AP_AUTHMODE must be WIFI_AUTH_OPEN
  209. */
  210. #define DEFAULT_AP_PASSWORD CONFIG_DEFAULT_AP_PASSWORD
  211. /** @brief Defines access point's bandwidth.
  212. * Value: WIFI_BW_HT20 for 20 MHz or WIFI_BW_HT40 for 40 MHz
  213. * 20 MHz minimize channel interference but is not suitable for
  214. * applications with high data speeds
  215. */
  216. #define DEFAULT_AP_BANDWIDTH WIFI_BW_HT20
  217. /** @brief Defines access point's channel.
  218. * Channel selection is only effective when not connected to another AP.
  219. * Good practice for minimal channel interference to use
  220. * For 20 MHz: 1, 6 or 11 in USA and 1, 5, 9 or 13 in most parts of the world
  221. * For 40 MHz: 3 in USA and 3 or 11 in most parts of the world
  222. */
  223. #define DEFAULT_AP_CHANNEL CONFIG_DEFAULT_AP_CHANNEL
  224. /** @brief Defines the access point's default IP address. Default: "10.10.0.1 */
  225. #define DEFAULT_AP_IP CONFIG_DEFAULT_AP_IP
  226. /** @brief Defines the access point's gateway. This should be the same as your IP. Default: "10.10.0.1" */
  227. #define DEFAULT_AP_GATEWAY CONFIG_DEFAULT_AP_GATEWAY
  228. /** @brief Defines the access point's netmask. Default: "255.255.255.0" */
  229. #define DEFAULT_AP_NETMASK CONFIG_DEFAULT_AP_NETMASK
  230. /** @brief Defines access point's maximum number of clients. Default: 4 */
  231. #define DEFAULT_AP_MAX_CONNECTIONS CONFIG_DEFAULT_AP_MAX_CONNECTIONS
  232. /** @brief Defines access point's beacon interval. 100ms is the recommended default. */
  233. #define DEFAULT_AP_BEACON_INTERVAL CONFIG_DEFAULT_AP_BEACON_INTERVAL
  234. /** @brief Defines if esp32 shall run both AP + STA when connected to another AP.
  235. * Value: 0 will have the own AP always on (APSTA mode)
  236. * Value: 1 will turn off own AP when connected to another AP (STA only mode when connected)
  237. * Turning off own AP when connected to another AP minimize channel interference and increase throughput
  238. */
  239. #define DEFAULT_STA_ONLY 1
  240. /** @brief Defines if wifi power save shall be enabled.
  241. * Value: WIFI_PS_NONE for full power (wifi modem always on)
  242. * Value: WIFI_PS_MODEM for power save (wifi modem sleep periodically)
  243. * Note: Power save is only effective when in STA only mode
  244. */
  245. #define DEFAULT_STA_POWER_SAVE WIFI_PS_MIN_MODEM
  246. void network_reboot_ota(char * url);
  247. /**
  248. * @brief simplified reason codes for a lost connection.
  249. *
  250. * esp-idf maintains a big list of reason codes which in practice are useless for most typical application.
  251. * UPDATE_CONNECTION_OK - Web UI expects this when attempting to connect to a new access point succeeds
  252. * UPDATE_FAILED_ATTEMPT - Web UI expects this when attempting to connect to a new access point fails
  253. * UPDATE_USER_DISCONNECT = 2,
  254. * UPDATE_LOST_CONNECTION = 3,
  255. * UPDATE_FAILED_ATTEMPT_AND_RESTORE - Web UI expects this when attempting to connect to a new access point fails and previous connection is restored
  256. * UPDATE_ETHERNET_CONNECTED = 5
  257. */
  258. typedef enum update_reason_code_t {
  259. UPDATE_CONNECTION_OK = 0, // expected when
  260. UPDATE_FAILED_ATTEMPT = 1,
  261. UPDATE_USER_DISCONNECT = 2,
  262. UPDATE_LOST_CONNECTION = 3,
  263. UPDATE_FAILED_ATTEMPT_AND_RESTORE = 4,
  264. UPDATE_ETHERNET_CONNECTED = 5
  265. }update_reason_code_t;
  266. /**
  267. * Frees up all memory allocated by the wifi_manager and kill the task.
  268. */
  269. void network_destroy();
  270. /**
  271. * Filters the AP scan list to unique SSIDs
  272. */
  273. void filter_unique( wifi_ap_record_t * aplist, uint16_t * ap_num);
  274. char* network_status_alloc_get_ap_list_json();
  275. cJSON * network_manager_clear_ap_list_json(cJSON **old);
  276. /**
  277. * @brief A standard wifi event handler as recommended by Espressif
  278. */
  279. esp_err_t network_manager_event_handler(void *ctx, system_event_t *event);
  280. /**
  281. * @brief Clears the connection status json.
  282. * @note This is not thread-safe and should be called only if network_status_lock_json_buffer call is successful.
  283. */
  284. cJSON * network_status_clear_ip_info_json(cJSON **old);
  285. cJSON * network_status_get_new_json(cJSON **old);
  286. /**
  287. * @brief Start the mDNS service
  288. */
  289. void network_manager_initialise_mdns();
  290. /**
  291. * @brief Register a callback to a custom function when specific network manager states are reached.
  292. */
  293. esp_err_t network_register_state_callback(nm_state_t state, int sub_state, const char* from, network_status_reached_cb cb);
  294. bool network_is_wifi_prioritized();
  295. esp_netif_t * network_get_active_interface();
  296. esp_err_t network_get_hostname( const char **hostname);
  297. esp_err_t network_get_ip_info(tcpip_adapter_ip_info_t* ipInfo);
  298. void network_set_timer(uint16_t duration);
  299. void network_set_hostname(esp_netif_t * netif);
  300. esp_err_t network_get_ip_info_for_netif(esp_netif_t* netif, tcpip_adapter_ip_info_t* ipInfo);
  301. void network_start_stop_dhcp(esp_netif_t* netif, bool start);
  302. void network_start_stop_dhcps(esp_netif_t* netif, bool start);
  303. void network_prioritize_wifi(bool activate);
  304. #define ADD_ROOT_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name)
  305. #define ADD_ROOT_LEAF_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name)
  306. #define ADD_LEAF_FORWARD_DECLARATION(name, ...) ADD_STATE_FORWARD_DECLARATION_(name)
  307. #define ADD_STATE_FORWARD_DECLARATION_(name) \
  308. static state_machine_result_t name##_handler(state_machine_t* const State_Machine); \
  309. static state_machine_result_t name##_entry_handler(state_machine_t* const State_Machine); \
  310. static state_machine_result_t name##_exit_handler(state_machine_t* const State_Machine);
  311. void initialize_network_handlers(state_machine_t* state_machine);
  312. 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 );
  313. 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) ;
  314. char* network_manager_alloc_get_mac_string(uint8_t mac[6]);
  315. #if defined(LOG_LOCAL_LEVEL) && LOG_LOCAL_LEVEL >=ESP_LOG_VERBOSE
  316. #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 )
  317. #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)
  318. #define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,__FUNCTION__);
  319. #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__)
  320. #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__)
  321. #define network_handler_print(State_Machine, begin) network_manager_format_state_machine(ESP_LOG_DEBUG,begin?"HANDLER START":"HANDLER END",State_Machine,false,__FUNCTION__)
  322. #elif defined(LOG_LOCAL_LEVEL) && LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG
  323. #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,"")
  324. #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,"")
  325. #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,"")
  326. #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__);
  327. #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)
  328. #else
  329. #define network_exit_handler_print(nm, begin)
  330. #define network_handler_entry_print(State_Machine, begin)
  331. #define network_handler_print(State_Machine, begin)
  332. #define NETWORK_EXECUTE_CB(mch) network_execute_cb(mch,NULL)
  333. #define NETWORK_PRINT_TRANSITION(prefix, source,target, event, print_source,caller )
  334. #define NETWORK_DEBUG_STATE_MACHINE(begin, cb_prefix,state_machine,print_from,caller)
  335. #endif
  336. #ifdef __cplusplus
  337. }
  338. #endif