Điều khiển bật tắt đèn LED từ xa thông qua NodeJS và WebSocket với thư viện SocketIO

Với bài viết của bạn Tống Quốc Thái rất hay, bạn Thái đã chọn một con đường mới là IOT với NodeJS. Hôm nay, là mình xin mở rộng bài này cho các bạn yêu thích. Mục tiêu của bài viết này là "điều khiển một bóng LED từ xa qua Webserver đơn giản". Bạn sẽ học được cách tạo một webserver đơn giản cùng với đó là viết một trang web để điều khiển bé LED của mình trên board mạch Arduino.

Để đơn giản, mình sẽ làm toàn bộ bài hướng dẫn trên một máy tính Windows! Các bạn hoàn toàn có thể thực hiện lại bài hướng dẫn này trên một thiết bị khác như: máy tính Raspberry Pi chạy Linux (Raspbian) hay Orange Pi chạy Linux (Armbian),...

Bạn có thể dùng bất kỳ board Arduino nào!

Đặt vấn đề

Vì sao mình lại chọn WebSocket để giao tiếp giữa người dùng từ trình duyệt với Arduino? Mình có thể sử dụng các yêu cầu HTTP truyền thống mà! Và lý do là:

  • Một lệnh HTTP truyền thống cần phải có thời gian thiết lập kết nối, điều đó là bắt buộc. Sau đó, tuần tự các phép chuyển dữ liệu mới diễn ra. Trong khi đó, websocket chỉ cần thiết đặt một lần duy nhất và khi kết nối còn giữ thì mọi việc diễn ra rất nhanh, dữ liệu được gửi đi ngay tức khắc với độ trễ chỉ khoảng 1-2 mili giây.
  • Việc trao đổi diễn ra hai chiều: Nghĩa là server có thể tạo ra một sự kiện ở client.

Vì sao mình lại chọn NodeJS thay cho ngôn ngữ C++ truyền thống?

  • Vì việc viết code bằng ngôn ngữ Javascript trong ngôi trường NodeJS rất nhanh.
  • Client ở trên máy tính, điện thoại có thể được viết bằng cách tạo webserver và yêu cầu các thiết bị truy cập đến.
  • Việc phân chia các công việc theo xu hướng bất đồng bộ rất tiện lợi. Nôm na, việc viết các đoạn chương trình ngắn "song song" là hoàn toàn có thể và dễ dàng với NodeJS. 
    • Ghi chú: "song song" = bất đồng bộ, không phải theo nghĩa multithread.

Bài toán mình sẽ giải quyết trong bài này:

  • Tạo 3 nút trên webserver
    • 1 nút bật
      • Làm nhiệm vụ bật đèn LED 13
    • 1 nút tắt
      • Làm nhiệm vụ tắt đèn LED 13
    • 1 nút nhấp nháy
      • Làm nhiệm vụ khiến LED 13 nhấp nháy với chu kỳ bật / tắt là 1 giây.

Cài đặt môi trường NodeJS

Các bạn có thể xem toàn văn hướng dẫn và bài test cài đặt thành công ngay tại đây.

Tạo và truy cập project

Chỉ việc tạo một thư mục với và cd (change dir) vào là chúng ta đã tạo và truy cập dự án thành công!

mkdir nodejsProject

cd nodejsProject

Cài đặt các thư viện

npm install express
npm install socket.io
npm install johnny-five

Ý nghĩa các thư viện:

  • express: dùng để tạo một http server (dùng cho việc tạo webserver)
  • socket.io: thư viện giúp cho việc dùng WebSocket dễ dàng hơn
  • johnny-five: thư viện dùng để giao tiếp với Arduino

Nạp code cho Arduino

Ngoài việc nạp chương trình cơ sở (firmware) cho Arduino tên là Firmata, thì bạn không cần phải làm gì cả, nếu chưa nạp Firmata bạn có thể xem bài hướng dẫn ở đây:

Bạn không cần phải lắp mạch trên board Arduino vì trên board Arduino đã có sẵn đèn LED 13 được gắn sẵn rồi mà haha.

Xây dựng code ở server và client

Việc xây dựng một server và một client đối với một người mới học thì sẽ rất khó. Vì vậy, mình sẽ viết phần kết nối giữa server và client trước, sau đó sẽ xây dựng phần server điều khiển Arduino.

Bạn cần phải hiểu rằng, việc kết nối giữa một thiết bị A đến một thiết bị B luôn có hai vấn đề cần giải quyết (các phần bôi đậm là quan trọng nhất và phải trả lời trong mọi trường hợp cho việc xây dựng server-client):

  1. Logic:
    • Bạn sẽ lựa chọn công nghệ truyền tin nào?
    • Các phương thức truyền tin bao gồm gì?
    • Kịch bản truyền tin là gì?
    • Các tham số của mỗi phương thức là gì?
    • ...
  2. UI:
    • Bạn lựa chọn công nghệ và ngôn ngữ lập trình nào để viết nên client?
    • Công nghệ nào sẽ đẹp và phù hợp với công nghệ hiện tại?
    • Tối ưu hóa giao diện cho từng người dùng như thế nào?
    • ...

Chỉ cần giải quyết các vấn đề bôi đậm và ứng dụng các câu trả lời vào thực thế thành công thì bạn đã tự xây dựng được một dự án server-client.

Bạn sẽ lựa chọn công nghệ truyền tin nào?

Mình dùng công nghệ NodeJS (môi trường) và WebSocket (truyền tin). Dùng thư viện SocketIO để dùng WebSocket dễ dàng trên cả server và client.

Các phương thức truyền tin là gì?

Mình sẽ xây dựng các phương thức sau:

  • bật
    • Bật đèn LED 13
  • tắt
    • Tắt đèn LED 13
  • nhấp nháy
    • Nhấp nháy đèn LED 13

Bạn lựa chọn công nghệ và ngôn ngữ lập trình nào để viết nên client?

Mình lựa chọn HTML + Javascript để lập trình client.

Xây dựng chương trình trên Server

Bạn tạo file index.js với nội dung sau:

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(8000); //lắng nghe ở port 8000

app.get('/', function(req, res) { //tạo webserver khi truy nhập đường dẫn "/".
    res.sendfile(__dirname + '/index.html'); // thì mở nội dung ở file index.html lên
});

io.on('connection', function(socket) { //sau khi client kết nối tới server 
    //khi server nhận được yêu cầu "bật" từ client
    socket.on('bật', function() {
        console.log("bật")
    });
    //khi server nhận được yêu cầu "tắt" từ client
    socket.on('tắt', function() {
        console.log("tắt")
    });
    //khi server nhận được yêu cầu "nhấp nháy" từ client
    socket.on('nhấp nháy', function() {
        console.log("nhấp nháy")
    });
});


console.log("Đã khởi động socket server")

Xây dựng chương trình trên Client

Bạn tạo file index.htm như sau:

<meta charset="UTF-8"> <!-- bật tiếng Việt -->
<script src="/socket.io/socket.io.js"></script> <!-- thêm thư viện để dùng được các hàm websocket client - file này sẽ được tạo file mở socket server -->
<script>
  var socket = io.connect('http://127.0.0.1:8000');
  socket.on('connect', function () {
    console.log();
	console.log("Đã kết nối tới socket server")
  });
  
  var bat = function() {
	console.log("Bật") //debug - báo bật
	socket.emit("bật") // gửi sự kiện "bật" đến Server
  }
  
  var tat = function() {
	console.log("Tắt") 
	socket.emit("tắt")
  }
  
  var nhapnhay = function() {
	console.log("Nhấp nháy")
	socket.emit("nhấp nháy")
  }
</script>

<button onclick="bat()">Bật</button> <!-- Khi nhấn nút Bật thì gọi lệnh bat() ở client -->
<br /> <!-- xuống dòng -->
<button onclick="tat()">Tắt</button>
<br /> <!-- xuống dòng -->
<button onclick="nhapnhay()">Nhấp nháy</button>
<br /> <!-- xuống dòng -->

Các bạn hãy chạy đoạn code sau ở Command line:

node index.js

Sau đó hãy truy cập địa chỉ http://127.0.0.1:8000 ở trình duyệt và thử nhấn các nút như video dưới đây nhé.

Xây dựng code trên server để điều khiển board

Bây giờ mình sẽ sửa code ở file index.js để điều khiển đèn LED.

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var five = require("johnny-five"); //Gọi thư viện Johnny-five
 
var board = new five.Board(); //Tạo board Arduino từ thư viện
 

server.listen(8000); //lắng nghe ở port 8000

app.get('/', function(req, res) { //tạo webserver khi truy nhập đường dẫn "/".
    res.sendfile(__dirname + '/index.html'); // thì mở nội dung ở file index.html lên
});

board.on("ready", function() { //Arduino đã sẵn sàng làm việc rồi(đây là một sự kiện, nó sẽ diễn ra khi board Arduino đã sẵn sàng cho việc lập trình)
	
	var led = new five.Led(13); //Khai báo led ở chân số 13
	
	io.on('connection', function(socket) { //sau khi client kết nối tới server 
		//khi server nhận được yêu cầu "bật" từ client
		socket.on('bật', function() {
			led.on();//bật đèn LED
			console.log("bật")
		});
		//khi server nhận được yêu cầu "tắt" từ client
		socket.on('tắt', function() {
			led.off();//tắt đèn LED
			console.log("tắt")
		});
		//khi server nhận được yêu cầu "nhấp nháy" từ client
		socket.on('nhấp nháy', function() {
			led.blink();//nhấp nháy đèn LED
			console.log("nhấp nháy")
		});
	});

});
console.log("Đã khởi động socket server")

Chỉ cần khởi tạo board một lần, khởi tạo led một lần. Sau đó khi có bất từ client kết nối tới là điều khiển được ngay.

Kết luận

Bạn thấy đấy, việc tạo một client-server hoàn toàn không khó. Bạn hoàn toàn có thể làm lại được. Bạn hãy sử dụng code mình đã up lên github ở đây để thử nghiệm. 

https://github.com/ngohuynhngockhanh/nodeJsDemoControlLed

Những hình ảnh về dự án: 
Bài viết truyền cảm hứng: 
lên
7 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Bộ điều khiển PID - ứng dụng phần 2 - xe dò line dùng thuật toán PID

Tiép nối bài viết về xe dò line cảm ơn Đỗ Hữu Toàn đã viết hộ mình phần 4. hôm nay mình sẽ làm cho chiếc xe dò line đi mượt và có hồn hơn 

lên
34 thành viên đã đánh giá bài viết này hữu ích.
Các bài viết cùng tác giả

Bảng mã ASCII

Bảng mã ASCII (American Standard Code for Information Interchange) được ra đời vào thập kỉ 60 của thế kỷ trước. Đây là tiêu chuẩn trong việc mã hóa chuỗi thành một số và ngược lại.

Lưu ý: 32 ký tự đầu tiên của bảng mã này (0-31) không thể xuất hiện trên đây được. Các ký tự này được gọi là ký tự điều khiển (ví dụ: khi nhấn vào nút Ctrl, bạn có thầy cái gì xuất hiện không ?)

lên
6 thành viên đã đánh giá bài viết này hữu ích.