|
@@ -53,6 +53,7 @@
|
|
|
#include <WiFi.h>
|
|
#include <WiFi.h>
|
|
|
#include <Wire.h>
|
|
#include <Wire.h>
|
|
|
#include <WebServer.h>
|
|
#include <WebServer.h>
|
|
|
|
|
+#include <Preferences.h>
|
|
|
#include "DSPWriter.h"
|
|
#include "DSPWriter.h"
|
|
|
#include <hd44780.h>
|
|
#include <hd44780.h>
|
|
|
#include <hd44780ioClass/hd44780_I2Cexp.h>
|
|
#include <hd44780ioClass/hd44780_I2Cexp.h>
|
|
@@ -65,11 +66,13 @@
|
|
|
//=============================================================
|
|
//=============================================================
|
|
|
// WiFi / UI
|
|
// WiFi / UI
|
|
|
//=============================================================
|
|
//=============================================================
|
|
|
-const char* ssid = "alfred";
|
|
|
|
|
-const char* password = "alfred16";
|
|
|
|
|
const char* hostname = "modulos-dsp";
|
|
const char* hostname = "modulos-dsp";
|
|
|
const char* version = "VER: 260304_13";
|
|
const char* version = "VER: 260304_13";
|
|
|
|
|
|
|
|
|
|
+// Runtime WiFi credentials — loaded from NVS at boot
|
|
|
|
|
+static char s_ssid[64] = "";
|
|
|
|
|
+static char s_pass[64] = "";
|
|
|
|
|
+
|
|
|
#define I2C_SDA 13
|
|
#define I2C_SDA 13
|
|
|
#define I2C_SCL 12
|
|
#define I2C_SCL 12
|
|
|
|
|
|
|
@@ -78,6 +81,7 @@ WebServer httpServer(80);
|
|
|
|
|
|
|
|
#include "index_html.h"
|
|
#include "index_html.h"
|
|
|
#include "ota_html.h"
|
|
#include "ota_html.h"
|
|
|
|
|
+#include "ap_html.h"
|
|
|
|
|
|
|
|
hd44780_I2Cexp lcd;
|
|
hd44780_I2Cexp lcd;
|
|
|
static bool s_lcdOk = false;
|
|
static bool s_lcdOk = false;
|
|
@@ -318,6 +322,88 @@ static void printHex(const char* label, const uint8_t* buf, uint16_t len, uint16
|
|
|
Serial.println();
|
|
Serial.println();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//=============================================================
|
|
|
|
|
+// NVS credential helpers
|
|
|
|
|
+//=============================================================
|
|
|
|
|
+static Preferences s_prefs;
|
|
|
|
|
+
|
|
|
|
|
+static bool loadWifiCreds()
|
|
|
|
|
+{
|
|
|
|
|
+ s_prefs.begin("wifi", true);
|
|
|
|
|
+ String ssid = s_prefs.getString("ssid", "");
|
|
|
|
|
+ String pass = s_prefs.getString("pass", "");
|
|
|
|
|
+ s_prefs.end();
|
|
|
|
|
+ if (ssid.length() == 0) return false;
|
|
|
|
|
+ ssid.toCharArray(s_ssid, sizeof(s_ssid));
|
|
|
|
|
+ pass.toCharArray(s_pass, sizeof(s_pass));
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void saveWifiCreds(const String& ssid, const String& pass)
|
|
|
|
|
+{
|
|
|
|
|
+ s_prefs.begin("wifi", false);
|
|
|
|
|
+ s_prefs.putString("ssid", ssid);
|
|
|
|
|
+ s_prefs.putString("pass", pass);
|
|
|
|
|
+ s_prefs.end();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void clearWifiCreds()
|
|
|
|
|
+{
|
|
|
|
|
+ s_prefs.begin("wifi", false);
|
|
|
|
|
+ s_prefs.clear();
|
|
|
|
|
+ s_prefs.end();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//=============================================================
|
|
|
|
|
+// SoftAP config portal — runs when no credentials are stored
|
|
|
|
|
+// or when a previous connection attempt failed.
|
|
|
|
|
+// Serves a simple HTML form; never returns.
|
|
|
|
|
+//=============================================================
|
|
|
|
|
+static void startConfigAP()
|
|
|
|
|
+{
|
|
|
|
|
+ Serial.println("Starting config AP: ModulosDSP-Setup");
|
|
|
|
|
+ WiFi.mode(WIFI_AP);
|
|
|
|
|
+ WiFi.softAP("ModulosDSP-Setup");
|
|
|
|
|
+ delay(100);
|
|
|
|
|
+ IPAddress apIP = WiFi.softAPIP();
|
|
|
|
|
+ Serial.print("AP IP: "); Serial.println(apIP);
|
|
|
|
|
+
|
|
|
|
|
+ if (s_lcdOk) {
|
|
|
|
|
+ lcd.clear();
|
|
|
|
|
+ lcd.setCursor(0, 0); lcd.print("WiFi Setup Mode");
|
|
|
|
|
+ lcd.setCursor(0, 1); lcd.print("ModulosDSP-Setup");
|
|
|
|
|
+ lcd.setCursor(0, 2); lcd.print(apIP);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ httpServer.on("/", HTTP_GET, []() {
|
|
|
|
|
+ httpServer.send_P(200, "text/html", AP_HTML);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ httpServer.on("/save", HTTP_POST, []() {
|
|
|
|
|
+ if (!httpServer.hasArg("ssid") || httpServer.arg("ssid").length() == 0) {
|
|
|
|
|
+ httpServer.send(400, "text/plain", "SSID is required.");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ String newSsid = httpServer.arg("ssid");
|
|
|
|
|
+ String newPass = httpServer.arg("pass");
|
|
|
|
|
+ saveWifiCreds(newSsid, newPass);
|
|
|
|
|
+ Serial.printf("Credentials saved for SSID: %s\n", newSsid.c_str());
|
|
|
|
|
+ httpServer.send(200, "text/html",
|
|
|
|
|
+ "<html><body style='font-family:sans-serif;max-width:380px;margin:60px auto;padding:0 20px'>"
|
|
|
|
|
+ "<h3>Saved!</h3><p>Connecting to <strong>" + newSsid +
|
|
|
|
|
+ "</strong>… The device will reboot now.</p></body></html>");
|
|
|
|
|
+ delay(1000);
|
|
|
|
|
+ ESP.restart();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ httpServer.begin();
|
|
|
|
|
+ Serial.println("Config portal active — waiting for credentials");
|
|
|
|
|
+ while (true) {
|
|
|
|
|
+ httpServer.handleClient();
|
|
|
|
|
+ delay(1);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void printWifiInfo()
|
|
static void printWifiInfo()
|
|
|
{
|
|
{
|
|
|
Serial.println();
|
|
Serial.println();
|
|
@@ -497,6 +583,19 @@ static void handleDspStatus() {
|
|
|
httpServer.send(allOk ? 200 : 500, "application/json", buf);
|
|
httpServer.send(allOk ? 200 : 500, "application/json", buf);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+//=============================================================
|
|
|
|
|
+// HTTP WiFi reset handler POST /wifi_reset
|
|
|
|
|
+//=============================================================
|
|
|
|
|
+static void handleWifiReset() {
|
|
|
|
|
+ Serial.println("WiFi credentials cleared — rebooting to AP setup mode");
|
|
|
|
|
+ clearWifiCreds();
|
|
|
|
|
+ httpServer.send(200, "text/plain",
|
|
|
|
|
+ "Credentials cleared. Rebooting into setup mode.\n"
|
|
|
|
|
+ "Connect to 'ModulosDSP-Setup' and open 192.168.4.1.");
|
|
|
|
|
+ delay(500);
|
|
|
|
|
+ ESP.restart();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
//=============================================================
|
|
//=============================================================
|
|
|
// HTTP GPIO handlers GET /gpio POST /gpio
|
|
// HTTP GPIO handlers GET /gpio POST /gpio
|
|
|
//=============================================================
|
|
//=============================================================
|
|
@@ -610,12 +709,23 @@ void setup() {
|
|
|
Serial.println(); Serial.println("Booting...");
|
|
Serial.println(); Serial.println("Booting...");
|
|
|
Serial.printf("Reset reason: %d\n", (int)esp_reset_reason());
|
|
Serial.printf("Reset reason: %d\n", (int)esp_reset_reason());
|
|
|
|
|
|
|
|
|
|
+ if (!loadWifiCreds()) {
|
|
|
|
|
+ Serial.println("No WiFi credentials stored — entering setup mode");
|
|
|
|
|
+ startConfigAP(); // never returns
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Serial.printf("Connecting to %s", s_ssid);
|
|
|
WiFi.mode(WIFI_STA);
|
|
WiFi.mode(WIFI_STA);
|
|
|
WiFi.setAutoReconnect(true);
|
|
WiFi.setAutoReconnect(true);
|
|
|
- WiFi.begin(ssid, password);
|
|
|
|
|
- while (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
|
|
|
|
- Serial.println("Connection Failed! Rebooting...");
|
|
|
|
|
- delay(5000); ESP.restart();
|
|
|
|
|
|
|
+ WiFi.begin(s_ssid, s_pass);
|
|
|
|
|
+ uint32_t t0 = millis();
|
|
|
|
|
+ while (WiFi.status() != WL_CONNECTED && millis() - t0 < 15000) {
|
|
|
|
|
+ delay(500); Serial.print(".");
|
|
|
|
|
+ }
|
|
|
|
|
+ Serial.println();
|
|
|
|
|
+ if (WiFi.status() != WL_CONNECTED) {
|
|
|
|
|
+ Serial.println("WiFi connect failed — entering setup mode");
|
|
|
|
|
+ startConfigAP(); // never returns
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (MDNS.begin(hostname)) {
|
|
if (MDNS.begin(hostname)) {
|
|
@@ -645,6 +755,7 @@ void setup() {
|
|
|
httpServer.on("/dsp_status", HTTP_GET, handleDspStatus);
|
|
httpServer.on("/dsp_status", HTTP_GET, handleDspStatus);
|
|
|
httpServer.on("/gpio", HTTP_GET, handleGpioGet);
|
|
httpServer.on("/gpio", HTTP_GET, handleGpioGet);
|
|
|
httpServer.on("/gpio", HTTP_POST, handleGpioSet);
|
|
httpServer.on("/gpio", HTTP_POST, handleGpioSet);
|
|
|
|
|
+ httpServer.on("/wifi_reset", HTTP_POST, handleWifiReset);
|
|
|
httpServer.onNotFound([]() {
|
|
httpServer.onNotFound([]() {
|
|
|
String uri = httpServer.uri();
|
|
String uri = httpServer.uri();
|
|
|
if (streamFromFS(uri)) return;
|
|
if (streamFromFS(uri)) return;
|