
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_NeoPixel.h>
// 配置wifi信息
const char* ssid = "山东酷影";
const char* password = "sdky86400265";
AsyncWebServer server(80);
#define DEFAULT_PIN 12
#define DEFAULT_LED_COUNT 30
Adafruit_NeoPixel *strip;
bool runningEffect = false;
unsigned long previousMillis = 0;
int effectInterval = 100;
struct Config {
int pin;
int ledCount;
uint8_t brightness;
uint32_t color;
bool marquee;
bool randomEffect; // 新增随机效果标志
};
Config config;
void setup() {
Serial.begin(115200);
// 使用更安全的初始化方式
config.pin = DEFAULT_PIN;
config.ledCount = DEFAULT_LED_COUNT;
config.brightness = 50;
config.color = Adafruit_NeoPixel::Color(255, 255, 255); // 使用静态方法
config.marquee = false;
config.randomEffect = false; // 初始化随机效果标志
strip = new Adafruit_NeoPixel(config.ledCount, config.pin, NEO_GRB + NEO_KHZ800);
strip->begin();
strip->setBrightness(config.brightness);
strip->show();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected! IP: " + WiFi.localIP().toString());
// 使用自定义分隔符的原始字符串
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
String html = R"=====(
<!DOCTYPE html>
<html><head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {font-family: Arial; margin: 20px;}
input, button {margin: 5px;}
#colorPicker {width: 200px; height: 200px; border: 1px solid #000; cursor: crosshair;}
</style>
</head>
<body>
<h1>WS2812 controller</h1>
<form id="configForm">
LED NUMBER: <input type="number" name="ledCount" value=")=====";
html += String(config.ledCount);
html += R"=====("><br>
PIN NUMBER: <input type="number" name="pin" value=")=====";
html += String(config.pin);
html += R"=====("><br>
Brightness(0-255): <input type="range" name="brightness" min="0" max="255" value=")=====";
html += String(config.brightness);
html += R"=====("><br>
Marquee: <input type="checkbox" name="marquee" )=====";
html += config.marquee ? "checked" : "";
html += R"=====(><br>
Random Effect: <input type="checkbox" name="randomEffect" )=====";
html += config.randomEffect ? "checked" : "";
html += R"=====(><br>
</form>
<h3>Color Picker</h3>
<canvas id="colorPicker" width="200" height="200"></canvas>
<script>
// 创建色盘
const canvas = document.getElementById('colorPicker');
const ctx = canvas.getContext('2d');
const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop(0, 'red');
gradient.addColorStop(0.16, 'orange');
gradient.addColorStop(0.32, 'yellow');
gradient.addColorStop(0.48, 'green');
gradient.addColorStop(0.64, 'blue');
gradient.addColorStop(0.80, 'indigo');
gradient.addColorStop(1, 'violet');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 监听色盘点击事件
canvas.addEventListener('click', function(event) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const pixel = ctx.getImageData(x, y, 1, 1).data;
const color = '#' + ((1 << 24) + (pixel[0] << 16) + (pixel[1] << 8) + pixel[2]).toString(16).slice(1);
// 发送颜色值到服务器
fetch('/config', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'color=' + encodeURIComponent(color)
});
});
// 监听表单变化
const form = document.getElementById('configForm');
form.addEventListener('change', function() {
let formData = new FormData(form);
fetch('/config', {
method: 'POST',
body: new URLSearchParams(formData)
});
});
</script>
</body></html>
)=====";
request->send(200, "text/html", html);
});
server.on("/config", HTTP_POST, [](AsyncWebServerRequest *request){
// 处理配置更新
if(request->hasParam("ledCount", true))
config.ledCount = request->getParam("ledCount", true)->value().toInt();
if(request->hasParam("pin", true))
config.pin = request->getParam("pin", true)->value().toInt();
if(request->hasParam("brightness", true))
config.brightness = request->getParam("brightness", true)->value().toInt();
if(request->hasParam("color", true)){
String colorStr = request->getParam("color", true)->value().substring(1);
config.color = strtoul(colorStr.c_str(), NULL, 16);
}
config.marquee = request->hasParam("marquee", true);
config.randomEffect = request->hasParam("randomEffect", true); // 更新随机效果标志
// 安全重建灯带
delete strip;
strip = new Adafruit_NeoPixel(config.ledCount, config.pin, NEO_GRB + NEO_KHZ800);
strip->begin();
strip->setBrightness(config.brightness);
strip->clear();
strip->show();
request->send(200, "text/plain", "OK");
});
server.begin();
}
void loop() {
static int pos = 0;
if(config.marquee) {
if(millis() - previousMillis >= effectInterval) {
previousMillis = millis();
strip->clear();
strip->setPixelColor(pos, config.color);
strip->show();
pos = (pos + 1) % config.ledCount;
}
} else if (config.randomEffect) {
if(millis() - previousMillis >= effectInterval) {
previousMillis = millis();
strip->clear();
for(int i = 0; i < config.ledCount; i++) {
if(random(2) == 1) { // 随机决定是否点亮
strip->setPixelColor(i, Adafruit_NeoPixel::Color(random(256), random(256), random(256))); // 随机颜色
}
}
strip->show();
}
} else {
strip->fill(config.color);
strip->show();
}
}
本文链接:
http://152.69.194.25:22380/index.php/archives/13/