A laundry-locker access app. A user walks up, scans a locker, enters their details, and the app unlocks the assigned Bluetooth padlock over BLE. An administrator side retrieves orders from lockers and toggles each locker's availability between in-use and open.
It's built around the part that actually decides whether this works: reliable, secure BLE communication with the padlocks, wrapped in a clean walk-up flow and an admin workspace that keeps locker state correct.
User (walk-up)
- Scan a locker's QR (or code) to identify which locker.
- Enter the required details (name / contact / order reference).
- The app authenticates the request against the backend, then connects to that locker's BLE padlock and sends the unlock command.
- The locker opens; its state is marked in-use and the drop-off/pickup recorded.
Administrator
- See all lockers and their state (open / in-use / needs attention).
- Unlock a locker to retrieve an order.
- Toggle a locker back to open so it can be used again.
- Review locker/order history.
Talking to Bluetooth padlocks is the make-or-break piece, so it's kept as a well-isolated layer and the rest of the app never depends on one lock's quirks:
- A device-abstraction layer wraps the padlock's BLE interface: connect, authenticate, unlock, read status. The app talks to the abstraction, not a specific lock's raw protocol.
- Secure pairing and command authorization. An unlock is only sent after the backend authorizes the request, and the command to the lock is authenticated, so a locker can't be opened by a replayed or spoofed message.
- BLE specifics per lock model. Smart padlocks differ: some expose a documented GATT service or a manufacturer SDK, others use a proprietary or encrypted protocol. The integration targets a specific padlock, and isolating it behind the abstraction means supporting a different lock is a contained change, not a rewrite.
- Connection robustness. Out-of-range, failed connections, and retries are handled, because BLE in the field is far less reliable than on a bench.
The single most important input is the padlock's make/model and whether it has an SDK or a documented BLE protocol. With a documented interface the unlock path is straightforward; the abstraction exists so the rest of the system is stable no matter which lock is chosen.
- User app - the walk-up flow: QR scan, detail entry, BLE unlock. Runs on a device with Bluetooth and a camera (a mobile app is the natural fit; the BLE and app logic port across targets).
- Admin app - locker overview, unlock-to-retrieve, availability toggle, history.
- BLE layer - the device abstraction above, shared by both apps.
- Backend service - the source of truth for locker state, orders, and access authorization: which locker is assigned to whom, whether an unlock is permitted, and the record of drop-offs and pickups. Secure REST API to both apps.
- Store - lockers, their state, orders, users, and an action history.
Keeping locker state and authorization on the backend (not only on the lock or the phone) is what stops two people, or a user and an admin, from getting an inconsistent view of the same locker.
Each locker moves through a small, explicit set of states so the system never double-assigns or loses track:
- open - available for use.
- in_use - assigned, contains an order, awaiting pickup or retrieval.
- needs_attention - a failed unlock, an error, or an admin flag.
Transitions are driven by the backend: a successful drop-off marks in-use; an admin retrieval and toggle returns it to open. Every transition is recorded.
lockerble backend # the source-of-truth REST service
lockerble unlock --locker A12 # walk-up: authorize then BLE-unlock
lockerble admin lockers # admin overview
lockerble admin retrieve --locker A12
- Backend-authorized unlocks. The app never unlocks on its own say-so.
- Authenticated lock commands. The BLE unlock is HMAC-authenticated with a single-use nonce, so it can't be trivially replayed or forged.
- Role separation. User actions and admin actions (retrieve, toggle, override) are distinct and access-controlled.
- Auditable history. Drop-offs, pickups, admin retrievals, and state changes are recorded.
- Field-robust BLE. Retries and clear failure states, because real-world Bluetooth connections drop.
- Isolate the padlock protocol. The device-abstraction layer keeps the app stable no matter which BLE lock is used, and makes a swap a contained change.
- Backend owns locker state. State and authorization live server-side so users and admins always see a consistent view.
- Authorize then unlock. Every unlock is authorized by the backend and the lock command is authenticated. An unlock is a permission decision, not just a button.
- Two clear roles. The walk-up user flow and the admin workspace are separate, with admin-only control over retrieval and availability.
- Built for the field. BLE reliability, explicit locker states, and recorded history so it holds up in real use.
MIT licensed.