Qua bài đăng lần trước, chúng ta đã có thể thu thập dữ liệu từ ESP8266 và gửi dữ liệu này lên Cloud nhờ một webserver trên internet, tuy nhiên dữ liệu này mới chỉ được hiển thị ra ở dạng bảng kẻ, nhìn nó không được đẹp mắt và không thể hiện sinh động được loại dữ liệu mà ta đang theo dõi.
Ví dụ với dữ liệu chúng ta thu thập về nhiệt độ hoặc độ ẩm, nếu chúng ta chỉ hiển thị dữ liệu dạng bảng trên thì rất khó để hình dung và nhận định về dữ liệu này, với Highcharts, mọi thứ sẽ đẹp hơn, chuyên nghiệp hơn.
Trong bài viết này, tôi sẽ hướng dẫn các bạn xây dựng hệ thống giám sát nhiệt độ sử dụng Highcharts đơn giản với một số dòng lệnh PHP.
- Trước hết các bạn cần có một hệ thống upload dữ liệu từ ESP8266 lên MySQL hoàn chỉnh, có nghĩa là chúng ta phải có cơ sở dữ liệu rồi thì mới vẽ ra được cái hình biểu đồ như ở trên. Nếu các bạn chưa có thì tham khảo bài viết trước.
- Truy cập vào Webhosting, tạo ra file index.php để thực hiện vẽ biểu đồ, file esp_data.php chúng ta tạo ra trong project trước chỉ để nhận data từ ESP8266 và lưu vào MySQL.
Công việc của chúng ta bây giờ là đọc lại dữ liệu từ MySQL, ứng dụng Highcharts để vẽ lại data đó thành biểu đồ.
Mã nguồn file index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<?php require('db_config.php'); $sql = "SELECT value1,time_act FROM SensorData ORDER BY id DESC LIMIT 30"; ?> <!DOCTYPE html> <html> <head> <title>luuvachiase</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> </head> <body> <?php if ($result = $conn->query($sql)) { while ($row = $result->fetch_assoc()) { $row_value1 = $row["value1"]; $datetime = $row['time_act']; $time= strtotime($row['time_act'])*1000; // chuyển sang dạng format unix *1000 $data[] = "[$time,$row_value1]"; } $result->free(); } ?> <script type="text/javascript"> $(function () { $('#container').highcharts({ chart: { type: 'line' }, title: { text: 'Nhiệt độ phòng 1515' }, xAxis: { type: 'datetime', }, yAxis: { title: { text: 'Nhiệt độ' } }, series: [{ name: 'Vị trí 1', data: [<?php echo join($data, ',') ?>] }] }); }); </script> <div class="container"> <br/> <h2 class="text-center">BẢNG THEO DÕI NHIỆT ĐỘ SỬ DỤNG ESP8266</h2> <div class="row"> <div class="col-md-10 col-md-offset-1"> <div class="panel panel-default"> <div class="panel-heading">Dashboard</div> <div class="panel-body"> <div id="container"></div> </div> </div> </div> </div> </div> </body> </html> |
Giải thích ngắn gọn code và các chú ý:
1 2 3 4 |
<?php require('db_config.php'); $sql = "SELECT value1,time_act FROM SensorData ORDER BY id DESC LIMIT 30"; ?> |
Đoạn code đầu tiên dùng để gọi thêm một file có tên db_config.php vào trong mã nguồn file index.php, file này có tác dụng tạo ra kết nối đến database. Nội dung mã nguồn file db_config.php này như sau:
db_config.php
1 2 3 4 5 6 7 |
<?php $dbHost = "localhost"; $dbDatabase = "xxxxx"; $dbPasswrod = "xxxxx"; $dbUser = "xxxxx"; $conn = mysqli_connect($dbHost, $dbUser, $dbPasswrod, $dbDatabase); ?> |
Tất các các tham số về database chúng ta đã tạo trong project trước.
$sql = “SELECT value1,time_act FROM SensorData ORDER BY id DESC LIMIT 30”;
Câu lệnh trên thực hiện truy vấn 2 dòng dữ liệu value1 và time_act từ cơ sở dữ liệu mà chúng ta lưu data của esp8266, và chúng ta lấy ra theo thứ tự 30 hàng data mới nhất. Ví dụ như bảng dưới, thời gian mới nhất insert vào database là 11h30, thì chúng ta lấy từ trên xuống 30 hàng data mới nhất để có thể vẽ ra biểu đồ.
Đoạn mã nguồn tiếp theo, như bên dưới, chủ yếu là để chúng ta đưa ra các đường dẫn đến thư viện của Highchart, Bootstrap, css. Chú ý các thư viện này cơ bản là online nên nếu các bạn chạy local sẽ không vẽ được Chart nhé.
1 2 3 4 5 6 7 8 9 |
<!DOCTYPE html> <html> <head> <title>luuvachiase</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> </head> <body> |
Đoạn mã nguồn tiếp theo là đoạn mã nguồn rất quan trọng, nó quyết định xem Highchart có dữ liệu để vẽ biểu đồ hay không.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php if ($result = $conn->query($sql)) { while ($row = $result->fetch_assoc()) { $row_value1 = $row["value1"]; $datetime = $row['time_act']; $time= strtotime($row['time_act'])*1000; // chuyển sang dạng format unix *1000 $data[] = "[$time,$row_value1]"; } $result->free(); } ?> |
$result = $conn->query($sql) // chúng ta sẽ lấy được kết quả truy vấn database trong biến $result
Sau đó là lấy lần lượt ra các biến $row_value1, $datetime từ cơ sở dữ liệu ( Cái này các bạn cần biết một chút về cách truy vấn và lấy được dữ liệu từ SQL, còn không thì hiểu nôm na như vậy)
$time= strtotime($row[‘time_act’])*1000; // Câu lệnh này đặc biệt quan trọng, vì nó chuyển đổi kiểu thời gian timestamp của SQL sang dạng hiển thị thời gian của Highchart.
$data[] = “[$time,$row_value1]”; // Câu lệnh này thực hiện ghép 2 biến $time, $row_value1 thành cặp để phù hợp với định dạng đầu vào của Highchart.
Tiếp theo là mã nguồn thực hiện khởi tạo, vẽ biểu đồ của Highcharts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<script type="text/javascript"> $(function () { $('#container').highcharts({ chart: { type: 'line' }, title: { text: 'Nhiệt độ phòng 1515' }, xAxis: { type: 'datetime', }, yAxis: { title: { text: 'Nhiệt độ' } }, series: [{ name: 'Vị trí 1', data: [<?php echo join($data, ',') ?>] }] }); }); </script> |
Chúng ta chú ý một số tham số sau:
type: ‘line’ // chúng ta có thể thay line bằng bar,…
xAxis, và yAxis là định nghĩa tham số cho 2 trục Ox và Oy
series: [{data: [<?php echo join($data, ‘,’) ?>] , đây là cậu lệnh quan trọng, nếu không đúng sẽ không thể vẽ được biểu đồ, thực chất câu lệnh này giúp chúng ta nhóm các data bao gồm $time,$row_value1 thành đôi một, và liệt kê hết 30 cặp giá trị bằng dấu “,”.
Đoạn code cuối cùng là đoạn code ứng dụng bootstrap cơ bản ( hiểu đơn giản đây là một kĩ thuật giúp cho việc hiển thị tốt nội dung web trên các kích thước màn hình khác nhau), các bạn có thể tùy chỉnh theo ý của mình.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<div class="container"> <br/> <h2 class="text-center">BẢNG THEO DÕI NHIỆT ĐỘ SỬ DỤNG ESP8266</h2> <div class="row"> <div class="col-md-10 col-md-offset-1"> <div class="panel panel-default"> <div class="panel-heading">Dashboard</div> <div class="panel-body"> <div id="container"></div> </div> </div> </div> </div> <span style="font-family: tahoma, arial, helvetica, sans-serif; font-size: 12pt;"></div></span> |
Các bạn có thể tham khảo giao diện của tôi đang dùng, dữ liệu của tôi là nhiệt độ đo từ cảm biến DS18B20
http://iot.luuvachiase.net/
3. Kết nối ESP8266 va DS18b20, lập trình gửi dữ liệu.
Cơ bản dựa trên bài đăng lần trước, chỉ thay bằng việc chúng ta đọc cảm biến DS18B20 bằng ESP8266
Kết nối DS18b20 và ESP8266 như sau:
DS18b20 | ESP8266 | |
Vcc | 3 | 3.3V |
GND | 1 | GND |
Tín hiệu | 2 | GPIO4 |
Mã nguồn Arduino IDE cho ESP8266
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#ifdef ESP32 #include <WiFi.h> #include <HTTPClient.h> #else #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #include <WiFiClient.h> #endif #include <OneWire.h> #include <DallasTemperature.h> // Replace with your network credentials const char* ssid = "xxx"; const char* password = "xxxx"; // REPLACE with your Domain name and URL path or IP address with path const char* serverName = "your_host"//"http://luuvachiase.000webhostapp.com/esp_data.php"; const int oneWireBus = 4; // dùng pin GPIO4 // Keep this API Key value to be compatible with the PHP code provided in the project page. // If you change the apiKeyValue value, the PHP file /post-esp-data.php also needs to have the same key String apiKeyValue = "xxxxxxxxx"; // thay đổi key này theo ý bạn và nhập trên esp_data.php cho đúng String sensorName = "temperature"; String sensorLocation = "home"; OneWire oneWire(oneWireBus); DallasTemperature sensors(&oneWire); void setup() { Serial.begin(115200); // Start the DS18B20 sensor sensors.begin(); WiFi.begin(ssid, password); Serial.println("Connecting"); while(WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to WiFi network with IP Address: "); Serial.println(WiFi.localIP()); } void loop() { //Check WiFi connection status if(WiFi.status()== WL_CONNECTED){ HTTPClient http; sensors.requestTemperatures(); float temperatureC = sensors.getTempCByIndex(0); // Your Domain name with URL path or IP address with path http.begin(serverName); // Specify content-type header http.addHeader("Content-Type", "application/x-www-form-urlencoded"); // Prepare your HTTP POST request data String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName + "&location=" + sensorLocation + "&value1=" +temperatureC + "&value2=5678"+""; Serial.print("httpRequestData: "); Serial.println(httpRequestData); // Send HTTP POST request int httpResponseCode = http.POST(httpRequestData); if (httpResponseCode>0) { Serial.print("HTTP Response code: "); Serial.println(httpResponseCode); } else { Serial.print("Error code: "); Serial.println(httpResponseCode); } // Free resources http.end(); } else { Serial.println("WiFi Disconnected"); } //Send an HTTP POST request every 60 seconds delay(60000); } |
*** Nếu bạn nào làm bị lỗi với việc gửi bản tin POST, thì quay lại bài này để cập nhật cách dùng GET nhé. Đã test và chạy OK.*** Chúc các bạn thành công.
sao của em nó không hiện ra biểu đồ vậy admin ]
Chỗ data php echo join($data, ‘,’)
Bạn đưa code lên mình xem thử!
Code như trên luôn ạ
Cho mình hỏi time act lấy ở đâu vậy ad
date_default_timezone_set(‘Asia/Ho_Chi_Minh’);
$time_act = date(‘Y-m-d H:i:s’); // use actual date() format displayed in your table.
Trong esp_data.php nhe, theo doi bai theo link duoi
https://luuvachiase.net/index.php/2019/10/21/iot-webserver-esp8266-esp32-gui-du-lieu-len-cloud-hien-thi-ra-trinh-duyet-web-voi-mysql-va-php/
Thanks admin bài viết hay quá. Mình đã thử hiển thị cả biểu đồ và bảng bằng cách kết hợp bài này với bài hướng dẫn trước mà các cột của bảng bị dính vào nhau ý có cách nào khắc phục không ạ?
Nếu các cột trong bảng hiển thị dữ liệu dính vào nhau thì chắc trong file index.php của bạn, bạn hãy tìm hiểu cách hiển thị một bảng trong HTML ấy. Trong code của mình thì nó bắt đầu từ dòng này “echo ‘
Cảm ơn admin. Btw, ad ơi mình không tìm được bài đăng về sử dụng cảm biến nhiệt độ DS18B20 dùng cho bài này ý admin up lại giúp mình với
admin ơi cho mình hỏi muốn viết code để hiển thị hai biểu đồ thì viết như nào ạ?
ad ơi em muốn hiển thị hai đồ thị thì viết code như thế nào ạ?
Cái này nói thì hơi dài dòng, để cho đơn giản bạn cứ hiểu code trong bài là cho 1 biểu đồ, còn bạn muốn 2 biểu đồ bạn cần chia giao diện của bạn theo các div trong html, rồi thực hiện cho các div này ngang nhau hay dọc, sau đó bạn copy code của biểu đồ cũ vào, chỉnh sửa phần data hiển thị theo cái mới, chọn dạng biểu đồ , vv.. nói chung là nhiều thứ, bạn cần chịu khó google một chút, đợt này ad bận nhiều việc nên ít check comment cũng như ko đăng bài mới dc.
vâng cảm ơn ad nhé
Nếu muốn vẽ nhiệt độ và độ ẩm của con DHT11 trong 1 bảng vẽ như thế nào ạ.
Aw, this was an extremely good post. Taking the time and actual effort to generate a
really good article but what can I say I procrastinate a whole lot and never manage to get anything done.
What a information of un-ambiguity and preserveness of
valuable knowledge about unexpected feelings.
I do not even understand how I finished up right here, however I believed this
put up used to be great. I don’t understand who you might be however certainly you are going to
a famous blogger in the event you are not already. Cheers!
At this time it sounds like Drupal is the preferred blogging
platform out there right now. (from what I’ve read) Is that what you’re using on your blog?
MÌnh làm theo hướng dẫn mà sao nó bị sai giờ lúc hiển thị,còn trong database thì đúng.
Bạn đọc tham khảo bài này cho cập nhật time_act nhé, https://luuvachiase.net/index.php/2019/10/21/iot-webserver-esp8266-esp32-gui-du-lieu-len-cloud-hien-thi-ra-trinh-duyet-web-voi-mysql-va-php/