network_manager_handlers.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  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. case EN_LOST_CONNECTION:
  770. if(nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE || nm->event_parameters->disconnected_event->reason == WIFI_REASON_AUTH_EXPIRE || nm->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_EXPIRE) {
  771. ESP_LOGI(TAG,"Wifi was disconnected from previous access point. Waiting to connect.");
  772. }
  773. else if(nm->event_parameters->disconnected_event->reason != WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) {
  774. network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
  775. result = local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
  776. }
  777. break;
  778. default:
  779. result = EVENT_UN_HANDLED;
  780. }
  781. network_handler_print(State_Machine,false);
  782. return result;
  783. }
  784. static state_machine_result_t WIFI_CONNECTING_STATE_exit_handler(state_machine_t* const State_Machine) {
  785. network_exit_handler_print(State_Machine,true);
  786. network_exit_handler_print(State_Machine,false);
  787. return EVENT_HANDLED;
  788. }
  789. /*********************************************************************************************
  790. * WIFI_CONNECTING_NEW_STATE
  791. */
  792. static state_machine_result_t WIFI_CONNECTING_NEW_STATE_entry_handler(state_machine_t* const State_Machine) {
  793. network_t* const nm = (network_t *)State_Machine;
  794. network_handler_entry_print(State_Machine,true);
  795. network_start_stop_dhcp_client(nm->wifi_netif, true);
  796. network_wifi_connect(nm->event_parameters->ssid,nm->event_parameters->password);
  797. FREE_AND_NULL(nm->event_parameters->ssid);
  798. FREE_AND_NULL(nm->event_parameters->password);
  799. NETWORK_EXECUTE_CB(State_Machine);
  800. network_handler_entry_print(State_Machine,false);
  801. return EVENT_HANDLED;
  802. }
  803. static state_machine_result_t WIFI_CONNECTING_NEW_STATE_handler(state_machine_t* const State_Machine) {
  804. HANDLE_GLOBAL_EVENT(State_Machine);
  805. network_handler_print(State_Machine,true);
  806. state_machine_result_t result = EVENT_HANDLED;
  807. switch (State_Machine->Event) {
  808. case EN_GOT_IP:
  809. network_status_update_ip_info(UPDATE_CONNECTION_OK);
  810. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
  811. break;
  812. case EN_CONNECTED:
  813. ESP_LOGD(TAG,"Successfully connected to the new access point. Waiting for IP Address");
  814. result = EVENT_HANDLED;
  815. break;
  816. case EN_LOST_CONNECTION:
  817. if(((network_t *)State_Machine)->event_parameters->disconnected_event->reason == WIFI_REASON_ASSOC_LEAVE){
  818. ESP_LOGD(TAG,"Successfully disconnected from the existing access point. ");
  819. return EVENT_HANDLED;
  820. }
  821. ESP_LOGW(TAG,"Trying to connect failed");
  822. result = local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTING_NEW_FAILED_STATE],__FUNCTION__);
  823. break;
  824. default:
  825. result= EVENT_UN_HANDLED;
  826. }
  827. network_handler_print(State_Machine,false);
  828. return result;
  829. }
  830. static state_machine_result_t WIFI_CONNECTING_NEW_STATE_exit_handler(state_machine_t* const State_Machine) {
  831. network_exit_handler_print(State_Machine,true);
  832. network_set_timer(0,NULL);
  833. FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event);
  834. network_exit_handler_print(State_Machine,false);
  835. return EVENT_HANDLED;
  836. }
  837. /*********************************************************************************************
  838. * WIFI_CONNECTING_NEW_FAILED_STATE
  839. */
  840. static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_entry_handler(state_machine_t* const State_Machine) {
  841. network_t* const nm = (network_t *)State_Machine;
  842. network_handler_entry_print(State_Machine,true);
  843. if (nm->wifi_connected ) {
  844. // Wifi was already connected to an existing access point. Restore connection
  845. network_connect_active_ssid(State_Machine);
  846. }
  847. NETWORK_EXECUTE_CB(State_Machine);
  848. network_handler_entry_print(State_Machine,false);
  849. return EVENT_HANDLED;
  850. }
  851. static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_handler(state_machine_t* const State_Machine) {
  852. HANDLE_GLOBAL_EVENT(State_Machine);
  853. network_handler_print(State_Machine,true);
  854. state_machine_result_t result = EVENT_HANDLED;
  855. switch (State_Machine->Event) {
  856. case EN_GOT_IP:
  857. network_status_update_ip_info(UPDATE_FAILED_ATTEMPT_AND_RESTORE);
  858. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_CONNECTED_STATE],__FUNCTION__);
  859. break;
  860. case EN_CONNECTED:
  861. ESP_LOGD(TAG,"Successfully connected to the previous access point. Waiting for IP Address");
  862. result = EVENT_HANDLED;
  863. break;
  864. case EN_LOST_CONNECTION:
  865. network_status_update_ip_info(UPDATE_FAILED_ATTEMPT);
  866. messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "Unable to fall back to previous access point.");
  867. result = EVENT_HANDLED;
  868. break;
  869. default:
  870. result= EVENT_UN_HANDLED;
  871. }
  872. network_handler_print(State_Machine,false);
  873. return result;
  874. }
  875. static state_machine_result_t WIFI_CONNECTING_NEW_FAILED_STATE_exit_handler(state_machine_t* const State_Machine) {
  876. network_exit_handler_print(State_Machine,true);
  877. network_set_timer(0,NULL);
  878. FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event);
  879. network_exit_handler_print(State_Machine,false);
  880. return EVENT_HANDLED;
  881. }
  882. /*********************************************************************************************
  883. * WIFI_CONNECTED_STATE
  884. */
  885. static state_machine_result_t WIFI_CONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) {
  886. network_t* const nm = (network_t *)State_Machine;
  887. network_handler_entry_print(State_Machine,true);
  888. nm->last_connected = esp_timer_get_time();
  889. // cancel timeout pulse
  890. network_set_timer(0,NULL);
  891. ESP_LOGD(TAG, "Checking if wifi config changed.");
  892. if (network_wifi_sta_config_changed()) {
  893. ESP_LOGD(TAG, "Wifi Config changed. Saving it.");
  894. network_wifi_save_sta_config();
  895. }
  896. ESP_LOGD(TAG, "Updating the ip info json.");
  897. network_interface_coexistence(State_Machine);
  898. nm->wifi_connected = true;
  899. NETWORK_EXECUTE_CB(State_Machine);
  900. network_handler_entry_print(State_Machine,false);
  901. return EVENT_HANDLED;
  902. }
  903. static state_machine_result_t WIFI_CONNECTED_STATE_handler(state_machine_t* const State_Machine) {
  904. HANDLE_GLOBAL_EVENT(State_Machine);
  905. network_handler_print(State_Machine,true);
  906. state_machine_result_t result = EVENT_HANDLED;
  907. switch (State_Machine->Event) {
  908. case EN_LOST_CONNECTION:
  909. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_LOST_CONNECTION_STATE],__FUNCTION__);
  910. break;
  911. default:
  912. result = EVENT_UN_HANDLED;
  913. break;
  914. }
  915. network_handler_print(State_Machine,false);
  916. return result;
  917. }
  918. static state_machine_result_t WIFI_CONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) {
  919. network_exit_handler_print(State_Machine,true);
  920. FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event);
  921. network_exit_handler_print(State_Machine,false);
  922. return EVENT_HANDLED;
  923. }
  924. /*********************************************************************************************
  925. * WIFI_USER_DISCONNECTED_STATE
  926. */
  927. static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) {
  928. network_handler_entry_print(State_Machine,true);
  929. ESP_LOGD(TAG, " WiFi disconnected by user");
  930. network_wifi_clear_config();
  931. network_status_update_ip_info(UPDATE_USER_DISCONNECT);
  932. NETWORK_EXECUTE_CB(State_Machine);
  933. network_handler_entry_print(State_Machine,false);
  934. return EVENT_HANDLED;
  935. }
  936. static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_handler(state_machine_t* const State_Machine) {
  937. HANDLE_GLOBAL_EVENT(State_Machine);
  938. network_handler_print(State_Machine,true);
  939. state_machine_result_t result = EVENT_HANDLED;
  940. switch (State_Machine->Event) {
  941. case EN_LOST_CONNECTION:
  942. // this is a success! we're actually asking to disconnect
  943. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
  944. break;
  945. default:
  946. result= EVENT_UN_HANDLED;
  947. }
  948. network_handler_print(State_Machine,false);
  949. return result;
  950. }
  951. static state_machine_result_t WIFI_USER_DISCONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) {
  952. network_exit_handler_print(State_Machine,true);
  953. network_exit_handler_print(State_Machine,false);
  954. return EVENT_HANDLED;
  955. }
  956. /*********************************************************************************************
  957. * WIFI_LOST_CONNECTION_STATE
  958. */
  959. static state_machine_result_t WIFI_LOST_CONNECTION_STATE_entry_handler(state_machine_t* const State_Machine) {
  960. network_t* const nm = (network_t *)State_Machine;
  961. network_handler_entry_print(State_Machine,true);
  962. ESP_LOGE(TAG, " WiFi Connection lost.");
  963. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "WiFi Connection lost");
  964. network_status_update_ip_info(UPDATE_LOST_CONNECTION);
  965. network_status_safe_reset_sta_ip_string();
  966. if (nm->last_connected > 0)
  967. nm->total_connected_time += ((esp_timer_get_time() - nm->last_connected) / (1000 * 1000));
  968. nm->last_connected = 0;
  969. nm->num_disconnect++;
  970. 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);
  971. if (nm->retries < WIFI_MANAGER_MAX_RETRY) {
  972. nm->retries++;
  973. ESP_LOGD(TAG, " Retrying connection connection, %d/%d.", nm->retries, WIFI_MANAGER_MAX_RETRY);
  974. network_async(EN_CONNECT);
  975. } else {
  976. /* In this scenario the connection was lost beyond repair */
  977. nm->retries = 0;
  978. ESP_LOGD(TAG,"Checking if ethernet interface is connected");
  979. if (network_is_interface_connected(nm->eth_netif)) {
  980. ESP_LOGW(TAG, "Cannot connect to Wifi. Falling back to Ethernet ");
  981. network_async(EN_ETHERNET_FALLBACK);
  982. } else {
  983. network_status_update_ip_info(UPDATE_LOST_CONNECTION);
  984. wifi_mode_t mode;
  985. ESP_LOGW(TAG, " All connect retry attempts failed.");
  986. /* put us in softAP mode first */
  987. esp_wifi_get_mode(&mode);
  988. if (WIFI_MODE_APSTA != mode) {
  989. nm->STA_duration = nm->sta_polling_min_ms;
  990. network_async_configure();
  991. } else if (nm->STA_duration < nm->sta_polling_max_ms) {
  992. nm->STA_duration *= 1.25;
  993. }
  994. /* keep polling for existing connection */
  995. network_set_timer(nm->STA_duration, "Wifi Polling timeout");
  996. ESP_LOGD(TAG, " STA search slow polling of %d", nm->STA_duration);
  997. }
  998. }
  999. NETWORK_EXECUTE_CB(State_Machine);
  1000. network_handler_entry_print(State_Machine,false);
  1001. return EVENT_HANDLED;
  1002. }
  1003. static state_machine_result_t WIFI_LOST_CONNECTION_STATE_handler(state_machine_t* const State_Machine) {
  1004. HANDLE_GLOBAL_EVENT(State_Machine);
  1005. network_t* const nm = (network_t *)State_Machine;
  1006. state_machine_result_t result = EVENT_HANDLED;
  1007. network_handler_print(State_Machine,true);
  1008. switch (State_Machine->Event) {
  1009. case EN_CONFIGURE:
  1010. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONFIGURING_STATE],__FUNCTION__);
  1011. break;
  1012. case EN_TIMER:
  1013. ESP_LOGI(TAG, "Timer: %s ",STR_OR_ALT(nm->timer_tag,"Lost connection"));
  1014. result= local_traverse_state(State_Machine, &Wifi_Active_State[WIFI_LOST_CONNECTION_STATE],__FUNCTION__);
  1015. break;
  1016. case EN_CONNECT:
  1017. result= local_traverse_state(State_Machine, &Wifi_Configuring_State[WIFI_CONNECTING_STATE],__FUNCTION__);
  1018. break;
  1019. default:
  1020. result= EVENT_UN_HANDLED;
  1021. }
  1022. network_handler_print(State_Machine,false);
  1023. return result;
  1024. }
  1025. static state_machine_result_t WIFI_LOST_CONNECTION_STATE_exit_handler(state_machine_t* const State_Machine) {
  1026. network_exit_handler_print(State_Machine,true);
  1027. FREE_AND_NULL(((network_t *)State_Machine)->event_parameters->disconnected_event);
  1028. network_exit_handler_print(State_Machine,false);
  1029. return EVENT_HANDLED;
  1030. }
  1031. /*********************************************************************************************
  1032. * ETH_ACTIVE_CONNECTED_STATE
  1033. */
  1034. static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_entry_handler(state_machine_t* const State_Machine) {
  1035. network_t* const nm = (network_t *)State_Machine;
  1036. network_handler_entry_print(State_Machine,true);
  1037. network_status_update_ip_info(UPDATE_ETHERNET_CONNECTED);
  1038. nm->ethernet_connected = true;
  1039. // start a wifi Scan so web ui is populated with available entries
  1040. NETWORK_EXECUTE_CB(State_Machine);
  1041. network_handler_entry_print(State_Machine,false);
  1042. return EVENT_HANDLED;
  1043. }
  1044. static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_handler(state_machine_t* const State_Machine) {
  1045. HANDLE_GLOBAL_EVENT(State_Machine);
  1046. state_machine_result_t result = EVENT_HANDLED;
  1047. network_handler_print(State_Machine,true);
  1048. switch (State_Machine->Event) {
  1049. case EN_TIMER:
  1050. ESP_LOGD(TAG, "Ignoring ethernet link up timer check");
  1051. result= EVENT_HANDLED;
  1052. break;
  1053. default:
  1054. result= EVENT_UN_HANDLED;
  1055. }
  1056. network_handler_print(State_Machine,false);
  1057. return result;
  1058. }
  1059. static state_machine_result_t ETH_ACTIVE_CONNECTED_STATE_exit_handler(state_machine_t* const State_Machine) {
  1060. network_exit_handler_print(State_Machine,true);
  1061. network_exit_handler_print(State_Machine,false);
  1062. return EVENT_HANDLED;
  1063. }
  1064. static state_machine_result_t local_switch_state(state_machine_t* state_machine,
  1065. const state_t* const target_state, const char * caller) {
  1066. const state_t* source = state_machine->State;
  1067. NETWORK_PRINT_TRANSITION(true, "BEGIN SWITCH", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller);
  1068. state_machine_result_t result = switch_state(state_machine, target_state);
  1069. NETWORK_PRINT_TRANSITION( false,"BEGIN SWITCH", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller);
  1070. ((network_t *)state_machine)->source_state = source;
  1071. return result;
  1072. }
  1073. static state_machine_result_t local_traverse_state(state_machine_t* const state_machine,
  1074. const state_t* const target_state, const char * caller) {
  1075. const state_t * source = state_machine->State;
  1076. NETWORK_PRINT_TRANSITION( true,"BEGIN TRAVERSE", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true, caller);
  1077. state_machine_result_t result = traverse_state(state_machine, target_state);
  1078. NETWORK_PRINT_TRANSITION( false,"END TRAVERSE", ((network_t *)state_machine)->source_state, target_state, state_machine->Event, true,caller);
  1079. ((network_t *)state_machine)->source_state = source;
  1080. return result;
  1081. }
  1082. static void network_interface_coexistence(state_machine_t* state_machine) {
  1083. // this function is called whenever both wifi and ethernet are
  1084. // found to be active at the same time
  1085. network_t* nm = (network_t *)state_machine;
  1086. if (nm->wifi_connected && state_machine->Event == EN_ETH_GOT_IP) {
  1087. char* eth_reboot = config_alloc_get_default(NVS_TYPE_STR, "eth_boot", "N", 0);
  1088. network_prioritize_wifi(false);
  1089. if (strcasecmp(eth_reboot, "N")) {
  1090. ESP_LOGW(TAG, "Option eth_reboot set to reboot when ethernet is connected. Rebooting");
  1091. simple_restart();
  1092. } else {
  1093. ESP_LOGW(TAG, "Option eth_reboot set to not reboot when ethernet is connected. Using Wifi interface until next reboot");
  1094. }
  1095. FREE_AND_NULL(eth_reboot);
  1096. } else if (get_root(state_machine->State)->Id == NETWORK_ETH_ACTIVE_STATE){
  1097. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi Connected with Ethernet active. System reload needed");
  1098. simple_restart();
  1099. }
  1100. }