
IoT-Ep4 | HTTP GET gửi dữ liệu lên Thingspeak
Trong bài viết này, chúng ta sẽ đi tìm hiểu cách sử dụng phương thức GET (HTTP GET request) để cập nhật dữ liệu cảm biến trên Thingspeak. Các bạn có thể theo dõi video-demo hoặc bài hướng dẫn dưới đây.
Mục lục
1. Giới thiệu
Trong 2 bài trước, chúng ta cùng tìm hiểu về Thingspeak và cách gửi dữ liệu cảm biến nhiệt độ và độ ẩm từ DHT22 lên Thingspeak bằng cách sử dụng thư viện Thingspeak mà MathWorks phát triển. Ngoài ra, nền tảng Thingspeak còn cung cấp các API (Application Programming Interface) hay còn được gọi là giao diện lập trình ứng dụng cho phép nhà các nhà phát triển ứng dụng có thể viết chương trình giao tiếp với Thingspeak từ bất kì thiết bị nào có hỗ trợ stack TCP/IP. Như vậy, bằng việc sử dụng các API này chúng ta có thể lập trình cho các thiết khác ngoài NodeMCU để gửi dữ liệu lên Thingspeak.
Giao thức HTTP có thể coi là một trong những giao thức phổ biến nhất hiện nay, bởi vì hầu hết tất cả chúng ta đều sử dụng trình duyệt Web mỗi ngày và giao thức HTTP đóng vai trò quan trọng trong truyền tải dữ liệu Web. HTTP RESTfull là một trong những dịch vụ Web sử dụng giao thức HTTP để trao đổi dữ liệu với những yêu cầu như: GET, PUT, POST, DELETE, tương đương với việc đọc, cập nhật, tạo và xoá các thao tác liên quan đến tài nguyên. Bằng cách sử dụng các Request mà dữ liệu có thể được xoá và cập nhật trên Field của Channel trên Thingspeak.
2. API GET Requests
Để tìm hiểu về các API Requests được Thingspeak hỗ trợ, chúng ta có thể tìm thấy tab API Key ở bất cứ trang Channel nào (Hình 1).
Hình 1. API
- Ví dụ 1: Sử dụng GET request để ghi dữ liệu vào trường dữ liệu.
GET https://api.thingspeak.com/update?api_key=YOUR_WRITE_API_KEY&field1=0
Câu lệnh (Request) ở đây được xây dựng với https://api.thingspeak.com/update?api_key= + OurWriteAPIKey + & + tên Field + = + giá trị. Với GET Request chúng ta có thể dán link vào trình duyệt Web (Hình 2). Nếu Request thực hiện thành công thì số 0 sẽ được trả về trên trang web. Khi đó giá trị 40 sẽ được ghi vào trường số 1 Field1 của kênh.
Hình 2. Test GET request
Ngoài ra, để ghi dữ liệu vào nhiều trường khác nhau, chúng ta có thể thêm &field2=30, ví dụ như sau:
GET https://api.thingspeak.com/update?api_key=YOUR_WRITE_API_KEY&field1=10&field2=30
Phương thức HTTP GET có thể miêu tả ở Hình 3.
Hình 3. Phương thức HTTP GET
Dựa theo Hình 3, chúng ta có thể viết yêu cầu theo phương thức HTTP GET trên NodeMCU theo dạng như sau:
GET /update?api_key=RBDRQF9W9SDPJA6T&field1=10&field2=30 |
Host: api.thingspeak.com |
Code trên Arduino IDE thì chúng ta sử dụng đối tượng client từ WiFiClient theo:
String getUrl = "/update?api_key=" + writeAPIKey + "&field1=" + String(t) + "&field2=" + String(h);
// Make a HTTP request:
client.println("GET " + getUrl + " HTTP/1.1");
client.println("Host: api.thingspeak.com");
client.println("Connection: close");
client.println();
- Ví dụ 2: Sử dụng phương thức HTTP GET đọc thông tin của kênh
GET https://api.thingspeak.com/channels/1679735/feeds.json?api_key=56R00C2TUIT40NY6&results=2
Thực hiện Request này trên trình duyệt Web, chuỗi dạng json được trả về hiển thị các thông tin của kênh và các giá trị của các trường.
{"channel":{"id":1679735,"name":"Hệ thống quan trắc thời tiết",
"description":"Hệ thống theo dõi thời tiết để thu thập dữ liệu nhiệt độ và độ ẩm từ xa.","latitude":"0.0","longitude":"0.0",
"field1":"Nhiệt độ","field2":"Độ ẩm","created_at":"2022-03-19T12:14:27Z","updated_at":"2022-03-19T12:14:28Z","last_entry_id":1259},
"feeds":[{"created_at":"2022-03-19T21:49:49Z","entry_id":1258,"field1":"27.10000","field2":"11.70000"},
{"created_at":"2022-03-19T21:50:14Z","entry_id":1259,"field1":"27.10000","field2":"11.30000"}]}
3. Kết nối và lập trình
3.1. Kết nối
Trong bài này, chúng ta tiếp tục làm việc với NodeMCU và DHT22. Cảm biến có thể được kết nối tới mô-đun NodeMCU theo sơ đồ Hình 4.
Hình 4. Sơ đồ kết nối NodeMCU với DHT22
3.2. Sử dụng HTTP GET request
Trong ví dụ này, chúng ta cần cập nhật 2 trường dữ liệu: field1 cho nhiệt độ và field2 cho độ ẩm. Các bạn có thể tham khảo code mẫu tại đây.
Có 2 cách lập trình trên Arduino IDE cho NodeMCU có thể gửi HTTP GET request tới máy chủ (Server) từ xa:
- Cách 1: chúng ta chỉ sử dụng 1 thư viện ESP8266WiFi.h.
- Cách 2: chúng ta có thể sử dụng kết hợp 2 thư viện ESP8266WiFi.h và ESP8266HTTPClient.h.
a. Sử dụng ESP8266WiFi.h: các bạn có thể tham khảo Sketch sau đây.
#include <ESP8266WiFi.h>
#include "DHT.h"
// You need to edit with your network credentials.
#define WIFI_NAME "YOUR_WIFI_NAME"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
// Initialize the client library
WiFiClient client;
// You need to edit with your ThingSpeak information.
#define THING_SPEAK_ADDRESS "api.thingspeak.com"
String writeAPIKey="YOUR_WRITE_API_KEY";
// DHT information
#define DHTPIN D2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
unsigned long lastTime = 0;
unsigned long delayTime = 20000; // set a period of sending data.
void setup()
{
Serial.begin(115200);
Serial.println();
WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
// Begin DHT Sensor
dht.begin();
delay(2000);
}
void loop() {
if ((millis() - lastTime) > delayTime) {
HTTPGet();
lastTime = millis();
}
}
void HTTPGet() {
if (client.connect(THING_SPEAK_ADDRESS, 80)) {
Serial.println("Server connected");
// Read DHT sensor
float h = dht.readHumidity(); // Read humidity as %
float t = dht.readTemperature(); // Read temperature as Celsius (the default)
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
// Use HTTP GET request
Serial.print("Requesting URL: ");
// Build the GET url: http://api.thingspeak.com/update?api_key=RBDRQF9W9SDPJA6T&field1=0
String getUrl = "/update?api_key=" + writeAPIKey + "&field1=" + String(t) + "&field2=" + String(h);
Serial.println(getUrl);
// Make a HTTP request:
client.println("GET " + getUrl + " HTTP/1.1");
client.println("Host: api.thingspeak.com");
client.println("Connection: close");
client.println();
}
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000){
Serial.println(">>> Client Timeout !");
client.stop(); return;
}
}
// Read all the lines of the reply from server and print them to Serial
while (client.available()){
String line = client.readStringUntil('\r'); Serial.print(line);
}
Serial.println("\nClosing connection\n");
}
Thay đổi thông tin kết nối WiFi dành cho mô-đun:
// You need to edit with your network credentials.
#define WIFI_NAME "YOUR_WIFI_NAME"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
Tiếp theo, để cập nhật dữ liệu lên Thingspeak, chúng ta cũng cần tới Write API Key trên kênh của mình.
// You need to edit with your ThingSpeak information.
String writeAPIKey="YOUR_WRITE_API_KEY";
Câu lệnh HTTP GET request được thực thi tại đây để yêu cầu cập nhật 2 giá trị cho field1 và field2.
// Use HTTP GET request
Serial.print("Requesting URL: ");
// Build the GET url: http://api.thingspeak.com/update?api_key=RBDRQF9W9SDPJA6T&field1=0
String getUrl = "/update?api_key=" + writeAPIKey + "&field1=" + String(t) + "&field2=" + String(h);
Serial.println(getUrl);
// Make a HTTP request:
client.println("GET " + getUrl + " HTTP/1.1");
client.println("Host: api.thingspeak.com");
client.println("Connection: close");
client.println();
Sau khi Upload chương trình lên mô-đun, chúng ta có thể theo dõi Response Code trả về qua Serial Monitor. Code trả về 200 OK có nghĩa là yêu cầu cập nhật dữ liệu thành công (Hình 5).
Hình 5. Code trả về qua Serial Montior
b. Sử dụng ESP8266WiFi.h và ESP8266HTTPClient.h. Chúng ta có thể sử dụng Sketch sau:
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include "DHT.h"
// You need to edit with your network credentials.
#define WIFI_NAME "YOUR_WIFI_NAME"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
// You need to edit with your ThingSpeak information.
String writeAPIKey = "YOUR_WRITE_API_KEY";
// DHT information
#define DHTPIN D2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
unsigned long lastTime = 0;
unsigned long delayTime = 20000; // set a period of sending data.
void setup()
{
Serial.begin(115200);
Serial.println();
WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
// Begin DHT Sensor
dht.begin();
delay(2000);
}
void loop() {
//Send an HTTP POST request every 20 seconds
if ((millis() - lastTime) > delayTime) {
httpGETRequest();
lastTime = millis();
}
}
void httpGETRequest() {
WiFiClient client;
HTTPClient http;
// Read DHT sensor
float h = dht.readHumidity(); // Read humidity in %
float t = dht.readTemperature(); // Read temperature as Celsius (the default)
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
// Build URL GET path.
String urlPath = "http://api.thingspeak.com/update?api_key=" + writeAPIKey + "&field1=" + String(t) + "&field2=" + String(h);
http.begin(client, urlPath);
// Send HTTP GET request
Serial.println("Sending HTTP GET request");
int httpResponseCode = http.GET();
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
}
Trong Sketch này, thư viện ESP8266HTTPClient.h cho phép chúng ta khởi tạo một đối tượng HTTPClient và các phương thức HTTP requests được hỗ trợ ở đây. Đối tượng http gọi phương thức GET() để gửi GET URL Request.
WiFiClient client;
HTTPClient http;
// Build URL GET path.
String urlPath = "http://api.thingspeak.com/update?api_key=" + writeAPIKey + "&field1=" + String(t) + "&field2=" + String(h);
http.begin(client, urlPath);
// Send HTTP GET request
Serial.println("Sending HTTP GET request");
int httpResponseCode = http.GET();
Sau khi gửi GET request, máy chủ gửi lại HTTP code response để xác nhận yêu cầu đã gửi thành công.
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
Tương như trong trường hợp trên, sau khi Upload chương trình lên mô-đun, chúng ta có thể theo dõi Response Code trả về qua Serial Monitor. Code trả về 200 có nghĩa là yêu cầu cập nhật dữ liệu thành công (Hình 6).
Hình 6. Code trả về qua Serial Montior
4. Kết luận
Như vậy, chúng ta có thể sử dụng HTTP GET request để cập nhật dữ liệu trên Thingspeak. Trong 2 cách lập trình cho NodeMCU, chúng ta đều nhận được các kết quả như nhau, dữ liệu được cập nhật thành công trên Thingspeak và trả về code 200 OK (Hình 7).
Hình 7. Đồ thị biểu diễn dữ liệu trên Thingspeak
Thông thường, phương thức GET request được sử dụng để truy vấn hoặc yêu cầu nhận dữ liệu từ máy chủ (Server). Tuy nhiên, sử dụng GET URL chúng ta cũng có thể gửi yêu cầu kèm theo thông tin cần thiết để yêu cầu máy chủ cập nhật dữ liệu.
Tuy nhiên nội dung mà Server trả về sau yêu cầu GET có thể là lớn và không cần thiết với một số thiết bị IoT cần tiết kiệm năng lượng hơn. Do đó mà hiện nay một số giao thức khác như MQTT, CoAP được phát triển dành cho các thiệt bị IoT.