开发版选择ESP8266 NodeMCU 1.0

Arduino 代码

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoOTA.h>
#include <EEPROM.h>

const char* ssid = "SSID";
const char* password = "password";

ESP8266WebServer server(80);

const int powerButton = D2;
const int increaseButton = D1;
const int decreaseButton = D5;

int currentSpeed = 6; // 当前风速档位,默认为6档

bool apModeActive = false;

void handleRoot() {
  String page = "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1.0'><title>Fan Control</title>";
  page += "<style>body{font-family: Arial, sans-serif;text-align: center;}.input{margin: 10px;}.btn{padding: 10px 20px;margin: 10px;font-size: 16px;background-color: #3498db;color: #fff;border: none;border-radius: 5px;cursor: pointer;}</style>";
  page += "</head><body><h1>Fan Control</h1>";
  page += "<p id='currentSpeed'>Current Speed: " + String(currentSpeed) + "</p>";
  page += "<input type='range' min='1' max='12' value='" + String(currentSpeed) + "' id='speedSlider'><br>";
  page += "<button class='btn' id='powerOnBtn'>Power On</button><button class='btn' id='increaseSpeedBtn'>Increase Speed</button><button class='btn' id='decreaseSpeedBtn'>Decrease Speed</button>";
  page += "<br><br><a href='/config' class='btn'>Network Configuration</a>";
  page += "<script>const currentSpeedElement = document.getElementById('currentSpeed');";
  page += "const speedSlider = document.getElementById('speedSlider');";
  page += "speedSlider.addEventListener('input', function() {sendRequest('/setSpeed?speed=' + speedSlider.value);});";
  page += "function updateCurrentSpeed() {fetch('/getCurrentSpeed').then(response => response.text()).then(speed => {currentSpeedElement.innerText = 'Current Speed: ' + speed; speedSlider.value = speed;});}";
  page += "setInterval(updateCurrentSpeed, 500);";
  page += "const powerOnBtn = document.getElementById('powerOnBtn');const increaseSpeedBtn = document.getElementById('increaseSpeedBtn');const decreaseSpeedBtn = document.getElementById('decreaseSpeedBtn');";
  page += "powerOnBtn.addEventListener('click', function() {sendRequest('/powerOn');});increaseSpeedBtn.addEventListener('click', function() {sendRequest('/increaseSpeed');});decreaseSpeedBtn.addEventListener('click', function() {sendRequest('/decreaseSpeed');});";
  page += "function sendRequest(endpoint) {fetch(endpoint).then(response => {if (response.ok) {console.log('Request successful');} else {console.error('Request failed');}}).catch(error => {console.error('Error:', error);});}</script>";
  page += "</body></html>";

  server.send(200, "text/html", page);
}

void handleConfigPage() {
  String configPage = "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1.0'><title>Network Configuration</title>";
  configPage += "<style>body{font-family: Arial, sans-serif;text-align: center;}.input{margin: 10px;}.btn{padding: 10px 20px;margin: 10px;font-size: 16px;background-color: #3498db;color: #fff;border: none;border-radius: 5px;cursor: pointer;}</style>";
  configPage += "</head><body><h1>Network Configuration</h1>";
  configPage += "<form action='/config' method='post'>";
  configPage += "<label for='ssid'>SSID:</label><br><input type='text' id='ssid' name='ssid' class='input'><br>";
  configPage += "<label for='password'>Password:</label><br><input type='password' id='password' name='password' class='input'><br>";
  configPage += "<input type='submit' value='Connect' class='btn'></form>";
  configPage += "</body></html>";

  server.send(200, "text/html", configPage);
}

void handleConfig() {
  if (server.hasArg("ssid") && server.hasArg("password")) {
    String newSSID = server.arg("ssid");
    String newPassword = server.arg("password");

    WiFi.begin(newSSID.c_str(), newPassword.c_str());

    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
      delay(1000);
      attempts++;
    }

    if (WiFi.status() == WL_CONNECTED) {
      // Save the new WiFi credentials to EEPROM
      saveWiFiCredentials(newSSID, newPassword);
      server.send(200, "text/plain", "Connected to new WiFi network.");
    } else {
      server.send(200, "text/plain", "Failed to connect to new WiFi network.");
    }
  } else {
    server.send(400, "text/plain", "Bad Request");
  }
}

void saveWiFiCredentials(String ssid, String password) {
  // Save WiFi credentials to EEPROM for automatic connection
  // You can store them at specific locations in EEPROM
  // For simplicity, let's assume we store them at addresses 0 and 32
  for (int i = 0; i < ssid.length(); i++) {
    EEPROM.write(i, ssid[i]);
  }
  EEPROM.write(32, ssid.length()); // Store the length of the SSID

  for (int i = 0; i < password.length(); i++) {
    EEPROM.write(i + 64, password[i]);
  }
  EEPROM.write(96, password.length()); // Store the length of the password

  EEPROM.commit();
}

void loadWiFiCredentials() {
  // Load WiFi credentials from EEPROM
  int ssidLength = EEPROM.read(32);
  int passwordLength = EEPROM.read(96);

  String loadedSSID = "";
  String loadedPassword = "";

  for (int i = 0; i < ssidLength; i++) {
    loadedSSID += char(EEPROM.read(i));
  }

  for (int i = 0; i < passwordLength; i++) {
    loadedPassword += char(EEPROM.read(i + 64));
  }

  WiFi.begin(loadedSSID.c_str(), loadedPassword.c_str());
}

void activateAPMode() {
  WiFi.softAP("Geekman FAN");
  Serial.println("AP Mode Activated: Geekman FAN");
  apModeActive = true;
}

void deactivateAPMode() {
  WiFi.softAPdisconnect(true);
  apModeActive = false;
}

void handlePowerOn() {
  digitalWrite(powerButton, HIGH);
  delay(100);
  digitalWrite(powerButton, LOW);
  server.sendHeader("Location", "/");
  server.send(303);
}

void handleIncreaseSpeed() {
  if (currentSpeed < 12) {
    currentSpeed++;
  }
  digitalWrite(increaseButton, HIGH);
  delay(100);
  digitalWrite(increaseButton, LOW);
  server.sendHeader("Location", "/");
  server.send(303);
}

void handleDecreaseSpeed() {
  if (currentSpeed > 1) {
    currentSpeed--;
  }
  digitalWrite(decreaseButton, HIGH);
  delay(100);
  digitalWrite(decreaseButton, LOW);
  server.sendHeader("Location", "/");
  server.send(303);
}

void handleGetCurrentSpeed() {
  server.send(200, "text/plain", String(currentSpeed));
}

void handleSetSpeed() {
  if (server.hasArg("speed")) {
    int newSpeed = server.arg("speed").toInt();
    int speedDifference = abs(newSpeed - currentSpeed);
    
    for (int i = 0; i < speedDifference; i++) {
      if (newSpeed > currentSpeed) {
        handleIncreaseSpeed();
      } else {
        handleDecreaseSpeed();
      }
    }
  }
  
  server.sendHeader("Location", "/");
  server.send(303);
}

void setup() {
  Serial.begin(115200);

  pinMode(powerButton, OUTPUT);
  pinMode(increaseButton, OUTPUT);
  pinMode(decreaseButton, OUTPUT);

  EEPROM.begin(512); // Initialize EEPROM

  loadWiFiCredentials();

  // Start OTA
  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_SPIFFS
      type = "filesystem";
    }
    Serial.println("OTA Start updating " + type);
  });

  ArduinoOTA.onEnd([]() {
    Serial.println("OTA End");
  });

  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("OTA Progress: %u%%\r", (progress / (total / 100)));
  });

  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("OTA Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });

  ArduinoOTA.begin();

  if (WiFi.status() != WL_CONNECTED) {
    activateAPMode();
  }

  server.on("/config", HTTP_GET, handleConfigPage);
  server.on("/config", HTTP_POST, handleConfig);
  server.onNotFound([] {
    server.send(200, "text/html", "Page not found");
  });

  server.on("/", handleRoot);
  server.on("/powerOn", handlePowerOn);
  server.on("/increaseSpeed", handleIncreaseSpeed);
  server.on("/decreaseSpeed", handleDecreaseSpeed);
  server.on("/getCurrentSpeed", HTTP_GET, handleGetCurrentSpeed);
  server.on("/setSpeed", HTTP_GET, handleSetSpeed);

  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  ArduinoOTA.handle();
  server.handleClient();

  if (WiFi.status() == WL_CONNECTED && apModeActive) {
    deactivateAPMode();
  } else if (WiFi.status() != WL_CONNECTED && !apModeActive) {
    activateAPMode();
  }
}