Đ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

Xe điều khiển bằng tay game Dual Shock3 thông qua Bluetooth

Vừa bắt đầu với arduino được hơn 1 tuần, có tham khảo qua các nguồn từ "trung ương đến địa phương", nắm được 1 số kiến thức cơ bản nên mình bắt đầu thực hiện 1 sản phẩm để đúc kết kinh nghiệm. Trong số đó thì xe điều khiển là dễ nhất. Kết hợp với cái tay game ps3 nằm lăn lóc ở góc nhà. Thế là có 1 chiếc xe điều khiển từ xa. Bắt đầu nhé.

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

Làm xe điều khiển từ xa bằng Bluetooth - Điều khiển bằng Android với App Inventor

Mình rất thích điện tử nhưng không học về ngành điện tử. Rất may là có Adruino, rồi có cộng đồng Adruino Việt Nam, đặc biệt là sự nhiệt tình của tất cả các bạn trong cộng đồng, mình đã làm được 1 chiếc xe điều khiển từ xa. Cho con chơi là lí do phụ thôi, còn tìm hiểu, học tập là chính. Hôm nay chia sẻ cùng các bạn, cùng gửi lời cảm ơn đến tất cả các bạn trong cộng đồng. Có bạn thì giúp đỡ trực tiếp, có bạn thì viết bài, rồi có bạn thì bình luận, nêu câu hỏi. Tất cả đều có giá trị đối với mình.

Ngại viết bài nên mình đăng dưới dạng ảnh.

lên
26 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ả

Xử lý chuỗi trong Arduino

Ngôn ngữ lập trình Arduino được xây dựng dựa trên ngôn ngữ C, điều đó có nghĩa là bạn có thể sử dụng các thư viện của ngôn ngữ C một cách dễ dàng cho việc lập trình. Trong đó có thư viện string.h để làm việc với chuỗi. Ngoải ra, Arduino còn hỗ trợ cả đối tượng  String của C++. Hãy khám phá ngay!

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

Tự làm thiết bị bật tắt đèn điều khiển qua phần mềm iNut trên Android và iPhone

Điều khiển thiết bị điện trong nhà là một trong những mong muốn cháy bỏng nhất của mình trong quá trình tìm tòi và nghiên cứu phát triển Arduino. Với board mạch ESP8266, ước mong của mình đã trở thành hiện thực. Và mình đã thực hiện hóa nó qua dự án iNut. Và đây là thời điểm hoàn hảo để triển khai dự án điều khiển thiết bị điện trong nhà này. Hãy cùng khám phá nhé.

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