Sau khi các bạn tìm hiểu về Webhook Response và biết cách sử dụng thư viện Actions-on-Google Client Library ở phần trước thì phần này chúng ta sẽ tìm hiểu nền tảng Firebase Realtime Database để lưu trữ, truy vấn dữ liệu, tiếp tục hoàn thiện fulfillment và lập trình ESP8266 để hoàn thành ứng dụng. Các bạn có thể xem lại các phần khác trong chuỗi bài viết này tại đây.
Phần cuối: Kết nối Firebase Realtime Database
1. Firebase Realtime Database
Firebase Realtime Database (FRD) là một dịch vụ cơ sở dữ liệu của nền tảng Firebase Google, dữ liệu được lưu trữ trên cloud (cloud hosted database) dưới định dạng JSON và đồng bộ với tất cả máy khách theo thời gian thực kể cả khi offline. FRD hỗ trợ nhiều nền tảng ngôn ngữ và hệ điều hành khác nhau như iOS, Android, Web app,… và có thể sử dụng REST API để truy vấn dữ liệu.
FRD là cơ sở dữ liệu theo mô hình “NoSQL database”, được tổ chức đơn giản do đó chúng ta có thể thực thi các truy vấn rất nhanh chóng, linh động và phù hợp với các ứng dụng có số lượng người dùng lớn mà không bị hạn chế về khả năng đáp ứng.
Với những ưu điểm đó, FRD rất phù hợp với các ứng dụng Internet of Things. Trong ứng dụng này, chúng ta sẽ sử dụng FRD để lưu trữ trạng thái các thiết bị theo thời gian thực, ESP8266 cùng với trợ lý ảo Google Assistant thông qua webhook có thể kết nối đến để cập nhật trạng thái mới hoặc truy vấn trạng thái của thiết bị.
Cùng xem lại sơ đồ mô tả thiết kế hệ thống đã xây dựng ở phần 1:
Để sử dụng Firebase Realtime Database, mở giao diện Firebase console, tiến hành đăng nhập và chọn project đã tạo ở Google Console trước đó.
Ở thanh menu bên trái, chọn Develop -> Database, sau đó cuộn xuống phần Or choose Realtime Database và chọn Create Database
Chọn Start in test mode -> Enable
Sau khi tạo xong sẽ hiển thị giao diện chính của database, dữ liệu về trạng thái thiết bị của chúng ta sau này sẽ được lưu trữ ở database này. Các bạn lưu trữ lại địa chỉ Firebase host có dạng https://projectid.firebaseio.com để lát nữa sử dụng cho fulfillment và ESP8266 kết nối đến nhé.
2.Webhook và Firebase Realtime Database
Trong phần 5 mình đã hướng dẫn các bạn sử dụng Actions-on-Google Client Library để lập trình xử lý 2 intent là: Input_Welcome, Control_Devices. Bây giờ chúng ta sẽ hoàn thành nốt intent còn lại là Get_Status_Devices và lập trình thêm chức năng kết nối đến Firebase Realtime Database. Chương trình của chúng ta bây giờ sẽ như sau:
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 |
'use strict'; //Khai báo thư viện để kết nối triển khai code lên firebase-functions const functions = require('firebase-functions'); //Khai báo thư viện để kết nối với Firebase Realtime Database const admin = require('firebase-admin'); admin.initializeApp({ credential: admin.credential.applicationDefault(), databaseURL: 'https://nodemculed-b2d48.firebaseio.com' }); // Khai báo các dịch vụ được hỗ trợ bởi actions-on-google const { dialogflow, BasicCard, BrowseCarousel, BrowseCarouselItem, Button, Carousel, Image, LinkOutSuggestion, List, MediaObject, Suggestions, SimpleResponse, Table } = require('actions-on-google'); //Khai báo các gợi ý dành cho người dùng (tối đa 8 gợi ý) const intentSuggestions = [ 'Control', 'Get Status', 'light on', 'light off', 'light status', 'fan on', 'fan off', 'fan status', ]; // Tạo instance đặt tên là "app" để tương tác với dialogflow. const app = dialogflow(); // Xử lý các Dialogflow intents. app.intent('Input_Welcome', (conv) => { conv.ask(`Welcome, How can I help?`); conv.ask(new Suggestions(intentSuggestions)); }); app.intent('Control_Devices',(conv, { devices, status }) => { return admin.database().ref(`/ESP8266/${devices}/value`).set(status) .then(snapshot => { conv.ask(`OK, switching ${devices} ${status}. Do you want more?`); conv.ask(new Suggestions(intentSuggestions)); }); }); app.intent('Get_Status_Devices',(conv, { devices }) => { return admin.database().ref(`/ESP8266/${devices}`).once("value") .then(snapshot => { var sta = snapshot.child("value").val(); conv.ask(`${devices} status is ` + sta + `. Do you want more?`); conv.ask(new Suggestions(intentSuggestions)); }); }); exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app); |
Copy đoạn chương trình trên vào cửa sổ index.js ở trình Inline editor, sửa thông sống databaseURL bằng địa chỉ của Firebase host vừa lưu lại ở trên (của mình là: https://nodemculed-b2d48.firebaseio.com), chọn DEPLOY và đợi vài phút để triển khai code lên Firebase Functions. Các bạn có thể tìm thấy các function đã triển khai lên Firebase Functions bằng cách chọn Develop->Functions ở thanh menu bên trái của giao diện Firebase console.
Giải thích chương trình:
– Để sử dụng dịch vụ Firebase Realtime Database, chúng ta sẽ sử dụng Firebase Admin Node.js SDK và khai báo, khởi tạo như sau:
const admin = require(‘firebase-admin’);
admin.initializeApp();
– Để lưu trữ dữ liệu vào Firebase Realtime Database: Có 4 phương thức để ghi dữ liệu vào FRD là: set, update, push và transaction support. Các bạn có thể tham khảo cụ thể các phương thức ở đây. Trong bài này, mình sẽ sử dụng phương thức set để lưu dữ liệu theo cú pháp sau:
admin.database().ref(‘path’).set(‘data’)
.then(snapshot => {
………………..
});
Với path là đường dẫn tham chiếu đến vị trí cần lưu dữ liệu trong database và data là dữ liệu muốn ghi vào, nếu thành công dữ liệu sẽ trả về tham số snapshot.
– Truy xuất dữ liệu từ Firebase Realtime Database: Việc truy xuất dữ liệu có thể được thực hiện bởi nhiều ngôn ngữ khác nhau và mỗi ngôn ngữ sẽ được hỗ trợ thực thi theo phương thức khác nhau, có 2 phương thức chính là: Asynchronous listeners ( đối với Java, Node.js and Python Admin SDKs) và Blocking reads (đối với Python and Go Admin SDKs), tham khảo cụ thể ở đây. Đối với ứng dụng này chúng ta sử dụng Node.js thực hiện truy xuất như sau:
admin.database().ref(path
).once(‘value’)
.then (snapshot => {
……………….
});
Với path là đường dẫn tham chiếu đến vị trí cần truy xuất dữ liệu trong database, nếu thành công dữ liệu sẽ trả về tham số snapshot.
3. ESP8266 và Firebase Realtime Database
Sau khi xây dựng xong fulfillment cho trợ lý ảo Google Assistant, bây giờ chúng ta sẽ lập trình ESP8266 để kết nối và đồng bộ dữ liệu đến Firebase Realtime Database.
Đầu tiên, cần tải thư viện Firebase Arduino và ArduinoJson phiên bản 5.13.2, sau đó include vào Arduino IDE bằng cách chọn Sketch -> Include Library -> add .ZIP Library… và chọn file Zip vừa tải về.
Để mô phỏng cho thiết bị, ở đây mình sẽ sử dụng board NodeMCU Dev Kit và đèn led on board ở chân GPIO16 sẽ đại diện cho thiết bị “light”. Copy đoạn code dưới đây vào Arduino IDE:
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 |
#include <ESP8266WiFi.h> #include <FirebaseArduino.h> #define LedPin 16 // Set these to run example. #define FIREBASE_HOST "Your-Host" #define FIREBASE_AUTH "Your-Auth" #define WIFI_SSID "Your-SSID" #define WIFI_PASSWORD "Your-Password" void setup() { pinMode(LedPin, OUTPUT); Serial.begin(115200); // connect to wifi. WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("connecting"); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println(); Serial.print("connected: ") ; Serial.println(WiFi.localIP()); Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); Firebase.stream("/ESP8266"); } void loop() { if (Firebase.failed()) { Serial.println("streaming error"); Serial.println(Firebase.error()); } if (Firebase.available()) { FirebaseObject event = Firebase.readEvent(); String eventType = event.getString("type"); Serial.print("event: "); Serial.println(eventType); if (eventType == "put") { String path = event.getString("path"); String data = event.getString("data"); Serial.println(String("data: ") + data); if (path.equals("/light/value")) { if (data.equals("off")) { digitalWrite(LedPin, HIGH); } else { digitalWrite(LedPin, LOW); } } } } } |
Để kết nối với Firebase Realtime Database, cần định nghĩa 2 tham số là:
- FIREBASE_HOST: địa chỉ của Firebase Endpoint, có dạng: firebaseio.com chính là giá trị chúng ta đã lưu lại phía trên
Lưu ý: không bao gồm https:// .
- FIREBASE_AUTH: secret key để xác thực kết nối với Firebase Realtime Database.
Để lấy secret key, chọn dấu răng cưa ở bên cạnh Project Overview từ thanh menu bên trái và chọn Project settings. Ở tab Service accounts, chọn Database secrets và chọn show để hiển thị secret key
Upload code xong, chúng ta có thể sử dụng công cụ Simulator của Google Actions hoặc Google Assitant trên điện thoại thông minh để chạy thử ứng dụng điều khiển đèn bằng giọng nói:
Trạng thái cập nhật vào Firebase Realtime Database:
Tương tự các bạn có thể mở rộng thêm cho “fan” hoặc các thiết bị khác tùy ý. Như vậy là chúng ta đã hoàn thành xong ứng dụng Internet of Things điều khiển và giám sát thiết bị sử dụng trợ lý ảo Google Assitant, hy vọng thông qua chuỗi bài viết này sẽ giúp các bạn có được kiến thức nền tảng về Actions on Google, Dialogflow và nền tảng Firebase Realtime Database để có thể xây dựng được các ứng dụng Internet of Things kết hợp với trợ lý ảo Google ứng dụng vào thực tế nhé. Hẹn gặp lại các bạn ở nhũng bài hướng dẫn tiếp theo của Nhóm TAPIT IoTs.
Chúc các bạn thành công!
Xem thêm: Tổng hợp hướng dẫn Internet of Things với NodeMCU ESP8266 và ESP32
Nhóm TAPIT IoTs