wifi.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #ifndef KBF_WIFI_H
  2. #define KBF_WIFI_H
  3. #include <string>
  4. #include <memory>
  5. #include <map>
  6. #include <esp_wifi.h>
  7. #include <esp_log.h>
  8. #include "net.h"
  9. using std::string;
  10. using std::shared_ptr;
  11. using std::map;
  12. /** @brief WiFi functions */
  13. namespace kbf::wifi {
  14. /** @brief Tag used for logging */
  15. static constexpr const char *TAG = "kbf::wifi";
  16. class AP;
  17. class STA;
  18. /**
  19. * @brief Starts WiFi in soft-AP mode.
  20. *
  21. * @see #kbf::wifi::AP::create()
  22. *
  23. * @param ap AP pointer
  24. */
  25. void start(shared_ptr<AP> ap);
  26. /**
  27. * @brief Starts WiFi in STA mode.
  28. *
  29. * @param sta STA pointer; if nullptr, kbf::wifi::STA::create() will be called.
  30. */
  31. void start(shared_ptr<STA> sta = nullptr);
  32. /**
  33. * @brief Starts WiFi in AP+STA dual mode.
  34. *
  35. * @warning not yet implemented
  36. *
  37. * @param ap
  38. * @param sta
  39. */
  40. void start(shared_ptr<AP> ap, shared_ptr<STA> sta);
  41. /**
  42. * @brief Stops WiFi.
  43. */
  44. void stop();
  45. /**
  46. * @brief Returns the currently used AP instance.
  47. *
  48. * @return AP pointer or nullptr if not in AP mode
  49. */
  50. shared_ptr<AP> getAP();
  51. /**
  52. * @brief Returns the currently used STA instance.
  53. *
  54. * @return STA pointer or nullptr if not in STA mode
  55. */
  56. shared_ptr<STA> getSTA();
  57. /**
  58. * @brief WiFi station (STA) mode.
  59. */
  60. class STA {
  61. /** @see #kbf::wifi::start() */
  62. friend void kbf::wifi::start(shared_ptr<STA>);
  63. /** @see #kbf::wifi::start() */
  64. friend void kbf::wifi::start(shared_ptr<AP>, shared_ptr<STA>);
  65. /** @see #kbf::wifi::start() */
  66. friend void kbf::wifi::stop();
  67. public:
  68. /** @brief Tag used for logging. */
  69. static constexpr const char *TAG = "kbf::wifi::STA";
  70. /**
  71. * @brief Creates STA instance.
  72. *
  73. * @note WiFi requires NVS. If NVS hasn't been initialized yet, the constructor will call #kbf::nvs::init()
  74. * and try again.
  75. *
  76. * @see #kbf::wifi::start()
  77. *
  78. * @return shared_ptr<STA>
  79. */
  80. static shared_ptr<STA> create();
  81. /**
  82. * Destructor. Unregisters event handlers from the default event loop.
  83. */
  84. ~STA();
  85. /**
  86. * @brief Initiates connection to an AP.
  87. *
  88. * @param ssid SSID of AP
  89. * @param password Password
  90. * @param maxRetryAttempts maximum number of retry attempts if the connection fails
  91. */
  92. void connect(const string &ssid, const string &password, int maxRetryAttempts = 3);
  93. /**
  94. * @brief Disconnects from the AP.
  95. */
  96. void disconnect();
  97. /**
  98. * @brief Called when the WiFi has started.
  99. */
  100. void (*onStart)(){};
  101. /**
  102. * @brief Called when the WiFi has stopped.
  103. */
  104. void (*onStop)(){};
  105. /**
  106. * @brief Called when the connection to the AP was successful.
  107. *
  108. * @note Connection may be useless until an IP address is assigned by the AP. See onIp().
  109. * @see onIp()
  110. */
  111. void (*onConnect)(){};
  112. /**
  113. * @brief Called once an IP address is assigned by the AP. The connection should be ready to use at this point.
  114. */
  115. void (*onIp)(){};
  116. /**
  117. * @brief Called before reconnect attempts.
  118. *
  119. * Reconnect is attempted after disconnect events if retryMax hasn't been reached yet.
  120. *
  121. * @note The retry attempt counter is reset after successful connection.
  122. *
  123. * @param attempt number of current attempt
  124. * @param max maximum number of attempts
  125. * @return if false is returned, reconnect will be cancelled
  126. */
  127. bool (*onReconnecting)(int attempt, int max){};
  128. /**
  129. * @brief Called if disconnected and retryMax has been reached.
  130. */
  131. void (*onDisconnect)(){};
  132. /** @brief Returns the IP address for the connection. */
  133. [[nodiscard]] const kbf::net::IP &ip() const { return m_ip; };
  134. private:
  135. STA();
  136. int retryNum = 0;
  137. int retryMax{};
  138. void registerEventHandlers();
  139. void unregisterEventHandlers();
  140. static void handleStart(void *arg, esp_event_base_t baseType, int32_t eventId, void *);
  141. static void handleStop(void *arg, esp_event_base_t baseType, int32_t eventId, void *);
  142. static void handleConnect(void *arg, esp_event_base_t baseType, int32_t eventId, void *);
  143. static void handleDisconnect(void *arg, esp_event_base_t baseType, int32_t eventId, void *);
  144. static void handleGotIp(void *arg, esp_event_base_t baseType, int32_t eventId, void *pEventData);
  145. esp_netif_obj *netif = nullptr;
  146. wifi_sta_config_t config = {};
  147. esp_event_handler_instance_t startHandler = {};
  148. esp_event_handler_instance_t stopHandler = {};
  149. esp_event_handler_instance_t connectHandler = {};
  150. esp_event_handler_instance_t disconnectHandler = {};
  151. esp_event_handler_instance_t gotIpHandler = {};
  152. kbf::net::IP m_ip;
  153. };
  154. /**
  155. * @brief WiFi Software-enabled AccessPoint (AP) mode
  156. *
  157. * To start AP, use the #create() method to create an instance of this class, then pass it to #kbf::wifi::start().
  158. */
  159. class AP {
  160. /** @see #kbf::wifi::start() */
  161. friend void kbf::wifi::start(shared_ptr<AP>);
  162. /** @see #kbf::wifi::start() */
  163. friend void kbf::wifi::start(shared_ptr<AP>, shared_ptr<STA>);
  164. /** @see #kbf::wifi::start() */
  165. friend void kbf::wifi::stop();
  166. public:
  167. /** @brief Tag used for logging. */
  168. static constexpr const char *TAG = "kbf::wifi::AP";
  169. /**
  170. * @brief Creates an instance of the class.
  171. *
  172. * @param ssid
  173. * @param password
  174. * @return shared_ptr<AP>
  175. */
  176. static shared_ptr<AP> create(const string &ssid, const string &password);
  177. // TODO figure out why this doesn't work then use make_shared
  178. // template<typename ...Arg> std::shared_ptr<AP> static create(Arg&&...arg) {
  179. // struct EnableMakeShared : public AP {
  180. // explicit EnableMakeShared(Arg&&...arg) :AP(std::forward<Arg>(arg)...) {}
  181. // };
  182. // return std::make_shared<EnableMakeShared>(std::forward<Arg>(arg)...);
  183. // }
  184. /**
  185. * @brief Destructor; will unregister event handlers from the default event loop.
  186. */
  187. ~AP();
  188. /** @brief SSID to use. */
  189. const string ssid;
  190. /** @brief WPA2/PSK password. */
  191. const string password;
  192. /**
  193. * @brief Represents a station connected to this AP.
  194. */
  195. class STA {
  196. public:
  197. STA() : aid(0), mac{} {};
  198. explicit STA(wifi_event_ap_staconnected_t &);
  199. const int aid;
  200. const kbf::net::MAC mac;
  201. };
  202. /** @brief aid mapped to STA instances */
  203. map<int, STA> stations{};
  204. /**
  205. * @brief Called when the AP has started.
  206. *
  207. * @param ap
  208. */
  209. void (*onStart)(AP &ap){};
  210. /**
  211. * @brief Called when the AP has stopped.
  212. *
  213. * @param ap
  214. */
  215. void (*onStop)(AP &ap){};
  216. /**
  217. * @brief Called when a station connects to the AP.
  218. *
  219. * @param ap
  220. * @param sta
  221. */
  222. void (*onConnect)(AP &ap, STA &sta){};
  223. /**
  224. * @brief Called when a station disconnects from the AP.
  225. *
  226. * @param ap
  227. * @param sta
  228. */
  229. void (*onDisconnect)(AP &ap, STA &sta){};
  230. private:
  231. AP() { ESP_LOGW(TAG, "running default constructor!"); }
  232. AP(string ssid, string password);
  233. void registerEventHandlers();
  234. void unregisterEventHandlers();
  235. static void handleStart(void *arg, esp_event_base_t baseType, int32_t eventId, void *);
  236. static void handleStop(void *arg, esp_event_base_t baseType, int32_t eventId, void *);
  237. static void handleConnect(void *arg, esp_event_base_t baseType, int32_t eventId, void *);
  238. static void handleDisconnect(void *arg, esp_event_base_t baseType, int32_t eventId, void *);
  239. esp_netif_obj *netif = nullptr;
  240. wifi_ap_config_t config = {};
  241. esp_event_handler_instance_t startHandler = {};
  242. esp_event_handler_instance_t stopHandler = {};
  243. esp_event_handler_instance_t connectHandler = {};
  244. esp_event_handler_instance_t disconnectHandler = {};
  245. };
  246. }
  247. #endif //KBF_WIFI_H