2
0

wifi.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include "common.h"
  2. #include "WiFi.h"
  3. #include "wifi.h"
  4. #include "storage.h"
  5. #include "httpd.h"
  6. #include <lwip/dns.h>
  7. #include <lwip/inet.h>
  8. #include <lwip/apps/sntp.h>
  9. #include <esp_sntp.h>
  10. static String ssid = "";
  11. static String password = "";
  12. static String otaPassword = "";
  13. static String hostname = "max80";
  14. static String DNSServer = "";
  15. static String SNTPServer = "";
  16. static String TimeZone = "CET-1CEST,M3.5.0,M10.5.0/3"; // Sweden
  17. static void sntp_sync_cb(struct timeval *tv)
  18. {
  19. static uint8_t prev_sync_status = SNTP_SYNC_STATUS_RESET;
  20. uint8_t sync_status = sntp_get_sync_status();
  21. switch (sync_status) {
  22. case SNTP_SYNC_STATUS_RESET:
  23. sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED); // Until first sync
  24. if (prev_sync_status != sync_status) {
  25. printf("[SNTP] time synchronization lost\n");
  26. }
  27. break;
  28. case SNTP_SYNC_STATUS_COMPLETED:
  29. sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH); // After successful sync
  30. if (prev_sync_status != sync_status) {
  31. char timebuf[64];
  32. const struct tm *tm = localtime(&tv->tv_sec);
  33. strftime(timebuf, sizeof timebuf, "%a %Y-%m-%d %H:%M:%S %z", tm);
  34. printf("[SNTP] Time synchronized: %s\n", timebuf);
  35. }
  36. break;
  37. default:
  38. break;
  39. }
  40. prev_sync_status = sync_status;
  41. }
  42. static void my_sntp_start()
  43. {
  44. sntp_set_time_sync_notification_cb(sntp_sync_cb);
  45. sntp_setoperatingmode(SNTP_OPMODE_POLL);
  46. sntp_servermode_dhcp(1);
  47. sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED); // Until first sync
  48. sntp_init();
  49. }
  50. static bool services_started;
  51. static void stop_services(void)
  52. {
  53. if (services_started) {
  54. esp_unregister_shutdown_handler(stop_services);
  55. my_httpd_stop();
  56. services_started = false;
  57. }
  58. }
  59. static inline bool invalid_ip(const ip_addr_t *ip)
  60. {
  61. return !memcmp(ip, &ip_addr_any, sizeof *ip);
  62. }
  63. static void start_services(void)
  64. {
  65. /* Always run after connect */
  66. const ip_addr_t *dns_ip = dns_getserver(0);
  67. if (invalid_ip(dns_ip)) {
  68. /* No DNS server from DHCP? */
  69. ip_addr_t addr;
  70. if (inet_aton(DNSServer.c_str(), &addr)) {
  71. dns_setserver(0, &addr);
  72. }
  73. }
  74. dns_ip = dns_getserver(0);
  75. printf("[DNS] DNS server: %s\n", inet_ntoa(*dns_ip));
  76. // If Arduino supported both of these at the same that would be
  77. // awesome, but it requires ESP-IDF reconfiguration...
  78. const ip_addr_t *sntp_ip = sntp_getserver(0);
  79. if (invalid_ip(sntp_ip) && !SNTPServer.isEmpty())
  80. sntp_setservername(0, SNTPServer.c_str());
  81. sntp_ip = sntp_getserver(0);
  82. printf("[SNTP] Time server: %s\n", inet_ntoa(*sntp_ip));
  83. /* Only run on first start */
  84. if (!services_started) {
  85. services_started = true;
  86. my_httpd_start();
  87. esp_register_shutdown_handler(stop_services);
  88. }
  89. }
  90. static String wifi_local_ip(void)
  91. {
  92. return WiFi.localIP().toString();
  93. }
  94. static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
  95. {
  96. bool retry = false;
  97. bool connected = false;
  98. switch (event) {
  99. case ARDUINO_EVENT_WIFI_READY:
  100. printf("[WIFI] Interface ready\n");
  101. break;
  102. case ARDUINO_EVENT_WIFI_SCAN_DONE:
  103. printf("[WIFI] Completed scan for access points\n");
  104. break;
  105. case ARDUINO_EVENT_WIFI_STA_START:
  106. printf("[WIFI] Client started\n");
  107. break;
  108. case ARDUINO_EVENT_WIFI_STA_STOP:
  109. printf("[WIFI] Clients stopped\n");
  110. break;
  111. case ARDUINO_EVENT_WIFI_STA_CONNECTED:
  112. printf("[WIFI] Connected to access point\n");
  113. break;
  114. case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
  115. printf("[WIFI] Disconnected from WiFi access point\n");
  116. retry = true;
  117. break;
  118. case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
  119. printf("[WIFI] Authentication mode of access point has changed\n");
  120. break;
  121. case ARDUINO_EVENT_WIFI_STA_GOT_IP:
  122. printf("[WIFI] Obtained IP address: %s\n", wifi_local_ip().c_str());
  123. connected = true;
  124. break;
  125. case ARDUINO_EVENT_WIFI_STA_LOST_IP:
  126. printf("[WIFI] Lost IP address and IP address is reset to 0\n");
  127. retry = true;
  128. break;
  129. case ARDUINO_EVENT_WPS_ER_SUCCESS:
  130. printf("[WIFI] WiFi Protected Setup (WPS): succeeded in enrollee mode\n");
  131. break;
  132. case ARDUINO_EVENT_WPS_ER_FAILED:
  133. printf("[WIFI] WiFi Protected Setup (WPS): failed in enrollee mode\n");
  134. break;
  135. case ARDUINO_EVENT_WPS_ER_TIMEOUT:
  136. printf("[WIFI] WiFi Protected Setup (WPS): timeout in enrollee mode\n");
  137. break;
  138. case ARDUINO_EVENT_WPS_ER_PIN:
  139. printf("[WIFI] WiFi Protected Setup (WPS): pin code in enrollee mode\n");
  140. break;
  141. case ARDUINO_EVENT_WIFI_AP_START:
  142. printf("[WIFI] Access point started\n");
  143. break;
  144. case ARDUINO_EVENT_WIFI_AP_STOP:
  145. printf("[WIFI] Access point stopped\n");
  146. break;
  147. case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
  148. printf("[WIFI] Client connected\n");
  149. break;
  150. case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
  151. printf("[WIFI] Client disconnected\n");
  152. break;
  153. case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
  154. printf("[WIFI] Assigned IP address to client\n");
  155. break;
  156. case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED:
  157. printf("[WIFI] Received probe request\n");
  158. break;
  159. case ARDUINO_EVENT_WIFI_AP_GOT_IP6:
  160. printf("[WIFI] AP IPv6 is preferred\n");
  161. break;
  162. case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
  163. printf("[WIFI] STA IPv6 is preferred\n");
  164. connected = true;
  165. break;
  166. case ARDUINO_EVENT_ETH_GOT_IP6:
  167. printf("[ETH] Ethernet IPv6 is preferred\n");
  168. connected = true;
  169. break;
  170. case ARDUINO_EVENT_ETH_START:
  171. printf("[ETH] Ethernet started\n");
  172. break;
  173. case ARDUINO_EVENT_ETH_STOP:
  174. printf("[ETH] Ethernet stopped\n");
  175. break;
  176. case ARDUINO_EVENT_ETH_CONNECTED:
  177. printf("[ETH] Ethernet connected\n");
  178. break;
  179. case ARDUINO_EVENT_ETH_DISCONNECTED:
  180. printf("[ETH] Ethernet disconnected\n");
  181. retry = true;
  182. break;
  183. case ARDUINO_EVENT_ETH_GOT_IP:
  184. printf("[ETH] Obtained IP address: %s\n", wifi_local_ip().c_str());
  185. connected = true;
  186. break;
  187. default:
  188. break;
  189. }
  190. /* Maybe need to do these in a different thread? */
  191. if (connected) {
  192. start_services();
  193. }
  194. if (retry) {
  195. WiFi.disconnect();
  196. WiFi.begin();
  197. }
  198. }
  199. void SetupWiFi() {
  200. services_started = false;
  201. ssid = GetWifiSSID();
  202. password = GetWifiPassword();
  203. hostname = GetHostname();
  204. if (!TimeZone.isEmpty()) {
  205. printf("[INFO] Setting TZ = %s\n", TimeZone.c_str());
  206. setenv("TZ", TimeZone.c_str(), 1);
  207. tzset();
  208. }
  209. my_sntp_start();
  210. printf("[INFO] Setting up WiFi\n");
  211. printf("[INFO] SSID: %s\n", ssid.c_str());
  212. WiFi.onEvent(WiFiEvent);
  213. if (WiFi.getMode() != WIFI_STA) {
  214. WiFi.mode(WIFI_STA);
  215. delay(10);
  216. }
  217. if (WiFi.SSID() != ssid || WiFi.psk() != password) {
  218. printf("[INFO] WiFi config changed.\n");
  219. // ... Try to connect to WiFi station.
  220. WiFi.begin(ssid.c_str(), password.c_str());
  221. } else {
  222. WiFi.begin();
  223. }
  224. WiFi.setAutoReconnect(true);
  225. WiFi.setHostname(hostname.c_str());
  226. }