SecureLock is a component-based smart lock system built on ESP32 + PlatformIO with a responsive web dashboard served from LittleFS.
It combines:
- RFID card authentication
- Keypad-based second factor (Telegram OTP or offline backup PIN)
- Tamper/theft detection with alarm logic
- Web-based admin management (users, logs, diagnostics, emergency unlock)
- Telegram alerting and remote command support
- Overview
- Core Features
- Architecture
- Hardware & GPIO Mapping
- Project Structure
- Prerequisites
- Quick Start
- Build, Upload, Monitor
- Web Dashboard
- REST API
- Telegram Commands
- Data Storage
- Security Notes
- Troubleshooting
- Development Workflow
- License
SecureLock is a full-stack IoT access-control project for ESP32 with:
- Firmware layer in C++ (PlatformIO / Arduino framework)
- Web UI layer in modular vanilla JavaScript + CSS
- Persistence via LittleFS JSON files (
users.json,logs.json) - Async networking via ESPAsyncWebServer
The system is designed around non-blocking patterns (millis() timers + async HTTP) to keep lock/security logic responsive.
- RFID card scan (RC522)
- 2FA flow after valid RFID:
- Primary: Telegram OTP (4 digits, 30s TTL)
- Fallback: Offline Backup PIN (4 digits)
- Guest PIN support via Telegram admin command (
/guest_code, 30 seconds) - Duress code support (
2580) with unlock + silent escalation path
- Door tamper detection via reed switch
- Anti-theft vibration strike window detection
- Alarm siren + buzzer feedback patterns
- Emergency lock/unlock state transitions with cooldown protections
- Token-based admin login (
/api/auth/login) - Real-time status polling
- Emergency override action
- User CRUD + RFID enrollment polling
- Logs view with pagination and clear/reset actions
- Diagnostics panel data exposure (RFID/keypad/buzzer/storage integrity)
- Alerts for duress/theft/RFID events
- Admin control commands (
/status,/my_info,/admin_open, lockdown controls) - User informational commands (
/help,/my_info)
SecureLock uses a 4-component modular firmware design:
-
LockManager(lib/LockManager/)- Relay control, lock state, door reed monitoring
- Auto-lock timer logic
-
SecurityManager(lib/SecurityManager/)- Vibration sensing
- Buzzer/siren state machine
-
AuthHandler(lib/AuthHandler/)- RFID reading + keypad scanning
- User store loading/compaction from LittleFS
- Backup PIN / Telegram Chat ID user metadata
-
WebServer(lib/WebServer/)- WiFi + LittleFS + async API routes
- Token-based API auth
- Logs/users synchronization utilities
src/main_runtime.cpp orchestrates runtime flows, including Telegram bot logic and cross-component events.
Source of truth:
include/hardware_pins.h
| Function | GPIO |
|---|---|
| Relay (solenoid lock) | 22 |
| Status LED | 2 |
| Door reed switch | 13 |
| Vibration sensor (SW-420) | 27 |
| Buzzer | 14 (override-capable) |
| Factory reset / BOOT | 0 |
| RFID SS | 5 |
| RFID RST | 4 |
| SPI SCK | 18 |
| SPI MOSI | 25 |
| SPI MISO | 19 |
| Keypad rows | 34, 35, 39, 36 |
| Keypad cols | 16, 17, 21, 23 |
SecureLock/
├─ src/
│ ├─ main_runtime.cpp
│ └─ main.cpp (placeholder)
├─ lib/
│ ├─ LockManager/
│ ├─ SecurityManager/
│ ├─ AuthHandler/
│ └─ WebServer/
├─ include/
│ ├─ hardware_pins.h
│ ├─ secrets.h
│ └─ secrets.h.example
├─ data/ # uploaded to LittleFS
│ ├─ html/pages/dashboard.html
│ ├─ css/
│ ├─ js/
│ │ ├─ entry/main.js
│ │ ├─ app/index.js
│ │ ├─ core/
│ │ ├─ features/
│ │ └─ ui/
│ ├─ users.json
│ └─ logs.json
├─ scripts/
│ ├─ deploy_all.ps1
│ └─ deploy_safe.sh
├─ platformio.ini
└─ build.ps1
- ESP32 DevKit (or compatible
esp32devtarget) - PlatformIO Core / VS Code PlatformIO extension
- USB serial driver for your ESP32 board
- 2.4GHz WiFi network
- Telegram bot token + chat IDs
-
Configure secrets
- Edit
include/secrets.h - Set WiFi, Telegram, and dashboard admin credentials
- Edit
-
Build firmware
pio run
-
Upload web filesystem (required for dashboard changes)
pio run --target uploadfs
-
Upload firmware
pio run --target upload
-
Open serial monitor
pio device monitor -b 115200 -f direct
-
Open dashboard
- Visit
http://securelock.local/ - Fallback:
http://<ESP32_IP>/if.localis not resolved on your client
- Visit
- Build:
pio run - Upload firmware:
pio run --target upload - Upload LittleFS assets:
pio run --target uploadfs - Monitor serial:
pio device monitor -b 115200 -f direct
build.ps1— clean/install/update/build helperscripts/deploy_all.ps1— Windows full pipeline (clean -> build -> uploadfs -> upload -> monitor)scripts/deploy_safe.sh— Linux/macOS safe deployment helper
If your machine cannot find
pioin PATH, use your PlatformIO executable path directly.
Main UI file: data/html/pages/dashboard.html
- Entry:
data/js/entry/main.js - Composition root:
data/js/app/index.js - Modules:
core/→ config, state, DOM mapping, API client, helpersfeatures/→ auth, status, guest, logs, usersui/feedback.js→ modal + toast UX
- Admin overlay lock until authenticated
- Polling intervals (from
data/js/core/config.js):- Status: 2.5s desktop / 3.2s mobile (with hidden-tab backoff)
- Logs: 10s (20s when tab hidden)
- Users: 15s (30s when tab hidden)
- Diagnostics: 3s desktop / 8s mobile (12s when hidden)
- RFID enrollment poll: 400ms (adaptive backoff under errors/hidden tab)
- Responsive logs pagination
- Add/Edit user dialogs with live RFID scan polling and duplicate checks
Base path: /api
Most endpoints require Authorization: Bearer <token> from /api/auth/login.
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /api/auth/login |
Admin login, issue session token |
| POST | /api/auth/logout |
Revoke active session |
| GET | /api/auth/status |
Validate session state |
| GET | /api/status |
Realtime system status |
| POST | /api/unlock |
Emergency unlock (cooldown protected) |
| POST | /api/guest-code |
Disabled path (guest code is Telegram-managed) |
| GET | /api/users |
List users |
| POST | /api/users |
Add user |
| PUT | /api/users |
Edit user |
| DELETE | /api/users?uid=<UID> |
Delete user |
| POST | /api/users/reset |
Reset all users (explicit confirmation body) |
| GET | /api/logs |
Get logs |
| DELETE | /api/logs |
Clear logs |
| GET | /api/rfid/scan |
Last RFID scan state (for enrollment flow) |
| GET | /api/diagnostics |
Runtime hardware/storage diagnostics |
| POST | /api/addUser |
Alias of add-user endpoint |
- CORS headers are enabled for API responses.
- Logs are persisted to LittleFS and returned newest-first.
users.jsonis synchronized from auth storage to avoid drift.
/help/start/my_info/status/admin_open/guest_code/lockdown/unlockdown/reboot
/help/start/my_info
Unknown or unauthorized command attempts are logged and handled explicitly.
LittleFS files:
data/users.json(user list + optional settings block)data/logs.json(activity logs)
Runtime behavior:
- User records are compacted/self-healed for schema consistency
- Log list is capped to prevent uncontrolled growth
include/secrets.his sensitive and should remain private.- Keep
include/secrets.hout of version control. - Rotate WiFi and Telegram credentials if leaked.
- Change default admin credentials before deployment.
- Prefer isolated network/VLAN for production devices.
- Do not expose device API directly to public internet.
.env exists for local placeholder hygiene, but firmware currently reads credentials from include/secrets.h.
- Upload filesystem first:
pio run --target uploadfs
- Close monitor sessions, retry upload
- Re-check active COM port and USB cable quality
- Verify credentials in
include/secrets.h - Ensure 2.4GHz AP availability
- Login first via dashboard (
/api/auth/login) - Ensure Bearer token is attached by frontend client
- Use
/api/diagnosticsto inspect readiness/mute/cooldown state - Confirm GPIO wiring matches
include/hardware_pins.h
- Edit code
pio runpio run --target upload
- Edit HTML/CSS/JS/JSON
pio run --target uploadfs- Hard refresh browser
- Upload filesystem
- Upload firmware
- Monitor serial output
- Validate dashboard/API flows
No license file is currently present in this repository.
If you want open-source distribution, add a LICENSE file (e.g., MIT/Apache-2.0) and update this section.
Built for IoT Group 7 with ❤️ on ESP32.