/ firmware / src / networking / wifi_ap.cpp
wifi_ap.cpp
  1  #include "wifi_internal.h"
  2  
  3  #include <identity.h>
  4  
  5  #include <Arduino.h>
  6  #include <ESPmDNS.h>
  7  #include <Preferences.h>
  8  #include <WiFi.h>
  9  
 10  namespace {
 11  
 12  void configure_ap(const char *ssid, const char *password) {
 13    Preferences prefs;
 14    if (!networking::wifi::internal::openPreferences(false, &prefs)) return;
 15    prefs.putString("ap_ssid", ssid);
 16    prefs.putString("ap_pass", password);
 17    prefs.end();
 18    Serial.printf("[wifi] AP config saved: ssid=%s\n", ssid);
 19  }
 20  
 21  }
 22  
 23  void networking::wifi::ap::accessConfig(APConfig *config) {
 24    Preferences prefs;
 25    bool prefs_ok = networking::wifi::internal::openPreferences(true, &prefs);
 26    if (!prefs_ok || prefs.getString("ap_ssid", config->ssid, sizeof(config->ssid)) == 0) {
 27      strncpy(config->ssid, config::wifi::ap::SSID, sizeof(config->ssid) - 1);
 28      config->ssid[sizeof(config->ssid) - 1] = '\0';
 29    }
 30    if (!prefs_ok || prefs.getString("ap_pass", config->password, sizeof(config->password)) == 0) {
 31      strncpy(config->password, config::wifi::ap::PASSWORD, sizeof(config->password) - 1);
 32      config->password[sizeof(config->password) - 1] = '\0';
 33    }
 34    if (prefs_ok) prefs.end();
 35  }
 36  
 37  bool networking::wifi::ap::accessSnapshot(APSnapshot *snapshot) {
 38    if (!snapshot) return false;
 39    memset(snapshot, 0, sizeof(*snapshot));
 40    snapshot->active = networking::wifi::internal::ap_active;
 41    APConfig config = {};
 42    networking::wifi::ap::accessConfig(&config);
 43    strncpy(snapshot->ssid, config.ssid, sizeof(snapshot->ssid) - 1);
 44    strncpy(snapshot->password, config.password, sizeof(snapshot->password) - 1);
 45    strncpy(snapshot->ip, WiFi.softAPIP().toString().c_str(), sizeof(snapshot->ip) - 1);
 46    snapshot->clients = WiFi.softAPgetStationNum();
 47    strncpy(snapshot->hostname, services::identity::access_hostname(), sizeof(snapshot->hostname) - 1);
 48    strncpy(snapshot->mac, WiFi.softAPmacAddress().c_str(), sizeof(snapshot->mac) - 1);
 49    return true;
 50  }
 51  
 52  bool networking::wifi::ap::applyConfig(APConfigureCommand *command) {
 53    if (!command) return false;
 54    configure_ap(command->config.ssid, command->config.password);
 55    if (networking::wifi::ap::isActive()) {
 56      networking::wifi::ap::disable();
 57      networking::wifi::ap::enable();
 58    }
 59    networking::wifi::ap::accessSnapshot(&command->snapshot);
 60    return true;
 61  }
 62  
 63  void networking::wifi::ap::enable() {
 64    {
 65      Preferences prefs;
 66      if (networking::wifi::internal::openPreferences(false, &prefs)) {
 67        prefs.putBool("ap_on", true);
 68        prefs.end();
 69      }
 70    }
 71  
 72    if (networking::wifi::internal::ap_active) return;
 73  
 74    APConfig cfg = {};
 75    networking::wifi::ap::accessConfig(&cfg);
 76  
 77    WiFi.mode(WIFI_AP_STA);
 78  
 79    IPAddress ap_ip(192, 168, 4, 1);
 80    IPAddress gateway(192, 168, 4, 1);
 81    IPAddress subnet(255, 255, 255, 0);
 82    WiFi.softAPConfig(ap_ip, gateway, subnet);
 83    WiFi.softAP(cfg.ssid, cfg.password, config::wifi::ap::CHANNEL);
 84  
 85  #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
 86    WiFi.AP.enableDhcpCaptivePortal();
 87  #endif
 88  
 89    networking::wifi::internal::ap_active = true;
 90  
 91    if (!networking::wifi::internal::mdns_started && MDNS.begin(services::identity::access_hostname())) {
 92      networking::wifi::internal::configureMdnsServices(services::identity::access_hostname());
 93      networking::wifi::internal::mdns_started = true;
 94      Serial.printf("[mdns] %s.local\n", services::identity::access_hostname());
 95    }
 96  
 97    Serial.printf("[wifi] AP started: %s (%s)\n",
 98                  cfg.ssid, ap_ip.toString().c_str());
 99  }
100  
101  bool networking::wifi::ap::setEnabled(APEnabledCommand *command) {
102    if (!command) return false;
103    if (command->enabled) networking::wifi::ap::enable();
104    else networking::wifi::ap::disable();
105    networking::wifi::ap::accessSnapshot(&command->snapshot);
106    return true;
107  }
108  
109  void networking::wifi::ap::disable() {
110    {
111      Preferences prefs;
112      if (networking::wifi::internal::openPreferences(false, &prefs)) {
113        prefs.putBool("ap_on", false);
114        prefs.end();
115      }
116    }
117  
118    if (!networking::wifi::internal::ap_active) return;
119  
120    WiFi.softAPdisconnect(true);
121  
122    if (WiFi.isConnected()) {
123      WiFi.mode(WIFI_MODE_STA);
124    }
125  
126    networking::wifi::internal::ap_active = false;
127    Serial.println(F("[wifi] AP stopped"));
128  }
129  
130  bool networking::wifi::ap::isActive() {
131    return networking::wifi::internal::ap_active;
132  }