Mi Smart Band 4, Address: cd:0b:a8:85:32:1f
Amazfit T-Rex, Address: c3:39:ed:41:a4:a6
iTAG 1, Address: 53:23:7b:ac:93:a5
iTAG 2, Address: ff:ff:11:50:e9:9a
iTAG 3, Address: ff:ff:11:51:07:e2
// keyless
// DATA BLE ASUN
// 1. Amazfit T-Rex, Address: c3:39:ed:41:a4:a6
// 2. Mi Smart Band 4, Address: cd:0b:a8:85:32:1f
// 3. Mi Band 3, Address: eb:b0:13:96:32:16
// 4. B01_M4, Address: 02:fc:da:d7:dc:97
// BOARD: FireBeetle.esp32
// Flash : 80mhz
// upload : 921600
// progrmmer : avr ISP
// elco 1uf/10uf/25uf
// + ke EN & - ke GND
// tidak perlu tekan apapun
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#define kontak 2 // PIN D2 untuk relay
#define LED1 12 // PIN D12 untuk LED indikator 1
#define LED2 13 // PIN D13 untuk LED indikator 2
#define LED3 14 // PIN D14 untuk LED indikator 3
#define LED4 15 // PIN D15 untuk LED indikator 4
#define LED5 16 // PIN D16 untuk LED indikator 5
String knownBLEAddresses[] = {"c3:39:ed:41:a4:a6"}; //masukan address itag kalian AMAZFIT T RTEX
bool device_found = false;
int scanTime = 1; //In seconds
int tapCount = 0;
unsigned long lastTapTime = 0;
unsigned long relayStartTime = 0;
unsigned long relayDuration = 0;
bool relayActive = false;
// Array untuk LED indikator
int ledPins[] = {LED1, LED2, LED3, LED4, LED5};
int numLeds = 5;
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
bool dapat = false;
for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++) {
String deviceAddr = String(advertisedDevice.getAddress().toString().c_str());
deviceAddr.toLowerCase();
String knownAddr = String(knownBLEAddresses[i].c_str());
knownAddr.toLowerCase();
if (deviceAddr == knownAddr) {
dapat = true;
break;
}
}
if (dapat) {
Serial.println("Device ditemukan!");
Serial.print("Address: ");
Serial.println(advertisedDevice.getAddress().toString().c_str());
Serial.print("RSSI: ");
Serial.println(advertisedDevice.getRSSI());
if (advertisedDevice.getRSSI() > -50) {
device_found = true;
Serial.println("Device dalam jangkauan - siap untuk tap");
} else {
device_found = false;
Serial.println("Device terlalu jauh");
}
}
// Uncomment untuk debug semua device BLE
// Serial.printf("BLE Device: %s RSSI: %d\n", advertisedDevice.getAddress().toString().c_str(), advertisedDevice.getRSSI());
}
};
void setup() {
Serial.begin(115200);
Serial.println("Memulai BLE Scanner...");
// Inisialisasi pin relay
pinMode(kontak, OUTPUT);
digitalWrite(kontak, LOW);
// Inisialisasi pin LED
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
BLEDevice::init("");
pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
Serial.println("System ready - Waiting for BLE device...");
Serial.print("Monitoring address: ");
for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++) {
Serial.println(knownBLEAddresses[i]);
}
}
void updateLEDs() {
// Matikan semua LED terlebih dahulu
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
// Nyalakan LED sesuai jumlah tap
for (int i = 0; i < tapCount && i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
Serial.print("LED status: ");
Serial.print(tapCount);
Serial.println(" LED(s) ON");
}
void countTap() {
unsigned long currentTime = millis();
// Reset tap count jika lebih dari 3 detik sejak tap terakhir
if (currentTime - lastTapTime > 3000) {
tapCount = 0;
Serial.println("Tap count reset - timeout");
updateLEDs();
}
tapCount++;
lastTapTime = currentTime;
// Batasi maksimal tap count sampai 6
if (tapCount > 6) {
tapCount = 6;
}
Serial.print("Tap count: ");
Serial.println(tapCount);
// Update LED indikator
updateLEDs();
// Tentukan durasi berdasarkan jumlah tap
if (tapCount == 1) {
relayDuration = 60000; // 1 menit
} else if (tapCount == 2) {
relayDuration = 120000; // 2 menit
} else if (tapCount == 3) {
relayDuration = 180000; // 3 menit
} else if (tapCount == 4) {
relayDuration = 240000; // 4 menit
} else if (tapCount == 5) {
relayDuration = 300000; // 5 menit
} else if (tapCount >= 6) {
// Matikan relay dan reset semua
relayActive = false;
tapCount = 0;
digitalWrite(kontak, LOW);
updateLEDs();
Serial.println("Relay OFF - All LEDs OFF - Tap 6x");
return;
}
// Aktifkan relay
relayActive = true;
relayStartTime = currentTime;
digitalWrite(kontak, HIGH);
Serial.print("Relay ON for ");
Serial.print(relayDuration / 60000);
Serial.println(" minute(s)");
}
void loop() {
// PERBAIKAN: Gunakan pointer BLEScanResults* atau tidak perlu variabel
pBLEScan->start(scanTime, false); // Tidak perlu simpan hasilnya
if (device_found) {
Serial.println("BLE device detected - Counting tap...");
countTap();
device_found = false;
delay(1000);
}
// Cek timer relay
if (relayActive) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - relayStartTime;
// Tampilkan countdown setiap 10 detik
static unsigned long lastCountdown = 0;
if (currentTime - lastCountdown >= 10000) {
lastCountdown = currentTime;
unsigned long remaining = (relayDuration - elapsedTime) / 1000;
Serial.print("Time remaining: ");
Serial.print(remaining);
Serial.println(" seconds");
}
if (elapsedTime >= relayDuration) {
relayActive = false;
digitalWrite(kontak, LOW);
tapCount = 0;
updateLEDs();
Serial.println("Relay OFF - Timeout");
}
}
pBLEScan->clearResults();
delay(100);
}
Keyless With Timer ini akan menyala ketika di dekatkan dengan smartwatch. 1 kali dekat 1 menit on, 2 kali dekat 2 menit on sampai 5 kali dekat 5 menit, ke 6 kali lampu OFF.
// keyless 86
// DATA BLE ASUN
// 1. Amazfit T-Rex, Address: c3:39:ed:41:a4:a6
// 2. Mi Smart Band 4, Address: cd:0b:a8:85:32:1f
// 3. Mi Band 3, Address: eb:b0:13:96:32:16
// 4. B01_M4, Address: 02:fc:da:d7:dc:97
// BOARD: FireBeetle.esp32
// Flash : 80mhz
// upload : 921600
// progrmmer : avr ISP
// elco 1uf/10uf/25uf
// + ke EN & - ke GND
// tidak perlu tekan apapun
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#define kontak 2 // PIN D2 untuk relay
#define LED1 12 // PIN D12 untuk LED indikator 1
#define LED2 13 // PIN D13 untuk LED indikator 2
#define LED3 14 // PIN D14 untuk LED indikator 3
#define LED4 15 // PIN D15 untuk LED indikator 4
#define LED5 16 // PIN D16 untuk LED indikator 5
String knownBLEAddresses[] = {"c3:39:ed:41:a4:a6"}; //masukan address itag kalian AMAZFIT T RTEX
bool device_found = false;
int scanTime = 1; //In seconds
int tapCount = 0;
unsigned long lastTapTime = 0;
unsigned long relayStartTime = 0;
unsigned long relayDuration = 0;
bool relayActive = false;
// Array untuk LED indikator
int ledPins[] = {LED1, LED2, LED3, LED4, LED5};
int numLeds = 5;
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
bool dapat = false;
for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++) {
String deviceAddr = String(advertisedDevice.getAddress().toString().c_str());
deviceAddr.toLowerCase();
String knownAddr = String(knownBLEAddresses[i].c_str());
knownAddr.toLowerCase();
if (deviceAddr == knownAddr) {
dapat = true;
break;
}
}
if (dapat) {
Serial.println("Device ditemukan!");
Serial.print("Address: ");
Serial.println(advertisedDevice.getAddress().toString().c_str());
Serial.print("RSSI: ");
Serial.println(advertisedDevice.getRSSI());
if (advertisedDevice.getRSSI() > -50) {
device_found = true;
Serial.println("Device dalam jangkauan - siap untuk tap");
} else {
device_found = false;
Serial.println("Device terlalu jauh");
}
}
// Uncomment untuk debug semua device BLE
// Serial.printf("BLE Device: %s RSSI: %d\n", advertisedDevice.getAddress().toString().c_str(), advertisedDevice.getRSSI());
}
};
void setup() {
Serial.begin(115200);
Serial.println("Memulai BLE Scanner...");
// Inisialisasi pin relay
pinMode(kontak, OUTPUT);
digitalWrite(kontak, LOW);
// Inisialisasi pin LED
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
BLEDevice::init("");
pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
Serial.println("System ready - Waiting for BLE device...");
Serial.print("Monitoring address: ");
for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++) {
Serial.println(knownBLEAddresses[i]);
}
}
void updateLEDs() {
// Matikan semua LED terlebih dahulu
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
// Nyalakan LED sesuai jumlah tap
for (int i = 0; i < tapCount && i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
Serial.print("LED status: ");
Serial.print(tapCount);
Serial.println(" LED(s) ON");
}
void countTap() {
unsigned long currentTime = millis();
// Reset tap count jika lebih dari 3 detik sejak tap terakhir
if (currentTime - lastTapTime > 3000) {
tapCount = 0;
Serial.println("Tap count reset - timeout");
updateLEDs();
}
tapCount++;
lastTapTime = currentTime;
// Kembali ke mode 1 setelah mode 5
if (tapCount > 5) {
tapCount = 1;
Serial.println("Kembali ke Mode 1");
}
Serial.print("Tap count: ");
Serial.println(tapCount);
// Update LED indikator
updateLEDs();
// Tentukan durasi berdasarkan jumlah tap
if (tapCount == 1) {
relayDuration = 60000; // 1 menit
} else if (tapCount == 2) {
relayDuration = 120000; // 2 menit
} else if (tapCount == 3) {
relayDuration = 180000; // 3 menit
} else if (tapCount == 4) {
relayDuration = 240000; // 4 menit
} else if (tapCount == 5) {
relayDuration = 300000; // 5 menit
}
// Aktifkan relay
relayActive = true;
relayStartTime = currentTime;
digitalWrite(kontak, HIGH);
Serial.print("Relay ON for ");
Serial.print(relayDuration / 60000);
Serial.println(" minute(s)");
}
void loop() {
// PERBAIKAN: Gunakan pointer BLEScanResults* atau tidak perlu variabel
pBLEScan->start(scanTime, false); // Tidak perlu simpan hasilnya
if (device_found) {
Serial.println("BLE device detected - Counting tap...");
countTap();
device_found = false;
delay(1000);
}
// Cek timer relay
if (relayActive) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - relayStartTime;
// Tampilkan countdown setiap 10 detik
static unsigned long lastCountdown = 0;
if (currentTime - lastCountdown >= 10000) {
lastCountdown = currentTime;
unsigned long remaining = (relayDuration - elapsedTime) / 1000;
Serial.print("Time remaining: ");
Serial.print(remaining);
Serial.println(" seconds");
}
if (elapsedTime >= relayDuration) {
relayActive = false;
digitalWrite(kontak, LOW);
tapCount = 0;
updateLEDs();
Serial.println("Relay OFF - Timeout");
}
}
pBLEScan->clearResults();
delay(100);
}
Keyless With Timer ini akan menyala ketika di dekatkan dengan smartwatch. 1 kali dekat 1 menit on, 2 kali dekat 2 menit on sampai 5 kali dekat 5 menit, setelah 5 kali tap kembali lagi ke mode 1, dibarengi dengan LED Indikator ada 5 LED
// keyless 86
// DATA BLE ASUN
// 1. Amazfit T-Rex, Address: c3:39:ed:41:a4:a6
// 2. Mi Smart Band 4, Address: cd:0b:a8:85:32:1f
// 3. Mi Band 3, Address: eb:b0:13:96:32:16
// 4. B01_M4, Address: 02:fc:da:d7:dc:97
// BOARD: FireBeetle.esp32
// Flash : 80mhz
// upload : 921600
// progrmmer : avr ISP
// elco 1uf/10uf/25uf
// + ke EN & - ke GND
// tidak perlu tekan apapun
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#define kontak 2 // PIN D2 untuk relay
#define LED1 12 // PIN D12 untuk LED indikator 1
#define LED2 13 // PIN D13 untuk LED indikator 2
#define LED3 14 // PIN D14 untuk LED indikator 3
#define LED4 15 // PIN D15 untuk LED indikator 4
#define LED5 16 // PIN D16 untuk LED indikator 5
String knownBLEAddresses[] = {"c3:39:ed:41:a4:a6"}; //masukan address itag AMAZFIT T RTEX
bool device_found = false;
int scanTime = 1; //In seconds
int tapCount = 0;
unsigned long lastTapTime = 0;
unsigned long relayStartTime = 0;
unsigned long relayDuration = 0;
bool relayActive = false;
// Variabel baru untuk mode selamat datang dan 30 menit
bool welcomeAnimationDone = false;
bool auto30minActive = false;
unsigned long auto30minStartTime = 0;
const unsigned long auto30minDuration = 1800000; // 30 menit dalam milidetik
// Array untuk LED indikator
int ledPins[] = {LED1, LED2, LED3, LED4, LED5};
int numLeds = 5;
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
bool dapat = false;
for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++) {
String deviceAddr = String(advertisedDevice.getAddress().toString().c_str());
deviceAddr.toLowerCase();
String knownAddr = String(knownBLEAddresses[i].c_str());
knownAddr.toLowerCase();
if (deviceAddr == knownAddr) {
dapat = true;
break;
}
}
if (dapat) {
Serial.println("Device ditemukan!");
Serial.print("Address: ");
Serial.println(advertisedDevice.getAddress().toString().c_str());
Serial.print("RSSI: ");
Serial.println(advertisedDevice.getRSSI());
if (advertisedDevice.getRSSI() > -60) {
device_found = true;
Serial.println("Device dalam jangkauan - siap untuk tap");
// BLE terdeteksi, nonaktifkan mode 30 menit otomatis
if (auto30minActive) {
auto30minActive = false;
digitalWrite(kontak, LOW);
Serial.println("Mode 30 menit otomatis dinonaktifkan - BLE terdeteksi");
}
} else {
device_found = false;
Serial.println("Device terlalu jauh");
}
}
// Uncomment untuk debug semua device BLE
// Serial.printf("BLE Device: %s RSSI: %d\n", advertisedDevice.getAddress().toString().c_str(), advertisedDevice.getRSSI());
}
};
void welcomeAnimation() {
Serial.println("Memulai animasi selamat datang...");
// Animasi LED berkedip bergantian 500ms
for (int cycle = 0; cycle < 3; cycle++) { // Ulangi 3 kali
// Mode 1: LED1 menyala
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i == 0) ? HIGH : LOW);
}
delay(500);
// Mode 2: LED1 & LED2 menyala
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 1) ? HIGH : LOW);
}
delay(500);
// Mode 3: LED1, LED2, LED3 menyala
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 2) ? HIGH : LOW);
}
delay(500);
// Mode 4: LED1, LED2, LED3, LED4 menyala
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 3) ? HIGH : LOW);
}
delay(500);
// Mode 5: Semua LED menyala
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
delay(500);
// Matikan semua LED
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
delay(500);
}
Serial.println("Animasi selamat datang selesai");
welcomeAnimationDone = true;
}
void startAuto30min() {
if (!auto30minActive && !relayActive) {
auto30minActive = true;
auto30minStartTime = millis();
digitalWrite(kontak, HIGH);
Serial.println("Mode 30 menit otomatis diaktifkan");
Serial.println("Relay ON untuk 30 menit");
// Nyalakan semua LED sebagai indikator mode 30 menit
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
}
}
void updateLEDs() {
// Matikan semua LED terlebih dahulu
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
// Nyalakan LED sesuai jumlah tap
for (int i = 0; i < tapCount && i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
Serial.print("LED status: ");
Serial.print(tapCount);
Serial.println(" LED(s) ON");
}
void countTap() {
unsigned long currentTime = millis();
// Reset tap count jika lebih dari 3 detik sejak tap terakhir
if (currentTime - lastTapTime > 3000) {
tapCount = 0;
Serial.println("Tap count reset - timeout");
updateLEDs();
}
tapCount++;
lastTapTime = currentTime;
// Kembali ke mode 1 setelah mode 5
if (tapCount > 5) {
tapCount = 1;
Serial.println("Kembali ke Mode 1");
}
Serial.print("Tap count: ");
Serial.println(tapCount);
// Update LED indikator
updateLEDs();
// Tentukan durasi berdasarkan jumlah tap
if (tapCount == 1) {
relayDuration = 60000; // 1 menit
} else if (tapCount == 2) {
relayDuration = 120000; // 2 menit
} else if (tapCount == 3) {
relayDuration = 180000; // 3 menit
} else if (tapCount == 4) {
relayDuration = 240000; // 4 menit
} else if (tapCount == 5) {
relayDuration = 300000; // 5 menit
}
// Aktifkan relay
relayActive = true;
relayStartTime = currentTime;
digitalWrite(kontak, HIGH);
Serial.print("Relay ON for ");
Serial.print(relayDuration / 60000);
Serial.println(" minute(s)");
}
void setup() {
Serial.begin(115200);
Serial.println("Memulai BLE Scanner...");
// Inisialisasi pin relay
pinMode(kontak, OUTPUT);
digitalWrite(kontak, LOW);
// Inisialisasi pin LED
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
BLEDevice::init("");
pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
Serial.println("System ready - Waiting for BLE device...");
Serial.print("Monitoring address: ");
for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++) {
Serial.println(knownBLEAddresses[i]);
}
// Jalankan animasi selamat datang
welcomeAnimation();
// Mulai mode 30 menit otomatis setelah animasi selesai
startAuto30min();
}
void loop() {
// Jalankan animasi selamat datang jika belum selesai
if (!welcomeAnimationDone) {
welcomeAnimation();
startAuto30min();
}
// PERBAIKAN: Gunakan pointer BLEScanResults* atau tidak perlu variabel
pBLEScan->start(scanTime, false); // Tidak perlu simpan hasilnya
if (device_found) {
Serial.println("BLE device detected - Counting tap...");
countTap();
device_found = false;
delay(1000);
}
// Cek timer relay (mode BLE)
if (relayActive) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - relayStartTime;
// Tampilkan countdown setiap 10 detik
static unsigned long lastCountdown = 0;
if (currentTime - lastCountdown >= 10000) {
lastCountdown = currentTime;
unsigned long remaining = (relayDuration - elapsedTime) / 1000;
Serial.print("Time remaining (BLE mode): ");
Serial.print(remaining);
Serial.println(" seconds");
}
if (elapsedTime >= relayDuration) {
relayActive = false;
digitalWrite(kontak, LOW);
tapCount = 0;
updateLEDs();
Serial.println("Relay OFF - Timeout (BLE mode)");
}
}
// Cek timer 30 menit otomatis
if (auto30minActive && !relayActive) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - auto30minStartTime;
// Tampilkan countdown setiap 30 detik
static unsigned long lastAutoCountdown = 0;
if (currentTime - lastAutoCountdown >= 30000) {
lastAutoCountdown = currentTime;
unsigned long remaining = (auto30minDuration - elapsedTime) / 1000;
Serial.print("Time remaining (Auto 30min): ");
Serial.print(remaining / 60);
Serial.print(" minutes ");
Serial.print(remaining % 60);
Serial.println(" seconds");
}
if (elapsedTime >= auto30minDuration) {
auto30minActive = false;
digitalWrite(kontak, LOW);
// Matikan semua LED
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
Serial.println("Auto 30min mode OFF - Timeout");
}
}
pBLEScan->clearResults();
delay(100);
}
Penjelasan tambahan yang saya buat:
Animasi Selamat Datang:
LED akan berkedip bergantian menunjukkan mode 1-5 dengan interval 500ms
Diulang 3 kali cycle kemudian semua LED mati
Mode 30 Menit Otomatis:
Setelah animasi selesai, relay langsung HIGH selama 30 menit
Semua LED menyala sebagai indikator mode ini aktif
Prioritas BLE:
Ketika BLE terdeteksi, mode 30 menit otomatis langsung dinonaktifkan
Sistem kembali ke mode normal (1-5) sesuai tap count
Indikator Visual:
Mode 30 menit: Semua LED menyala
Mode BLE: LED menyala sesuai jumlah tap (1-5 LED)
Monitoring Waktu:
Countdown untuk mode 30 menit ditampilkan setiap 30 detik
Countdown untuk mode BLE tetap setiap 10 detik
Fitur ini memberikan pengalaman "selamat datang" yang menarik bagi pengguna saat pertama kali menyalakan perangkat, sambil tetap mempertahankan fungsionalitas utama sistem BLE yang sudah ada.
// lima 5 Tag
// keyless 86
// DATA BLE ASUN
// Mi Smart Band 4, Address: cd:0b:a8:85:32:1f
// Amazfit T-Rex, Address: c3:39:ed:41:a4:a6
// iTAG 1, Address: 53:23:7b:ac:93:a5
// iTAG 2, Address: ff:ff:11:50:e9:9a
// iTAG 3, Address: ff:ff:11:51:07:e2
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
// Pin definitions
#define kontak 2 // PIN D2 untuk relay
#define LED1 12 // PIN D12 untuk LED indikator 1
#define LED2 13 // PIN D13 untuk LED indikator 2
#define LED3 14 // PIN D14 untuk LED indikator 3
#define LED4 15 // PIN D15 untuk LED indikator 4
#define LED5 16 // PIN D16 untuk LED indikator 5
// BLE Addresses
String knownBLEAddresses[] = {
"c3:39:ed:41:a4:a6",
"cd:0b:a8:85:32:1f",
"53:23:7b:ac:93:a5",
"ff:ff:11:50:e9:9a",
"ff:ff:11:51:07:e2"
};
// Global variables
bool device_found = false;
int scanTime = 1; // In seconds
int tapCount = 0;
unsigned long lastTapTime = 0;
unsigned long relayStartTime = 0;
unsigned long relayDuration = 0;
bool relayActive = false;
// Variables for welcome mode and 30 minutes
bool welcomeAnimationDone = false;
bool auto30minActive = false;
unsigned long auto30minStartTime = 0;
const unsigned long auto30minDuration = 1800000; // 30 minutes
// Improved BLE detection variables
unsigned long lastBLEDetectionTime = 0;
const unsigned long BLE_COOLDOWN_TIME = 800; // Reduced to 800ms for faster tapping
const unsigned long TAP_TIMEOUT = 4000; // Increased to 4 seconds for more comfortable tapping
bool canAcceptTap = true;
// LED array
int ledPins[] = {LED1, LED2, LED3, LED4, LED5};
int numLeds = 5;
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
unsigned long currentTime = millis();
// Cooldown check - hanya terima tap setiap 800ms
if (currentTime - lastBLEDetectionTime < BLE_COOLDOWN_TIME || !canAcceptTap) {
return;
}
bool deviceFound = false;
String deviceAddress = String(advertisedDevice.getAddress().toString().c_str());
deviceAddress.toLowerCase();
for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++) {
String knownAddr = String(knownBLEAddresses[i].c_str());
knownAddr.toLowerCase();
if (deviceAddress == knownAddr) {
deviceFound = true;
break;
}
}
if (deviceFound) {
int rssi = advertisedDevice.getRSSI();
// RSSI threshold yang lebih longgar
if (rssi > -60) { // Diubah ke -75 untuk detection yang sangat mudah
Serial.println("=== BLE Device Detected ===");
Serial.print("Address: ");
Serial.println(deviceAddress);
Serial.print("RSSI: ");
Serial.println(rssi);
device_found = true;
lastBLEDetectionTime = currentTime;
canAcceptTap = false; // Sementara tidak terima tap baru
// Disable auto 30min mode when BLE detected
if (auto30minActive) {
auto30minActive = false;
digitalWrite(kontak, LOW);
// Turn off 30min mode LEDs
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
Serial.println("Auto 30min mode disabled");
}
Serial.println("Ready for tap counting...");
Serial.println("========================");
}
}
}
};
void welcomeAnimation() {
Serial.println("Starting welcome animation...");
// LED blinking animation 500ms
for (int cycle = 0; cycle < 3; cycle++) {
// Mode 1: LED1 ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i == 0) ? HIGH : LOW);
}
delay(500);
// Mode 2: LED1 & LED2 ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 1) ? HIGH : LOW);
}
delay(500);
// Mode 3: LED1, LED2, LED3 ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 2) ? HIGH : LOW);
}
delay(500);
// Mode 4: LED1, LED2, LED3, LED4 ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 3) ? HIGH : LOW);
}
delay(500);
// Mode 5: All LEDs ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
delay(500);
// All LEDs OFF
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
delay(500);
}
Serial.println("Welcome animation completed");
welcomeAnimationDone = true;
}
void startAuto30min() {
if (!auto30minActive && !relayActive) {
auto30minActive = true;
auto30minStartTime = millis();
digitalWrite(kontak, HIGH);
Serial.println("Auto 30min mode activated");
Serial.println("Relay ON for 30 minutes");
// Turn on all LEDs as indicator
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
}
}
void updateLEDs() {
// Turn off all LEDs first
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
// Turn on LEDs according to tap count
for (int i = 0; i < tapCount && i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
Serial.print(">>> Mode ");
Serial.print(tapCount);
Serial.print(" - ");
Serial.print(tapCount);
Serial.println(" LED ON <<<");
}
void countTap() {
unsigned long currentTime = millis();
// Reset tap count jika lebih dari 4 detik sejak tap terakhir
if (currentTime - lastTapTime > TAP_TIMEOUT) {
tapCount = 0;
Serial.println(">>> Tap sequence reset <<<");
updateLEDs();
}
tapCount++;
lastTapTime = currentTime;
// Kembali ke mode 1 setelah mode 5
if (tapCount > 5) {
tapCount = 1;
Serial.println(">>> Back to Mode 1 <<<");
}
Serial.print(">>> TAP ");
Serial.print(tapCount);
Serial.println(" DETECTED <<<");
// Update LED indicator
updateLEDs();
// Set duration based on tap count
switch(tapCount) {
case 1:
relayDuration = 60000; // 1 minute
break;
case 2:
relayDuration = 120000; // 2 minutes
break;
case 3:
relayDuration = 180000; // 3 minutes
break;
case 4:
relayDuration = 240000; // 4 minutes
break;
case 5:
relayDuration = 300000; // 5 minutes
break;
}
// Aktifkan relay
relayActive = true;
relayStartTime = currentTime;
digitalWrite(kontak, HIGH);
Serial.println("****************************");
Serial.print("*** RELAY ON - MODE ");
Serial.print(tapCount);
Serial.print(" - ");
Serial.print(relayDuration / 60000);
Serial.println(" MINUTES ***");
Serial.println("****************************");
// Reset flag untuk menerima tap berikutnya setelah delay singkat
canAcceptTap = true;
}
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE Scanner...");
// Initialize relay pin
pinMode(kontak, OUTPUT);
digitalWrite(kontak, LOW);
// Initialize LED pins
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
BLEDevice::init("");
pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
Serial.println("System ready - Waiting for BLE device...");
Serial.print("Monitoring ");
Serial.print(sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0]));
Serial.println(" BLE addresses:");
for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++) {
Serial.print(" ");
Serial.println(knownBLEAddresses[i]);
}
// Run welcome animation
welcomeAnimation();
// Start auto 30min mode after animation
startAuto30min();
}
void loop() {
// Run welcome animation if not done
if (!welcomeAnimationDone) {
welcomeAnimation();
startAuto30min();
}
// BLE scan
pBLEScan->start(scanTime, false);
if (device_found) {
Serial.println(">>> Processing BLE detection <<<");
countTap();
device_found = false;
// Beri waktu sangat singkat sebelum bisa terima tap lagi
delay(200);
}
// Check relay timer (BLE mode)
if (relayActive) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - relayStartTime;
// Show countdown every 10 seconds
static unsigned long lastCountdown = 0;
if (currentTime - lastCountdown >= 10000) {
lastCountdown = currentTime;
unsigned long remaining = (relayDuration > elapsedTime) ? (relayDuration - elapsedTime) / 1000 : 0;
Serial.print("Time remaining (Mode ");
Serial.print(tapCount);
Serial.print("): ");
Serial.print(remaining);
Serial.println(" seconds");
}
if (elapsedTime >= relayDuration) {
relayActive = false;
digitalWrite(kontak, LOW);
tapCount = 0;
updateLEDs();
Serial.println(">>> Relay OFF - Ready for new sequence <<<");
}
}
// Check 30min auto timer
if (auto30minActive && !relayActive) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - auto30minStartTime;
// Show countdown every 30 seconds
static unsigned long lastAutoCountdown = 0;
if (currentTime - lastAutoCountdown >= 30000) {
lastAutoCountdown = currentTime;
unsigned long remaining = (auto30minDuration > elapsedTime) ? (auto30minDuration - elapsedTime) / 1000 : 0;
Serial.print("Time remaining (Auto 30min): ");
Serial.print(remaining / 60);
Serial.print(" minutes ");
Serial.print(remaining % 60);
Serial.println(" seconds");
}
if (elapsedTime >= auto30minDuration) {
auto30minActive = false;
digitalWrite(kontak, LOW);
// Turn off all LEDs
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
Serial.println("Auto 30min mode OFF - Timeout");
}
}
// Reset canAcceptTap flag setelah cooldown period
if (!canAcceptTap && (millis() - lastBLEDetectionTime > BLE_COOLDOWN_TIME)) {
canAcceptTap = true;
}
pBLEScan->clearResults();
delay(100);
}
// MULTY BLE TAG
// keyless 86 - UNIVERSAL BLE DETECTOR
// Semua device BLE dengan RSSI > -60 akan dieksekusi
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
// Pin definitions
#define kontak 2 // PIN D2 untuk relay
#define LED1 12 // PIN D12 untuk LED indikator 1
#define LED2 13 // PIN D13 untuk LED indikator 2
#define LED3 14 // PIN D14 untuk LED indikator 3
#define LED4 15 // PIN D15 untuk LED indikator 4
#define LED5 16 // PIN D16 untuk LED indikator 5
// Global variables
bool device_found = false;
int scanTime = 1; // In seconds
int tapCount = 0;
unsigned long lastTapTime = 0;
unsigned long relayStartTime = 0;
unsigned long relayDuration = 0;
bool relayActive = false;
// Variables for welcome mode and 30 minutes
bool welcomeAnimationDone = false;
bool auto30minActive = false;
unsigned long auto30minStartTime = 0;
const unsigned long auto30minDuration = 1800000; // 30 minutes
// Improved BLE detection variables
unsigned long lastBLEDetectionTime = 0;
const unsigned long BLE_COOLDOWN_TIME = 800; // Reduced to 800ms for faster tapping
const unsigned long TAP_TIMEOUT = 4000; // Increased to 4 seconds for more comfortable tapping
bool canAcceptTap = true;
// LED array
int ledPins[] = {LED1, LED2, LED3, LED4, LED5};
int numLeds = 5;
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
unsigned long currentTime = millis();
// Cooldown check - hanya terima tap setiap 800ms
if (currentTime - lastBLEDetectionTime < BLE_COOLDOWN_TIME || !canAcceptTap) {
return;
}
int rssi = advertisedDevice.getRSSI();
String deviceAddress = String(advertisedDevice.getAddress().toString().c_str());
String deviceName = String(advertisedDevice.getName().c_str());
// Terima SEMUA device BLE dengan RSSI > -60
if (rssi > -60) {
Serial.println("=== UNIVERSAL BLE DEVICE DETECTED ===");
Serial.print("Address: ");
Serial.println(deviceAddress);
Serial.print("Name: ");
Serial.println(deviceName);
Serial.print("RSSI: ");
Serial.println(rssi);
device_found = true;
lastBLEDetectionTime = currentTime;
canAcceptTap = false; // Sementara tidak terima tap baru
// Disable auto 30min mode when BLE detected
if (auto30minActive) {
auto30minActive = false;
digitalWrite(kontak, LOW);
// Turn off 30min mode LEDs
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
Serial.println("Auto 30min mode disabled - BLE detected");
}
Serial.println("Ready for tap counting...");
Serial.println("================================");
}
}
};
void welcomeAnimation() {
Serial.println("Starting welcome animation...");
// LED blinking animation 500ms
for (int cycle = 0; cycle < 3; cycle++) {
// Mode 1: LED1 ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i == 0) ? HIGH : LOW);
}
delay(500);
// Mode 2: LED1 & LED2 ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 1) ? HIGH : LOW);
}
delay(500);
// Mode 3: LED1, LED2, LED3 ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 2) ? HIGH : LOW);
}
delay(500);
// Mode 4: LED1, LED2, LED3, LED4 ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], (i <= 3) ? HIGH : LOW);
}
delay(500);
// Mode 5: All LEDs ON
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
delay(500);
// All LEDs OFF
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
delay(500);
}
Serial.println("Welcome animation completed");
welcomeAnimationDone = true;
}
void startAuto30min() {
if (!auto30minActive && !relayActive) {
auto30minActive = true;
auto30minStartTime = millis();
digitalWrite(kontak, HIGH);
Serial.println("Auto 30min mode activated");
Serial.println("Relay ON for 30 minutes");
// Turn on all LEDs as indicator
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
}
}
void updateLEDs() {
// Turn off all LEDs first
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
// Turn on LEDs according to tap count
for (int i = 0; i < tapCount && i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH);
}
Serial.print(">>> Mode ");
Serial.print(tapCount);
Serial.print(" - ");
Serial.print(tapCount);
Serial.println(" LED ON <<<");
}
void countTap() {
unsigned long currentTime = millis();
// Reset tap count jika lebih dari 4 detik sejak tap terakhir
if (currentTime - lastTapTime > TAP_TIMEOUT) {
tapCount = 0;
Serial.println(">>> Tap sequence reset <<<");
updateLEDs();
}
tapCount++;
lastTapTime = currentTime;
// Kembali ke mode 1 setelah mode 5
if (tapCount > 5) {
tapCount = 1;
Serial.println(">>> Back to Mode 1 <<<");
}
Serial.print(">>> TAP ");
Serial.print(tapCount);
Serial.println(" DETECTED <<<");
// Update LED indicator
updateLEDs();
// Set duration based on tap count
switch(tapCount) {
case 1:
relayDuration = 60000; // 1 minute
break;
case 2:
relayDuration = 120000; // 2 minutes
break;
case 3:
relayDuration = 180000; // 3 minutes
break;
case 4:
relayDuration = 240000; // 4 minutes
break;
case 5:
relayDuration = 300000; // 5 minutes
break;
}
// Aktifkan relay
relayActive = true;
relayStartTime = currentTime;
digitalWrite(kontak, HIGH);
Serial.println("****************************");
Serial.print("*** RELAY ON - MODE ");
Serial.print(tapCount);
Serial.print(" - ");
Serial.print(relayDuration / 60000);
Serial.println(" MINUTES ***");
Serial.println("****************************");
// Reset flag untuk menerima tap berikutnya setelah delay singkat
canAcceptTap = true;
}
void setup() {
Serial.begin(115200);
Serial.println("Starting UNIVERSAL BLE Scanner...");
Serial.println("SYSTEM: ALL BLE DEVICES ACCEPTED (RSSI > -60)");
// Initialize relay pin
pinMode(kontak, OUTPUT);
digitalWrite(kontak, LOW);
// Initialize LED pins
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
BLEDevice::init("");
pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
Serial.println("System ready - Waiting for ANY BLE device...");
Serial.println("NOTE: All BLE devices with RSSI > -60 will be accepted");
// Run welcome animation
welcomeAnimation();
// Start auto 30min mode after animation
startAuto30min();
}
void loop() {
// Run welcome animation if not done
if (!welcomeAnimationDone) {
welcomeAnimation();
startAuto30min();
}
// BLE scan
pBLEScan->start(scanTime, false);
if (device_found) {
Serial.println(">>> Processing BLE detection <<<");
countTap();
device_found = false;
// Beri waktu sangat singkat sebelum bisa terima tap lagi
delay(200);
}
// Check relay timer (BLE mode)
if (relayActive) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - relayStartTime;
// Show countdown every 10 seconds
static unsigned long lastCountdown = 0;
if (currentTime - lastCountdown >= 10000) {
lastCountdown = currentTime;
unsigned long remaining = (relayDuration > elapsedTime) ? (relayDuration - elapsedTime) / 1000 : 0;
Serial.print("Time remaining (Mode ");
Serial.print(tapCount);
Serial.print("): ");
Serial.print(remaining);
Serial.println(" seconds");
}
if (elapsedTime >= relayDuration) {
relayActive = false;
digitalWrite(kontak, LOW);
tapCount = 0;
updateLEDs();
Serial.println(">>> Relay OFF - Timeout <<<");
Serial.println(">>> Ready for new BLE detection <<<");
}
}
// Check 30min auto timer
if (auto30minActive && !relayActive) {
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - auto30minStartTime;
// Show countdown every 30 seconds
static unsigned long lastAutoCountdown = 0;
if (currentTime - lastAutoCountdown >= 30000) {
lastAutoCountdown = currentTime;
unsigned long remaining = (auto30minDuration > elapsedTime) ? (auto30minDuration - elapsedTime) / 1000 : 0;
Serial.print("Time remaining (Auto 30min): ");
Serial.print(remaining / 60);
Serial.print(" minutes ");
Serial.print(remaining % 60);
Serial.println(" seconds");
}
if (elapsedTime >= auto30minDuration) {
auto30minActive = false;
digitalWrite(kontak, LOW);
// Turn off all LEDs
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
Serial.println(">>> Auto 30min mode OFF - Timeout <<<");
}
}
// Reset canAcceptTap flag setelah cooldown period
if (!canAcceptTap && (millis() - lastBLEDetectionTime > BLE_COOLDOWN_TIME)) {
canAcceptTap = true;
Serial.println(">>> System ready for next BLE detection <<<");
}
pBLEScan->clearResults();
delay(100);
}