https://thuviensach.vn

Internet Of Things (IoT)

cho người mới bắt đầu

IoT Maker Việt Nam

https://thuviensach.vn

Mục lục

Lời mở đầu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Đôi lời về tác giả . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Thuật ngữ hay sử dụng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Giải thích code trong bài. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Giới thiệu nội dung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Ai có thể sử dụng? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Mục tiêu mang lại cho người đọc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Chuẩn bị . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Kiến thức cơ bản . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

Internet Of Things (IoT) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

Internet of Things (IoT) là gì? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

Hệ thống Internet of Things (IoT) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

Những ứng dụng thực tế trong cuộc sống. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

ESP8266. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Sơ đồ chân . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Thông số phần cứng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

SDK hỗ trợ chính thức từ hãng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

ESP8285 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Module và Board mạch phát triển . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Board mạch phát triển ESP8266. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Arduino là gì? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Một số đặc điểm của Arduino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Các lợi ích khi sử dụng Arduino. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Cộng đồng Arduino trên thế giới . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Arduino cho ESP8266 & board mạch ESP8266 WiFi Uno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

Lý do sử dụng Node.js trong cuốn sách này. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

Cuốn sách này có hướng dẫn Node.js ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

Sublime Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

Cài đặt và chuẩn bị. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Arduino IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Cài đặt thư viện Arduino. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

USB CDC driver. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

Chọn Board ESP8266 WiFi Uno trong Arduino IDE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

Nạp chương trình xuống board dùng Arduino IDE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Xuất firmware binary trong Arduino IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Serial Terminal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

Sublime Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

https://thuviensach.vn

Tổng kết . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

Chớp tắt bóng LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Kiến thức . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Đấu nối . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

Mã nguồn chớp tắt dùng Delay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

Mã nguồn chớp tắt dùng định thời . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

Digital IO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

Tổng kết . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

Kiến thức . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

Mã nguồn dùng hỏi vòng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Mã nguồn dùng ngắt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Các khái niệm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

OLED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Màn hình OLED. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Màn hình OLED SSD1306 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Giao tiếp I2C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Hiển thị màn hình OLED với ESP8266. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Tổng kết . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

ESP8266 WiFi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

Chế độ WiFi Station . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Kiến thức . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Kết nối vào mạng WiFi nội bộ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Sử dụng WiFiMulti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

HTTP Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

Giao thức HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

Ứng dụng xem giá Bitcoin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

Chế độ WiFi Access Point. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

ESP8266 hoạt động ở chế độ Access Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

Khởi tạo mạng WiFi sử dụng ESP8266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

Web Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

Web Server là gì? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

HTML - Javascript - CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

Ứng dụng điều khiển đèn LED thông qua Webserver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

ESP8266 Web Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

Kết hợp WiFi AP và Web Server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

Trao đổi dữ liệu giữa 2 ESP8266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

Yêu cầu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

Hướng dẫn thực hiện. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

Tổng kết . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

Dự án đọc cảm biến DHT11 và gởi về Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

Thiết kế ứng dụng. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

https://thuviensach.vn

Yêu cầu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

Phân tích . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

Kiến thức . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

Thực hiện . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

Server Nodejs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

Code ESP8266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

Chuẩn bị . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

Ứng dụng mở rộng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

Dùng ESP8266 như 1 Web Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

Tổng kết . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

Các chế độ cấu hình WiFi. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

Smartconfig . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

Kiến thức . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

Thực hiện SmartConfig với ESP8266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

WPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

WPS là gì?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

Thực hiện WPS với ESP8266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Wifi Manager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

Hoạt động cơ bản WifiManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

Chuẩn bị . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

Mở rộng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

Tổng kết . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

MQTT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

Publish, subscribe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

QoS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

Retain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

LWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

MQTT Client. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

MQTT Lens. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

MQTT.js. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

ESP8266 MQTT Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

MQTT Broker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

MOSCA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

Một số MQTT Broker sử dụng cho sản phẩm thực tế . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

Tổng kết. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

Websocket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

Ưu điểm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

Nhược điểm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

Sử dụng ESP8266 như Websocket Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

Yêu cầu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

Chuẩn bị . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

https://thuviensach.vn

Đoạn code Javascript để tạo kết nối Web Socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

Nhúng file HTML chứa đoạn code JS vào ESP8266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Chương trình hoàn chỉnh cho ESP8266 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

Kết quả . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

Video kết quả. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

Sử dụng ESP8266 như Websocket Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

Javascript Websocket Client trên trình duyệt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

Node.js Websocket Server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

ESP8266 Websocket Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Tổng kết . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

Firmware update over the air (FOTA). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

Cập nhật firmware từ xa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

Bảo mật. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

An toàn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

Yêu cầu căn bản . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

Update process - memory view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

OTA sử dụng Arduino IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

Bước 1: nạp firmware hỗ trợ OTA thông qua cổng Serial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

Bước 2: Lựa chọn cổng nạp thông qua OTA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

Bước 3: Sửa firmware mới và nạp lại thông qua WiFi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

Sử dụng mật khẩu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

Những sự cố thường gặp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

Cập nhật Firmware dùng Web Browser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

Thực hiện . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

Bảo mật . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

HTTP Server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

ESP8266 ESPhttpUpdate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

Node.js OTA Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

Cheatsheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

Arduino - ESP8266 Cheatsheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

C - Cheatsheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

Lời kết . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

Các thành viên tham gia đóng góp. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

Lời kết. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

Giấy phép sử dụng tài liệu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

1/155

Lời mở đầu

Internet Of Things (IoT) – Internet vạn vật dường như đang đứng trước một bước ngoặt để đi đến giai đoạn tiếp theo cho một thế giới hiện đại, văn minh. Đó là viễn cảnh mà mọi vật đều có thể kết nối với nhau thông qua Internet không dây. Các doanh nghiệp đang có xu hướng ứng dụng sản phẩm

công nghệ IoT vào sản xuất ngày càng nhiều bởi thị trường sáng tạo tiềm năng và chi phí sản xuất

ngày càng thấp.

Chứng kiến sự phát triển như vũ bão của các sản phẩm ứng dụng công nghệ IoT và thị trường công

nghệ Start up tiềm năng đang ngày càng sôi động hơn bao giờ hết, quyển sách này cung cấp các

nội dung về IoT với triết lí Không chỉ là thực tế – không rời rạc, hướng đến những người trẻ tuổi đã, đang và muốn tập trung năng lực của mình cho không gian Internet Of Things. Mong muốn cho ra đời

những sản phẩm độc đáo, sáng tạo, ngày càng hoàn thiện và đồng bộ để có thể đáp ứng nhu cầu

của cuộc sống.

Nội dung được thiết kế một cách cơ bản giúp học viên có cái nhìn tổng quan về việc xây dựng hệ

thống, sản xuất thiết bị và dễ dàng tham gia vào lĩnh vực IoT mới mẻ.

Đôi lời về tác giả

Chủ biên của cuốn sách là ông Phạm Minh Tuấn(TuanPM), có nhiều năm kinh nghiệm làm việc trong mảng IoT và phát triển các thư viện mã nguồn mở cho cộng đồng. Tác giả xây dựng cuốn sách này

với mục đích đóng góp 1 phần nhỏ những kiến thức của mình vào sự phát triển của ngành công

nghiệp vẫn còn mới mẻ nhưng rất tiềm năng này.

Thuật ngữ hay sử dụng

• IoT - Internet Of Things hay internet vạn vật.

• ESP8266 - Chip xử lí tích hợp thu phát WiFi.

• Git - Trình quản lý phiên bản.

• Github - Mạng xã hội dành cho lập trình viên.

• IDE - Viết tắt của Integrated Development Enviroment - môi trường phát triển tích hợp.

• Compiler - Trình biên dịch.

• Logic Level - Mức điện áp để chip hiểu được (1 hay 0).

https://thuviensach.vn

2/155

Giải thích code trong bài

void setup()

{

//comment ①

int a = 1;

a ++; ②

}

① Dòng này giải thích đây là comment (chú thích).

② Dòng này giải thích biến a tăng thêm 1 đơn vị.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

3/155

Giới thiệu nội dung

Nội dung quyển sách này bao gồm các hướng dẫn chi tiết cho người đọc lập trình ứng dụng IoT sử

dụng Chip WiFi phổ biến hiện này là ESP8266 để kết nối với Server, gởi, nhận dữ liệu và thực thi các lệnh từ Server. Internet Of Things dựa và các kết nối Internet khá nhiều, do vậy các nội dung cũng tập trung nhiều vào các giao thức (prototcol), các phương pháp quản lý cũng như cấu hình kết nối.

Phần cứng sử dụng chính là System On Chip (SoC) ESP8266 - có khả năng kết nối WiFi và lập trình được với giá thành rẻ và phổ biến trên thế giới. Board mạch sử dụng là board phần cứng mở. IoT WiFi

Uno có sơ đồ chân tương thích với các board Arduino Uno.

Phần mềm sử dụng lập trên máy tính cho Chip ESP8266 là Arduino, ngôn ngữ lập trình C/C++.

Các phần liên quan đến Server chạy trên máy tính sử dụng NodeJS với ngôn ngữ lập trình Javascript.

Ngoài ra, bạn sẽ cần tìm hiểu một số công cụ và khái niệm thường xuyên được sử dụng trong quyển

sách này như sau:

• Git - Trình quản lý phiên bản sử dụng rất rộng rãi trên thế giới, Github là một mạng xã hội cho lập trình viên dựa trên Git. Git giúp bạn quản lý được mã nguồn, làm việc nhóm, xử lý các thao

tác hợp nhất, lịch sử mã nguồn … Có thể trong quá trình làm việc với quyển sách này, bạn sẽ

cần sử dụng các thư viện mã nguồn mở cho Arduino từ Github, nên việc cài đặt và sử dụng công

cụ khá cần thiết cho việc đó. Chưa kể, nó sẽ giúp bạn quản lý mã nguồn và dự án ngày càng

chuyên nghiệp hơn.

• Sublime Text - Là một trình soạn thảo phổ biến, nhanh, nhẹ và nhiều tính năng hay. Sử dụng để lập trình. Javascript (NodeJS)

• Code formater - Dùng để định dạng mã nguồn phù hợp, dễ đọc, dễ sửa chữa.

• Editorconfig - Là một công cụ cộng thêm vào cho các Editor, giúp việc đồng bộ hóa các tiêu

chuẩn như Indent, Align, Space … để đảm bảo code khi được mở ở các Editor không bị thay đổi.

Tuy phần cứng chính thức sử dụng là board mạch phần cứng mở IoT WiFi Uno,



nhưng bạn hoàn toàn có thể sử dụng bất kỳ board ESP8266 nào khác trên thị

trường cho cuốn sách này, ví dụ như: NODEMCU, Wemos, …

Các nội dung trong quyển sách này tập trung vào hướng dẫn các giao thức,



cách thức làm việc với có hệ thống với board ESP8266, Server …, còn các dự án

mẫu, hướng dẫn chi tiết có thể tìm thêm tại arduino.esp8266.vn.



Tất cả các phần Code đều không giải thích rõ chi tiết API cho mỗi tính năng. Mà

thay vào đó được cung cấp tại phụ lục Cheat Sheet (Arduino và C).

https://thuviensach.vn

4/155

Ai có thể sử dụng?

• Các lập trình viên phần mềm/Mobile App, Web App… muốn tham gia làm sản phẩm IoT.

• Sinh viên muốn nâng cao kỹ năng, bổ sung kiến thức.

• Cá nhân muốn tự mình làm các sản phẩm phục vụ cuộc sống, phục vụ công việc.

• Startup Tech không chuyên về phần cứng hoặc phần mềm.

Mục tiêu mang lại cho người đọc

• Giúp cho người không chuyên về phần cứng tiếp cận để làm sản phẩm IoT dễ dàng.

• Có thể tự phát triển hệ thống tích hợp cho sản phẩm IoT.

• Hiểu biết về quy trình tạo ra sản phẩm phần cứng, đi vào mảng sản xuất thiết bị.

• Tránh những sai sót không đáng có khi phát triển và thiết kế sai hệ thống.

Chuẩn bị

• Ít nhất bạn cần 1 board mạch ESP8266 lập trình được, tốt nhất nên sử dụng các board mạch

tương tích với Arduino IDE (đã có các module nạp cho chip).

• Nên có thêm các module khác như cảm biến, động cơ để thực hành, một bộ StarterKit là phù

hợp.

• 1 máy tính cá nhân (Windows, MacOS hoặc Linux).

• C & Arduino ESP8266 Cheatsheet (Mục lục cuối quyển sách này).

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

5/155

Kiến thức cơ bản

Trong phần này, chúng ta sẽ bắt đầu bằng việc tìm hiểu tổng quan về hệ thống IoT, tổng quan về

dòng chip ESP8266, rồi đến việc cài đặt công cụ phát triển Arduino trên máy tính của bạn. Tiếp đến là việc biên dịch các dự án mẫu, lựa chọn trình thư viện, trình soạn thảo sẽ làm việc. Kết thúc chương này chúng ta sẽ có được cái nhìn tổng quát về hệ thống IoT, làm thế nào và sử dụng công cụ gì để

lập trình ứng dụng với ESP8266.

Điểm qua phần này như sau:

• IoT và ứng dụng thực tế.

• Tìm hiểu về chip WiFi ESP8266.

• Arduino IDE và sử dụng Arduino với ESP8266.

• Starter Kit bộ công cụ khởi động việc học lập trình IoT.

• Node.js - Javascript ngôn ngữ lập trình Server Side.

• Cài đặt tất cả các công cụ.

Với những ai đã từng hiểu rõ ESP8266, đã từng làm về hệ thống IoT, đã chuyên nghiệp trong lập trình C/C++ có thể bỏ qua chương này.

https://thuviensach.vn

6/155

Internet Of Things (IoT)

Internet of Things (IoT) là gì?

Internet of Things (IoT) - Mạng lưới vạn vật kết nối Internet là một kịch bản

của thế giới, khi mà mỗi đồ vật, con người được cung cấp một định danh của

riêng mình, và tất cả có khả năng truyền tải, trao đổi thông tin, dữ liệu qua

một mạng duy nhất mà không cần đến sự tương tác trực tiếp giữa người với

người, hay người với máy tính. IoT đã phát triển từ sự hội tụ của công nghệ

không dây, công nghệ vi cơ điện tử và Internet[1]. Nói đơn giản là một tập

hợp các thiết bị có khả năng kết nối với nhau, với Internet và với thế giới bên

ngoài để thực hiện một công việc nào đó. Link: vi.wikipedia.org/wiki/

Mạng_lưới_vạn_vật_kết_nối_Internet

— Wikipedia

Internet of things (IoT) dùng để chỉ các đối tượng có thể được nhận biết cũng như chỉ sự tồn tại của chúng trong một kiến trúc tổng hòa mang tính kết nối: Mạng lưới vạn vật kết nối Internet, hay gọi đơn giản hơn là Things.

IoT có thể là bộ cảm ứng được lắp ráp trong một chiếc tủ lạnh để ghi lại nhiệt độ, là một trái tim được cấy ghép trong cơ thể con người,… Hiểu đơn giản, IoT có thể khiến mọi vật giờ đây có thể giao tiếp với nhau dễ dàng hơn và ưu điểm lớn nhất của “Thông minh” là khả năng phòng ngừa và cảnh báo tại

bất kì đâu.

Cụm từ Internet of things được đưa ra bởi Kevin Ashton vào năm 1999, tiếp sau đó nó cũng được dùng nhiều trong các ấn phẩm đến từ các hãng và nhà phân tích. Họ cho rằng IoT là một hệ thống phức

tạp, bởi nó là một lượng lớn các đường liên kết giữa máy móc, thiết bị và dịch vụ với nhau. Ban đầu, IoT không mang ý nghĩa tự động và thông minh. Về sau, người ta đã nghĩ đến khả năng kết hợp giữa

hai khái niệm IoT - Autonomous control lại với nhau. Nó có thể quan sát sự thay đổi và phản hồi với môi trường xung quanh, cũng có thể tự điều khiển bản thân mà không cần kết nối mạng. Việc tích

hợp trí thông minh vào IoT còn có thể giúp các thiết bị, máy móc, phần mềm thu thập và phân tích

các dữ liệu điện tử của con người khi chúng ta tương tác với chúng. Xu hướng tất yếu trong tương lai, con người có thể giao tiếp với máy móc chỉ qua mạng internet không dây mà không cần thêm bất cứ

hình thức trung gian nào khác.

Câu hỏi đặt ra là, điều gì giúp IoT “thông minh” và “hiểu” con người? Ban đầu, người ta cho rằng

Internet của vạn vật chủ yếu xoay quanh giao tiếp M2M (các thiết bị kết nối với nhau thông qua một thiết bị khác điều khiển). Nhưng khi hướng đến sự “thông minh hóa”, đó không chỉ là giao tiếp giữa M2M nữa mà cần phải đề cập đến các cảm biến (sensor). Và cũng đừng lầm tưởng rằng Sensor là

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

7/155

một cỗ máy hoạt động dưới sự vận hành của các thiết bị khác mà thực chất, nó tương tự như đôi mắt và đôi tai của loài người với sự ghi nhận liên tục những đo lường, định lượng, thu thập dữ liệu từ thế

giới bên ngoài. Suy cho cùng, Internet of things đem đến sự kết nối giữa máy móc và cảm biến, và

nhờ đến dữ liệu điện toán đám mây để mã hóa dữ liệu. Những ứng dụng điện toán đám mây là mắt

xích quan trọng giúp cho Internet of things có thể hoạt động nhờ sự phân tích, xử lí và sử dụng dữ

liệu mà các cảm biến thu thập được.

Tình hình trên thế giới hiện nay, tác động của IOT rất đa dạng và tích cực ở nhiều lĩnh vực: quản lý hạ

tầng, y tế, xây dựng và tự động hóa, giao thông…. John Chambers (CEO của Cisco) đã công bố: Cho

đến năm 2024 sẽ có 500 tỷ thiết bị được kết nối. Thực tế, con số này lớn hơn gần 100 lần số người trên Trái đất, điều đó cho thấy “vạn vật” nhiều hơn con người rất nhiều. Chúng ta đều biết ứng dụng IoT có thể “nói chuyện” với con người thông qua bàn phím, thiết bị cũng được thiết kế ngày càng

hoàn thiện với nhiều cảm biến hơn để có thể giao tiếp một cách nhanh nhất và chính xác nhất với

con người, thu thập dữ liệu đơn giản từ mỗi người chúng ta. Nhưng quan trọng nhất, tuy giao tiếp với con người nhưng ứng dụng IoT không phải là con người.

Người ta cho rằng, IoT là chìa khóa của sự thành công, là bước ngoặt và cơ hội lớn của tương lai. Để

không bị tụt lại phía sau, các chính phủ và doanh nghiệp cần có sự đổi mới và đầu tư mạnh tay hơn để phát triển các sản phẩm ứng dụng công nghệ Internet of things.

Các hashtag: #IoT #InternetOfThings

Hệ thống Internet of Things (IoT)

Hệ thống IoT cho phép người dùng tiến sâu hơn vào việc tự động hóa, phân tích, tích hợp. Giúp cho việc cải thiện tầm nhìn, tính chính xác, nâng tầm các công nghệ về cảm biến, kết nối, robot để đạt hiệu quả cao nhất.

Các hệ thống IoT phát triển, khai thác các tiến bộ của phần mềm, giảm giá thành khi xây dụng phần cứng và tận dụng các công nghệ hiện đại. Những cải tiến này làm thay đổi cách vận hành của quá

trình sản xuất sản phẩm, dịch vụ, xã hội, kinh tế và ảnh hưởng đến cả chính trị

Những điểm mấu chốt của IoT

Những vấn đề quan trọng nhất của hệ thống IoT bao gồm trí thông minh nhân tạo, kết nối, cảm biến

và các thiết bị nhỏ nhưng mang tính cơ động cao, chúng được mô tả sơ lược như bên dưới:

• AI (Artifical Intelligence) - Hệ thống IoT về cơ bản được hiểu là làm cho mọi thiết bị trở nên thông minh, nghĩa là nó giúp nâng cao mọi khía cạnh của cuộc sống bằng những dữ liệu thu

thập được, thông qua các thuật toán tính toán nhân tạo và kết nối mạng. Một ví dụ đơn giản như

hộp đựng gạo của bạn, khi biết rằng gạo sắp hết, hệ thống tự động đặt một đơn hàng mới cho

nhà cung cấp.

• Connectivity - Là một đặc trưng cơ bản của IoT, hiện nay các mạng thiết bị đang trở nên phổ

https://thuviensach.vn

8/155

biến, nhiều mạng thiết bị ngày càng nhỏ hơn, rẻ hơn và được phát triển phù hợp với thực tế

cũng như nhu cầu của người dùng .

• Sensors - IoT sẽ mất đi sự quan trọng của mình nếu không có sensors. Các cảm biến hoạt

động giống như một công cụ giúp IoT chuyển từ mạng lưới các thiết bị thụ động sang mạng lưới

các thiết bị tích cực, đồng thời có thể tương tác với thế giới thực.

• Active Engagement Ngày nay, phần lớn các tương tác của những công nghệ kết nối xảy ra 1

cách thụ động. IoT được cho là sẽ đem đến những hệ thống mang tích tích cực về nội dung, sản

phẩm cũng như các dịch vụ gắn kết.

• Small Devices - Như đã được dự đoán từ trước, các thiết bị ngày càng được tối ưu với mục đích nâng cao độ chính xác, khả năng mở rộng cũng như tính linh hoạt. Nó được thiết kế ngày càng

nhỏ hơn, rẻ hơn và mạnh mẽ hơn theo thời gian.

IoT − Những lợi ích mang lại

Những lợi ích mà IoT đem lại được dàn trải hầu hết đến các tất cả các lĩnh vực trong đời sống, kinh doanh… Dưới đây liệt kê ngắn gọn một số tính năng hữu ích của IoT:

• Cải thiện việc gắn kết khách hàng - Hệ thống IoT giúp phân tích các điểm mù hiện tại, tìm ra những sai sót về độ chính xác. IoT thay đổi điều này để mang lại nhiều sự gắn kết hơn và hiệu

quả hơn với người dùng. Một ứng dụng tại các cửa hàng, dịch vụ iBeacon giúp tăng số lượng

sản phẩm tới người tiêu dùng bằng cách chỉ dẫn người dùng tới khu vực cụ thể trong cửa hàng

và đưa ra các gợi ý về sản phẩm. Chúng cung cấp các thông tin chi tiết, các đánh giá về sản

phẩm, …Bên cạnh đó chúng cũng có khả năng cho phép người dùng chia sẻ các sản phẩm qua

mạng xã hội …

• Tối ưu hóa công nghệ - giúp nâng cao trải nghiệm của khách hàng cũng như cải thiện việc sử

dụng thiết bị và hỗ trợ cải tiến công nghệ.

• Giảm sự hao phí - IoT giúp việc quản lí tài nguyên ở các lĩnh vực được cải thiện 1 cách rõ ràng.

Các phân tích hiện tại thường cung cấp cho chúng ta cái nhìn ở khía cạnh bên ngoài, trong khi

IoT cung cấp các dữ liêu, thông tin thực tế để quản lí tài nguyên một cách hiệu quả hơn.

• Tăng cường việc thu thập dữ liệu - Thông thường, việc thu thập dữ liệu bị hạn chế do thiết kế hệ thống mang tính thụ động. IoT phá vỡ sự ràng buộc, giới hạn của thiết kế và tạo ra 1 hình

ảnh chính xác của tất cả mọi thứ.

IoT − Những thách thức gặp phải

Mặc dù IoT mang lại khá nhiều lợi ích ấn tượng, nó cũng gặp phải những thách thức đáng kể. Dưới

đây là 1 số vấn đề chính của IoT :

• Kiểm soát an ninh - IoT tạo ra 1 hệ sinh thái mà ở đó các thiết bị kết nối liên tục và giao tiếp với nhau qua mạng lưới các kết nối. Tuy nhiên, hệ thống thường chưa chú trọng đến các biện pháp

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

9/155

an ninh nhằm bảo mật thông tin, dẫn đến nó có thể gặp phải các cuộc tấn công nhằm lấy cắp

thông tin của người dùng.

• Tính bảo mật - Do tính bảo mật chưa cao cộng với bản chất của IoT là không cần nhiều sự

tương tác của con người nên các kẻ tấn công có thể cung cấp các thông tin người dùng giả

mạo.

• Tính phức tạp - Một số hệ thống IoT có độ phức tạp về thiết kế và triển khai ứng dụng cũng như khó khăn trong việc bảo trì, nâng cấp hệ thống do sử dụng nhiều công nghệ còn khá mới

mẻ.

• Tính linh hoạt - Có nhiều sự lo ngại khi đề cập đến tính linh hoạt của hệ thống IoT khi tích hợp với các hệ thống khác bởi các hệ thống khi kết hợp có thể xảy ra xung đột và các tính năng sẽ bị

khóa lẫn nhau.

• Tuân thủ các tiêu chuẩn - Giống như các công nghệ khác trong lĩnh vực thương mại, IoT cũng phải tuân thủ các tiêu chuẩn, quy định đã đặt ra trước đó. Tính phức tạp của IoT làm cho việc

tuân thủ các tiêu chuẩn là một thử thách thực sự

Hình 1. Hình minh họa

https://thuviensach.vn

10/155

Hình 2. Sự phát triển của iot dự đoán đến năm 2020

Những ứng dụng thực tế trong cuộc sống

Những ứng dụng của IoT vào các lĩnh vực trong đời sống là vô cùng phong phú và đa dạng. Chúng ta

sẽ cùng điểm qua một số ứng dụng điển hình đã mang lại "tiếng tăm" cho IoT:

• Smart Home - Theo thống kê, smart home là ứng dụng liên quan đến IoT được tìm kiếm nhiều nhất trên Google. Smart Home là 1 ngôi nhà với rất nhiều tính năng tự động như bật máy điều

không khí khi bạn sắp về tới nhà, tắt đèn ngay khi bạn rời khỏi nhà, mở khóa khi người thân trong gia đình đang ở cửa nhà, mở garage khi bạn lái xe đi làm về … còn rất nhiều những tính năng

giúp nâng cao chất lượng cuộc sống khi sử dụng smart home.

• Vật dụng mang theo trên người - Có thể kể đến một số thiết bị như Dashbon Mask, đây là 1

chiếc smart headphone giúp bạn vừa có thể nghe nhạc với âm thanh có độ trung thực cao vừa

có thể xem phim HD với máy chiếu ảo , hoặc AMPL SmartBag ba lô có pin dự phòng có thể sạc

điện cho các thiết bị di động, kể cả máy tính.

• Connected cars - Giúp nâng cao những trải nghiệm cho người dùng xe ôtô, 1 chiếc Connected car có thể tối ưu các hoạt động của nó như thông báo khi hết nhiên liệu, đưa ra các cảnh báo

khi có vật tới gần hoặc mới đây nhất là xe điện tự lái của hãng Tesla…

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

11/155

ESP8266

ESP8266 là dòng chip tích hợp Wi-Fi 2.4Ghz có thể lập trình được, rẻ tiền được sản xuất bởi một công ty bán dẫn Trung Quốc: Espressif Systems.

Được phát hành đầu tiên vào tháng 8 năm 2014, đóng gói đưa ra thị trường dạng Mô dun ESP-01, được sản xuất bởi bên thứ 3: AI-Thinker. Có khả năng kết nối Internet qua mạng Wi-Fi một cách nhanh

chóng và sử dụng rất ít linh kiện đi kèm. Với giá cả có thể nói là rất rẻ so với tính năng và khả năng ESP8266 có thể làm được.

ESP8266 có một cộng đồng các nhà phát triển trên thế giới rất lớn, cung cấp nhiều Module lập trình mã nguồn mở giúp nhiều người có thể tiếp cận và xây dựng ứng dụng rất nhanh.

Hiện nay tất cả các dòng chip ESP8266 trên thị trường đều mang nhãn ESP8266EX, là phiên bản

nâng cấp của ESP8266

Sơ đồ chân

U0TXD

SPI_CS1

U0RXD

LƯU Ý:

Dòng trên mỗi chân 6mA,lớn nhất 12mA

EXT_RSTT

RES12K

VDDA

VDDD

XTALI

XTALO

GPIO1

GPIO3

Cho chế độ ngủ nối tắt GPIO16 và

32

31

30

29

28

27

26

25

EXT_RSTB. Để wakeup, GPIO16 sẽ xuất mức

THẤP khởi động lại hệ thống

Khi khởi động/khởi động lại/weakup, giữ GPIO15 THẤP

và GPIO2 CAO.

VDDA 1

LNA

2

23 GPIO8 SDIO

DATA1

SPI_MOSI U1RXD

VDD3P3 3

22 GPIO7

SDIO

SPI_MISO

DATA0

VDD3P3 4

21 GPIO6 SDIO SPI_CLK

CLK

VDD_RTC 5

20 GPIO11

SDIO

SPI_CS0

CMD

TOUT ADC

6

19 GPIO10 SDIO

DATA3 SPIWP HSPIWP

CHIP_EN CHIP_EN 7

18 GPIO9 SDIO

DATA2

SPIHD HSPIHD

TOUT GPIO16 8

17 VDDPST

SP. FUNCTION(S)

19

10

11

12

13

14

15

16

COMM. INTERFACE

PIN NUMBER

GPIO14

GPIO12

VDPST

GPIO13

GPIO15

GPIO2

GPIO0

GPIO4

PWM

POWER

MTMS

MTDI

MTCK

MTDO

U1TXD

SPI_CS2

I/O

HSPI CLK

HSPI MISO

HSPI

ADC

MOSI

HSPI_CS

CONTROL

N/C

U0CTS

U0RTS

Hình 3. Sơ đồ chân ESP8266EX

https://thuviensach.vn

12/155

Thông số phần cứng

• 32-bit RISC CPU : Tensilica Xtensa LX106 chạy ở xung nhịp 80 MHz

• Hổ trợ Flash ngoài từ 512KiB đến 4MiB

• 64KBytes RAM thực thi lệnh

• 96KBytes RAM dữ liệu

• 64KBytes boot ROM

• Chuẩn wifi EEE 802.11 b/g/n, Wi-Fi 2.4 GHz

◦ Tích hợp TR switch, balun, LNA, khuếch đại công suất và matching network

◦ Hổ trợ WEP, WPA/WPA2, Open network

• Tích hợp giao thức TCP/IP

• Hổ trợ nhiều loại anten

• 16 chân GPIO

• Hổ trợ SDIO 2.0, UART, SPI, I²C, PWM,I²S với DMA

• 1 ADC 10-bit

• Dải nhiệt độ hoạt động rộng : -40C ~ 125C

Hình 4. Một module tích hợp phổ biến (Module ESP12E)

SDK hỗ trợ chính thức từ hãng

Espressif hiện đã hỗ trợ 3 nền tảng SDK (Software Development Kit - Gói phát triển phần mềm) độc

lập, là: NONOS SDK, RTOS SDK và Arduino. Cả 3 đều có những ưu điểm riêng phù hợp với từng ứng dụng nhất định, và sử dụng chung nhiều các hàm điều khiển phần cứng. Hiện nay Arduino đang được sử dụng rộng rãi bởi tính dễ sử dụng, kiến trúc phần mềm tốt và tận dụng được nhiều thư viện

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

13/155

cộng đồng

ESP8266 NONOS SDK

Hiện nay, NONOS SDK phiên bản từ 2.0.0 trở lên đã ổn định và cung cấp gần như là đầy đủ tất cả

các tính năng mà ESP8266 có thể thực hiện:

• Các API cho Timer, System, Wifi, đọc ghi SPI Flash, Sleep và các Module phần cứng: GPIO, SPI, I²C, PWM, I²S với DMA.

• Smartconfig: Hỗ trợ cấu hình thông số Wi-Fi cho ESP8266 nhanh chóng.

• Sniffer API: Bắt các gói tin trong mạng không dây 2.4Ghz.

• SNTP API: Đồng bộ thời gian với Máy chủ thời gian.

• WPA2 Enterprise API: Cung cấp việc quản lý kết nối Wi-Fi bằng tài khoản sử dụng các máy chủ

RADIUS.

• TCP/UDP API: Cho kết nối internet và hỗ trợ các Module dựa trên các giao thức như: HTTP, MQTT,

CoAP.

• mDNS API: Giúp tìm ra IP của thiết bị trong mạng nội bộ bằng tên (hostname).

• MESH API: Liên kết các module ESP8266 với cấu trúc mạng MESH

• FOTA API: Firmware Over The Air - cập nhật firmware từ xa cho thiết bị .

• ESP-Now API: Sử dụng các gói tin Wireless 2.4GHz trao đổi trực tiếp với ESP8266 khác mà không

cần kết nối tới Access Point.

• Simple Pair API: Thiết lập kết nối bảo mật giữa 2 thiết bị tự động.

ESP8266 RTOS SDK

RTOS SDK sử dụng FreeRTOS làm nền tảng, đồng thời hầu hết các API của NON OS SDK đều có thể

sử dụng với RTOS SDK.

ESP8285

ESP8285 là một phiên bản khác sau này của ESP8266EX, giống hoàn toàn ESP8266EX ngoại trừ việc

thay vì dùng SPI FLASH bên ngoài thì ESP8285 tích hợp 1MiB Flash bên trong giúp giảm diện tích phần cứng và đơn giản hóa quá trình sản xuất.

https://thuviensach.vn

14/155

Module và Board mạch phát triển

ESP8266 cần ít nhất thêm 7 linh kiện nữa mới có thể hoạt động, trong đó phần khó nhất là Antena.

Đòi hỏi phải được sản xuất, kiểm tra với các thiết bị hiện đại. Do đó, trên thị trường xuất hiện nhiều Module và Board mạch phát triển đảm đương hết để người dùng đơn giản nhất trong việc phát triển

ứng dụng. Một số Module và Board phát triển phổ biến:

Bảng 1. Một số module ESP8266 trên thị trường

Tên

Số chân

Pitch

LEDs

Antenna

Shielded

Dimensions

ESP-01

6

0.1"

Yes

PCB

No

14.3 × 24.8

ESP-02

6

0.1"

No

U-FL

No

14.2 × 14.2

ESP-03

10

2mm

No

Ceramic

No

17.3 × 12.1

ESP-04

10

2mm

No

None

No

14.7 × 12.1

ESP-05

3

0.1"

No

U-FL

No

14.2 × 14.2

ESP-06

11

misc

No

None

Yes

14.2 × 14.7

ESP-07

14

2mm

Yes

Ceramic+U- Yes

20.0 × 16.0

FL

ESP-08

10

2mm

No

None

Yes

17.0 × 16.0

ESP-09

10

misc

No

None

No

10.0 × 10.0

ESP-10

3

2mm

No

None

No

14.2 × 10.0

ESP-11

6

0.05"

No

Ceramic

No

17.3 × 12.1

ESP-12

14

2mm

Yes

PCB

Yes

24.0 × 16.0

ESP-12E

20

2mm

Yes

PCB

Yes

24.0 × 16.0

ESP-12F

20

2mm

Yes

PCB

Yes

24.0 × 16.0

ESP-13

16

1.5mm

No

PCB

Yes

18.0 x 20.0

ESP-14

22

2mm

No

PCB

Yes

24.3 x 16.2

Board mạch phát triển ESP8266

Module ESP8266 chỉ bao gồm Chip ESP8266 và các linh kiện giúp chip có thể hoạt động được, tuy

nhiên, trong quá trình phát triển sản phẩm, chúng ta cần phải nạp chương trình cho chip trước khi đưa vào hoạt động thực tế. Quá trình này là quá trình gởi dữ liệu Binary (đã biên dịch trên máy tính) xuống bộ nhớ Flash của ESP8266. Để đưa ESP8266 vào chế độ Nạp (Program) thì cần phải đặt mức logic 0 (0V - GND) vào chân GPIO0, đồng thời RESET chip. Rồi sau đó có thể dùng các công cụ nạp để

gởi Firmware từ máy tính xuống.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

15/155

Hình 5. Một mạch nạp tự động sử dụng chip USB CDC

Hiện nay các Board mạch phát triển đều tích hợp các mạch nạp tự động, nghĩa là phần mềm sẽ tự

động điều chỉnh các chân DTR và RTS của chip USB CDC, đưa ESP8266 vào chế độ nạp, sau đó sẽ gởi

firmware xuống. Arduino IDE cũng vậy, nó sẽ điều chỉnh dựa trên việc khai báo Board mạch sử dụng.

Nếu bạn là người mới bắt đầu và chưa rõ về phần cứng, thì tốt nhất nên sử dụng

một Board mạch phát triển sẵn có các chế độ nạp tự động. Khi bạn chuyển



sang sản xuất phần cứng cho các ứng dụng cụ thể, thì có thể tách rời phần nạp

tự động này ra để tiết giảm chi phí. Các mạch điện này đều được công bố rộng

rãi.

https://thuviensach.vn

16/155

Arduino là gì?

Hình 6. Board mạch Arduino

Arduino là một IDE tích hợp sẵn editor, compiler, programmer và đi kèm với nó là các firmware có bootloader, các bộ thư viện được xây dựng sẵn và dễ dàng tích hợp. Ngôn ngữ sử dụng là C/C++. Tất cả đều opensource và được đóng góp, phát triển hàng ngày bởi cộng đồng. Triết lý thiết kế và sử

dụng của Arduino giúp cho người mới, không chuyên rất dễ tiếp cận, các công ty, hardware dễ dàng

tích hợp. Tuy nhiên, với trình biên dịch C/C++ và các thư viện chất lượng được xây dựng bên dưới thì mức độ phổ biến ngày càng tăng và hiệu năng thì không hề thua kém các trình biên dịch chuyên

nghiệp cho chip khác.

Đại diện cho Arduino ban đầu là chip AVR, nhưng sau này có rất nhiều nhà sản xuất sử dụng các chip khác nhau như ARM, PIC, STM32 gần đây nhất là ESP8266, ESP32, và RISCV với năng lực phần cứng và phần mềm đi kèm mạnh mẽ hơn nhiều.

Một số đặc điểm của Arduino

• Arduino che dấu đi sự phức tạp của điện tử bằng các khái niệm đơn giản, che đi sự phức tạp

của phần mềm bằng các thủ tục ngắn gọn. Việc setup output cho 1 MCU bằng cách setup

thanh ghi rõ ràng phức tạp đến độ người chuyên cũng phải lật datasheet ra xem, nhưng với

Arduino thì chỉ cần gọi 1 hàm.

• Bởi vì tính phổ biến và dễ dùng, với các thư viện được tích hợp sẵn. Bạn chỉ cần quan tâm đến

tính năng sản phẩm mà bỏ qua các tiểu tiết (protocol, datasheet …) Nên giúp các newbie không

chuyên dễ dàng tiếp cận và làm ra các sản phẩm tuyệt vời mà không cần phải biết nhiều về

điện tử.

• Chính vì không quan tâm nhiều đến cách thức hoạt động của các Module đi kèm, nên đa phần

người dùng sẽ khó xử lý được khi có các vấn đề phát sinh ngoài tầm của thư viện.

• Các module prototype làm sẵn cho Arduino có độ bền không cao, mục tiêu đơn giản hóa quá

trình làm sản phẩm.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

17/155

Các lợi ích khi sử dụng Arduino

• Thiết kế IDE tốt, có thể dễ dàng tích hợp nhiều loại compiler, nhiều loại hardware mà không hề

giảm hiệu năng. Ví dụ: Arduino gốc cho AVR, nhưng có nhiều phiên bản cho STM32, PIC32,

ESP8266, ESP32… tận dụng tối đa các thư viện sẵn có.

• Các thư viện được viết dựa trên lớp API trên cùng, nên đa số các thư viện cho Arduino có thể

dùng được cho tất cả các chip. Điển hình là Arduino cho ESP8266 có thể tận dụng trên 90% các

thư viện cho Arduino khác

• Trình biên dịch cho Arudino là C/C++, bạn có biết là khi biên dịch ESP8266 non-os SDK và

ESP8266 Arduino cùng dùng chung trình biên dịch? Vậy thì hiệu năng không hề thua kém

• Cách tổ chức các thư viện C/C++ theo dạng OOP giúp phân lớp, kế thừa và quản lý cực kỳ tốt

cho các ứng dụng lớn .Các MCU ngày càng mạnh mẽ và ứng dụng cho nó sẽ ngày càng lớn.

Các mô hình quản lý code đơn giản trước đây (thuần C) sẽ khó.

• Các project cho Arduino đều opensource, bạn dễ dàng lấy nó và đưa vào sản phẩm production

với chất lượng tốt và học hỏi được nhiều từ cách thức thiết kế chương trình của các bậc thầy.

• Arduino chú trọng tính đa nền tảng, module hóa cao, phù hợp với các ứng dụng từ phức tạp tới

cực kỳ phức tạp. Các ứng dụng kiểu này rất phổ biến trong thực tế. Nếu bạn không dùng C++,

hoặc arduino mà gặp vấn đề về overcontrol thì nên thử qua Arduino.

• Bạn sẽ tiết kiệm được rất rất nhiều thời gian cho việc tập trung vào tính năng sản phẩm đấy.

Thời buổi này, thời gian là tiền và có quá nhiều thứ để học, làm thì nên ưu tiên đúng chỗ.

Cộng đồng Arduino trên thế giới

• Arduino chính thức(IDE & AVR/ARM/x86 Board) www.arduino.cc

• Arduino cho ESP8266 github.com/esp8266/Arduino

• Arduino cho ESP32 github.com/espressif/arduino-esp32

• Arduino cho PIC32 chipkit.net/

• Arduino cho STM32 www.stm32duino.com/

• *Các dự án Arduino www.hackster.io/arduino

Arduino cho ESP8266 & board mạch ESP8266 WiFi

Uno

Board mạch ESP8266 WiFi Uno là một dự án mã nguồn mở giúp hỗ trợ môi trường phát triển Arduino cho ESP8266. Giúp bạn có thể viết 1 Sketch sử dụng các thư viện và hàm tương tự của Arduino, có thể

https://thuviensach.vn

18/155

chạy trực tiếp trên ESP8266 mà không cần bất kỳ vi điều khiển nào khác.

ESP8266 Arduino core đi kèm với thư viện kết nối WiFi hỗ trợ TCP, UDP và các ứng dụng HTTP, mDNS, SSDP, DNS Servers. Ngoài ra còn có thể thực hiện cập nhật OTA, sử dụng Filesystem dùng bộ nhớ

Flash hay thẻ SD, điều khiển servos, ngoại vi SPI, I2C.

Link: github.com/iotmakervn/iot-wifi-uno-hw

Hình 7. PINOUT

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

19/155

Node.js

Node.js là một Javascript Run time Cross Platform (chạy đa hệ điều hành) được xây dựng dựa trên

mã nguồn mở Google’s V8 JavaScript engine cho Chrome (Browser). Node.js cho phép các lập trình

viên có thể xây dựng ứng dụng Server Side, truy cập vào tài nguyên hệ thống và thực hiện được

phần lớn các tác vụ hệ điều hành có thể thực hiện bằng ngôn ngữ Javascript, hoặc liên kết C++.

Hiện nay trên thế giới đã có nhiều công ty ứng dụng Node.js xây dựng các hệ thống production lớn, như Paypal, hoặc các microservice dựa trên Node.js cũng được triển khai ở đa số các hãng hàng đầu về công nghệ.

Nền tảng Cloud của gần như tất cả các nhà phát triển lớn hiện nay đều hỗ trợ thực thi Node.js, điển hình như Amazon Lambda, Google Script, IBM Blumix, Microsoft Azure …

Ngôn ngữ lập trình Javascript được cải tiến liên tục, hiện nay là Ecmascript 6 (ES5, ES2015) và đang được cải tiến rất nhanh, với nhiều ưu điểm như dễ học, xúc tích, OOP…

Một lý do Node.js được ưa chuộng nữa là đa phần các lập trình viên viết Web, Mobile đều biết, và giờ

đây, nhờ Node.js mà họ có thể triển khai các ứng dụng Server Side bằng Javascript, mà không cần

dùng ngôn ngữ nào khác (như trước kia phải cần Java, PHP …)

Lý do sử dụng Node.js trong cuốn sách này

Một hệ thống Internet Of Things đầy đủ khá phức tạp, bao gồm thiết bị, Server xử lý kết nối, Server dữ

liệu (Database), các hệ thống cân bằng tải, các hệ thống phân thích, báo cáo dữ liệu, trí tuệ nhân tạo.

Mô hình ví dụ của Google IoT Core

Hình 8. Google IoT Core Diagram

Server là một thành phần không thể thiếu trong hệ thống IoT. Với nhiều ưu điểm của Node.js thì nó rất phù hợp trong việc phát triển các Server cho IoT trong tương lai. Ngoài ra, Node.js được cộng đồng hỗ trợ rất nhiều, và không khó để tìm thấy 1 package cần thiết, tiết kiệm rất nhiều thời gian phát triển ứng dụng.

https://thuviensach.vn

20/155

Cuốn sách này có hướng dẫn Node.js ?

Không, nhưng bạn đừng vội thất vọng, các ứng dụng Node.js sử dụng để thực hiện các bài tập trong cuốn sách này khá đơn giản và ít mã nguồn, đủ cho bạn vẫn hiểu dù cho trước đây chưa bao giờ lập

trình với Node.js.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

21/155

Sublime Text

Nếu ở phần Chip, lập trình cho ESP8266 bạn đã có Arduino IDE, bao gồm cả trình soạn thảo. Nhưng

với Node.js thì bạn cần 1 trình soạn thảo khác. Ngoài Sublime Text, bạn có thể lựa chọn các trình soạn thảo phổ biến hiện nay như Atom, Visual Code, nhưng đừng dại sử dụng Nodepad, mặc dù là

vẫn được.

Sublime Text là một trình soạn thảo được nhiều lập trình viên ưu thích hàng đầu hiện nay, bởi nhiều lý do, trong đó tốc độ là quan trọng nhất. Nó thực sự nhanh, nhanh gần như là số 1 trong số các trình soạn thảo hiện nay. Ngoài ra nó miễn phí (lâu lâu nhắc mua, khung thoại mà nhiều lập trình viên bảo thiếu thì buồn).

Hình 9. Sublime Text

https://thuviensach.vn

22/155

Cài đặt và chuẩn bị

Arduino IDE

Bước 1: Cài đặt Arduino IDE.

Download và cài đặt arduino từ trang chủ của arduino. Link donwload: www.arduino.cc/en/Main/

Software.

Tùy hệ điều hành mà chọn gói cài đặt thích hợp.

Bước 2: Cài đặt bộ công cụ, trình biên dịch, SDK hỗ trợ chip ESP8266 trong Arudino IDE.

Với bộ công cụ này, chúng ta có thể dễ dàng lập trình, biên dịch và sử dụng các thư viện dành cho ESP8266 trực tiếp trên Arduino IDE. Mở Arduino IDE, trên thanh Menu chọn File → Preferecens, trong tab settings chọn các tùy chọn như hình dưới:

Hình 10. Thêm file thông tin board ESP8266

Sketchbook location là đường dẫn mà bạn muốn lưu Sketch (file chương trình), trên các hệ điều hành Unix liked đường dẫn mặc định là: /home/name_your_computer/Arduino. Đây cũng sẽ là vị trí lưu

những thư viện mà chúng ta sẽ thêm vào sau này.

Mục Additional Board Manager URLs field nhập đường dẫn

http://arduino.esp8266.com/stable/package_esp8266com_index.json.

Bước 3: Cài đặt board ESP8266.

Mở Boards Manager ở mục Tools trên thanh menu-bar → tìm board cần sử dụng với keyword Generic

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

23/155

8266 → chọn board cần cài đặt như hình và nhấn vào install.

Hình 11. Cài đặt board ESP8266

Cài đặt thư viện Arduino

Một số thư viện do các nhà phát triển khác công bố và được tự do sử dụng có thể cài đặt trực tiếp bằng công cụ Library Manager của Arduino.

Khởi động arduino IDE và chọn mục Sketch ⇒ include library ⇒ Manage libraries:

Hình 12. Khởi động Library Manager

Trong mục libbrary manager nhập nội dung thư viện cần tìm tại hộp thoại text box, chọn phiên bản, rồi nhấn install, Những thư viện đã được cài đặt sẽ có text hiển thị INSTALLED ở đầu mỗi thư viện. Ví dụ tìm thư viện OLED liên quan đến ESP8266:

https://thuviensach.vn

24/155

Hình 13. Cài đặt thư viện

USB CDC driver.

Board ESP8266 WiFi Uno được kết nối với máy tính qua cổng USB MicroB và sử dụng chip CH340 để

chuyển đổi USB sang UART. Vì vậy cần cài USB driver để máy tính và board có thể giao tiếp với nhau.

Thực hiện kết nối cable USB với board, đảm bảm đèn LED khoanh tròn sáng như ở hình dưới:

Hình 14. Connect USB

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

25/155

Windows & Linux

Tải bản cài đặt USB driver cho Windows www.wch.cn/download/CH341SER_ZIP.html và cho Linux

www.wch.cn/download/CH341PAR_LINUX_ZIP.html Làm theo các yêu cầu cài đặt. Sau khi cài đặt, kết quả hiển thì trên Arduino như hình:

Hình 15. Kết nối thành công

Mac OS

Tải bản cài đặt: arduino.esp8266.vn/_static/download/CH34x_Install_V1.3.pkg

Đối với Mac OS Sierra trở về sau nếu gặp vấn đề bị RESET máy thì xử lý như sau:

• Mở ứng dụng "Terminal" cmd + space -→ Enter Terminal

• Xóa driver: sudo rm -rf /System/Library/Extensions/usb.kext

• Với một số máy, bạn phải thực thi thêm sudo rm -rf /Library/Extensions/usbserial.kext

• Nếu không thể thực hiện được lệnh trên, bạn cần phải thay đổi Security and Privacy trong phần

System Preference. Chọn Allow Apps Downloaded From từ Mac App Store and Identified

Developers sang Anywhere - Và tải CH34x_Install_V1.3.pkg về cài đặt lại.

https://thuviensach.vn

26/155

Hình 16. Lựa chọn Allow Apps Downloaded From Anywhere

Chọn Board ESP8266 WiFi Uno trong Arduino IDE

Sau khi kết nối và cài đặt xong, sẽ xuất hiện cổng COM ảo trên máy tính (Tùy từng loại hệ điều hành mà có những tên cổng như: COM1, COM2 … đối với Windows, /dev/tty.wchusbserial1420 trên Mac OS,

/dev/ttyUSB0 trên Linux) Mở Arduino IDE và lựa chọn (tham khảo cấu hình kết nối như hình dưới):

Hình 17. Cấu hình Board ESP8266 WiFi Uno

• Board: Generic ESP8266 Module.

• Flash Size: 4M (3M SPIFFS).

• Port: chọn cổng khi gắn thiết bị vào sẽ thấy xuất hiện.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

27/155

• Upload speed: Chọn cao nhất, nếu nạp không được chọn thấp dần.

Nạp chương trình xuống board dùng Arduino IDE

Trên giao diện Arduino có 2 nút, ngoài cùng bên trái là nút Verify, để biên dịch chương trình, tương đương với Sketch > Verify/Compile, nút tiếp theo là Upload, tương đương Sketch > Upload. Khi đã lựa chọn board phù hợp, chương trình không có lỗi, thì nhấn Upload sẽ nạp chương trình vào board và

thực thi sau đó.

Hình 18. Nạp chương trình

Xuất firmware binary trong Arduino IDE

Với bất kỳ tình huống nào cần file Binary, bạn có thể được xuất ra bằng cách Sketch > Export

compiled Binary, và file .bin sẽ nằm trong thư mục của Sketch.

https://thuviensach.vn

28/155

Hình 19. Xuất file Binary

Serial Terminal

Có nhiều ứng dụng miễn phí để tương tác với cổng Serial trên máy tính:

• Windows: PuTTY, realterm

• Linux: minicom, screen

• MacOS: minicom, screen

Sử dụng Arduino IDE Serial Monitor

Arduino có tích hợp sẵn Serial Monitor, khi chọn đúng cổng Serial, thì có thể nhấn biểu tượng Serial trên IDE để mở:

Hình 20. Arduino IDE Serial Monitor

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

29/155

Node.js

Tải và cài đặt Node.js tại: nodejs.org/en/download/

Sublime Text

Tải và cài đặt tại: www.sublimetext.com/

Git

Một công cụ hỗ trợ khác bạn cũng nên cài đặt và tập sử dụng, nó không giúp bạn trở thành 1 lập trình viên, nhưng nó giúp 1 lập trình viên trở nên chuyên nghiệp và làm việc hiệu quả: git-scm.com/

https://thuviensach.vn

30/155

Tổng kết

Tới lúc này, bạn có thể đã có cái nhìn tổng quan về hệ sinh thái, công cụ và phương thức làm việc với ESP8266 cũng như tổng quan về hệ thống IoT. Đồng thời đã có thể bắt đầu việc phát triển ứng dụng cho ESP8266 ngay lập tức. Các công cụ được lựa chọn đều là đa nền tảng, dễ dàng được sử dụng

cho các hệ điều hành Mac OS, Windows, hay Linux

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

31/155

Hello World

Bất kỳ một chương trình học nào cũng cần nên bắt đầu một cách từ từ. Bởi vì thời điểm này chúng ta đều mới bắt đầu, nhiều khái niệm, kiến thức về lĩnh mực này gần như không có nhiều. Helloworld giúp các bạn có thể nắm được các kiến thức cơ bản, làm sao để biên dịch, nạp được chương trình. Làm

sao để sử dụng các thư viện công cộng. Cũng như nắm được một số kiến thức về kiến trúc chương

trình Arduino.

https://thuviensach.vn

32/155

Chớp tắt bóng LED

Kiến thức

Đèn LED viết tắt (Light Emitting Diodes) - là bóng bán dẫn có thể phát sáng với màu sắc khác nhau tùy thuộc vào chất liệu bán dẫn. Để điều khiển được bóng LED cần cung cấp mức điện áp chênh lệch

giữa cực âm và cực dương của bóng LED cao hơn mức điện áp Vf (datasheet), thường là 3.2v, và dòng điện nhỏ hơn mức chịu đựng của nó, thường là 15mA.

Anode

Cathode

Hình 21. Ký hiệu LED trên mạch điện (Cathode+, Anode-)

Hình 22. Mạch có thể chạy được như sau

Arduino IDE

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

33/155

Hình 23. Arduini IDE

① Biên dịch chương trình (kiểm tra có lỗi hay không).

② Biên dịch và nạp chương trình.

③ Tab tên file.

④ Khu vực nội dung file ino.

Đấu nối

Hình 24. Mạch ESP8266 WiFi Uno có đấu nối sẵn LED vào Pin 16, và nút nhất vào Pin 0

Với mã nguồn bên dưới, sau khi kiểm tra chương trình, bạn cần chắc chắn đã Chọn Board ESP8266

WiFi Uno trong Arduino IDE và Nạp chương trình xuống board dùng Arduino IDE

https://thuviensach.vn

34/155

Mã nguồn chớp tắt dùng Delay

int pin_led = 16;

/* h à m n à y đượ c g ọ i 1 l ầ n duy nh ấ t khi kh ở i độ ng */

void setup() {

pinMode(pin_led, OUTPUT); // c ấ u h ì nh pin 16 l à ng õ ra

}

/* h à m loop s ẽ đượ c g ọ i li ê n t ụ c */

void loop() {

digitalWrite(pin_led, HIGH); // t ắ t LED (HIGH - c ó ngh ĩ a l à m ứ c cao) delay(1000); // ch ờ 1 gi â y

digitalWrite(pin_led, LOW); // b ậ t LED b ở i m ứ c đ i ệ n á p LOW

delay(1000); // ch ờ 1 gi â y

}

Mã nguồn chớp tắt dùng định thời

int ledPin = 16;

int ledState = LOW;

unsigned long previousMillis = 0;

const long interval = 1000;

void setup() {

pinMode(ledPin, OUTPUT);

}

void loop() {

unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (ledState == LOW)

ledState = HIGH; // Đổ i tr ạ ng th á i

else

ledState = LOW; // Đổ i tr ạ ng th á i

digitalWrite(ledPin, ledState);

}

}

Digital IO

Tên Pin trong Arduino (Pin number) giống với thứ tự chân của ESP8266. pinMode, digitalRead, và

digitalWrite đều sử dụng Pin Number như nhau, ví dụ như đọc GPIO2, gọi hàm digitalRead(2).

Các chân GPIO0 đến GPIO15 có thể là INPUT, OUTPUT, hay INPUT_PULLUP. Chân GPIO16 có thể là

INPUT, OUTPUT hay INPUT_PULLDOWN_16. Khi khởi động, tất cả các chân sẽ được cấu hình là INPUT.

Mỗi chân có thể phục vụ cho một tính năng nào đó, ví dụ Serial, I2C, SPI. Và tính năng đó sẽ được cấu hình đúng khi sử dụng thư viện.

GPIO6 và GPIO11 không được thể hiện bởi vì nó được sử dụng cho việc kết nối với Flash. Việc sử dụng 2

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

35/155

chân này có thể gây lỗi chương trình.

Một số board và module khác (ví dụ ESP-12ED, NodeMCU 1.0) không có GPIO9 và



GPIO11, họ sử dụng với chế độ DIO cho Flash, trong khi ESP12 chúng ta nói bên

trên sử dụng chế độ QIO

Ngắt GPIO hỗ trợ thông qua các hàm attachInterrupt, detachInterrupt Ngắt GPIO có thể gán cho bất

kỳ GPIO nào, ngoại trừ GPIO16 và đều hỗ trợ các ngắt tiêu chuẩn của Arduino như: CHANGE, RISING,

FALLING.

Tổng kết

Các ứng dụng mở rộng

• Fading LED (sáng dần hay tắt dần)

• Chớp tắt LED dùng Ticker == Nút nhấn

Kiến thức

Nút nhấn sẽ giúp việc ESP8266 khởi động một hành động nào đó khi cần thiết. Trong nhiều ứng dụng

chúng ta hầu như đều cần những kích hoạt từ bên ngoài. Xuyên suốt cuốn sách này, sẽ dùng nút

nhấn để kích hoạt chạy các ứng dụng mẫu cũng như đèn LED để thông báo các trạng thái. Trong

phần này, nhấn nút đèn LED sẽ chuyển trạng thái (từ sáng → tắt và ngược lại).

Đây là ví dụ đơn giản, trong thực tế việc xử lý nút nhấn khá phiền phức. Bởi vì nút nhấn vật lý khi được nhấn sẽ tạo ra hàng loạt các xung lên xuống (nhiễu, bouncing…). Thường thì chỉ cần đảm bảo mức

Logic của chân đo được đã được giữ ổn định trong khoảng 100 mili giây là được xem đã ổn định.

Ngoài cách dùng ngắt để xác định nút nhấn có được nhấn hay không - cách này sẽ tiết kiệm tài

nguyên tính toán của CPU, nó chỉ được gọi khi có sự kiện xảy ra, thì còn một cách nữa là hỏi vòng: Cách này đỏi hỏi CPU liên tục kiểm tra xem mức Logic của nút nhấn. Đồng thời việc đáp ứng cũng

không nhanh bằng sử dụng ngắt.

https://thuviensach.vn

36/155



Yêu cầu: Nhấn nút (GPIO0) thì chớp tắt đèn LED (GPIO6) và in ra cổng Serial



Mạch ESP8266 WiFi Uno đấu sẵn nút nhấn vào GPIO0

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

Mã nguồn dùng hỏi vòng

int ledPin = 16; // LED n ố i v à o ch â n 16

int btnPin = 0; // N ú t nh ấ n n ố i v à o ch â n 0

int ledState = LOW;

void blink()

{

if (ledState == LOW) {

ledState = HIGH;

} else {

ledState = LOW;

}

digitalWrite(ledPin, ledState); // Đả o tr ạ ng th á i LED & in ra serial Serial.println("Pressed, value=" + String(ledState));

}

bool isPressed()

{

return (digitalRead(btnPin) == 0);

}

void setup()

{

pinMode(ledPin, OUTPUT); // C ấ u h ì nh LED l à ng õ ra

pinMode(btnPin, INPUT_PULLUP); // C ấ u h ì nh n ú t nh ấ n l à ng õ v à o pull-up Serial.begin(115200);

}

void loop()

{

if (isPressed()) {

blink();

}

}

Mã nguồn dùng ngắt

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

37/155

int ledPin = 16; // LED n ố i v à o ch â n 16

int btnPin = 0; // N ú t nh ấ n n ố i v à o ch â n 0

int ledState = LOW;

void blink()

{

if (ledState == LOW) {

ledState = HIGH;

} else {

ledState = LOW;

}

digitalWrite(ledPin, ledState);

Serial.println("Pressed, value=" + String(ledState));

}

void setup()

{

pinMode(ledPin, OUTPUT); // sets the digital pin as output

pinMode(btnPin, INPUT_PULLUP); // C ấ u h ì nh n ú t nh ấ n l à ng õ v à o pull-up attachInterrupt(btnPin, blink, FALLING); //c à i đặ t ng ắ t cho ch â n LED

Serial.begin(115200);

}

void loop()

{

//Kh ô ng ph ả i l à m g ì

}

Các khái niệm

• Ngắt Ngắt là một khái niệm liên quan nhiều đến phần cứng, một sự kiện nào đó xảy ra, bắt buộc CPU phải dừng các tác vụ bình thường khác đang thực thi để thực hiện tác vụ Ngắt. Ví dụ, cấu

hình ngắt khi có thay đổi mức logic từ 1 về 0 (cạnh xuống) của GPIO, thì khi mức logic thay đổi

trên GPIO đó, CPU sẽ ngay lập tức dừng và lưu các trạng thái tại chương trình chính và nhảy vào

hàm ngắt để thực thi các lệnh trong đó.

• pull-up/pull-down Đa số các chân GPIO của Chip đều có thể có 3 trạng thái, trạng thái là ngõ ra mức cao (logic 1), trạng thái là ngõ ra mức thấp (logic 0) và trạng thái ngõ vào (input). Ở trạng thái Input, thì các GPIO được cấu hình trở kháng cao (Hi-Z), hay còn gọi là trạng thái cách ly,

không cho dòng điện đi qua, nhưng vẫn cảm nhận được điện áp. Ở trạng thái Hi-Z, nếu không

xác định mức logic trước cho GPIO thì GPIO này bị thả trôi, nghĩa là rất dễ ảnh hưởng bởi môi

trường, khi đọc về sẽ không đoán định được mức Logic. Pull-up là nối 1 điện trở với GPIO này lên

mức logic 1, xác định trước 1 điện áp cho nó để đảm bảo không không có tác động điện nào thì

nó là mức logic 1. Tương tự, pull-down xác định trước mức logic 0 cho GPIO.

https://thuviensach.vn

38/155

OLED

Màn hình OLED

OLED (Organic Light Emitting Diode) là loại màn hình hiển thị bao gồm một lớp vật liệu hữu cơ với chủ

yếu là cacbon nằm giữa hai điện cực anot và catot sẽ tự động phát sáng mỗi khi có dòng điện chạy

qua. OLED sử dụng đi-ốt phát quang hữu cơ, chính vì thế nó không cần tới đèn nền chiếu sáng, do đó có lợi thế về kích thước cũng như tiết kiệm điện hơn so với các loại LCD. Và độ sáng tương đối tốt ở

môi trường sáng tự nhiên

Màn hình OLED SSD1306

Là màn hình loại nhỏ, kích thước tầm 0.96 inch cho tới 1.25 inch, được dùng khá rộng rãi trong các sản phẩm điện tử. Tấm nền được điều khiển bằng chip driver SSD1306. Chip này giao tiếp với các bộ điều khiển/MCU khác bằng giao tiếp LCD

Hình 25. OLED SSD1306

Giao tiếp I2C

I2C (Inter-Integrated Circuit) là một loại bus nối tiếp được phát triển bởi hãng Philips nhằm truyền nhận dữ liệu giữa các IC. I2C sử dụng 2 đường truyền tín hiệu, 1 đường xung nhịp đồng hồ (SCL) do

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

39/155

Master phát đi và 1 đường truyền dữ liệu theo 2 hướng (SDA)

Hình 26. I2C Clock

Hình 27. Mô hình mạng I2C

Mạch vật lý I2C là mạch cực thu hở, do đó để mạng I2C có thể hoạt động được, cần tối thiểu 2 cặp

điện trở pull-up như trên hình. Thông thường 4k7, hoặc 1k2. Tùy thuộc vào tốc độ truyền và khoảng cách truyền.

Hiển thị màn hình OLED với ESP8266

Bước 1: Đấu nối nối chân GPIO4 của ESP8266 với chân SDA của OLED, chân GPIO5 với SCL. Cấp

nguồn 3v3 vào VCC và đấu GND cho OLED. Tuy nhiên với board ESP8266 IoT Uno thì phần đấu nối đã

ra sẵn header, bạn chỉ cần cắm OLED vào như hình

https://thuviensach.vn

40/155

Hình 28. ESP8266 với OLED

Bước 2: Cài đặt thư viện ESP8266 and ESP32 OLED driver for SSD1306 display, xem thêm Cài đặt

thư viện Arduino

Bước 3: Lập trình Chúng ta sẽ thực hiện hiển thị giả lập đồng hô trên màn hình OLED

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

41/155

#include <Wire.h>

#include "SSD1306.h"

SSD1306 display(0x3c, 4, 5);

int thoi_gian = 0;

void setup()

{

Serial.begin(115200);

display.init();

//display.flipScreenVertically(); // đả o chi ề u

display.setFont(ArialMT_Plain_10);

display.drawString(0, 0, "Hello world");

display.display();

delay(1000);

display.clear();

}

void loop()

{

int gio, phut, giay;

delay(1000);

thoi_gian ++;

gio = thoi_gian/3600;

phut = (thoi_gian%3600)/60;

giay = thoi_gian % 60;

display.clear();

display.drawString(0, 0, String(gio) + ":" + String(phut) + ":" + String(giay)); display.display();

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

https://thuviensach.vn

42/155

Tổng kết

Thông qua các ví dụ mẫu về điều khiển đèn LED, nút nhấn và OLED, chúng ta có thể triển khai thêm

nhiều ví dụ khác sử dụng GPIO của ESP8266, cũng như hiểu rõ hơn về cách làm việc của Arduino IDE, cách nạp chương trình, sử dụng thư viện …

Một trong những ứng dụng có thể sử dụng các kiến thức này như là trò chơi Flappy Bird, bạn có thể

thử nghiệm tại đây: https://github.com/esp8266vn/arduino-flappybird

Hình 29. Arduino FlappyBird

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

43/155

ESP8266 WiFi

Kết nối WiFi chính điểm mạnh nhất của chip ESP8266, nó có thể kết nối đến các Router sẵn có trong gia đình, các Access Point với các tiêu chuẩn kết nối thông dụng hiện nay ở tần số 2.4GHz - ở chế độ

STA. Ngoài ra, ESP8266 còn hỗ trợ chế độ AP (Access Point), tức là nó có thể khởi động một (hoặc

nhiều) Access Point và cho phép các client khác có thể kết nối vào, hoặc chạy đồng thời cả chế độ

STA và AP.

Trong đa phần các ứng dụng thì chế độ STA được sử dụng rất nhiều, nó giúp thiết bị kết nối đến

mạng WiFi cục bộ, có internet để kết nối đến Server và gởi dữ liệu. Một số trường hợp khác thì chế độ

AP được sử dụng để trao đổi dữ liệu với ESP8266 và máy tính (hoặc thiết bị có hỗ trợ trình duyệt). Ví dụ như điều khiển đóng tắt đèn thông qua Web Server chạy trên ESP8266.

WiFi Access Point là một thiết bị xử lý kết nối trung tâm và phân phối các luồng dữ liệu. Như là việc xử

lý các gói tin IP để định địa chỉ mạng LAN, định tuyến các gói tin từ Internet về các máy trạm (Station).

Hình 30. WiFi Access Point

Thiết bị kết nối đến Access Point được gọi là Station, các máy tính Laptop, máy tính có card WiFi khi kết nối vào Access Point thì đều được gọi là Station

https://thuviensach.vn

44/155

Hình 31. Mạng WiFi

Các Station khi muốn kết nối vào Access Point thì cần xác định thông qua BSSID, thông thường

chúng ta hay gọi là SSID - hay mạng WiFi. Bạn có thể dễ dàng xem danh sánh SSID xung quanh mình

khi scan wifi trên máy tính để kết nối mạng Internet.

Trong phần này chúng ta sẽ tìm hiểu về các chế độ WiFi của ESP8266

• Chế độ Station - STA kết nối tới Access Point sẵn có.

• Sử dụng HTTPClient để gởi và lấy dữ liệu từ Internet.

• Chế độ Access Point - AP cho phép Client khác kết nối vào.

• Web Server chạy trên ESP8266, dùng để bật tắt đèn LED.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

45/155

Chế độ WiFi Station

Kiến thức

Để kết nối được vào mạng Internet, thì đầu tiên ESP8266 phải kết nối vào mạng WiFi nội bộ, và mạng WiFi nội bộ phải có kết nối WAN Internet. Đa phần các Modem hiện nay đều tích hợp luôn cả WiFi

Access Point, do đó khá dễ dàng trong việc triển khai các ứng dụng IoT.

Khi muốn kết nối vào mạng WiFi cục bộ thì ESP8266 cần phải hoạt động ở chế độ Station (STA), đồng thời nó phải được cung cấp tên (SSID) và mật khẩu mạng WiFi.

Mỗi Access Point đều yêu cầu một phương thức mã hóa để Station sử dụng nhằm tạo kết nối - ví dụ

các phương thức WEP, WPA2, tuy nhiên chúng ta có lẽ không cần quan tâm nhiều, vì ESP8266 sẽ tự

động thực hiện các thao tác lựa chọn phương thức mã hóa.

Khi kết nối thành công vào mạng WiFi thì ESP8266 sẽ khởi động DHCP Client (mặc định) để xin cấp

phát địa chỉ IP trước khi bắt đầu các kết nối IP. Do đó, nếu như vì lý do gì đó, mà Access Point của bạn không có DHCP Server để cấp phát IP thì bạn phải cấu hình IP tĩnh cho ESP8266.

Kết nối vào mạng WiFi nội bộ

Với đoạn code này, nếu bạn cung cấp đúng SSID và PASSWORD, đồng thời Access Point hoạt động

thì thiết bị sẽ kết nối và in ra Serial Terminal địa chỉ IP của ESP8266 trong mạng LAN

https://thuviensach.vn

46/155

#include <ESP8266WiFi.h>

const char* ssid = "your-ssid";

const char* password = "your-password";

void setup() {

// Thi ế t l ậ p truy ề n d ữ li ệ u n ố i ti ế p ở t ố c độ 115200 bits/s Serial.begin(115200);

delay(10);

Serial.print("Connecting to ");

// In ra t ê n m ạ ng wifi s ẽ k ế t n ố i đế n

Serial.println(ssid);

// Thi ế t l ậ p ESP8266 ở ch ế độ station v à k ế t n ố i đế n m ạ ng wifi đã ch ỉ đị nh WiFi.begin(ssid, password);

// Đ o ạ n code in ra d ấ u . n ế u ESP8266 ch ư a đượ c k ế t n ố i while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

// In ra d ò ng "WiFi connected" v à đị a ch ỉ IP c ủ a ESP8266

Serial.println("");

Serial.println("WiFi connected");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

}

void loop() {

}

Sử dụng WiFiMulti

Tuy nhiên, đôi lúc ứng dụng bạn cần nồi đồng cối đá, thì có 2-3 mạng WiFi để backup là bình thường, class WiFiMulti sẽ giúp bạn điều đó. Cùng với một hàm monitor đơn giản để báo cho các chức năng

khác biết khi mạng đã được thiết lập.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

47/155

#include <ESP8266WiFi.h>

#include <ESP8266WiFiMulti.h>

// Khai b á o bi ế n wifiMulti thu ộ c class ESP8266WiFiMulti để s ử d ụ ng c á c ch ứ c n ă ng c ủ a class n à y.

ESP8266WiFiMulti wifiMulti;

// Bi ế n connectioWasAlive nh ằ m ki ể m tra k ế t n ố i c ủ a ESP8266 đế n m ạ ng wifi.

boolean connectioWasAlive = true;

void setup()

{

Serial.begin(115200);

Serial.println();

// Add v à o c á c m ạ ng wifi m à ESP8266 đượ c ch ỉ đị nh s ẽ k ế t n ố i wifiMulti.addAP("primary-network-name", "pass-to-primary-network");

wifiMulti.addAP("secondary-network-name", "pass-to-secondary-network");

wifiMulti.addAP("tertiary-network-name", "pass-to-tertiary-network");

}

void monitorWiFi()

{

// Ki ể m tra n ế u ch ư a k ế t n ố i đế n 1 m ạ ng wifi n à o s ẽ c à i đặ t connectioWasAlive = false

// đồ ng th ờ i in ra d ấ u "." sau m ỗ i 500ms n ế u ch ư a đượ c k ế t n ố i.

if (wifiMulti.run() != WL_CONNECTED)

{

if (connectioWasAlive == true)

{

connectioWasAlive = false;

Serial.print("Looking for WiFi ");

}

Serial.print(".");

delay(500);

}

// N ế u đã k ế t n ố i đế n 1 trong c á c m ạ ng wifi s ẽ in ra t ê n m ạ ng wifi v à set connectioWasAlive = true

// để khi m ấ t k ế t n ố i ch ươ ng tr ì nh s ẽ v à o ph ầ n if (connectioWasAlive == true) nh ằ m th ô ng b á o đ ang

// t ì m ki ế m m ạ ng wifi

else if (connectioWasAlive == false)

{

connectioWasAlive = true;

Serial.printf(" connected to %s\n", WiFi.SSID().c_str());

}

}

void loop()

{

monitorWiFi();

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

https://thuviensach.vn

48/155

HTTP Client

Giao thức HTTP

HTTP - Hypertext Transfer Protocol (giao thức truyền dẫn siêu văn bản), là giao thức để truyền dữ

liệu giữa các máy tính qua www (World Wide Web), với dữ liệu có thể là dạng text, file, ảnh, hoặc video.

HTTP được thiết kế để trao đổi dữ liệu giữa Client và Server trên nền TCP/IP, nó vận hành theo cơ chế

yêu cầu/trả lời, stateless - không lưu trữ trạng thái. Trình duyệt Web chính là Client, và một máy chủ

chứa Web Site là Server. Client sẽ kết nối tới Server, gởi dữ liệu đến server bao gồm các thông tin header. Server nhận được thông tin và căn cứ trên đó gởi phản hồi lại cho Client. Đồng thời đóng kết nối.

Một ví dụ điển hình là khi bạn gõ địa chỉ vào thanh địa chỉ của trình duyệt và nhấn Enter, thì ngay lập tức Web Client sẽ thực hiện việc gởi yêu cầu tới Web Server có địa chỉ mà bạn vừa gõ. Web Server sẽ

trả lời bằng nội dung Web Site mà bạn cần xem.

Trong giao thức HTTP, việc thiết lập kết nối chỉ có thể xuất phát từ phía client ( lúc này có thể gọi là HTTP Client ). Khi client gửi yêu cầu, cùng với URL và payload ( dữ liệu muốn lấy ) tới server. Server (

HTTP Server ) lắng nghe mọi yêu cầu từ phía client và trả lời các yêu cầu ấy. Khi trả lời xong kết nối được chấm dứt.

Hình 32. Cách thức HTTP hoạt động

Khi nhắc tới HTTP thì Hyperlink, hay URL (Uniform Resource Locator) là những khái niệm được thấy

hàng ngày

URL được dùng để định dạng địa chỉ Website, chứa các thông tin yêu cầu từ client và server dựa vào đó xử lý, cấu trúc của nó như hình:

Hình 33. Cấu trúc 1 URL

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

49/155

Ví dụ bạn có thể gởi thông tin về nhiệt độ đến server thông qua đường dẫn:

http://esp8266.vn/log.php?nhiet_do=30

Cấu trúc 1 URL

|scheme | host |port |path |query |fragment|

http:// server.com: 8080 /path/to/log.php ?nhiet_do=30&do_am=80 #test

① scheme xác định giao thức truyền tới server, nếu là https thì sẽ được mã hóa.

② host địa chỉ server.

③ port port server dùng để phục vụ, nếu ko có thì mặc định là 80 cho web.

④ path thông tin client muốn truy suất.

⑤ query thông tin client muốn gởi lên.

⑥ fragment thuộc tính này giúp browser đi đến vị trí của trang.

Với đường dẫn như trên, khi bạn gõ vào trình duyệt, thì trình duyệt sẽ thực hiện kết nối và gởi dữ liệu như sau.

GET /log.php?nhiet_do=30 HTTP/1.1

Host: esp8266.vn

User-Agent: curl/7.49.1

Accept: */*

Dữ liệu trả về:

HTTP/1.1 200 OK

Content-Type: text/html; charset=utf-8

Transfer-Encoding: chunked

Connection: keep-alive

data



Trên linux, bạn có thể sử dụng curl để xem chi tiết dữ liệu raw truyền nhận, gõ

lệnh curl -v http://esp8266.vn/log.php?nhiet_do=30 trên terminal

Giao thức HTTP định nghĩa một số phương thức (method) truyền đến

Server:

• GET là phương thức yêu cầu dữ liệu đơn giản và thường sử dụng nhất của HTTP. Phương thức

GET yêu cầu server chỉ trả về dữ liệu bằng việc cung cấp các thông tin truy vấn trên URL, thông thường Server căn cứ vào thông tin truy vấn đó trả về dữ liệu mà không thay đổi nó. path và

query trong URL chứa thông tin truy vấn.

• POST tương tự như GET, nhưng POST có thể gởi dữ liệu về Server.

https://thuviensach.vn

50/155

• PUT là phương thức yêu cầu tạo mới một dữ liệu, giống POST nhưng đánh dấu cho Server biết,

nếu dữ liệu không tồn tại trong cơ sở dữ liệu thì tạo mới, hoặc sửa đổi nó.

• DELETE Tương tự như GET, nhưng báo cho Server biết về việc xóa dữ liệu thông qua URL.

Các phương thức thông thường chỉ dùng GET và POST, các phương thức còn lại thường sử dụng

trong API server (RESTful). Một số điểm khác biệt giữ POST và GET.

• GET có thể bị cache (lưu trữ ở trình duyệt và sử dụng lại sau đó), nội dung request có thể lưu trữ

ở lịch sử trình duyệt, có thể được đánh dấu (bookmark).

• GET không nên sử dụng để gởi các dữ liệu nhạy cảm.

• GET bị giới hạn độ lớn dữ liệu cần gởi.

• GET chỉ nên dùng để lấy dữ liệu về.

• POST không bị catch, không tồn tại dữ liệu gởi trong lịch sử trình duyệt, không thể đánh dấu

(bookmark).

• POST không giới hạn bởi độ lớn dữ liệu cần gởi.

HTTP Header & Status Code

Dữ liệu trả về bao giờ cũng có phần thông tin header với dòng đầu tiên chưa Status Code HTTP/1.1

200 OK có nghĩa là status code = 200, request được trả về phù hợp. Theo sau đó là các cặp header

chứa thông tin Server muốn trao đổi với Client, mà nếu là trình duyệt thì nó bị ẩn đi (người dùng bình thường không thể thấy). Các cặp header này định dạng theo kiểu name: value và kết thúc bằng ký tự

xuống dòng không thấy bằng mắt thường (0x0D 0x0A hay \r\n). Trong ví dụ trên, thông tin header

Content-Type: text/html; charset=utf-8 báo cho trình duyệt biết rằng định dạng dữ liệu gởi về là

dạng text, mã hóa utf-8. Transfer-Encoding: chunked chiều dài dữ liệu không được biết trước và gởi cho tới khi server đóng kết nối.

Một số HTTP status code thường thấy:

• 1xx: Mã trạng thái thông tin. Bản chất của mã trạng thái này, chỉ để thông báo với client rằng request đã được chấp nhận. Các mã trạng thái thông tin này được quy định trong HTTP/1.1, còn phiên bản HTTP/1.0 hay trước đó thì không có, có thể bỏ qua phần mã trạng thái này. Các mã hay gặp:

◦ 100 Continue: Thông báo cho Client biết là có thể gửi tiếp phần request còn lại nếu còn, kết thúc nếu đã hết. Nếu trong request POST, phần thân request lớn sẽ bị server từ chối và

để giải quyết điều này thì client phải gửi Expect: 100-continue theo sau phần header

ban đầu.

• 2xx: Nhóm mã trạng thái này thông báo với Client rằng request đã được nhận, hiểu và xử lý thành công. Với một số mã thường thấy:

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

51/155

◦ 200 OK: Thông báo cho Client biết là request đã gửi thành công. Có thể thấy mã trạng thái này trong các phương thức GET, HEAD, POST, TRACE.

◦ 201 Created: Cho biết request đã xử lý thành công và tài nguyên đã được khởi tạo. Được

sử dụng để xác nhận sự thành công của một request PUT hoặc POST.

◦ 204 No Content: Thông báo không có phần thân message trong response.

• 3xx: Nhóm mã trạng thái thông báo Client còn phải thực hiện thêm hành động để hoàn thành request. Mã trạng thái thường gặp trong nhóm:

◦ 301 Moved Permanently: Thông báo tài nguyên được yêu cầu đã được chuyển hướng

sang một URL mới và server sẽ gửi URL mới này trong response cho Client biết.

• 4xx: Nhóm mã thông báo các lỗi từ phía Client. Được sử dụng khi server cho rằng phía Client đang xảy ra lỗi, với một request, hoặc tài nguyên không hợp lệ, hoặc một request không đúng.

Các mã thông dụng:

◦ 400 Bad Request: Thông báo request đã gửi là sai.

◦ 401 Unauthorized: Chỉ ra rằng request cần được xác thực. Client có thể gửi lại request với header đã được xác thực. Trường hợp đã đính kèm header xác thực nhưng vẫn nhận được

thông báo này tức là header xác thực chưa hợp lệ.

◦ 403 Forbidden: Server từ chối quyền truy cập của Client.

◦ 404 Not Found: Thông báo tài nguyên không hợp lệ và không tồn tại trên server.

◦ 409 Conflict: Server không thể hoàn thành yêu cầu vì Client cố chỉnh sửa tài nguyên mới

hơn so với timestamp của Client. Xung đột xảy ra chủ yếu trong các request PUT trong quá trình hợp tác chỉnh sửa tài nguyên.

• 5xx: Nhóm lệnh thông báo server đang ở trong tình trạng lỗi hoặc không có khả năng thực hiện yêu cầu. Một số mã thường gặp:

◦ 500 Internal Server Eror: Cho biết là không thể thực hiện request của Client.

◦ 501 Not Implemented: Thông báo server không có phương thức được yêu cầu hoặc

không có khả năng hổ trợ chức năng mà Client đã request.

◦ 503 Service Unavailable: Xảy ra khi hệ thống của server đang bảo dưỡng hoặc quá tải.

JSON

JSON (JavaScript Object Notation) là 1 định dạng trao đổi dữ liệu để giúp việc đọc và viết dữ liệu trở

nên dễ dàng hơn, máy tính cũng sẽ dễ phân tích và tạo ra JSON. Chúng là cơ sở dựa trên tập hợp

của ngôn ngữ lập trình JavaScript. JSON là 1 định dạng kiểu text mà hoàn toàn độc lập với các ngôn ngữ hoàn chỉnh, thuộc họ hàng với các ngôn ngữ trong họ hàng của C, gồm có C, C++, C#, Java,

JavaScript, Perl, Python, và nhiều ngôn ngữ khác. Những đặc tính đó đã tạo nên JSON 1 ngôn ngữ

https://thuviensach.vn

52/155

hoán vị dữ liệu lý tưởng.

JSON được xây dựng trên 2 cấu trúc:

• Là tập hợp của các cặp tên và giá trị name-value. Trong những ngôn ngữ khác nhau, đây có thể

là 1 object, record, struct, dictionary, hash table, keyed list hay associative array.

• Là 1 tập hợp các giá trị đã được sắp xếp. Trong hầu hết các ngôn ngữ, dữ liệu này được xem như

array, véc tơ, list hay sequence. Đây là 1 cấu trúc dữ liệu phổ dụng. Hầu như tất cả các ngôn

ngữ lập trình hiện đại đều hổ trợ. Chúng tạo nên ý nghĩa của 1 định dạng hoán vị dữ liệu với các

ngôn ngữ lập trình cũng đã được cơ sở hoá trên cấu trúc này.

Cú pháp

• Dữ liệu nằm trong các cặp name/value

• Các dữ liệu được ngăn cách bởi dấy phẩy ,

• Các đối tượng (name/value) nằm giữa hai dấu ngoặc kép "

• Tất cả các đối tượng nằm bên trong hai dấu ngoặc nhọn {}

• Dữ liệu của JSON được viết theo từng cặp name/value. Một cặp name/value bao gồm trường

name ( nằm trong hai dấu ngoặc kép ", theo sau là dấu hai chấm :, và sau cùng là trường value (cũng được nằm trong hai dấu ngoặc kép ". Ví dụ: "name":"John"

{

"username" : "your-user-name",

"email" : "your-email@email.com",

"website" : "iota.edu.vn",

"title" : "IoT Stater Cource"

}

Ứng dụng xem giá Bitcoin

Một ứng dụng đơn giản sử dụng giao thức HTTP để lấy tỉ giá Bitcoin (BTC)/USD từ các trang Web giao dịch, hiển thị lên màn hình OLED.

Chúng ta có rất nhiều nguồn lấy tỉ giá, một trong số đó là www.cryptocompare.com/. Với tài liệu được cung cấp, và nhu cầu là chỉ lấy tỉ giá Bitcoin/USD, chúng ta chỉ cần ESP8266 gởi 1 HTTP Request đến

min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD thì sẽ nhận được một chuỗi JSON

dạng như:

{"USD" :4731.44}

và giá trị của trường USD chính là giá trị chúng ta muốn hiển thị.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

53/155

Đa số các dịch vụ Web hiện nay đều sử dụng giao thức bảo mật HTTPS, về cơ



bản nó cũng là HTTP, nhưng quá trình truyền nhận được mã hóa dữ liệu, thực

hiện xác thực trước khi gửi giữa Client và Server.

Khi dùng HTTPS, chúng ta cần cung cấp SHA1 Fingerpint để Client có thể xác thực server. Bạn có thể

dùng trình duyệt để truy cập trước để lấy. Nếu là Chrome, sau khi truy cập vào địa chỉ min-

api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD, Nhấn Ctrl+Shift+I (Shift + ⌘ + I với MacOS) và đi đến Security > View Certificate > Details > Thumbprint. Bạn sẽ thấy hình như bên dưới, và copy nó.

Hình 34. HTTPS Fingerprint

Đây là đoạn Code lấy giá Bitcoin, cứ mỗi 5 giây, ESP8266 sẽ kết nối đến Cryptocompare server để

lấy thông tin và hiển thị lên OLED.

https://thuviensach.vn

54/155

#include <ESP8266WiFi.h>

#include <ESP8266HTTPClient.h>

#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson

#include "SSD1306.h" //https://github.com/squix78/esp8266-oled-ssd1306

const char* ssid = ".....";

const char* password = "....";

SSD1306 display(0x3c, 4, 5);

/* xem th ê m https://www.cryptocompare.com/api/ */

const char* host = "https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD";

/*SHA1 fingerprint*/

const char* fingerprint = "61 DE E9 FF BB 6B AD AA E4 9A 38 95 DC EC 74 2C 61 4B 7D 07"; void getBitcoin()

{

HTTPClient http;

Serial.print("connecting to ");

Serial.println(host);

http.begin(host, fingerprint);

int httpCode = http.GET();

if (httpCode == HTTP_CODE_OK) {

String payload = http.getString();

Serial.println(payload);

StaticJsonBuffer<512> jsonBuffer;

JsonObject& root = jsonBuffer.parseObject(payload);

if (!root.success()) {

Serial.println("parseObject() failed");

return;

}

double priceUSD = root["USD"];

display.clear();

display.drawString(0, 0, "Bitcoin price");

display.drawString(0, 18, String(priceUSD));

display.display();

Serial.println(priceUSD);

}

http.end();

}

void setup() {

Serial.begin(115200);

display.init();

display.clear();

display.setFont(ArialMT_Plain_16);

display.drawString(0, 0, "Connecting to");

display.drawString(0, 18, ssid);

display.display();

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

display.clear();

display.drawString(0, 0, "Connected");

display.display();

}

void loop() {

if (WiFi.status() == WL_CONNECTED) {

getBitcoin();

}

delay(5000);

}

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

55/155

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

Hình 35. Kết quả lấy giá Bitcoin và hiện thị mỗi 5 giây

https://thuviensach.vn

56/155

Chế độ WiFi Access Point

ESP8266 hoạt động ở chế độ Access Point

ESP8266 có khả năng cho phép các thiết bị khác (Station - STA) truy cập vào và hoạt động như là 1

Access Point, có thể tự thiết lập 1 mạng WiFi nội bộ, với khả năng khởi động DHCP Client và cung cấp được IP cho các Client kết nối tới. Do giới hạn về RAM, nên số lượng tối đa các STA có thể kết nối đến một ESP8266 hiện tại là 5.

Khởi tạo mạng

Đầu tiên bạn cần include <ESP8266WiFi.h>, thư viện này chứa hàm softAP dùng để cấu hình Access Point mềm (soft AP) để khởi tạo một mạng WiFi.

Một mạng WiFi đơn giản nhất chỉ cần cung cấp tên SSID và không mật khẩu WiFi.softAP(ssid). Phức

tạp hơn, bạn cung cấp mật khẩu cho mạng WiFi WiFi.softAP(ssid, password), hoặc chi tiết

WiFi.softAP(ssid, password, channel, hidden) khi cung cấp chính xác kênh truyền (1..13), mặc định 1 và ẩn nó đi, không hiển thị ra khi hidden = true

Nhớ rằng ssid sử dụng chuỗi ký tự không quá 63, và mật khẩu (có thể không cần) với tối thiểu 8 ký tự

cho mạng WPA2-PSK

Hàm softAP sẽ trả về true nếu khởi tạo thành công mạng WiFi

Lưu ý rằng, mạng WiFi khởi tạo bởi hàm softAP sẽ sử dụng địa chỉ IP mặc định là

192.168.4.1, và chạy 1 DHCP Server cung cấp dải IP cho client kết nối tới là



192.168.1.x. Bạn có thể thay đổi địa chỉ IP mặc định này bằng hàm softAPConfig.

Ngoài ra, ESP8266 có thể chạy được song song 2 chế độ Station và Access

Point, nhưng lưu ý, chỉ được 1 channel, và channel của softAP sử dụng bởi

channel của Station.

WiFi.softAPConfig (local_ip, gateway, subnet) dùng để cấu hình IP cho Access Point

Cấu hình địa chỉ IP cho ESP8266 AP là 192.168.4.22

IPAddress local_IP(192,168,4,22);

IPAddress gateway(192,168,4,9);

IPAddress subnet(255,255,255,0);

WiFi.softAPConfig(local_IP, gateway, subnet)

WiFi.softAPgetStationNum() sẽ trả về số lượng client đang kết nối tới Access Point

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

57/155

Khởi tạo mạng WiFi sử dụng ESP8266

Với đoạn code này, bạn có thể tạo ra một mạng WiFi cục bộ có SSID là AP-XXXXXX và có thể dùng

máy tính để kết nối trực tiếp vào với password là password

#include <ESP8266WiFi.h>

const char *password = "password";

void setup() {

Serial.begin(115200);

Serial.print("Configuring access point...");

char ssid[64];

sprintf(ssid, "AP-%06X", ESP.getChipId());

WiFi.softAP(ssid, password);

IPAddress myIP = WiFi.softAPIP();

Serial.print("AP IP address: ");

Serial.println(myIP);

}

void loop() {

Serial.printf("Stations connected = %d\n", WiFi.softAPgetStationNum());

delay(3000);

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

Hình 36. Khi khởi động 1 WiFiAccesspoint

https://thuviensach.vn

58/155

Web Server

Web Server là gì?

Web Server là một máy chủ Web mà khi có bất kỳ một Web Client nào (chẳng hạn Web Browser) truy

cập vào, thì nó sẽ căn cứ trên các thông tin yêu cầu truy cập để xử lý, và phản hồi lại nội dung. Đa phần các nội dung Web Server phục vụ là HTML, Javascript, CSS, JSON và bao gồm cả các dữ liệu

Binary.

Mặc định các Web Server phục vụ trên Port 80, và 443 cho dịch vụ Web có bảo mật HTTPS

HTML - Javascript - CSS

HTML, Javascript và CSS là ba ngôn ngữ để xây dựng và phát triển Web. Những hiểu biết cơ bản về

chúng sẽ tạo điều kiện thuận lợi cho các quá trình tiếp theo sau được dễ dàng hơn.

HTML

Viết đầy đủ là Hyper Text Markup Language - ngôn ngữ đánh dấu siêu văn bản dùng để cấu trúc nội dung của một trang Web, ví dụ như: chỉ định các đoạn văn bản, tiêu đề, bảng dữ liệu, hoặc nhúng hình ảnh hoặc video vào Web. Mỗi trang Web chứa một loạt các liên kết đến các trang khác được gọi là hyperlinks (siêu liên kết). Mỗi trang được tạo ra từ nhiều tag (thẻ) khác nhau, với cấu trúc một tag như sau

Cấu trúc 1 tag

<tagname> nội dung tag...</tagname>

• Các tag thường đi theo cặp, bắt đầu bởi <tagname> và kết thúc bằng </tagname>



Tag kết thúc phải có dấu gạch chéo / phía trước tên thẻ.

Trang HTML cơ bản có thể được thấy như sau:

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

59/155

<!DOCTYPE html>

< html>

< head>

< title>Page Title</title>

</head>

< body>

< h1>This is a Heading</h1>

< p>This is a paragraph.</p>

</body>

</html>

Với một số tag cơ bản như sau:

• <!DOCTYPE html> cho biết là HTML5.

• <html> root của trang HTML.

• <head> chứa thông tin về tài liệu.

• <title> phần tiêu đề trang.

• <body> phần chứa nội dung trang hiển thị.

• <h1> nơi chứa phần tiêu đề chính.

• <p> phần ghi các đoạn văn bản.

Javascript

Javascript là một ngôn ngữ được thiết kế chủ yếu để thêm tương tác vào các trang Web, và tạo ra

các ứng dụng Web.

Các chương trình Javascript có thể được nhúng trực tiếp vào HTML của Web. Và tùy vào mục đích cụ

thể, script có thể chạy khi mở trang Web, nhấp chuột, gõ phím, gửi biểu mẫu, cập nhật dữ liệu, giao tiếp với cơ sở dữ liệu…

Để nhúng chương trình viết bằng Javascript vào trang HTML, chỉ cần thêm tag <script> và thuộc tính type. Có thể thêm phần này ở phần <head> hoặc phần <body> của HTML. Ví dụ sau đây minh họa việc thêm một chương trình Javascript vào phần thân (<body>) của HTML:

https://thuviensach.vn

60/155

<!DOCTYPE html>

< html>

< head>

< title>My first JavaScript page</title>

</head>

< body>

< script type="text/javascript">

// ch ươ ng tr ì nh Javascript n ê n đượ c vi ế t ở đâ y

// ngay tr ướ c </body>

</script>

</body>

</html>

CSS

CSS là từ viết tắt của Cascading Style Sheets, là một ngôn ngữ được thiết kế để xử lý giao diện Web, giúp các trang Web được đẹp hơn. CSS có thể kiểm soát được màu sắc của văn bản, phong

chữ, kích cỡ chữ, khoảng cách giữa các đoạn văn, hình nền hoặc màu nền, và nhiều hiệu ứng khác.

Một đoạn CSS bao gồm 4 phần như thế này:

vùng-chọn {

thuộc-tính-a: giá-trị-x;

thuộc-tính-b: giá-trị-y;

.....

}

Ví dụ về sử dụng CSS trong HTML

<!DOCTYPE html>

< html>

< head>

< title>My first JavaScript page</title>

< style>

. class-select {

background-color: red;

}

#id-select {

background-color: green;

}

div {

color: blue;

}

</style>

</head>

< body>

< div id="id-select"> css select by id </div>

< div class="class-select"> css select by class </div>

</body>

</html>

Với đoạn HTML bên trên, thì màu nền của tag div có id = id-select sẽ có màu xanh lá cây, tag div có class = class-select sẽ có màu đỏ, và chữ của tất cả những thẻ div có màu xanh nước biển.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

61/155

Ứng dụng điều khiển đèn LED thông qua Webserver

ESP8266 hoàn toàn có thể thực hiện vai trò Web Server để phục vụ cho một vài kết nối đến, tận dụng giao diện Web để điều khiển, cấu hình cho nó.

ESP8266 Web Server

Với ứng dụng này, ESP8266 sẽ khởi tạo 1 Web Server, khi có bất kỳ client nào kết nối tới (Web

Browser) thì ESP8266 sẽ gởi về 1 trang HTML với các thông tin để Client có thể điều khiển chớp tắt đèn LED của board.

#include <ESP8266WiFi.h>

#include <ESP8266WebServer.h>

const char* ssid = "........";

const char* password = "........";

const int led = 16; //LED pin = gpio16

/* HTML s ẽ đượ c g ở i xu ố ng client */

const char *html = \

"<html>\

<head>\

<title>ESP8266 Webserver</title>\

</head>\

<body>\

<a href=\" /on\" >ON</a>\

<a href=\" /off\" >OFF</a>\

</body>\

</html>";

/* Web Server l ắ ng nghe ở port 80 */

ESP8266WebServer server(80);

/* h à m n à y đượ c g ọ i khi tr ì nh duy ệ t truy v ấ n đế n '/on'

* s ẽ b ậ t đè n LED (0 = on), sau đó chuy ể n h ướ ng tr ì nh duy ệ t

* v ề l ạ i trang ch ủ '/'

*/

void handleOn() {

digitalWrite(led, 0);

server.sendHeader("Location","/");

server.send(301);

}

/* h à m n à y đượ c g ọ i khi tr ì nh duy ệ t truy v ấ n đế n '/off'

* s ẽ t ắ t đè n LED (1 = off), sau đó chuy ể n h ướ ng tr ì nh duy ệ t

* v ề l ạ i trang ch ủ '/'

*/

void handleOff() {

digitalWrite(led, 1);

server.sendHeader("Location","/");

server.send(301);

}

/* h à m n à y đượ c g ọ i khi tr ì nh duy ệ t truy v ấ n đế n trang ch ủ '/'

* s ẽ g ở i d ữ li ệ u HTML, cung c ấ p c á c th ô ng tin để b ậ t, t ắ t LED

*/

void handleRoot() {

server.send(200, "text/html", html);

}

https://thuviensach.vn

62/155

void setup(void){

pinMode(led, OUTPUT);

digitalWrite(led, 0);

Serial.begin(115200);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

Serial.println("");

Serial.print("Connected to ");

Serial.println(ssid);

Serial.print("IP address: ");

/* Ch ú ng ta c ó th ể bi ế t IP c ủ a ESP8266

* để k ế t n ố i t ớ i nh ờ g ọ i h à m n à y

*/

Serial.println(WiFi.localIP());

server.on("/", handleRoot);

server.on("/on", handleOn);

server.on("/off", handleOff);

server.begin();

Serial.println("HTTP server started");

}

void loop(void){

server.handleClient();

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

Kết hợp WiFi AP và Web Server

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

63/155

Trao đổi dữ liệu giữa 2 ESP8266

Thông thường, muốn hai hay nhiều ESP8266 có thể liên lạc, trao đổi dữ liệu với nhau sẽ cần đến một router hay access-point, các module ESP8266 này sẽ kết nối vào Access Point rồi sau đó giao tiếp

với nhau.

Có một số ứng dụng đơn giản để kết nối 2 ESP8266 với nhau mà không cần Access Point, chúng ta có

thể khởi tạo 1 board hoạt động như là WiFi Access Point, đồng thời khởi tạo 1 TCP Server. Board khác hoạt động như 1 WiFi client thông thường, kết nối vào mạng WiFi đã được tạo, và khởi động 1 TCP

Client kết nối vào TCP Server kia.

Yêu cầu

• Không cần bất kỳ một Router, hay Access Point nào, thực hiện việc kết nối giao tiếp giữa 2

ESP8266 thông qua mạng WiFi, 2 Board này sẽ truyền dữ liệu với nhau mỗi giây, và hiển thị lên

Serial Terminal

Hướng dẫn thực hiện

Để trao đổi dữ liệu giữa 2 ESP8266 cần đáp ứng các điều kiện sau:

• 1 ESP8266 sẽ khởi động SoftAP để tạo mạng WiFi, đồng thời khởi động 1 TCP Server để làm

Server.

• 1 ESP8266 phải là client với chế độ WiFi Station và kết nối đến ESP8266 server đã tạo ở trên.

• Sau mỗi giây, Board ESP8266 này sẽ gởi dữ liệu vào Board kia, board nhận được dữ liệu sẽ in ra

cổng Serial và gởi ngược lại.

Code

P2P server

#include <ESP8266WiFi.h>

#define PORT 23

// Gioi han so luong clients ket noi

#define MAX_CLIENTS 3

// Ten va mat khau cua ESP8266 AP se tao

const char *ssid = "yourSSID";

const char *password = "yourPassword";

//khoi tao IP adress

IPAddress local_IP(192, 168, 4, 1);

IPAddress gateway(192, 168, 4, 1);

IPAddress subnet(255, 255, 255, 0);

https://thuviensach.vn

64/155

// Khoi tao port de clients ket noi.

WiFiServer server(PORT);

WiFiClient clients[MAX_CLIENTS];

void setup() {

Serial.begin(115200);

Serial.println();

Serial.print("Setting soft-AP configuration ... ");

//Cau hinh acces point, cai dat soft AP de client ket noi vao.

WiFi.softAPConfig(local_IP, gateway, subnet);

WiFi.softAP(ssid, password);

//In ra local_IP cua AP.

Serial.print("AP IP address: ");

Serial.println(WiFi.softAPIP());

Serial.println("Telnet server started");

server.begin();

}

void loop() {

uint8_t i;

// kiem tra co client moi ket noi khong

if (server.hasClient()) {

for (i = 0; i < MAX_CLIENTS; i++) {

if (!clients[i] || !clients[i].connected())

{ if (clients[i]) clients[i].stop();

clients[i] = server.available();

Serial.print("New client: "); Serial1.print(i);

continue;

}

}

WiFiClient serverClient = server.available();

serverClient.stop();

}

// Kiem tra neu so client ket noi MAX_CLIENTS

// co client, client duoc ket noi va o trang thai available

// doc du lieu tu client, va gui lai du lieu cho client do.

for (i = 0; i < MAX_CLIENTS; i++) {

if (clients[i] && clients[i].connected()) {

if (clients[i].available()) {

String line = clients[i].readStringUntil('\r');

Serial.print("Server receive from Client:");

Serial.println(line);

//Gui thong tin hoai dap cho client

String resp = String(line.reserve(line.length() - 1));

Serial.print(" Then, response back to client:");

Serial.println(resp);

clients[i].write(resp.c_str());

Serial.println();

}

}

}

}

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

65/155

P2P client

#include "ESP8266WiFi.h"

// Ten va mat khau cua ESP8266 AP lam server se vao

const char *ssid = "yourSSID";

const char *password = "yourPassword";

IPAddress server_ip(192, 168, 4, 1);

#define PORT 23

// port 23 la port cua esp8226 lam AP da khoi tao.

WiFiClient client;

void setup() {

uint8_t i = 0;

Serial.begin(115200);

WiFi.begin(ssid, password);

Serial.print(" \nConnecting to ");

Serial.println(ssid);

// Kiem tra t ì nh trang ket noi, neu chua ket noi duoc

// se in chuoi "connecting..." tren man hinh serial terminal.

while (WiFi.status() != WL_CONNECTED) {

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

delay(500);

}

}

unsigned long previousMillis = 0;

void loop() {

if (WiFi.status() == WL_CONNECTED) {

// Kiem tra neu client(STA) chua duoc ket noi.

// Kiem tra tiep tuc neu khong duoc ket noi den IP va PORT cua server(AP

// thi in ra serial terminal chuoi "connection failed".

while (!client.connected()) {

if (!client.connect(server_ip, PORT)) {

Serial.println("connection failed");

delay(1000);

return;

}

}

// Neu client(STA) duoc ket noi thi se doc du lieu tu server(AP)

// den khi gap ki tu \r va in ra seria terminal du lieu nhan duoc.

while (client.available()) {

String line = client.readStringUntil('\r');

Serial.print("Client receive from Server:");

Serial.println(line);

}

//Send PING to server every 1000ms.

unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= 1000) {

previousMillis = currentMillis;

client.write("PING\r");

}

}

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

https://thuviensach.vn

66/155

Tổng kết

Trong phần này, chúng ta đã nắm rõ các chế độ hoạt động của ESP8266, các giao thức truyền

TCP/IP, HTTP và các định dạng HTML, CSS, Javascript. Ngoài các ví dụ thực tiễn sử dụng ESP8266 như

HTTP Client ở hướng dẫn trên, bạn có thể sử dụng HTTPClient để kết nối đến các Server tự tạo, gởi dữ

liệu cảm biến đến Server, cũng như lấy dữ liệu từ Server để thực thi các tác vụ.

Chế độ WiFi Access Point và Web Server chạy trên ESP8266 thường sử dụng để cấu hình các thông

số cho sản phẩm, sử dụng giao diện Web có ở bất kỳ máy tính nào để cung cấp các thông số phức

tạp cho ứng dụng một cách dễ dàng.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

67/155

Dự án đọc cảm biến DHT11

và gởi về Server

Trong bài này chúng ta sẽ xây dựng ứng dụng dùng cảm biến DHT11 để thu thập nhiệt độ, độ ẩm của

môi trường. Thông tin về nhiệt độ và độ ẩm sẽ được hiển thị trên máy tính và hiển thị trên trình duyệt web bằng cách truy cập vào 1 địa chỉ URL được chỉ định. Một số kiến thức cần thiết :

• Nhiệt độ là đại lượng thể hiện tính chất vật lý nóng, lạnh của vật chất. Nhiệt độ được đo bằng các đơn vị khác nhau và có thể biến đổi bằng các công thức. Trong hệ đo lường quốc tế, nhiệt

độ được đo bằng đơn vị Kelvin, ký hiệu là K. Trong đời sống ở Việt Nam và nhiều nước, nó được

đo bằng độ C.

• Độ ẩm tương đối là tỷ số của áp suất hơi nước hiện tại của bất kỳ một hỗn hợp khí nào với hơi nước so với áp suất hơi nước bão hòa tính theo đơn vị là %. Định nghĩa khác của độ ẩm tương

đối là tỷ số giữa khối lượng nước trên một thể tích hiện tại so với khối lượng nước trên cùng thể

tích đó khi hơi nước bão hòa

• DHT11 là một cảm biến có khả năng đo nhiệt độ và độ ẩm không khí với độ chính xác vừa phải, giá cả phải chăng. Có thể lấy dữ liệu đo được của cảm biến bằng giao thức OneWire.

https://thuviensach.vn

68/155

Thiết kế ứng dụng

Hình ảnh bên dưới mô tả tổng quan dự án

Hình 37. Tổng quan mô hình của dự án

Trong thực tế, khi thiết kế ứng dụng, người dùng cần một giao diện giám sát và điều khiển thân thiện, đồng thời có thể phát triển thêm các tính năng như hiển thị kết quả dưới dạng đồ thị (chart), lưu trữ

dữ liệu theo thời gian chỉ định hay điều khiển trạng thái các thiết bị chỉ với 1 click chuột trên máy tính.

Các dự án với mô hình phức tạp sẽ cần quản lí các kết nối cũng như dữ liệu của các thiết bị…

Chúng ta sẽ giải quyết những vấn đề trên thông qua ứng dụng đọc nhiệt độ, độ ẩm của môi trường

và gửi về server. Đây là một ứng dụng khá đơn giản, hữu ích và dễ làm. Thông qua phần này chúng ta có thể xây dựng được một ứng dụng IoT thực tế, nắm bắt được các kiến thức cơ bản về thu thập dữ

liệu, xây dựng thiết bị và server.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

69/155

Yêu cầu

• Dùng cảm biến DHT11 để thu thập nhiệt độ, độ ẩm của môi trường và kết nối với board mạch

ESP8266

• Board mạch ESP8266 sẽ kết nối không dây đến mạng WiFi và gởi dữ liệu về HTTP Server

• Phần cơ bản: HTTP Server hiển thị dữ liệu nhiệt độ, độ ẩm ra màn hình Log trên máy tính

• Phần nâng cao: HTTP Server lưu trữ dữ liệu, và cung cấp file HTML cho người dùng có thể xem

qua Browser

Phân tích

• Chúng ta cần 1 Web Server viết bằng Javascript, thực thi bởi Node.js, lắng nghe ở Port được chỉ

định trên máy tính cá nhân. Ở đây là port 8000

• Máy tính phải có kết nối cùng mạng WiFi nội bộ với ESP8266 và cần biết địa chỉ IP của máy tính

để ESP8266 có thể truy cập, ví dụ IP là 192.168.1.102

• ESP8266 sau khi kết nối vào mạng WiFi nội bộ, sẽ tiến hành đọc thông số nhiệt độ, độ ẩm từ cảm

biến DHT11 và gởi về Server sau mỗi 2 giây.

• Quá trình gởi được thực hiện bởi phương thức GET, ví dụ

http://192.168.1.102/update?temp=25&humd=80 với 192.168.1.102 là địa chỉ Web Server, /update là đường dẫn, temp=20 và humd=80 chứa thông tin nhiệt độ 20 độ C và độ ẩm 80%.

• Web Server trả về trạng thái HTTP status = 200 (OK), cùng với việc hiển thị ra cửa sổ log giá trị

nhiệt độ, độ ẩm.

• Ở phần nâng cao: — Web Server lưu trữ dữ liệu nhiệt độ, độ ẩm trong mảng, chứa ở bộ nhớ RAM

— Web Server còn cung cấp 1 file index.html chứa mã Javascript có thể yêu cầu lấy dữ liệu

nhiệt độ, độ ẩm lưu trong RAM, và hiển thị lên biểu đồ

Kiến thức

Sẽ dễ dàng hơn nếu chúng ta có những kiến thức cơ bản về

• Chuẩn truyền dữ liệu OneWire giữa các IC

• Ngôn ngữ Javascript để xây dựng server bằng cách dùng Node.js

• Ngôn ngữ HTML để xây dựng 1 trang html đơn giản nhằm hiển thị dữ liệu

Tuy nhiên cũng đừng quá lo lắng nếu bạn chưa từng dùng những thứ này, chúng ta sẽ hiểu nó khi

đọc các phần tiếp theo.

https://thuviensach.vn

70/155

Cảm biến DHT 11 và chuẩn dữ liệu OneWire

• DHT11 là cảm biến có chức năng đo nhiệt độ, độ ẩm của môi trường, được dùng khá phổ biến vì

giá thành thấp và độ ổn định cao. Cảm biến sử dụng chuẩn truyền dữ liệu OneWire. Thông tin

chi tiết về DHT11 có thể xem tại Datasheet

• OneWire là chuẩn giao tiếp nối tiếp được thiết kế bởi hãng Dallas. Đó là hệ thống bus nhằm kết

nối các thiết bị với nhau để truyền hoặc nhận dữ liệu.Trong chuẩn giao tiếp này thường chỉ sử

dụng 1 chân đồng thời là vừa là nguồn cung cấp vừa là chân truyền nhận dữ liệu. Cũng giống

như các chuẩn giao tiếp khác, OneWire cũng gồm 3 giai đoạn reqquest (hỏi) → respond (đáp) →

data reading (truyền nhận dữ liệu).

Hình ảnh mô tả quá trình truyền,nhận dữ liệu của DHT11 như hình bên dưới

Hình 38. Quá trình truyền nhận dữ liệu trong chuẩn OneWire

Tóm tắt

1. Master (ESP8266) gửi tín hiệu START, DHT11 sẽ chuyển từ chế độ tiết kiệm năng lượng (low-

power mode) sang chế độ làm việc bình thường (high-speed mode)

2. DHT11 nhận được tín hiệu và phản hồi đến master, master nhận tín hiệu và bắt đầu quá trình

truyền dữ liệu.

3. DHT11 sẽ gửi dữ liệu lên bus, mỗi lần gửi là 1 gói 40 bits data.

4. Khi muốn kết thúc, Master sẽ gửi tín hiệu STOP, kết thúc quá trình truyền nhận dữ liệu

Chi tiết về chuẩn OneWire xem tại maximintegrated.com

Ngôn ngữ HTML

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

71/155

Một trong những địa chỉ web để học HTML cho người mới bắt đầu là w3school.com/HTML, lưu ý rằng chúng ta sẽ không đi quá sâu vào việc học HTML, bởi việc này có thể ảnh hướng đến tiến độ thực

hiện của project, tại thời điểm này chúng ta chỉ cần học đủ để xây dựng project hoàn chỉnh.

Node.js và Javascript

Để tạo server dùng Node.js cần trang bị một số kiến thức cơ bản về Javascript và Node.js, để học

Javascript chúng ta có thể truy cập địa chỉ URL w3school.com/Javascrpit, với Node.js thì

codeschool.com thật sự hữu ích với người mới bắt đầu.

Thực hiện

Linh kiện cần có

☑ Cảm biến DHT11

☑ Board ESP8266 WiFi Uno

☑ Dây nối male-female header

☑ Điện trở 5K Ohm

☑ Cable kết nối giữa board ESP8266 và máy tính

Đấu nối

Kết nối sơ đồ mạch điện như hình bên dưới

Hình 39. Kết nối DHT11 và ESP8266 WiFi Uno

https://thuviensach.vn

72/155

Server Nodejs

Về phía Web Server, chúng ta cần đảm bảo nó có thể phục vụ cho nhiều Client, với path là:

• /update thì sẽ thêm mới dữ liệu để lưu trữ, và in ra màn hình

• /get trả về dữ liệu đã lưu trữ định dạng JSON

• / và còn lại thì trả về file index.html

• Mảng dữ liệu lưu trữ có định dạng: [{"temp": 25, "humd":80, time: "time"}, ...]

Mã nguồn file server.js

//---------------------------------------------------------------------------------------------

var fs = require('fs');

var url = require('url');

var http = require('http');①

var querystring = require('querystring');

var db = []; //database

//---------------------------------------------------------------------------------------------

// function g ử i y ê u c ầ u(response) t ừ ph í a server ho ặ c nh ậ n y ê u c ầ u (request) c ủ a client g ử i l ê n function requestHandler(request, response) {

// Gi ả s ử đị a ch ỉ nh ậ n đượ c http://192.168.1.7:8000/update?temp=30&humd=40

var uriData = url.parse(request.url);

var pathname = uriData.pathname; // /update?

var query = uriData.query; // temp=30.5&hum=80

var queryData = querystring.parse(query); // queryData.temp = 30.5, queryData.humd = 40

//-----------------------------------------------------------------------------------------

if (pathname == '/update') {

var newData = {

temp: queryData.temp,

humd: queryData.humd,

time: new Date()②

};

db.push(newData);

console.log(newData);

response.end();

//-----------------------------------------------------------------------------------------

} else if (pathname == '/get') {③

response.writeHead(200, {

'Content-Type': 'application/json'

});

response.end(JSON.stringify(db));

db = [];

//-----------------------------------------------------------------------------------------

} else { ④

fs.readFile('./index.html', function(error, content) {

response.writeHead(200, {

'Content-Type': 'text/html'

});

response.end(content);

});

}

//-----------------------------------------------------------------------------------------

}

var server = http.createServer(requestHandler);

server.listen(8000); ⑤

console.log('Server listening on port 8000');

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

73/155

Giải thích mã nguồn

① require dùng để load các thư viện hoặc module cần thiết cho dự án

• fs: Module giúp đọc file từ server hoặc upload file lên server

• url: Chia nhỏ URL thành những thành phần để dễ dàng truy xuất

• http: Phương thức truyền nhận dữ liệu dùng http

• querystring: Module giúp chuyển string sang object

• db = []: Biến kiểu mảng nhằm chứa dữ liệu nhiệt độ, độ ẩm

② So sánh giá trị pathname để xử lí dữ liệu. Nếu pathname =/update thì sẽ tạo biến newData nhằm

lấy dữ liệu client gửi lên thông qua URL, sau đó đẩy dữ liệu vào mảng db thông qua lệnh

db.push(newData) , giá trị được hiển thị qua Log khi dùng lệnh console.log(newData). Hàm Date()

giúp lấy thời gian hiện tại.

③ Trả về định dạng JSON ('Content-Type': 'application/json') của mảng db nếu pathname = /get, sau đó xóa giá trị của mảng. Hàm response.end() sẽ trả về HTTP code (mã 200 là kết quả OK)

④ Trả về nội dung của file index.html khi không xảy ra 2 trường hợp <2> và <3>. Dùng fs để đọc file index.html và gán nội dung vào content thông qua lệnh fs.readFile('./index.html', function(error, content). Hàm response.writeHead(200, {'Content-Type': 'text/html' }) nhằm khai báo mã HTTP

code, định dạng trả về là HTML để đọc file

⑤ Khởi tạo một server HTTP và mở port 8000 để các client truy cập

Bạn có thể truy cập đến đường dẫn của file server.js và thực thi đoạn code trên với dòng lệnh node server.js, sau đó thử truy vập vào localhost:8000 để xem trang index.html. Hoặc truy cập vào

localhost:8000/update?temp=20&humd=60 để xem màn hình Log in ra kết quả nhiệt độ và độ ẩm.

{ temp: '20', humd: '60', time: 2017-08-21T16:56:23.358Z }

{ temp: '20', humd: '60', time: 2017-08-21T16:57:06.277Z }

{ temp: '20', humd: '60', time: 2017-08-21T16:57:17.708Z }

Ở phần cơ bản chúng ta chưa cần phải quan tâm đến file index.html và đoạn code Javascript trong

đó. Cũng nhưng chưa quan tâm tới việc xử lý khi đường dẫn là /get hoặc /\*, mà chỉ quan tâm duy

nhất khi nhận được với đường dẫn /update.

Khi đã hoàn thành phần cơ bản chúng ta sẽ đi đến một ứng dụng khá phổ biến, người dùng cần hiển

thị các dữ liệu thu thập một cách trực quan thông qua trình duyệt Web. Vì vậy chúng ta sẽ làm 1 file index.html chứa mã nguồn Javascript có thể yêu cầu Server trả về dữ liệu mỗi giây để hiển thị lên 1

biểu đồ canvas.

Mã nguồn file index.html

<!DOCTYPE html>①

< html>

https://thuviensach.vn

74/155

< head>

< meta charset="UTF-8">

< title>DHT11</title>

<!-- Nh ú ng file Javasript t ạ i đườ ng d ẫ n src để c ó th ể x â y d ự ng 1 graph -->

< script type="text/javascript" src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>②

</head>

< body>

< h1> 1. THONG SO NHIET DO, DO AM</h>< br> ③

< h2> Temprature</h2> < input type="text" size="6" id="temp"> &#176; C< br>

< h2> Humidity</h2> < input type="text" size="6" id="humd">%< br>

< h1> 2. DO THI</h1>< br>

<!-- thi ế t l ậ p k í ch th ướ c cho graph th ô ng qua id ChartContainer đã thi ế t l ậ p ở tr ê n -->

< div id="ChartContainer" style="height: 300px; width:80%;"></div>

< script type="text/javascript">

function httpGetAsync(theUrl, callback) { ④

var xmlHttp = new XMLHttpRequest();

xmlHttp.onreadystatechange = function() {

if (xmlHttp.readyState == 4 && xmlHttp.status == 200)

callback(JSON.parse(xmlHttp.responseText));

}

xmlHttp.open("GET", theUrl, true); // true for asynchronous

xmlHttp.send(null);

}

window.onload = function() {

var dataTemp = [];

var dataHumd = [];

var Chart = new CanvasJS.Chart("ChartContainer", {

zoomEnabled: true, // D ù ng thu ộ c t í nh c ó th ể zoom v à o graph title: {

text: "Temprature & Humidity" // Vi ế t ti ê u đề cho graph

},

toolTip: { // Hi ể n th ị c ù ng l ú c 2 tr ườ ng gi á tr ị nhi ệ t độ , độ ẩ m tr ê n graph shared: true

},

axisX: {

title: "chart updates every 2 secs" // Ch ú th í ch cho tr ụ c X

},

data: [{

// Khai b á o c á c thu ộ c t í nh c ủ a dataTemp v à dataHumd type: "line", // Ch ọ n ki ể u d ữ li ệ u đườ ng xValueType: "dateTime", // C à i đặ t ki ể u gi á tr ị t ạ i tr ụ c X l à thu ộ c t í nh th ờ i gian showInLegend: true, // Hi ể n th ị "temp" ở m ụ c ch ú th í ch (legend items) name: "temp",

dataPoints: dataTemp // D ữ li ệ u hi ể n th ị s ẽ l ấ y t ừ dataTemp

},

{

type: "line",

xValueType: "dateTime",

showInLegend: true,

name: "humd",

dataPoints: dataHumd

}

],

});

var yHumdVal = 0; // Bi ế n l ư u gi á tr ị độ ẩ m (theo tr ụ c Y) var yTempVal = 0; // Bi ế n l ư u gi á tr ị nhi ệ t độ (theo tr ụ c Y) var updateInterval = 2000; // Th ờ i gian c ậ p nh ậ t d ữ li ệ u 2000ms = 2s var time = new Date(); // L ấ y th ờ i gian hi ệ n t ạ i var updateChart = function() {

httpGetAsync('/get', function(data) {

// G á n gi á tr ị t ừ localhost:8000/get v à o textbox để hi ể n th ị

document.getElementById("temp").value = data[0].temp;

document.getElementById("humd").value = data[0].humd;

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

75/155

// Xu ấ t ra m à n h ì nh console tr ê n browser gi á tr ị nh ậ n đượ c t ừ localhost:8000/get console.log(data);

// C ậ p nh ậ t th ờ i gian v à l ấ y gi á tr ị nhi ệ t độ , độ ẩ m t ừ server time.setTime(time.getTime() + updateInterval);

yTempVal = parseInt(data[0].temp);

yHumdVal = parseInt(data[0].humd);

dataTemp.push({ // c ậ p nh â t d ữ li ệ u m ớ i t ừ server x: time.getTime(),

y: yTempVal

});

dataHumd.push({

x: time.getTime(),

y: yHumdVal

});

Chart.render(); // chuy ể n đổ i d ữ li ệ u c ủ a c ủ a graph th à nh m ô h ì nh đồ h ọ a

});

};

updateChart(); // Ch ạ y l ầ n đầ u ti ê n

setInterval(function() { // C ậ p nh ậ t l ạ i gi á tr ị graph sau th ờ i gian updateInterval updateChart()

}, updateInterval);

}

</script>

</body>

</html>

Giải thích mã nguồn

① Những tag cơ bản khi khởi tạo 1 trang HTML

• <!DOCTYPE html> cho trình duyệt biết phiên bản HTML được sử dụng

• <html> cho trình duyệt biết đây là văn bản HTML

• <head> khai báo thông tin cho trang HTML

• <meta charset="UTF-8"> cung cấp dữ liệu về văn bản HTML, dạng mã hóa charset="UTF-8"

• <title>DHT11</title> tiêu đề của trang

② Sử dụng CanvasJS Chart để vẽ biểu đồ nhiệt độ, độ ẩm.

③ Tạo 2 textbox tại tag tiêu đề phụ <h1> để hiển thị nhiệt độ, độ ẩm. Mỗi textbox sẽ có 1 id để cập nhật giá nhiệt độ, độ ẩm từ server. Mã định dạng &#176;C là của kí tự độ C

④ Hàm giúp lấy dữ liệu từ server

Phân tích phần vẽ biểu đồ

• Chúng ta sẽ lấy dữ liệu từ server gửi xuống và vẽ biểu đồ dùng mã Javascrpit, sử dụng tag

<scrpit>code JS </scrpit> để chèn nội dung code Javascrpit vào file HTML.

• Việc lấy dữ liệu được thực thi bằng hàm httpGetAsync(). Hàm này sử dụng đối tượng

XMLHttpRequest để lấy dữ liệu từ server mà không cần phải load lại trang, dữ liệu

xmlHttp.responseText lấy từ server tại địa chỉ localhost:8000/get ở định dạng JSON nên cần

phải chuyển sang dạng Object bằng hàm JSON.parse().

https://thuviensach.vn

76/155



Cần phải có dữ liệu từ ESP8266 gửi lên server thì tại địa chỉ localhost:8000/get

mới có dữ liệu.

Hình 40. Hình ảnh dữ liệu tại địa chỉ localhost:8000/get

• Sử dụng window.onload = function() để load lại nội dung của graph, các lệnh trong hàm đã được

giải thích trong code.



Truy cập vào trang canvasjs.com/javascript-charts/ để lựa chọn và xây dựng những đồ thị phù hợp với mục đích của bạn.

Hình ảnh trang HTML sau khi xây dựng

Hình 41. Hình ảnh giao diện HTML

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

77/155

Code ESP8266

ESP8266 sử dụng thư viện HTTPClient để kết nối tới Web Server và lấy dữ liệu nhiệt độ, đổ ẩm thông qua phương thức GET với query là temp và humd.

Chuẩn bị

• Cung cấp SSID và PASSWORD WiFi cho board mạch ESP8266 để kết nối vào mạng nội bộ với Web

Server.

• Cung cấp địa chỉ IP, port của Web Server.

• Thư viện hỗ trợ lấy dữ liệu của DHT11. Dựa theo chuẩn truyền nhận 1 wire và sự phổ biến của

dòng sensor DHTXX (DHT11, DHT22,…), có rất nhiều thư viện được xây dựng lên để việc lập trình

với DHT11 trở nên dễ dàng hơn. Trong bài này chúng ta sẽ cài đặt và sử dụng thư viện DHT

sensor library của Adafruit.

Hình 42. Hình ảnh thư viện DHT sensor library

Mã nguồn ESP8266

https://thuviensach.vn

78/155

#include <DHT.h> // Khai b á o s ử d ụ ng th ư vi ệ n DHT

#include <ESP8266WiFi.h> // Khai b á o s ử d ụ ng th ư vi ệ n ESP8266WiFi.h để thi ế t l ậ p ch ế độ HTTP client cho ESP8266

#define DHTPIN 4 // Ch â n d ữ li ệ u c ủ a DHT11 k ế t n ố i v ớ i GPIO4 c ủ a ESP8266

#define DHTTYPE DHT11 // Lo ạ i DHT đượ c s ử d ụ ng

DHT dht(DHTPIN, DHTTYPE);

WiFiClient client; // T ạ o 1 bi ế n client thu ộ c ki ể u WiFiClient const char* ssid = "YOUR-WIFI-SSID"; // T ê n m ạ ng Wifi đượ c ch ỉ đị nh s ẽ k ế t n ố i (SSID) const char* password = "YOUR-WIFI-PASS"; // Password c ủ a m ạ ng Wifi đượ c ch ỉ đị nh s ẽ k ế t n ố i const char* server = "Your-local-IP"; // Đị a ch ỉ IP c ủ a m á y khi truy c ậ p c ù ng m ạ ng WiFi const int port = 8000; // Port c ủ a server đã m ở

const int sendingInternval = 2 * 1000; // Bi ế n c ậ p nh ậ t d ữ li ệ u sau m ỗ i 2s void setup() {

Serial.begin(115200);

dht.begin(); // Kh ở i t ạ o DHT1 11 để truy ề n nh ậ n d ữ li ệ u Serial.println("Connecting");

// Thi ế t l ậ p ESP8266 l à Station v à k ế t n ố i đế n Wifi. in ra d ấ ù.` tr ê n terminal n ế u ch ư a đượ c k ế t n ố i WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

Serial.print(".");

delay(100);

}

Serial.println(" \r\nWiFi connected");

}

void loop() {

// Đọ c g í a tr ị nhi ệ t độ ( độ C), độ ẩ m. Xu ấ t ra th ô ng b á o l ỗ i v à tho á t ra n ế u d ữ li ệ u kh ô ng ph ả i l à s ố

float temp = dht.readTemperature();

float humi = dht.readHumidity();

if (isnan(temp) || isnan(humi)) {

Serial.println("Failed to read from DHT sensor!");

return;

}

if (client.connect(server, port)) { // Kh ở i t ạ o k ế t n ố i đế n server th ô ng qua IP v à PORT đã m ở

//---------------------------------------------------------------------------------------

String req_uri = "/update?temp=" + String(temp, 1) + "&humd=" + String(humi, 1); client.print("GET " + req_uri + " HTTP/1.1\n" + "Host: "+ server +" \n" + "Connection: close\n" + "Content-Length: 0\n" +" \n\n"); ①

//---------------------------------------------------------------------------------------

// temp, humi chuy ể n t ừ đị nh d ạ ng float sang đị nh d ạ ng string v à in ra m à n h ì nh serial // terminal tr ê n Arduino.

Serial.printf("Nhiet do %s - Do am %s\r\n", String(temp, 1).c_str(), String(humi, 1).c_str());

}

client.stop(); // Ng ắ t k ế t n ố i đế n server

delay(sendingInternval);

}

① ESP8266 sẽ gửi dữ liệu lên server sau khi kết nối thành công đến server thông qua lệnh

client.print(). Nội dung gửi :

• GET /update?temp=30.6&humd=60 HTTP/1.1 với :

◦ GET là phương thức gửi dữ liệu.

◦ /update?temp=30.6&humd=60 là nội dung cần gửi bao gồm cả pathname và dữ liệu.

◦ HTTP/1.1 khai báo sử dụng giao thức HTTP version 1.1 để có thể tạo 1 HTTP request

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

79/155

• Host: 192.168.1.7:8000 thông tin về địa chỉ IP và port của server.

• Connection, Content-Length

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

Có thể xem thông các thông tin của quá trình truyền nhận dữ liệu với lệnh: curl -v

http://192.168.1.7:8000/update?temp=28.0&humd=45.0. Thông tin hiển thị như bên dưới:

name@yourname:~$ curl -v http: //192.168.1.7:8000/update?temp=28.0&humd=45.0

[1] 9277

name@yourname:~$ * Trying 192.168.1.7...

* Connected to 192.168.1.7 (192.168.1.7) port 8000 (#0)

> GET /update?temp=28.0 HTTP/1.1 // > Th ô ng tin g ử i t ừ ESP8266

> Host: 192.168.1.7:8000

> User-Agent: curl/7.47.0

> Accept: */*

> // < Th ô ng tin g ử i t ừ server

< HTTP/1.1 200 OK

< Date: Wed, 23 Aug 2017 17:22:49 GMT

< Connection: keep-alive

< Content-Length: 0

<

* Connection #0 to host 192.168.1.7 left intact

Kết quả hiển thị trên Arduino IDE và màn hình Log của máy tính:

Hình 43. Hình ảnh trên Arduino và terminal sau khi kết nối

https://thuviensach.vn

80/155

Ứng dụng mở rộng

Dùng ESP8266 như 1 Web Server

Xây dựng 1 dự án giám sát và điều khiển nhiệt độ, độ ẩm hiển thị trên web với giao diện điều khiển :

• Hiển thị giá trị nhiệt độ, độ ẩm.

• Hiển thị chart nhiệt độ, độ ẩm theo thời gian.

• Có 2 chế độ Auto và Manual.

◦ Với chế độ Auto, nhiệt độ > 35ºC sẽ tự động bật quạt, độ ẩm > 50% sẽ bật máy phun sương.

◦ Với chế độ manual có thể điều khiển quạt và máy phun sương bằng các nút nhấn ở

ON/OFF

• Có tùy chọn hiển thị lịch sử nhiệt độ, độ ẩm theo thời gian từ ngày aa/bb/cccc đến ngày

xx/yy/zzzz

Hình ảnh thiết kế giao diện như bên dưới:

Hình 44. Giao diện điều khiển trên trang HTML

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

81/155

Tổng kết

Sau khi hoàn thành dự án, chúng ta đã có cái nhìn tổng quan về trình tự các bước để xây dựng một

dự án hoàn chỉnh trong việc thu thập dữ liệu của cảm biến cũng như xây dựng server để quản lí các máy khách. Từ đó là bước đệm để giúp bạn phát triển thêm nhiều các dự án thu thập và xử lí dữ liệu trong tương lai.

https://thuviensach.vn

82/155

Các chế độ cấu hình WiFi

Thông thường, khi bắt đầu kết nối wifi cho ESP8266, ta phải cấu hình cho thiết bị các thông số của Access Point cũng như SSID và password nếu mạng wifi được thiết lập các bảo mật như

WEP/WPA/WPA2. Tuy nhiên, các ứng dụng nhúng sử dụng Wi-fi thường ít chú trọng đến giao diện

người dùng (user interface), không có bàn phím hay touchscreen,.. để giao tiếp. Vì thế, mỗi khi muốn kết nối thiết bị ESP với một Access Point nào đó, bạn cần phải có một máy tính đã cài đặt sẵn phần mềm biên dịch, tiếp theo là viết code cấu hình lại thông số wifi cho thiết bị, sau đó nạp code cho thiết bị thông qua một cable USB.

Điều này làm cho việc kết nối wifi trở nên khá bất tiện và phức tạp. Do vậy ESP8266 cung cấp các

phương pháp thay thế khác giúp đơn giản hóa việc kết nối trạm ESP (chế độ Station) với một điểm

truy cập. Đó là kết nối bằng SmartConfig, WPS hay Wifi Manager.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

83/155

Smartconfig

Kiến thức

SmartConfig là một giao thức được tạo ra nhằm cấu hình cho các thiết bị kết nối với mạng WiFi một cách dễ dàng nhất bằng smart phone. Nói một cách đơn giản, để kết nối WiFi cho thiết bị ESP8266, ta chỉ cần cung cấp thông tin mạng wifi (bao gồm SSID và password) cho ESP thông qua 1 ứng dụng trên smart phone.

Hình 45. SmartConfig với ESP8266

Chúng ta nên biết rằng, khi 1 điện thoại thông minh đã kết nối vào mạng WiFi có mật khẩu, thì toàn bộ

dữ liệu trao đổi giữa Điện thoại và đầu mối khác trong mạng sẽ được mã hóa. Nghĩa là các thiết bị

chưa được kết nối mạng và không có mật khẩu thì không thể giải mã được dữ liệu. Vậy làm thế nào để

Ứng dụng trên điện thoại gởi thông tin kết nối này đến 1 thiết bị khác chưa hề kết nối mạng. Để làm được điều này, thì nhờ vào 2 đặc điểm sau:

• ESP8266 có khả năng lắng nghe tất cả các gói tin không dây WiFi xung quanh nó, bao gồm cả

các gói tin đã được mã hóa.

• Các gói tin gởi trong mạng WiFi được mã hóa và không thể đọc được nội dung, tuy nhiên độ dài

gói tin là một hằng số. Ví dụ, gói tin A chưa mã hóa có chiều dài là x, khi mã hóa gói tin A thành gói tin B, thì gói tin B sẽ có chiều dài là x + n, thì n là hằng số.

https://thuviensach.vn

84/155

Cách thức để giao thức ESPTOUCH thực hiện việc gởi thông tin SSID và mật khầu cho thiết bị như

sau:

• ESP8266 sẽ vào chế độ lắng nghe, lần lượt từng kênh.

• Điện thoại phải kết nối vào mạng WiFi được mã hóa.

• Ứng dụng trên điện thoại sẽ tiến hành gởi các gói tin với nội dung bất kỳ, nhưng có độ dài n

theo từng ký tự của SSID và mật khẩu. Ví dụ, ssid của mạng là mynetwork thì sẽ có ký tự m, với

ký tự ascii = 109, Ứng dụng sẽ gởi gói tin có độ dài 109 với nội dung bất kỳ, và lặp lại cho đến hết ký tự k, cũng như mật khẩu, và các ký tự khác như CRC.

• Có thể giao thức ESPTOUCH sẽ mã hóa cả các thông số gởi đi, nhưng vẫn giữ nguyên tắc như

trên.

• ESP8266 sẽ phát hiện ra các gói tin với độ dài thay đổi này và ghép nối lại thành SSID và

password để kêt nối vào mạng.

• Khi ESP8266 kết nối thành công đến mạng, ESP8266 sẽ kết nối đến IP của Điện thoại, được cung

cấp thông qua ESPTOUCH, và gởi thông tin kết nối thành công đến ứng dụng trên điện thoại.

Hình 46. Gói tin UDP

Lưu ý:

• Khoảng cách giữa thiết bị và router càng xa thì thời gian kết nối sẽ càng lâu.

• Nếu thiết bị không thể kết nối với router trong khoảng thời gian quy định thì ứng dụng sẽ trả về

thông báo cấu hình thất bại. Người dùng có thể cài đặt thời gian timeout này thông qua lệnh

esptouch_set_timeout(uint8 time_s)

• Trong quá trình cấu hình kết nối thiết bị bằng SmartConfig, thiết bị phải được cài đặt ở chế độ

Station.

• Người dùng có thể cấu hình cho nhiều thiết bị kết nối chung vào một router cùng lúc.

• ESP Touch hiện nay hỗ trợ đối với Access Point chuẩn 802.11n 2.4Ghz

Thực hiện SmartConfig với ESP8266

Trong ví dụ dưới đây, chúng ta sẽ tiến hành kết nối wifi cho board ESP8266 bằng SmartConfig. Sử

dụng ứng dụng ESP8266 SmartConfig (Android). Bạn có thể dễ dàng tìm thấy ứng dụng này cũng như

các ứng dụng tương tự trên Play Store (Android) hay iTunes (iOS) để thực hiện việc kết nối bằng

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

85/155

SmartConfig này.

Trước tiên, ta sẽ nạp chương trình cho ESP8266. Điểm mấu chốt trong chương trình này chính là hàm WiFi.beginSmartConfig() được cung cấp trong thư viện ESP8266WiFi. Hàm này cho phép thiết bị khởi

động chế độ SmartConfig, thu thập các thông tin từ các gói tin và giải mã chúng để có thể kết nối vào mạng Wifi.

Sau khi nạp xong chương trình, ta nhấn giữ button (GPIO0) trong 3s để thiết bị đi vào chế độ

smartconfig. (Lúc này bạn sẽ thấy led trên board nhấp nháy nhanh hơn). Dùng smart phone của bạn

truy cập vào wifi muốn kết nối, sau đó mở ứng dụng smartconfig và nhập các thông tin SSID và

PASSWORD (nếu có) của wifi. Nhấn CONFIRM để xác nhận.

 https://www.youtube.com/watch?v=-RqMKvMLPi0 (YouTube video) Video Demo

Code

#include <Arduino.h>

#include <ESP8266WiFi.h>

#include <Ticker.h>

#include <time.h>

#define PIN_LED 16

#define PIN_BUTTON 0

#define LED_ON() digitalWrite(PIN_LED, HIGH)

#define LED_OFF() digitalWrite(PIN_LED, LOW)

#define LED_TOGGLE() digitalWrite(PIN_LED, digitalRead(PIN_LED) ^ 0x01)

Ticker ticker;

/* H à m ki ể m tra tr ạ ng th á i c ủ a button*/

bool longPress()

{

static int lastPress = 0;

if (millis() - lastPress > 3000 && digitalRead(PIN_BUTTON) == 0) { // N ế u button đượ c nh ấ n v à gi ữ trong 3s th ì return true;

} else if (digitalRead(PIN_BUTTON) == 1) { // N ế u button kh ô ng đượ c nh ấ n v à gi ữ đủ 3s th ì lastPress = millis(); // g á n bi ế n lastPress b ằ ng th ờ i đ i ể m khi g ọ i h à m

}

return false;

}

void tick()

{

int state = digitalRead(PIN_LED); // L ấ y tr ạ ng th á i hi ệ n t ạ i c ủ a LED (GPIO16) digitalWrite(PIN_LED, !state); // Đả o tr ạ ng th á i LED.

}

bool in_smartconfig = false; // Bi ế n tr ạ ng th á i ki ể m tra thi ế t b ị c ó đ ang trong ch ế độ smartconfig hay kh ô ng.

/* V à o ch ế độ Smartconfig*/

void enter_smartconfig()

{

if (in_smartconfig == false) { // Ki ể m tra tra bi ế n tr ạ ng th á i, n ế u kh ô ng ở ch ế độ smartconfig th ì in_smartconfig = true; // G á n bi ế n tr ạ ng th á i b ằ ng "true", ngh ĩ a l à đ ang trong smartconfig ticker.attach(0.1, tick); // Nh ấ p nh á y led chu k ì 0.1s.

https://thuviensach.vn

86/155

WiFi.mode(WIFI_STA); // Thi ế t l ậ p k ế t n ố i cho thi ế t b ị ở ch ế độ Station mode WiFi.beginSmartConfig(); // B ắ t đầ u ch ế độ smartconfig

Serial.println("Enter smartconfig"); // In th ô ng b á o "Enter smartconfig" ra m à n h ì nh

}

}

/* Tho á t ch ế độ smartconfig*/

void exit_smart()

{

ticker.detach(); // Ng ừ ng nh á y led

LED_ON(); // B ậ t LED

in_smartconfig = false; // G á n bi ế n tr ạ ng th á i tr ở v ề ban đầ u.

Serial.println("Connected, Exit smartconfig"); // In th ô ng b á o ra m à n h ì nh.

}

/* C à i đặ t c á c th ô ng s ố ban đầ u*/

void setup() {

Serial.begin(115200); // T ố c độ baud = 115200

Serial.setDebugOutput(true); // hi ể n th ị c á c th ô ng tin debug h ệ th ố ng l ê n m à n h ì nh qua serial pinMode(PIN_LED, OUTPUT); // C ấ u h ì nh GPIO cho c á c ch â n LED v à button pinMode(PIN_BUTTON, INPUT); // Ch ớ p t ắ t led chu k ì 1s

Serial.println("Setup done"); // In th ô ng b á o đã c à i đặ t xong

}

/* Ch ươ ng tr ì nh ch í nh*/

void loop() {

if (longPress()) { // G ọ i h à m longPress ki ể m tra tr ạ ng th á i button enter_smartconfig(); // N ế u button đượ c nh ấ n gi ữ trong 3s th ì v à o tr ạ ng th á i smartconfig

}

if (WiFi.status() == WL_CONNECTED && in_smartconfig && WiFi.smartConfigDone()) { //Ki ể m tra tr ạ ng th á i k ế t n ố i wifi,

// c á c th ô ng s ố c ấ u h ì nh c ũ ng nh ư tr ạ ng th á i smartconfig exit_smart(); // khi thi ế t b ị đã h ế t n ố i wifi th à nh c ô ng, tho á t ch ế độ smartconfig

}

if (WiFi.status() == WL_CONNECTED) {

//Ch ươ ng tr ì nh c ủ a b ạ n khi thi ế t b ị đã đượ c k ế t n ố i wifi

}

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

87/155

WPS

WPS là gì?

Nếu đã từng cấu hình cho một router wifi, sẽ gặp qua các thuật ngữ WPS trong các menu cấu hình

của router. Hoặc từng nhìn thấy một nút nhấn trên các router với chữ viết bên cạnh WPS. Vậy WPS là gì ? Quá trình thực hiện kết nối như thế nào ? Cũng như thực hiện WPS với ESP8266, là những những nội dung sẽ được nói đến ở phần này.

WPS là từ viết tắc của Wifi Protected Setup, một phương thức giúp việc kết nối với mạng không dây giữa router và thiết bị kết nối không dây một cách nhanh chóng và dễ dàng, thay vì làm một cách thủ

công: tìm mạng wifi cần kết nối và nhập mật khẩu để vào mạng wifi. WPS chỉ hoạt động khi cả hai thiết bị là router và thiết bị cần kết nối đến router có hổ trợ chuẩn bảo mật cá nhân WPA/WPA2.

WPS có ba chế độ hoạt động : chế độ kết nối với mã PIN, chế độ kết nối bằng nút nhấn, và chế độ kết nối NFC - Near Field Communication (chưa phổ biến). Một trong những chế độ phổ biến và sẽ thực

hiện trong phần này là chế độ kết nối bằng nút nhấn.

Ở chế độ kết nối bằng nút nhấn, điều trước tiên cần thực hiện :

• Nhấn nút WPS trên router, để giúp router vào chế độ bảo mật đặc biệt, ở chế độ này router sẽ

cho phép các yêu cầu kết nối đến router từ các thiết bị WPS (các thiết bị có hổ trợ WPS).

• Tiếp theo là nhấn nút nhấn ở thiết bị WPS. Nút nhấn này giúp thiết bị WPS kết nối đến router,

việc kết nối này có thể thất bại nếu quá thời gian. Thời gian này được nhà sản xuất các thiết bị

hổ trợ chế độ này quy đinh, khoảng từ 1 phút đến 5 phút.

Hình 47. Nút nhấn WPS trên router

https://thuviensach.vn

88/155

Thực hiện WPS với ESP8266

ESP8266 hổ trợ hàm WiFi.beginWPSConfig() trong thư viện ESP8266WiFi. Với hàm này giúp ESP8266

vào chế độ cấu hình với WPS và kết nối đến mạng wifi của router. Ví dụ này ESP8266 sẽ được đưa sẳn vào chế độ WPS, mà không cần thêm nút nhấn nào.

- WPS chỉ có thể thực hiện khi ESP8266 ở chế độ STA (Station)

- Router phải ở trong chế độ WPS trước

Code

#include <ESP8266WiFi.h>

void setup()

{

// C à i đặ t c á c th ô ng s ố ban đầ u

Serial.begin(115200);

WiFi.mode(WIFI_STA);

// K ế t n ố i v ớ i AP c ũ đã v à o tr ướ c đó , SSID v à password đượ c l ư u trong b ộ nh ớ flash c ủ a thi ế t b ị

WiFi.begin("", "");

delay(4000);

// Ki ể m tra xem wifi đã đượ c k ế t n ố i ch ư a, n ế u ch ư a, b ắ t đầ u k ế t n ố i b ằ ng WPS

// L ư u ý , c ầ n ph ả i đả m b ả o r ằ ng Router c ủ a b ạ n đ ang ở trong tr ạ ng th á i WPS.

while (WiFi.status() != WL_CONNECTED)

{

Serial.println(" \nAttempting connection ...");

WiFi.beginWPSConfig();

delay(6000);

}

// Khi k ế t n ố i th à nh c ô ng, in th ô ng b á o ra m à n h ì nh c ù ng v ớ i c á c th ô ng s ố c ủ a Wifi v ừ a k ế t n ố i.

Serial.println(" \nConnection already established.");

Serial.println(WiFi.localIP());

Serial.println(WiFi.SSID());

Serial.println(WiFi.macAddress());

}

void loop()

{

// ch ươ ng tr ì nh ch í nh

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

89/155

Wifi Manager

WifiManager là một thư viện cấu hình ESP8266 kết nối vào mạng WiFi cục bộ sử dụng giao diện Web.

Bằng cách khởi động 1 mạng WiFi riêng với Captive Portal, ESP8266 sẽ cho phép các thiết bị khác như

máy tính, điện thoại thông minh kết nối vào, đồng thời chuyển hướng mọi kết nối đến giao diện Web do ESP8266 tạo nên. Trên giao diện này, sẽ cung cấp các trường để người dùng có thể dễ dàng quét

mạng xung quanh, chọn mạng WiFi, nhập mật khẩu, lưu cấu hình.

Hoạt động cơ bản WifiManager

• Khi ESP8266 khởi động, ESP8266 sẽ vào chế độ STATION và sẽ tự động kết nối đến một Access

Point với các thông tin kết nối đã được lưu vào ESP8266 ở lần kết nối thành công trước đó.

• Nếu như kết nối không thành công (có thể là Access Point lần trước không còn nữa, hay sai mật

khẩu, hoặc chưa có thông tin của bất cứ Access Point nào trong ESP8266 ), lúc này ESP8266 sẽ

vào chế độ AP với một DNS trỏ về chính nó (có thể thiết lập DNS trỏ về địa chỉ khác) và khởi động Web Server (với địa chỉ mặc định là 192.168.4.1)

• Sử dụng các thiết bị có hổ trợ wifi, và có trình duyệt web (điện thoại thông minh, laptop, máy

tính bảng…) để kết nối đến AP của ESP8266 vừa mới tạo ra. Có thể thấy một giao diện (với tên AP

của ESP8266 là mặc định và không cài đặt mật khẩu cho ESP8266 AP) tương tự như sau :

https://thuviensach.vn

90/155

• Sau khi vào được giao diện option của ESP8266 AP ở địa chỉ 192.168.4.1, chọn mục cấu hình cho

wifi cho ESP8266 (như ví dụ trên là Configure WiFi hoặc Configure WiFi (No Scan)), có thể sẽ thấy giao diện tiếp theo tương tự như sau :

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

91/155

• Chọn mạng wifi cần kết nối và nhập mật khẩu để vào wifi.

• Nếu ESP8266 kết nối thành công, ta sẽ không thấy tên của ESP8266 AP nữa. Nếu chưa thành

công thì chỉ cần kết nối lại ESP8266 AP và cấu hình lại.

Chuẩn bị

• Cài đặt thư viện: github.com/tzapu/WiFiManager, xem thêm Cài đặt thư viện Arduino

Code

https://thuviensach.vn

92/155

#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino

//c á c th ư vi ệ n c ầ n thi ế t

#include <DNSServer.h>

#include <ESP8266WebServer.h>

#include "WiFiManager.h" //https://github.com/tzapu/WiFiManager

void configModeCallback (WiFiManager *myWiFiManager)

{

Serial.println("Entered config mode");

Serial.println(WiFi.softAPIP());

Serial.println(myWiFiManager->getConfigPortalSSID());

}

// C à i đặ t th ô ng s ố ban đầ u

void setup()

{

Serial.begin(115200);

//Khai b á o wifiManager thu ộ c class WiFiManager, đượ c quy đị nh trong file WiFiManager.h WiFiManager wifiManager;

//c ó th ể reset c á c c à i đặ t c ũ b ằ ng c á ch g ọ i h à m:

//wifiManager.resetSettings();

//C à i đặ t callback, khi k ế t n ố i v ớ i wifi c ũ th ấ t b ạ i, thi ế t b ị s ẽ g ọ i h à m callback

//v à kh ở i độ ng ch ế độ AP v ớ i SSID đượ c c à i t ự độ ng l à "ESP+chipID"

wifiManager.setAPCallback(configModeCallback);

if (!wifiManager.autoConnect())

{

Serial.println("failed to connect and hit timeout");

//N ế u k ế t n ố i th ấ t b ạ i, th ử k ế t n ố i l ạ i b ằ ng c á ch reset thi ế t b ị

ESP.reset();

delay(1000);

}

//N ế u k ế t n ố i wifi th à nh c ô ng, in th ô ng b á o ra m à n h ì nh Serial.println("connected...yeey :)");

}

void loop()

{

// Ch ươ ng tr ì nh ch í nh

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

Mở rộng

Ngoài các chế độ cơ bản, thì thư viện WiFiManager còn nhiều tính năng hữu ích khác như

startConfigPortal để khởi động cấu hình khi cần (ví dụ nhấn nút để cấu hình), bổ sung các trường tùy chọn trên giao diện Web, tùy chọn lại giao diện …

Các thông tin API và ví dụ bạn có thể dễ dàng tìm thấy tại github.com/tzapu/WiFiManager

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

93/155

Tổng kết

Để triển khai một ứng dụng IoT thực tế thì đòi hỏi rất nhiều vấn đề, một trong số những điều quan trọng là dễ dùng, dễ cấu hình cho người sử dụng và phải bảo mật trong quá trình cung cấp thông tin cho thiết bị. Tùy thuộc vào nhu cầu phát triển sản phẩm và tính năng của sản phẩm mà bạn có thể

lựa chọn cho mình phương pháp cấu hình phù hợp. Ví dụ, nếu thiết bị có nút nhấn và có phần mềm

trên điện thoại, thì SmartConfig và WPS là một sự lựa chọn. Nếu là 1 bóng đèn trống trơn không có gì cả, thì WiFiManager lại hữu hiệu.

https://thuviensach.vn

94/155

MQTT

MQTT (Message Queuing Telemetry Transport) là một giao thức gởi dạng publish/subscribe sử dụng

cho các thiết bị Internet of Things với băng thông thấp, độ tin cậy cao và khả năng được sử dụng

trong mạng lưới không ổn định.

Bởi vì giao thức này sử dụng băng thông thấp trong môi trường có độ trễ cao nên nó là một giao thức lý tưởng cho các ứng dụng M2M.

MQTT cũng là giao thức sử dụng trong Facebook Messager.

Và MQTT là gì? Để có một cái nhìn toàn diện hoặc định nghĩa chi tiết, chỉ cần google "what is mqtt",

"mqtt slides" … Ở đây chúng ta chỉ nói ngắn gọn thôi, đủ để hiểu giao thức MQTT, bao gồm các định nghĩa "subscribe", "publish", "qos", "retain", "last will and testament (lwt)"

Publish, subscribe

Trong một hệ thống sử dụng giao thức MQTT, nhiều node trạm (gọi là mqtt client - gọi tắt là client) kết nối tới một MQTT Server (gọi là Broker). Mỗi client sẽ đăng ký một vài kênh (topic), ví dụ như

"/client1/channel1", "/client1/channel2". Quá trình đăng ký này gọi là "subscribe" , giống như chúng ta đăng ký nhận tin trên một kênh Youtube vậy. Mỗi Client sẽ nhận được dữ liệu khi bất kỳ trạm nào

khác gởi dữ liệu vào kênh đã đăng ký. Khi một Client gởi dữ liệu tới kênh đó, gọi là "publish" .

QoS

Ở đây có 3 tuỳ chọn QoS (Qualities of service) khi "publish" và "subscribe":

• QoS0 Broker/Client sẽ gởi dữ liệu đúng 1 lần, quá trình gởi được xác nhận bởi chỉ giao thức TCP/IP, giống kiểu đem con bỏ chợ.

• QoS1 Broker/Client sẽ gởi dữ liệu với ít nhất 1 lần xác nhận từ đầu kia, nghĩa là có thể có nhiều hơn 1 lần xác nhận đã nhận được dữ liệu.

• QoS2 Broker/Client đảm bảm khi gởi dữ liệu thì phía nhận chỉ nhận được đúng 1 lần, quá trình này phải trải qua 4 bước bắt tay.

Xem thêm QoS: code.google.com/p/mqtt4erl/wiki/QualityOfServiceUseCases

Một gói tin có thể được gởi ở bất kỳ QoS nào, và các Client cũng có thể subscribe với bất kỳ yêu cầu

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

95/155

QoS nào. Có nghĩa là Client sẽ lựa chọn QoS tối đa mà nó có để nhận tin. Ví dụ, nếu 1 gói dữ liệu được publish với QoS2, và Client subscribe với QoS0, thì gói dữ liệu được nhận về Client này sẽ được

broker gởi với QoS0, và 1 Client khác đăng ký cùng kênh này với QoS 2, thì nó sẽ được Broker gởi dữ

liệu với QoS2.

Một ví dụ khác, nếu 1 Client subscribe với QoS2 và gói dữ liệu gởi vào kênh đó publish với QoS0 thì Client đó sẽ được Broker gởi dữ liệu với QoS0. QoS càng cao thì càng đáng tin cậy, đồng thời độ trễ

và băng thông đòi hỏi cũng cao hơn.

Retain

Nếu RETAIN được set bằng 1, khi gói tin được publish từ Client, Broker PHẢI lưu trữ lại gói tin với QoS, và nó sẽ được gởi đến bất kỳ Client nào subscribe cùng kênh trong tương lai. Khi một Client kết nối tới Broker và subscribe, nó sẽ nhận được gói tin cuối cùng có RETAIN = 1 với bất kỳ topic nào mà nó đăng ký trùng. Tuy nhiên, nếu Broker nhận được gói tin mà có QoS = 0 và RETAIN = 1, nó sẽ huỷ tất cả

các gói tin có RETAIN = 1 trước đó. Và phải lưu gói tin này lại, nhưng hoàn toàn có thể huỷ bất kỳ lúc nào.

Khi publish một gói dữ liệu đến Client, Broker phải set RETAIN = 1 nếu gói được gởi như là kết quả của việc subscribe mới của Client (giống như tin nhắn ACK báo subscribe thành công). RETAIN phải bằng 0 nếu không quan tâm tới kết quả của việc subscribe.

LWT

Gói tin LWT (last will and testament) không thực sự biết được Client có trực tuyến hay không, cái này do gói tin KeepAlive đảm nhận. Tuy nhiên gói tin LWT như là thông tin điều gì sẽ xảy đến sau khi thiết bị ngoại tuyến.

Một ví dụ

Tôi có 1 cảm biến, nó gởi những dữ liệu quan trọng và rất không thường xuyên. Nó có đăng ký trước với Broker một tin nhắn lwt ở topic /node/gone-offline với tin nhắn id của nó. Và tôi cũng đăng ký theo dõi topic /node/gone-offline, sẽ gởi SMS tới điện thoại thôi mỗi khi nhận được tin nhắn nào ở

kênh mà tôi theo dõi. Trong quá trình hoạt động, cảm biến luôn giữ kết nối với Broker bởi việc luôn gởi gói tin keepAlive. Nhưng nếu vì lý do gì đó, cảm biến này chuyển sang ngoại tuyến, kết nối tới Broker timeout do Broker không còn nhận được gói keepAlive. Lúc này, do cảm biến của tôi đã đăng ký LWT, do vậy broker sẽ đóng kết nối của Cảm biến, đồng thời sẽ publish một gói tin là Id của cảm biến vào kênh /node/gone-offline, dĩ nhiên là tôi cũng sẽ nhận được tin nhắn báo cái cảm biến yêu quý của mình đã ngoại tuyến.

Ngắn gọn

Ngoài việc đóng kết nối của Client đã ngoại tuyến, gói tin LWT có thể được định nghĩa trước và được gởi bởi Broker tới kênh nào đó khi thiết bị đăng ký LWT ngoại tuyến.

https://thuviensach.vn

96/155

MQTT Client

Như chúng ta đã tìm hiểu ở phần trước, 2 thành phần publisher và subscriber là đặc trưng tạo nên

giao thức MQTT. Các MQTT Client không kết nối trực tiếp với nhau, mọi gói dữ liệu được gửi đi đều thông qua MQTT Broker. Để có thể triển khai các ứng dụng của MQTT Client, chúng ta cần MQTT

Broker (sẽ được trình bày trong phần sau). Ở phần này chúng ta sẽ làm quen với giao thức MQTT

bằng các ví dụ sử dụng MQTT Client thông dụng và các dịch vụ MQTT Broker miễn phí và phổ biến, 2

trong số chúng là test.mostquitto.org và cloudmqtt.com

MQTT Lens

Thông tin

MQTT Lens là một tiện ích mở rộng của Chrome (Chrome Extension), nó sử dụng trình duyệt Chrome

để kết nối đến MQTT Broker cũng như test các tính năng publish/subcribe của giao thức MQTT. Đây

là một công cụ rất hữu ích để kiểm tra kết nối đến MQTT Broker và kiểm tra việc gửi và nhận gói tin.

Một số thông tin của MQTT Lens được trình bày ở bảng dưới.

Bảng 2. Short Profile

Type

Chrome App

License

MIT

Operating Systems

Windows, Linux & MacOSX

Website

"https

Kết nối

Chúng ta sẽ sử dụng công cụ này với dịch vụ MQTT Broker tại iot.eclipse.org được trình bày như các bước bên dưới:

• Bước 1: Cài đặt trình duyệt Chrome, thực hiện đăng nhập tài khoản của bạn vào chrome, truy

cập vào địa chỉ chrome.google.com/webstore/category/extensions và gõ mqttlens vào mục tìm kiếm tiện ích như hình bên dưới.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

97/155

Hình 48. Hình ảnh tìm kiếm tiện ích mqttlens trên chrome store

• Bước 2: Thêm và khởi chạy MQTT lens

Hình 49. Hình ảnh các bước thêm và khởi chạy tiện ích MQTT lens

• Bước 3 : Tạo 1 MQTT Client kết nối đến MQTT Broker eclipse như các bước bên dưới.

https://thuviensach.vn

98/155

Hình 50. Hình ảnh tạo 1 MQTT client

Giải thích

Chúng ta sẽ tạo 1 connection có tên eclipse MQTT với host name của MQTT Broker là iot.eclipse.org, Broker này sẽ giúp trao đổi dữ liệu của các Client với nhau và lắng nghe các Client ở port 1883 (port sử dụng giao thức MQTT và không mã hóa dữ liệu, các port khác tham khảo tại test.mosquitto.org) Ở

connection này sẽ đăng kí nhận gói tin tại topic Home/garden/sensor/# (kí tự # cho phép subcribe

các topic Home/garden/sensor/1, Home/garden/sensor/2 vv…). Tiếp theo chúng ta sẽ pulish 1 gói dữ

liệu với nội dung "Temp in garden: 27degree Celcius " tại topic Home/garden/sensor/1.

Kết quả: Tại mục subrcriptions, chúng ta sẽ nhận được gói dữ liệu đã publish do đã subcribe topic Home/garden/sensor/# như hình bên dưới.

Hình 51. Hình ảnh dữ liệu nhận được sau khi publish gói tin

Mở rộng

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

99/155

Tạo nhiều connection để subcribe và publish các gói tin với MQTT Broker iot.eclipse.org đồng thời test các gói tin với QoS và LWT

MQTT.js

MQTT.js là một thư viện MQTT client, được viết bằng ngôn ngữ JavaScript trên nền tảng Node.js và hỗ

trợ MQTT Over Websocket (MOW).

MQTT.js là dự án mã nguồn mở (open source), bạn có thể tải MQTT.js bản cập nhật mới nhất tại

github.com/mqttjs/MQTT.js.git

Cài đặt

Trước tiên ta cần kiểm tra hệ điều hành đã hỗ trợ Node.js trước khi cài đặt MQTT.js. Nếu chưa thì có thể tham khảo cách cài đặt tại nodejs.org/en/

Khởi tạo một dự án Node.js. Để dễ quản lý, có thể tạo một thư mục riêng, ví dụ mqtt-client và một file javascrip trong đó, ví dụ như client-a.js. Đi đến thư mục này và mở terminal (linux OS) hoặc Command Prompt (trên Windowns OS) và dùng lệnh:

npm init

Khi chạy lệnh này, bạn cũng cần phải khai báo thêm một số thông tin cho dự án như tên, phiên bản, keywords, tác giả,… Sau khi tạo xong, trong thư mục vừa tạo sẽ xuất hiện một file là package.json với nội dung là các phần đã khai báo. File này cũng chứa thuộc tính dùng để lưu trữ các package chúng ta đã cài đặt.

Tiếp theo chúng ta sẽ cài MQTT.js, sử dụng lệnh:

npm install mqtt --save

Sau khi cài đặt xong, bạn có thể sử dụng module mqtt để thực hiện việc kết nối MQTT Client với

Broker, publish message hay subscribe topic. Tất nhiên, toàn bộ các file liên quan đến thư viện sẽ

nằm trong thư mục node_modules, trong thư mục dự án.

Để hiểu rõ hơn cách hoạt động của MQTT.js, chúng ta sẽ tạo ra thêm 1 số file mã nguồn Javascript

(file .js) là client-a.js và client-b.js thực hiện subcribe và puslish các gói tin.

Nội dung thực hiện

2 Client này sẽ kết nối vào cùng 1 MQTT Broker. Client A sẽ subscribe kênh /client-a/sub, nếu nhận bất kỳ dữ liệu nào được publish vào kênh này, client A sẽ public dữ liệu Hello from client A vào kênh

/client-b/sub và đóng kết nối, kết thúc. Client B sẽ subscribe kênh /client-b/sub, nếu nhận bất kỳ dữ

liệu nào được public vào kênh này, client B sẽ đóng kết nối và kết thúc. Ngay khi kết nối vào Broker, client B sẽ public 1 gói tin Hello from client B vào kênh /client-a/sub

https://thuviensach.vn

100/155

Mã nguồn của client A

client-a.js

// t ạ o bi ế n mqtt s ử d ụ ng c á c ch ứ c n ă ng c ủ a module mqtt var mqtt = require('mqtt')

// t ạ o bi ế n client s ử d ụ ng thu ộ c t í nh connect để k ế t n ố i đế n broket MQTT v ớ i hostname mqtt://iot.eclipse.org var client = mqtt.connect('mqtt://iot.eclipse.org')

// function c ó ch ứ c n ă ng subscribe 1 topic n ế u đã k ế t n ố i th à nh c ô ng đế n broker client.on('connect', function() {

console.log('Client A connected')

// client subcribe topic /client-a/sub

client.subscribe('/client-a/sub')

})

// function c ó ch ứ c n ă ng g ử i 1 g ó i tin đễ n đế n topic đã đă ng k í client.on('message', function(topic, message) {

// in ra m à n h ì nh console 1 message ở đị nh d ạ ng string console.log(message.toString())

// publish g ó i tin 'Hello from client A' đế n topic /client-b/sub

client.publish('/client-b/sub', 'Hello from client A')

// đó ng k ế t n ố i c ủ a client

client.end()

})

console.log('Client A started')

Mã nguồn của client B

client-b.js

// t ạ o bi ế n mqtt s ử d ụ ng c á c ch ứ c n ă ng c ủ a module mqtt var mqtt = require('mqtt')

// t ạ o bi ế n client s ử d ụ ng thu ộ c t í nh connect để k ế t n ố i đế n broket MQTT v ớ i hostname mqtt://iot.eclipse.org var client = mqtt.connect('mqtt://iot.eclipse.org')

// function c ó ch ứ c n ă ng subscribe 1 topic n ế u đã k ế t n ố i th à nh c ô ng đế n broker client.on('connect', function() {

console.log('Client B connected')

// client subcribe topic /client-b/sub

client.subscribe('/client-b/sub')

// publish g ó i tin 'Hello from client B' đế n topic /client-a/sub

client.publish('/client-a/sub', 'Hello from client B')

})

client.on('message', function(topic, message) {

// in ra m à n h ì nh console 1 message ở đị nh d ạ ng string console.log(message.toString())

// đó ng k ế t n ố i c ủ a client

client.end()

})

console.log('Client B started')

Kết quả hiển thị như hình bên dưới:

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

101/155

Hình 52. Hình ảnh kết quả khi khởi chạy các MQTT client

Ngoài ra, MQTT.js còn cung cấp thêm các lệnh để có thể tương tác với Broker thông qua terminal. Để

làm được điều này, chúng ta cài đặt MQTT.js như một module toàn cục bằng cách sử dụng lệnh:

npm install mqtt -g.

Bạn có thể kiểm tra bằng cách mở 2 màn hình terminal, ở màn hình 1 (tạm gọi là subscriber) sẽ

subscribe vào topic tên là "topicA" bằng lệnh:

mqtt sub -t 'topicA' -h 'test.mosquitto.org' -v

Ở terminal thứ 2 (tạm gọi là publisher) thực hiện publish một tin nhắn với nội dung "hello subscriber"

tới "topicA":

mqtt pub -t 'topicA' -h 'test.mosquitto.org' -m 'hello subscriber'

Các options:

• -t : MQTT topic, nơi sẽ thực hiện pushlish 1 message.

• -h : Xác định máy chủ sẽ kết nối đến.

• -m : Gửi 1 message dùng command line.

• -v : verbose, option cho phép ghi lại nhật kí hoạt động của các tập tin trong file cấu hình.

https://thuviensach.vn

102/155

Hình 53. Hình ảnh message được publish dùng command line



Để xem thêm các API khác trong MQTT.js, bạn có thể sử dụng lệnh: mqtt help

[command].

ESP8266 MQTT Client

Thực tế có khá nhiều thư viện MQTT cho ESP8266 trên Arudino, ở đây chúng ta chỉ đề cập đến 2 thư

viện phổ biến là PubSubClient và ESP8266MQTTClient

PubSubClient

Trong phần này chúng ta sẽ thực hiện kết nối board ESP8266 WiFi Uno đến 1 broker sử dụng thư viện PubSubClient.

• Bước 1 : Download thư viện PubSubClient tại đường dẫn github.com/knolleary/pubsubclient và add vào chương trình Arduino. Ngoài ra có thể import thư viện này trong Arduino bằng cách tìm

kiếm thư viện với từ khóa PubSubClient, chọn thư viện PubSubClient của tác giả Nick O’Leary và

nhấn install.

• Bước 2 : Viết và nạp chương trình cho ESP8266. Mã nguồn được trình bày ở phía dưới

#include <ESP8266WiFi.h>

#include <PubSubClient.h>

const char* ssid = "........";

const char* password = ".........";

const char* mqtt_server = "broker.mqtt-dashboard.com";

WiFiClient espClient;

PubSubClient client(espClient);

void setup() {

pinMode(16, OUTPUT);

Serial.begin(115200);

// h à m th ự c hi ệ n ch ứ c n ă ng k ế t n ố i Wifi v à in ra đị a ch ỉ IP c ủ a ESP8266

setup_wifi();

// c à i đặ t server l à broker.mqtt-dashboard.com v à l ắ ng nghe client ở port 1883

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

103/155

client.setServer(mqtt_server, 1883);

// g ọ i h à m callback để th ự c hi ệ n c á c ch ứ c n ă ng publish/subcribe client.setCallback(callback);

// g ọ i h à m reconnect() để th ự c hi ệ n k ế t n ố i l ạ i v ớ i server khi b ị m ấ t k ế t n ố i reconnect();

}

void setup_wifi() {

delay(10);

Serial.println();

Serial.print("Connecting to ");

Serial.println(ssid);

// k ế t n ố i đế n m ạ ng Wifi

WiFi.begin(ssid, password);

// in ra d ấ u . n ế u ch ư a k ế t n ố i đượ c đế n m ạ ng Wifi while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

// in ra th ô ng b á o đã k ế t n ố i v à đị a ch ỉ IP c ủ a ESP8266

Serial.println("");

Serial.println("WiFi connected");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

}

void callback(char* topic, byte* payload, unsigned int length) {

//in ra t ê n c ủ a topic v à n ộ i dung nh ậ n đượ c t ừ k ê nh MQTT lens đã publish Serial.print("Message arrived [");

Serial.print(topic);

Serial.print("] ");

for (int i = 0; i < length; i++) {

Serial.print((char)payload[i]);

}

// ki ể m tra n ế u d ữ li ệ u nh ậ n đượ c t ừ topic ESP8266/LED_GPIO16/status l à chu ỗ i "on"

// s ẽ b ậ tled GPIO16, n ế u l à chu ỗ i "off" s ẽ t ắ t led GPIO16

if ((char)payload[0] == 'o' && (char)payload[1] == 'n') //on

digitalWrite(16, LOW);

else if ((char)payload[0] == 'o' && (char)payload[1] == 'f' && (char)payload[2] == 'f') //off digitalWrite(16, HIGH);

Serial.println();

}

void reconnect() {

// l ặ p cho đế n khi đượ c k ế t n ố i tr ở l ạ i while (!client.connected()) {

Serial.print("Attempting MQTT connection...");

if (client.connect("ESP8266")) {

Serial.println("connected");

// publish g ó i tin "Connected!" đế n topic ESP8266/connection/board client.publish("ESP8266/connection/board", "Connected!");

// đă ng k í nh ậ n g ó i tin t ạ i topic ESP8266/LED_GPIO16/status client.subscribe("ESP8266/LED_GPIO16/status");

} else {

// in ra m à n h ì nh tr ạ ng th á i c ủ a client khi kh ô ng k ế t n ố i đượ c v ớ i MQTT broker Serial.print("failed, rc=");

Serial.print(client.state());

Serial.println(" try again in 5 seconds");

// delay 5s tr ướ c khi th ử l ạ i

delay(5000);

}

}

}

void loop() {

// ki ể m tra n ế u ESP8266 ch ư a k ế t n ố i đượ c th ì s ẽ th ự c hi ệ n k ế t n ố i l ạ i if (!client.connected()) {

https://thuviensach.vn

104/155

reconnect();

}

client.loop();

}

Giải thích mã nguồn:

Chúng ta sẽ tạo một biến espClient thuộc lớp WiFiClient, biến này được khai báo là MQTT Client và sử

dụng các thuộc tính của thư viện PubSubClient. Tại hàm setup() sẽ thiết lập ESP8266 ở chế độ

station, kết nối đến mạng wifi. Bên cạnh đó hàm setup() cũng sẽ thực hiện chức năng tự động kết nối lại với MQTT Broker khi xảy ra mất kết nối đồng thời thực hiện các chức năng publish, subscribe của 1

MQTT Client thông qua hàm reconnect(). Hàm callback() có nhiệm vụ lấy dữ liệu của các puslisher khi publish 1 message sau đó gửi đến các client đã subscribe topic đó và kiểm tra nội dung của

message để điều khiển led ở GPIO16. Hàm loop() có chức năng kết nối Client là ESP8266 với Broker, thực hiện chức năng publish 1 message và subscribe topic. client.loop() sẽ kiểm tra thời gian kết nối của Client với gói KEEP_ALIVE để đưa ra các thông tin về trạng thái kết nối của ESP8266 đồng thời lấy dữ liệu của message từ buffer để gửi đến các Client đã subcribe topic.

• Bước 3 : Mở MQTT lens trên trình duyệt Chrome, tạo 1 connection với host name broker.mqtt-dashboard.com, sử dụng port 1883. Thực hiện subscribe topic ESP8266/connection/board. Sau

khi nhấn nút subscribe trên MQTT lens sẽ xuất hiện 1 message gửi từ esp8288 với nội dung

connnected. Thực hiện pushlish các message vào topic ESP8266/LED_GPIO16/status. Nếu

pushlish message với nội dung on, led GPIO16 trên board sẽ sáng, pushlish message off led

GPIO16 trên board sẽ tắt. Các message với nội dung khác thì vẫn sẽ hiển thị dữ liệu nhận được

trên serial terminal của Arduino nhưng sẽ không có tác dụng điều khiển led GPIO16. Kết quả

hiển thị như hình bên dưới:

Hình 54. Kết quả hiển thị trên serial terminal và MQTT lens khi sử dụng thư viện pubsubClient

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

105/155

ESP8266MQTTClient

Tiếp theo, chúng ta sẽ tìm hiểu cách sử dụng thư viện ESP8266MQTTClient, thư viện được cộng đồng

developer đánh giá là ổn định dễ sử dụng hơn so với thư viện PubSubClient thông qua 1 ứng dụng

điều khiển led trên board ESP8266 WiFi Uno bằng 1 ứng dụng trên điện thoại smartphone.

• Bước 1 : Download thư viện ESP8266MQTTClient tại đường dẫn github.com/tuanpmt/

ESP8266MQTTClient và add vào chương trình Arduino. Ngoài ra có thể import thư viện này trong Arduino bằng cách tìm kiếm thư viện với từ khóa ESP8266MQTT, chọn thư viện của tác giả Tuan

PM, version 1.3 và nhấn install.

• Bước 2 : Viết và nạp chương trình cho ESP8266. Mã nguồn được trình bày ở phía dưới.

#include <ESP8266MQTTClient.h>

#include <ESP8266WiFi.h>

#define ledPin 16 //Led on board ESP8266 WiFi Uno

MQTTClient mqtt;

const char* ssid = "Your SSID";

const char* password = "Your password";

void setup() {

Serial.begin(115200);

pinMode(ledPin, OUTPUT);

// OFF led GPIO16 khi b ắ t đầ u ch ươ ng tr ì nh

digitalWrite(ledPin, HIGH);

// Thi ế t l ậ p ESP8266 ở ch ế độ STA v à k ế t n ố i Wifi WiFi.mode(WIFI_STA);

WiFi.begin(ssid, password);

Serial.print(" \nConnecting to ");

Serial.println(ssid);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

Serial.println("");

Serial.println("WiFi connected");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

// K ế t n ố i đế n server MQTT, in ra id c ủ a topic "esp8266/GPIO16" đồ ng th ờ i đă ng k í nh ậ n message v ớ i g ó i QoS 0,

// v à subcribe c á c topic "hello/esp8266"

mqtt.onConnect([]() {

Serial.printf("MQTT: Connected\r\n");

Serial.printf("Subscribe id: %d\r\n", mqtt.subscribe("esp8266/GPIO16", 0)); mqtt.subscribe("esp8266/GPIO16", 0);

});

// Th ự c hi ệ n ch ứ c n ă ng subscribe topic v à publish c á c message mqtt.onSubscribe([](int sub_id) {

//in ra id c ủ a c á c topic đã subscribe l à "hello/esp8266" v à "MQTTlens/test/#"

Serial.printf("Subscribe topic id: %d ok\r\n", sub_id);

//publish message c ó n ộ i dung hello app đế n topic Broker/app v ớ i g ó i QoS 0 v à c ờ retain 0

mqtt.publish("Broker/app", "hello app", 0, 0);

});

https://thuviensach.vn

106/155

// X ử l í d ữ li ệ u nh ậ n đượ c c ủ a c á c topic đã subscribe mqtt.onData([](String topic, String data, bool cont) {

Serial.printf("Data received, topic: %s, data: %s\r\n", topic.c_str(), data.c_str());

// N ế u chu ỗ i nh ậ n đượ c l à 'on' s ẽ ON led tr ê n board ESP8266 WiFi Uno, chu ỗ i 'off' s ẽ OFF led if (topic == "esp8266/GPIO16" && data[0] == 'o' && data[1] == 'n' && data[2] == '\0') {

digitalWrite(ledPin, LOW);

Serial.println("Turn on the led on board");

} else if (topic == "esp8266/GPIO16" && data[0] == 'o' && data[1] == 'f' && data[2] == 'f' && data[3] == '\0' ) {

digitalWrite(ledPin, HIGH);

Serial.println("Turn off the led on board");

}

});

// kh ở i t ạ o broker MQTT l à iot.eclipse.org s ử d ụ ng ph ươ ng th ứ c websocket v à l ắ ng nghe client ở port 80

mqtt.begin("ws://iot.eclipse.org:80/ws");

}

void loop() {

// H à m kh ở i t ạ o MQTT, ki ể m tra v à x ử l í c á c d ữ li ệ u t ừ c á c topic, ki ể m tra c á c thu ộ c t í nh c ủ a giao

// th ứ c nh ư g ó i keep-a-live, g ó i tin QoS, id c ủ a topic..., mqtt.handle();

}

Giải thích mã nguồn

Tương tự như mã nguồn của chương trình sử dụng thư viện pubsubCLient, chúng ta cũng sẽ khởi tạo

ESP8266 là MQTT Client trong class MQTT của thư viện ESP8266MQTTClient. Cài đặt ESP8266 ở chế

độ Station và kết nối đến network wifi. Chức năng của các hàm trong thư viện đã được giải thích ở file mã nguồn, ở hàm mqtt.onConnect() chúng ta sẽ subscribe topic là esp8266/GPIO16. Hàm

mqtt.onSubscribe() sẽ thực hiện puslish các message ở topic đã chỉ định là Broker/app. Hàm

mqtt.onData() sẽ nhận, kiểm tra và xử lí dữ liệu nhận được từ topic đã subscribe. Ở đây ta sẽ dùng 1

public MQTT Broker là iot.eclipse.org, sử dụng phương thức Websocket là lắng nghe các MQTT Client ở port 80, đây là port mặc định khi sử dụng Websocket. Việc gửi nhận dữ liệu bằng phương thức

Websocket sẽ giúp giảm băng thông và độ trể khi truyền nhận dữ liệu thông qua giao thức MQTT. Chi tiết về Websocket chúng ta sẽ được học ở các bài học sau. Ở loop() chúng ta chỉ cần gọi hàm

handle() để khởi tạo và kiểm tra các thuộc tính của giao thức cũng như xử lí, truyền và nhận dữ liệu từ

các topic đã subscribe và public.



Để tìm hiểu chi tiết file cấu hình của thư viện, có thể xem tại github.com/

tuanpmt/ESP8266MQTTClient/tree/master/src

• Bước 3 : Cài đặt và sử dụng ứng dụng trên điện thoại để điều khiển led GPIO16.

Truy cập vào App Store trên hệ điều hành iOS hoặc CH Play trên hệ điều hành Android. nhập từ khóa IoT Smartconfig và cài đặt ứng dụng IoT Smartconfig của developer Tuan PM. Hình ảnh ứng dụng

hiển thị như bên dưới:

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

107/155

Hình 55. Hình ảnh ứng dụng IoT Smartconfig trên hệ điều hành iOS và Android

Ứng dụng này sử dụng với ESP8266 và ESP32, ngoài chức năng cơ bản là publish, subscribe của giao

thức MQTT, ứng dụng còn có chức năng smartconfig để ESP8266 và ESP32 có thể dễ dàng thiết lập

kết nối với các network wifi khác nhau một cách thuận tiện và nhanh chóng mà không phải nạp lại mã nguồn.

Tiếp theo, trượt ứng dụng qua phần MQTT, nhấn vào nút connect để kết nối đến server MQTT Broker

ws://iot.eclipse.org:80/ws. Thực hiện subscribe topic Broker/app và publish message vào topic

esp8266/GPIO16. Nếu publish message on vào esp8266/GPIO16 thì led trên board ESP8266 WiFi Uno

sẽ sáng, gửi off sẽ tắt led, đồng thời khi ESP8266 publish các message ở topic Broker/app thì nội dung các message sẽ được hiển thị trên ứng dụng. Kết quả hiển thị như hình bên dưới:

https://thuviensach.vn

108/155

Hình 56. Hình ảnh subcribe topic và publish các message trên ứng dụng

Hình 57. Hình ảnh trên Serial terminal của Arduino

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

109/155

MQTT Broker

Ở phần trước chúng ta sử dụng các dịch vụ MQTT Broker miễn phí để thử nghiệm, tuy nhiên ta có thể

sẽ phải trả phí dịch vụ với những ứng dụng lớn cần băng thông rộng và tốc độ đáp ứng nhanh, cộng

với việc dữ liệu có thể bị tấn công do độ bảo mật thông tin chưa cao. Do đó, ở phần này, chúng ta sẽ

tự mình xây dựng 1 MQTT Broker. Việc tự thiết lập 1 MQTT broker giúp chúng ta có thể sử dụng giao thức MQTT trên máy local mà không cần kết nối đến các dịch vụ MQTT Broker ở mạng internet. Quá

trình truyền, nhận và xử lí dữ liệu diễn ra 1 cách nhanh chóng cũng như bảo mật thông tin của người dùng. Tuy nhiên, để tạo được 1 MQTT Broker với đầy đủ tính năng của giao thức MQTT đòi hỏi chúng

ta phải có kiến thưc tốt về giao thức MQTT cũng như các ngôn ngữ lập trình bổ trợ cho việc xây dựng nó. Để bắt đầu, ta sẽ tạo ra 1 MQTT Broker đơn giản bằng cách dùng 1 module hỗ trợ sẵn có đó là

Mosca.

MOSCA

Mosca là 1 trong số rất nhiều server MQTT Broker của giao thức MQTT. Có thể kế đến các server khác như HiveMQ, Apache Apollo, Mosquitto, Mongoose. Mosca có 1 số đặc điểm như sau:

• Nó là 1 Node.js Broker, được viết bằng ngôn ngữ JavaScript vì vậy để có thể xây dựng MQTT

Broker, chúng ta cần Node.js để chạy. Mosca có thể nhúng vào ứng dụng của bạn nếu ứng

dụng này được viết bằng Node.js

• Mosca là 1 multi-transport MQTT Broker, có nghĩa là nó hỗ trợ tất cả các chức năng publish,

subscribe của các broker khác. Danh sách các publish/subscribe broker được hỗ trợ bao gồm

RabbitMQ, Redis, Mosquitto, ZeroMQ. Ở phần này chúng ta sẽ tạo ta 1 MQTT Broker đơn giản

dùng Mosca với sự hỗ trợ của cơ sở dữ liệu Mongodb

Mục tiêu

• Chúng ta sẽ tạo 1 MQTT Client là ESP8266 và 1 MQTT Client trên máy tính sử dụng MQTT.js nhằm

kết nối đến MQTT Broker , subscribe topic và publish các message.

• Dùng Mosca tạo 1 MQTT Broker trên máy tính cá nhân nhằm broadcast messages (truyền bá

các gói tin) đến các MQTT Client.

Các bước thực hiện

• Bước 1 : Trước tiên, chúng ta nên tạo 1 folder để thiết lập 1 MQTT Broker trên máy local. Đi đến folder này, tạo file package.js bằng lệnh npm init và thiết lập các thông tin của dự án. Tiếp theo, cài đặt module mosca bằng lệnh npm install mosca --save. Để lắng nghe các kết nối đến từ

client cũng như lưu trữ dữ liệu về thông tin kết nối và nội dung các message ta cần công cụ hỗ

trợ đó là MongoDB, bạn cũng có thể chọn Redis, Mosquitto, RabbitMQ… và tìm hiểu thêm về điểm

https://thuviensach.vn

110/155

mạnh, yếu của các cơ sở dữ liệu này. Để cài đặt MongoDB, chúng ta sẽ truy cập vào điạ chỉ

docs.mongodb.com/manual/administration/install-community/, tùy theo hệ điều hành để chọn gói cài đặt thích hợp. Sau khi cài đặt xong, chúng ta sẽ mở port 27017 (port mặc định khi dùng

mongodb, chúng ta có thể điều chỉnh port ở file cấu hình của mongodb) để lắng nghe các kết

nối từ client thông qua lệnh sudo service mongod start. Trên hệ điều hành Linux, có thể kiểm

tra các kết nối trên hệ thống bằng lệnh Netstat như hình dưới:

Hình 58. Hình ảnh port 27017 đã mở thành công và lắng nghe các kết nối

• Bước 2 : Tạo file Javascript để viết mã nguồn cho MQTT Broker. Ví dụ về mã nguồn của file serverMosca.js được viết bên dưới:

Mã nguồn file serverMosca.js

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

111/155

var mosca = require('mosca'); // Khai b á o bi ế n mosca s ử d ụ ng c á c thu ộ c t í nh c ủ a module mosca

// S ử d ụ ng th ư vi ệ n ascoltatore nh ằ m h ỗ tr ợ publish message, subscribe topic đế n t ừ c á c Broker/Protocol var ascoltatore = {

type: 'mongo',

url: 'mongodb://localhost:27017/mqtt', // url: đị a ch ỉ url c ủ a mongodb, server s ẽ l ắ ng nghe c á c client ở đị a

// ch ỉ localhost:27017

pubsubCollection: 'ascoltatori', // pubsubCollection: N ơ i để l ư u tr ữ c á c message c ủ a mongodb mongo: {} // mongo: C à i đặ t d à nh cho k ế t n ố i c ủ a mongo. Kh ô ng s ử d ụ ng

};

var settings = {

port: 1883, // port k ế t n ố i đế n server

backend: ascoltatore // ascoltatore s ẽ đượ c g ọ i v à th ự c thi khi t ạ o server đượ c t ạ o để thi ế t l ậ p c á c k ế t n ố i

};

// L ệ nh t ạ o server s ử d ụ ng mosca

var server = new mosca.Server(settings);

// Th ự c hi ệ n h à m setup, in ra m à n h ì nh console n ế u c ó s ự ki ệ n ready c ủ a server server.on('ready', setup);

function setup() {

console.log('Mosca server is up and running');

}

// In ra d ò ng ch ữ client connected v à id c ủ a client khi c ó s ự ki ệ n client k ế t n ố i th à nh c ô ng đế n server server.on('clientConnected', function(client) {

console.log('client connected', client.id);

});

// In ra d ò ng ch ữ client disconnected v à id c ủ a client khi c ó s ự ki ệ n client ng ắ t k ế t n ố i v ớ i server server.on('clientDisconnected', function(client) {

console.log('client disconnected', client.id);

});

// In ra message c ủ a client g ử i ở d ạ ng string khi c ó s ự ki ệ n client publish 1 message server.on('published', function(packet, client) {

console.log('Published', packet.payload.toString());

});

• Bước 3 : Viết mã nguồn cho ESP8266. Để nhanh chóng, chúng ta sẽ dùng mã nguồn của thư

viện ESP8266MQTTClient đã viết ở mục trước. Sửa đổi địa chỉ của MQTT Broker từ

mqtt.begin("mqtt://iot.eclipse.org:1883"); thành mqtt.begin("mqtt://your-local-ip:1883"); với your-local-ip là địa chỉ IP của máy tính (ví dụ 192.168.1.7), chú ý rằng ESP8266 và MQTT Broker phải kết nối chung 1 network WiFi.

• Bước 4 : Tạo MQTT Client dùng MQTT.js. Chúng ta sẽ tạo 1 folder để chứa các file của MQTT

Client. Tương tự như bước 1 , dùng npm init để tạo file package.js và thiết lập các thông tin của dự án. Tiếp theo cài đặt module mqtt bằng lệnh npm install mqtt --save và tạo file Javascript

để viết nội dung cho MQTT Client. Ví dụ về mã nguồn file moscaClient.js được trình bày bên

dưới:

Mã nguồn file moscaClient.js

https://thuviensach.vn

112/155

// Khai b á o bi ế n mqtt để s ử d ụ ng c á c thu ộ c t í nh thu ộ c module mqtt var mqtt = require('mqtt');

// T ạ o 1 k ế t n ố i đế n đị a ch ỉ 192.168.1.7 port 1883 th ô ng qua giao th ứ c MQTT

var client = mqtt.connect('mqtt://192.168.1.7:1883');

// Khi c ó s ự ki ệ n connect đế n server, client s ẽ subscribe topic MQTTlens/test/3 v à

// publish 1 message "on" v à o topic hello/world để ON led ở board ESP8266 WiFi Uno client.on('connect', function () {

client.subscribe('Broker/app');

client.publish('esp8266/GPIO16', 'on');

})

// Khi c ó message g ử i đế n client, client s ẽ chuy ể n đổ i d ữ li ệ u t ừ Buffer sang d ạ ng String v à in ra m à n

// h ì nh console d ữ li ệ u nh ậ n đượ c v à đó ng k ế t n ố i.

client.on('message', function (topic, message) {

// message is Buffer

console.log(message.toString());

//client.end();

})

Kết quả

Trên terminal, đi đến thư mục chứa file moscaServer.js và khởi chạy server bằng lệnh node

moscaServer.js. Server sẽ khởi động và lắng nghe các kết nối đến từ các MQTT Client. Tiếp theo, nạp chương trình trên Arduino cho ESP8266, sau đó khởi chạy MQTT Client trên máy tính bằng lệnh node

moscaClient.js. Khi có các sự kiện kết nối , ngắt kết nối, pushlish 1 message hay subcrible 1 topic đến từ các client thì bên phía server đều sẽ hiển thị nội dung và thông tin. Các terminal hiển thị kết quả

như hình bên dưới:

Hình 59. Hình ảnh thông tin nhận được từ các client ở server mosca

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

113/155

Hình 60. Hình ảnh thông tin nhận được ở client mqtt.js và client ESP8266

Một số MQTT Broker sử dụng cho sản phẩm thực tế

Mosquitto

Mosquitto là 1 MQTT Broker viết bằng ngôn ngữ lập trình C. Một số đặc điểm nổi bật của mosquitto là tốc độ truyền nhận và xử lí dữ liệu nhanh, độ ổn định cao, được sử dụng rộng rãi và phù hợp với

những ứng dụng embedded. Thích hợp cho các hệ thống nhỏ chạy trên máy local như Raspberry Pi,

bên cạnh đó Mosquitto cũng được hỗ trợ các giao thức TLS/SSL (các giao thức nhằm xác thực server

và client, mã hóa các message để bảo mật dữ liệu).

Một số nhược điểm của mosquitto là khó thiết kế khi làm những ứng dụng lớn và ít phương thức xác

thực thiết bị nên khả năng bảo mật vẫn chưa tối ưu.

EMQ

EMQ (Erlang MQTT Broker) là một MQTT Broker được viêt bằng ngôn ngữ lập trình Erlang. Ưu điểm của EMQ là tính ổn định cao, thích hợp để thiết kế các hệ thống lớn do khả năng mở rộng ứng dụng dễ

dàng cũng như khá dễ để cài đặt. Ngoài ra EMQ còn hỗ trợ nhiều phương thức xác thực người dùng,

phát triển và cập nhật tính năng liên tục bởi cộng đồng developer. Tuy nhiên điểm yếu của MQTT

broker này là khó đối với những người mới bắt đầu. Thông tin về EMQ có thể xem tại trang emqttd-

docs.readthedocs.io/en/latest/#

https://thuviensach.vn

114/155

Tổng kết

Từ những nội dung đã trình bày ở trên, chúng ta phần nào hiểu rõ về cách thức hoạt động của giao

thức MQTT cũng như vai trò của nó trong các ứng dụng IoT. Những nội dung được trình bày ở phần

này chỉ là phần cơ bản của giao thức, vì đây là giao thức quan trọng và thường sử dụng trong IoT nên chúng ta hãy dành nhiều thời gian hơn để nghiên cứu thêm về hoạt động của các gói QoS, Keep

alive, cũng như các vấn đề chứng thực tài khoản, vấn đề bảo mật dữ liệu khi sử dụng MQTT.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

115/155

Websocket

WebSoket là công nghệ hỗ trợ giao tiếp hai chiều giữa client và server bằng cách sử dụng một TCP

socket để tạo một kết nối liên tục, hiệu quả và ít tốn kém. Mặc dù được thiết kế để chuyên sử dụng cho các ứng dụng web, lập trình viên vẫn có thể đưa chúng vào bất kì loại ứng dụng nào.

WebSockets mới xuất hiện trong HTML5, cho phép các kênh giao tiếp song song hai chiều và hiện đã

được hỗ trợ trong nhiều trình duyệt. Kết nối được mở thông qua một HTTP request (yêu cầu HTTP), với những header đặc biệt thông báo cho Server (có hỗ trợ) chuyển sang kết nối Websocket. Kết nối này được duy trì để bạn có thể gởi và nhận dữ liệu một cách liên tục, không đứt quãng, và không cần bất kỳ HTTP header (overhead) nào nữa.

Websocket hỗ trợ cho các trình duyệt phổ biến hiện nay như: Google Chrome, Microsoft Edge,

Internet Explorer, Firefox, Safari và Opera.

Ưu điểm

WebSockets cung cấp khả năng giao tiếp hai chiều với kết nối được duy trì, có độ trễ thấp, giúp

Server dễ dàng giao tiếp với Client. Do đó, websocket sẽ phù hợp cho các ứng dụng real-time, người dùng sẽ không mất thời gian phải reload lại trình duyệt để cập nhật thông tin mới nhất như khi sử

dụng giao thức HTTP.

Nhược điểm

Giao thức Websocket chưa được tất cả các trình duyệt đã có hiện nay hỗ trợ. Websocket cũng đòi

hỏi các ứng dụng web trên server để hỗ trợ nó.

https://thuviensach.vn

116/155

Sử dụng ESP8266 như Websocket Server

Trong phần này, chúng ta sẽ thiết lập ứng dụng sử dụng ESP8266 như 1 Websocket Server và Trình

duyệt như là một Web Socket Client để cập nhật trạng thái nút nhấn, cũng như điều khiển đèn LED

trên board thời gian thực thông qua Trình duyệt.

Yêu cầu

• Khởi động 1 Webserver (có hỗ trợ Websocket) trên chip ESP8266.

• Khi truy cập vào địa chỉ IP của ESP8266 sẽ trả về 1 file HTML bao gồm nội dung của đoạn

Javascript thiết lập kết nối Websocket đến ESP8266 đồng thời lắng nghe các gói tin từ ESP8266

Server.

• Khi nhấn nút trên board ESP8266 sẽ gởi nội dung trạng thái nút nhất đến Web Browser hiển thị

dạng hộp kiểm (checkbox), nhấn nút là có kiểm, không nhấn nút là không có kiểm.

• Đồng thời khi nhấn hộp kiểm trên trình duyệt sẽ thay đổi trạng thái đèn LED trên board

ESP8266.

Chuẩn bị

Cài đặt thư viện, xem thêm Cài đặt thư viện Arduino:

• github.com/me-no-dev/ESPAsyncWebServer

• github.com/me-no-dev/ESPAsyncTCP

Giới thiệu về thư viện ESPAsyncWebServer

Thư viện ESPAsyncWebServer dùng cho việc thiết lập HTTP server và websocket server cho module

ESP8266, và xử lí các sự kiện trên server-client.

Để các chương trình dùng thư viện ESPAsyncWebserver hoat động, ta cần dùng thêm thư viện

ESPAsyncTCP.

Đoạn code Javascript để tạo kết nối Web Socket

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

117/155

//Tr ì nh t ự m ở m ộ t websocket c ơ b ả n:

var ws = new WebSocket('ws://domain.com:8000/'); // m ở 1 websocket

ws.onopen = function() //

{

// s ự ki ệ n khi websocket đượ c m ở th à nh c ô ng

};

ws.onmessage = function(evt)

{

// s ự ki ệ n x ả y ra khi client nh ậ n d ữ li ệ u t ừ server

};

ws.onclose = function() {

// s ự ki ệ n khi websocket b ị đó ng

};

Nhúng file HTML chứa đoạn code JS vào ESP8266

https://thuviensach.vn

118/155

<!DOCTYPE HTML>

< html>

< head>

< title>ESP8266 WebSocket</title>

</head>

< body>

< div> Webscoket status < span id="status" style="font-weight: bold;"> disconnected </span> </div>

< div> ESP8266 Button Status < input type="checkbox" id="btn" name="btn" /> </div>

< div> Control LED < input type="checkbox" id="led" name="led" disabled="true" /> </div>

< script type="text/javascript">

var button = document.getElementById('btn');

var led = document.getElementById('led');

var url = window.location.host; // h à m tr ả v ề url c ủ a trang hi ệ n t ạ i k è m theo port var ws = new WebSocket('ws://' + url + '/ws'); // m ở 1 websocket v ớ i port 8000

ws.onopen = function() //khi websocket đượ c m ở th ì h à m n à y s ẽ đượ c th ư c hi ệ n

{

document.getElementById('status').innerHTML = 'Connected';

led.disabled = false; //khi websocket đượ c m ở , m ớ i cho ph é p

};

ws.onmessage = function(evt) // s ự ki ệ n x ả y ra khi client nh ậ n d ữ li ệ u t ừ server

{

if(evt.data == 'BTN_PRESSED') {

button.checked = true;

} else if(evt.data == 'BTN_RELEASE') {

button.checked = false;

}

};

ws.onclose = function() { // h à m n à y s ẽ đượ c th ự c hi ệ n khi đó ng websocket led.disabled = true;

document.getElementById('status').innerHTML = 'Disconnected';

};

led.onchange = function() { // th ự c hi ệ n thay đổ i b ậ t/t ắ t led var status = 'LED_OFF';

if (led.checked) {

status = 'LED_ON';

}

ws.send(status)

}

</script>

</body>

</html>

Chương trình hoàn chỉnh cho ESP8266

#include <ESP8266WiFi.h>

#include <ESPAsyncWebServer.h>

const char* ssid = "******";

const char* password = "*********";

const int LED = 16;

const int BTN = 0;

// để đư a đ o ạ n code HTML v à o ch ươ ng tr ì nh Arduino, c ầ n chuy ể n đổ i code HTML sang d ạ ng char const char index_html[] PROGMEM = ""

"<!DOCTYPE HTML>"

"<html>"

"<head>"

" <title>ESP8266 WebSocket</title>"

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

119/155

"</head>"

"<body>"

" <div> Webscoket status <span id=\" status\" style=\" font-weight: bold; \" > disconnected </span> </div>"

" <div> ESP8266 Button Status <input type=\" checkbox\" id=\" btn\" name=\" btn\" /> </div>"

" <div> Control LED <input type=\" checkbox\" id=\" led\" name=\" led\" disabled=\" true\" /> </div>"

" <script type=\" text/javascript\" >"

" var button = document.getElementById('btn');"

" var led = document.getElementById('led');"

" var status = document.getElementById('status');"

" var url = window.location.host;"

" var ws = new WebSocket('ws://' + url + '/ws');"

" ws.onopen = function()"

" {"

" status.text = 'Connected';"

" led.disabled = false;"

" };"

" ws.onmessage = function(evt)"

" {"

" if(evt.data == 'BTN_PRESSED') {"

" button.checked = true;"

" } else if(evt.data == 'BTN_RELEASE') {"

" button.checked = false;"

" }"

" };"

" ws.onclose = function() {"

" led.disabled = true;"

" status.text = 'Disconnected';"

" };"

" led.onchange = function() {"

" var status = 'LED_OFF';"

" if (led.checked) {"

" status = 'LED_ON';"

" }"

" ws.send(status)"

" }"

" </script>"

"</body>"

"</html>";

AsyncWebServer server(8000);

AsyncWebSocket ws("/ws");

// H à m x ử l í s ự ki ệ n tr ê n Server khi client l à browser ph á t s ự ki ệ n void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {

if (type == WS_EVT_DATA && len > 0) { // type: lo ạ i s ự ki ệ n m à server nh ậ n đượ c. N ế u s ự ki ệ n nh ậ n đượ c l à t ừ

websocket th ì b ắ t đầ u x ử l í

data[len] = 0;

String data_str = String((char*)data); // é p ki ể u, đổ i t ừ ki ể u char sang String if (data_str == "LED_ON") {

digitalWrite(LED, 0); // Khi client ph á t s ự ki ệ n "LED_ON" th ì server s ẽ b ậ t LED

} else if (data_str == "LED_OFF") {

digitalWrite(LED, 1); // Khi client ph á t s ự ki ệ n "LED_OFF" th ì server s ẽ t ắ t LED

}

}

}

void setup()

{

pinMode(LED, OUTPUT);

pinMode(BTN, INPUT);

Serial.begin(115200);

Serial.setDebugOutput(true);

WiFi.mode(WIFI_AP_STA);

WiFi.begin(ssid, password);

if (WiFi.waitForConnectResult() != WL_CONNECTED) {

Serial.printf("STA: Failed! \n");

https://thuviensach.vn

120/155

WiFi.disconnect(false);

delay(1000);

WiFi.begin(ssid, password);

}

ws.onEvent(onWsEvent); // g ọ i h à m onWsEvent

server.addHandler(&ws);

server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {

request->send_P(200, "text/html", index_html); // tr ả v ề file index.html tr ê n giao di ệ n browser khi browser truy c ậ p v à o IP c ủ a server

});

server.begin(); // kh ở i độ ng server

}

void loop()

{

static bool isPressed = false;

if (!isPressed && digitalRead(BTN) == 0) { //Nh ấ n n ú t nh ấ n GPIO0

isPressed = true;

ws.textAll("BTN_PRESSED");

} else if (isPressed && digitalRead(BTN)) { //Nh ả n ú t nh ấ n GPIO0

isPressed = false;

ws.textAll("BTN_RELEASE");

}

}

Thực hiện sau khi kiểm tra mã nguồn:

• Chọn Board ESP8266 WiFi Uno trong Arduino IDE

• Nạp chương trình xuống board dùng Arduino IDE

Kết quả

Sau khi biên dịch xong code trên Arduino, ta vào browser, truy cập vào địa chỉ IP của ESP8266 đã trả

về trên Serial Monitor cùng với port đã thiết lập trên server, ở trường hợp này là 192.168.1.65:8000

Hình 61. Cửa sổ trình duyệt có thể điều khiển ESP8266 thông qua Web Socket

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

121/155

Video kết quả

 https://www.youtube.com/watch?v=pN3YSLiWbHk (YouTube video) https://thuviensach.vn

122/155

Sử dụng ESP8266 như Websocket Client

Trong một số ứng dụng khác, chúng ta có 1 Server Websocket để thực hiện các tác vụ thời gian thực như Ứng dụng điện thoại, trình duyệt Web. Thì ESP8266 có thể kết nối trực tiếp vào các server này như 1 Websocket Client để tiếp nhận, hoặc gởi thông tin thông qua Websocket.

Một số dịch vụ sử dụng Websocket điển hình như dịch vụ tin nhắn Slack, dịch vụ cơ sở dữ liệu thời gian thực Firebase

Ở phần này, chúng ta sẽ sử dụng Node.js để tự xây dựng 1 Web server, vừa đóng vai trò là 1

Websocket Server. Có những tính năng:

• Có thể cung cấp file index.html chứa các đoạn mã javascript tạo kết nối Websocket giữa trình

duyệt với Server, giống như phần Server Nodejs

• Cho phép kết nối Websocket đến, bao gồm từ trình duyệt, hay từ ESP8266

• Server sẽ broadcast tất cả các gói tin từ bất kỳ 1 client nào gởi đến, tới tất cả các client còn lại.

Với tính năng như trên thì bạn có thể hình dung như sau: Nếu 1 cửa sổ trình duyệt có kết nối

Websocket đến Server, khi nhấn 1 nút kiểm, thì sẽ gởi về server trạng thái của nút kiểm đó. Ví dụ

LED_ON, server nhận được sẽ gởi dữ liệu LED_ON đến các trình duyệt còn lại (hoặc bao gồm cả

ESP8266), và trình duyệt còn lại sẽ hiển thị trạng thái nút kiểm này đang bật.

Hình 62. Hai cửa sổ trình duyệt sẽ hiển thị trạng thái nút kiểm giống nhau khi click thay đổi

Javascript Websocket Client trên trình duyệt

Với file index.html có chứa mã nguồn Javascript tạo kết nối đến Websocket, để cùng thư mục với file server.js

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

123/155

index.html

<!DOCTYPE HTML>

< html>

< head>

< title>ESP8266 WebSocket</title>

</head>

< body>

< div> Webscoket status < span id="status" style="font-weight: bold;"> disconnected </span> </div>

< div> ESP8266 Button Status < input type="checkbox" id="btn" name="btn" /> </div>

< div> Control LED < input type="checkbox" id="led" name="led" disabled="true" /> </div>

< script type="text/javascript">

var button = document.getElementById('btn');

var led = document.getElementById('led');

var url = window.location.host; // h à m tr ả v ề url c ủ a trang hi ệ n t ạ i k è m theo port var ws = new WebSocket('ws://' + url + '/ws'); // m ở 1 websocket v ớ i port 8000

console.log('connecting...')

ws.onopen = function() //khi websocket đượ c m ở th ì h à m n à y s ẽ đượ c th ư c hi ệ n

{

document.getElementById('status').innerHTML = 'Connected';

led.disabled = false; //khi websocket đượ c m ở , m ớ i cho ph é p console.log('connected...')

};

ws.onmessage = function(evt) // s ự ki ệ n x ả y ra khi client nh ậ n d ữ li ệ u t ừ server

{

console.log(evt.data)

if(evt.data == 'BTN_PRESSED') {

button.checked = true;

} else if(evt.data == 'BTN_RELEASE') {

button.checked = false;

} else if(evt.data == 'LED_OFF') {

led.checked = false;

} else if(evt.data == 'LED_ON') {

led.checked = true;

}

};

ws.onclose = function() { // h à m n à y s ẽ đượ c th ự c hi ệ n khi đó ng websocket led.disabled = true;

document.getElementById('status').innerHTML = 'Connected';

};

led.onchange = function() { // th ự c hi ệ n thay đổ i b ậ t/t ắ t led var led_status = 'LED_OFF';

if (led.checked) {

led_status = 'LED_ON';

}

ws.send(led_status)

}

</script>

</body>

</html>

Node.js Websocket Server

Trong phần này chúng ta cần dùng thư viện Websocket ws github.com/websockets/ws. Bạn có thể

cài đặt bằng cách thực thi lệnh:

npm install ws

https://thuviensach.vn

124/155

server.js

var fs = require('fs');

var url = require('url');

var http = require('http');

var WebSocket = require('ws');

// function g ử i y ê u c ầ u(response) t ừ ph í a server ho ặ c nh ậ n y ê u c ầ u (request) c ủ a client g ử i l ê n function requestHandler(request, response) {

fs.readFile('./index.html', function(error, content) {

response.writeHead(200, {

'Content-Type': 'text/html'

});

response.end(content);

});

}

// create http server

var server = http.createServer(requestHandler);

var ws = new WebSocket.Server({ server });

var clients = [];

function broadcast(socket, data) {

console.log(clients.length);

for(var i=0; i<clients.length; i++) {

if(clients[i] != socket) {

clients[i].send(data);

}

}

}

ws.on('connection', function(socket, req) {

clients.push(socket);

socket.on('message', function(message) {

console.log('received: %s', message);

broadcast(socket, message);

});

socket.on('close', function() {

var index = clients.indexOf(socket);

clients.splice(index, 1);

console.log('disconnected');

});

});

server.listen(8000);

console.log('Server listening on port 8000');

ESP8266 Websocket Client

github.com/Links2004/arduinoWebSockets

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

125/155

#include <Arduino.h>

#include <ESP8266WiFi.h>

#include <WebSocketsClient.h> //https://github.com/Links2004/arduinoWebSockets

WebSocketsClient webSocket;

const char* ssid = "...";

const char* password = "...";

const int LED = 16;

const int BTN = 0;

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {

switch (type) {

case WStype_DISCONNECTED:

Serial.printf("[WSc] Disconnected! \n");

break;

case WStype_CONNECTED:

{

Serial.printf("[WSc] Connected to url: %s\n", payload);

}

break;

case WStype_TEXT:

Serial.printf("[WSc] get text: %s\n", payload);

if(strcmp((char*)payload, "LED_ON") == 0) {

digitalWrite(LED, 0); // Khi client ph á t s ự ki ệ n "LED_ON" th ì server s ẽ b ậ t LED

} else if(strcmp((char*)payload, "LED_OFF") == 0) {

digitalWrite(LED, 1); // Khi client ph á t s ự ki ệ n "LED_OFF" th ì server s ẽ t ắ t LED

}

break;

case WStype_BIN:

Serial.printf("[WSc] get binary length: %u\n", length);

break;

}

}

void setup() {

pinMode(LED, OUTPUT);

pinMode(BTN, INPUT);

Serial.begin(115200);

Serial.println("ESP8266 Websocket Client");

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

webSocket.begin("192.168.0.106", 8000);

webSocket.onEvent(webSocketEvent);

}

void loop() {

webSocket.loop();

static bool isPressed = false;

if (!isPressed && digitalRead(BTN) == 0) { //Nh ấ n n ú t nh ấ n GPIO0

isPressed = true;

webSocket.sendTXT("BTN_PRESSED");

} else if (isPressed && digitalRead(BTN)) { //Nh ả n ú t nh ấ n GPIO0

isPressed = false;

webSocket.sendTXT("BTN_RELEASE");

}

}

https://thuviensach.vn

126/155

Hình 63. Click nút kiểm sẽ thay đổi trạng thái LED trên board

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

127/155

Tổng kết

Việc sử dụng giao thức websocket sẽ có nhiều lợi ích cho các kết nối 2 chiều, luôn được duy trì và có độ trễ thấp.

https://thuviensach.vn

128/155

Firmware update over the

air (FOTA)

Các phương pháp phát triển phần mềm và sản phẩm phổ biến hiện nay, thì xuất bản kết quả từng

giai đoạn thường mang lại hiệu quả cao, sản phẩm có thể đến tay người dùng sớm, nhận được phản

hồi sớm từ khách hàng, và được điều chỉnh để hợp lý hơn. Chính việc phát hành sản phẩm sớm

thường sẽ ít tính năng và cần cập nhật thêm tính năng, nâng cao chất lượng sản phẩm trong tương

lai.

Cập nhật ứng dụng từ xa trên các phần mềm điện thoại, máy tính đã rất phổ biến. Các phần mềm

được cập nhật hàng tuần, tháng… để sửa lỗi, nâng cấp tính năng.

Đối với các sản phẩm phần cứng cũng tương tự, chúng ta nên bổ sung các tính năng cập nhật từ xa

ngay từ giai đoạn phát triển sản phẩm. Ngoài việc giúp nâng cấp các tính năng trong tương lai một cách dễ dàng, thì vấn để sửa lỗi, nâng cấp hệ thống từ xa sẽ giúp tiết kiệm được rất nhiều chi phí và nguồn lực.

Trong phần này, chúng ta sẽ tìm hiểu các phương pháp cập nhật từ xa cho ESP8266, làm sao để nạp

Firmware không dây cho module, làm sao để ESP8266 có thể tự tải Firmware về, làm sao để ESP8266

có thể tự khởi động 1 HTTP Server để có giao diện Web upload firmware lên chip.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

129/155

Cập nhật firmware từ xa

Cập nhật firmware OTA (Over the Air) là tiến trình tải firmware mới vào ESP8266 module thay vì sử

dụng cổng Serial. Tính năng này thực sự rất hữu dụng trong nhiều trường hợp giới hạn về kết nối vật lý đến ESP Module.

OTA có thể thực hiện với:

• Arduino IDE

• Web Browser

• HTTP Server

Sử dụng OTA với tùy chọn dùng Arduino IDE trong quá trình phát triển, thử nghiệm, 2 tùy chọn còn lại phù hợp cho việc triển khai ứng dụng thực tế, cung cấp tính năng cập nhật OTA thông qua web hay

sử dụng HTTP Server.

Trong tất cả các trường hợp, thì Firmware hỗ trợ OTA phải được nạp lần đầu tiên qua cổng Serial, nếu mọi thứ hoạt động trơn tru, logic ứng dụng OTA hoạt động đúng thì có thể thực hiện việc cập nhật

firmware thông qua OTA.

Sẽ không có đảm bảo an ninh đối với quá trình cập nhật OTA bị hack. Nó phụ thuộc vào nhà phát

triển đảm bảo việc cập nhật được phép từ nguồn hợp pháp, đáng tin cậy. Khi cập nhật hoàn tất,

ESP8266 sẽ khởi động lại và thực thi code mới. Nhà phát triển phải đảm bảo ứng dụng thực trên

module phải được tắt và khởi động lại 1 cách an toàn. Nội dung bên dưới cung cấp bổ sung các thông tin về an ninh, và an toàn cho tiến trình cập nhật OTA.

Bảo mật

Khi ESP8266 được phép thực thi OTA, có nghĩa nó được kết nối mạng không dây và có khả năng được

cập nhập Sketch mới. Cho nên khả năng ESP8266 bị tấn công sẽ nhiều hơn và bị nạp bởi mã thực thi

khác là rất cao. Để giảm khả năng bị tấn công cần xem xét bảo vệ cập nhật của bạn với một mật

khẩu, cổng sử dụng cố định khác biệt, v.v…

Kiểm tra những tính năng được cung cấp bởi thư viện ArduinoOTA thường xuyên, có thể được nâng

cấp khả năng bảo vệ an toàn:

void setPort(uint16_t port);

void setHostname(const char* hostname);

void setPassword(const char* password);

Một số chức năng bảo vệ đã được xây dựng trong và không yêu cầu bất kỳ mã hóa nào cho nhà phát

triển. ArduinoOTA và espota.py sử dụng Digest-MD5 để chứng thực việc tải firmware lên. Đơn giản là đảm bảo tính toàn vẹn của firmware bằng việc tính MD5.

https://thuviensach.vn

130/155

Hãy phân tích rủi ro cho riêng ứng dụng của bạn và tùy thuộc vào ứng dụng mà quyết định những

chức năng cũng như thư viện để thực hiện. Nếu cần thiết, có thể xem xét việc thực hiện các phương thức bảo vệ khỏi bị hack, ví dụ như cập nhật OTA chỉ cho tải lên chỉ theo lịch trình cụ thể, kích hoạt OTA chỉ được người dùng nhấn nút chuyên dụng “Cập nhật”, v.v…

An toàn

Quá trình OTA tiêu tốn nguồn tài nguyên và băng thông của ESP8266 khi tải lên. Sau đó, ESP8266

được khởi động lại và một Sketch mới được thực thi. Cần phân tích và kiểm tra ảnh hưởng của quá

trình này tới các chức năng cũ và sketch mới của ESP module.

Nếu ESP được đặt ở xa và điều khiển một vài thiết bị, ta nên chú ý tới hoạt động của thiết bị nếu thiết bị ngừng hoạt động đột xuất do quá trình cập nhật. Do đó, ta cần phải xác định được trạng thái làm việc an toàn của thiết bị trước quá trình cập nhật. Ví dụ, module được dùng để điều khiển hệ thống tưới nước tự động trong vườn. Nếu trong quá trình hoạt động mà hệ thống điều khiển bị tắt đột ngột và các van bị mở, thì cả vườn sẽ bị ngập nước.

Các hàm sau đây được cung cấp bởi thư viện ArduinoOTA và được dùng để xử lý ứng dụng trong quá

trình cập nhật OTA hoặc để xử lý khi OTA gặp lỗi:

void onStart(OTA_CALLBACK(fn));

void onEnd(OTA_CALLBACK(fn));

void onProgress(OTA_CALLBACK_PROGRESS(fn));

void onError(OTA_CALLBACK_ERROR (fn));

Yêu cầu căn bản

Bộ nhớ Flash phải có đủ dung lượng để lưu cả sketch cũ (đang vận hành trên hệ thống) và sketch

mới (cập nhật OTA).

Hệ thống File và EEPROM cũng cần dung lượng để lưu trữ.

Hàm ESP.getFreeSketchSpace(); được dùng để kiểm tra dung lượng trống cho sketch mới.

Update process - memory view

• Sketch mới sẽ được chứa trong dung lượng trống gĩưa sketch cũ và spiff.

• Trong lần reboot tiếp theo thì “eboot” bootloader kiểm tra các câu lệnh.

• Sketch mới sẽ được copy.

• Sketch mới khởi động.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

131/155

https://thuviensach.vn

132/155

OTA sử dụng Arduino IDE

Thưc hiện OTA với Arduino IDE chỉ nên thưc hiện khi:

• Sử dụng nạp firmware cho module ESP8266 thông qua WiFi mà không dùng cổng Serial

• ESP8266 và máy tính chạy Arduino IDE sử dụng chung mạng WiFi nội bộ

• ESP8266 đã kết nối thành công vào mạng WiFi

• Nạp firmware đã hỗ trợ OTA thông qua cổng Serial trước đó

Trước khi bắt đầu, cần phải chắc chắn Arduino IDE đã được cài đặt phiên bản mới nhất, bao gồm gói ESP8266 cho Arudino, và Python 2.7

Bước 1: nạp firmware hỗ trợ OTA thông qua cổng

Serial

Mở sketch ví dụ mẫu BasicOTA.ino. Vào File > Examples > ArduinoOTA.

Hình 64. Mở sketch ví dụ mẫu OTA

Cung cấp chính xác SSID và mật khẩu mạng WiFi đang dùng để ESP8266 có thể kết nối vào

Cung cấp SSID và password

const char* ssid = "..........";

const char* password = "..........";

Tùy vào phiên bản và board ESP bạn sử dụng, bạn có thể thấy `Ùpload Using:``



trong menu. Lựa chọn này sẽ không hoạt động và không ảnh hưởng tới lựa

chọn của bạn. Chức năng này tương thích với các phiên bản OTA cũ và bị gỡ bỏ

ở platform package version 2.2.0.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

133/155

Upload sketch Ctrl+U Khi hoàn thành, mở Serial Monitor Ctrl+Shift+M (xem Sử dụng Arduino IDE Serial

Monitor) và kiểm tra module đã trup cập được WIFI chưa

Hình 65. Kiểm tra module ESP8266 đã truy cập được mạng WiFi nội bộ chưa



ESP module nên được reset sau khi Upload xong firmware

https://thuviensach.vn

134/155

#include <ESP8266WiFi.h>

#include <ESP8266mDNS.h>

#include <WiFiUdp.h>

#include <ArduinoOTA.h>

const char* ssid = "...";

const char* password = "...";

void setup() {

Serial.begin(115200);

Serial.println("Booting");

WiFi.mode(WIFI_STA);

WiFi.begin(ssid, password);

while (WiFi.waitForConnectResult() != WL_CONNECTED) {

Serial.println("Connection Failed! Rebooting...");

delay(5000);

ESP.restart();

}

ArduinoOTA.onStart([]() {

String type;

if (ArduinoOTA.getCommand() == U_FLASH)

type = "sketch";

else // U_SPIFFS

type = "filesystem";

// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()

Serial.println("Start updating " + type);

});

ArduinoOTA.onEnd([]() {

Serial.println(" \nEnd");

});

ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {

Serial.printf("Progress: %u%%\r", (progress / (total / 100)));

});

ArduinoOTA.onError([](ota_error_t error) {

Serial.printf("Error[%u]: ", error);

if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");

else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");

else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");

else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");

else if (error == OTA_END_ERROR) Serial.println("End Failed");

});

ArduinoOTA.setPassword((const char *)"ota-pass");

ArduinoOTA.begin();

Serial.println("Ready");

Serial.print("IP address: ");

Serial.println(WiFi.localIP());

}

void loop() {

ArduinoOTA.handle();

}

Bước 2: Lựa chọn cổng nạp thông qua OTA

Khi module kết nối tới mạng WiFi thành công, sau vài giây, cổng esp8266-ota sẽ xuất hiện trên

Arduino IDE. Lúc này bạn hoàn toàn có thể bỏ kết nối Serial từ board mạch đến máy tính. Arduino IDE

có thể nạp firmware mới thông qua WiFi. Chọn port với địa chỉ IP hiện trên cửa sổ Serial Monitor ở

bước trước.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

135/155

Hình 66. Chọn cổng nạp từ Network

Nếu cổng OTA không hiện lên, bạn cần thoát Arduino IDE, và mở lại. Kiểm tra lại



port OTA. Nếu vẫn tiếp tục không hiển thị cổng OTA, kiểm tra tưòng lửa của máy

và các cài đặt trên router.

Bước 3: Sửa firmware mới và nạp lại thông qua WiFi

Sau khi đã chọn đúng cổng nạp OTA, bạn hoàn toàn có thể sửa lại firmware mới và nạp thông qua

WiFi, tuy nhiên cần lưu ý như sau:

• Firmware mới phải đảm bảo kết nối đến WiFi không bị mất (ví dụ cấp sai mật khẩu)

• Firmware mới phải có các hàm khởi tạo và xử lý OTA như Bước 1: nạp firmware hỗ trợ OTA thông

qua cổng Serial

https://thuviensach.vn

136/155

Hình 67. Nạp firmware thành công thông qua OTA

Sử dụng mật khẩu

Bảo vệ quá trình upload OTA với password là một quá trình khá đơn gỉản. Những việc bạn cần làm là bổ sung đoạn mã nguồn:

ArduinoOTA.setPassword((const char *)"your-password");

Sau đó upload lại sketch một lần nữa (dùng OTA). Sau khi biên dịch và upload xong, cửa sổ sẽ hiện lên yêu cầu nhập password:

Hình 68. Password cho OTA

Nhập password, nếu đúng, kết quả là thông báo Authenticating...OK và quá trình nạp diễn ra bình

thường.

Các lần nạp sau Arduino IDE sẽ nhớ mật khẩu và không hỏi lại, trừ khi bạn thay đổi mật khẩu OTA, và các bước xác thực không thành công, Arduino IDE sẽ hỏi lại bạn.

Cần lưu ý là password có thể dễ dàng thấy được, nếu IDE không được đóng sau lần upload cuối

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

137/155

cùng. Việc này có thể được thực hiện bằng cách cho phép Show verbose ouput during: upload trong

File > Preferences và upload lên module.

Những sự cố thường gặp

Nếu việc cập nhật OTA thất bại, bước đầu tiên bạn cần làm là kiểm tra phần báo lỗi hiện trên cửa sổ

Log của Arduino IDE. Nếu việc này không giúp được bạn, hãy upload lại khi kiểm tra các thông tin của ESP hiện trên serial port.

Các nguyên nhân phổ biến gây lỗi OTA như sau:

• Không đủ dung lượng bộ nhớ trên chip (ví dụ như ESP01 với 512KB bộ nhớ flash không đủ cho

OTA).

• Khu vực dữ liệu cho SPIFFS quá nhiều, không còn đủ để chưa firmware, trong trường hợp bạn có

4MB Flash thì trường hợp này không xảy ra.

• Khu vực bộ nhớ chưa firmware quá ít, tối thiểu là 512KB

• Không reset module ESP sau lần upload đầu dùng Serial Port.

https://thuviensach.vn

138/155

Cập nhật Firmware dùng Web Browser

Khi thực hiện cập nhật firmware dùng Web Browser, ESP8266 sẽ khởi động 1 HTTP Server, với 1 form

upload. Khi truy cập đúng địa chỉ của nó, bạn sẽ được cung cấp 1 giao diện để chọn file binary, và upload lên Chip. Việc này hữu dụng khi không dùng Arudino IDE cho việc cập nhật, sử dụng luôn trình duyệt sẵn có. Hoặc tích hợp vào 1 ứng dụng mà bạn có thể muốn cập nhật nó trong tương.

Cập nhật với web browser được thực hiện bằng thư viện ESP8266HTTPUpdateServer cùng với 2 thư

viện khác ESP8266WebServer và ESP8266mDNS cho việc nhận diện ESP8266 trong mạng nội bộ.

Thực hiện

Mở ví dụ: File > Examples > ESP8266HTTPUpdateServer > WebUpdater

#include <ESP8266WiFi.h>

#include <WiFiClient.h>

#include <ESP8266WebServer.h>

#include <ESP8266mDNS.h>

#include <ESP8266HTTPUpdateServer.h>

const char* host = "esp8266-webupdate";

const char* ssid = "...";

const char* password = "...";

ESP8266WebServer httpServer(80);

ESP8266HTTPUpdateServer httpUpdater;

void setup(void){

Serial.begin(115200);

Serial.println();

Serial.println("Booting Sketch...");

WiFi.mode(WIFI_AP_STA);

WiFi.begin(ssid, password);

while(WiFi.waitForConnectResult() != WL_CONNECTED){

WiFi.begin(ssid, password);

Serial.println("WiFi failed, retrying.");

}

MDNS.begin(host);

httpUpdater.setup(&httpServer);

httpServer.begin();

MDNS.addService("http", "tcp", 80);

Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host);

}

void loop(void){

httpServer.handleClient();

}

Cung cấp đúng SSID và mật khẩu mạng WiFi máy tính bạn đang dùng, nạp Firmware WebUpdater vào

ESP8266 Chọn Board ESP8266 WiFi Uno trong Arduino IDE và Nạp chương trình xuống board dùng

Arduino IDE

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

139/155



Lưu ý là máy tính phải sử dụng mạng WiFi cùng với ESP8266

Khi bạn không thể truy cập vào module ESP8266 theo công Serial, thì để nhận diện được địa chỉ IP

của module trong mạng LAN, bạn cần chạy dịch vụ mDNS trên máy tính. Dịch vụ này sẵn có trong

MacOS, tuy nhiên, với Linux thì bạn cần cài đặt Avahi: avahi.org/, còn Windows thì Bonjour:

support.apple.com/downloads/bonjour_for_windows

Với dịch vụ mDNS chạy trên máy tính, bạn dễ dàng truy cập vào ESP8266 theo đường dẫn esp8266-

webupdate.local/update

Hình 69. Giao diện Web cập nhật firmware

Bằng cách chọn file và nhấn cập nhật, ESP8266 sẽ tiến hành cập nhật firmware mới do bạn gởi lên.

File này có thể được xuất ra bằng cách Sketch > Export compiled Binary, và file .bin sẽ nằm trong thư

mục của Sketch

Hình 70. Xuất file Binary

https://thuviensach.vn

140/155

Khi đã nhập esp8266-webupdate.local/update mà không thưc hiện được, hãy thay esp8266-webupdate với địa chỉ IP của module (bạn có thể xem trong



modem/router, hay Serial Terminal). Ví dụ, nếu IP của module là 192.168.1.100 thì

URL phải là 192.168.1.100/update. Phương pháp này hữu hiệu trong trường hợp host software cài đặt ở bước 1 không hoạt động.

Nếu các bước diễn ra thành công tốt đẹp, thì trên trình duyệt và cửa sổ Serial Terminal (nếu mở) như

hình

Hình 71. Thực hiện thành công cập nhật Firmware sử dụng WebUpdater

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

141/155

Bảo mật

Nếu bổ sung WebUpdater vào sản phẩm của mình, dĩ nhiên bạn sẽ không muốn người khác tự do đưa

vào thiết bị 1 firmware khác. Hãy sử dụng hàm httpUpdater.setup(&httpServer, update_path,

update_username, update_password); với các thông số username, password mà bắt buộc bạn phải

nhập đúng mới được phép upload firmware mới.

Mở ví dụ : File > Examples > ESP8266HTTPUpdateServer > SecureWebUpdater để xem chi tiết

https://thuviensach.vn

142/155

HTTP Server

Với 2 phương pháp trước, bạn dễ dàng cập nhật Firmware thông qua mạng WiFi nội bộ. Tuy nhiên, khi triển khai ứng dụng thực tế, chúng ta sẽ cần cập nhật Firmware từ xa thông qua Internet, và cần 1

Server để lưu trữ firmware, quản lý các phiên bản.

Một kịch bản phổ thông thường được làm nhất đó là:

• Khi ESP8266 khởi động (khoảng sau 1 khoảng thời gian - ví dụ như 1 ngày), nó sẽ kết nối đến

Server, cung cấp thông tin phiên bản hiện có của nó

• Server khi nhận thấy phiên bản hiện tại cần phải được nâng cấp, nó sẽ trả về firmware mới

• Nếu phiên bản hiện tại của ESP8266 không cần phải cập nhật, nó sẽ trả về mã 304.

Để thực hiện được điều này, chúng ta cần thực hiện trên cả ESP8266 và trên Server side. Thử nghiệm trong mục này, chúng ta sẽ dùng Node.js làm server. Bạn hoàn toàn có thể thực thi đoạn code

Server này và gán cho nó domain để có thể truy cập từ bất kỳ đâu.

ESP8266 ESPhttpUpdate

Bằng cách thực thi ESPhttpUpdate.update("your-domain.com", 8000, "/fimrware.bin");, ESP8266 sẽ tự

động kết nối tới server ở địa chỉ your-domain.com:8000/fimrware.bin để tải phiên bản firmware mới về. Mã HTTP Status Code:

• (Mã) 200: Nếu tồn tại firmware mới, và nội dung file sẽ được gởi kèm sau đó

• (Mã) 304: Thông báo là không có bản update mới.

Đoạn mã có thể dễ dàng tìm thấy ở File > Examples > ESPhttpUpdate > httpUpdate

Bạn cần cung cấp SSID, mật khẩu WiFi chính xác, thực hiên Chọn Board ESP8266 WiFi Uno trong

Arduino IDE và Nạp chương trình xuống board dùng Arduino IDE

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

143/155

#include <Arduino.h>

#include <ESP8266WiFi.h>

#include <ESP8266HTTPClient.h>

#include <ESP8266httpUpdate.h>

const char* ssid = "...";

const char* password = "...";

const char *currentVersion = "1.0"; ①

const char *serverUrl = "http://192.168.0.106:8000/firmware.bin"; ②

void setup() {

Serial.begin(115200);

Serial.println();

Serial.println();

Serial.print("ESP8266 http update, current version: ");

Serial.println(currentVersion);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

t_httpUpdate_return ret = ESPhttpUpdate.update(serverUrl, currentVersion);

switch (ret) {

case HTTP_UPDATE_FAILED:

Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(),

ESPhttpUpdate.getLastErrorString().c_str());

break;

case HTTP_UPDATE_NO_UPDATES:

Serial.println("HTTP_UPDATE_NO_UPDATES");

break;

case HTTP_UPDATE_OK:

Serial.println("HTTP_UPDATE_OK");

break;

}

}

void loop() {

}

① Phiên bản firmware của bạn, giả sử bạn thay đổi là 2.0 và đặt lên server, sau đó bạn đổi lại 1.0 và nạp vào board

② Đường dẫn đến firmware của bạn, là địa chỉ web, ip, hay domain

https://thuviensach.vn

144/155

Node.js OTA Server

Khi ESP8266 kết nối tới Web Server, thì nó sẽ cung cấp các thông tin Header để Server căn cứ vào đó đánh giá firmware có cần phải cập nhật hay không. Ví dụ về các header

[HTTP_USER_AGENT] => ESP8266-http-Update

[HTTP_X_ESP8266_STA_MAC] => 18:FE:AA:AA:AA:AA

[HTTP_X_ESP8266_AP_MAC] => 1A:FE:AA:AA:AA:AA

[HTTP_X_ESP8266_FREE_SPACE] => 671744

[HTTP_X_ESP8266_SKETCH_SIZE] => 373940

[HTTP_X_ESP8266_SKETCH_MD5] => a56f8ef78a0bebd812f62067daf1408a

[HTTP_X_ESP8266_CHIP_SIZE] => 4194304

[HTTP_X_ESP8266_SDK_VERSION] => 1.3.0

[HTTP_X_ESP8266_VERSION] => 1.0

Dựa trên kiến thức phần Server Nodejs, chúng ta xây dựng 1 OTA Server dùng Node.js như sau server.js

var fs = require('fs');

var url = require('url');

var http = require('http');

var querystring = require('querystring');

var crypto = require('crypto');

// function g ử i y ê u c ầ u(response) t ừ ph í a server ho ặ c nh ậ n y ê u c ầ u (request) c ủ a client g ử i l ê n function requestHandler(request, response) {

// Gi ả s ử đị a ch ỉ y ê u c ầ u firmware http://192.168.1.7:8000/firmware.bin var uriData = url.parse(request.url);

var pathname = uriData.pathname; // /firmware.bin

if (pathname == '/firmware.bin') {

var ver = request.headers['x-esp8266-version'];

console.log('Client request update, version ', ver);

if(ver == '1.0') {

console.log('Send firmware 2.0 to client');

fs.readFile('./esp8266-firmware-2.0.bin', function(error, content) {

response.writeHead(200, {

'Content-Type': 'binary/octet-stream',

'Content-Length': Buffer.byteLength(content),

'x-MD5': crypto.createHash('md5').update(content).digest("hex")

});

response.end(content);

});

} else {

response.statusCode = 304;

response.end();

}

}

}

var server = http.createServer(requestHandler);

server.listen(8000);

console.log('Server listening on port 8000');

Thực thi node server.js để khởi động Server

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

145/155



Khi bạn làm việc với các ngôn ngữ lập trình khác, luôn phải đảm bảo khi gởi về

client cần có đầy đủ thông tin header Content-Length và x-MD5



Bạn cần file esp8266-firware-2.0.bin ở mục ESP8266 ESPhttpUpdate biên dịch

với currentVersion = "2.0" đặt cùng thư mục với file server.js

Nếu bạn thực hiện đầy đủ các bước như trên, kết quả thực thi sẽ như hình

Hình 72. Kết quả thực hiện OTA sử dụng HTTP Server

https://thuviensach.vn

146/155

Cheatsheet

Phần này cung cấp thông tin cho việc tra cứu nhanh các hàm có thể sử dụng với Arduino, ESP8266

và ngôn ngữ lập trình C. Có rất nhiều thư viện cho Arduino cung cấp các tính năng hữu ích thông qua các API cho phép người sử dụng gọi, nội dung tóm lược ở đây chỉ đề cập tới các thư viện thường

xuyên được sử dụng nhất. Nếu bạn sử dụng các thư viện khác, hoàn toàn có thể tra cứu dễ dàng

trong tài liệu sử dụng của thư viện đó. Thông thường các thư viện được phát hành nguồn mở trên

Github sẽ có file README.md cung cấp đầy đủ các thông tin.

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

147/155

Arduino - ESP8266 Cheatsheet

/* C Ấ U TR Ú C C Ơ B Ả N C Ủ A 1 SKETCH */

/* D Ữ LI Ệ U KI Ể U CHU Ỗ I */

void setup() {

/* Chu ỗ i bao g ồ m k í t ự k ế t th ú c chu ỗ i \0 (null) */

/*

char str1[8] = {'A','r','d','u','i','n','o','\0'};

H à m đượ c g ọ i khi b ắ t đầ u sketch. D ù ng để kh ở i t ạ o

/* Tr ì nh bi ê n d ị ch t ự độ ng th ê m k í t ự \0 v à o cu ố i bi ế n, c ấ u h ì nh ch â n, kh ở i t ạ o th ư vi ệ n...

chu ỗ i */

Code trong setup ch ỉ ch ạ y 1 l ầ n (khi kh ở i độ ng ho ặ c char str2[8] = {'A','r','d','u','i','n','o'};

reset board)

/* Khai b á o chu ỗ i ,kh ô ng khai b á o s ố ph ầ n t ử v à g á n gi á

*/

tr ị chu ỗ i*/

}

char str3[] = "Arduino";

void loop() {

/* Khai b á o v à g á n gi á tr ị cho chu ỗ i */

// N ộ i dung trong loop() l ặ p l ạ i li ê n t ụ c

char str4[8] = "Arduino";

}

/* D Ữ LI Ệ U KI Ể U M Ả NG */

/* L Ệ NH R Ẻ NH Á NH */

/* Khai b á o m ả ng ki ể u int c ó 6 ph ầ n t ử v à g á n gi á tr ị

if (x < 5) // th ự c thi code n ế u x<5

cho m ỗ i ph ầ n t ử */

{ code }

int myPins[] = {2, 4, 8, 3, 6};

else if (x > 10) // th ự c thi code n ế u x>10

/* M ả ng ki ể u int 6 ph ầ n t ử v à kh ô ng g á n gi á tr ị */

{ code }

int myInts[6];

else { code } // th ự c thi code c á c tr ườ ng h ợ p c ò n l ạ i myInts[0] = 42; // G á n gi á tr ị 42 cho ph ầ n t ử đầ u ti ê n myInts[6] = 12; // L Ỗ I ! ch ỉ s ố c ủ a m ả ng ch ỉ t ừ 0 đế n 5

switch (var) { // th ự c thi case c ó gi á tr ị var

case 1:

/*Qualifiers*/

...

static // Kh ô ng thay đổ i gi á tr ị ở c á c l ầ n g ọ i break;

volatile // In RAM (Th ườ ng d ù ng trong ng ắ t)

case 2:

const // Kh ô ng đổ i (ch ỉ đọ c)

...

PROGMEM /* Cho ph é p l ư u tr ữ d ữ li ệ u trong b ộ nh ớ

break;

FLASH thay v ì SRAM */

default:

...

/* C Á C TO Ả N T Ử , PH É P TO Á N TH ƯỜ NG D Ù NG */

}

/* C á c to á n t ử th ườ ng d ù ng */

= toán tử bằng

/* C Á C KI Ể U V Ò NG L Ặ P */

+ toán tử cộng

/* Th ự c hi ệ n code n ế u x<5 */

- toán tử trừ

while (x < 5) { code };

* toán tử nhân

/* Th ự c hi ệ n code, so s á nh, n ế u x<0 ti ế p t ụ c th ự c hi ệ n

/ toán tử chia lấy phần nguyên

code */

% toán tử chia lấy phần dư

do { code } while(x < 0);

== phép so sánh bằng

/* Kh ở i t ạ o i, th ự c hi ệ n code v à t ă ng i n ế u i < 10 */

!= phép so sánh không không bằng (khác)

for (int i = 0; i < 10; i++) { code };

< phép so sánh nhỏ hơn

/* Tho á t ra v ò ng l ặ p (for, while, do-while) ngay l ậ p

> phép so sánh lớn hơn

t ứ c */

<= phép so sánh nhỏ hơn hoặc bằng

break;

>= phép so sánh lớn hơn hoặc bằng

/* Đ i đế n chu k ì l ặ p ti ế p theo c ủ a v ò ng l ặ p hi ệ n t ạ i */

&& phép toán logic (AND)

continue;

|| phép toán logic (OR)

! phép toán logic (NOT)

/* C Á C ĐỊ NH NGH Ĩ A V Ề H À M*/

<ret. type> <name>(<params>) { ... }

/* C á c to á n t ử h ợ p nh ấ t */

int func_name(int x) { return x*2; }

++ tăng 1 đơn vị

return x; // x ph ả i tr ù ng kh ớ p v ớ i ki ểủ tr ả v ề c ủ a h à m

-- giảm 1 đơn vị

return; // lo ạ i return d à nh cho h à m void

+= phép toán cộng và gán giá trị

ex: x = 5; x+= 1; //x = 6

/* INCLUDE */

-= phép toán trừ và gán giá trị

/* include th ư vi ệ n chu ẩ n */

ex: x = 5; x-= 1; //x = 4

#include <stdio.h>

*= phép toán nhân và gán giá trị

/* include th ư vi ệ n t ạ o b ở i ng ườ i d ù ng */

ex: x = 5; x*= 3; //x = 15

#include "your-library.h"

/= phép toán chia lấy phần nguyên và gán giá trị

ex: x = 6; x/= 2; //x = 3

https://thuviensach.vn

148/155

ex: x = 6; x/= 2; //x = 3

analogWrite(pin, value)

&= phép toán logic AND và gán giá trị

/* ESP8266: thay đổ i RANGE PWM output */

ex: x = 0b1010; x&= 0110; //x =0b0010

analogWriteRange(new_range)

|= phép toán logic OR và gán giá trị

/* ESP8266: T ầ n s ố PWM output */

ex: x = 0b1010; x&= 0110; //x =0b1110

analogWriteFreq(new_frequency)

/* C á c to á n t ử tr ê n bit */

/* ADVANCED I/O */

& and ^ xor

/* T ạ o s ó ng vu ô ng t ầ n s ố freq_Hz v ớ i duty cycle=50% */

<< dịch trái >> dịch phảii

tone(pin, freq_Hz)

| or ~ not

/* T ạ o s ó ng vu ô ng t ầ n s ố freq_Hz, duration mili gi â y */

tone(pin, freq_Hz, duration_ms)

/* Th ự c thi v ớ i con tr ỏ */

/* Ng ừ ng vi ệ c t ạ o s ó ng vu ô ng khi d ù ng tone() */

&reference: // l ấ y đị a ch ỉ c ủ a bi ế n m à con tr ỏ tr ỏ t ớ i noTone(pin)

*dereference: // l ấ y gi á tr ị c ủ a bi ế n m à con tr ỏ tr ỏ t ớ i

/* D ị ch 1 byte, m ỗ i l ầ n d ị ch 1 bit, d ị ch t ừ bit cao */

shiftOut(dataPin, clockPin,[MSBFIRST, LSBFIRST], value)

/* H Ằ NG S Ố V À KI Ể U D Ữ LI Ệ U */

/* Tr ả v ề (ms) c ủ a xung HIGH/LOW tr ê n ch â n pin */

123 Số thập phân

unsigned long pulseIn(pin,[HIGH, LOW])

0b0111 Số nhị phân

0173 Số Octal - base 8

/* CH Ứ C N Ă NG NG Ắ T */

0x7B Số thập lục phân base 16

/* Thi ế t l ậ p ch ứ c n ă ng ng ắ t ở c á c ch â n digital */

123U Số nguyên không dấu

attachInterrupt(interrupt, func, mode)

123L Số nguyên có dấu 4 bytes

/*

123UL Số nguyên không dấu 4bytes

interrupt: s ố ng ắ t (th ườ ng l à ch â n s ử d ụ ng ch ứ c n ă ng 123.0 Số thực

ng ắ t)

1.23e6 Số thực dùng cơ số mũ ex: 1.23*10^3 = 1230

func : h à m s ẽ đượ c g ọ i khi ng ắ t x ả y ra (l ư u ý : h à m kh ô ng c ó tham s ố đầ u v à o c ũ ng nh ư ki ể u tr ả v ề )

/*PH Ạ M VI C Ủ A KI Ể U D Ữ LI Ệ U */

mode : g ồ m c á c ch ế độ LOW,CHANGE, RISING, FALLING. Ng ắ t boolean true | false

s ẽ đượ c k í ch ho ạ t khi ch â n ng ắ t ở mode t ươ ng ứ ng char -128 - 127, 'a' '$' etc.

*/

unsigned char 0 - 255

/* V ô hi ệ u h ó a ng ắ t interrupt */

byte 0 - 255

detachInterrupt(interrupt)

int -32768 - 32767

/* V ô hi ệ u h ó a t ấ c ả c á c ng ắ t */

unsigned int 0 - 65535

noInterrupts()

word 0 - 65535

/* Cho ph é p t á i ng ắ t sau khi d ù ng noInterrupts() */

long -2147483648 - 2147483647

interrupts()

unsigned long 0 - 4294967295

float -3.4028e+38 - 3.4028e+38

/*************************************************

double -3.4028e+38 - 3.4028e+38

* TH Ư VI Ệ N PH Ổ BI Ế N *

void i.e., no return value

*************************************************/

/* KHAI B Á O BI Ế N */

/*************************************************

int a;

* Serial *

int a = 0b01111011, b = 0123, c = 1, d;

*Th ư vi ệ n giao ti ế p v ớ i PC ho ặ c th ô ng qua RX/TX*

float fa = 1.0f;

*************************************************/

double da = 1.0;

/* Thi ế t l ậ p giao ti ế p serial-UART v ớ i t ố c độ speed */

char *pointer;

begin(long speed)

char *other_pointer = NULL;

/* V ô hi ệ u h ó a giao ti ế p serial */

end()

/**

/* Tr ả v ề s ố bytes c ó s ẵ n để đọ c */

* BUILT-IN FUNCTIONS

int available()

* Pin Input/Output

/* đọ c d ữ li ệ u đế n t ừ serial (tr ả v ề byte đầ u ti ê n c ủ a

* Digital I/O - pins 0-13 A0-A5

d ữ li ệ u t ừ serial ho ặ c -1 n ế u d ữ li ệ u kh ô ng c ó */

*/

int read()

/* Thi ế t l ậ p c ấ u h ì nh ch â n */

/* Ch ờ qu á tr ì nh truy ề n d ữ li ệ u serial ho à n t ấ t */

pinMode(pin,[INPUT, OUTPUT, INPUT_PULLUP])

flush()

/* Đọ c gi á tr ị c ủ a pin_6 v à g á n cho a */

/* In ra serial port d ữ li ệ u data (v ớ i b ấ t k ì ki ể u d ữ

int a = digitalRead(pin_6);

li ệ u n à o đượ c thi ế t l ậ p */

/* C à i đặ t m ứ c HIGH/LOW cho pin_5 */

print(data)

digitalWrite(pin_5, [HIGH, LOW])

/* T ươ ng t ự nh ư print(data) nh ư ng sau khi in ra serial

/* Đọ c gi á tr ị c ủ a pin v à g á n cho a, pin t ừ A0-->A5 */

-port, con tr ỏ s ẽ xu ố ng d ò ng ti ế p theo */

int a = analogRead(pin)

println(data)

/* G ử i d ữ li ệ u value/string/array đế n serial port */

/* PWM ng õ ra - pins 3 5 6 9 10 11

write(byte)

* ESP8266: pin 0..16, range = 0..1023, 1KHz default

/* H à m đượ c g ọ i khi c ó d ữ li ệ u đế n t ừ ch â n RX */

*/

SerialEvent()

/* Đặ t gi á tr ị PWM cho pin */

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

149/155

/*************************************************

/* D ù ng khi ch ươ ng tr ì nh c ầ n th ự c thi nhi ề u t á c v ụ c ù ng

* Servo.h *

m ộ t l ú c, th ư vi ệ n h ỗ tr ợ <Scheduler.h> */

* Th ư vi ệ n h ỗ tr ợ đ i ề u khi ể n độ ng c ơ servo *

void yield();

*************************************************/

/* Reset chip ESP */

/*

void ESP.reset();

Thi ế t l ậ p ch â n k ế t n ố i v ớ i servo v à độ r ộ ng xung

/* Tr ả v ề k í ch th ướ c v ù ng nh ớ tr ố ng ở heap */

pin : Ch â n k ế t n ố i v ớ i servo

uint32_t ESP.getFreeHeap();

[min_uS, max_uS] : Độ r ộ ng xung t í nh theo us t ươ ng ứ ng

/* Tr ả v ề ID c ủ a chip ESP */

v ớ i g ó c xoay t ừ 0 đế n 180

uint32_t ESP.getChipId();

*/

attach(pin, [min_uS, max_uS])

/* CH Ế ĐỘ C Ấ U H Ì NH WIFI STATION */

/* Ghi d ữ li ệ u g ó c xoay cho độ ng c ơ angle t ừ 0~180 */

/* Thi ế t l ậ p ch ế độ station */

write(angle)

WiFi.mode(WIFI_STA);

/* Vi ế t gi á tr ị để đ i ề u khi ể n g ó c quay cho servo, gi á

/* K ế t n ố i đế n AP */

tr ị t ừ 700 ~ 2300 */

WiFi.begin(ssid, password);

writeMicroseconds(uS)

/* Ng ắ t k ế t n ố i đế n network wifi hi ệ n t ạ i */

/* Đọ c gi á tr ị g ó c xoay (0 đế n 180 độ ) */

bool WiFi.disconnect();

int read()

/* Tr ả v ề đị a ch ỉ IP c ủ a station */

/* Tr ả v ề true n ế u bi ế n servo đã k ế t n ố i đế n pin */

WiFi.localIP();

bool attached()

/* Tr ả v ề tr ạ ng th á i khi k ế t n ố i đế n AP */

/* G ỡ b ỏ bi ế n servo ra kh ỏ i ch â n đã k ế t n ố i */

WiFi.status();

detach()

/* Tr ả v ề t ê n c ủ a netwwork WiFi đã k ế t n ố i */

WiFi.SSID();

/*************************************************

/* Tr ả v ề c ườ ng độ c ủ a WiFi ( đơ n v ị dBm) */

* Wire.h *

WiFi.RSSI();

* D ù ng trong giao ti ế p I2C *

/* B ắ t đầ u thi ế t l ậ p ch ế độ WPS */

*************************************************/

WiFi.beginWPSConfig();

/* Master kh ở i t ạ o th ư vi ệ n Wire v ớ i giao ti ế p I2C */

/* B ắ t đầ u thi ế t l ậ p ch ế độ smart config */

begin()

WiFi.beginSmartConfig();

/* Slave tham gia v à o k ế t n ố i i2C, addr l à 7 bits đị a ch ỉ c ủ a slave */

/* CH Ế ĐỘ C Ấ U H Ì NH WIFI SOFT ACCESS POINT (AP) */

begin(addr)

/* Kh ở i t ạ o 1 AP v ớ i t ê n v à password */

/*

WiFi.softAP(ssid, password);

Master y ê u c ầ u 1 s ố byte t ừ slave:

/* Kh ở i t ạ o 1 AP v à thi ế t l ậ p c ấ u h ì nh cho AP g ồ m đị a address: 7bits đị a ch ỉ c ủ a slave.

ch ỉ IP, gateway v à subnet */

count: S ố l ượ ng byte master y ê u c ầ u

WiFi.softAPConfig (local_ip, gateway, subnet);

stop: Ki ể u boolean, n ế u true, master t í n hi ệ u stop sau

/* Tr ả v ề s ố station đã k ế t n ố i đế n AP */

khi y ê u c ầ u v à gi ả i ph ó ng bus I2C, n ế u false, master WiFi.softAPgetStationNum();

g ử i y ê u c ầ u restart để gi ữ k ế t n ố i

/* Ng ắ t k ế t n ố i c ủ a c á c station */

*/

WiFi.softAPdisconnect(wifioff);

requestFrom(address, count, stop)

/* Tr ả v ề đị a ch ỉ IP c ủ a AP */

/* G ử i t í n hi ệ u b ắ t đầ u, truy ề n d ữ li ệ u đế n slave c ó WiFi.softAPIP();

đị a ch ỉ addr */

/* Tr ả v ề đị a ch ỉ MAC c ủ a AP */

beginTransmission(addr)

WiFi.softAPmacAddress(mac);

/* G ử i d ữ li ệ u (1 byte) đế n slave */

send(byte)

/* WIFI FEATURES */

/* G ử i d ữ li ệ u (string) đế n slave */

/* SCAN */

send(char * string)

/* Thi ế t l ậ p ch ế độ Station */

/* G ử i d ữ li ệ u (1 m ả ng )v ớ i s ố byte l à size */

WiFi.mode(WIFI_STA);

send(byte * data, size)

/* Scan v à tr ả v ề s ố l ượ ng network avalable */

/* G ử i t í n hi ệ u k ế t th ú c truy ề n d ữ li ệ u t ớ i slave */

WiFi.scanNetworks();

endTransmission()

/* Tr ả v ề t ê n c ủ a network (ki ể u string) ở v ị tr í num */

/* Tr ả v ề s ố byte availabe sau khi đọ c b ở i read() */

WiFi.SSID(num).c_str();

int available()

/* Tr ả v ề th ô ng tin c ủ a t ấ t c ả c á c network */

/* truy xu ấ t đế n 1 byte đã truy ề n t ừ slave đế n master WiFi.getNetworkInfo(networkItem,&ssid,

ho ặ c truy ề n ở chi ề u ng ượ c l ạ i khi nh ậ n đượ c

&encryptionType, &RSSI,*&BSSID, &channel, &isHidden)

requestFrom. Tr ả v ề byte ti ế p theo đã nh ậ n đượ c */

byte receive()

/* DIAGNOSTICS */

/* H à m handler s ẽ đượ c g ọ i khi slave nh ậ n d ữ li ệ u */

/*

onReceive(handler)

* M ụ c đí ch : chu ẩ n đ o á n, cung c ấ p th ô ng tin v à kh ắ c

/* Handler s ẽ đượ c g ọ i khi master y ê u c ầ u d ữ li ệ u */

* ph ụ c s ự c ố khi kh ô ng k ế t n ố i đế n net work WiFi onRequest(handler)

*/

/* In ra serial c á c chu ẩ n đ o á n th ô ng tin c ủ a network */

/*************************************************

WiFi.printDiag(Serial);

* ESP8266 *

/* Enable ch ế độ debug */

*************************************************/

Serial.setDebugOutput(true);

https://thuviensach.vn

150/155

/* WEBSERVER */

mqtt.unSubscribe("/qos0");

/* M á y ch ủ TCP t ạ i port 80 s ẽ ph ả n h ồ i c á c HTTP request

/* Th ự c hi ệ n subscribe topic v à publish c á c message */

đượ c g ử i l ê n t ừ client */

mqtt.onSubscribe([](int sub_id)

ESP8266WebServer server (80);

/* Publish 1 message "qos0" đế n topic /qos0 v ớ i QoS =0,

/* Server b ắ t đầ u l ắ ng nghe c á c client */

v à Retain = 0 */

server.begin();

mqtt.publish("/qos0", "qos0", 0, 0);

/* Vi ế t d ữ li ệ u đế n c á c client */

/* K ế t n ố i đế n server MQTT */

server.write(buf, len)

mqtt.onConnect([]()

/* Kh ở i t ạ o server ở đị a ch ỉ URL, handleRoot l à n ộ i

/* Subscribe topic v à nh ậ n message t ạ i topic /qos0 */

dung ho ặ c h à m s ẽ th ự c hi ệ n */

mqtt.subscribe("/qos0", 0)

server.on ( "URL", handleRoot );

/* B ắ t đầ u truy ề n nh ậ n d ữ li ệ u v ớ i broker MQTT c ó url

/* Server t ươ ng t á c v ớ i client để g ử i, nh ậ n d ữ li ệ u */

mqtt://test.mosquitto.org t ạ i port 1883 */

server.handleClient();

mqtt.begin("mqtt://test.mosquitto.org:1883")

/* Tr ả v ề 1 n ế u bi ế n val c ó t ồ n t ạ i tr ê n server */

/* H à m đượ c g ọ i trong loop() nh ằ m kh ở i t ạ o MQTT, ki ể m server.hasArg(val)

tra x ử l í c á c d ữ li ệ u t ừ c á c topic, ki ể m tra c á c thu ộ c

/* L ấ y gi á tr ị c ủ a bi ế n val tr ê n server */

t í nh c ủ a giao th ứ c nh ư g ó i keep-a-live, QoS... */

server.arg(val);

mqtt.handle();

/* G ử i y ê u c ầ u c ậ p nh ậ t d ữ li ệ u t ừ server: code : HTTP code

/* C á c h à m c ủ a th ư vi ệ n PubSubClient*/

text/html : Đị nh d ạ ng tr ả v ề l à file HTML

/* Khai b á o bi ế n espClient thu ộ c đố i t ượ ng client trong content: N ộ i dung s ẽ tr ả v ề t ừ ph í a server */

class PubSubClient */

server.send (code, "text/html",content);

PubSubClient client(espClient);

/* Publish g ó i tin "Connected!" đế n topic ESP8266 */

/* MQTT */

client.publish("ESP8266", "Connected!");

/*

/* Subscribe để nh ậ n c á c message t ừ topic ESP8266 */

C á c th ư vi ệ n h ỗ tr ợ giao th ứ c MQTT d à nh cho ESP8266

client.subscribe("ESP8266");

tr ê n arduino th ườ ng s ử d ụ ng l à ESP8266MQTTClient

/* C à i đặ t server l ắ ng nghe client ở port 1883 */

v à PubSubClient. Ph ầ n n à y gi ả i th í ch c á c h à m c ủ a c á c client.setServer(url_server, 1883);

th ư vi ệ n

/* G ọ i h à m callback để th ự c hi ệ n c á c ch ứ c n ă ng

*/

publish/subcribe */

/* C á c h à m c ủ a th ư vi ệ n ESP8266MQTTClient*/

client.setCallback(callback);

/* Khai b á o 1 bi ế n mqtt thu ộ c class MQTTClient */

/* H à m đượ c g ọ i trong loop() nh ằ m kh ở i t ạ o MQTT, ki ể m MQTTClient mqtt;

tra

/* L ấ y d ữ li ệ u nh ậ n đượ c t ừ topic đã subcribe */

x ử l í c á c d ữ li ệ u t ừ c á c topic, ki ể m tra c á c thu ộ c t í nh mqtt.onData([](String topic, String data, bool cont)

c ủ a giao th ứ c nh ư g ó i keep-a-live, g ó i tin QoS... */

/* H ủ y subcribe topic /qos0 */

client.loop();

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

151/155

C - Cheatsheet

/* C Ấ U TR Ú C C Ơ B Ả N */

123L Số nguyên có dấu 4 bytes

Viết chú thích trên 1 dòng dùng //

123UL Số nguyên không dấu 4bytes

ex: x++ ; // t ă ng x 1 đơ n v ị

123.0 Số thực

/* */ Viết chú thích trên nhiều dòng.

1.23e6 Số thực dùng cơ số mũ ex: 1.23*10^3 = 1230

ex : /*************************

/* đị nh ngh ĩ a h ằ ng s ố a ki ể u nguy ê n, c ó gi á tr ị l à 1 */

* Ch ú th í ch đượ c vi ế t *

const int a = 1;

* tr ê n nhi ề u d ò ng *

/* Đị nh ngh ĩ a h ằ ng s ố x ki ể u th ự c, c ó gi á tr ị l à 4.0 */

************************/

const float x = 4;

/* C Ấ U TR Ú C 1 CH ƯƠ NG TR Ì NH */

/* Đị nh ngh ĩ a h ằ ng s ố c ki ể u integer c ó gi á tr ị 49 */

#include <stdio.h>//include th ư vi ệ n chu ẩ n c ủ a C

const c = ‘1’; // K í t ự 1 trong m ã ASCII l à 49

#include "iLib.h" //include th ư vi ệ n t ạ o b ở i ng ườ i d ù ng

/* Đị nh ngh ĩ a str l à h ằ ng s ố ki ể u con tr ỏ , tr ỏ t ớ i int global_var; //bi ế n đượ c d ù ng trong ch ươ ng tr ì nh chu ỗ i “Cheasheet C” */

/* Khai b á o h à m b ắ t đầ u c ủ a 1 ch ươ ng tr ì nh C v ớ i ki ể u const char * str = “Cheasheet C”;

tr ả v ề l à integer. Đố i s ố arg ki ể u int đượ c truy ề n v à o h à m */

/* KHAI B Á O BI Ế N */

int main (int arg){

/* Khai b á o bi ế n a ki ể u nguy ê n v à kh ô ng g á n gi á tr ị */

float local_var ; // Bi ế n ch ỉ đượ c d ù ng trong h à m main int a;

Lệnh 1

/* khai b á o a ki ể u binary, b ki ể u base8, c ki ể u s ố

...

nguy ê n, d ki ể u s ố nguy ê n v à kh ô ng g á n gi á tr ị */

Lệnh n ;

int a = 0b01111011, b = 0123, c = 1, d;

return 0; //ch ươ ng tr ì nh th ự c hi ệ n th à nh c ô ng v à tho á t

/* Khai b á o bi ế n fa thu ộ c ki ể u s ố th ự c float */

}

float fa = 1.0f;

/* Khai b á o bi ế n da thu ộ c ki ể u s ố th ự c double */

/*KI Ể U D Ữ LI Ệ U V À PH Ạ M VI */

double da = 1.0;

boolean true | false

/* Khai b á o bi ế n con tr ỏ v à tr ỏ đế n 1 v ù ng nh ớ kh ô ng char -128 - 127, 'a' '$' etc.

x á c đị nh */

unsigned char 0 - 255

char *pointer;

byte 0 - 255

/* Khai b á o bi ế n con tr ỏ v à tr ỏ v ề NULL (0)*/

int -32768 - 32767

char *other_pointer = NULL;

unsigned int 0 - 65535

word 0 - 65535

/* CHU Ỗ I K Í T Ự */

long -2147483648 - 2147483647

/* Chu ỗ i bao g ồ m k í t ự k ế t th ú c chu ỗ i \0 (null) */

unsigned long 0 - 4294967295

char str1[8] = {'A','r','d','u','i','n','o','\0'};

float -3.4028e+38 - 3.4028e+38

/* Tr ì nh bi ê n d ị ch t ự độ ng th ê m k í t ự \0 v à o cu ố i double -3.4028e+38 - 3.4028e+38

chu ỗ i */

void i.e., no return value

char str2[8] = {'A','r','d','u','i','n','o'};

/* Khai b á o chu ỗ i ,kh ô ng khai b á o s ố ph ầ n t ử v à g á n gi á

/* ĐẶ T T Ê N BI Ế N */

tr ị chu ỗ i */

/* Đặ t t ê n đú ng */

char str3[] = "Arduino";

int x; // M ộ t bi ế n

/* Khai b á o v à g á n gi á tr ị cho chu ỗ i */

int x = 1; // Bi ế n đượ c khai b á o v à kh ở i t ạ o char str4[8] = "Arduino";

float x, y, z; // Nhi ề u bi ế n c ù ng ki ể u d ữ li ệ u const int x = 88; // Bi ễ n t ĩ nh, kh ô ng ghi đượ c

/* C á c h à m x ử l í chu ỗ i th ườ ng d ù ng */

int tenBien1ok; // Đặ t t ê n bi ế n n à y đú ng

/* N ố i c á c k í t ự t ừ chu ỗ i source ti ế p v à o v ị tr í cu ố i int ten_bien_nay_ok;

c ủ a chu ỗ i dest */

/* Đặ t t ê n sai */

strcat(dest, source)

int 2001_tensai; // V ì s ố ở đầ u

/* T ì m v ị tr í xu ấ t hi ệ n đầ u ti ê n c ủ a k í t ự c trong int ten-sai; // D ấ u '-' kh ô ng ph ả i l à alphanumberic source, tr ả v ề con tr ỏ ch ỉ t ớ i v ị tr í đó ho ặ c null n ế u int while; // Sai, v ì d ù ng t ừ kh ó a v ò ng l ặ p while kh ô ng t ì m th ấ y c trong source */

strchr(source, c)

/* H Ằ NG S Ố V À KI Ể U D Ữ LI Ệ U */

/* H à m tr ả v ề độ d à i c ủ a chu ỗ i st */

123 Số thập phân

strlen(st)

0b0111 Số nhị phân

/* copy v à thay c á c k í t ự c ủ a chu ỗ i soure v à o dest */

0173 Số Octal - base 8

strcpy(dest, source)

0x7B Số thập lục phân base 16

/* ch é p k í t ự t ừ đầ u đế n n t ừ chu ỗ i source v à o dest */

123U Số nguyên không dấu

strncpy(dest, source, n)

https://thuviensach.vn

152/155

/* M Ả NG */

/* for : Kh ở i t ạ o v à g á n gi á tr ị cho i, th ự c hi ệ n code

/* Khai b á o m ả ng 1 chi ề u 6 ph ầ n t ử ki ể u integer v à g á n t ă ng i n ế u i < 10 */

gi á tr ị cho m ỗ i ph ầ n t ử */

for (int i = 0; i < 10; i++) { code };

int myPins[] = {2, 4, 8, 3, 6};

/* Khai b á o m ả ng 1 chi ề u 6 ph ầ n t ử ki ể u integer v à

/* PH É P TO Á N V À TO Á N T Ử TH ƯỜ NG D Ù NG

kh ô ng g á n gi á tr ị */

/* C á c to á n t ử th ườ ng d ù ng */

int myInts[6];

= toán tử bằng

myInts[0] = 42; // G á n gi á tr ị 42 cho ph ầ n t ử đầ u ti ê n

+ toán tử cộng

myInts[6] = 12; // L Ỗ I ! ch ỉ s ố c ủ a m ả ng ch ỉ t ừ 0 đế n 5

- toán tử trừ

/* L ấ y gi á tr ị c ủ a ph ầ n t ử th ứ 3 trong m ả ng myInts */

* toán tử nhân

int c = myInts[2]; // C ó th ể d ù ng *(myInts + 2)

/ toán tử chia lấy phần nguyên

/* L ấ y đị a ch ỉ c ủ a ph ầ n t ử th ứ 3 trong m ả ng myInts */

% toán tử chia lấy phần dư

int c = &myInts[2]; // C ó th ể d ù ng int c = myInts + int

== phép so sánh bằng

/* Tr ả v ề chi ề u d à i c ủ a m ả ng myInts */

!= phép so sánh không không bằng (khác)

int length = sizeof(myInts) / sizeof(myInts[0]);

< phép so sánh nhỏ hơn

/* Khai b á o 2 m ả ng ki ể u float, arr1 c ó 5 ph ầ n t ử , arr2

> phép so sánh lớn hơn

c ó 10 ph ầ n t ử */

<= phép so sánh nhỏ hơn hoặc bằng

float arr1[5], arr2[10];

>= phép so sánh lớn hơn hoặc bằng

/* Khai b á o m ả ng s ố nguy ê n arr c ó 2 d ò ng, 5 c ộ t. T ổ ng

&& phép toán logic (AND)

c ộ ng c ó 10 ph ầ n t ử */

|| phép toán logic (OR)

int a[2][5];

! phép toán logic (NOT)

/* KH Ố I L Ệ NH V À C Á C L Ệ NH D Ù NG TRONG V Ò NG L Ặ P */

/* C á c to á n t ử h ợ p nh ấ t */

{} // bao g ồ m nhi ề u l ệ nh, th ườ ng đượ c s ử d ụ ng trong h

++ tăng 1 đơn vị

à m

-- giảm 1 đơn vị

/* Goto : ch ươ ng tr ì nh s ẽ nh ả y đế n nh ã n (nh ã n ph ả i c ó

+= phép toán cộng và gán giá trị

m ặ t trong c â u l ệ nh ch ứ a goto) */

ex: x = 5; x+= 1; //x = 6

goto nhãn;

-= phép toán trừ và gán giá trị

/* Continue : Ch ỉ d ù ng trong c á c l ệ nh c ó v ò ng l ặ p s ẽ

ex: x = 5; x-= 1; //x = 4

chuy ể n qua chu k ì m ớ i c ủ a v ò ng l ặ p trong c ù ng nh ấ t */

*= phép toán nhân và gán giá trị

continue; /*

ex: x = 5; x*= 3; //x = 15

/* Break : D ù ng v ớ i c á c v ò ng l ặ p tho á t kh ỏ i v ò ng l ặ p

/= phép toán chia lấy phần nguyên và gán giá trị

trong c ù ng nh ấ t, ho ặ c d ù ng trong c ấ u tr ú c switch..case ex: x = 6; x/= 2; //x = 3

để tho á t ra kh ỏ i case t ươ ng ứ ng */

&= phép toán logic AND và gán giá trị

break; /*

ex: x = 0b1010; x&= 0110; //x =0b0010

/* Return */

|= phép toán logic OR và gán giá trị

/* D ù ng cho h à m kh ô ng c ó ki ể u tr ả v ề (void) */

ex: x = 0b1010; x&= 0110; //x =0b1110

return;

/* Value c ó th ể l à h ằ ng s ố , bi ế n, bi ể u th ứ c ho ặ c g ọ i

/* C á c to á n t ử tr ê n bit */

đế n 1 h à m kh á c để tr ả v ề gi á tr ị */

& and ^ xor

return <value>;

<< dịch trái >> dịch phảii

| or ~ not

/* L Ệ NH R Ẻ NH Á NH */

if (x < 5) // th ự c thi code n ế u x<5

/* TH Ự C THI V Ớ I CON TR Ỏ */

{ code }

&reference: // l ấ y đị a ch ỉ c ủ a bi ế n m à con tr ỏ tr ỏ t ớ i else if (x > 10) // th ự c thi code n ế u x>10

*dereference: // l ấ y gi á tr ị c ủ a bi ế n m à con tr ỏ tr ỏ t ớ i

{ code }

/* khai b á o bi ế n con tr ỏ ki ể u int tr ỏ t ớ i đị a ch ỉ c ủ a else { code } // th ự c thi code c á c tr ườ ng h ợ p c ò n l ạ i bi ế n a */

int a = 5; int *pointer = &a;

switch (var) { // th ự c thi case c ó gi á tr ị var

case 1:

/* C Á C K Í T Ự Đ I Ề U KHI Ể N V À K Í T Ự ĐẶ C BI Ệ T */

...

\n Nhảy xuống dòng kế tiếp canh về cột đầu tiên

break;

\t Canh cột tab ngang.

case 2:

\r Nhảy về đầu hàng, không xuống hàng.

...

\a Tiếng kêu bip.

break;

\\ In ra dấu \

default:

\" In ra dấu "

...

\' In ra dấu '

}

%%: In ra dấu %

\b ~ backspace (xóa 1 ký tự ngay trước)

/* C Á C KI Ể U V Ò NG L Ặ P */

/* While: Th ự c hi ệ n code n ế u x<5 */

/* H À M V À C Á C V Ấ N ĐỀ LI Ê N QUAN */

while (x < 5) { code };

/* Khai b á o prototype c ủ a h à m max, c ó 2 đố i s ố đầ u v à o

/* Do-While : Th ự c hi ệ n code, so s á nh, n ế u x<0 ti ế p t ụ c l à a v à b thu ộ c ki ể u s ố nguy ê n, k ế t qu ả tr ả v ề c ủ a h à m th ự c hi ệ n code */

ki ể u s ố nguy ê n */

do { code } while(x < 0);

int max(int a, int b);

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

153/155

/* Khai b á o bi ế n c l à gi á tr ị tr ả v ề c ủ a h à m max */

SINHVIEN */

int c = max(5,4);

typedef struct sinhVien SINHVIEN;

/* Khai b á o prototype c ủ a h à m kh ô ng c ó đố i s ố v à kh ô ng

/* Khai b á o bi ế n sinhVienA thu ộ c struct SINHVIEN */

c ó ki ể u tr ả v ề (void) */

SINHVIEN sinhVienA;

void none();

/* C Á C L Ệ NH X Ử L Ý T Ậ P TIN (#include <stdio.h>) */

/* TYPEDEF- Đị nh ngh ĩ a ki ể u d ữ li ệ u */

/* Khai b á o 1 bi ế n con tr ỏ l à đườ ng d ẫ n c ủ a 1 file */

/* Đị nh ngh ĩ a ki ể u unsigned char l à BYTE, khai b á o c á c const char *filePath = "Đường/dẫn/file/document.txt";

bi ế n a, b thu ộ c ki ể u BYTE */

/* T ạ o 1 bi ế n con tr ỏ thu ộ c ki ể u FILE */

typedef unsigned char BYTE; BYTE a, b;

FILE *file;

/* M ở 1 file ở đườ ng d ẫ n filePath v à đọ c d ữ li ệ u */

/* KI Ể U LI Ệ T K Ê - ENUMERATION (enum) */

file = fopen(filePath, "r"); // Tr ả v ề NULL n ế u th ấ t b ạ i

/* khai b á o ki ể u d ữ li ệ u enum l à c á c ng à y trong tu ầ n */

/* Đó ng 1 file đã m ở , tr ả v ề 0 n ế u th à nh c ô ng , ng ượ c enum daysOfWeek { sunday, monday, tuesday, wednesday };

l ạ i tr ả v ề EOF */

/* T ạ o bi ế n toDay thu ộ c daysOfWeek v à g á n gi á tr ị */

fclose(file);

daysOfWeek toDay = wednesday;

/* Vi ế t k í t ự c l ê n file đ ang m ở , tr ả v ề EOF n ế u ghi th ấ t b ạ i, tr ả v ề m ã ASCII c ủ a c n ế u th à nh c ô ng */

/* STRUCT - KI Ể U D Ữ LI Ệ U DO NG ƯỜ I D Ù NG ĐỊ NH NGH Ĩ A */

int fputc(int c, FILE *f);

/* Khai b á o struct sinhVien */

/* Vi ế t chu ỗ i "hello" l ê n file đ ang m ở */

struct sinhVien{

int c = fputs("hello", file);

char tenSinhVien;

/* Đọ c (255-1) k í t ự t ừ file đ ang m ở , k ế t qu ả đọ c char MSSinhVien;

đượ c

int tuoiSinhVien;

s ẽ l ư u v à o m ả ng str, vi ệ c đọ c b ị d ừ ng n ế u g ặ p k í t ự

};

'\n' ho ặ c EOL */

/* Truy xu ấ t đế n th à nh ph ầ n MSSinhVien trong struct

fgets(str, 255, file);

sinhVien */

/* Thay đổ i v ị tr í tr ỏ đế n trong file c ủ a con tr ỏ

sinhVien.MSSinhVien;

internal file position indicator v ề l ạ i đầ u file */

/* Đổ i t ê n struct sinhVien th à nh 1 bi ế n duy nh ấ t l à int fseek(file, 0, SEEK_SET);

/* Tr ả v ề k í ch th ướ c c ủ a n ộ i dung c ó trong file */

ftell(file);

www.cheatography.com/ashlyn-black/cheat-sheets/c-reference/

https://thuviensach.vn

154/155

Lời kết

Các thành viên tham gia đóng góp.

Để hoàn thiện nội dung của sách còn có sự đóng góp của các thành viên sau:

• 1. Phạm Minh Tuấn (TuanPM) - Chủ biên

• 2. Lâm Nhật Quân - Kĩ sư làm việc tại IoT Maker Việt Nam.

• 3. Trịnh Hoàng Đức - Kĩ sư làm việc tại IoT Maker Việt Nam.

• 4. Lê Phương Trình - Thực tập sinh tại IoT Maker Việt Nam - Sinh viên Đại Học Bách Khoa, chuyên ngành điện tử viễn thông, khóa học 2014.

• 5. Trần Phúc Vinh - Thực tập sinh tại IoT Maker Việt Nam - Sinh viên Đại Học Bách Khoa,

chuyên ngành kĩ thuật điện, khóa học 2014.

Và sự đóng góp của cộng đồng tại arduino.esp8266.vn

Lời kết.

Thật vui khi bạn đã đồng hành cùng chúng tôi đi đến hết cuốn sách này. Mục đích của cuốn sách là

giúp những người mới bắt đầu tìm hiểu về Internet Of Things (IoT) có kiến thức cơ bản và hướng đi chính xác để nghiên cứu về IoT một cách nhanh chóng hơn. Hi vọng cuốn sách sẽ đến tay thật nhiều

bạn đam mê lĩnh vực công nghệ còn mới mẻ nhưng rất tiềm năng này. Chúc các bạn thành công trên

con đường mà mình đã chọn.

Mặc dù đã cố gắng để hoàn thành tốt nhất nội dung cho cuốn sách, tuy nhiên vẫn không tránh khỏi

những thiếu sót. Mọi ý kiến đóng góp xin gửi mail về địa chỉ support@iotmaker.vn

Ngoài ra các bạn có thể tương tác với chúng tôi qua 1 số địa chỉ:

• 1. Webstore : iotmaker.vn/

• 2. Facebook : www.facebook.com/iotmaker.vn/

Một số trang web đóng góp cho cộng đồng (mong nhận được sự chia sẻ và đóng góp của các bạn để

cộng đồng IoT Việt Nam nói riêng cũng như cộng đồng kĩ thuật Việt Nam nói chung ngày một phát

triển hơn):

• 1. Về ESP8266 với Arduino : arduino.esp8266.vn/

iotmaker.vn

https://thuviensach.vn

Internet Of Things (IoT) cho người mới bắt đầu

155/155

• 2. Về ESP32 : esp32.vn

• 3. Facebook Group: www.facebook.com/groups/iotmaker/

Giấy phép sử dụng tài liệu.

• Tài liệu tuân theo giấy phép CC-BY-NC-SA (creativecommons.org/licenses/by-nc-sa/4.0/

legalcode)

• Bản quyền toàn bộ tài liệu này thuộc về IoT Maker Việt Nam, bạn được miễn phí sử dụng cho mục đích cá nhân, học tập và sử dụng trong các dự án của mình, không được sử dụng cho mục

đích thương mại. Nếu bạn muốn sửa chữa, phân phối lại, bạn bắt buộc phải giữ nguyên giấy

phép và cần có sự đồng ý của IoT Maker Việt Nam.

• Chỉ duy nhất các các nhân, tổ chức được liệt kê tại iota.edu.vn là được phép sử dụng tài liệu cho mục đích thương mại.

https://thuviensach.vn

Document Outline

- Internet Of Things (IoT) : cho người mới bắt đầu

- Mục lục

- Lời mở đầu

- Đôi lời về tác giả

- Thuật ngữ hay sử dụng

- Giải thích code trong bài

- Giới thiệu nội dung

- Ai có thể sử dụng?

- Mục tiêu mang lại cho người đọc

- Chuẩn bị

- Kiến thức cơ bản

- Internet Of Things (IoT)

- Internet of Things (IoT) là gì?

- Hệ thống Internet of Things (IoT)

- Những ứng dụng thực tế trong cuộc sống

- ESP8266

- Sơ đồ chân

- Thông số phần cứng

- SDK hỗ trợ chính thức từ hãng

- ESP8285

- Module và Board mạch phát triển

- Board mạch phát triển ESP8266

- Arduino là gì?

- Một số đặc điểm của Arduino

- Các lợi ích khi sử dụng Arduino

- Cộng đồng Arduino trên thế giới

- Arduino cho ESP8266 & board mạch ESP8266 WiFi Uno

- Node.js

- Lý do sử dụng Node.js trong cuốn sách này

- Cuốn sách này có hướng dẫn Node.js ?

- Sublime Text

- Cài đặt và chuẩn bị

- Arduino IDE

- Cài đặt thư viện Arduino

- USB CDC driver.

- Chọn Board ESP8266 WiFi Uno trong Arduino IDE

- Nạp chương trình xuống board dùng Arduino IDE

- Xuất firmware binary trong Arduino IDE

- Serial Terminal

- Node.js

- Sublime Text

- Git

- Tổng kết

- Hello World

- Chớp tắt bóng LED

- Kiến thức

- Đấu nối

- Mã nguồn chớp tắt dùng Delay

- Mã nguồn chớp tắt dùng định thời

- Digital IO

- Tổng kết

- Kiến thức

- Mã nguồn dùng hỏi vòng

- Mã nguồn dùng ngắt

- Các khái niệm

- OLED

- Màn hình OLED

- Màn hình OLED SSD1306

- Giao tiếp I2C

- Hiển thị màn hình OLED với ESP8266

- Tổng kết

- ESP8266 WiFi

- Chế độ WiFi Station

- Kiến thức

- Kết nối vào mạng WiFi nội bộ

- Sử dụng WiFiMulti

- HTTP Client

- Giao thức HTTP

- JSON

- Ứng dụng xem giá Bitcoin

- Chế độ WiFi Access Point

- ESP8266 hoạt động ở chế độ Access Point

- Khởi tạo mạng WiFi sử dụng ESP8266

- Web Server

- Web Server là gì?

- HTML - Javascript - CSS

- Ứng dụng điều khiển đèn LED thông qua Webserver

- ESP8266 Web Server

- Kết hợp WiFi AP và Web Server

- Trao đổi dữ liệu giữa 2 ESP8266

- Yêu cầu

- Hướng dẫn thực hiện

- Code

- Tổng kết

- Dự án đọc cảm biến DHT11 và gởi về Server

- Thiết kế ứng dụng

- Yêu cầu

- Phân tích

- Kiến thức

- Thực hiện

- Server Nodejs

- Code ESP8266

- Chuẩn bị

- Ứng dụng mở rộng

- Dùng ESP8266 như 1 Web Server

- Tổng kết

- Các chế độ cấu hình WiFi

- Smartconfig

- Kiến thức

- Thực hiện SmartConfig với ESP8266

- Code

- WPS

- WPS là gì?

- Thực hiện WPS với ESP8266

- Code

- Wifi Manager

- Hoạt động cơ bản WifiManager

- Chuẩn bị

- Code

- Mở rộng

- Tổng kết

- MQTT

- Publish, subscribe

- QoS

- Retain

- LWT

- MQTT Client

- MQTT Lens

- MQTT.js

- ESP8266 MQTT Client

- MQTT Broker

- MOSCA

- Một số MQTT Broker sử dụng cho sản phẩm thực tế

- Tổng kết

- Websocket

- Ưu điểm

- Nhược điểm

- Sử dụng ESP8266 như Websocket Server

- Yêu cầu

- Chuẩn bị

- Đoạn code Javascript để tạo kết nối Web Socket

- Nhúng file HTML chứa đoạn code JS vào ESP8266

- Chương trình hoàn chỉnh cho ESP8266

- Kết quả

- Video kết quả

- Sử dụng ESP8266 như Websocket Client

- Javascript Websocket Client trên trình duyệt

- Node.js Websocket Server

- ESP8266 Websocket Client

- Tổng kết

- Firmware update over the air (FOTA)

- Cập nhật firmware từ xa

- Bảo mật

- An toàn

- Yêu cầu căn bản

- Update process - memory view

- OTA sử dụng Arduino IDE

- Bước 1: nạp firmware hỗ trợ OTA thông qua cổng Serial

- Bước 2: Lựa chọn cổng nạp thông qua OTA

- Bước 3: Sửa firmware mới và nạp lại thông qua WiFi

- Sử dụng mật khẩu

- Những sự cố thường gặp

- Cập nhật Firmware dùng Web Browser

- Thực hiện

- Bảo mật

- HTTP Server

- ESP8266 ESPhttpUpdate

- Node.js OTA Server

- Cheatsheet

- Arduino - ESP8266 Cheatsheet

- C - Cheatsheet

- Lời kết

- Các thành viên tham gia đóng góp.

- Lời kết.

- Giấy phép sử dụng tài liệu.

Table of Contents

Internet Of Things (IoT) : cho người mới bắt đầu

Mục lục

Lời mở đầu

Đôi lời về tác giả

Thuật ngữ hay sử dụng

Giải thích code trong bài

Giới thiệu nội dung

Ai có thể sử dụng?

Mục tiêu mang lại cho người đọc

Chuẩn bị

Kiến thức cơ bản

Internet Of Things (IoT)

Internet of Things (IoT) là gì?

Hệ thống Internet of Things (IoT)

Những ứng dụng thực tế trong cuộc sống

ESP8266

Sơ đồ chân

Thông số phần cứng

SDK hỗ trợ chính thức từ hãng

ESP8285

Module và Board mạch phát triển

Board mạch phát triển ESP8266

Arduino là gì?

Một số đặc điểm của Arduino

Các lợi ích khi sử dụng Arduino

Cộng đồng Arduino trên thế giới

Arduino cho ESP8266 & board mạch ESP8266 WiFi Uno

Node.js

Lý do sử dụng Node.js trong cuốn sách này

Cuốn sách này có hướng dẫn Node.js ?

Sublime Text

Cài đặt và chuẩn bị

Arduino IDE

Cài đặt thư viện Arduino

USB CDC driver.

Chọn Board ESP8266 WiFi Uno trong Arduino IDE

Nạp chương trình xuống board dùng Arduino IDE

Xuất firmware binary trong Arduino IDE

Serial Terminal

Node.js

Sublime Text

Git

Tổng kết

Hello World

Chớp tắt bóng LED

Kiến thức

Đấu nối

Mã nguồn chớp tắt dùng Delay

Mã nguồn chớp tắt dùng định thời

Digital IO

Tổng kết

Kiến thức

Mã nguồn dùng hỏi vòng

Mã nguồn dùng ngắt

Các khái niệm

OLED

Màn hình OLED

Màn hình OLED SSD1306

Giao tiếp I2C

Hiển thị màn hình OLED với ESP8266

Tổng kết

ESP8266 WiFi

Chế độ WiFi Station

Kiến thức

Kết nối vào mạng WiFi nội bộ

Sử dụng WiFiMulti

HTTP Client

Giao thức HTTP

JSON

Ứng dụng xem giá Bitcoin

Chế độ WiFi Access Point

ESP8266 hoạt động ở chế độ Access Point

Khởi tạo mạng WiFi sử dụng ESP8266

Web Server

Web Server là gì?

HTML - Javascript - CSS

Ứng dụng điều khiển đèn LED thông qua Webserver

ESP8266 Web Server

Kết hợp WiFi AP và Web Server

Trao đổi dữ liệu giữa 2 ESP8266

Yêu cầu

Hướng dẫn thực hiện

Code

Tổng kết

Dự án đọc cảm biến DHT11 và gởi về Server

Thiết kế ứng dụng

Yêu cầu

Phân tích

Kiến thức

Thực hiện

Server Nodejs

Code ESP8266

Chuẩn bị

Ứng dụng mở rộng

Dùng ESP8266 như 1 Web Server

Tổng kết

Các chế độ cấu hình WiFi

Smartconfig

Kiến thức

Thực hiện SmartConfig với ESP8266

Code

WPS

WPS là gì?

Thực hiện WPS với ESP8266

Code

Wifi Manager

Hoạt động cơ bản WifiManager

Chuẩn bị

Code

Mở rộng

Tổng kết

MQTT

Publish, subscribe

QoS

Retain

LWT

MQTT Client

MQTT Lens

MQTT.js

ESP8266 MQTT Client

MQTT Broker

MOSCA

Một số MQTT Broker sử dụng cho sản phẩm thực tế

Tổng kết

Websocket

Ưu điểm

Nhược điểm

Sử dụng ESP8266 như Websocket Server

Yêu cầu

Chuẩn bị

Đoạn code Javascript để tạo kết nối Web Socket

Nhúng file HTML chứa đoạn code JS vào ESP8266

Chương trình hoàn chỉnh cho ESP8266

Kết quả

Video kết quả

Sử dụng ESP8266 như Websocket Client

Javascript Websocket Client trên trình duyệt

Node.js Websocket Server

ESP8266 Websocket Client

Tổng kết

Firmware update over the air (FOTA)

Cập nhật firmware từ xa

Bảo mật

An toàn

Yêu cầu căn bản

Update process - memory view

OTA sử dụng Arduino IDE

Bước 1: nạp firmware hỗ trợ OTA thông qua cổng Serial

Bước 2: Lựa chọn cổng nạp thông qua OTA

Bước 3: Sửa firmware mới và nạp lại thông qua WiFi

Sử dụng mật khẩu

Những sự cố thường gặp

Cập nhật Firmware dùng Web Browser

Thực hiện

Bảo mật

HTTP Server

ESP8266 ESPhttpUpdate

Node.js OTA Server

Cheatsheet

Arduino - ESP8266 Cheatsheet

C - Cheatsheet

Lời kết

Các thành viên tham gia đóng góp.

Lời kết.

Giấy phép sử dụng tài liệu.