9.3 KiB
OpenParcelBox Mobile App
Flutter application for local OpenParcelBox setup and administration.
User Interface
- Project
background.jpgbehind the application, button surfaces#292929, modal surfaces#303030, accent#c19d60, and text#c6c6c6. - Solid
#292929dashboard header containing the logo, box name, current application identity, and Bluetooth connection indicator. - Project logo used for the Android launcher icon and centered native splash. The splash variant includes transparent safe-area padding so Android displays the complete logo instead of cropping it through the system icon mask.
- Native splash uses the project
background.jpgon pre-Android 12 devices. Android 12 mandates a solid-color system launch screen, so its redundant system icon is transparent and the first Flutter frame presents the single visible logo overbackground.jpg. - Automatic French or English selection from the phone, with a manual override.
- Empty state restricted to box registration and encrypted-backup restoration.
- Shortcut bar for opening, explicit synchronization, and history, plus modal cards for codes, NFC tags, guests, and settings.
- When the saved box is offline, a solid
#353535disconnected banner is shown below the header. Opening and mutating actions are disabled, while history, permanent codes, temporary codes, NFC tags, and guest lists remain readable. The synchronization shortcut becomes a reconnect action until the BLE link is restored. - Dashboard actions anchored as one group to the bottom with equal side and bottom margins; NFC, guests, and settings share one compact three-card row.
- Guest mode hides NFC, guest administration, factory reset, firmware update, and permanent-code mutation controls. Guests can read the global code lists and opening history, and can manage temporary codes.
Registration and Secure Storage
The first phone connecting to an unprovisioned box:
- chooses the box identifier;
- selects one detected box with a radio button and confirms with the explicit add button;
- generates a random 128-bit administrator identity;
- sends both values over the encrypted BLE link;
- stores the remote BLE identifier, box name, role, and identity in the phone secure keystore.
Selecting a discovered box enables the add action immediately, even while the scan timeout is still running. The application stops the Android scan before connecting and displays a persistent registration progress page. If registration fails, the same page shows the complete error and a close action. Once administrator provisioning and secure local storage complete, the progress page closes immediately; clock synchronization continues in the background.
An administrator creates named guest identities and displays an invitation QR code. A guest scans that QR code to register the same box and its unique guest identity, even when the box is currently offline. The guest receives the cached offline-readable state only after the first successful connection to the box. The inviter's BLE address is treated only as a non-portable hint: the guest phone performs its own scan, creates its own encrypted bond, and authenticates with the guest identity key when it first reaches the box. Saved boxes reconnect automatically in the background when the application starts. Cached dashboard content is displayed immediately while the box is offline or out of range.
After every authenticated state synchronization, the application stores the complete state snapshot in Android secure storage, indexed by the application identity rather than the rotating BLE address. Opening history, permanent and one-time codes, NFC tags, and guest identities therefore remain available after an application restart while the box is offline. Forgetting a box also deletes its cached snapshot from the phone.
Application backups contain the saved connection records. They are protected
with AES-256-GCM and a PBKDF2-SHA256 key derived from the user password before a
file is written. During restoration, the application first asks for the backup
file and only then requests the password needed to decrypt it. Settings display
the persisted date and time of the most recent successful backup, or never
when no backup has been created.
Android Bluetooth bond keys cannot be exported by applications and are not part of the backup. A restored administrator or guest record keeps its OpenParcelBox identity but is marked for BLE rediscovery. On the new phone, the application scans for the stored box name, creates a new encrypted Android bond, authenticates with the restored identity key, and then stores that phone's BLE address. The firmware retains up to four phone bonds and can replace the oldest unused record when needed.
Features
- Direct lock opening, explicit state synchronization, and seven-day opening history refreshed automatically after firmware changes.
- Eight permanent and twenty one-time access codes shared globally. Guests can manage temporary codes and view permanent codes; only administrators can modify permanent codes. Random generation excludes every currently active permanent and temporary value. Administrators can also edit permanent codes through the six-digit numeric editor; choosing an existing temporary value requires confirmation before converting it to permanent. Every permanent or temporary code row has a local clipboard action before the edit action; it remains available while the box is offline.
- NFC tag listing, renaming, deletion, manual UID entry, phone NFC scanning, and a box-reader enrollment modal that scans for 15 seconds, keeps errors visible, asks for a name only after detecting a new UID, and refreshes the authoritative tag list after validation.
- Named guest creation, invitation QR display, and revocation.
- Firmware clock synchronization after connection.
- Language override, encrypted backup/restore, factory reset, and local removal of a saved box. Box reset is offered as an optional checkbox only when an administrator removes the saved box and is disabled while offline; guest removal clears phone data and the Android Bluetooth bond.
- Reserved disabled entry for a later firmware-update flow.
BLE Security and Protocol
The firmware requires BLE LE Secure Connections and encrypted GATT access. Bluetooth uses AES-CCM link encryption. Every application command is also authorized with the random administrator or guest identity stored in the phone keystore.
On Android, connection setup is serialized as connection, secure bonding, MTU negotiation, and GATT service discovery. The application does not perform the first encrypted state read until bonding has completed. If the initial provisioning connection is dropped because Android retained an obsolete bond, the application removes that bond and retries the setup once.
Connection timeouts and an out-of-range box never remove the Android bond. Bond recovery is restricted to encrypted GATT setup failures while Android still reports an existing bond. If a saved private BLE address is no longer usable, the application scans for OpenParcelBox devices, verifies the stored box name and application identity, and persists the rediscovered address.
The application subscribes to the compact state-change notification and then reassembles the complete state from 480-byte pages. Keypad openings and consumed one-time codes therefore update the open application without requiring a reconnect. A manual synchronization action is also available from the dashboard.
After an administrator factory reset, the application waits for the firmware to clear its persistent state and BLE bonds, removes Android's matching local bond, and only then deletes the saved box record.
The firmware negotiates an ATT MTU of 247 bytes, leaving 244 bytes for a single GATT write. This keeps the administrator provisioning JSON in one acknowledged write instead of relying on prepared long-write support.
Service UUID:
f2a00000-8e7a-4f8d-9b1d-7d8e4b7a0001
Command characteristic:
f2a00001-8e7a-4f8d-9b1d-7d8e4b7a0001
State characteristic:
f2a00002-8e7a-4f8d-9b1d-7d8e4b7a0001
See docs/firmware/bluetooth.md from the repository root for the command and
state formats.
Dependencies
The app uses:
flutter_blue_plusfor BLE;flutter_secure_storagefor connection identities;mobile_scannerandqr_flutterfor guest invitations;nfc_managerfor optional phone-side NFC UID scans;file_pickerandcryptographyfor encrypted backups.
flutter_blue_plus 2.3.10 requires a license mode when connecting. The app uses
License.nonprofit for this open-source project.
The discovery scan is intentionally unfiltered at the Android API level, then restricted in the application to advertisements carrying the OpenParcelBox name or service UUID. The registration modal listens to scan results in real time and the scan action remains active until the plugin's timeout completes.
Development
flutter pub get
flutter analyze
flutter test
flutter build apk --debug
Native assets can be regenerated with:
dart run flutter_launcher_icons
dart run flutter_native_splash:create
After regenerating native splash assets, preserve the Android 12
transparent_splash override in both values-v31/styles.xml files; otherwise
the generator restores the redundant masked system icon.