ساخت سرور ایستگاه هواشناسی با BME280 و برد ESP32

به اپلیکیشنهای هواشناسی گوشی یا ایستگاههای تجاری که دادهها را از ایستگاههایی در فاصله چند مایلی ارائه میدهند، اکتفا نکنید. با این پروژه اینترنت اشیاء، شما میتوانید خودتان پیشبینیکننده هوا باشید!
این پروژه از ESP32 به عنوان دستگاه کنترلکننده استفاده میکند که به راحتی به هر شبکه وایفای موجود متصل شده و یک وبسرور ایجاد میکند. هر دستگاه متصل که به این وبسرور دسترسی پیدا کند، ESP32 دادههای دما، رطوبت، فشار بارومتریک و ارتفاع را از سنسور BME280 دریافت کرده و آنها را با رابط کاربری مناسب در مرورگر وب دستگاه نمایش میدهد. هیجانزدهاید؟ بیایید شروع کنیم!
معرفی سنسور BME280
ابتدا به طور مختصر درباره ماژول BME280 توضیح میدهیم.
BME280 یک سنسور دیجیتال نسل جدید برای اندازهگیری دما، رطوبت و فشار است که توسط شرکت Bosch تولید میشود. این سنسور جانشین مدلهایی مانند BMP180، BMP085 و BMP183 است.
مشخصات سنسور برای دما، رطوبت، فشار و ارتفاع
ماژول BME280 در محدوده ولتاژ 3.3 تا 5 ولت عمل میکند و برای اتصال به میکروکنترلرهایی با ولتاژ 3.3 ولت مانند ESP32 بسیار مناسب است.
این ماژول از یک رابط ساده دو سیمه I2C برای ارتباط استفاده میکند. آدرس پیشفرض I2C برای ماژول BME280 برابر با 0x76 است، اما میتوان آن را به سادگی به 0x77 تغییر داد.
اتصال سنسور BME280 به ESP32
اتصالات بسیار ساده هستند. ابتدا پین VIN ماژول BME280 را به خروجی 3.3 ولت ESP32 و پین GND را به زمین متصل کنید.
سپس پین SCL ماژول BME280 را به پین D22 (ساعت I2C) و پین SDA را به پین D21 (داده I2C) متصل کنید.
جدول زیر اتصالات پینها را نشان میدهد:
سنسور BME280 | ESP32 |
---|---|
VCC | 3.3V |
GND | GND |
SCL | D22 |
SDA | D21 |
نمودار زیر نحوه سیمبندی کامل را نشان میدهد.
آمادهسازی Arduino IDE برای سنسور BME280
یک افزونه برای Arduino IDE وجود دارد که به شما امکان میدهد ESP32 را مستقیماً در محیط Arduino IDE برنامهنویسی کنید. اگر هنوز آن را راهاندازی نکردهاید، از آموزش برنامه نویسی ESP32 در آردوینو استفاده کنید.
ارتباط با ماژول BME280 کمی پیچیده به نظر میرسد، اما خوشبختانه کتابخانه Adafruit BME280 این پیچیدگیها را ساده کرده و امکان صدور دستورات ساده برای خواندن دما، رطوبت نسبی و فشار بارومتریک را فراهم میکند.
برای نصب این کتابخانه، در Arduino IDE مسیر Sketch > Include Library > Manage Libraries… را دنبال کنید و منتظر بمانید تا Library Manager فهرست کتابخانهها را بهروزرسانی کند.
برای پیدا کردن کتابخانه، عبارت «bme280» را در فیلتر جستجو وارد کنید. چند نتیجه ظاهر میشود؛ کتابخانه Adafruit BME280 Library توسط Adafruit را پیدا کرده و روی آن کلیک کرده و سپس Install را انتخاب کنید.
توجه داشته باشید که کتابخانه سنسور BME280 به پشتیبانی Adafruit Sensor Backend وابسته است. در Library Manager عبارت Adafruit Unified Sensor را جستجو کرده و آن را نیز نصب کنید.
پروژه نمایش دما، رطوبت، فشار و ارتفاع در سرور ESP32
اکنون بیایید ESP32 را طوری تنظیم کنیم که در حالت Station (STA) عمل کند و به شبکه وایفای موجود متصل شود و یک وبسرور ایجاد کند. این وبسرور صفحات وب را به هر دستگاه متصل به شبکه ارائه میدهد.
اگر میخواهید نحوه ایجاد وبسرور با ESP32 در حالت AP/STA را بیاموزید، میتوانید به این آموزش مراجعه کنید: آموزش ساخت 4 وب سرور با برد ESP32
ESP32 یکی از محبوبترین میکروکنترلرها در دنیای اینترنت اشیاء است و ویژگی های خوبی هم دارد؛ قدرتمند، مقرون به صرفه و دارای قابلیتهای داخلی فراوان است.
قبل از آپلود کد، باید یک تغییر مهم ایجاد کنید: دو متغیر زیر را با مشخصات شبکه خودتان بهروز کنید تا ESP32 بتواند به شبکه متصل شود.
const char* ssid = "YourNetworkName"; // نام شبکه خود را وارد کنید
const char* password = "YourPassword"; // رمز عبور شبکه خود را وارد کنید
پس از اعمال تغییرات، اسکچ را اجرا کنید.
کد کامل پروژه در فایل دانلودی انتهای صفحه قرار داده شده است. در اینجا قسمت های مهم کد را توضیح میدهیم.
دسترسی به وبسرور
پس از آپلود اسکچ، Serial Monitor را باز کرده و نرخ انتقال را روی 115200 قرار دهید، سپس دکمه EN روی ESP32 را فشار دهید. آدرس IP پویا که از روتر دریافت کردهاید و پیام «HTTP server started» نمایش داده میشود.
حالا مرورگر را باز کرده و به آدرس IP نمایش داده شده در Serial Monitor بروید. ESP32 صفحهای را ارائه میدهد که شامل دادههای دما، رطوبت، فشار و ارتفاع از سنسور BME280 است.
توضیح دقیق کد
اسکچ با وارد کردن کتابخانههای زیر شروع میشود:
- WiFi.h: روشهای مخصوص ESP32 برای اتصال به شبکه وایفای را ارائه میدهد.
- WebServer.h: متدهایی برای راهاندازی سرور و مدیریت درخواستهای HTTP ورودی فراهم میکند.
- Wire.h: امکان ارتباط با هر دستگاه I2C، از جمله BME280، را فراهم میکند.
- Adafruit_BME280.h و Adafruit_Sensor.h: کتابخانههای سختافزاری هستند که وظایف سطح پایین سنسور را مدیریت میکنند.
#include <WiFi.h> #include <WebServer.h> #include <Wire.h> #include <Adafruit_Sensor.h> #include <Adafruit_BME280.h>
سپس یک شیء برای سنسور ایجاد میکنیم و متغیرهایی برای ذخیره دادههای دما، رطوبت، فشار و ارتفاع تعریف میکنیم.
#define SEALEVELPRESSURE_HPA (1013.25) Adafruit_BME280 bme; float temperature, humidity, pressure, altitude;
از آنجا که ESP32 را در حالت Station (STA) پیکربندی میکنیم، باید SSID و رمز عبور شبکه را مشخص کنیم و سپس وبسرور را روی پورت 80 راهاندازی کنیم.
const char* ssid = "YourNetworkName"; const char* password = "YourPassword"; WebServer server(80);
بخش Setup()
در تابع setup()، سرور HTTP را پیکربندی میکنیم.
ابتدا ارتباط سریال با کامپیوتر برقرار میشود و شیء BME با تابع begin() مقداردهی اولیه میشود. این تابع رابط I2C را با آدرس داده شده (0x76) راهاندازی کرده، شناسه تراشه را بررسی میکند، تراشه را ریست نرمافزاری میکند و پس از بیداری سنسور منتظر کالیبراسیون میماند.
Serial.begin(115200); delay(100); bme.begin(0x76);
سپس ESP32 تلاش میکند با استفاده از WiFi.begin() به شبکه وصل شود، که SSID و رمز عبور را به عنوان پارامتر میگیرد.
Serial.println("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password);
در حین تلاش برای اتصال، وضعیت اتصال با WiFi.status() بررسی میشود.
while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); }
پس از اتصال موفق، آدرس IP ESP32 با WiFi.localIP() در Serial Monitor نمایش داده میشود.
Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP());
برای مدیریت درخواستهای HTTP ورودی، مشخص میکنیم هنگام دسترسی به یک URL خاص چه کدی اجرا شود. با server.on() این کار انجام میشود و دو پارامتر میگیرد: مسیر URL و نام تابعی که هنگام دسترسی به آن مسیر اجرا میشود.
server.on("/", handle_OnConnect);
در صورتی که درخواست URL مشخص نشده دریافت شود، سرور باید با کد HTTP 404 (Not Found) و یک پیام پاسخ دهد. برای این کار از server.onNotFound() استفاده میکنیم.
server.onNotFound(handle_NotFound);
در نهایت برای شروع سرور، تابع begin() فراخوانی میشود.
server.begin(); Serial.println("HTTP server started");
بخش Loop()
برای مدیریت درخواستهای HTTP واقعی، باید متد handleClient() روی شیء سرور فراخوانی شود.
server.handleClient();
تابع handle_OnConnect()
این تابع با URL ریشه (/) مرتبط است و در ابتدای آن دادههای دما، رطوبت، فشار و ارتفاع از سنسور خوانده میشود. برای پاسخ به درخواست HTTP، از send() استفاده میکنیم.
void handle_OnConnect() { temperature = bme.readTemperature(); humidity = bme.readHumidity(); pressure = bme.readPressure() / 100.0F; altitude = bme.readAltitude(SEALEVELPRESSURE_HPA); server.send(200, "text/html", SendHTML(temperature,humidity,pressure,altitude)); }
در اینجا کد HTTP 200 (OK) ارسال میشود، نوع محتوا text/html تعیین میشود و تابع سفارشی SendHTML() صفحه HTML پویا شامل دادههای سنسور را تولید میکند.
تابع handle_NotFound()
برای مدیریت صفحات خطای 404، این تابع ایجاد شده است.
void handle_NotFound(){ server.send(404, "text/plain", "Not found"); }
نمایش صفحه وب HTML
تابع SendHTML() مسئول تولید صفحه وب است که هر بار سرور ESP32 درخواست دریافتی از یک مرورگر وب را پردازش میکند. این تابع دادههای دما، رطوبت، فشار و ارتفاع را به عنوان پارامتر دریافت کرده و محتویات HTML را به صورت یک رشته طولانی برای تابع server.send() بازمیگرداند.
هر سند HTML با اعلان آغاز میشود:
String SendHTML(float temperature,float humidity,float pressure,float altitude){ String ptr = "<!DOCTYPE html> <html>\n";
عنصر <meta>
با ویژگی viewport تضمین میکند که صفحه در مرورگرهای مختلف واکنشگرا باشد و تگ <title>
عنوان صفحه را تعیین میکند.
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; ptr +="<title>ESP32 Weather Station</title>\n";
طراحی ظاهر صفحه وب
با استفاده از CSS، ظاهر صفحه وب را زیبا میکنیم. فونت Helvetica انتخاب شده و محتوا به صورت inline-block و مرکزچین نمایش داده میشود.
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"; ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n"; ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n";
تنظیم هدر صفحه
هدر صفحه با استفاده از تگ <h1>
تعیین میشود و میتوانید متن آن را به دلخواه تغییر دهید.
ptr +="<div id=\"webpage\">\n"; ptr +="<h1>ESP32 Weather Station</h1>\n";
نمایش دادهها در صفحه وب
برای نمایش پویا دادههای دما، رطوبت، فشار و ارتفاع، این مقادیر در تگهای <p>
قرار میگیرند.
ptr +="<p>Temperature: "; ptr +=temperature; ptr +="°C</p>"; ptr +="<p>Humidity: "; ptr +=humidity; ptr +="%</p>"; ptr +="<p>Pressure: "; ptr +=pressure; ptr +="hPa</p>"; ptr +="<p>Altitude: "; ptr +=altitude; ptr +="m</p>"; ptr +="</div>\n"; ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }
حرفهایتر کردن ظاهر صفحه وب ESP32
گاهی اوقات ما به طراحی وب صفحاتمان توجه زیادی نمیکنیم، اما با کمی تلاش میتوان صفحات وب را جذابتر و حرفهایتر کرد. در این مثال، صفحه وب سنسور BME280 روی ESP32 به صورت حرفهای طراحی شده است.
تغییرات کلیدی در کد SendHTML()
فقط کافی است این تابع sendHTML را با مورد اولیه جایگزین کنید تا تغییرات ظاهری اعمال شود.
String SendHTML(float temperature,float humidity,float pressure,float altitude){ String ptr = "<!DOCTYPE html>"; ptr +="<html>"; ptr +="<head>"; ptr +="<title>ESP32 Weather Station</title>"; ptr +="<meta name='viewport' content='width=device-width, initial-scale=1.0'>"; ptr +="<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600' rel='stylesheet'>"; ptr +="<style>"; ptr +="html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #444444;}"; ptr +="body{margin: 0px;} "; ptr +="h1 {margin: 50px auto 30px;} "; ptr +=".side-by-side{display: table-cell;vertical-align: middle;position: relative;}"; ptr +=".text{font-weight: 600;font-size: 19px;width: 200px;}"; ptr +=".reading{font-weight: 300;font-size: 50px;padding-right: 25px;}"; ptr +=".temperature .reading{color: #F29C1F;}"; ptr +=".humidity .reading{color: #3B97D3;}"; ptr +=".pressure .reading{color: #26B99A;}"; ptr +=".altitude .reading{color: #955BA5;}"; ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;top: 10px;}"; ptr +=".data{padding: 10px;}"; ptr +=".container{display: table;margin: 0 auto;}"; ptr +=".icon{width:65px}"; ptr +="</style>"; ptr +="</head>"; ptr +="<body>"; ptr +="<h1>ESP32 Weather Station</h1>"; ptr +="<div class='container'>"; ptr +="<div class='data temperature'>"; ptr +="<div class='side-by-side icon'>"; ptr +="<svg enable-background='new 0 0 19.438 54.003'height=54.003px id=Layer_1 version=1.1 viewBox='0 0 19.438 54.003'width=19.438px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M11.976,8.82v-2h4.084V6.063C16.06,2.715,13.345,0,9.996,0H9.313C5.965,0,3.252,2.715,3.252,6.063v30.982"; ptr +="C1.261,38.825,0,41.403,0,44.286c0,5.367,4.351,9.718,9.719,9.718c5.368,0,9.719-4.351,9.719-9.718"; ptr +="c0-2.943-1.312-5.574-3.378-7.355V18.436h-3.914v-2h3.914v-2.808h-4.084v-2h4.084V8.82H11.976z M15.302,44.833"; ptr +="c0,3.083-2.5,5.583-5.583,5.583s-5.583-2.5-5.583-5.583c0-2.279,1.368-4.236,3.326-5.104V24.257C7.462,23.01,8.472,22,9.719,22"; ptr +="s2.257,1.01,2.257,2.257V39.73C13.934,40.597,15.302,42.554,15.302,44.833z'fill=#F29C21 /></g></svg>"; ptr +="</div>"; ptr +="<div class='side-by-side text'>Temperature</div>"; ptr +="<div class='side-by-side reading'>"; ptr +=(int)temperature; ptr +="<span class='superscript'>°C</span></div>"; ptr +="</div>"; ptr +="<div class='data humidity'>"; ptr +="<div class='side-by-side icon'>"; ptr +="<svg enable-background='new 0 0 29.235 40.64'height=40.64px id=Layer_1 version=1.1 viewBox='0 0 29.235 40.64'width=29.235px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><path d='M14.618,0C14.618,0,0,17.95,0,26.022C0,34.096,6.544,40.64,14.618,40.64s14.617-6.544,14.617-14.617"; ptr +="C29.235,17.95,14.618,0,14.618,0z M13.667,37.135c-5.604,0-10.162-4.56-10.162-10.162c0-0.787,0.638-1.426,1.426-1.426"; ptr +="c0.787,0,1.425,0.639,1.425,1.426c0,4.031,3.28,7.312,7.311,7.312c0.787,0,1.425,0.638,1.425,1.425"; ptr +="C15.093,36.497,14.455,37.135,13.667,37.135z'fill=#3C97D3 /></svg>"; ptr +="</div>"; ptr +="<div class='side-by-side text'>Humidity</div>"; ptr +="<div class='side-by-side reading'>"; ptr +=(int)humidity; ptr +="<span class='superscript'>%</span></div>"; ptr +="</div>"; ptr +="<div class='data pressure'>"; ptr +="<div class='side-by-side icon'>"; ptr +="<svg enable-background='new 0 0 40.542 40.541'height=40.541px id=Layer_1 version=1.1 viewBox='0 0 40.542 40.541'width=40.542px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M34.313,20.271c0-0.552,0.447-1,1-1h5.178c-0.236-4.841-2.163-9.228-5.214-12.593l-3.425,3.424"; ptr +="c-0.195,0.195-0.451,0.293-0.707,0.293s-0.512-0.098-0.707-0.293c-0.391-0.391-0.391-1.023,0-1.414l3.425-3.424"; ptr +="c-3.375-3.059-7.776-4.987-12.634-5.215c0.015,0.067,0.041,0.13,0.041,0.202v4.687c0,0.552-0.447,1-1,1s-1-0.448-1-1V0.25"; ptr +="c0-0.071,0.026-0.134,0.041-0.202C14.39,0.279,9.936,2.256,6.544,5.385l3.576,3.577c0.391,0.391,0.391,1.024,0,1.414"; ptr +="c-0.195,0.195-0.451,0.293-0.707,0.293s-0.512-0.098-0.707-0.293L5.142,6.812c-2.98,3.348-4.858,7.682-5.092,12.459h4.804"; ptr +="c0.552,0,1,0.448,1,1s-0.448,1-1,1H0.05c0.525,10.728,9.362,19.271,20.22,19.271c10.857,0,19.696-8.543,20.22-19.271h-5.178"; ptr +="C34.76,21.271,34.313,20.823,34.313,20.271z M23.084,22.037c-0.559,1.561-2.274,2.372-3.833,1.814"; ptr +="c-1.561-0.557-2.373-2.272-1.815-3.833c0.372-1.041,1.263-1.737,2.277-1.928L25.2,7.202L22.497,19.05"; ptr +="C23.196,19.843,23.464,20.973,23.084,22.037z'fill=#26B999 /></g></svg>"; ptr +="</div>"; ptr +="<div class='side-by-side text'>Pressure</div>"; ptr +="<div class='side-by-side reading'>"; ptr +=(int)pressure; ptr +="<span class='superscript'>hPa</span></div>"; ptr +="</div>"; ptr +="<div class='data altitude'>"; ptr +="<div class='side-by-side icon'>"; ptr +="<svg enable-background='new 0 0 58.422 40.639'height=40.639px id=Layer_1 version=1.1 viewBox='0 0 58.422 40.639'width=58.422px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M58.203,37.754l0.007-0.004L42.09,9.935l-0.001,0.001c-0.356-0.543-0.969-0.902-1.667-0.902"; ptr +="c-0.655,0-1.231,0.32-1.595,0.808l-0.011-0.007l-0.039,0.067c-0.021,0.03-0.035,0.063-0.054,0.094L22.78,37.692l0.008,0.004"; ptr +="c-0.149,0.28-0.242,0.594-0.242,0.934c0,1.102,0.894,1.995,1.994,1.995v0.015h31.888c1.101,0,1.994-0.893,1.994-1.994"; ptr +="C58.422,38.323,58.339,38.024,58.203,37.754z'fill=#955BA5 /><path d='M19.704,38.674l-0.013-0.004l13.544-23.522L25.13,1.156l-0.002,0.001C24.671,0.459,23.885,0,22.985,0"; ptr +="c-0.84,0-1.582,0.41-2.051,1.038l-0.016-0.01L20.87,1.114c-0.025,0.039-0.046,0.082-0.068,0.124L0.299,36.851l0.013,0.004"; ptr +="C0.117,37.215,0,37.62,0,38.059c0,1.412,1.147,2.565,2.565,2.565v0.015h16.989c-0.091-0.256-0.149-0.526-0.149-0.813"; ptr +="C19.405,39.407,19.518,39.019,19.704,38.674z'fill=#955BA5 /></g></svg>"; ptr +="</div>"; ptr +="<div class='side-by-side text'>Altitude</div>"; ptr +="<div class='side-by-side reading'>"; ptr +=(int)altitude; ptr +="<span class='superscript'>m</span></div>"; ptr +="</div>"; ptr +="</div>"; ptr +="</body>"; ptr +="</html>"; return ptr; }
این تغییرات عبارتند از:
استفاده از فونت وب گوگل
ما از فونت Open Sans استفاده کردهایم که توسط گوگل ارائه شده است. این فونت در مرورگر به صورت دینامیک بارگذاری میشود، بنابراین بدون اتصال اینترنت قابل مشاهده نیست.
ptr +="<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600' rel='stylesheet'>";
استفاده از CSS برای زیباییبخشی
- کلاسهای
.temperature
,.humidity
,.pressure
,.altitude
برای رنگبندی و نمایش خوانا استفاده شدهاند. - کلاس
.side-by-side
برای چیدمان دادهها و آیکونها به صورت افقی (table-cell) استفاده شده است. - کلاس
.reading
اندازه و وزن فونت دادهها را مشخص میکند.
استفاده از SVG برای آیکونها
- هر پارامتر (دما، رطوبت، فشار، ارتفاع) با یک آیکون SVG نشان داده شده است.
- SVG ها قابل ویرایش هستند و میتوانید با ابزارهایی مثل Canva SVG Editor آیکون دلخواه خود را بسازید.
ساختار HTML به صورت container و data
- یک div با کلاس
container
داریم که دادهها را در خود جای میدهد. - هر پارامتر داخل یک div با کلاس
data
قرار دارد که شامل آیکون، نام و مقدار میشود.
بهبود عملکرد: رفرش خودکار صفحه
برای بهروز رسانی مقادیر سنسور، میتوانیم با اضافه کردن یک تگ meta به <head>
، مرورگر را وادار کنیم هر چند ثانیه صفحه را مجدد بارگذاری کند:
<meta http-equiv="refresh" content="2">
این مثال باعث میشود صفحه هر 2 ثانیه یکبار رفرش شود و مقادیر جدید سنسور نمایش داده شود.
بارگذاری پویا دادههای سنسور با AJAX
رفرش مداوم یک صفحه وب، بهویژه برای صفحات سنگین، کارآمد نیست. رویکرد بهتر استفاده از AJAX (Asynchronous JavaScript and XML) است که امکان دریافت داده از سرور بدون نیاز به بارگذاری مجدد کل صفحه را فراهم میکند.
در وب، برای درخواستهای AJAX معمولاً از شیء XMLHttpRequest استفاده میشود. این شیء درخواستهای GET را به صورت خاموش (بدون رفرش صفحه) به سرور ارسال کرده و المانهای صفحه را بهروز میکند. AJAX فناوری جدید یا زبان جداگانهای نیست، بلکه استفادهای نوین از تکنولوژیهای موجود است. با AJAX میتوانیم:
- بعد از بارگذاری صفحه، از سرور داده درخواست کنیم
- بعد از بارگذاری صفحه، داده دریافت کنیم
- در پسزمینه، داده به سرور ارسال کنیم
مثال اسکریپت AJAX
این اسکریپت را قبل از بسته شدن تگ <head>
قرار دهید:
ptr +="<script>\n"; ptr +="setInterval(loadDoc,1000);\n"; ptr +="function loadDoc() {\n"; ptr +="var xhttp = new XMLHttpRequest();\n"; ptr +="xhttp.onreadystatechange = function() {\n"; ptr +="if (this.readyState == 4 && this.status == 200) {\n"; ptr +="document.body.innerHTML = this.responseText; }\n"; ptr +="};\n"; ptr +="xhttp.open(\"GET\", \"/\", true);\n"; ptr +="xhttp.send();\n"; ptr +="}\n"; ptr +="</script>\n";
توضیح عملکرد کد
- اسکریپت با تگ
<script>
آغاز میشود، زیرا AJAX در واقع JavaScript است و باید در این تگ قرار گیرد. - برای اجرای مکرر یک تابع، از setInterval() استفاده میکنیم که دو پارامتر میگیرد: نام تابع و فاصله زمانی اجرای آن (به میلیثانیه).
setInterval(loadDoc,1000);
- هسته اصلی کد، تابع loadDoc() است که در آن شیء XMLHttpRequest() ایجاد میشود تا درخواست داده به وبسرور ارسال شود.
function loadDoc() { var xhttp = new XMLHttpRequest();
تابع xhttp.onreadystatechange() هر بار که مقدار readyState تغییر کند فراخوانی میشود. مقدار readyState وضعیت درخواست را مشخص میکند:
- 0: درخواست مقداردهی اولیه نشده
- 1: اتصال به سرور برقرار شد
- 2: درخواست دریافت شد
- 3: پردازش درخواست
- 4: درخواست کامل و پاسخ آماده است
ویژگی status وضعیت HTTP را نشان میدهد:
- 200: OK
- 403: Forbidden
- 404: Page not found
وقتی readyState = 4 و status = 200 باشد، پاسخ آماده است و محتوای <body>
با دادههای دریافتی جایگزین میشود.
xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.body.innerHTML = this.responseText; } };
در نهایت درخواست HTTP با استفاده از open() و send() ارسال میشود.
xhttp.open("GET", "/", true); xhttp.send();
با این روش، صفحه وب ESP32 میتواند دادههای سنسور را بهصورت پویا و بدون رفرش کامل بهروز کند، که کارایی و تجربه کاربری بهتری ارائه میدهد.
موارد موجود در فایل : سورس کامل
برای دانلود فایل ها باید حساب کاربری داشته باشید ثبت نام / ورود