ESP32软AP模式下WebServer无法执行HTML中的JavaScript文件,实时压力图表不显示
ESP32软AP模式下WebServer无法执行HTML中的JavaScript文件,实时压力图表不显示
你已经精准定位到了核心问题——ESP32软AP模式下无法访问互联网,导致HTML中引用的在线Highcharts图表库脚本加载失败,进而依赖这个库的本地JavaScript代码完全无法启动执行。
虽然你确认了/readings接口能正常返回数据,本地JS文件单独运行时功能正常,但因为在线脚本加载失败,后续的图表初始化、数据绘制逻辑都没有触发的基础。
下面是具体的修复步骤和优化建议:
修复步骤
1. 下载Highcharts本地文件
前往Highcharts官方渠道下载和你之前在线引用版本一致的highcharts.js文件(确保功能兼容)。
2. 上传本地资源到LittleFS
将下载好的highcharts.js,和你的index.html、script.js、style.css、favicon.png等文件一起,通过Arduino IDE的ESP32 Sketch Data Upload插件(需提前安装)上传到ESP32的LittleFS分区中。
3. 修改HTML的脚本引用
把HTML中原来的在线脚本引用替换为本地路径:
<!-- 原在线引用(注释或删除) --> <!-- <script src="https://code.highcharts.com/highcharts.js"></script> --> <!-- 替换为本地引用 --> <script type="text/javascript" src="/highcharts.js"></script>
4. 验证LittleFS文件结构
确保LittleFS根目录下的文件完整:
/ ├─ index.html ├─ script.js ├─ highcharts.js ├─ style.css └─ favicon.png
额外调试建议
- 连接ESP32软AP后,打开浏览器访问ESP32的IP地址,按
F12打开开发者工具,切换到**控制台(Console)**标签,查看是否有Failed to load resource类的加载错误——这是最直接的问题验证方式。 - 你的
AsyncWebServer配置中server.serveStatic("/", LittleFS, "/");已经正确设置了静态资源根路径,无需修改。
整理后的完整代码
Arduino代码(.ino)
#include <Arduino.h> #include <WiFi.h> #include <AsyncTCP.h> #include <ESPAsyncWebServer.h> #include <LittleFS.h> #include <Arduino_JSON.h> #define ZERO_SAMPLES 50 #define COUNTS_PER_PSI 735990 // Increased to further scale down PSI values #define PSI_TO_CMH2O 70.307 // Conversion factor from PSI to cmH2O #define DRIFT_THRESHOLD 0.1 // PSI threshold to consider as "no pressure" #define STABLE_TIME 3000 // Time in ms that readings need to be stable for re-zeroing #define DRIFT_SAMPLES 10 // SoftAP credentials const char* ssid = "ESP32"; const char* password = NULL; long zeroOffset = 8290303; bool isCalibrated = false; int sampleCount = 0; long calibrationSum = 0; // Drift compensation variables unsigned long stableStartTime = 0; bool isStable = false; float lastPSI = 0; int stableSampleCount = 0; const int inputpin = 15; const int outputpin = 2; char pressuredata[40]; // Create AsyncWebServer object on port 80 AsyncWebServer server(80); // Create an Event Source on /events AsyncEventSource events("/events"); // Json Variable to Hold Sensor Readings JSONVar readings; // Timer variables unsigned long lastTime = 0; unsigned long timerDelay = 750; // Initialize LittleFS void initLittleFS() { if (!LittleFS.begin()) { Serial.println("An error has occurred while mounting LittleFS"); } else{ Serial.println("LittleFS mounted successfully"); } } void checkAndUpdateZero(long rawPressure, float currentPSI) { // Check if current pressure is close to zero if (abs(currentPSI - 1) < DRIFT_THRESHOLD) { // Remember we're applying -1 offset to PSI if (!isStable) { // Start tracking stable period isStable = true; stableStartTime = millis(); stableSampleCount = 1; } else { stableSampleCount++; // Check if we've been stable long enough and have enough samples if (stableSampleCount >= DRIFT_SAMPLES && (millis() - stableStartTime) >= STABLE_TIME) { // Update zero offset zeroOffset = rawPressure; stableSampleCount = 0; isStable = false; } } } else { // Reset stable tracking if pressure is not near zero isStable = false; stableSampleCount = 0; } } float convertToPSI(long rawValue, long zero) { return (float)(rawValue - zero) / COUNTS_PER_PSI; } String readPressureRaw() { while (digitalRead(inputpin)) {} long result = 0; noInterrupts(); for (int i = 0; i < 24; i++) { digitalWrite(outputpin, HIGH); digitalWrite(outputpin, LOW); result = (result << 1); if (digitalRead(inputpin)) { result++; } } for (char i = 0; i < 3; i++) { digitalWrite(outputpin, HIGH); digitalWrite(outputpin, LOW); } interrupts(); long pressure = result ^ 0x800000; if (!isCalibrated){ calibrationSum += pressure; sampleCount++; readings["sensor1"] = String(0,3); if (sampleCount >= 15){ long zeroOffset = calibrationSum/15; isCalibrated = true; } } else { float psi = convertToPSI(pressure , zeroOffset); float cmH20 = psi * 70.307; checkAndUpdateZero(pressure,psi); String pressuredata = String(cmH20,3); readings["sensor1"] = pressuredata; } String jsonresult = JSON.stringify(readings); return jsonresult; } void setup() { pinMode(inputpin,INPUT); pinMode(outputpin, OUTPUT); Serial.begin(115200); Serial.println(); // Setting the ESP as an access point Serial.print("Setting AP (Access Point)…"); WiFi.softAP(ssid, password); IPAddress IP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(IP); initLittleFS(); digitalWrite(outputpin, LOW); for(int i = 0; i < 10; i++) { digitalWrite(outputpin, HIGH); digitalWrite(outputpin, LOW); } // Web Server Root URL server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(LittleFS, "/index.html", "text/html"); }); server.serveStatic("/", LittleFS, "/"); // Request for the latest sensor readings server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){ String json = readPressureRaw(); request->send(200, "application/json", json); json = String(); }); events.onConnect([](AsyncEventSourceClient *client){ if(client->lastId()){ Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId()); } client->send("hello!", NULL, millis(), 10000); }); server.addHandler(&events); // Start server server.begin(); } void loop() { if ((millis() - lastTime) > timerDelay) { events.send("ping",NULL,millis()); events.send(readPressureRaw().c_str(),"new_readings" ,millis()); lastTime = millis(); } }
修改后的HTML文件
<!DOCTYPE html> <html> <head> <title>DASHBOARD</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/png" href="favicon.png"> <link rel="stylesheet" type="text/css" href="style.css"> <!-- 本地Highcharts引用 --> <script type="text/javascript" src="/highcharts.js"></script> </head> <body> <div class="topnav"> <h1 id="header"> Pressure Waveform and Control Data</h1> </div> <div class="content"> <div class="card-grid"> <div class="card"> <p id = "id1" class="card-title">Pressure Chart</p> <div id="chart-pressure" class="chart-container"></div> </div> </div> </div> <script type="text/javascript" src="script.js"></script> </body> </html>
JavaScript文件(script.js)
window.addEventListener('load', getReadings); var chartT = new Highcharts.Chart({ chart:{ renderTo:'chart-pressure' }, series: [ { name: 'Pressure #21', type: 'line', color: '#101D42', }, ], title: { text: undefined }, xAxis: { type: 'datetime', dateTimeLabelFormats: { second: '%H:%M:%S' } }, yAxis: { title: { text: 'Pressure ' } }, credits: { enabled: false } }); function plotPressure(jsonValue) { var keys = Object.keys(jsonValue); var x = (new Date()).getTime(); const key = keys[0]; var y = Number(jsonValue[key]); if(chartT.series[0].data.length > 40) { chartT.series[0].addPoint([x, y], true, true, true); } else { chartT.series[0].addPoint([x, y], true, false, true); } } function getReadings(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var myObj = JSON.parse(this.responseText); console.log(myObj); plotPressure(myObj); } }; xhr.open("GET", "/readings", true); xhr.send(); } if (!!window.EventSource) { var source = new EventSource('/events'); source.addEventListener('open', function(e) { console.log("Events Connected"); }, false); source.addEventListener('error', function(e) { if (e.target.readyState != EventSource.OPEN) { console.log("Events Disconnected"); } }, false); source.addEventListener('message', function(e) { console.log("message", e.data); }, false); source.addEventListener('new_readings', function(e) { console.log("new_readings", e.data); var myObj = JSON.parse(e.data); plotPressure(myObj); }, false); }
备注:内容来源于stack exchange,提问作者Agasthya Valluri
相关产品推荐
相关产品推荐

