分离html并优化

This commit is contained in:
2025-07-09 17:29:39 +08:00
parent 62060e254e
commit 1f790a3ec3
17 changed files with 1020 additions and 1021 deletions

94
data/config.html Normal file
View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>ESP32 WiFi 设置</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
background-color: #f0f2f5;
display: flex;
flex-direction: column;
align-items: center;
padding: 40px;
}
h1 {
color: #333;
margin-bottom: 30px;
}
form {
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
width: 100%;
max-width: 400px;
}
label {
font-weight: 500;
display: block;
margin: 10px 0 5px;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
input[type="submit"] {
width: 100%;
background-color: #1890ff;
color: white;
border: none;
padding: 12px;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
input[type="submit"]:hover {
background-color: #40a9ff;
}
</style>
<script>
async function saveWiFiSettings() {
const ssid = document.getElementById("ssid").value;
const password = document.getElementById("password").value;
try {
const response = await fetch("/saveWiFi", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "ssid=" + encodeURIComponent(ssid) + "&password=" + encodeURIComponent(password)
});
const result = await response.json();
alert(result.message || "WiFi 设置保存成功!");
} catch (error) {
alert("保存失败,请重试。");
}
}
</script>
</head>
<body>
<h1>WiFi 设置</h1>
<form onsubmit="event.preventDefault(); saveWiFiSettings();">
<label for="ssid">SSID</label>
<input type="text" id="ssid" name="ssid" required />
<label for="password">密码</label>
<input type="password" id="password" name="password" required />
<input type="submit" value="保存设置" />
</form>
</body>
</html>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<title>ESP32 WiFi Setup</title>
<meta charset="UTF-8">
<script>
async function saveWiFiSettings() {
const ssid = document.getElementById("ssid").value;
const password = document.getElementById("password").value;
try {
const response = await fetch("/saveWiFi", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "ssid=" + encodeURIComponent(ssid) + "&password=" + encodeURIComponent(password)
});
if (response.ok) {
// 解析JSON响应
const result = await response.json();
alert(result.message || "WiFi 设置保存成功!");
} else {
// 尝试解析错误消息
try {
const errorResult = await response.json();
alert(errorResult.message || "保存失败,请重试。");
} catch (e) {
alert("保存失败,请重试。");
}
}
} catch (error) {
console.error("Error:", error);
alert("ok");
}
}
</script>
</head>
<body>
<h1>WiFi 设置</h1>
<form onsubmit="event.preventDefault(); saveWiFiSettings();">
<label for="ssid">SSID:</label><br/>
<input type="text" id="ssid" name="ssid"><br/><br/>
<label for="password">密码:</label><br/>
<input type="password" id="password" name="password"><br/><br/>
<input type="submit" value="保存">
</form>
</body>
</html>

View File

@ -0,0 +1,146 @@
<!DOCTYPE html>
<html>
<head>
<title>ESP32 Data Display</title>
<meta charset="UTF-8">
<script>
async function fetchData() {
const response = await fetch('/data');
if (!response.ok) {
alert('数据获取失败');
return;
}
const data = await response.json();
document.getElementById('activeDuration').innerText = data.duration;
document.getElementById('temperature').innerText = data.temperature;
document.getElementById('humidity').innerText = data.humidity;
document.getElementById('lightA').innerText = data.lightA;
document.getElementById('lightB').innerText = data.lightB;
document.getElementById('wiper').innerText = data.wiper;
document.getElementById('busVoltage').innerText = data.busVoltage;
document.getElementById('shuntVoltage').innerText = data.shuntVoltage;
document.getElementById('current').innerText = data.current;
document.getElementById('power').innerText = data.power;
// 获取灯光状态
const statusResponse = await fetch('/lightStatus');
const statusText = await statusResponse.text();
document.getElementById('lightStatus').innerText = statusText === 'on' ? '开启' : '关闭';
// 获取自动调节状态
const autoAdjustStatusResponse = await fetch('/autoAdjustStatus');
const autoAdjustStatusText = await autoAdjustStatusResponse.text();
document.getElementById('autoAdjustStatus').innerText = autoAdjustStatusText === 'enabled' ? '开启' : '关闭';
}
async function setWiper() {
const wiperValue = document.getElementById('wiperValue').value;
const response = await fetch('/setWiper', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'value=' + encodeURIComponent(wiperValue)
});
if (response.ok) {
alert('Wiper value set successfully!');
} else {
alert('Failed to set Wiper value!');
}
}
async function resetDuration() {
const response = await fetch('/resetDuration', { method: 'POST' });
if (response.ok) {
alert('累计使用时长已清空');
} else {
alert('清空失败');
}
}
async function turnOnLight() {
const response = await fetch('/LightOpen', { method: 'POST' });
if (response.ok) {
updateLightStatus("开启");
} else {
alert('打开失败');
}
}
async function turnOffLight() {
const response = await fetch('/LightClose', { method: 'POST' });
if (response.ok) {
updateLightStatus("关闭");
} else {
alert('关闭失败');
}
}
function updateLightStatus(status) {
document.getElementById('lightStatus').innerText = status;
}
async function enableAutoAdjust() {
const targetLux = document.getElementById('targetLux').value;
if (!targetLux || isNaN(targetLux) || parseInt(targetLux) <= 0) {
alert('请输入有效的正整数作为目标照度');
return;
}
const response = await fetch('/startAutoAdjust', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'target=' + encodeURIComponent(targetLux)
});
if (response.ok) {
alert('已开启自动调节');
} else {
alert('开启失败');
}
}
async function disableAutoAdjust() {
const response = await fetch('/stopAutoAdjust', { method: 'POST' });
if (response.ok) {
alert('已关闭自动调节');
} else {
alert('关闭失败');
}
}
setInterval(fetchData, 1000);
</script>
</head>
<body onload="fetchData()">
<h1>实时数据显示</h1>
<p>累计使用时长: <span id="activeDuration">加载中...</span></p>
<button onclick="resetDuration()">清空累计时长</button>
<p>温度: <span id="temperature">加载中...</span> °C</p>
<p>湿度: <span id="humidity">加载中...</span> %RH</p>
<p>光照强度A: <span id="lightA">加载中...</span> lx</p>
<p>光照强度B: <span id="lightB">加载中...</span> lx</p>
<p>电位器Wiper值: <span id="wiper">加载中...</span></p>
<p>总线电压: <span id="busVoltage">加载中...</span> V</p>
<p>分流电压: <span id="shuntVoltage">加载中...</span> mV</p>
<p>电流: <span id="current">加载中...</span> A</p>
<p>功率: <span id="power">加载中...</span> W</p>
<h2>设置Wiper值</h2>
<input type="range" id="wiperValue" min="0" max="127" step="1" value="2" />
<button onclick="setWiper()">设置</button>
<h2>灯光控制</h2>
<p>灯光状态: <span id="lightStatus">加载中...</span></p>
<button onclick="turnOnLight()">开灯</button>
<button onclick="turnOffLight()">关灯</button>
<h2>自动调节</h2>
<p>状态: <span id="autoAdjustStatus">加载中...</span></p>
<p>目标照度: <input type="number" id="targetLux" min="0" max="100000" step="1" value="2000" /> lux</p>
<button onclick="enableAutoAdjust()">开启</button>
<button onclick="disableAutoAdjust()">关闭</button>
</body>
</html>

264
data/index.html Normal file
View File

@ -0,0 +1,264 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>ESP32 实时监控面板</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
background-color: #f5f7fa;
color: #333;
padding: 30px;
max-width: 1000px;
margin: auto;
}
h1 {
text-align: center;
color: #1890ff;
margin-bottom: 30px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 20px;
}
.data-box {
flex: 1;
min-width: 140px;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
padding: 12px;
text-align: center;
}
.data-label {
font-size: 14px;
color: #666;
}
.data-value {
font-size: 20px;
font-weight: bold;
color: #1890ff;
margin-top: 4px;
}
.control-section {
margin-top: 30px;
background-color: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
}
.control-group {
margin-bottom: 20px;
}
.control-group label {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
}
.control-group input[type="range"] {
width: 100%;
}
.control-group input[type="number"] {
width: 100px;
padding: 6px;
margin-right: 10px;
}
.wiper-value {
display: inline-block;
font-size: 16px;
color: #1890ff;
font-weight: bold;
margin-left: 10px;
}
button {
padding: 8px 16px;
margin: 5px 5px 0 0;
background-color: #1890ff;
color: white;
border: none;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #40a9ff;
}
.status-inline {
font-weight: bold;
color: #1890ff;
}
</style>
<script>
async function fetchData() {
const res = await fetch('/data');
if (!res.ok) return alert('获取数据失败');
const data = await res.json();
document.getElementById('duration').innerText = data.duration;
document.getElementById('temperature').innerText = data.temperature + ' °C';
document.getElementById('humidity').innerText = data.humidity + ' %RH';
document.getElementById('lightA').innerText = data.lightA + ' lx';
document.getElementById('lightB').innerText = data.lightB + ' lx';
document.getElementById('busVoltage').innerText = data.busVoltage + ' V';
document.getElementById('current').innerText = data.current + ' A';
document.getElementById('power').innerText = data.power + ' W';
document.getElementById('wiperNow').innerText = data.wiper;
const lightStatus = await (await fetch('/lightStatus')).text();
document.getElementById('lightStatus').innerText = lightStatus === 'on' ? '开启' : '关闭';
const autoStatus = await (await fetch('/autoAdjustStatus')).text();
document.getElementById('autoAdjustStatus').innerText = autoStatus === 'enabled' ? '开启' : '关闭';
}
function updateWiperDisplay() {
const val = document.getElementById('wiperValue').value;
document.getElementById('wiperDisplay').innerText = val;
}
async function setWiper() {
const val = document.getElementById('wiperValue').value;
const res = await fetch('/setWiper', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'value=' + encodeURIComponent(val)
});
alert(res.ok ? 'Wiper 设置成功!' : '设置失败');
}
async function resetDuration() {
const res = await fetch('/resetDuration', { method: 'POST' });
alert(res.ok ? '已清空累计时长' : '操作失败');
}
async function turnOnLight() {
const res = await fetch('/LightOpen', { method: 'POST' });
if (res.ok) document.getElementById('lightStatus').innerText = '开启';
else alert('打开失败');
}
async function turnOffLight() {
const res = await fetch('/LightClose', { method: 'POST' });
if (res.ok) document.getElementById('lightStatus').innerText = '关闭';
else alert('关闭失败');
}
async function enableAutoAdjust() {
const val = document.getElementById('targetLux').value;
if (!val || val <= 0 || val > 65535) {
alert('请输入合理的照度1~65535');
return;
}
const res = await fetch('/startAutoAdjust', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'target=' + encodeURIComponent(val)
});
alert(res.ok ? '已开启自动调节' : '开启失败');
}
async function disableAutoAdjust() {
const res = await fetch('/stopAutoAdjust', { method: 'POST' });
alert(res.ok ? '已关闭自动调节' : '关闭失败');
}
setInterval(fetchData, 1000);
</script>
</head>
<body onload="fetchData()">
<h1>📟 ESP32 实时监控面板</h1>
<div class="row">
<div class="data-box">
<div class="data-label">累计使用时长</div>
<div class="data-value" id="duration">--</div>
</div>
<div class="data-box">
<button onclick="resetDuration()">清空累计时长</button>
</div>
</div>
<!-- 温湿度 -->
<div class="row">
<div class="data-box">
<div class="data-label">温度</div>
<div class="data-value" id="temperature">--</div>
</div>
<div class="data-box">
<div class="data-label">湿度</div>
<div class="data-value" id="humidity">--</div>
</div>
</div>
<!-- 光照 -->
<div class="row">
<div class="data-box">
<div class="data-label">光照 A</div>
<div class="data-value" id="lightA">--</div>
</div>
<div class="data-box">
<div class="data-label">光照 B</div>
<div class="data-value" id="lightB">--</div>
</div>
</div>
<!-- 电源信息(已去除分流电压) -->
<div class="row">
<div class="data-box">
<div class="data-label">总线电压</div>
<div class="data-value" id="busVoltage">--</div>
</div>
<div class="data-box">
<div class="data-label">电流</div>
<div class="data-value" id="current">--</div>
</div>
<div class="data-box">
<div class="data-label">功率</div>
<div class="data-value" id="power">--</div>
</div>
</div>
<!-- 控制面板 -->
<div class="control-section">
<div class="control-group">
<label>Wiper 当前值:<span class="status-inline" id="wiperNow">--</span></label>
<input type="range" id="wiperValue" min="0" max="100" value="0" oninput="updateWiperDisplay()" />
<span class="wiper-value" id="wiperDisplay">0</span>
<button onclick="setWiper()">设置</button>
</div>
<div class="control-group">
<label>灯光状态:<span class="status-inline" id="lightStatus">--</span></label>
<button onclick="turnOnLight()">开灯</button>
<button onclick="turnOffLight()">关灯</button>
</div>
<div class="control-group">
<label>自动调节状态:<span class="status-inline" id="autoAdjustStatus">--</span></label>
<input type="number" id="targetLux" min="1" max="65535" value="2000" />
<button onclick="enableAutoAdjust()">开启</button>
<button onclick="disableAutoAdjust()">关闭</button>
</div>
</div>
</body>
</html>

View File

@ -14,7 +14,6 @@ board = esp32-s3-devkitc-1
framework = arduino
lib_deps =
robtillaart/INA226@^0.6.0
esphome/ESPAsyncWebServer-esphome@^3.3.0
bblanchon/ArduinoJson@^7.4.1
monitor_speed = 115200

View File

@ -1,240 +0,0 @@
/**
* DHT11.cpp
* Library for reading temperature and humidity from the DHT11 sensor.
*
* Author: Dhruba Saha
* Version: 2.1.0
* License: MIT
*/
#include "DHT11.h"
/**
* Constructor for the DHT11 class.
* Initializes the pin to be used for communication and sets it to output mode.
*
* @param pin: Digital pin number on the Arduino board to which the DHT11 sensor is connected.
*/
DHT11::DHT11(int pin) : _pin(pin)
{
pinMode(_pin, OUTPUT);
digitalWrite(_pin, HIGH);
}
/**
* Sets the delay between consecutive sensor readings.
* If this method is not called, a default delay of 500 milliseconds is used.
*
* @param delay: Delay duration in milliseconds between sensor readings.
*/
void DHT11::setDelay(unsigned long delay)
{
_delayMS = delay;
}
/**
* Reads raw data from the DHT11 sensor.
* This method handles the direct communication with the DHT11 sensor and retrieves the raw data.
* It's used internally by the readTemperature, readHumidity, and readTemperatureHumidity methods.
*
* @param data: An array of bytes where the raw sensor data will be stored.
* The array must be at least 5 bytes long, as the DHT11 sensor returns 5 bytes of data.
* @return: Returns 0 if the data is read successfully and the checksum matches.
* Returns DHT11::ERROR_TIMEOUT if the sensor does not respond or communication times out.
* Returns DHT11::ERROR_CHECKSUM if the data is read but the checksum does not match.
*/
int DHT11::readRawData(byte data[5])
{
delay(_delayMS);
startSignal();
unsigned long timeout_start = millis();
while (digitalRead(_pin) == HIGH)
{
if (millis() - timeout_start > TIMEOUT_DURATION)
{
return DHT11::ERROR_TIMEOUT;
}
}
if (digitalRead(_pin) == LOW)
{
delayMicroseconds(80);
if (digitalRead(_pin) == HIGH)
{
delayMicroseconds(80);
for (int i = 0; i < 5; i++)
{
data[i] = readByte();
if (data[i] == DHT11::ERROR_TIMEOUT)
{
return DHT11::ERROR_TIMEOUT;
}
}
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF))
{
return 0; // Success
}
else
{
return DHT11::ERROR_CHECKSUM;
}
}
}
return DHT11::ERROR_TIMEOUT;
}
/**
* Reads a byte of data from the DHT11 sensor during the communication process.
*
* @return: A byte of data read from the sensor.
*/
byte DHT11::readByte()
{
byte value = 0;
for (int i = 0; i < 8; i++)
{
while (digitalRead(_pin) == LOW)
;
delayMicroseconds(30);
if (digitalRead(_pin) == HIGH)
{
value |= (1 << (7 - i));
}
while (digitalRead(_pin) == HIGH)
;
}
return value;
}
/**
* Sends a start signal to the DHT11 sensor to initiate a data read.
* This involves setting the data pin low for a specific duration, then high,
* and finally setting it to input mode to read the data.
*/
void DHT11::startSignal()
{
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
delay(18);
digitalWrite(_pin, HIGH);
delayMicroseconds(40);
pinMode(_pin, INPUT);
}
/**
* Reads and returns the temperature from the DHT11 sensor.
* Utilizes the readRawData method to retrieve raw data from the sensor and then extracts
* the temperature from the data array.
*
* @return: Temperature value in Celsius. Returns DHT11::ERROR_TIMEOUT if reading times out,
* or DHT11::ERROR_CHECKSUM if checksum validation fails.
*/
int DHT11::readTemperature()
{
byte data[5];
int error = readRawData(data);
if (error != 0)
{
return error;
}
//return data[2];
int temp = data[2];
if (temp != DHT11::ERROR_CHECKSUM && temp != DHT11::ERROR_TIMEOUT)
{
return temp;
}
}
/**
* Reads and returns the humidity from the DHT11 sensor.
* Utilizes the readRawData method to retrieve raw data from the sensor and then extracts
* the humidity from the data array.
*
* @return: Humidity value in percentage. Returns DHT11::ERROR_TIMEOUT if reading times out,
* or DHT11::ERROR_CHECKSUM if checksum validation fails.
*/
int DHT11::readHumidity()
{
byte data[5];
int error = readRawData(data);
if (error != 0)
{
return error;
}
//return data[0];
int humi = data[0];
if (humi != DHT11::ERROR_CHECKSUM && humi != DHT11::ERROR_TIMEOUT)
{
return humi;
}
}
/**
* Reads and returns the temperature and humidity from the DHT11 sensor.
* Utilizes the readRawData method to retrieve raw data from the sensor and then extracts
* both temperature and humidity from the data array.
*
* @param temperature: Reference to a variable where the temperature value will be stored.
* @param humidity: Reference to a variable where the humidity value will be stored.
* @return: An integer representing the status of the read operation.
* Returns 0 if the reading is successful, DHT11::ERROR_TIMEOUT if a timeout occurs,
* or DHT11::ERROR_CHECKSUM if a checksum error occurs.
*/
int DHT11::readTemperatureHumidity(int &temperature, int &humidity)
{
byte data[5];
int error = readRawData(data);
if (error != 0)
{
return error;
}
humidity = data[0];
temperature = data[2];
return 0; // Indicate success
}
/**
* Returns a human-readable error message based on the provided error code.
* This method facilitates easier debugging and user feedback by translating
* numeric error codes into descriptive strings.
*
* @param errorCode The error code for which the description is required.
* @return A descriptive string explaining the error.
*/
String DHT11::getErrorString(int errorCode)
{
switch (errorCode)
{
case DHT11::ERROR_TIMEOUT:
return "Error 253 Reading from DHT11 timed out.";
case DHT11::ERROR_CHECKSUM:
return "Error 254 Checksum mismatch while reading from DHT11.";
default:
return "Error Unknown.";
}
}
int DHT11::getTempHumi(int &temperature, int &humidity)
{
// Attempt to read the temperature and humidity values from the DHT11 sensor.
int result = readTemperatureHumidity(temperature, humidity);
// Check the results of the readings.
// If the reading is successful, print the temperature and humidity values.
// If there are errors, print the appropriate error messages.
if (result == 0) {
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print(" °C\tHumidity: ");
Serial.print(humidity);
Serial.println(" %");
} else {
// Print error message based on the error code.
Serial.println(DHT11::getErrorString(result));
}
}

View File

@ -1,110 +0,0 @@
/**
* DHT11.h
* Header file for the DHT11 library, providing functionalities to interface with
* the DHT11 temperature & humidity sensor.
*
* Author: Dhruba Saha
* Version: 2.1.0
* License: MIT
*/
#ifndef DHT11_h
#define DHT11_h
#include "Arduino.h"
/**
* DHT11 Class
* Provides methods to read temperature and humidity data from the DHT11 sensor.
*/
class DHT11
{
public:
/**
* Constructor
* Initializes the data pin to be used for communication with the DHT11 sensor.
*
* @param pin: Digital pin number on the Arduino board to which the DHT11 sensor is connected.
*/
DHT11(int pin);
/**
* Sets the delay between consecutive sensor readings.
* If this method is not called, a default delay of 500 milliseconds is used.
*
* @param delay: Delay duration in milliseconds between sensor readings.
*/
void setDelay(unsigned long delay);
/**
* Reads and returns the humidity from the DHT11 sensor.
*
* @return: Humidity value in percentage. Returns DHT11_ERROR_TIMEOUT if reading times out.
* Returns DHT11_ERROR_CHECKSUM if checksum validation fails.
*/
int readHumidity();
/**
* Reads and returns the temperature from the DHT11 sensor.
*
* @return: Temperature value in Celsius. Returns DHT11_ERROR_TIMEOUT if reading times out.
* Returns DHT11_ERROR_CHECKSUM if checksum validation fails.
*/
int readTemperature();
/**
* Reads and returns the temperature and humidity from the DHT11 sensor.
*
* @param temperature: Reference to a variable where the temperature value will be stored.
* @param humidity: Reference to a variable where the humidity value will be stored.
* @return: true if the reading is successful, false if it fails due to timeout or checksum error.
*/
int readTemperatureHumidity(int &temperature, int &humidity);
int getTempHumi(int &temperature, int &humidity);
// Constants to represent error codes.
static const int ERROR_CHECKSUM = 254; // Error code indicating checksum mismatch.
static const int ERROR_TIMEOUT = 253; // Error code indicating a timeout occurred during reading.
static const int TIMEOUT_DURATION = 1000; // Duration (in milliseconds) to wait before timing out.
/**
* Returns a human-readable error message based on the provided error code.
*
* @param errorCode: The error code for which the message is required.
* @return: A string describing the error.
*/
static String getErrorString(int errorCode);
private:
int _pin; // Pin number used for communication with the DHT11 sensor.
unsigned long _delayMS = 500; // Default delay in milliseconds between sensor readings.
/**
* Private method to read raw data from the DHT11 sensor.
* This method encapsulates the communication with the sensor and data reading process,
* and is utilized by public methods to get temperature and humidity data.
*
* @param data: Array to store the raw data read from the sensor.
* @return: An integer representing the status of the read operation.
* Returns 0 if the reading is successful, DHT11::ERROR_TIMEOUT if a timeout occurs,
* or DHT11::ERROR_CHECKSUM if a checksum error occurs.
*/
int readRawData(byte data[5]);
/**
* Reads a byte of data from the DHT11 sensor.
*
* @return: A byte of data read from the sensor.
*/
byte readByte();
/**
* Sends a start signal to the DHT11 sensor to initiate a data read.
* This involves setting the data pin low for a specific duration, then high,
* and finally setting it to input mode to read the data.
*/
void startSignal();
};
#endif

208
src/WebHandlers.cpp Normal file
View File

@ -0,0 +1,208 @@
#include "WebHandlers.h"
#define LIGHT_CONTROL_PIN 1
// 全局WebServer指针用于在处理函数中访问
WebServer* webServerPtr = nullptr;
// 读取SPIFFS文件的辅助函数
String readFile(const String& path) {
if (!SPIFFS.exists(path)) {
return "File not found";
}
File file = SPIFFS.open(path, "r");
if (!file) {
return "Failed to open file";
}
String content = file.readString();
file.close();
return content;
}
// 根路径页面处理
void handleRoot() {
String html = readFile("/index.html");
webServerPtr->send(200, "text/html", html);
}
// 配置页面处理
void handleConfig() {
String html = readFile("/config.html");
webServerPtr->send(200, "text/html", html);
}
// 保存WiFi凭证处理
void handleSaveWiFi() {
if (webServerPtr->hasArg("ssid") && webServerPtr->hasArg("password")) {
// 获取 SSID 和密码
String ssid = webServerPtr->arg("ssid");
String password = webServerPtr->arg("password");
// 存储到全局变量
ssid.toCharArray(user_ssid, sizeof(user_ssid));
password.toCharArray(user_pass, sizeof(user_pass));
// 设置待连接的WiFi信息
SSID = ssid;
Password = password;
shouldConnectWiFi = true;
Serial.println("Received WiFi credentials:");
Serial.print("SSID: ");
Serial.println(user_ssid);
Serial.print("Password: ");
Serial.println(user_pass);
// 使用ArduinoJson库生成成功响应
JsonDocument doc;
doc["status"] = "success";
doc["message"] = "WiFi设置已保存正在连接...";
String jsonResponse;
serializeJson(doc, jsonResponse);
webServerPtr->send(200, "application/json", jsonResponse);
} else {
// 使用ArduinoJson库生成错误响应
JsonDocument errorDoc;
errorDoc["status"] = "error";
errorDoc["message"] = "缺少SSID或密码参数";
String errorResponse;
serializeJson(errorDoc, errorResponse);
webServerPtr->send(400, "application/json", errorResponse);
}
}
// 传感器数据API处理
void handleData() {
JsonDocument doc;
doc["temperature"] = sensorData.temperature;
doc["humidity"] = sensorData.humidity;
doc["lightA"] = sensorData.lightA;
doc["lightB"] = sensorData.lightB;
doc["wiper"] = ds3502.getWiper();
doc["busVoltage"] = sensorData.busVoltage;
doc["shuntVoltage"] = sensorData.shuntVoltage_mV;
doc["current"] = sensorData.current;
doc["power"] = sensorData.power;
doc["duration"] = runtime.formatDuration(runtime.getActiveDuration());
String json;
serializeJson(doc, json);
webServerPtr->send(200, "application/json", json);
}
// 设置Wiper值处理
void handleSetWiper() {
if (webServerPtr->hasArg("value")) {
int wiperValue = webServerPtr->arg("value").toInt();
ds3502.setWiper(wiperValue);
webServerPtr->send(200, "text/plain", "Wiper value set");
} else {
webServerPtr->send(400, "text/plain", "Missing value parameter");
}
}
// 重置运行时长处理
void handleResetDuration() {
runtime.resetActiveDuration();
webServerPtr->send(200, "text/plain", "Duration reset");
}
// 开灯处理
void handleLightOpen() {
LightOpen();
webServerPtr->send(200, "text/plain", "Light ON");
}
// 关灯处理
void handleLightClose() {
LightClose();
webServerPtr->send(200, "text/plain", "Light OFF");
}
// 获取灯光状态处理
void handleLightStatus() {
bool isOn = (digitalRead(LIGHT_CONTROL_PIN) == HIGH); // 高电平为开灯
webServerPtr->send(200, "text/plain", isOn ? "on" : "off");
}
// 启动自动调节处理
void handleStartAutoAdjust() {
if (webServerPtr->hasArg("target")) {
int targetLux = webServerPtr->arg("target").toInt();
if (targetLux > 0) {
lightCtrl.setTargetLight(targetLux);
lightCtrl.adjustToTarget();
isAutoAdjustEnabled = true;
webServerPtr->send(200, "text/plain", "Auto adjust started");
} else {
webServerPtr->send(400, "text/plain", "Invalid target lux");
}
} else {
webServerPtr->send(400, "text/plain", "Missing target parameter");
}
}
// 停止自动调节处理
void handleStopAutoAdjust() {
isAutoAdjustEnabled = false;
webServerPtr->send(200, "text/plain", "Auto adjust stopped");
}
// 获取自动调节状态处理
void handleAutoAdjustStatus() {
webServerPtr->send(200, "text/plain", isAutoAdjustEnabled ? "enabled" : "disabled");
}
// 404处理
void handleNotFound() {
webServerPtr->send(404, "text/plain", "404 Not Found");
}
// Web服务器初始化函数
void WebServer_Init(WebServer& server) {
// 设置全局指针
webServerPtr = &server;
// 初始化SPIFFS
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
// 启用CORS
server.enableCORS(true);
// 根路径页面
server.on("/", HTTP_GET, handleRoot);
// AP配网相关
server.on("/config", HTTP_GET, handleConfig);
server.on("/saveWiFi", HTTP_POST, handleSaveWiFi);
// 数据API
server.on("/data", HTTP_GET, handleData);
// 设备控制API
server.on("/setWiper", HTTP_POST, handleSetWiper);
server.on("/resetDuration", HTTP_POST, handleResetDuration);
// 灯光控制API
server.on("/LightOpen", HTTP_POST, handleLightOpen);
server.on("/LightClose", HTTP_POST, handleLightClose);
server.on("/lightStatus", HTTP_GET, handleLightStatus);
// 自动调节API
server.on("/startAutoAdjust", HTTP_POST, handleStartAutoAdjust);
server.on("/stopAutoAdjust", HTTP_POST, handleStopAutoAdjust);
server.on("/autoAdjustStatus", HTTP_GET, handleAutoAdjustStatus);
// 404处理
server.onNotFound(handleNotFound);
// 启动服务器
server.begin();
}

55
src/WebHandlers.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef WEBHANDLERS_H
#define WEBHANDLERS_H
#include <Arduino.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <FS.h>
#include "SPIFFS.h"
#include "TJC_Show.h"
#include "LightControl.h"
#include "RunTime.h"
#include "DS3502.h"
#include "WiFiControl.h"
// 声明外部变量
extern SensorData sensorData;
extern DS3502 ds3502;
extern RunTime runtime;
extern LightControl lightCtrl;
extern bool isAutoAdjustEnabled;
extern char user_ssid[64];
extern char user_pass[64];
// WiFi连接相关变量
extern bool shouldConnectWiFi;
extern String SSID;
extern String Password;
// 声明外部函数
extern void LightOpen();
extern void LightClose();
extern void connectToWiFi(String ssid, String password);
// Web处理函数声明
void handleRoot();
void handleConfig();
void handleSaveWiFi();
void handleData();
void handleSetWiper();
void handleResetDuration();
void handleLightOpen();
void handleLightClose();
void handleLightStatus();
void handleStartAutoAdjust();
void handleStopAutoAdjust();
void handleAutoAdjustStatus();
void handleNotFound();
// 辅助函数
String readFile(const String& path);
// Web服务器初始化函数
void WebServer_Init(WebServer& server);
#endif

View File

@ -1,94 +0,0 @@
// #include "WebServer.h"
// extern RunTime runtime;
// extern MCP45HVX1 digiPot;
// extern INA226 INA;
// extern DS18B20 ds18b20;
// extern BH1750 bh1750_a;
// extern BH1750 bh1750_b;
// AsyncWebServer server(80);
// void WebServer_Init(const char* ssid, const char* password) {
// WiFi.begin(ssid, password); // WiFi
// while (WiFi.status() != WL_CONNECTED) {
// delay(1000);
// Serial.println("Connecting to WiFi...");
// }
// Serial.print("Address: ");
// Serial.println(WiFi.localIP());
// // 根路径的页面
// server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
// request->send_P(200, "text/html", index_html);
// });
// // 温度接口
// server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request) {
// String temp = String(ds18b20.getTempC());
// request->send(200, "text/plain", temp);
// });
// // 光照强度传感器A
// server.on("/lightA", HTTP_GET, [](AsyncWebServerRequest *request) {
// String lightA = String(bh1750_a.readLightLevel());
// request->send(200, "text/plain", lightA);
// });
// // 光照传感器B
// server.on("/lightB", HTTP_GET, [](AsyncWebServerRequest *request) {
// String lightB = String(bh1750_b.readLightLevel());
// request->send(200, "text/plain", lightB);
// });
// // 配置Wiper接口
// server.on("/wiper", HTTP_GET, [](AsyncWebServerRequest *request) {
// String wiper = String(digiPot.readWiper());
// request->send(200, "text/plain", wiper);
// });
// server.on("/busVoltage", HTTP_GET, [](AsyncWebServerRequest *request) {
// String busVoltage = String(INA.getBusVoltage(), 3);
// request->send(200, "text/plain", busVoltage);
// });
// server.on("/shuntVoltage", HTTP_GET, [](AsyncWebServerRequest *request) {
// String shuntVoltage = String(INA.getShuntVoltage_mV(), 3);
// request->send(200, "text/plain", shuntVoltage);
// });
// server.on("/current", HTTP_GET, [](AsyncWebServerRequest *request) {
// String current = String(INA.getCurrent_mA(), 3);
// request->send(200, "text/plain", current);
// });
// server.on("/power", HTTP_GET, [](AsyncWebServerRequest *request) {
// String power = String(INA.getPower_mW(), 3);
// request->send(200, "text/plain", power);
// });
// // 获取累计时长接口
// server.on("/duration", HTTP_GET, [](AsyncWebServerRequest *request) {
// request->send(200, "text/plain", runtime.formatDuration(runtime.getActiveDuration()));
// });
// // 清空累计时长接口
// server.on("/resetDuration", HTTP_POST, [](AsyncWebServerRequest *request) {
// runtime.resetActiveDuration();
// request->send(200, "text/plain", "Duration reset");
// });
// // 接收设置Wiper的请求
// server.on("/setWiper", HTTP_POST, [](AsyncWebServerRequest *request) {
// if (request->hasParam("value", true)) {
// int wiperValue = request->getParam("value", true)->value().toInt();
// digiPot.writeWiper(wiperValue);
// request->send(200, "text/plain", "Wiper value set");
// } else {
// request->send(400, "text/plain", "Missing value parameter");
// }
// });
// server.begin();
// }

View File

@ -1,17 +0,0 @@
#ifndef WEBSERVER_H
#define WEBSERVER_H
#include "webpages.h" // 包含 HTML 页面内容
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include "BH1750.h"
#include "Wire.h"
//#include "MCP45HVX1.h"
#include "INA226.h"
#include "RunTime.h"
void WebServer_Init(void);
#endif // WEBSERVER_H

View File

@ -1,6 +1,8 @@
#include "WiFiControl.h"
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include "SPIFFS.h"
#include "mywebserver.h"
// AP 模式下的 SSID 和密码
const char* AP_SSID = "LampController_AP";
@ -10,42 +12,7 @@ const char* AP_PASSWORD = "12345678";
char user_ssid[64] = "";
char user_pass[64] = "";
//extern AsyncWebServer server(80); // 创建 Web 服务器实例
// 简单的 HTML 表单页面
const char html_form[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>WiFi Configuration</title>
<style>
body { font-family: Arial; margin: 30px; background-color: #f2f2f2; }
h2 { color: #333; }
input[type=text], input[type=password] {
width: 100%; padding: 12px 20px; margin: 8px 0; display: inline-block; border: 1px solid #ccc; box-sizing: border-box;
}
button { background-color: #4CAF50; color: white; padding: 14px 20px; margin: 8px 0; border: none; cursor: pointer; width: 100%; }
button:hover { opacity: 0.8; }
.container { background-color: #fff; padding: 20px; border-radius: 8px; max-width: 400px; margin: auto; box-shadow: 0 0 10px rgba(0,0,0,0.1); }
</style>
</head>
<body>
<div class="container">
<h2>Connect to WiFi</h2>
<form action="/connect" method="POST">
<label for="ssid"><b>SSID</b></label>
<input type="text" placeholder="Enter WiFi Name" name="ssid" required>
<label for="password"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="password" required>
<button type="submit">Save and Connect</button>
</form>
</div>
</body>
</html>
)rawliteral";
extern mywebserver* webServer;
void WiFi_Init()
{
@ -56,14 +23,12 @@ void WiFi_Init()
Serial.println("AP Mode started");
Serial.print("AP IP address: ");
Serial.println(WiFi.softAPIP());
}
void connectToWiFi()
void connectToWiFi(String ssid, String password)
{
WiFi.mode(WIFI_STA); // 切换为 Station 模式
WiFi.begin(user_ssid, user_pass);
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi...");

View File

@ -3,8 +3,9 @@
#include <Arduino.h>
void WiFi_Init();
void connectToWiFi();
void setupWebServer();
void connectToWiFi(String ssid, String password);
#endif

View File

@ -2,26 +2,32 @@
#include "BH1750.h"
#include "Wire.h"
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <Arduino.h>
#include <WebServer.h>
#include "INA226.h"
#include <Ticker.h>
#include <Preferences.h> // 用于存储非易失性数据
#include "TJC_Show.h"
#include "RunTime.h"
#include "WebServer.h"
#include "WiFiControl.h"
#include "DS3502.h"
#include "LightControl.h"
#include <ArduinoJson.h>
//#include "mywebserver.h"
#include "WebHandlers.h"
// #include <esp_task_wdt.h>
// 全局变量用于存储 WiFi 凭据
extern char user_ssid[64]; // 存储 SSID
extern char user_pass[64]; // 存储密码
String SSID;
String Password;
bool shouldConnectWiFi = false;
// Ticker 用于定时检查电流状态
Ticker currentCheckTicker;
@ -31,7 +37,7 @@ DS3502 ds3502(0x28);
// INA226 电流监控器
INA226 INA(0x40);
AsyncWebServer server(80);
WebServer server(80);
// DHT11 温湿度传感器
@ -162,162 +168,6 @@ void LightClose() {
}
void WebServer_Init(void) {
// 根路径页面
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
// /*************************** AP配网 ***************** */
server.on("/config", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", config_html);
});
server.on("/saveWiFi", HTTP_POST, [](AsyncWebServerRequest *request){
if (request->hasParam("ssid", true) && request->hasParam("password", true)) {
// 获取 SSID 和密码
String ssid = request->getParam("ssid", true)->value();
String password = request->getParam("password", true)->value();
// 存储到全局变量
ssid.toCharArray(user_ssid, sizeof(user_ssid));
password.toCharArray(user_pass, sizeof(user_pass));
Serial.println("Received WiFi credentials:");
Serial.print("SSID: ");
Serial.println(user_ssid);
Serial.print("Password: ");
Serial.println(user_pass);
connectToWiFi(); // 连接目标 WiFi
}
// 返回确认页面
String response = "<!DOCTYPE html><html><body><h2>Configuration Received</h2><p>Please wait while the device connects to WiFi...</p></body></html>";
request->send(200, "text/html", response);
});
// int32_t IRIS_Protocol_Pack(uint8_t Command,uint16_t LenthofIn, uint8_t *BufferIn, uint8_t *PackData);
// 合并数据接口
server.on("/data", HTTP_GET, [](AsyncWebServerRequest *request){
//StaticJsonDocument<256> doc;
JsonDocument doc;
doc["temperature"] = sensorData.temperature;
doc["humidity"] = sensorData.humidity;
doc["lightA"] = sensorData.lightA;
doc["lightB"] = sensorData.lightB;
doc["wiper"] = ds3502.getWiper();
doc["busVoltage"] = sensorData.busVoltage;
doc["shuntVoltage"] = sensorData.shuntVoltage_mV;
doc["current"] = sensorData.current;
doc["power"] = sensorData.power;
doc["duration"] = runtime.formatDuration(runtime.getActiveDuration());
String json;
serializeJson(doc, json);
request->send(200, "application/json", json);
// uint8_t *bufferfosend;
// int lentofpack=IRIS_Protocol_Pack(0x00, json.length(), (uint8_t*)json.c_str(),bufferfosend);
// Serial1.write(bufferfosend,lentofpack);
// delete[] bufferfosend;
});
// 设置Wiper值
server.on("/setWiper", HTTP_POST, [](AsyncWebServerRequest *request){
if (request->hasParam("value", true)) {
int wiperValue = request->getParam("value", true)->value().toInt();
ds3502.setWiper(wiperValue);
request->send(200, "text/plain", "Wiper value set");
} else {
request->send(400, "text/plain", "Missing value parameter");
}
});
// 清空累计时长
server.on("/resetDuration", HTTP_POST, [](AsyncWebServerRequest *request){
runtime.resetActiveDuration();
request->send(200, "text/plain", "Duration reset");
});
// 灯光控制接口
server.on("/LightOpen", HTTP_POST, [](AsyncWebServerRequest *request){
LightOpen();
request->send(200, "text/plain", "Light ON");
});
server.on("/LightClose", HTTP_POST, [](AsyncWebServerRequest *request){
LightClose();
request->send(200, "text/plain", "Light OFF");
});
// 获取灯光状态接口
server.on("/lightStatus", HTTP_GET, [](AsyncWebServerRequest *request){
bool isOn = (digitalRead(LIGHT_CONTROL_PIN) == HIGH); // 高电平为开灯
request->send(200, "text/plain", isOn ? "on" : "off");
});
// 启动自动调节
server.on("/startAutoAdjust", HTTP_POST, [](AsyncWebServerRequest *request){
if (request->hasParam("target", true)) {
int targetLux = request->getParam("target", true)->value().toInt();
if (targetLux > 0) {
lightCtrl.setTargetLight(targetLux);
//lightCtrl.runUntilTargetReached(targetLux, 150);
lightCtrl.adjustToTarget();
isAutoAdjustEnabled = true;
request->send(200, "text/plain", "Auto adjust started");
} else {
request->send(400, "text/plain", "Invalid target lux");
}
} else {
request->send(400, "text/plain", "Missing target parameter");
}
});
// 停止自动调节
server.on("/stopAutoAdjust", HTTP_POST, [](AsyncWebServerRequest *request){
isAutoAdjustEnabled = false;
request->send(200, "text/plain", "Auto adjust stopped");
});
// 获取自动调节状态
server.on("/autoAdjustStatus", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", isAutoAdjustEnabled ? "enabled" : "disabled");
});
// 启动服务器
server.begin();
}
//usb串口打印信息
// void SerialPrintInfo(void) {
// // 获取温湿度数据
// dht11.readTemperatureHumidity(temperature, humidity);
// // 获取光照数据
// float lightA = bh1750_a.readLightLevel();
// float lightB = bh1750_b.readLightLevel();
// // 获取电流监控数据
// float busVoltage = INA.getBusVoltage();
// float shuntVoltage_mV = INA.getShuntVoltage_mV();
// float current = INA.getCurrent();
// float power = INA.getPower();
// // 打印信息(只使用变量)
// Serial.printf("Temperature: %dC, Humidity: %d%%\n", temperature, humidity);
// Serial.printf("A: %.0f lux :: B: %.0f lux \n", lightA, lightB);
// Serial.println("\nBUS\tSHUNT\tCURRENT\tPOWER");
// Serial.printf("%.2f\t%.2f\t%.2f\t%.2f\n", busVoltage, shuntVoltage_mV, current, power);
// }
void SerialPrintInfo(void) {
UpdateSensorData(sensorData);
@ -373,7 +223,7 @@ void setup(void)
WiFi_Init();
//WebServer 初始化
WebServer_Init();
WebServer_Init(server);
// 初始化 runtime NVS
runtime.begin();
@ -414,7 +264,6 @@ void loop(void)
lastSensorRead = millis();
}
//串口解析tjc控制指令
tjcShow.processSerial();
@ -427,6 +276,13 @@ void loop(void)
if (isAutoAdjustEnabled) {
lightCtrl.adjustToTarget(); // 使用新的持续调节函数
}
server.handleClient(); // 替换webServer->loop()
if (shouldConnectWiFi) {
connectToWiFi(SSID, Password);
shouldConnectWiFi = false; // 重置标志位
}
}

151
src/mywebserver.cpp Normal file
View File

@ -0,0 +1,151 @@
#include "mywebserver.h"
#include <FS.h>
#include "SPIFFS.h"
String getContentType(String filename)
{
if (filename.endsWith(".htm"))
return "text/html";
else if (filename.endsWith(".html"))
return "text/html";
else if (filename.endsWith(".css"))
return "text/css";
else if (filename.endsWith(".js"))
return "application/javascript";
else if (filename.endsWith(".png"))
return "image/png";
else if (filename.endsWith(".gif"))
return "image/gif";
else if (filename.endsWith(".jpg"))
return "image/jpeg";
else if (filename.endsWith(".ico"))
return "image/x-icon";
else if (filename.endsWith(".xml"))
return "text/xml";
else if (filename.endsWith(".pdf"))
return "application/x-pdf";
else if (filename.endsWith(".zip"))
return "application/x-zip";
else if (filename.endsWith(".gz"))
return "application/x-gzip";
return "text/plain";
}
bool handleFileRead(String path)
{ // 处理浏览器HTTP访问
if (path.endsWith("/"))
{ // 如果访问地址以"/"为结尾
path = "/index.html"; // 则将访问地址修改为/index.html便于SPIFFS访问
}
String contentType = getContentType(path); // 获取文件类型
if (SPIFFS.exists(path))
{ // 如果访问的文件可以在SPIFFS中找到
File file = SPIFFS.open(path, "r"); // 则尝试打开该文件
MYSERVER->streamFile(file, contentType); // 并且将该文件返回给浏览器
file.close(); // 并且关闭文件
return true; // 返回true
}
return false; // 如果文件未找到则返回false
}
void handleUserRequet()
{
// 获取用户请求网址信息
String webAddress = MYSERVER->uri();
// 通过handleFileRead函数处处理用户访问
bool fileReadOK = handleFileRead(webAddress);
// 如果在SPIFFS无法找到用户访问的资源则回复404 (Not Found)
if (!fileReadOK)
{
MYSERVER->send(404, "text/plain", "404 Not Found");
}
}
// 获取文件类型
void founddate(){
Serial.println("sdfasdfasdf");
Serial.println(MYSERVER->arg("rolloffset"));
Serial.println(MYSERVER->arg("pitchoffset"));
if (MYSERVER->hasArg("Angle0"))
{
Serial.println(MYSERVER->arg("Angle0"));
/* code */
}
if (MYSERVER->hasArg("Angle90"))
{
Serial.println(MYSERVER->arg("Angle90"));
/* code */
}
Serial.println(MYSERVER->arg("pitchoffset"));
}
mywebserver::mywebserver()
{
if(SPIFFS.begin()){ // 启动闪存文件系统
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
server = new WebServer(80);
server->enableCORS(true);
MYSERVER=server;
server->onNotFound(handleUserRequet);
server->on("/setting",HTTP_GET,founddate);
}
mywebserver::mywebserver(int port)
{
Serial.begin(9600);
if(SPIFFS.begin()){ // 启动闪存文件系统
Serial.println("SPIFFS Started.");
} else {
Serial.println("SPIFFS Failed to Start.");
}
server = new WebServer(port);
server->enableCORS(true);
MYSERVER=server;
server->sendHeader("Access-Control-Allow-Origin", "*");
server->sendHeader("Access-Control-Allow-Methods","server->sendHeader");
server->onNotFound(handleUserRequet);
server->on("/setting",HTTP_GET,founddate);
}
void mywebserver::loop()
{
server->handleClient();
}
void mywebserver::begin()
{
server->begin();
}
void mywebserver::on(String str,void *funct())
{
server->on(str,funct);
}

25
src/mywebserver.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef MYWEBSERVER_H
#define MYWEBSERVER_H
#include<Arduino.h>
#include <WebServer.h>
static WebServer *MYSERVER;
class mywebserver
{
public:
mywebserver();
WebServer *server;
mywebserver(int port);
void loop();
void begin();
void on(String str,void *funct());
private:
};
#endif

View File

@ -1,354 +0,0 @@
// #ifndef WEBPAGES_H
// #define WEBPAGES_H
// #include <Arduino.h>
// const char index_html[] PROGMEM = R"rawliteral(
// <!DOCTYPE html>
// <html>
// <head>
// <title>ESP32 Data Display</title>
// <meta charset="UTF-8">
// <script>
// async function fetchData() {
// const response = await fetch('/data');
// if (!response.ok) {
// alert('数据获取失败');
// return;
// }
// const data = await response.json();
// document.getElementById('activeDuration').innerText = data.duration;
// document.getElementById('temperature').innerText = data.temperature;
// document.getElementById('humidity').innerText = data.humidity;
// document.getElementById('lightA').innerText = data.lightA;
// document.getElementById('lightB').innerText = data.lightB;
// document.getElementById('wiper').innerText = data.wiper;
// document.getElementById('busVoltage').innerText = data.busVoltage;
// document.getElementById('shuntVoltage').innerText = data.shuntVoltage;
// document.getElementById('current').innerText = data.current;
// document.getElementById('power').innerText = data.power;
// // 获取灯光状态
// const statusResponse = await fetch('/lightStatus');
// const statusText = await statusResponse.text();
// document.getElementById('lightStatus').innerText = statusText === 'on' ? '开启' : '关闭';
// // 获取自动调节状态
// const autoAdjustStatusResponse = await fetch('/autoAdjustStatus');
// const autoAdjustStatusText = await autoAdjustStatusResponse.text();
// document.getElementById('autoAdjustStatus').innerText = autoAdjustStatusText === 'enabled' ? '开启' : '关闭';
// }
// async function setWiper() {
// const wiperValue = document.getElementById('wiperValue').value;
// const response = await fetch('/setWiper', {
// method: 'POST',
// headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
// body: 'value=' + encodeURIComponent(wiperValue)
// });
// if (response.ok) {
// alert('Wiper value set successfully!');
// } else {
// alert('Failed to set Wiper value!');
// }
// }
// async function resetDuration() {
// const response = await fetch('/resetDuration', { method: 'POST' });
// if (response.ok) {
// alert('累计使用时长已清空');
// } else {
// alert('清空失败');
// }
// }
// async function turnOnLight() {
// const response = await fetch('/LightOpen', { method: 'POST' });
// if (response.ok) {
// updateLightStatus("开启");
// } else {
// alert('打开失败');
// }
// }
// async function turnOffLight() {
// const response = await fetch('/LightClose', { method: 'POST' });
// if (response.ok) {
// updateLightStatus("关闭");
// } else {
// alert('关闭失败');
// }
// }
// function updateLightStatus(status) {
// document.getElementById('lightStatus').innerText = status;
// }
// async function enableAutoAdjust() {
// const targetLux = document.getElementById('targetLux').value;
// if (!targetLux || isNaN(targetLux) || parseInt(targetLux) <= 0) {
// alert('请输入有效的正整数作为目标照度');
// return;
// }
// // 发送请求给 ESP32 开启自动调节并设置目标照度
// const response = await fetch('/startAutoAdjust', {
// method: 'POST',
// headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
// body: 'target=' + encodeURIComponent(targetLux)
// });
// if (response.ok) {
// alert('已开启自动调节');
// } else {
// alert('开启失败');
// }
// }
// async function disableAutoAdjust() {
// const response = await fetch('/stopAutoAdjust', { method: 'POST' });
// if (response.ok) {
// alert('已关闭自动调节');
// } else {
// alert('关闭失败');
// }
// }
// setInterval(fetchData, 1000); // 每秒刷新一次数据
// </script>
// </head>
// <body onload="fetchData()">
// <h1>实时数据显示</h1>
// <p>累计使用时长: <span id="activeDuration">加载中...</span></p>
// <button onclick="resetDuration()">清空累计时长</button>
// <p>温度: <span id="temperature">加载中...</span> °C</p>
// <p>湿度: <span id="humidity">加载中...</span> %RH</p>
// <p>光照强度A: <span id="lightA">加载中...</span> lx</p>
// <p>光照强度B: <span id="lightB">加载中...</span> lx</p>
// <p>电位器Wiper值: <span id="wiper">加载中...</span></p>
// <p>总线电压: <span id="busVoltage">加载中...</span> V</p>
// <p>分流电压: <span id="shuntVoltage">加载中...</span> mV</p>
// <p>电流: <span id="current">加载中...</span> A</p>
// <p>功率: <span id="power">加载中...</span> W</p>
// <h2>设置Wiper值</h2>
// <input type="range" id="wiperValue" min="0" max="127" step="1" value="2" />
// <button onclick="setWiper()">设置</button>
// <h2>灯光控制</h2>
// <p>灯光状态: <span id="lightStatus">加载中...</span></p>
// <button onclick="turnOnLight()">开灯</button>
// <button onclick="turnOffLight()">关灯</button>
// <h2>自动调节</h2>
// <p>状态: <span id="autoAdjustStatus">加载中...</span></p>
// <p>目标照度: <input type="number" id="targetLux" min="0" max="100000" step="1" value="2000" /> lux</p>
// <button onclick="enableAutoAdjust()">开启</button>
// <button onclick="disableAutoAdjust()">关闭</button>
// </body>
// </html>
// )rawliteral";
// #endif // WEBPAGES_H
#ifndef WEBPAGES_H
#define WEBPAGES_H
#include <Arduino.h>
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>ESP32 Data Display</title>
<meta charset="UTF-8">
<script>
async function fetchData() {
const response = await fetch('/data');
if (!response.ok) {
alert('');
return;
}
const data = await response.json();
document.getElementById('activeDuration').innerText = data.duration;
document.getElementById('temperature').innerText = data.temperature;
document.getElementById('humidity').innerText = data.humidity;
document.getElementById('lightA').innerText = data.lightA;
document.getElementById('lightB').innerText = data.lightB;
document.getElementById('wiper').innerText = data.wiper;
document.getElementById('busVoltage').innerText = data.busVoltage;
document.getElementById('shuntVoltage').innerText = data.shuntVoltage;
document.getElementById('current').innerText = data.current;
document.getElementById('power').innerText = data.power;
// 获取灯光状态
const statusResponse = await fetch('/lightStatus');
const statusText = await statusResponse.text();
document.getElementById('lightStatus').innerText = statusText === 'on' ? '' : '';
// 获取自动调节状态
const autoAdjustStatusResponse = await fetch('/autoAdjustStatus');
const autoAdjustStatusText = await autoAdjustStatusResponse.text();
document.getElementById('autoAdjustStatus').innerText = autoAdjustStatusText === 'enabled' ? '' : '';
}
async function setWiper() {
const wiperValue = document.getElementById('wiperValue').value;
const response = await fetch('/setWiper', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'value=' + encodeURIComponent(wiperValue)
});
if (response.ok) {
alert('Wiper value set successfully!');
} else {
alert('Failed to set Wiper value!');
}
}
async function resetDuration() {
const response = await fetch('/resetDuration', { method: 'POST' });
if (response.ok) {
alert('使');
} else {
alert('');
}
}
async function turnOnLight() {
const response = await fetch('/LightOpen', { method: 'POST' });
if (response.ok) {
updateLightStatus("开启");
} else {
alert('');
}
}
async function turnOffLight() {
const response = await fetch('/LightClose', { method: 'POST' });
if (response.ok) {
updateLightStatus("关闭");
} else {
alert('');
}
}
function updateLightStatus(status) {
document.getElementById('lightStatus').innerText = status;
}
async function enableAutoAdjust() {
const targetLux = document.getElementById('targetLux').value;
if (!targetLux || isNaN(targetLux) || parseInt(targetLux) <= 0) {
alert('');
return;
}
// 发送请求给 ESP32 开启自动调节并设置目标照度
const response = await fetch('/startAutoAdjust', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'target=' + encodeURIComponent(targetLux)
});
if (response.ok) {
alert('');
} else {
alert('');
}
}
async function disableAutoAdjust() {
const response = await fetch('/stopAutoAdjust', { method: 'POST' });
if (response.ok) {
alert('');
} else {
alert('');
}
}
setInterval(fetchData, 1000); // 每秒刷新一次数据
</script>
</head>
<body onload="fetchData()">
<h1></h1>
<p>使: <span id="activeDuration">...</span></p>
<button onclick="resetDuration()"></button>
<p>: <span id="temperature">...</span> °C</p>
<p>湿: <span id="humidity">...</span> %RH</p>
<p>A: <span id="lightA">...</span> lx</p>
<p>B: <span id="lightB">...</span> lx</p>
<p>Wiper值: <span id="wiper">...</span></p>
<p>线: <span id="busVoltage">...</span> V</p>
<p>: <span id="shuntVoltage">...</span> mV</p>
<p>: <span id="current">...</span> A</p>
<p>: <span id="power">...</span> W</p>
<h2>Wiper值</h2>
<input type="range" id="wiperValue" min="0" max="127" step="1" value="2" />
<button onclick="setWiper()"></button>
<h2></h2>
<p>: <span id="lightStatus">...</span></p>
<button onclick="turnOnLight()"></button>
<button onclick="turnOffLight()"></button>
<h2></h2>
<p>: <span id="autoAdjustStatus">...</span></p>
<p>: <input type="number" id="targetLux" min="0" max="100000" step="1" value="2000" /> lux</p>
<button onclick="enableAutoAdjust()"></button>
<button onclick="disableAutoAdjust()"></button>
</body>
</html>
)rawliteral";
// 新增 config_html 页面
const char config_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>ESP32 WiFi Setup</title>
<meta charset="UTF-8">
<script>
async function saveWiFiSettings() {
const ssid = document.getElementById("ssid").value;
const password = document.getElementById("password").value;
const response = await fetch("/saveWiFi", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "ssid=" + encodeURIComponent(ssid) + "&password=" + encodeURIComponent(password)
});
if (response.ok) {
alert("WiFi 设置保存成功!");
} else {
alert("保存失败,请重试。");
}
}
</script>
</head>
<body>
<h1>WiFi </h1>
<form onsubmit="event.preventDefault(); saveWiFiSettings();">
<label for="ssid">SSID:</label><br/>
<input type="text" id="ssid" name="ssid"><br/><br/>
<label for="password">:</label><br/>
<input type="password" id="password" name="password"><br/><br/>
<input type="submit" value="保存">
</form>
</body>
</html>
)rawliteral";
#endif // WEBPAGES_H