Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
665e230192 | ||
|
|
5288ffa07d | ||
|
|
97c43d282c |
No files matched your search
@@ -3,3 +3,5 @@
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
*.bin
|
||||
release_v*.json
|
||||
Binary file not shown.
@@ -1,10 +1,10 @@
|
||||
# ClearESP WindSensors
|
||||
# ClearMCU-Wind
|
||||
|
||||
## 项目简介
|
||||
|
||||
ClearESP WindSensors 是基于 `ESP32-C3` 的 RS485 风速风向传感器采集网关固件,面向现场部署、批量站号配置、Web 运维和 MQTT 上报场景。
|
||||
ClearMCU-Wind 是基于 `ESP32-C3` 的 RS485 风速风向传感器采集网关固件,面向现场部署、批量站号配置、Web 运维和 MQTT 上报场景。
|
||||
|
||||
当前固件版本:`RC1.0.4`
|
||||
当前固件版本:`RC2.0`
|
||||
|
||||
## 主要功能
|
||||
|
||||
@@ -101,7 +101,7 @@ ClearESP WindSensors 是基于 `ESP32-C3` 的 RS485 风速风向传感器采集
|
||||
|
||||
AP 名称格式:
|
||||
|
||||
- `ClearESP-Wind-<MAC>`
|
||||
- `ClearMCU-Wind-<MAC>`
|
||||
|
||||
### 4. Web 页面
|
||||
|
||||
@@ -209,7 +209,7 @@ AP 名称格式:
|
||||
```json
|
||||
{
|
||||
"mac": "B43A455471D4",
|
||||
"firmware_version": "RC1.0.4",
|
||||
"firmware_version": "RC2.0",
|
||||
"uptime_ms": 123456,
|
||||
"sensors": [
|
||||
{
|
||||
@@ -241,11 +241,8 @@ platformio run
|
||||
platformio run -t upload
|
||||
```
|
||||
|
||||
## RC1.0.4 变更
|
||||
## RC2.0 变更
|
||||
|
||||
- MQTT 仅保留 `/realtime` 上报与页面展示
|
||||
- 系统状态页显示固件版本
|
||||
- 云服务页 OTA 卡片改为现场可用的检查更新 / 下载升级流程
|
||||
- OTA 页面不再向用户展示项目地址或固件直链
|
||||
- 补齐 OTA 检查与升级接口
|
||||
- 修正文档中文乱码并同步更新说明
|
||||
- 品牌字样统一更新为 `ClearMCU-Wind`
|
||||
- 固件版本升级为 `RC2.0`
|
||||
- 保留既有 OTA、MQTT、Web 管理与现场配置能力
|
||||
+68
-9
@@ -30,8 +30,10 @@ constexpr uint32_t MODBUS_RESPONSE_TIMEOUT_MS = 500;
|
||||
constexpr uint32_t WIFI_RETRY_INTERVAL_MS = 15000;
|
||||
constexpr uint32_t WIFI_CONNECT_TIMEOUT_MS = 20000;
|
||||
constexpr bool ENABLE_BOOT_DIAGNOSTICS = false;
|
||||
constexpr char FIRMWARE_VERSION[] = "RC1.0.4";
|
||||
constexpr char FIRMWARE_VERSION[] = "RC2.0";
|
||||
constexpr char OTA_PROJECT_URL[] = "http://107.173.157.41:3000/clear/wind_vt_esp32";
|
||||
constexpr char OTA_LATEST_RELEASE_API_URL[] =
|
||||
"http://107.173.157.41:3000/api/v1/repos/clear/wind_vt_esp32/releases/latest";
|
||||
constexpr uint16_t MQTT_DEFAULT_PORT = 1883;
|
||||
constexpr uint32_t MQTT_RETRY_INTERVAL_MS = 10000;
|
||||
constexpr uint32_t MQTT_PUBLISH_INTERVAL_MS = 1000;
|
||||
@@ -108,7 +110,7 @@ const char WEB_PAGE[] PROGMEM = R"HTML(
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<title>ClearESP Wind</title>
|
||||
<title>ClearMCU-Wind</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg0: #081118;
|
||||
@@ -478,7 +480,7 @@ const char WEB_PAGE[] PROGMEM = R"HTML(
|
||||
<section class="topbar">
|
||||
<div class="brandline">
|
||||
<div class="brand">
|
||||
<h1>ClearESP WindSensors</h1>
|
||||
<h1>ClearMCU-Wind</h1>
|
||||
<div class="brand-note">数字植物实验室</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -598,6 +600,16 @@ const char WEB_PAGE[] PROGMEM = R"HTML(
|
||||
<section id="page-cloud" class="panel page">
|
||||
<h2>云服务</h2>
|
||||
<div class="stack">
|
||||
<div class="api-card">
|
||||
<div class="label">OTA</div>
|
||||
<div class="subtext" id="otaIntro">OTA 需要设备先连接外部 WiFi。检测到新版本后,可直接下载并升级。</div>
|
||||
<div class="subtext" id="otaSummary">当前固件版本 -- | 最新版本 --</div>
|
||||
<div class="subtext" id="otaStatusText" style="color:#cfe7de;">--</div>
|
||||
<div class="actions">
|
||||
<button id="btnOtaCheck" class="action ghost" onclick="checkOtaUpdate()">检查更新</button>
|
||||
<button id="btnOtaUpdate" class="action" onclick="startOtaUpdate()">下载并升级</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subtext">
|
||||
配置 MQTT 服务器后,设备会自动连接并上报传感器列表与实时数据。上报内容会带上设备 MAC,用于区分设备身份。
|
||||
</div>
|
||||
@@ -990,10 +1002,57 @@ const char WEB_PAGE[] PROGMEM = R"HTML(
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupDuplicateOtaNodes() {
|
||||
const duplicatedIds = ['otaSummary', 'otaStatusText', 'btnOtaCheck', 'btnOtaUpdate'];
|
||||
duplicatedIds.forEach((id) => {
|
||||
const nodes = document.querySelectorAll(`[id="${id}"]`);
|
||||
nodes.forEach((node, index) => {
|
||||
if (index > 0) {
|
||||
const card = node.closest('.api-card');
|
||||
if (card) {
|
||||
card.remove();
|
||||
} else {
|
||||
node.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderOtaPanel(data) {
|
||||
const intro = document.getElementById('otaIntro');
|
||||
const summary = document.getElementById('otaSummary');
|
||||
const status = document.getElementById('otaStatusText');
|
||||
const btnCheck = document.getElementById('btnOtaCheck');
|
||||
const btnUpdate = document.getElementById('btnOtaUpdate');
|
||||
const latestVersion = data.otaLatestVersion
|
||||
? (data.otaLatestVersion.startsWith('v') ? `RC${data.otaLatestVersion.slice(1)}` : data.otaLatestVersion)
|
||||
: '--';
|
||||
|
||||
if (intro) {
|
||||
intro.textContent = 'OTA 需要设备先连接外部 WiFi。检测到新版本后,可直接下载并升级。';
|
||||
}
|
||||
if (summary) {
|
||||
summary.textContent = `当前固件版本 ${data.firmwareVersion} | 最新版本 ${latestVersion}`;
|
||||
}
|
||||
if (status) {
|
||||
status.textContent = data.otaStatus || '--';
|
||||
}
|
||||
if (btnCheck) {
|
||||
btnCheck.disabled = busy;
|
||||
btnCheck.textContent = '检查更新';
|
||||
}
|
||||
if (btnUpdate) {
|
||||
btnUpdate.disabled = busy || !data.otaUpdateAvailable;
|
||||
btnUpdate.textContent = '下载并升级';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
scheduleRefresh(document.hidden ? 1200 : 100);
|
||||
});
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
cleanupDuplicateOtaNodes();
|
||||
const ssidInput = document.getElementById('wifiSsid');
|
||||
const passInput = document.getElementById('wifiPass');
|
||||
[ssidInput, passInput].forEach((input) => {
|
||||
@@ -1112,7 +1171,7 @@ String otaReleaseTag() {
|
||||
}
|
||||
|
||||
String otaAssetName() {
|
||||
return "ClearESP-WindSensors-ESP32C3-" + otaReleaseTag() + ".bin";
|
||||
return "ClearMCU-Wind-ESP32C3-" + otaReleaseTag() + ".bin";
|
||||
}
|
||||
|
||||
String otaReleaseUrl() {
|
||||
@@ -1124,7 +1183,7 @@ String otaBinUrl() {
|
||||
}
|
||||
|
||||
String otaAssetNameForTag(const String &tag) {
|
||||
return "ClearESP-WindSensors-ESP32C3-" + tag + ".bin";
|
||||
return "ClearMCU-Wind-ESP32C3-" + tag + ".bin";
|
||||
}
|
||||
|
||||
String otaReleaseUrlForTag(const String &tag) {
|
||||
@@ -1610,7 +1669,7 @@ bool fetchLatestOtaRelease(String &latestTag, String &latestBin, String &error)
|
||||
|
||||
HTTPClient http;
|
||||
WiFiClient client;
|
||||
const String url = String(OTA_PROJECT_URL) + "/api/v1/repos/clear/wind_vt_esp32/releases/latest";
|
||||
const String url = OTA_LATEST_RELEASE_API_URL;
|
||||
if (!http.begin(client, url)) {
|
||||
error = "无法建立 OTA 检查连接";
|
||||
return false;
|
||||
@@ -1740,7 +1799,7 @@ bool startMqttConnect(bool forceNow) {
|
||||
mqttClient->setServer(state.mqttHost.c_str(), state.mqttPort);
|
||||
mqttClient->setBufferSize(MQTT_BUFFER_SIZE);
|
||||
|
||||
const String clientId = "ClearESP-" + hexMacString();
|
||||
const String clientId = "ClearMCU-" + hexMacString();
|
||||
const bool ok = state.mqttUsername.isEmpty()
|
||||
? mqttClient->connect(clientId.c_str())
|
||||
: mqttClient->connect(clientId.c_str(), state.mqttUsername.c_str(),
|
||||
@@ -2111,7 +2170,7 @@ String buildNetworkJson() {
|
||||
|
||||
String buildSystemJson() {
|
||||
String json = "{";
|
||||
json += "\"device\":\"ClearESP-Wind\",";
|
||||
json += "\"device\":\"ClearMCU-Wind\",";
|
||||
json += "\"mac\":\"" + hexMacString() + "\",";
|
||||
json += "\"firmware_version\":\"" + String(FIRMWARE_VERSION) + "\",";
|
||||
json += "\"ota_latest_version\":\"" + jsonEscaped(state.otaLatestVersion) + "\",";
|
||||
@@ -2429,7 +2488,7 @@ void setupWebServer() {
|
||||
}
|
||||
|
||||
void setupWiFiAp() {
|
||||
state.apSsid = "ClearESP-Wind-" + hexMacString();
|
||||
state.apSsid = "ClearMCU-Wind-" + hexMacString();
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
WiFi.setAutoReconnect(true);
|
||||
WiFi.persistent(false);
|
||||
|
||||
Reference in new issue
Block a user