Bài viết
Cảm biến hiện diện Bluetooth cho nhà thông minh với ESP32
📶
Tự động hóa nhà thông minh dựa trên GPS điện thoại tốn pin và cần internet ổn định; dựa trên cảm biến chuyển động thì không phân biệt được ai đang ở nhà. Một cách rẻ và hiệu quả hơn: hầu hết điện thoại đều phát tín hiệu Bluetooth Low Energy (BLE) liên tục dù không kết nối với thiết bị nào — ESP32 có thể quét các tín hiệu này trong phạm vi vài mét và suy ra “có người ở nhà” hay “đã rời đi” mà không cần app hay cấu hình gì trên điện thoại.
Nguyên lý hoạt động
- ESP32 định kỳ quét (BLE scan) các thiết bị Bluetooth phát sóng xung quanh, thu thập địa chỉ MAC và cường độ tín hiệu (RSSI) của từng thiết bị.
- So sánh địa chỉ MAC quét được với danh sách MAC đã biết trước (điện thoại của các thành viên trong nhà) — MAC ngẫu nhiên thay đổi theo thời gian trên iOS/Android hiện đại là hạn chế cần lưu ý (xem phần lỗi thường gặp).
- Nếu một MAC quen thuộc xuất hiện liên tục qua vài lần quét, ESP32 coi như thiết bị đó “có mặt”; nếu vắng mặt trong nhiều lần quét liên tiếp (quá một khoảng thời gian chờ), coi như đã rời đi.
- Trạng thái hiện diện được publish qua MQTT tới Home Assistant hoặc broker tự dựng, từ đó kích hoạt automation: bật đèn/điều hòa khi về nhà, tắt hết thiết bị khi không còn ai.
Linh kiện
- ESP32 (bất kỳ dòng nào có BLE, kể cả ESP32-C3/S3)
- Nguồn 5V ổn định (adapter USB) vì thiết bị chạy liên tục 24/7
- Broker MQTT (Mosquitto tự host hoặc tích hợp sẵn trong Home Assistant)
- Điện thoại của các thành viên trong nhà để lấy địa chỉ MAC BLE (dùng app dò BLE như nRF Connect để xem MAC khi Bluetooth đang bật)
Code mẫu
#include <WiFi.h>
#include <PubSubClient.h>
#include <BLEDevice.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
const char* WIFI_SSID = "ten-wifi";
const char* WIFI_PASS = "mat-khau-wifi";
const char* MQTT_HOST = "192.168.1.10";
WiFiClient espClient;
PubSubClient mqtt(espClient);
BLEScan* bleScan;
// Dia chi MAC dien thoai can theo doi, thay bang MAC thuc te
const char* KNOWN_MAC = "aa:bb:cc:dd:ee:ff";
bool present = false;
unsigned long lastSeen = 0;
const unsigned long TIMEOUT_MS = 60000; // 1 phut khong thay -> coi nhu vang mat
void connectWifiMqtt() {
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
mqtt.setServer(MQTT_HOST, 1883);
while (!mqtt.connected()) {
mqtt.connect("esp32-presence");
delay(500);
}
}
void setup() {
Serial.begin(115200);
connectWifiMqtt();
BLEDevice::init("");
bleScan = BLEDevice::getScan();
bleScan->setActiveScan(false); // quet thu dong, tiet kiem pin dien thoai hon
}
void loop() {
if (!mqtt.connected()) connectWifiMqtt();
mqtt.loop();
BLEScanResults* results = bleScan->start(5, false); // quet 5 giay moi vong
bool foundNow = false;
for (int i = 0; i < results->getCount(); i++) {
BLEAdvertisedDevice device = results->getDevice(i);
if (device.getAddress().toString() == KNOWN_MAC) {
foundNow = true;
lastSeen = millis();
break;
}
}
bleScan->clearResults();
bool nowPresent = (millis() - lastSeen) < TIMEOUT_MS;
if (nowPresent != present) {
present = nowPresent;
mqtt.publish("home/presence/phone1", present ? "home" : "away", true);
Serial.println(present ? "Da ve nha" : "Da roi di");
}
delay(10000); // nghi giua cac lan quet
}
Những lỗi thường gặp
- Địa chỉ MAC ngẫu nhiên (MAC randomization): iOS và Android hiện đại thường xuyên đổi MAC quảng bá để bảo vệ quyền riêng tư, khiến việc theo dõi bằng MAC cố định không ổn định. Giải pháp thực tế: dùng một thiết bị BLE chuyên dụng phát MAC cố định (vòng đeo tay, tag BLE như Nordic Thingy hoặc beacon iBeacon) thay vì trực tiếp điện thoại, hoặc chấp nhận độ chính xác không tuyệt đối.
- Ngưỡng timeout quá ngắn khiến hệ thống báo “vắng mặt” giả khi điện thoại tạm thời không quảng bá BLE (màn hình khóa, tiết kiệm pin) — nên để timeout tối thiểu 1-2 phút.
- Quét quá thường xuyên làm nóng ESP32 và tốn điện không cần thiết — quét 5 giây, nghỉ 5-10 giây là đủ cho hầu hết nhu cầu nhà ở.
- Không xử lý mất kết nối WiFi/MQTT khiến thiết bị “treo” âm thầm — luôn kiểm tra và tự kết nối lại như trong code mẫu.
Mở rộng
Theo dõi nhiều thiết bị cùng lúc (mỗi thành viên trong nhà một MAC) để phân biệt “có người” và “ai đang ở nhà”, kết hợp với cảm biến chuyển động PIR để tăng độ tin cậy, hoặc tích hợp trực tiếp vào Home Assistant qua ESPHome thay vì tự viết firmware MQTT thủ công.
Thẻ:#esp32#bluetooth#home-automation
Bình luận