نمایش مقادیر چند سنسور DS18B20 بر روی وب سرور ESP8266 NodeMCU

نمایش مقادیر سنسور DS18B20 بر روی وب سرور ESP8266 NodeMCU

آیا تا به حال به این فکر کرده‌اید که سنسورهایی در جاهای مختلف خانه و باغچه‌تان داشته باشید که به طور مرتب دمای خود را به یک سرور مرکزی گزارش کنند؟ اگر پاسخ شما مثبت است، این پروژه اینترنت اشیاء می‌تواند بهترین نقطه شروع برای شما باشد!
در این پروژه برای نمایش مقادیر چند سنسور DS18B20 از ماژول ESP8266 NodeMCU به عنوان یک دستگاه کنترل‌کننده استفاده می‌کنیم که به سادگی به یک شبکه وای‌فای متصل می‌شود و یک وب سرور می‌سازد. زمانی‌که هر یک از دستگاه‌های متصل به شبکه‌ به این وب سرور دسترسی پیدا کنند، ESP8266 دما را از سنسورهای دمای DS18B20 خوانده و با یک ظاهر زیبا، به مرورگر وب دستگاه ارسال می‌کند. هیجان زده شدید؟ پس بیایید شروع کنیم!

استفاده از چند سنسور DS18B20 روی یک خط باس

یکی از قابلیت‌های مهم DS18B20 این است که چندین سنسور DS18B20 می‌توانند به طور همزمان روی یک باس تک سیمه مشترک وجود داشته باشند. هر سنسور DS18B20 یک شماره سریال 64 بیتی مختص به خود دارد که در زمان ساخت در کارخانه روی آن ریخته می‌شود تا تشخیص سنسورهای مختلف از هم امکان‌پذیر باشد.

این قابلیت زمانی اهمیت پیدا می­کند که بخواهید چندین DS18B20 را که در یک محوطه‌ی بزرگ پخش شده‌اند، کنترل کنید.

نحوه‌ی اتصال چند سنسور DS18B20 به ESP8266 NodeMCU

برای نمایش مقادیر چند سنسور DS18B20 و استفاده از آن نیاز است ابتدا با پایه‌ها و نحوه اتصال این سنسوربه ESP8266 آشنا شوید. اتصال سنسورهای DS18B20 به ESP8266 NodeMCU نسبتاً ساده است.

مشخصات پایه های سنسور DS18B20

با اتصال سنسورها به صورت موازی شروع کنید. همانطورکه در تصویر زیر نشان داده شده­‌است، بدین منظور باید همه پین‌های VDD را به هم متصل نمایید، برای پین­های GND و signal نیز به همین صورت عمل کنید. سپس پین VDD را به ولتاژ 3.3 متصل کنید، GND را زمین کنید و پین signal را به پین دیجیتال D2 روی برد ESP8266 NodeMCU متصل نمایید. سپس باید یک مقاومت پول­‌آپ 4.7 کیلواهم بین خط سیگنال و تغذیه قرار دهید تا انتقال اطلاعات به شکل پایدارتری صورت بگیرد.

سیم‌کشی چند سنسور دمای DS18B20 به ESP8266

آماده‌سازی IDE آردوینو

محیط برنامه­‌نویسی آردوینو افزونه‌­ای دارد که به شما اجازه می‌دهد با استفاده آن، ESP8266 NodeMCU را پروگرام کنید. اگر تا به حال این کار را نکرده‌اید، آموزش زیر را دنبال کنید:


نصب کتابخانه برای DS18B20

پروتکل تک سیمه Dallas مقداری پیچیده است و برای تحلیل اطلاعات نیاز به چندین خط کد دارد. برای عدم رویارویی با این پیچیدگی، کتابخانه DallasTemperature.h را نصب می‌کنیم تا بتوانیم با استفاده از چند فرمان ساده، دما را از سنسور بخوانیم.

برای نصب کتابخانه به مسیر Arduino IDE > Sketch > Include Library > Manage Libraries بروید. صبر کنید تا Library Manager لیست کتابخانه‌ها را دانلود کرده و لیست کتابخانه‌های نصب شده را آپدیت کند. سپس جستجوی خود را با نوشتن عبارت ‘ds18b20’ فیلتر کنید. از بین چند گزینه‌ای که می‌بینید، DallasTemperature از Miles Burton را پیدا کرده و آن را نصب کنید.

نصب کتابخانه از طریق library manager

کتابخانه DallasTemperature، یک کتابخانه سمت سخت‌افزار است که توابع سطح پایین را مدیریت می‌کند. این کتابخانه باید با کتابخانه One Wire جفت شود تا با قطعاتی مانند DS18B20 که ارتباط تک سیمه دارند ارتباط برقرار کند. پس این کتابخانه را هم نصب کنید.

نحوه‌ی نصب کتابخانه DallasTemperature

پیدا کردن آدرس سنسورهای DS18B20 بر روی خط باس

همانطور که می‌دانید برای تمایز سنسورهای دمای DS18B20، به هر کدام یک آدرس 64 بیتی منحصر به فرد اختصاص داده شده‌­است. ابتدا مشخص می‌کنیم هر سنسور چه آدرسی دارد و در ادامه از این آدرس استفاده می‌کنیم تا دمای هر سنسور را به طور جداگانه بخوانیم. برنامه زیر همه سنسورهای DS18B20 موجود روی باس را تشخیص می‌دهد و آدرسِ تک سیمه آن‌ها را روی سریال مانیتور چاپ می‌کند. شما می‌توانید هر بار فقط یک سنسور را متصل کنید و آدرس آن را بیابید (یا اینکه به ترتیب، با هر بار اجرای برنامه یک سنسور جدید اضافه کنید تا بتوانید آدرس هر سنسور را تشخیص دهید).

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port D2 on the ESP8266
#define ONE_WIRE_BUS D2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// variable to hold device addresses
DeviceAddress Thermometer;

int deviceCount = 0;

void setup(void)
{
  // start serial port
  Serial.begin(115200);

  // Start up the library
  sensors.begin();

  // locate devices on the bus
  Serial.println("Locating devices...");
  Serial.print("Found ");
  deviceCount = sensors.getDeviceCount();
  Serial.print(deviceCount, DEC);
  Serial.println(" devices.");
  Serial.println("");
  
  Serial.println("Printing addresses...");
  for (int i = 0;  i < deviceCount;  i++)
  {
    Serial.print("Sensor ");
    Serial.print(i+1);
    Serial.print(" : ");
    sensors.getAddress(Thermometer, i);
    printAddress(Thermometer);
  }
}

void loop(void)
{ }

void printAddress(DeviceAddress deviceAddress)
{ 
  for (uint8_t i = 0; i < 8; i++)
  {
    Serial.print("0x");
    if (deviceAddress[i] < 0x10) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
    if (i < 7) Serial.print(", ");
  }
  Serial.println("");
}

حال سریال مانیتور را باز کنید. باید چیزی شبیه به شکل زیر ببینید:

خروجی کد یافتن آدرس سنسورها در مانیتور سریال

همه آدرس‌ها را کپی و ذخیره کنید، چون در ادامه به آن‌ها نیاز خواهید داشت.

ساخت وب سرور ESP8266 در مد ایستگاه (STA)

حال می‌خواهیم ESP8266 خود را در مد Station تنظیم کنیم، و یک وب سرور بسازیم که صفحات وب را به دستگاه‌های متصل به شبکه تحویل دهد.

اگر می‌خواهید در مورد ساخت وب سرور با ESP8266 NodeMCU در مد‌های AP و STA بیشتر بدانید، آموزش زیر را دنبال کنید.


قبل از آپلود برنامه، لازم است تغییرات زیر را اعمال نمایید.

  • ابتدا باید متغیرهای زیر را برحسب مشخصات شبکه­‌ی خود تغییر دهید، تا ESP8266 بتواند با شبکه اتصال برقرار کند.
const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here
  • ESP8266 قبل از آماده‌سازی صفحه وب، دمای هر یک از سنسورهای DS18B20 را با کمک آدرس آن­‌ها می‌خواند. پس شما باید آدرس سنسورها را طبق آدرس‌هایی که در برنامه قبل به‌­دست آوردید، تغییر دهید.
uint8_t sensor1[8] = { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC };
uint8_t sensor2[8] = { 0x28, 0x61, 0x64, 0x12, 0x3C, 0x7C, 0x2F, 0x27 };
uint8_t sensor3[8] = { 0x28, 0x61, 0x64, 0x12, 0x3F, 0xFD, 0x80, 0xC6 };

پس از انجام این تغییرات، برنامه زیر را امتحان کنید:

#include <ESP8266WebServer.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port D2 on the ESP8266
#define ONE_WIRE_BUS D2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

float tempSensor1, tempSensor2, tempSensor3;

uint8_t sensor1[8] = { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC  };
uint8_t sensor2[8] = { 0x28, 0x61, 0x64, 0x12, 0x3C, 0x7C, 0x2F, 0x27  };
uint8_t sensor3[8] = { 0x28, 0x61, 0x64, 0x12, 0x3F, 0xFD, 0x80, 0xC6  };

/*Put your SSID & Password*/
const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here

ESP8266WebServer server(80);             
 
void setup() {
  Serial.begin(115200);
  delay(100);
  
  sensors.begin();              

  Serial.println("Connecting to ");
  Serial.println(ssid);

  //connect to your local wi-fi network
  WiFi.begin(ssid, password);

  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}
void loop() {
  server.handleClient();
}

void handle_OnConnect() {
  sensors.requestTemperatures();
  tempSensor1 = sensors.getTempC(sensor1); // Gets the values of the temperature
  tempSensor2 = sensors.getTempC(sensor2); // Gets the values of the temperature
  tempSensor3 = sensors.getTempC(sensor3); // Gets the values of the temperature
  server.send(200, "text/html", SendHTML(tempSensor1,tempSensor2,tempSensor3)); 
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(float tempSensor1,float tempSensor2,float tempSensor3){
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>ESP8266 Temperature Monitor</title>\n";
  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";
  ptr +="<div id=\"webpage\">\n";
  ptr +="<h1>ESP8266 Temperature Monitor</h1>\n";
  ptr +="<p>Living Room: ";
  ptr +=tempSensor1;
  ptr +="&deg;C</p>";
  ptr +="<p>Bedroom: ";
  ptr +=tempSensor2;
  ptr +="&deg;C</p>";
  ptr +="<p>Kitchen: ";
  ptr +=tempSensor3;
  ptr +="&deg;C</p>";
  ptr +="</div>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

دسترسی به وب سرور و نمایش مقادیر چند سنسور DS18B20

برای نمایش مقادیر چند سنسور DS18B20 پس از آپلود برنامه، سریال مانیتور را باز و با بادریت را روی 115200 تنظیم کنید. سپس دکمه ریست روی NodeMCU را فشار دهید. اگر همه چیز درست باشد، پیغام HTTP server started به همراه یک آدرس آی‌پی داینامیک نمایش داده می‌شود. این همان آدرسی است که از روتر شما گرفته شده‌است.

نمایش ادرس آی‌پی داینامیک در مانیتور سریال پس از تنظیم بادریت و ریست nodemcu

حال یک مرورگر باز کنید و به آدرسی که از سریال مانیتور دریافت کردید بروید. ESP8266 باید یک صفحه‌­ی وب بارگذاری کند که دمای همه سنسورهای DS18B20 را نشان می‌دهد.

نمایش مقادیر دما سنسورهای DS18B20 با استفاده از آی‌پی آدرس داینامیک

توضیح کد

برنامه با افزودن کتابخانه‌­های زیر آغاز می‌شود:

  • ESP8266WebServer.h: این کتابخانه توابع مربوط به وای‌­فای ESP8266 را ارائه می­دهد که برای اتصال به شبکه آن‌ها را فراخوانی می‌کنیم. همچنین این کتابخانه شامل توابعی است که به ما در ساخت یک وب سرور و مدیریت درخواست‌های HTTP کمک می­کند.
  • DallasTemperature.h : این کتابخانه‌­ی سخت افزاری، توابع سطح پایین را مدیریت می­کند و برای اینکه عملکرد صحیحی داشته باشد،­ باید با کتابخانه‌­ی One Wire جفت شود.
  • OneWire.h: این کتابخانه نه فقط با DS18B20 بلکه با هر قطعه­‌ای که ارتباط تک سیمه داشته باشد، می­تواند ارتباط برقرار می­کند.
#include <ESP8266WebServer.h>
#include <OneWire.h>
#include <DallasTemperature.h>

در ادامه متغیر‌های مورد نیاز برای ارتباط با سنسور و ذخیره‌­ی دما را می‌سازیم. سنسور دما نیز به پین D2 متصل شده‌­است.

// Data wire is plugged into port D2 on the ESP8266
#define ONE_WIRE_BUS D2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

float tempSensor1, tempSensor2, tempSensor3;

سپس نوبت وارد کردن آدرس سنسورهاست. برای سنسورهای ما آدرس‌­ها به شکل زیر هستند:

uint8_t sensor1[8] = { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC  };
uint8_t sensor2[8] = { 0x28, 0x61, 0x64, 0x12, 0x3C, 0x7C, 0x2F, 0x27  };
uint8_t sensor3[8] = { 0x28, 0x61, 0x64, 0x12, 0x3F, 0xFD, 0x80, 0xC6  };

در این پروژه ESP8266 را در مد STA تنظیم کردیم پس این ماژول باید به شبکه‌­ی وای‌­فای موجود متصل شود. در نتیجه باید پسورد و SSID شبکه خود را به آن بدهیم. سپس وب سرور را در پورت 80 راه­‌اندازی می‌کنیم.

/*Put your SSID & Password*/
const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here

ESP8266WebServer server(80);

تابع ()Setup

قبل از اجرای سرور HTTP، ابتدا آن را کانفیگ می­کنیم. در اولین قدم، ارتباط سریال با کامپیوتر و همچنین شیء DallasTemperature را با استفاده از تابع ()begin راه‌اندازی می­کنیم. این تابع ارتباط باس را فعال و همه­‌ی سنسورهای DS18B20 حاضر روی آن را شناسایی می­کند. سپس به هر سنسور یک شماره اختصاص می‌دهد و رزولوشن را روی 12 بیت تنظیم می­کند.

Serial.begin(115200);
delay(100);
  
sensors.begin(); 

حال باید با تابع ()WiFi.begin به شبکه‌­ی وای‌­فای متصل شویم. این تابع پارامترهای SSID (نام شبکه) و پسورد را به عنوان ورودی می‌گیرد.

Serial.println("Connecting to ");
Serial.println(ssid);

//connect to your local wi-fi network
WiFi.begin(ssid, password);

مادامی که ESP8266 تلاش می‌کند به شبکه متصل شود، می‌توانیم وضعیت اتصال را با تابع ()WiFi.status بررسی کنیم.

//check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }

با اتصال ESP8266 NodeMCU به شبکه، برنامه آدرس آی‌­پی تخصیص‌یافته به آن را از طریق نمایش مقدار تابع ()WiFi.localIP، روی سریال مانیتور چاپ می‌کند.

Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

به منظور مدیریت درخواست‌های HTTP دریافتی، باید مشخص کنیم هنگام وارد کردن هر URL، کدام کد اجرا شود. برای این کار، از تابع on استفاده می‌کنیم. این تابع دو پارامتر به عنوان ورودی می‌گیرد که پارامتر اول مسیر URL و پارامتر دوم نام تابعی است که می‌خواهیم هنگام استفاده URL مشخص شده، اجرا شود.

برای مثال در خط اول کد زیر، سرور پس از دریافت یک درخواست HTTP روی مسیر ریشه (/) ، تابع ()handle_OnConnect را اجرا می‌کند. توجه کنید URL مشخص شده، یک مسیر نسبی (relative path) است.

server.on("/", handle_OnConnect);

در صورتی که سرویس‌گیرنده، یک URL غیر از موارد مشخص شده را با تابع ()server.on ارسال کند، سرور با وضعیت HTTP 404 (Not Found) پاسخ و پیغامی به کاربر نمایش می­دهد. برای این امر از تابع دیگری تحت عنوان server.onNotFound استفاده می‌کنیم تا اگر سرور یک درخواست نامشخص دریافت کرد، این تابع اجرا شود.

server.onNotFound(handle_NotFound);

اکنون برای راه‌اندازی سرور، تابع begin را روی شیء server فراخوانی می‌کنیم.

server.begin();
Serial.println("HTTP server started");

حلقه‌­ی ()Loop

برای پاسخگویی به درخواست‌های HTTP، تابع ()handleClient را روی شیء server فراخوانی کنیم.

server.handleClient();

سپس، باید تابعی که با دستور server.on به آدرس ریشه (/) متصل کردیم را بسازیم.

اگر یادتان باشد در ابتدای این تابع، دما را از همه سنسورها خواندیم. برای پاسخ‌ به درخواست HTTP، از تابع send استفاده می‌کنیم. با اینکه این تابع می‌تواند با ترکیب دیگری از پارامترها هم فراخوانی شود، ولی ساده‌ترین فرم آن شامل کد پاسخ به HTTP، نوع محتوای صفحه و خود محتوا است.

در اینجا، ما کد 200 (یکی از کدهای وضعیت HTTP) را ارسال می‌کنیم که به معنای OK است. سپس “text/html” را به عنوان نوع محتوا مشخص و در نهایت تابع ()SendHTML را فراخوانی می‌کنیم. این تابع یک صفحه HTML داینامیک تولید می‌کند که شامل مقادیر دما است.

void handle_OnConnect() {
  sensors.requestTemperatures();
  tempSensor1 = sensors.getTempC(sensor1);
  tempSensor2 = sensors.getTempC(sensor2);
  tempSensor3 = sensors.getTempC(sensor3);
  server.send(200, "text/html", SendHTML(tempSensor1,tempSensor2,tempSensor3)); 
}

به همین شکل باید تابعی برای مدیریت صفحه خطای 404 بسازیم.

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

نمایش صفحه وب HTML

هر زمان که وب سرور ESP8266، درخواستی از سرویس‌گیرنده دریافت می‌کند، تابع ()SendHTML ساخت یک صفحه وب را برعهده می‌گیرد. این تابع فقط کد HTML را در یک ‌رشته‌­ی بزرگ (string) ذخیره می‌کند و آن را به تابع ()server.send که در مورد آن صحبت کردیم، برمی‌گرداند. تابع ()SendHTML دماهای خوانده شده را می‌گیرد و محتوای صفحه HTML را تولید می­کند.

اولین متنی که همیشه باید ارسال کنید اعلان <!DOCTYPE> است که مشخص می‌کند در حال ارسال کد HTML هستیم.

String SendHTML(float tempSensor1,float tempSensor2,float tempSensor3){
  String ptr = "<!DOCTYPE html> <html>\n";

سپس، المان ویوپورتِ <meta> را ارسال می‌کنیم که صفحه وب را در هر مرورگری نمایش می‌دهد. تگ title نیز عنوان صفحه را مشخص می‌کند.

ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>ESP8266 Temperature Monitor</title>\n";

طراحی صفحه وب

در ادامه، با چند خط کد CSS طراحی ظاهر صفحه وب را آغاز می‌کنیم. دراینجا فونت Helvetica انتخاب شده‌­است، همچنین نمایش محتویات صفحه را به‌ صورت inline-block تعریف و محل قرارگیری آن را در وسط صفحه تنظیم کردیم.

ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";

کد زیر رنگ، فونت و حاشیه بدنه و تگ‌های H1، H3 و p را مشخص می‌کند.

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";

تنظیم عنوان صفحه وب

در این قسمت عنوان صفحه وب تعیین شده­‌است. شما می‌توانید این متن را متناسب با کاربرد خود تغییر دهید.

ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP8266 Temperature Monitor</h1>\n";

نمایش مقادیر دما در صفحه وب

برای نمایش داینامیک دماهای خوانده شده، مقادیر را در تگ پاراگراف (<p>) قرار می‌دهیم و برای نماد درجه نیز از &deg استفاده می‌کنیم.

ptr +="<p>Living Room: ";
ptr +=tempSensor1;
ptr +="&deg;C</p>";
ptr +="<p>Bedroom: ";
ptr +=tempSensor2;
ptr +="&deg;C</p>";
ptr +="<p>Kitchen: ";
ptr +=tempSensor3;
ptr +="&deg;C</p>";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}

طراحی حرفه‌ای‌تر صفحه وب

ممکن است فکر کنید طراحی صفحه وب کار دشواری است! اما شما هم می‌توانید با کمی تلاش، صفحه وب خود را جذاب‌تر و حرفه‌ای‌تر نشان دهید. عکس زیر ایده کلی کاری که می‌خواهیم انجام دهیم را به شما نشان می‌دهد.

صفحه وب نمایش دهنده مقادیر سنسورها زیباتر و حرفه‌ای تر شده

شگفت انگیز نیست؟ پس بدون اتلاف وقت، بیایید کمی صفحه HTML قبلی خود را زیبا کنیم. برای شروع، کد زیر را کپی کرده و جایگزین تابع ()SendHTML در برنامه بالا کنید. اکنون برنامه جدید را امتحان کنید. در ادامه به بررسی دقیق‌تر این کد خواهیم پرداخت.

String SendHTML(float tempSensor1,float tempSensor2,float tempSensor3){
  String ptr = "<!DOCTYPE html>";
  ptr +="<html>";
  ptr +="<head>";
  ptr +="<title>ESP8266 Temperature Monitor</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-top: 50px;} ";
  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 +=".temperature{font-weight: 300;font-size: 50px;padding-right: 15px;}";
  ptr +=".living-room .temperature{color: #3B97D3;}";
  ptr +=".bedroom .temperature{color: #F29C1F;}";
  ptr +=".kitchen .temperature{color: #26B99A;}";
  ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -5px;top: 15px;}";
  ptr +=".data{padding: 10px;}";
  ptr +=".container{display: table;margin: 0 auto;}";
  ptr +=".icon{width:82px}";
  ptr +="</style>";
  ptr +="</head>";
  ptr +="<body>";
  ptr +="<h1>ESP8266 Temperature Monitor</h1>";
  ptr +="<div class='container'>";
  ptr +="<div class='data living-room'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 65.178 45.699'height=45.699px id=Layer_1 version=1.1 viewBox='0 0 65.178 45.699'width=65.178px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><polygon fill=#3B97D3 points='8.969,44.261 8.969,16.469 7.469,16.469 7.469,44.261 1.469,44.261 1.469,45.699 14.906,45.699 ";
  ptr +="14.906,44.261 '/><polygon fill=#3B97D3 points='13.438,0 3,0 0,14.938 16.438,14.938 '/><polygon fill=#3B97D3 points='29.927,45.699 26.261,45.699 26.261,41.156 32.927,41.156 '/><polygon fill=#3B97D3 points='58.572,45.699 62.239,45.699 62.239,41.156 55.572,41.156 '/><path d='M61.521,17.344c-2.021,0-3.656,1.637-3.656,3.656v14.199H30.594V21c0-2.02-1.638-3.656-3.656-3.656";
  ptr +="c-2.02,0-3.657,1.636-3.657,3.656v14.938c0,2.021,1.637,3.655,3.656,3.655H61.52c2.02,0,3.655-1.637,3.655-3.655V21";
  ptr +="C65.177,18.98,63.54,17.344,61.521,17.344z'fill=#3B97D3 /><g><path d='M32.052,30.042c0,2.02,1.637,3.656,3.656,3.656h16.688c2.019,0,3.656-1.638,3.656-3.656v-3.844h-24";
  ptr +="L32.052,30.042L32.052,30.042z'fill=#3B97D3 /><path d='M52.396,6.781H35.709c-2.02,0-3.656,1.637-3.656,3.656v14.344h24V10.438";
  ptr +="C56.053,8.418,54.415,6.781,52.396,6.781z'fill=#3B97D3 /></g></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Living Room</div>";
  ptr +="<div class='side-by-side temperature'>";
  ptr +=(int)tempSensor1;
  ptr +="<span class='superscript'>&deg;C</span></div>";
  ptr +="</div>";
  ptr +="<div class='data bedroom'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 43.438 35.75'height=35.75px id=Layer_1 version=1.1 viewBox='0 0 43.438 35.75'width=43.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='M25.489,14.909H17.95C13.007,14.908,0,15.245,0,20.188v3.688h43.438v-3.688";
  ptr +="C43.438,15.245,30.431,14.909,25.489,14.909z'fill=#F29C1F /><polygon fill=#F29C1F points='0,31.25 0,35.75 2.5,35.75 4.5,31.25 38.938,31.25 40.938,35.75 43.438,35.75 43.438,31.25 ";
  ptr +="43.438,25.375 0,25.375 	'/><path d='M13.584,11.694c-3.332,0-6.033,0.973-6.033,2.175c0,0.134,0.041,0.264,0.105,0.391";
  ptr +="c3.745-0.631,7.974-0.709,10.341-0.709h1.538C19.105,12.501,16.613,11.694,13.584,11.694z'fill=#F29C1F /><path d='M30.009,11.694c-3.03,0-5.522,0.807-5.951,1.856h1.425V13.55c2.389,0,6.674,0.081,10.444,0.728";
  ptr +="c0.069-0.132,0.114-0.268,0.114-0.408C36.041,12.668,33.34,11.694,30.009,11.694z'fill=#F29C1F /><path d='M6.042,14.088c0-2.224,3.376-4.025,7.542-4.025c3.825,0,6.976,1.519,7.468,3.488h1.488";
  ptr +="c0.49-1.97,3.644-3.489,7.469-3.489c4.166,0,7.542,1.801,7.542,4.025c0,0.17-0.029,0.337-0.067,0.502";
  ptr +="c1.08,0.247,2.088,0.549,2.945,0.926V3.481C40.429,1.559,38.871,0,36.948,0H6.49C4.568,0,3.009,1.559,3.009,3.481v12.054";
  ptr +="c0.895-0.398,1.956-0.713,3.095-0.968C6.069,14.41,6.042,14.251,6.042,14.088z'fill=#F29C1F /></g></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Bedroom</div>";
  ptr +="<div class='side-by-side temperature'>";
  ptr +=(int)tempSensor2;
  ptr +="<span class='superscript'>&deg;C</span></div>";
  ptr +="</div>";
  ptr +="<div class='data kitchen'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 48 31.5'height=31.5px id=Layer_1 version=1.1 viewBox='0 0 48 31.5'width=48px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><circle cx=24.916 cy=15.75 fill=#26B99A r=15.75 /><path d='M14.917,15.75c0-5.522,4.478-10,10-10c2.92,0,5.541,1.26,7.369,3.257l1.088-1.031";
  ptr +="c-2.103-2.285-5.106-3.726-8.457-3.726c-6.351,0-11.5,5.149-11.5,11.5c0,3.127,1.252,5.958,3.277,8.031l1.088-1.031";
  ptr +="C16.011,20.945,14.917,18.477,14.917,15.75z'fill=#FFFFFF /><path d='M45.766,2.906c-1.232,0-2.232,1-2.232,2.234v11.203c0,0,2.76,0,3,0v12H48v-12V2.906";
  ptr +="C48,2.906,46.035,2.906,45.766,2.906z'fill=#26B99A /><path d='M6.005,2.917v5.184c0,0.975-0.638,1.792-1.516,2.083V2.917H3.021v7.267c-0.878-0.29-1.516-1.107-1.516-2.083";
  ptr +="V2.917H0v5.458c0,1.802,1.306,3.291,3.021,3.592v16.376H4.49v-16.38c1.695-0.318,2.979-1.8,2.979-3.588V2.917H6.005z'fill=#26B99A /></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Kitchen</div>";
  ptr +="<div class='side-by-side temperature'>";
  ptr +=(int)tempSensor3;
  ptr +="<span class='superscript'>&deg;C</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'>";

  • آیکون‌­هایی که برای نمایش مقادیر دما استفاده شده‌اند، در حقیقت بردارهای گرافیکی با قابلیت تغییر اندازه (Scalable Vector Graphics یا SVG) هستند که با تگ <svg> تعریف شده­‌اند. ساخت SVG به مهارت برنامه‌نویسی خاصی نیاز ندارد. شما می‌توانید با استفاده از ابزار Google SVG Editor برای صفحه وب خود اشکال گرافیکی بسازید. ما از آیکون‌­های SVG زیر استفاده کردیم:
آیکن‌های svg ساخته شده برای نمایش مقادیر دما

افزودن به‌روزرسانی خودکار صفحه وب

یکی از بهبودهایی که می‌توانیم در برنامه اعمال کنیم به‌روزرسانی خودکار صفحه وب، به ‌منظور به‌روزرسانی مقادیر خوانده شده از سنسورهاست.

تنها با اضافه‌کردن یک تگ meta به فایل HTML، می‌توانیم به مرورگر نشان دهیم صفحه را پس از مدت‌زمان معینی به­‌روز­رسانی کند.

<meta http-equiv="refresh" content="2" >

این کد را در تگ <head> قرار دهید. تگ meta باعث می‌شود مرورگر هر دو ثانیه یک‌بار صفحه را به‌­روزرسانی کند.

بارگذاری داینامیک اطلاعات سنسور با AJAX

هنگامی که صفحه سنگینی داشته باشید، به­‌روزرسانی آن به درستی انجام نخواهد شد. یک روش بهتر، استفاده از “جاوا اسکریپت و Xml آسنکرون” (Asynchronous Javascript And Xml یا AJAX) است. در این روش می‌توانیم به صورت آسنکرون (در پس زمینه) و بدون نیاز به به­روزرسانی، اطلاعات را از سرور درخواست کنیم.

معمولاً برای اجرای 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 از جنس جاوا اسکریپت است، باید آن را در تگ <script> بنویسیم و برای اینکه این تابع مرتب فراخوانی شود از تابع جاوا اسکریپت setInterval() استفاده می‌کنیم. این تابع دو پارامتر به عنوان ورودی می‌گیرد. اولین پارامتر تابعی برای اجرا است و دومین پارامتر فاصله زمانی بین اجرای دوباره تابع (برحسب میلی­ثانیه) می­باشد.

ptr +="<script>\n";
ptr +="setInterval(loadDoc,1000);\n";

در قلب این اسکریپت، تابع ()loadDoc قرار دارد. به طوری که درون این تابع یک شیء ()XMLHttpRequest ساخته شده که اطلاعات را از وب سرور درخواست می‌کند.

ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";

به محض تغییر readyState، تابع ()xhttp.onreadystatechange فراخوانی می‌شود. مشخصه readyState وضعیت XMLHttpRequest را ذخیره می‌­کند که می‌­تواند یکی از مقادیر زیر باشد:

  • 0 : درخواست شروع نشده­است.
  • ·         1 : ارتباط با سرور برقرار شده­است.
  • ·         2 : درخواست دریافت شد.
  • ·         3 : درخواست در حال پردازش است.
  • ·         4 : درخواست انجام شده و پاسخ آماده است.

مشخصه status نیز وضعیت شیء XMLHttpRequest را ذخیره می­کند که می­تواند یکی از مقادیر زیر باشد:

  • 200 : OK
  • ·         403 : ممنوع
  • ·         404 : صفحه پیدا نشد.

وقتی مقادیر readyState و status به ترتیب برابر 4 و 200 باشد، یعنی پاسخ آماده است. اکنون محتوای بدنه‌­ی صفحه که مقادیر دمای خوانده شده را دربردارد به­روز می‌شود.

ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.body.innerHTML =this.responseText}\n";
ptr +="};\n";

سپس درخواست HTTP با توابع ()open و ()send آماده و ارسال می‌گردد.

ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";

امیدواریم از این آموزش لذت برده‌ باشید، اگر چگونگی نمایش مقادیر چند سنسور DS18B20 بر روی وب سرور ESP8266 NodeMCU برای شما مفید بوده و به حوزه اینترنت اشیا علاقه‌مند‌ هستید پیشنهاد میکنیم مقالات قبلی وبلاگ مارا مطالعه کنید و در ادامه همراه ما باشید. مثل همیشه نظرات و پیشنهادات خود را با ما در میان بگذارید.

مقالات مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

Fill out this field
Fill out this field
لطفاً یک نشانی ایمیل معتبر بنویسید.
You need to agree with the terms to proceed

پر بازدید ترین مقالات