Add firmware versioning and improve timer precision in web server
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
// 固件版本信息
|
||||
#define FIRMWARE_VERSION "v2.1.0"
|
||||
#define BUILD_DATE __DATE__
|
||||
#define BUILD_TIME __TIME__
|
||||
#define FIRMWARE_NAME "PetIO"
|
||||
|
||||
// WiFi 配置
|
||||
#define DEFAULT_AP_SSID "PetIO_Setup"
|
||||
#define WIFI_TIMEOUT 30000 // 30秒
|
||||
|
||||
18
src/main.cpp
18
src/main.cpp
@@ -17,7 +17,7 @@ WebServer webServer(&wifiManager, &timerManager, &timeManager);
|
||||
unsigned long lastUpdate = 0;
|
||||
unsigned long lastWiFiCheck = 0;
|
||||
unsigned long lastTimeUpdate = 0;
|
||||
const unsigned long UPDATE_INTERVAL = 1000; // 1秒
|
||||
const unsigned long UPDATE_INTERVAL = 10; // 10毫秒 - 高精度定时器更新
|
||||
const unsigned long WIFI_CHECK_INTERVAL = 30000; // 30秒
|
||||
const unsigned long TIME_UPDATE_INTERVAL = 10000; // 10秒
|
||||
|
||||
@@ -100,9 +100,16 @@ void loop()
|
||||
{
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// 处理 Web 请求
|
||||
// 处理 Web 请求 (优先级最高)
|
||||
webServer.handleClient();
|
||||
|
||||
// 高频更新定时器 (10ms间隔,确保定时器精度)
|
||||
if (currentTime - lastUpdate >= UPDATE_INTERVAL)
|
||||
{
|
||||
timerManager.update();
|
||||
lastUpdate = currentTime;
|
||||
}
|
||||
|
||||
// 定期更新时间同步
|
||||
if (currentTime - lastTimeUpdate >= TIME_UPDATE_INTERVAL)
|
||||
{
|
||||
@@ -110,13 +117,6 @@ void loop()
|
||||
lastTimeUpdate = currentTime;
|
||||
}
|
||||
|
||||
// 定期更新定时器
|
||||
if (currentTime - lastUpdate >= UPDATE_INTERVAL)
|
||||
{
|
||||
timerManager.update();
|
||||
lastUpdate = currentTime;
|
||||
}
|
||||
|
||||
// 定期检查 WiFi 连接
|
||||
if (currentTime - lastWiFiCheck >= WIFI_CHECK_INTERVAL)
|
||||
{
|
||||
|
||||
@@ -81,7 +81,8 @@ void TimerManager::update() {
|
||||
|
||||
String modeStr = timers[i].isPWM ? " PWM(" + String(timers[i].pwmValue) + ")" : "";
|
||||
Serial.println("定时器 " + String(i) + " 激活,引脚 " + String(timers[i].pin) + " 开启" + modeStr +
|
||||
(timers[i].repeatDaily ? " (每天重复)" : " (单次)"));
|
||||
(timers[i].repeatDaily ? " (每天重复)" : " (单次)") +
|
||||
", 预期运行时间: " + String(timers[i].duration * 1000.0) + "ms");
|
||||
|
||||
stateChanged = true;
|
||||
|
||||
@@ -94,13 +95,13 @@ void TimerManager::update() {
|
||||
|
||||
// 检查是否需要关闭
|
||||
if (timers[i].isActive &&
|
||||
currentTime - timers[i].startTime >= (unsigned long)(timers[i].duration * 1000.0)) {
|
||||
currentTime - timers[i].startTime >= (unsigned long)(timers[i].duration * 1000.0 + 0.5)) {
|
||||
|
||||
timers[i].isActive = false;
|
||||
timers[i].realStartTime = 0; // 清理真实时间戳
|
||||
setPin(timers[i].pin, LOW, 0);
|
||||
|
||||
Serial.println("定时器 " + String(i) + " 完成,引脚 " + String(timers[i].pin) + " 关闭");
|
||||
Serial.println("定时器 " + String(i) + " 完成,引脚 " + String(timers[i].pin) + " 关闭,实际运行时间: " + String(currentTime - timers[i].startTime) + "ms");
|
||||
stateChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,6 +640,8 @@ const char INDEX_HTML[] PROGMEM = R"rawliteral(
|
||||
systemInfo: null
|
||||
};
|
||||
|
||||
let isLoadingData = false;
|
||||
|
||||
// --- Class definitions for styling ---
|
||||
const activeTabClasses = ['active', 'text-indigo-600', 'font-semibold'];
|
||||
const inactiveTabClasses = ['text-gray-500', 'hover:text-gray-700'];
|
||||
@@ -653,10 +655,34 @@ const char INDEX_HTML[] PROGMEM = R"rawliteral(
|
||||
tab.classList.add(...inactiveTabClasses);
|
||||
}
|
||||
});
|
||||
|
||||
// Set current time as default for timer
|
||||
setCurrentTimeAsDefault();
|
||||
|
||||
loadData();
|
||||
setInterval(loadData, 5000);
|
||||
// 使用异步轮询替代 setInterval
|
||||
startPolling();
|
||||
});
|
||||
|
||||
function setCurrentTimeAsDefault() {
|
||||
const now = new Date();
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const currentTime = `${hours}:${minutes}`;
|
||||
document.getElementById('timer-time').value = currentTime;
|
||||
}
|
||||
|
||||
function startPolling() {
|
||||
async function poll() {
|
||||
if (!isLoadingData) {
|
||||
await loadData();
|
||||
}
|
||||
// 等待5秒后再次轮询
|
||||
setTimeout(poll, 5000);
|
||||
}
|
||||
poll();
|
||||
}
|
||||
|
||||
function switchTab(tabName, clickedTab) {
|
||||
document.querySelectorAll('.tab-content').forEach(content => content.classList.add('hidden'));
|
||||
document.querySelectorAll('.tab').forEach(tab => {
|
||||
@@ -674,6 +700,11 @@ const char INDEX_HTML[] PROGMEM = R"rawliteral(
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
if (isLoadingData) {
|
||||
return; // 如果正在加载,直接返回
|
||||
}
|
||||
|
||||
isLoadingData = true;
|
||||
try {
|
||||
const [statusRes, timersRes, pinsRes] = await Promise.all([
|
||||
fetch('/api/status'),
|
||||
@@ -698,6 +729,8 @@ const char INDEX_HTML[] PROGMEM = R"rawliteral(
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error);
|
||||
document.getElementById('connection-status').innerHTML = `<span class="inline-flex items-center px-2.5 py-0.5 rounded-full bg-red-100 text-red-800">加载失败</span>`;
|
||||
} finally {
|
||||
isLoadingData = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1128,8 +1161,8 @@ const char INDEX_HTML[] PROGMEM = R"rawliteral(
|
||||
const response = await fetch('/api/system');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
document.getElementById('current-version').textContent = `v1.0.0`;
|
||||
document.getElementById('build-time').textContent = new Date().toLocaleDateString();
|
||||
document.getElementById('current-version').textContent = data.firmwareVersion || 'v1.0.0';
|
||||
document.getElementById('build-time').textContent = data.buildDateTime || '未知';
|
||||
document.getElementById('firmware-chip-id').textContent = data.chipId || '未知';
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "web_server.h"
|
||||
#include "config.h"
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
#include <Updater.h>
|
||||
|
||||
@@ -134,6 +135,13 @@ void WebServer::handleGetSystemInfo() {
|
||||
|
||||
JsonDocument doc;
|
||||
|
||||
// 固件信息
|
||||
doc["firmwareVersion"] = FIRMWARE_VERSION;
|
||||
doc["firmwareName"] = FIRMWARE_NAME;
|
||||
doc["buildDate"] = BUILD_DATE;
|
||||
doc["buildTime"] = BUILD_TIME;
|
||||
doc["buildDateTime"] = String(BUILD_DATE) + " " + String(BUILD_TIME);
|
||||
|
||||
// 基本系统信息
|
||||
doc["chipId"] = String(ESP.getChipId(), HEX);
|
||||
doc["flashChipId"] = String(ESP.getFlashChipId(), HEX);
|
||||
|
||||
Reference in New Issue
Block a user