state_machine.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. #include <state_machine.hpp>
  2. #include <cstdlib>
  3. #include <iostream>
  4. #include <sstream>
  5. #include <string>
  6. #include "cmd_system.h"
  7. #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
  8. #include "esp_log.h"
  9. #include "esp_wifi_types.h"
  10. #include "http_server_handlers.h"
  11. #include "messaging.h"
  12. #include "network_ethernet.h"
  13. #include "network_status.h"
  14. #include "network_wifi.h"
  15. #include "state_machine.h"
  16. #include "trace.h"
  17. #include "dns_server.h"
  18. BaseType_t network_manager_task;
  19. /* objects used to manipulate the main queue of events */
  20. QueueHandle_t network_manager_queue;
  21. using namespace stateless;
  22. using namespace std::placeholders;
  23. static const char TAG[] = "network_manager";
  24. static TaskHandle_t task_network_manager = NULL;
  25. TimerHandle_t STA_timer = NULL;
  26. uint32_t STA_duration;
  27. static int32_t total_connected_time = 0;
  28. static int64_t last_connected = 0;
  29. static uint16_t num_disconnect = 0;
  30. void network_wifi_get_stats(int32_t* ret_total_connected_time, int64_t* ret_last_connected, uint16_t* ret_num_disconnect) {
  31. *ret_total_connected_time = total_connected_time;
  32. *ret_last_connected = last_connected;
  33. *ret_num_disconnect = num_disconnect;
  34. }
  35. namespace {
  36. std::ostream& operator<<(std::ostream& os, const state_t s) {
  37. //static const char* name[] = { "idle", "stopped", "started", "running" };
  38. static const char* name[] = {
  39. "initializing",
  40. "global",
  41. "eth_starting",
  42. "eth_active",
  43. "eth_active_linkup",
  44. "eth_active_connected",
  45. "eth_active_linkdown",
  46. "wifi_up",
  47. "wifi_initializing",
  48. "network_manager_async",
  49. "wifi_connecting_scanning",
  50. "wifi_connecting",
  51. "wifi_connected",
  52. "wifi_disconnecting",
  53. "wifi_user_disconnected",
  54. "wifi_connected_waiting_for_ip",
  55. "wifi_connected_scanning",
  56. "wifi_lost_connection",
  57. "wifi_ap_mode",
  58. "wifi_ap_mode_scanning",
  59. "wifi_ap_mode_scan_done",
  60. "wifi_ap_mode_connecting",
  61. "wifi_ap_mode_connected",
  62. "system_rebooting"};
  63. os << name[(int)s];
  64. return os;
  65. }
  66. const char* trigger_to_string(trig_t trigger) {
  67. switch (trigger) {
  68. ENUM_TO_STRING(t_link_up);
  69. ENUM_TO_STRING(t_link_down);
  70. ENUM_TO_STRING(t_configure);
  71. ENUM_TO_STRING(t_got_ip);
  72. ENUM_TO_STRING(t_next);
  73. ENUM_TO_STRING(t_start);
  74. ENUM_TO_STRING(t_scan);
  75. ENUM_TO_STRING(t_fail);
  76. ENUM_TO_STRING(t_success);
  77. ENUM_TO_STRING(t_scan_done);
  78. ENUM_TO_STRING(t_connect);
  79. ENUM_TO_STRING(t_reboot);
  80. ENUM_TO_STRING(t_reboot_url);
  81. ENUM_TO_STRING(t_lost_connection);
  82. ENUM_TO_STRING(t_update_status);
  83. ENUM_TO_STRING(t_disconnect);
  84. default:
  85. break;
  86. }
  87. return "Unknown trigger";
  88. }
  89. std::ostream& operator<<(std::ostream& os, const trig_t & t) {
  90. //static const char* name[] = { "start", "stop", "set_speed", "halt" };
  91. os << trigger_to_string(t);
  92. return os;
  93. }
  94. } // namespace
  95. // namespace stateless
  96. // {
  97. // template<> void print_state<state>(std::ostream& os, const state& s)
  98. // { os << s; }
  99. // template<> void print_trigger<trigger_t_t(std::ostream& os, const trigger& t)
  100. // { os << t; }
  101. // }
  102. // namespace
  103. // {
  104. // class network_manager
  105. // {
  106. // public:
  107. // network_manager()
  108. // : sm_(state_t::initializing)
  109. // ,
  110. // {
  111. //}
  112. // sm_.configure(state_t::idle)
  113. // .permit(trig_t::t_start, state_t::started);
  114. // sm_.configure(state_t::stopped)
  115. // .on_entry([=](const TTransition&) { speed_ = 0; })
  116. // .permit(trig_t::t_halt, state_t::idle);
  117. // sm_.configure(state_t::started)
  118. // .permit(trig_t::t_set_speed, state_t::running)
  119. // .permit(trig_t::t_stop, state_t::stopped);
  120. // sm_.configure(state_t::running)
  121. // .on_entry_from(
  122. // set_speed_trigger_,
  123. // [=](const TTransition& t, int speed) { speed_ = speed; })
  124. // .permit(trig_t::t_stop, state_t::stopped)
  125. // .permit_reentry(trig_t::t_set_speed);
  126. // void start(int speed)
  127. // {
  128. // sm_.fire(trig_t::t_start);
  129. // set_speed(speed);
  130. // }
  131. // void stop()
  132. // {
  133. // sm_.fire(trig_t::t_stop);
  134. // sm_.fire(trig_t::t_halt);
  135. // }
  136. // void set_speed(int speed)
  137. // {
  138. // sm_.fire(set_speed_trigger_, speed);
  139. // }
  140. // std::string print() const
  141. // {
  142. // std::ostringstream oss;
  143. // print(oss);
  144. // return oss.str();
  145. // }
  146. // void print(std::ostream& os) const
  147. // {
  148. // os << "Motor " << sm_ << " speed = " << speed_;
  149. // }
  150. // private:
  151. // //typedef std::shared_ptr<stateless::trigger_with_parameters<trigger_t, int>> TSetSpeedTrigger;
  152. // wifi_config_t * wifi_config;
  153. // TStateMachine sm_;
  154. // ;
  155. // ;
  156. // };
  157. // std::ostream& operator<<(std::ostream& os, const motor& m)
  158. // {
  159. // m.print(os);
  160. // return os;
  161. // }
  162. //}
  163. namespace {
  164. typedef state_machine<state_t, trig_t> TStateMachine;
  165. typedef TStateMachine::TTransition TTransition;
  166. typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, wifi_config_t*>> TConnectTrigger;
  167. typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, reboot_type_t>> TRebootTrigger;
  168. typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, char*>> TRebootOTATrigger;
  169. typedef std::shared_ptr<stateless::trigger_with_parameters<trig_t, wifi_event_sta_disconnected_t*>> TDisconnectTrigger;
  170. }; // namespace
  171. class NetworkManager {
  172. public:
  173. NetworkManager()
  174. : sm_(state_t::instantiated),
  175. connect_trigger_(sm_.set_trigger_parameters<wifi_config_t*>(trig_t::t_connect)),
  176. reboot_trigger_(sm_.set_trigger_parameters<reboot_type_t>(trig_t::t_reboot)),
  177. reboot_ota_(sm_.set_trigger_parameters<char*>(trig_t::t_reboot)),
  178. disconnected_(sm_.set_trigger_parameters<wifi_event_sta_disconnected_t*>(trig_t::t_lost_connection)) {
  179. sm_.configure(state_t::instantiated)
  180. .permit(trig_t::t_start, state_t::initializing);
  181. sm_.configure(state_t::global)
  182. .permit(trig_t::t_reboot, state_t::system_rebooting)
  183. .permit(trig_t::t_reboot_url, state_t::system_rebooting)
  184. .permit_reentry(trig_t::t_update_status)
  185. .on_entry_from(trig_t::t_update_status,
  186. [=](const TTransition& t) {
  187. wifi_manager_update_basic_info();
  188. });
  189. sm_.configure(state_t::system_rebooting)
  190. .on_entry_from(reboot_ota_, [=](const TTransition& t, char* url) {
  191. if (url) {
  192. start_ota(url, NULL, 0);
  193. free(url);
  194. }
  195. })
  196. .on_entry_from(reboot_trigger_, [=](const TTransition& t, reboot_type_t reboot_type) {
  197. switch (reboot_type) {
  198. case reboot_type_t::OTA:
  199. ESP_LOGD(TAG, "Calling guided_restart_ota.");
  200. guided_restart_ota();
  201. break;
  202. case reboot_type_t::RECOVERY:
  203. ESP_LOGD(TAG, "Calling guided_factory.");
  204. guided_factory();
  205. break;
  206. case reboot_type_t::RESTART:
  207. ESP_LOGD(TAG, "Calling simple_restart.");
  208. simple_restart();
  209. break;
  210. default:
  211. break;
  212. }
  213. });
  214. sm_.configure(state_t::initializing)
  215. .on_entry([=](const TTransition& t) {
  216. /* memory allocation */
  217. ESP_LOGD(TAG, "network_manager_start. Creating message queue");
  218. network_manager_queue = xQueueCreate(3, sizeof(queue_message));
  219. ESP_LOGD(TAG, "network_manager_start. Allocating memory for callback functions registration");
  220. // todo: allow registration of event callbacks
  221. ESP_LOGD(TAG, "Initializing tcp_ip adapter");
  222. esp_netif_init();
  223. ESP_LOGD(TAG, "Creating the default event loop");
  224. ESP_ERROR_CHECK(esp_event_loop_create_default());
  225. init_network_status();
  226. ESP_LOGD(TAG, "Initializing network. done");
  227. /* start wifi manager task */
  228. ESP_LOGD(TAG, "Creating network manager task");
  229. network_manager_task = xTaskCreate(&network_manager, "network_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_network_manager);
  230. // send a message to start the connections
  231. })
  232. .permit(trig_t::t_start, state_t::eth_starting);
  233. sm_.configure(state_t::eth_starting)
  234. .on_entry([=](const TTransition& t) {
  235. /* start http server */
  236. http_server_start();
  237. ESP_LOGD(TAG, "network_manager task started. Configuring Network Interface");
  238. init_network_ethernet();
  239. })
  240. .permit(trig_t::t_fail, state_t::wifi_initializing)
  241. .permit(trig_t::t_success, state_t::eth_active);
  242. sm_.configure(state_t::eth_active)
  243. .permit(trig_t::t_link_up, state_t::eth_active_linkup)
  244. .permit(trig_t::t_got_ip, state_t::eth_active_connected)
  245. .permit(trig_t::t_link_down, state_t::eth_active_linkdown)
  246. .permit(trig_t::t_fail, state_t::wifi_initializing);
  247. sm_.configure(state_t::eth_active_linkup)
  248. .sub_state_of(state_t::eth_active)
  249. .on_entry([=](const TTransition& t) {
  250. // Anything we need to do on link becoming active?
  251. });
  252. sm_.configure(state_t::eth_active_linkdown)
  253. .sub_state_of(state_t::eth_active)
  254. .on_entry([=](const TTransition& t) {
  255. // If not connected after a certain time, start
  256. // wifi
  257. });
  258. sm_.configure(state_t::eth_active_connected)
  259. .sub_state_of(state_t::eth_active)
  260. .on_entry([=](const TTransition& t) {
  261. })
  262. .on_exit([=](const TTransition& t) {
  263. });
  264. sm_.configure(state_t::wifi_up)
  265. .on_entry([=](const TTransition& t) {
  266. })
  267. .on_exit([=](const TTransition& t) {
  268. });
  269. sm_.configure(state_t::wifi_initializing)
  270. .sub_state_of(state_t::wifi_up)
  271. .on_entry([=](const TTransition& t) {
  272. esp_err_t err = ESP_OK;
  273. ESP_LOGD(TAG, "network_wifi_load_restore");
  274. if (!is_wifi_up()) {
  275. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "Wifi not started. Load Configuration");
  276. return ESP_FAIL;
  277. }
  278. if (wifi_manager_fetch_wifi_sta_config()) {
  279. ESP_LOGI(TAG, "Saved wifi found on startup. Will attempt to connect.");
  280. network_manager_async_connect(wifi_manager_get_wifi_sta_config());
  281. } else {
  282. /* no wifi saved: start soft AP! This is what should happen during a first run */
  283. ESP_LOGD(TAG, "No saved wifi. Starting AP.");
  284. network_manager_async_configure();
  285. }
  286. return err;
  287. })
  288. .permit(trig_t::t_configure, state_t::wifi_ap_mode)
  289. .permit(trig_t::t_connect, state_t::wifi_connecting_scanning);
  290. sm_.configure(state_t::wifi_connecting_scanning)
  291. .sub_state_of(state_t::wifi_up)
  292. .on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
  293. if (network_wifi_connect(wifi_config) == ESP_OK) {
  294. network_manager_async_connect(wifi_config);
  295. } else {
  296. network_manager_async_fail();
  297. }
  298. // STA_duration = STA_POLLING_MIN;
  299. // /* create timer for background STA connection */
  300. // if (!STA_timer) {
  301. // STA_timer = xTimerCreate("background STA", pdMS_TO_TICKS(STA_duration), pdFALSE, NULL, polling_STA);
  302. // }
  303. // setup a timeout here. On timeout,
  304. // check reconnect_attempts and
  305. // fire trig_t::t_scan if we have more attempts to try
  306. // fire trig_t::t_fail otherwise
  307. })
  308. .permit_reentry_if(trig_t::t_scan, [&]() {
  309. return ++reconnect_attempt < 3;
  310. })
  311. .permit(trig_t::t_connect, state_t::wifi_connecting)
  312. .permit(trig_t::t_fail, state_t::wifi_lost_connection);
  313. sm_.configure(state_t::wifi_connecting)
  314. .on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
  315. // setup a timeout here. On timeout,
  316. // check reconnect_attempts and
  317. // fire trig_t::t_wifi_connecting_existing if we have more attempts to try
  318. // fire trig_t::t_fail otherwise
  319. })
  320. .permit(trig_t::t_success, state_t::wifi_connected_waiting_for_ip)
  321. .permit(trig_t::t_got_ip, state_t::wifi_connected)
  322. .permit(trig_t::t_lost_connection, state_t::wifi_ap_mode);
  323. sm_.configure(state_t::wifi_connected_waiting_for_ip)
  324. .permit(trig_t::t_got_ip, state_t::wifi_connected);
  325. sm_.configure(state_t::wifi_ap_mode)
  326. .on_entry([=](const TTransition& t) {
  327. wifi_manager_config_ap();
  328. ESP_LOGD(TAG, "AP Starting, requesting wifi scan.");
  329. network_manager_async_scan();
  330. })
  331. .on_entry_from(disconnected_, [=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
  332. if(disconnected_event){
  333. free(disconnected_event);
  334. }
  335. })
  336. .permit(trig_t::t_scan, state_t::wifi_ap_mode_scanning);
  337. sm_.configure(state_t::wifi_ap_mode_scanning)
  338. .on_entry([=](const TTransition& t) {
  339. // build a list of found AP
  340. })
  341. .permit(trig_t::t_scan_done, state_t::wifi_ap_mode_scan_done);
  342. sm_.configure(state_t::wifi_ap_mode_scan_done)
  343. .permit(trig_t::t_connect, state_t::wifi_ap_mode_connecting);
  344. sm_.configure(state_t::wifi_ap_mode_connecting)
  345. .on_entry_from(connect_trigger_, [=](const TTransition& t, wifi_config_t* wifi_config) {
  346. })
  347. .permit(trig_t::t_got_ip, state_t::wifi_ap_mode_connected)
  348. .permit(trig_t::t_fail, state_t::wifi_ap_mode);
  349. sm_.configure(state_t::wifi_ap_mode_connected)
  350. .on_entry([=](const TTransition& t) {
  351. })
  352. .permit(trig_t::t_success, state_t::wifi_connected);
  353. sm_.configure(state_t::wifi_connected)
  354. .on_entry([&](const TTransition& t) {
  355. last_connected = esp_timer_get_time();
  356. /* bring down DNS hijack */
  357. ESP_LOGD(TAG, "Stopping DNS.");
  358. dns_server_stop();
  359. if (network_wifi_sta_config_changed()) {
  360. network_wifi_save_sta_config();
  361. }
  362. /* stop AP mode */
  363. esp_wifi_set_mode(WIFI_MODE_STA);
  364. })
  365. .permit_reentry(trig_t::t_scan_done)
  366. .permit(trig_t::t_lost_connection, state_t::wifi_lost_connection)
  367. .permit(trig_t::t_scan, state_t::wifi_connected_scanning)
  368. .permit(trig_t::t_disconnect, state_t::wifi_disconnecting)
  369. .permit(trig_t::t_connect, state_t::wifi_connecting);
  370. sm_.configure(state_t::wifi_disconnecting)
  371. .permit(trig_t::t_lost_connection, state_t::wifi_user_disconnected);
  372. sm_.configure(state_t::wifi_user_disconnected)
  373. .on_entry_from(disconnected_,
  374. [=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
  375. ESP_LOGD(TAG, "WiFi disconnected by user");
  376. network_wifi_clear_config();
  377. wifi_manager_generate_ip_info_json(UPDATE_USER_DISCONNECT);
  378. network_manager_async_configure();
  379. if (disconnected_event) {
  380. free(disconnected_event);
  381. }
  382. })
  383. .permit(trig_t::t_configure, state_t::wifi_ap_mode);
  384. sm_.configure(state_t::wifi_lost_connection)
  385. .on_entry_from(disconnected_,
  386. [=](const TTransition& t, wifi_event_sta_disconnected_t* disconnected_event) {
  387. ESP_LOGE(TAG, "WiFi Connection lost.");
  388. messaging_post_message(MESSAGING_WARNING, MESSAGING_CLASS_SYSTEM, "WiFi Connection lost");
  389. wifi_manager_generate_ip_info_json(UPDATE_LOST_CONNECTION);
  390. if (last_connected > 0)
  391. total_connected_time += ((esp_timer_get_time() - last_connected) / (1000 * 1000));
  392. last_connected = 0;
  393. num_disconnect++;
  394. ESP_LOGW(TAG, "Wifi disconnected. Number of disconnects: %d, Average time connected: %d", num_disconnect, num_disconnect > 0 ? (total_connected_time / num_disconnect) : 0);
  395. //network_manager_async_connect(wifi_manager_get_wifi_sta_config());
  396. if (retries < WIFI_MANAGER_MAX_RETRY) {
  397. ESP_LOGD(TAG, "Issuing ORDER_CONNECT_STA to retry connection.");
  398. retries++;
  399. network_manager_async_connect(wifi_manager_get_wifi_sta_config());
  400. free(disconnected_event);
  401. } else {
  402. /* In this scenario the connection was lost beyond repair: kick start the AP! */
  403. retries = 0;
  404. wifi_mode_t mode;
  405. ESP_LOGW(TAG, "All connect retry attempts failed.");
  406. /* put us in softAP mode first */
  407. esp_wifi_get_mode(&mode);
  408. if (WIFI_MODE_APSTA != mode) {
  409. STA_duration = STA_POLLING_MIN;
  410. network_manager_async_lost_connection(disconnected_event);
  411. } else if (STA_duration < STA_POLLING_MAX) {
  412. STA_duration *= 1.25;
  413. free(disconnected_event);
  414. }
  415. /* keep polling for existing connection */
  416. xTimerChangePeriod(STA_timer, pdMS_TO_TICKS(STA_duration), portMAX_DELAY);
  417. xTimerStart(STA_timer, portMAX_DELAY);
  418. ESP_LOGD(TAG, "STA search slow polling of %d", STA_duration);
  419. }
  420. })
  421. .on_entry([=](const TTransition& t) {
  422. wifi_manager_safe_reset_sta_ip_string();
  423. })
  424. .permit(trig_t::t_connect, state_t::wifi_connecting)
  425. .permit(trig_t::t_lost_connection, state_t::wifi_ap_mode);
  426. // Register a callback for state transitions (the default does nothing).
  427. sm_.on_transition([](const TTransition& t) {
  428. std::cout << "transition from [" << t.source() << "] to ["
  429. << t.destination() << "] via trigger [" << t.trigger() << "]"
  430. << std::endl;
  431. });
  432. // Override the default behaviour of throwing when a trigger is unhandled.
  433. sm_.on_unhandled_trigger([](const state_t s, const trig_t t) {
  434. std::cerr << "ignore unhandled trigger [" << t << "] in state [" << s
  435. << "]" << std::endl;
  436. });
  437. }
  438. public:
  439. bool
  440. Allowed(trig_t trigger) {
  441. if (!sm_.can_fire(trigger)) {
  442. ESP_LOGW(TAG, "Network manager might not be able to process trigger %s", trigger_to_string(trigger));
  443. return false;
  444. }
  445. return true;
  446. }
  447. bool Fire(trig_t trigger) {
  448. try {
  449. sm_.fire(trigger);
  450. return true;
  451. } catch (const std::exception& e) {
  452. std::cerr << e.what() << '\n';
  453. }
  454. return false;
  455. }
  456. bool Event(queue_message& msg) {
  457. trig_t trigger = msg.trigger;
  458. try {
  459. if (trigger == trig_t::t_connect) {
  460. sm_.fire(connect_trigger_, msg.wifi_config);
  461. } else if (trigger == trig_t::t_reboot) {
  462. sm_.fire(reboot_trigger_, msg.rtype);
  463. } else if (trigger == trig_t::t_reboot_url) {
  464. sm_.fire(reboot_ota_, msg.strval);
  465. } else if (trigger == trig_t::t_lost_connection) {
  466. sm_.fire(disconnected_, msg.disconnected_event);
  467. } else {
  468. sm_.fire(trigger);
  469. }
  470. return true;
  471. } catch (const std::exception& e) {
  472. std::cerr << e.what() << '\n';
  473. return false;
  474. }
  475. }
  476. private:
  477. uint8_t reconnect_attempt = 0;
  478. bool existing_connection = false;
  479. uint8_t retries = 0;
  480. TStateMachine sm_;
  481. TConnectTrigger connect_trigger_;
  482. TRebootTrigger reboot_trigger_;
  483. TRebootOTATrigger reboot_ota_;
  484. TDisconnectTrigger disconnected_;
  485. };
  486. NetworkManager nm;
  487. void network_manager_start() {
  488. nm.Fire(trig_t::t_start);
  489. }
  490. bool network_manager_async(trig_t trigger) {
  491. queue_message msg;
  492. msg.trigger = trigger;
  493. if (nm.Allowed(trigger)) {
  494. return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
  495. }
  496. return false;
  497. }
  498. bool network_manager_async_fail() {
  499. return network_manager_async(trig_t::t_fail);
  500. }
  501. bool network_manager_async_success() {
  502. return network_manager_async(trig_t::t_success);
  503. }
  504. bool network_manager_async_link_up() {
  505. return network_manager_async(trig_t::t_link_up);
  506. }
  507. bool network_manager_async_link_down() {
  508. return network_manager_async(trig_t::t_link_down);
  509. }
  510. bool network_manager_async_configure() {
  511. return network_manager_async(trig_t::t_configure);
  512. }
  513. bool network_manager_async_got_ip() {
  514. return network_manager_async(trig_t::t_got_ip);
  515. }
  516. bool network_manager_async_next() {
  517. return network_manager_async(trig_t::t_next);
  518. }
  519. bool network_manager_async_start() {
  520. return network_manager_async(trig_t::t_start);
  521. }
  522. bool network_manager_async_scan() {
  523. return network_manager_async(trig_t::t_scan);
  524. }
  525. bool network_manager_async_update_status() {
  526. return network_manager_async(trig_t::t_update_status);
  527. }
  528. bool network_manager_async_disconnect() {
  529. return network_manager_async(trig_t::t_disconnect);
  530. }
  531. bool network_manager_async_scan_done() {
  532. return network_manager_async(trig_t::t_scan_done);
  533. }
  534. bool network_manager_async_connect(wifi_config_t* wifi_config) {
  535. queue_message msg;
  536. msg.trigger = trig_t::t_connect;
  537. msg.wifi_config = wifi_config;
  538. if (nm.Allowed(msg.trigger)) {
  539. return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
  540. }
  541. return false;
  542. }
  543. bool network_manager_async_lost_connection(wifi_event_sta_disconnected_t* disconnected_event) {
  544. queue_message msg;
  545. msg.trigger = trig_t::t_lost_connection;
  546. msg.disconnected_event = disconnected_event;
  547. if (nm.Allowed(msg.trigger)) {
  548. return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
  549. }
  550. return false;
  551. }
  552. bool network_manager_async_reboot(reboot_type_t rtype) {
  553. queue_message msg;
  554. msg.trigger = trig_t::t_reboot;
  555. msg.rtype = rtype;
  556. if (nm.Allowed(msg.trigger)) {
  557. return xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
  558. }
  559. return false;
  560. }
  561. void network_manager_reboot_ota(char* url) {
  562. queue_message msg;
  563. if (url == NULL) {
  564. msg.trigger = trig_t::t_reboot;
  565. msg.rtype = reboot_type_t::OTA;
  566. } else {
  567. msg.trigger = trig_t::t_reboot_url;
  568. msg.strval = strdup(url);
  569. }
  570. if (nm.Allowed(msg.trigger)) {
  571. xQueueSendToFront(network_manager_queue, &msg, portMAX_DELAY);
  572. }
  573. return;
  574. }
  575. // switch (msg.code) {
  576. // case EVENT_SCAN_DONE:
  577. // err = wifi_scan_done(&msg);
  578. // /* callback */
  579. // if (cb_ptr_arr[msg.code]) {
  580. // ESP_LOGD(TAG, "Invoking SCAN DONE callback");
  581. // (*cb_ptr_arr[msg.code])(NULL);
  582. // ESP_LOGD(TAG, "Done Invoking SCAN DONE callback");
  583. // }
  584. // break;
  585. // case ORDER_START_WIFI_SCAN:
  586. // err = network_wifi_start_scan(&msg);
  587. // /* callback */
  588. // if (cb_ptr_arr[msg.code])
  589. // (*cb_ptr_arr[msg.code])(NULL);
  590. // break;
  591. // case ORDER_LOAD_AND_RESTORE_STA:
  592. // err = network_wifi_load_restore(&msg);
  593. // /* callback */
  594. // if (cb_ptr_arr[msg.code])
  595. // (*cb_ptr_arr[msg.code])(NULL);
  596. // break;
  597. // case ORDER_CONNECT_STA:
  598. // err = network_wifi_order_connect(&msg);
  599. // /* callback */
  600. // if (cb_ptr_arr[msg.code])
  601. // (*cb_ptr_arr[msg.code])(NULL);
  602. // break;
  603. // case EVENT_STA_DISCONNECTED:
  604. // err = network_wifi_disconnected(&msg);
  605. // /* callback */
  606. // if (cb_ptr_arr[msg.code])
  607. // (*cb_ptr_arr[msg.code])(NULL);
  608. // break;
  609. // case ORDER_START_AP:
  610. // err = network_wifi_start_ap(&msg);
  611. // /* callback */
  612. // if (cb_ptr_arr[msg.code])
  613. // (*cb_ptr_arr[msg.code])(NULL);
  614. // break;
  615. // case EVENT_GOT_IP:
  616. // ESP_LOGD(TAG, "MESSAGE: EVENT_GOT_IP");
  617. // /* save IP as a string for the HTTP server host */
  618. // //s->ip_info.ip.addr
  619. // ip_event_got_ip_t* event = (ip_event_got_ip_t*)msg.param;
  620. // wifi_manager_safe_update_sta_ip_string(&(event->ip_info.ip));
  621. // wifi_manager_generate_ip_info_json(network_manager_is_flag_set(WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT)? UPDATE_FAILED_ATTEMPT_AND_RESTORE : UPDATE_CONNECTION_OK, event->esp_netif, event->ip_changed);
  622. // free(msg.param);
  623. // /* callback */
  624. // if (cb_ptr_arr[msg.code])
  625. // (*cb_ptr_arr[msg.code])(NULL);
  626. // break;
  627. // case UPDATE_CONNECTION_OK:
  628. // messaging_post_message(MESSAGING_ERROR, MESSAGING_CLASS_SYSTEM, "UPDATE_CONNECTION_OK not implemented");
  629. // break;
  630. // case ORDER_DISCONNECT_STA:
  631. // ESP_LOGD(TAG, "MESSAGE: ORDER_DISCONNECT_STA. Calling esp_wifi_disconnect()");
  632. // /* precise this is coming from a user request */
  633. // xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT);
  634. // /* order wifi discconect */
  635. // ESP_ERROR_CHECK(esp_wifi_disconnect());
  636. // /* callback */
  637. // if (cb_ptr_arr[msg.code])
  638. // (*cb_ptr_arr[msg.code])(NULL);
  639. // break;
  640. // case ORDER_RESTART_OTA_URL:
  641. // ESP_LOGD(TAG, "Calling start_ota.");
  642. // start_ota(msg.param, NULL, 0);
  643. // free(msg.param);
  644. // break;
  645. // case ORDER_RESTART_RECOVERY:
  646. // break;
  647. // case ORDER_RESTART:
  648. // ESP_LOGD(TAG, "Calling simple_restart.");
  649. // simple_restart();
  650. // break;
  651. // case ORDER_UPDATE_STATUS:
  652. // ;
  653. // break;
  654. // case EVENT_ETH_TIMEOUT:
  655. // ESP_LOGW(TAG, "Ethernet connection timeout. Rebooting with WiFi Active");
  656. // network_manager_reboot(RESTART);
  657. // break;
  658. // case EVENT_ETH_LINK_UP:
  659. // /* callback */
  660. // ESP_LOGD(TAG,"EVENT_ETH_LINK_UP message received");
  661. // if (cb_ptr_arr[msg.code])
  662. // (*cb_ptr_arr[msg.code])(NULL);
  663. // break;
  664. // case EVENT_ETH_LINK_DOWN:
  665. // /* callback */
  666. // if (cb_ptr_arr[msg.code])
  667. // (*cb_ptr_arr[msg.code])(NULL);
  668. // break;
  669. // default:
  670. // break;
  671. // } /* end of switch/case */
  672. // if (!network_ethernet_wait_for_link(500)) {
  673. // if(network_ethernet_enabled()){
  674. // ESP_LOGW(TAG, "Ethernet not connected. Starting Wifi");
  675. // }
  676. // init_network_wifi();
  677. // wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL);
  678. // }
  679. void network_manager(void* pvParameters) {
  680. queue_message msg;
  681. esp_err_t err = ESP_OK;
  682. BaseType_t xStatus;
  683. network_manager_async(trig_t::t_start);
  684. /* main processing loop */
  685. for (;;) {
  686. xStatus = xQueueReceive(network_manager_queue, &msg, portMAX_DELAY);
  687. if (xStatus == pdPASS) {
  688. // pass the event to the sync processor
  689. nm.Event(msg);
  690. } /* end of if status=pdPASS */
  691. } /* end of for loop */
  692. vTaskDelete(NULL);
  693. }
  694. void network_manager_destroy() {
  695. vTaskDelete(task_network_manager);
  696. task_network_manager = NULL;
  697. /* heap buffers */
  698. destroy_network_status();
  699. destroy_network_wifi();
  700. destroy_network_status();
  701. /* RTOS objects */
  702. vQueueDelete(network_manager_queue);
  703. network_manager_queue = NULL;
  704. }