Trong bài này mình xin chia sẻ cách làm hệ thống cảnh báo trộm đơn giản, rất đơn giản thôi, chỉ là mình gắn nó bên ngoài cửa phòng mình, nếu mẹ mình chuẩn bị mở cửa phòng ra thì nó sẽ phát tiếng lên trên máy tính để mình biết để ngụy trang ngay lập tức.

Chuẩn bị

Phần cứng

  • ESP8266 phiên bản bất kỳ. (mình dùng NodeMCU)
  • Cảm biến chuyển động PIR (hoạt động nguồn 5V)
  • Dây nối

Ở đây phần cứng được mình sử dụng là mạch NodeMCU, các bạn có thể dùng bất kỳ mạch nào có ESP8266 ở trên đó. Lưu ý là nếu chỉ dùng mấy modul ESP8266 v1/v7 thì cần có thêm mạch USB2UART như PL2303 để nạp chương trình nhé.

Phần mềm

Nếu bạn mới bắt đầu với ESP8266 thì có thể tham khảo thêm các bước làm quen ban đầu với ESP8266

Các khái niệm

Trước khi bắt đầu mình cùng tìm hiểu thêm một chút về các khái niệm, những khái niệm này sẽ rất quen thuộc vì nó được nói rất nhiều trong các group, diễn đàn như Restful, Nodejs,..

RESTful

Theo định nghĩa từ codehub thì REST (Representational State Transfer) là một kiểu kiến trúc được sử dụng trong việc giao tiếp giữa các máy tính (máy tính cá nhân và máy chủ của trang web) trong việc quản lý các tài nguyên trên internet. REST được sử dụng rất nhiều trong việc phát triển các ứng dụng Web Services sử dụng giao thức HTTP trong giao tiếp thông qua mạng internet. Các ứng dụng sử dụng kiến trúc REST này thì sẽ được gọi là ứng dụng phát triển theo kiểu RESTful.

Nó có 4 phương thức được sử dụng:

  • POST  – Tạo một tài nguyên trên máy chủ
  • GET  – Truy xuất một tài nguyên
  • PUT  – Thay đổi trạng thái một tài nguyên hoặc để cập nhật nó
  • DELETE – Huỷ bỏ hoặc xoá một tài nguyên

REST nó dính tới khá nhiều về CNTT, về Web nên mình xin ko đi sâu, chỉ tận dụng thư viện về RESTful có sẵn là AREST dùng với ESP8266.

NodeJS

Node.js chỉ là một môi trường – nghĩa là bạn phải tự tay làm mọi thứ. Không có một server HTTP mặc định, hoặc bất kỳ server nào cho vấn đề đó. Điều này có thể gây bối rối cho những người mới học, nhưng bù lại chúng ta sẽ xây dựng được ứng dụng web có tốc độ thực thi cao. Một script quản lý tất cả truyền thông với các client. Điều này giúp giảm đáng kể số lượng tài nguyên sử dụng bởi ứng dụng đó.

Node.js có các thư viện built-in để xử lý các web request và response – do đó bạn không cần một máy chủ web riêng biệt hoặc những thành phần phụ thuộc khác

Cài đặt

Phần lý thuyết chắc cũng có khá nhiều bài viết nói về nó rồi, thôi mình tập trung vào mục đích chính, xem coi nodejs, restful nó hoạt động thế nào nhé.

NodeJs

Trước tiên sẽ là cài đặt Nodejs cho Win10 tại Nodejs, phiên bản hiện tại là v6.9.6 LTS, tiếp theo là next như cài bao phần mềm khác

ExpressJs

Đây là một framework dùng cho nodejs, nó sẽ giúp cho các thao tác với nodejs được dễ dàng hơn. Các bạn có thể xem hình minh họa tổng quan về cách hoạt động hệ thống sử dụng express

Để cài đặt Expressjs thì các bạn mở Command Prompt(cmd) của Win (phím tắt Windows + X), nhập lệnh

npm install express jade

Xây dựng hệ thống

Coi như đã tạm xong các bước cài đặt và chuẩn bị, giờ thì bắt tay vào xây dựng hệ thống chống trộm này

Ở đây máy tính của mình sẽ đóng vai trò là server, nó sẽ nhận thông tin có hay không có người từ ESP8266 gửi lên và hiển thị thông tin cảnh báo về âm thanh, hình ảnh cho mình thông qua web browser.

Kết nối phần cứng

Trước tiên chúng ta cần kết nối phần cứng giữa ESP8266 với cảm biến chuyển động như sau, chân D1(pin 5) trên NodeMCU sẽ được dùng để đọc giá trị của cảm biến

Đọc cảm biến với ESP8266

Trong chương trình sẽ có một số thứ cần quan tâm

  • Host ở đây là địa chỉ IP của máy bạn, bạn có thể xem địa chỉ này tại Network Preferences hoặc vào cmd gõ lệnh ipconfig
  • Kết nối với server với  httpPort = 3000; 3000 là port của server dùng nodejs.
  • ESP8266 sẽ gửi yêu cầu POST lên server thông báo trạng thái của cảm biến.

Các bạn có thể tham khảo chương trình đầy đủ ở đây

/***************************************************
Chương trình cảnh báo trộm
****************************************************/

// Thêm thư viện
#include <ESP8266WiFi.h>
#include <aREST.h>

// Địa chỉ IP của máy tính bạn
const char* host = "192.168.1.13";

// Thông tin wifi
const char* ssid = "ten_wifi";
const char* password = "pass_wifi";

// Trạng thái cảm biến chuyển động
int motion_sensor_state = 0;

void setup(void)
{
  // Khởi tạo serial
  Serial.begin(115200);

  // Cấu hình cảm biến là input
  pinMode(5, INPUT);

  // Kết nối WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  //  IN địa chỉ IP
  Serial.println(WiFi.localIP());
}

void loop() {

  // Kiểm tra trạng thái cảm biến
  int new_motion_sensor_state = digitalRead(5);
  // Nếu khác thì gửi thông tin lên server
  if (new_motion_sensor_state != motion_sensor_state) {

    // Đặt trạng thái mới
    motion_sensor_state = new_motion_sensor_state;

    Serial.print("Connecting to ");
    Serial.println(host);

    // Sử dụng WiFiClient để tạo kết nối TCP
    WiFiClient client;
    const int httpPort = 3000;
    if (!client.connect(host, httpPort)) {
      Serial.println("connection failed");
      return;
    }

    // Gửi yêu cầu tới server
    client.print(String("POST /motion?state=") + String(new_motion_sensor_state) + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
    delay(10);

    // Đọc phản hồi từ server
    while(client.available()){
      String line = client.readStringUntil('\r');
      Serial.print(line);
    }

    Serial.println();
    Serial.println("closing connection");
  }

}

Tạo cảnh báo lên server

Khi phát hiện có người, thông báo trên web browser sẽ có 2 option là cảnh báo bằng thông báo hoặc thông báo kèm âm thanh

Chương trình gồm 3 file:

  • app.js gồm code cho server, trong file sẽ có khởi tạo với expressjs, tạo một số biến để xác định trạng thái của cảm biến và phương thức get, post đưa thông tin về cảnh báo và trạng thái cảm biến, cuối cùng là khởi động web server.
  • interface.jade là giao diện hiển thị lên web
  • interface.js tạo liên kết giữa giao diện với server, với hàm refresh_motion để hiện query giá trị của cảm biến và thay đổi giao diện web. Nếu phát hiện chuyển động và tùy chọn âm thanh không được bật thì sẽ thay đổi trạng thái trên giao diện, nếu có chọn phát âm thanh thì sẽ có âm báo trên máy tính, hàm này được thực hiện mỗi 500ms

app.js

// Chọn Expressjs
var express = require('express');
var app = express();

// Khai báo port
var port = 3000;

// Biến cho cảm biến chuyển động
var motion = 0;

// Trạng thái ban đầu của cảnh báo
var alarm = 0;

// Hiển thị jade
app.set('view engine', 'jade');

// Cài public folder
app.use(express.static(__dirname + '/public'));

// Đưa ra giao diện
app.get('/', function(req, res){
  res.render('interface');
});

// Thay đổi trạng thái cảm biến cd
app.post('/motion', function(req, res) {
  motion = req.query.state;
  res.send('Data received: ' + motion);
});

// Lấy trạng thái cảm biến cd
app.get('/motion', function(req, res) {
  res.json({state: motion});
});

// Lấy trạng thái báo động
app.get('/alarm', function(req, res) {
  res.json({state: alarm});
});

// Thay đổi trạng thái báo động
app.post('/alarm', function(req, res) {
  alarm = req.query.state;
  res.send('Data received: ' + alarm);
});

// Khởi động server
app.listen(port);
console.log("Listening on port " + port);

interface.jade

doctype
html
  head
    title Interface
    link(rel='stylesheet', href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css")
    link(rel='stylesheet', href="/css/interface.css")
    meta(name='viewport', content='width=device-width, initial-scale=1')  

    script(src="https://code.jquery.com/jquery-2.1.1.min.js")
    script(src="/js/jquery.playSound.js")
    script(src="/js/ajaxq.js")
    script(src="/js/interface.js")
  body
    .container
      h1 He thong bao dong
      .row.voffset
        .col-md-4
          div Cam bien chuyen dong: 
        .col-md-4
          div#motion Khong co nguoi.
      .row.voffset
        .col-md-4
          button.btn.btn-block.btn-lg.btn-danger#alarm Tat bao am

interface.js

$(document).ready(function() {

  // Lấy thông tin từ cảm biến
  function refresh_motion() {
  	$.getq('queue', '/motion', function(data) {
      if (data.state == 0) {$('#motion').html("Khong co nguoi");}
      if (data.state == 1) {

        // Thay đổi thông báo trên giao diện
        $('#motion').html("Co thich khach");

        // Bật âm cảnh báo nếu tùy chọn Bat bao coi
        $.get('/alarm', function(data) {
          if (data.state == 1) {$.playSound('/audio/alarm');}
        });
        
      }	
    });
  }
  refresh_motion();
  setInterval(refresh_motion, 500);

  // Khởi tạo nút tùy chọn cảnh báo âm thanh
  $.get('/alarm', function(data) {
    var alarm_state = data.state;
    
    if (alarm_state == 1) {
      $('#alarm').html("Bat bao coi");
      $('#alarm').attr('class', 'btn btn-block btn-lg btn-success');
    }

    if (alarm_state == 0) {
      $('#alarm').html("Tat bao coi");
      $('#alarm').attr('class', 'btn btn-block btn-lg btn-danger');
    }
  });

  // Kiểm tra khi click chọn vào nút
  $('#alarm').click(function() {

  	// Lấy trạng thái
    $.get('/alarm', function(data) {
    	var alarm_state = data.state;
		
    	if (alarm_state == 0) {
    	  $.post('/alarm?state=1');
    	  $('#alarm').html("Bat bao coi");
        $('#alarm').attr('class', 'btn btn-block btn-lg btn-success');
    	}

    	if (alarm_state == 1) {
    	  $.post('/alarm?state=0');
    	  $('#alarm').html("Tat bao coi");
        $('#alarm').attr('class', 'btn btn-block btn-lg btn-danger');
    	}
    });

  });

});

Để tiện thì các bạn có thể tải tất cả tại đây, sau đó copy vào thư mục C:\Users\ten_pc với ten_pc là tên máy tính bạn

Đến đây là đã xong các bước lập trình

Khởi động nodejs trong thư mục alarm_system bằng lệnh trên cmd

$ cd alarm_system
$ node app.js

Mở trình duyệt vào địa chỉ http://localhost:3000/

Kết quả

Tạm kết

Mình đã trình bày một số khái niệm cơ bản, cách đưa nodejs,esp,restful, express vào trong một web đơn giản, nhận thông tin từ ESP8266 gửi lên, đây chỉ là bước khởi đầu, vẫn còn rất nhiều thứ để bạn học ở phía trước. Nếu bạn có biết về làm web, nodejs,.. thì chắc là khỏe hơn nhiều rồi 😀