network_manager_handlers.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  1. #ifdef NETWORK_HANDLERS_LOG_LEVEL
  2. #define LOG_LOCAL_LEVEL NETWORK_HANDLERS_LOG_LEVEL
  3. #endif
  4. #include "network_manager.h"
  5. #include <stdbool.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "network_ethernet.h"
  10. #include "network_status.h"
  11. #include "network_wifi.h"
  12. #include "dns_server.h"
  13. #include "esp_log.h"
  14. #include "esp_system.h"
  15. #include "freertos/FreeRTOS.h"
  16. #include "platform_esp32.h"
  17. #include "esp_netif.h"
  18. #include "freertos/task.h"
  19. #include "cJSON.h"
  20. #include "cmd_system.h"
  21. #include "esp_app_format.h"
  22. #include "esp_event.h"
  23. #include "esp_ota_ops.h"
  24. #include "esp_wifi.h"
  25. #include "esp_wifi_types.h"
  26. #include "lwip/api.h"
  27. #include "lwip/err.h"
  28. #include "lwip/ip4_addr.h"
  29. #include "lwip/netdb.h"
  30. #include "mdns.h"
  31. #include "messaging.h"
  32. #include "platform_config.h"
  33. #include "trace.h"
  34. #include "accessors.h"
  35. #include "esp_err.h"
  36. #include "tools.h"
  37. #include "http_server_handlers.h"
  38. #include "network_manager.h"
  39. static const char TAG[]="network_handlers";
  40. EXT_RAM_ATTR static state_t network_states[TOTAL_NM_STATE];
  41. EXT_RAM_ATTR static state_t Wifi_Active_State[TOTAL_WIFI_ACTIVE_STATE];
  42. EXT_RAM_ATTR static state_t Eth_Active_State[TOTAL_ETH_ACTIVE_STATE];
  43. EXT_RAM_ATTR static state_t Wifi_Configuring_State[TOTAL_WIFI_CONFIGURING_STATE];
  44. static void network_interface_coexistence(state_machine_t* state_machine);
  45. static state_machine_result_t local_traverse_state(state_machine_t* const state_machine,
  46. const state_t* const target_state, const char * caller) ;
  47. static state_machine_result_t local_switch_state(state_machine_t* state_machine,
  48. const state_t* const target_state, const char * caller);
  49. void network_execute_cb(state_machine_t* const state_machine, const char * caller);
  50. int get_root_id(const state_t * state);
  51. const state_t* get_root( const state_t* const state);
  52. #define ADD_ROOT(name,...) ADD_ROOT_FORWARD_DECLARATION(name,...)
  53. #define ADD_ROOT_LEAF(name,...) ADD_ROOT_LEAF_FORWARD_DECLARATION(name,...)
  54. #define ADD_LEAF(name,...) ADD_LEAF_FORWARD_DECLARATION(name,...)
  55. ALL_NM_STATE
  56. ALL_ETH_STATE(, )
  57. ALL_WIFI_STATE(, )
  58. ALL_WIFI_CONFIGURING_STATE(, )
  59. #undef ADD_ROOT
  60. #undef ADD_ROOT_LEAF
  61. #undef ADD_LEAF
  62. /*
  63. * --------------------- Global variables ---------------------
  64. */
  65. #define ADD_ROOT(NAME, CHILD) ADD_ROOT_(NAME, CHILD)
  66. #define ADD_LEAF(NAME, PARENT, LEVEL) ADD_LEAF_(NAME, PARENT, LEVEL)
  67. #define ADD_ROOT_LEAF(NAME) ADD_ROOT_LEAF_(NAME)
  68. #define ADD_ROOT_(NAME, CHILD) \
  69. [NAME] = { \
  70. .Handler = NAME##_handler, \
  71. .Entry = NAME##_entry_handler, \
  72. .Exit = NAME##_exit_handler, \
  73. .Level = 0, \
  74. .Parent = NULL, \
  75. .Id = NAME, \
  76. .Node = CHILD, \
  77. },
  78. #define ADD_ROOT_LEAF_(NAME) \
  79. [NAME] = { \
  80. .Handler = NAME##_handler, \
  81. .Entry = NAME##_entry_handler, \
  82. .Exit = NAME##_exit_handler, \
  83. .Id = NAME, \
  84. .Parent = NULL, \
  85. },
  86. #define ADD_LEAF_(NAME, PARENT, LEVEL) \
  87. [NAME] = { \
  88. .Handler = NAME##_handler, \
  89. .Entry = NAME##_entry_handler, \
  90. .Exit = NAME##_exit_handler, \
  91. .Id = NAME, \
  92. .Level = LEVEL, \
  93. .Parent = PARENT, \
  94. },
  95. static void network_initialize_state_machine_globals(){
  96. static state_t loc_network_states[] =
  97. {
  98. ALL_NM_STATE};
  99. static state_t loc_Wifi_Active_State[] = {
  100. ALL_WIFI_STATE(&network_states[NETWORK_WIFI_ACTIVE_STATE], 1)
  101. };
  102. static state_t loc_Eth_Active_State[]={
  103. ALL_ETH_STATE(&network_states[NETWORK_ETH_ACTIVE_STATE], 1)
  104. };
  105. static state_t loc_Wifi_Configuring_State[]={
  106. ALL_WIFI_CONFIGURING_STATE(&network_states[NETWORK_WIFI_CONFIGURING_ACTIVE_STATE], 1)
  107. };
  108. memcpy(&network_states,&loc_network_states,sizeof(network_states));
  109. memcpy(&Eth_Active_State,&loc_Eth_Active_State,sizeof(Eth_Active_State));
  110. memcpy(&Wifi_Active_State,&loc_Wifi_Active_State,sizeof(Wifi_Active_State));
  111. memcpy(&Wifi_Configuring_State,&loc_Wifi_Configuring_State,sizeof(Wifi_Configuring_State));
  112. }
  113. #undef ADD_ROOT
  114. #undef ADD_ROOT_LEAF
  115. #undef ADD_LEAF
  116. #define HANDLE_GLOBAL_EVENT(m) \
  117. if (handle_global_event(m) == EVENT_HANDLED) \
  118. return EVENT_HANDLED;
  119. static void network_connect_active_ssid(state_machine_t* const State_Machine) {
  120. network_t* const nm = (network_t*)State_Machine;
  121. if (network_wifi_connect_active_ssid() != ESP_OK) {
  122. ESP_LOGE(TAG, "Oups. Something went wrong!");
  123. nm->wifi_connected = false;
  124. ESP_LOGD(TAG, "Checking if ethernet interface is connected");
  125. if (network_is_interface_connected(nm->eth_netif)) {
  126. ESP_LOGD(TAG, "Ethernet connection is found. Try to fallback there");
  127. network_async(EN_ETHERNET_FALLBACK);
  128. } else {
  129. // returning to AP mode
  130. nm->STA_duration = nm->sta_polling_min_ms;
  131. ESP_LOGD(TAG, "No ethernet and no wifi configured. Go to configuration mode");
  132. network_async_configure();
  133. }
  134. }
  135. }
  136. void initialize_network_handlers(state_machine_t* state_machine){
  137. MEMTRACE_PRINT_DELTA();
  138. network_initialize_state_machine_globals();
  139. MEMTRACE_PRINT_DELTA();
  140. NETWORK_INSTANTIATED_STATE_handler(state_machine);
  141. MEMTRACE_PRINT_DELTA();
  142. }
  143. static state_machine_result_t handle_global_event(state_machine_t* state_machine) {
  144. network_t * net_sm= ((network_t *)state_machine);
  145. switch (net_sm->Machine.Event) {
  146. case EN_UPDATE_STATUS:
  147. // handle the event, but don't swicth
  148. MEMTRACE_PRINT_DELTA_MESSAGE("handle EN_UPDATE_STATUS - start");
  149. network_status_update_basic_info();
  150. MEMTRACE_PRINT_DELTA_MESSAGE("handle EN_UPDATE_STATUS - end");
  151. return EVENT_HANDLED;
  152. /* code */
  153. break;
  154. case EN_REBOOT:
  155. ESP_LOGD(TAG,"Called for reboot type %d",net_sm->event_parameters->rtype);
  156. switch (net_sm->event_parameters->rtype) {
  157. case OTA:
  158. ESP_LOGD(TAG, " Calling guided_restart_ota.");
  159. guided_restart_ota();
  160. break;
  161. case RECOVERY:
  162. ESP_LOGD(TAG, " Calling guided_factory.");
  163. guided_factory();
  164. break;
  165. case RESTART:
  166. ESP_LOGD(TAG, " Calling simple_restart.");
  167. simple_restart();
  168. break;
  169. default:
  170. break;
  171. }
  172. return EVENT_UN_HANDLED;
  173. break;
  174. case EN_REBOOT_URL:
  175. if (net_sm->event_parameters->strval) {
  176. start_ota(net_sm->event_parameters->strval, NULL, 0);
  177. FREE_AND_NULL(net_sm->event_parameters->strval);
  178. }
  179. return EVENT_UN_HANDLED;
  180. break;
  181. default:
  182. break;
  183. }
  184. return EVENT_UN_HANDLED;
  185. }
  186. /*********************************************************************************************
  187. * INSTANTIATED_STATE
  188. */
  189. static state_machine_result_t NETWORK_INSTANTIATED_STATE_entry_handler(state_machine_t* const State_Machine) {
  190. network_handler_entry_print(State_Machine,true);
  191. NETWORK_EXECUTE_CB(State_Machine);
  192. network_handler_entry_print(State_Machine,false);
  193. return EVENT_HANDLED;
  194. }
  195. static state_machine_result_t NETWORK_INSTANTIATED_STATE_handler(state_machine_t* const State_Machine) {
  196. network_handler_print(State_Machine,true);
  197. state_machine_result_t result = EVENT_UN_HANDLED;
  198. network_t* const nm = (network_t *)State_Machine;
  199. State_Machine->State = &network_states[NETWORK_INSTANTIATED_STATE];
  200. State_Machine->Event = EN_START;
  201. config_get_uint16t_from_str("pollmx",&nm->sta_polling_max_ms,600);
  202. nm->sta_polling_max_ms = nm->sta_polling_max_ms * 1000;
  203. config_get_uint16t_from_str("apdelay",&nm->ap_duration_ms,20);
  204. nm->ap_duration_ms = nm->ap_duration_ms * 1000;
  205. config_get_uint16t_from_str("pollmin",&nm->sta_polling_min_ms,15);
  206. nm->sta_polling_min_ms = nm->sta_polling_min_ms*1000;
  207. config_get_uint16t_from_str("ethtmout",&nm->eth_link_down_reboot_ms,30);
  208. nm->eth_link_down_reboot_ms = nm->eth_link_down_reboot_ms*1000;
  209. config_get_uint16t_from_str("dhcp_tmout",&nm->dhcp_timeout,30);
  210. nm->dhcp_timeout = nm->dhcp_timeout*1000;
  211. ESP_LOGI(TAG,"Network manager configuration: polling max %d, polling min %d, ap delay %d, dhcp timeout %d, eth timeout %d",
  212. nm->sta_polling_max_ms,nm->sta_polling_min_ms,nm->ap_duration_ms,nm->dhcp_timeout, nm->eth_link_down_reboot_ms);
  213. HANDLE_GLOBAL_EVENT(State_Machine);
  214. if (State_Machine->Event == EN_START) {
  215. result= local_traverse_state(State_Machine, &network_states[NETWORK_INITIALIZING_STATE],__FUNCTION__);
  216. }
  217. network_handler_print(State_Machine,false);
  218. return result;
  219. }
  220. static state_machine_result_t NETWORK_INSTANTIATED_STATE_exit_handler(state_machine_t* const State_Machine) {
  221. network_exit_handler_print(State_Machine,true);
  222. network_exit_handler_print(State_Machine,false);
  223. return EVENT_HANDLED;
  224. }
  225. /*********************************************************************************************
  226. * INITIALIZING_STATE
  227. */
  228. static state_machine_result_t NETWORK_INITIALIZING_STATE_entry_handler(state_machine_t* const State_Machine) {
  229. network_handler_entry_print(State_Machine,true);
  230. MEMTRACE_PRINT_DELTA_MESSAGE(" Initializing tcp_ip adapter");
  231. esp_netif_init();
  232. MEMTRACE_PRINT_DELTA_MESSAGE(" Creating the default event loop");
  233. ESP_ERROR_CHECK(esp_event_loop_create_default());
  234. MEMTRACE_PRINT_DELTA_MESSAGE("Initializing network status");
  235. init_network_status();
  236. MEMTRACE_PRINT_DELTA_MESSAGE("Loading wifi global configuration");
  237. network_wifi_global_init();
  238. MEMTRACE_PRINT_DELTA_MESSAGE(" Registering event handler");
  239. esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &network_ip_event_handler, NULL);
  240. MEMTRACE_PRINT_DELTA_MESSAGE(" Initializing network done. Starting http server");
  241. // send a message to start the connections
  242. http_server_start();
  243. MEMTRACE_PRINT_DELTA_MESSAGE("Executing Callback");
  244. NETWORK_EXECUTE_CB(State_Machine);
  245. network_handler_entry_print(State_Machine,false);
  246. return EVENT_HANDLED;
  247. }
  248. static state_machine_result_t NETWORK_INITIALIZING_STATE_handler(state_machine_t* const State_Machine) {
  249. network_handler_print(State_Machine,true);
  250. state_machine_result_t result = EVENT_UN_HANDLED;
  251. HANDLE_GLOBAL_EVENT(State_Machine);
  252. switch (State_Machine->Event) {
  253. case EN_START:
  254. if (network_is_wifi_prioritized()) {
  255. ESP_LOGI(TAG, "WiFi connection is prioritized. Starting WiFi");
  256. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__);
  257. }
  258. else if(is_recovery_running){
  259. ESP_LOGI(TAG, "Running recovery. Skipping ethernet, starting WiFi");
  260. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__);
  261. }
  262. else {
  263. result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_STARTING_STATE],__FUNCTION__);
  264. }
  265. break;
  266. default:
  267. result= EVENT_UN_HANDLED;
  268. }
  269. network_handler_print(State_Machine,false);
  270. return result;
  271. }
  272. static state_machine_result_t NETWORK_INITIALIZING_STATE_exit_handler(state_machine_t* const State_Machine) {
  273. network_exit_handler_print(State_Machine,true);
  274. network_exit_handler_print(State_Machine,false);
  275. return EVENT_HANDLED;
  276. }
  277. /*********************************************************************************************
  278. * ETH_STARTING_STATE
  279. */
  280. static state_machine_result_t ETH_STARTING_STATE_entry_handler(state_machine_t* const State_Machine) {
  281. network_handler_entry_print(State_Machine,true);
  282. ESP_LOGD(TAG, "Looking for ethernet Interface");
  283. network_t* const nm = (network_t *)State_Machine;
  284. init_network_ethernet();
  285. if (!network_ethernet_enabled()) {
  286. network_async_fail();
  287. } else {
  288. nm->eth_netif = network_ethernet_get_interface();
  289. }
  290. NETWORK_EXECUTE_CB(State_Machine);
  291. network_handler_entry_print(State_Machine,false);
  292. return EVENT_HANDLED;
  293. }
  294. static state_machine_result_t ETH_STARTING_STATE_handler(state_machine_t* const State_Machine) {
  295. state_machine_result_t result = EVENT_HANDLED;
  296. network_handler_print(State_Machine,true);
  297. HANDLE_GLOBAL_EVENT(State_Machine);
  298. switch (State_Machine->Event) {
  299. case EN_FAIL:
  300. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__);
  301. break;
  302. case EN_SUCCESS:
  303. result= local_traverse_state(State_Machine, &network_states[NETWORK_ETH_ACTIVE_STATE],__FUNCTION__);
  304. break;
  305. default:
  306. ESP_LOGE(TAG, "No handler");
  307. result= EVENT_UN_HANDLED;
  308. }
  309. network_handler_print(State_Machine,false);
  310. return result;
  311. }
  312. static state_machine_result_t ETH_STARTING_STATE_exit_handler(state_machine_t* const State_Machine) {
  313. network_exit_handler_print(State_Machine,true);
  314. network_exit_handler_print(State_Machine,false);
  315. return EVENT_HANDLED;
  316. }
  317. /*********************************************************************************************
  318. * NETWORK_ETH_ACTIVE_STATE
  319. */
  320. static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_entry_handler(state_machine_t* const State_Machine) {
  321. network_handler_entry_print(State_Machine,true);
  322. network_t* const nm = (network_t *)State_Machine;
  323. network_set_timer(nm->eth_link_down_reboot_ms,"Ethernet link not detected" );
  324. NETWORK_EXECUTE_CB(State_Machine);
  325. network_handler_entry_print(State_Machine,false);
  326. return EVENT_HANDLED;
  327. }
  328. static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_handler(state_machine_t* const State_Machine) {
  329. network_handler_print(State_Machine,true);
  330. state_machine_result_t result = EVENT_UN_HANDLED;
  331. network_t* const nm = (network_t *)State_Machine;
  332. switch (State_Machine->Event) {
  333. case EN_CONNECT_NEW:
  334. result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_CONNECTING_NEW_STATE],__FUNCTION__);
  335. break;
  336. case EN_LINK_UP:
  337. result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_LINKUP_STATE],__FUNCTION__);
  338. break;
  339. case EN_LINK_DOWN:
  340. result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_LINKDOWN_STATE],__FUNCTION__);
  341. break;
  342. case EN_ETH_GOT_IP:
  343. result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE],__FUNCTION__);
  344. break;
  345. case EN_ETHERNET_FALLBACK:
  346. result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE],__FUNCTION__);
  347. break;
  348. case EN_TIMER:
  349. ESP_LOGW(TAG, "Timeout %s. Rebooting to wifi",STR_OR_ALT(nm->timer_tag,"Ethernet link not detected"));
  350. network_prioritize_wifi(true);
  351. simple_restart();
  352. //result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_INITIALIZING_STATE],__FUNCTION__);
  353. break;
  354. case EN_SCAN:
  355. ESP_LOGW(TAG,"Wifi scan cannot be executed in this state");
  356. network_wifi_built_known_ap_list();
  357. result = EVENT_HANDLED;
  358. break;
  359. case EN_DELETE: {
  360. ESP_LOGD(TAG, "WiFi disconnected by user");
  361. network_wifi_clear_config();
  362. network_status_update_ip_info(UPDATE_USER_DISCONNECT);
  363. result= EVENT_HANDLED;
  364. } break;
  365. default:
  366. HANDLE_GLOBAL_EVENT(State_Machine);
  367. result=EVENT_UN_HANDLED;
  368. }
  369. network_handler_print(State_Machine,false);
  370. return result;
  371. }
  372. static state_machine_result_t NETWORK_ETH_ACTIVE_STATE_exit_handler(state_machine_t* const State_Machine) {
  373. network_exit_handler_print(State_Machine,true);
  374. network_set_timer(0,NULL);
  375. network_exit_handler_print(State_Machine,false);
  376. return EVENT_HANDLED;
  377. }
  378. /*********************************************************************************************
  379. * ETH_CONNECTING_NEW_STATE
  380. */
  381. static state_machine_result_t ETH_CONNECTING_NEW_STATE_entry_handler(state_machine_t* const State_Machine) {
  382. network_t* const nm = (network_t *)State_Machine;
  383. network_handler_entry_print(State_Machine,true);
  384. network_start_stop_dhcp_client(nm->wifi_netif, true);
  385. network_wifi_connect(nm->event_parameters->ssid,nm->event_parameters->password);
  386. FREE_AND_NULL(nm->event_parameters->ssid);
  387. FREE_AND_NULL(nm->event_parameters->password);
  388. NETWORK_EXECUTE_CB(State_Machine);
  389. network_handler_entry_print(State_Machine,false);
  390. return EVENT_HANDLED;
  391. }
  392. static state_machine_result_t ETH_CONNECTING_NEW_STATE_handler(state_machine_t* const State_Machine) {
  393. HANDLE_GLOBAL_EVENT(State_Machine);
  394. network_handler_print(State_Machine,true);
  395. state_machine_result_t result = EVENT_HANDLED;
  396. switch (State_Machine->Event) {
  397. case EN_GOT_IP:
  398. result= local_traverse_state(State_Machine, &network_states[WIFI_CONNECTED_STATE],__FUNCTION__);
  399. break;
  400. case EN_LOST_CONNECTION:
  401. network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
  402. messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to connect to new WiFi access point.");
  403. // no existing configuration, or wifi wasn't the active connection when connection
  404. // attempt was made
  405. network_async(EN_ETHERNET_FALLBACK);
  406. result = EVENT_HANDLED;
  407. break;
  408. default:
  409. result= EVENT_UN_HANDLED;
  410. }
  411. network_handler_print(State_Machine,false);
  412. return result;
  413. }
  414. static state_machine_result_t ETH_CONNECTING_NEW_STATE_exit_handler(state_machine_t* const State_Machine) {
  415. network_exit_handler_print(State_Machine,true);
  416. network_set_timer(0,NULL);
  417. network_exit_handler_print(State_Machine,false);
  418. return EVENT_HANDLED;
  419. }
  420. /*********************************************************************************************
  421. * ETH_ACTIVE_LINKDOWN
  422. */
  423. static state_machine_result_t ETH_ACTIVE_LINKDOWN_STATE_entry_handler(state_machine_t* const State_Machine) {
  424. network_handler_entry_print(State_Machine,true);
  425. network_t* const nm = (network_t *)State_Machine;
  426. network_set_timer(nm->eth_link_down_reboot_ms, "Ethernet link down" );
  427. NETWORK_EXECUTE_CB(State_Machine);
  428. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Ethernet link down.");
  429. network_handler_entry_print(State_Machine,false);
  430. return EVENT_HANDLED;
  431. }
  432. static state_machine_result_t ETH_ACTIVE_LINKDOWN_STATE_handler(state_machine_t* const State_Machine) {
  433. network_handler_print(State_Machine,true);
  434. HANDLE_GLOBAL_EVENT(State_Machine);
  435. network_handler_print(State_Machine,false);
  436. return EVENT_UN_HANDLED;
  437. }
  438. static state_machine_result_t ETH_ACTIVE_LINKDOWN_STATE_exit_handler(state_machine_t* const State_Machine) {
  439. network_exit_handler_print(State_Machine,true);
  440. network_set_timer(0,NULL);
  441. network_exit_handler_print(State_Machine,false);
  442. return EVENT_HANDLED;
  443. }
  444. /*********************************************************************************************
  445. * ETH_ACTIVE_LINKUP_STATE
  446. */
  447. static state_machine_result_t ETH_ACTIVE_LINKUP_STATE_entry_handler(state_machine_t* const State_Machine) {
  448. network_handler_entry_print(State_Machine,true);
  449. network_t* const nm = (network_t *)State_Machine;
  450. network_set_timer(nm->dhcp_timeout, "DHCP timeout" );
  451. NETWORK_EXECUTE_CB(State_Machine);
  452. messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_SYSTEM, "Ethernet link up.");
  453. network_handler_entry_print(State_Machine,false);
  454. return EVENT_HANDLED;
  455. }
  456. static state_machine_result_t ETH_ACTIVE_LINKUP_STATE_handler(state_machine_t* const State_Machine) {
  457. state_machine_result_t result = EVENT_UN_HANDLED;
  458. network_handler_print(State_Machine,true);
  459. HANDLE_GLOBAL_EVENT(State_Machine);
  460. network_handler_print(State_Machine,false);
  461. return result;
  462. }
  463. static state_machine_result_t ETH_ACTIVE_LINKUP_STATE_exit_handler(state_machine_t* const State_Machine) {
  464. network_exit_handler_print(State_Machine,true);
  465. network_exit_handler_print(State_Machine,false);
  466. return EVENT_HANDLED;
  467. }
  468. /*********************************************************************************************
  469. * WIFI_UP_STATE
  470. */
  471. static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_entry_handler(state_machine_t* const State_Machine) {
  472. network_handler_entry_print(State_Machine,true);
  473. NETWORK_EXECUTE_CB(State_Machine);
  474. network_handler_entry_print(State_Machine,false);
  475. return EVENT_HANDLED;
  476. }
  477. static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_handler(state_machine_t* const State_Machine) {
  478. HANDLE_GLOBAL_EVENT(State_Machine);
  479. network_handler_print(State_Machine,true);
  480. state_machine_result_t result = EVENT_UN_HANDLED;
  481. switch (State_Machine->Event)
  482. {
  483. case EN_LINK_UP:
  484. ESP_LOGW(TAG, "Ethernet link up in wifi mode");
  485. break;
  486. case EN_ETH_GOT_IP:
  487. network_interface_coexistence(State_Machine);
  488. break;
  489. case EN_GOT_IP:
  490. network_status_update_ip_info(UPDATE_CONNECTION_OK);
  491. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
  492. break;
  493. case EN_SCAN:
  494. if (network_wifi_start_scan() == ESP_OK) {
  495. result= EVENT_HANDLED;
  496. }
  497. break;
  498. case EN_SCAN_DONE:
  499. if(wifi_scan_done() == ESP_OK) {
  500. result= EVENT_HANDLED;
  501. }
  502. break;
  503. case EN_CONNECT_NEW:
  504. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_NEW_STATE],__FUNCTION__);
  505. break;
  506. case EN_DELETE:
  507. result= local_traverse_state(State_Machine,&Wifi_Active_State[WIFI_USER_DISCONNECTED_STATE],__FUNCTION__);
  508. break;
  509. case EN_ETHERNET_FALLBACK:
  510. result= local_traverse_state(State_Machine, &Eth_Active_State[ETH_ACTIVE_CONNECTED_STATE],__FUNCTION__);
  511. break;
  512. default:
  513. break;
  514. }
  515. network_handler_print(State_Machine,false);
  516. return result;
  517. }
  518. static state_machine_result_t NETWORK_WIFI_ACTIVE_STATE_exit_handler(state_machine_t* const State_Machine) {
  519. network_exit_handler_print(State_Machine,true);
  520. network_exit_handler_print(State_Machine,false);
  521. return EVENT_HANDLED;
  522. }
  523. /*********************************************************************************************
  524. * WIFI_INITIALIZING_STATE
  525. */
  526. static state_machine_result_t WIFI_INITIALIZING_STATE_entry_handler(state_machine_t* const State_Machine) {
  527. network_t* const nm = (network_t *)State_Machine;
  528. network_handler_entry_print(State_Machine,true);
  529. if(!nm->wifi_netif){
  530. nm->wifi_netif = network_wifi_start();
  531. }
  532. if (!is_wifi_up()) {
  533. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Load Configuration");
  534. return EVENT_UN_HANDLED;
  535. }
  536. if (network_wifi_get_known_count()>0) {
  537. ESP_LOGI(TAG, "Existing wifi config found. Attempting to connect.");
  538. network_async_success();
  539. } else {
  540. /* no wifi saved: start soft AP! This is what should happen during a first run */
  541. ESP_LOGW(TAG, "No saved wifi. Starting AP configuration mode.");
  542. network_async_configure();
  543. }
  544. NETWORK_EXECUTE_CB(State_Machine);
  545. network_handler_entry_print(State_Machine,false);
  546. return EVENT_HANDLED;
  547. }
  548. static state_machine_result_t WIFI_INITIALIZING_STATE_handler(state_machine_t* const State_Machine) {
  549. HANDLE_GLOBAL_EVENT(State_Machine);
  550. network_handler_print(State_Machine,true);
  551. state_machine_result_t result = EVENT_HANDLED;
  552. switch (State_Machine->Event) {
  553. case EN_CONFIGURE:
  554. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
  555. break;
  556. case EN_SUCCESS:
  557. result= local_switch_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_STATE],__FUNCTION__);
  558. break;
  559. default:
  560. result= EVENT_UN_HANDLED;
  561. }
  562. network_handler_print(State_Machine,false);
  563. return result;
  564. }
  565. static state_machine_result_t WIFI_INITIALIZING_STATE_exit_handler(state_machine_t* const State_Machine) {
  566. network_exit_handler_print(State_Machine,true);
  567. network_exit_handler_print(State_Machine,false);
  568. return EVENT_HANDLED;
  569. }
  570. /*********************************************************************************************
  571. * WIFI_CONFIGURING_ACTIVE_STATE
  572. */
  573. static state_machine_result_t NETWORK_WIFI_CONFIGURING_ACTIVE_STATE_entry_handler(state_machine_t* const State_Machine) {
  574. network_handler_entry_print(State_Machine,true);
  575. network_t* const nm = (network_t *)State_Machine;
  576. nm->wifi_ap_netif = network_wifi_config_ap();
  577. dns_server_start(nm->wifi_ap_netif);
  578. network_wifi_start_scan();
  579. network_handler_entry_print(State_Machine,false);
  580. return EVENT_HANDLED;
  581. }
  582. static state_machine_result_t NETWORK_WIFI_CONFIGURING_ACTIVE_STATE_handler(state_machine_t* const State_Machine) {
  583. HANDLE_GLOBAL_EVENT(State_Machine);
  584. network_handler_print(State_Machine,true);
  585. state_machine_result_t result = EVENT_HANDLED;
  586. switch (State_Machine->Event) {
  587. case EN_SCAN:
  588. if (network_wifi_start_scan() == ESP_OK) {
  589. result= EVENT_HANDLED;
  590. }
  591. break;
  592. case EN_SCAN_DONE:
  593. ESP_LOGD(TAG,"Network configuration active, wifi scan completed");
  594. if(wifi_scan_done() == ESP_OK) {
  595. result= EVENT_HANDLED;
  596. }
  597. break;
  598. case EN_CONNECT_NEW:
  599. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_STATE],__FUNCTION__);
  600. break;
  601. case EN_LINK_UP:
  602. ESP_LOGW(TAG, "Ethernet link up in wifi mode");
  603. break;
  604. case EN_ETH_GOT_IP:
  605. network_interface_coexistence(State_Machine);
  606. break;
  607. default:
  608. result =EVENT_UN_HANDLED;
  609. }
  610. network_handler_print(State_Machine,false);
  611. return result;
  612. }
  613. static state_machine_result_t NETWORK_WIFI_CONFIGURING_ACTIVE_STATE_exit_handler(state_machine_t* const State_Machine) {
  614. network_exit_handler_print(State_Machine, true);
  615. /* bring down DNS hijack */
  616. ESP_LOGD(TAG, " Stopping DNS.");
  617. dns_server_stop();
  618. ESP_LOGD(TAG, "Changing wifi mode to STA.");
  619. network_wifi_set_sta_mode();
  620. network_exit_handler_print(State_Machine, false);
  621. return EVENT_HANDLED;
  622. }
  623. /*********************************************************************************************
  624. * WIFI_CONFIGURING_STATE
  625. */
  626. static state_machine_result_t WIFI_CONFIGURING_STATE_entry_handler(state_machine_t* const State_Machine) {
  627. network_handler_entry_print(State_Machine,true);
  628. NETWORK_EXECUTE_CB(State_Machine);
  629. network_handler_entry_print(State_Machine,false);
  630. return EVENT_HANDLED;
  631. }
  632. static state_machine_result_t WIFI_CONFIGURING_STATE_handler(state_machine_t* const State_Machine) {
  633. network_handler_print(State_Machine,true);
  634. HANDLE_GLOBAL_EVENT(State_Machine);
  635. network_handler_print(State_Machine,false);
  636. return EVENT_UN_HANDLED;
  637. }
  638. static state_machine_result_t WIFI_CONFIGURING_STATE_exit_handler(state_machine_t* const State_Machine) {
  639. network_exit_handler_print(State_Machine,true);
  640. network_exit_handler_print(State_Machine,false);
  641. return EVENT_HANDLED;
  642. }
  643. /*********************************************************************************************
  644. * WIFI_CONFIGURING_CONNECT_STATE
  645. */
  646. static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_entry_handler(state_machine_t* const State_Machine) {
  647. network_t* const nm = (network_t *)State_Machine;
  648. network_handler_entry_print(State_Machine,true);
  649. network_start_stop_dhcp_client(nm->wifi_netif, true);
  650. network_wifi_connect(nm->event_parameters->ssid,nm->event_parameters->password);
  651. FREE_AND_NULL(nm->event_parameters->ssid);
  652. FREE_AND_NULL(nm->event_parameters->password);
  653. NETWORK_EXECUTE_CB(State_Machine);
  654. network_handler_entry_print(State_Machine,false);
  655. return EVENT_HANDLED;
  656. }
  657. static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_handler(state_machine_t* const State_Machine) {
  658. HANDLE_GLOBAL_EVENT(State_Machine);
  659. network_handler_print(State_Machine,true);
  660. network_t* const nm = (network_t *)State_Machine;
  661. state_machine_result_t result = EVENT_HANDLED;
  662. switch (State_Machine->Event) {
  663. case EN_CONNECTED:
  664. result=EVENT_HANDLED;
  665. ESP_LOGI(TAG,"Wifi was connected. Waiting for IP address");
  666. network_set_timer(nm->dhcp_timeout,"DHCP Timeout");
  667. break;
  668. case EN_GOT_IP:
  669. network_status_update_ip_info(UPDATE_CONNECTION_OK);
  670. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_CONNECT_SUCCESS_STATE],__FUNCTION__);
  671. break;
  672. case EN_LOST_CONNECTION:
  673. if(nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE) {
  674. ESP_LOGI(TAG,"Wifi was disconnected from previous access point. Waiting to connect.");
  675. }
  676. else {
  677. network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
  678. result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
  679. }
  680. break;
  681. case EN_TIMER:
  682. ESP_LOGW(TAG,"Connection timeout. (%s)",STR_OR_ALT(nm->timer_tag, "Unknown"));
  683. network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
  684. result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
  685. break;
  686. default:
  687. result= EVENT_UN_HANDLED;
  688. }
  689. network_handler_print(State_Machine,false);
  690. return result;
  691. }
  692. static state_machine_result_t WIFI_CONFIGURING_CONNECT_STATE_exit_handler(state_machine_t* const State_Machine) {
  693. network_exit_handler_print(State_Machine,true);
  694. FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event);
  695. network_set_timer(0,NULL);
  696. network_exit_handler_print(State_Machine,false);
  697. return EVENT_HANDLED;
  698. }
  699. /*********************************************************************************************
  700. * WIFI_CONFIGURING_CONNECT_SUCCESS_STATE
  701. */
  702. static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_entry_handler(state_machine_t* const State_Machine) {
  703. network_handler_entry_print(State_Machine,true);
  704. network_status_update_ip_info(UPDATE_CONNECTION_OK);
  705. ESP_LOGD(TAG, "Saving wifi configuration.");
  706. network_wifi_save_sta_config();
  707. NETWORK_EXECUTE_CB(State_Machine);
  708. network_handler_entry_print(State_Machine,false);
  709. return EVENT_HANDLED;
  710. }
  711. static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_handler(state_machine_t* const State_Machine) {
  712. network_handler_print(State_Machine,true);
  713. state_machine_result_t result = EVENT_HANDLED;
  714. network_t* const nm = (network_t *)State_Machine;
  715. switch (State_Machine->Event) {
  716. case EN_UPDATE_STATUS:
  717. network_status_update_basic_info();
  718. network_set_timer(nm->ap_duration_ms,"Access point teardown"); // set a timer to tear down the AP mode
  719. break;
  720. case EN_TIMER:
  721. network_status_update_basic_info();
  722. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
  723. break;
  724. default:
  725. result= EVENT_UN_HANDLED;
  726. }
  727. // Process global handler at the end, since we want to overwrite
  728. // UPDATE_STATUS with our own logic above
  729. HANDLE_GLOBAL_EVENT(State_Machine);
  730. network_handler_print(State_Machine,false);
  731. return result;
  732. }
  733. static state_machine_result_t WIFI_CONFIGURING_CONNECT_SUCCESS_STATE_exit_handler(state_machine_t* const State_Machine) {
  734. network_exit_handler_print(State_Machine,true);
  735. network_set_timer(0,NULL);
  736. network_exit_handler_print(State_Machine,false);
  737. return EVENT_HANDLED;
  738. }
  739. /*********************************************************************************************
  740. * WIFI_CONNECTING_STATE
  741. */
  742. static state_machine_result_t WIFI_CONNECTING_STATE_entry_handler(state_machine_t* const State_Machine) {
  743. network_t* const nm = (network_t *)State_Machine;
  744. network_handler_entry_print(State_Machine,true);
  745. network_start_stop_dhcp_client(nm->wifi_netif, true);
  746. network_connect_active_ssid(State_Machine);
  747. nm->STA_duration = nm->sta_polling_min_ms;
  748. /* create timer for background STA connection */
  749. network_set_timer(nm->STA_duration,"Wifi Polling timeout");
  750. NETWORK_EXECUTE_CB(State_Machine);
  751. network_handler_entry_print(State_Machine,false);
  752. return EVENT_HANDLED;
  753. }
  754. static state_machine_result_t WIFI_CONNECTING_STATE_handler(state_machine_t* const State_Machine) {
  755. HANDLE_GLOBAL_EVENT(State_Machine);
  756. state_machine_result_t result = EVENT_HANDLED;
  757. network_t* const nm = (network_t *)State_Machine;
  758. network_handler_print(State_Machine,true);
  759. switch (State_Machine->Event) {
  760. case EN_CONNECTED:
  761. // nothing to do here. Let's wait for IP address
  762. break;
  763. case EN_TIMER:
  764. // try connecting again.
  765. // todo: implement multi-ap logic
  766. ESP_LOGI(TAG, "Timer: %s ",STR_OR_ALT(nm->timer_tag,"Ethernet link not detected"));
  767. network_connect_active_ssid(State_Machine);
  768. break;
  769. default:
  770. result = EVENT_UN_HANDLED;
  771. }
  772. network_handler_print(State_Machine,false);
  773. return result;
  774. }
  775. static state_machine_result_t WIFI_CONNECTING_STATE_exit_handler(state_machine_t* const State_Machine) {
  776. network_exit_handler_print(State_Machine,true);
  777. network_exit_handler_print(State_Machine,false);
  778. return EVENT_HANDLED;
  779. }
  780. /*********************************************************************************************
  781. * WIFI_CONNECTING_NEW_STATE
  782. */
  783. static state_machine_result_t WIFI_CONNECTING_NEW_STATE_entry_handler(state_machine_t* const State_Machine) {
  784. network_t* const nm = (network_t *)State_Machine;
  785. network_handler_entry_print(State_Machine,true);
  786. network_start_stop_dhcp_client(nm->wifi_netif, true);
  787. network_wifi_connect(nm->event_parameters->ssid,nm->event_parameters->password);
  788. FREE_AND_NULL(nm->event_parameters->ssid);
  789. FREE_AND_NULL(nm->event_parameters->password);
  790. NETWORK_EXECUTE_CB(State_Machine);
  791. network_handler_entry_print(State_Machine,false);
  792. return EVENT_HANDLED;
  793. }
  794. static state_machine_result_t WIFI_CONNECTING_NEW_STATE_handler(state_machine_t* const State_Machine) {
  795. HANDLE_GLOBAL_EVENT(State_Machine);
  796. network_handler_print(State_Machine,true);
  797. state_machine_result_t result = EVENT_HANDLED;
  798. switch (State_Machine->Event) {
  799. case EN_GOT_IP:
  800. network_status_update_ip_info(UPDATE_CONNECTION_OK);
  801. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
  802. break;
  803. case EN_CONNECTED:
  804. ESP_LOGD(TAG,"Successfully connected to the new access point. Waiting for IP Address");
  805. result = EVENT_HANDLED;
  806. break;
  807. case EN_LOST_CONNECTION:
  808. if(((network_t *)State_Machine)->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE){
  809. ESP_LOGD(TAG,"Successfully disconnected from the existing access point. ");
  810. return EVENT_HANDLED;
  811. }
  812. ESP_LOGW(TAG,"Trying to connect failed");
  813. result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_NEW_FAILED_STATE],__FUNCTION__);
  814. break;
  815. default:
  816. result= EVENT_UN_HANDLED;
  817. }
  818. network_handler_print(State_Machine,false);
  819. return result;
  820. }
  821. static state_machine_result_t WIFI_CONNECTING_NEW_STATE_exit_handler(state_machine_t* const State_Machine) {
  822. network_exit_handler_print(State_Machine,true);
  823. network_set_timer(0,NULL);
  824. FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event);
  825. network_exit_handler_print(State_Machine,false);
  826. return EVENT_HANDLED;
  827. }
  828. /*********************************************************************************************
  829. * WIFI_CONNECTING_NEW_FAILED_STATE
  830. */
  831. static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_entry_handler(state_machine_t* const State_Machine) {
  832. network_t* const nm = (network_t *)State_Machine;
  833. network_handler_entry_print(State_Machine,true);
  834. if (nm->wifi_connected ) {
  835. // Wifi was already connected to an existing access point. Restore connection
  836. network_connect_active_ssid(State_Machine);
  837. }
  838. NETWORK_EXECUTE_CB(State_Machine);
  839. network_handler_entry_print(State_Machine,false);
  840. return EVENT_HANDLED;
  841. }
  842. static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_handler(state_machine_t* const State_Machine) {
  843. HANDLE_GLOBAL_EVENT(State_Machine);
  844. network_handler_print(State_Machine,true);
  845. state_machine_result_t result = EVENT_HANDLED;
  846. switch (State_Machine->Event) {
  847. case EN_GOT_IP:
  848. network_status_update_ip_info(UPDATE_FAILED_ATTEMPT_AND_RESTORE);
  849. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
  850. break;
  851. case EN_CONNECTED:
  852. ESP_LOGD(TAG,"Successfully connected to the previous access point. Waiting for IP Address");
  853. result = EVENT_HANDLED;
  854. break;
  855. case EN_LOST_CONNECTION:
  856. network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
  857. messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to fall back to previous access point.");
  858. result = EVENT_HANDLED;
  859. break;
  860. default:
  861. result= EVENT_UN_HANDLED;
  862. }
  863. network_handler_print(State_Machine,false);
  864. return result;
  865. }
  866. static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_exit_handler(state_machine_t* const State_Machine) {
  867. network_exit_handler_print(State_Machine,true);
  868. network_set_timer(0,NULL);
  869. FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event);
  870. network_exit_handler_print(State_Machine,false);
  871. return EVENT_HANDLED;
  872. }
  873. /*********************************************************************************************
  874. * WIFI_CONNECTED_STATE
  875. */
  876. static state_machine_result_t WIFI_CONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) {
  877. network_t* const nm = (network_t *)State_Machine;
  878. network_handler_entry_print(State_Machine,true);
  879. nm->last_connected = esp_timer_get_time();
  880. // cancel timeout pulse
  881. network_set_timer(0,NULL);
  882. ESP_LOGD(TAG, "Checking if wifi config changed.");
  883. if (network_wifi_sta_config_changed()) {
  884. ESP_LOGD(TAG, "Wifi Config changed. Saving it.");
  885. network_wifi_save_sta_config();
  886. }
  887. ESP_LOGD(TAG, "Updating the ip info json.");
  888. network_interface_coexistence(State_Machine);
  889. nm->wifi_connected = true;
  890. NETWORK_EXECUTE_CB(State_Machine);
  891. network_handler_entry_print(State_Machine,false);
  892. return EVENT_HANDLED;
  893. }
  894. static state_machine_result_t WIFI_CONNECTED_STATE_handler(state_machine_t* const State_Machine) {
  895. HANDLE_GLOBAL_EVENT(State_Machine);
  896. network_handler_print(State_Machine,true);
  897. state_machine_result_t result = EVENT_HANDLED;
  898. switch (State_Machine->Event) {
  899. case EN_LOST_CONNECTION:
  900. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_LOST_CONNECTION_STATE],__FUNCTION__);
  901. break;
  902. default:
  903. result = EVENT_UN_HANDLED;
  904. break;
  905. }
  906. network_handler_print(State_Machine,false);
  907. return result;
  908. }
  909. static state_machine_result_t WIFI_CONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) {
  910. network_exit_handler_print(State_Machine,true);
  911. FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event);
  912. network_exit_handler_print(State_Machine,false);
  913. return EVENT_HANDLED;
  914. }
  915. /*********************************************************************************************
  916. * WIFI_USER_DISCONNECTED_STATE
  917. */
  918. static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) {
  919. network_handler_entry_print(State_Machine,true);
  920. ESP_LOGD(TAG, " WiFi disconnected by user");
  921. network_wifi_clear_config();
  922. network_status_update_ip_info(UPDATE_USER_DISCONNECT);
  923. NETWORK_EXECUTE_CB(State_Machine);
  924. network_handler_entry_print(State_Machine,false);
  925. return EVENT_HANDLED;
  926. }
  927. static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_handler(state_machine_t* const State_Machine) {
  928. HANDLE_GLOBAL_EVENT(State_Machine);
  929. network_handler_print(State_Machine,true);
  930. state_machine_result_t result = EVENT_HANDLED;
  931. switch (State_Machine->Event) {
  932. case EN_LOST_CONNECTION:
  933. // this is a success! we're actually asking to disconnect
  934. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
  935. break;
  936. default:
  937. result= EVENT_UN_HANDLED;
  938. }
  939. network_handler_print(State_Machine,false);
  940. return result;
  941. }
  942. static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) {
  943. network_exit_handler_print(State_Machine,true);
  944. network_exit_handler_print(State_Machine,false);
  945. return EVENT_HANDLED;
  946. }
  947. /*********************************************************************************************
  948. * WIFI_LOST_CONNECTION_STATE
  949. */
  950. static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_machine_t* const State_Machine) {
  951. network_t* const nm = (network_t *)State_Machine;
  952. network_handler_entry_print(State_Machine,true);
  953. ESP_LOGE(TAG, " WiFi Connection lost.");
  954. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "WiFi Connection lost");
  955. network_status_update_ip_info(UPDATE_LOST_CONNECTION);
  956. network_status_safe_reset_sta_ip_string();
  957. if (nm->last_connected > 0)
  958. nm->total_connected_time += ((esp_timer_get_time() - nm->last_connected) / (1000 * 1000));
  959. nm->last_connected = 0;
  960. nm->num_disconnect++;
  961. ESP_LOGW(TAG, " Wifi disconnected. Number of disconnects: %d, Average time connected: %d", nm->num_disconnect, nm->num_disconnect > 0 ? (nm->total_connected_time / nm->num_disconnect) : 0);
  962. if (nm->retries < WIFI_MANAGER_MAX_RETRY) {
  963. nm->retries++;
  964. ESP_LOGD(TAG, " Retrying connection connection, %d/%d.", nm->retries, WIFI_MANAGER_MAX_RETRY);
  965. network_connect_active_ssid( State_Machine);
  966. } else {
  967. /* In this scenario the connection was lost beyond repair */
  968. nm->retries = 0;
  969. ESP_LOGD(TAG,"Checking if ethernet interface is connected");
  970. if (network_is_interface_connected(nm->eth_netif)) {
  971. ESP_LOGW(TAG, "Cannot connect to Wifi. Falling back to Ethernet ");
  972. network_async(EN_ETHERNET_FALLBACK);
  973. } else {
  974. network_status_update_ip_info(UPDATE_LOST_CONNECTION);
  975. wifi_mode_t mode;
  976. ESP_LOGW(TAG, " All connect retry attempts failed.");
  977. /* put us in softAP mode first */
  978. esp_wifi_get_mode(&mode);
  979. if (WIFI_MODE_APSTA != mode) {
  980. nm->STA_duration = nm->sta_polling_min_ms;
  981. network_async_configure();
  982. } else if (nm->STA_duration < nm->sta_polling_max_ms) {
  983. nm->STA_duration *= 1.25;
  984. }
  985. /* keep polling for existing connection */
  986. network_set_timer(nm->STA_duration, "Wifi Polling timeout");
  987. ESP_LOGD(TAG, " STA search slow polling of %d", nm->STA_duration);
  988. }
  989. }
  990. NETWORK_EXECUTE_CB(State_Machine);
  991. network_handler_entry_print(State_Machine,false);
  992. return EVENT_HANDLED;
  993. }
  994. static state_machine_result_t WIFI_LOST_CONNECTION_STATE_handler(state_machine_t* const State_Machine) {
  995. HANDLE_GLOBAL_EVENT(State_Machine);
  996. network_t* const nm = (network_t *)State_Machine;
  997. state_machine_result_t result = EVENT_HANDLED;
  998. network_handler_print(State_Machine,true);
  999. switch (State_Machine->Event) {
  1000. case EN_CONFIGURE:
  1001. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
  1002. break;
  1003. case EN_TIMER:
  1004. ESP_LOGI(TAG, "Timer: %s ",STR_OR_ALT(nm->timer_tag,"Lost connection"));
  1005. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_LOST_CONNECTION_STATE],__FUNCTION__);
  1006. break;
  1007. case EN_CONNECT:
  1008. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONNECTING_STATE],__FUNCTION__);
  1009. break;
  1010. default:
  1011. result= EVENT_UN_HANDLED;
  1012. }
  1013. network_handler_print(State_Machine,false);
  1014. return result;
  1015. }
  1016. static state_machine_result_t WIFI_LOST_CONNECTION_STATE_exit_handler(state_machine_t* const State_Machine) {
  1017. network_exit_handler_print(State_Machine,true);
  1018. network_exit_handler_print(State_Machine,false);
  1019. return EVENT_HANDLED;
  1020. }
  1021. /*********************************************************************************************
  1022. * ETH_ACTIVE_CONNECTED_STATE
  1023. */
  1024. static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) {
  1025. network_t* const nm = (network_t *)State_Machine;
  1026. network_handler_entry_print(State_Machine,true);
  1027. network_status_update_ip_info(UPDATE_ETHERNET_CONNECTED);
  1028. nm->ethernet_connected = true;
  1029. // start a wifi Scan so web ui is populated with available entries
  1030. NETWORK_EXECUTE_CB(State_Machine);
  1031. network_handler_entry_print(State_Machine,false);
  1032. return EVENT_HANDLED;
  1033. }
  1034. static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_handler(state_machine_t* const State_Machine) {
  1035. HANDLE_GLOBAL_EVENT(State_Machine);
  1036. state_machine_result_t result = EVENT_HANDLED;
  1037. network_handler_print(State_Machine,true);
  1038. switch (State_Machine->Event) {
  1039. case EN_TIMER:
  1040. ESP_LOGD(TAG, "Ignoring ethernet link up timer check");
  1041. result= EVENT_HANDLED;
  1042. break;
  1043. default:
  1044. result= EVENT_UN_HANDLED;
  1045. }
  1046. network_handler_print(State_Machine,false);
  1047. return result;
  1048. }
  1049. static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) {
  1050. network_exit_handler_print(State_Machine,true);
  1051. network_exit_handler_print(State_Machine,false);
  1052. return EVENT_HANDLED;
  1053. }
  1054. static state_machine_result_t local_switch_state(state_machine_t* state_machine,
  1055. const state_t* const target_state, const char * caller) {
  1056. const state_t* source = state_machine->State;
  1057. NETWORK_PRINT_TRANSITION(true, "BEGIN SWITCH", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller);
  1058. state_machine_result_t result = switch_state(state_machine, target_state);
  1059. NETWORK_PRINT_TRANSITION( false,"BEGIN SWITCH", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller);
  1060. ((network_t *)state_machine)->source_state = source;
  1061. return result;
  1062. }
  1063. static state_machine_result_t local_traverse_state(state_machine_t* const state_machine,
  1064. const state_t* const target_state, const char * caller) {
  1065. const state_t * source = state_machine->State;
  1066. NETWORK_PRINT_TRANSITION( true,"BEGIN TRAVERSE", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true, caller);
  1067. state_machine_result_t result = traverse_state(state_machine, target_state);
  1068. NETWORK_PRINT_TRANSITION( false,"END TRAVERSE", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller);
  1069. ((network_t *)state_machine)->source_state = source;
  1070. return result;
  1071. }
  1072. static void network_interface_coexistence(state_machine_t* state_machine) {
  1073. // this function is called whenever both wifi and ethernet are
  1074. // found to be active at the same time
  1075. network_t* nm = (network_t *)state_machine;
  1076. if (nm->wifi_connected && state_machine->Event == EN_ETH_GOT_IP) {
  1077. char* eth_reboot = config_alloc_get_default(NVS_TYPE_STR, "eth_boot", "N", 0);
  1078. network_prioritize_wifi(false);
  1079. if (strcasecmp(eth_reboot, "N")) {
  1080. ESP_LOGW(TAG, "Option eth_reboot set to reboot when ethernet is connected. Rebooting");
  1081. simple_restart();
  1082. } else {
  1083. ESP_LOGW(TAG, "Option eth_reboot set to not reboot when ethernet is connected. Using Wifi interface until next reboot");
  1084. }
  1085. FREE_AND_NULL(eth_reboot);
  1086. } else if (get_root(state_machine->State)->Id == NETWORK_ETH_ACTIVE_STATE){
  1087. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi Connected with Ethernet active. System reload needed");
  1088. simple_restart();
  1089. }
  1090. }