blifi 0.5.0 copy "blifi: ^0.5.0" to clipboard
blifi: ^0.5.0 copied to clipboard

BLE-based Wi-Fi provisioning for ESP32: send Wi-Fi credentials over an encrypted (X25519 + AES-256-GCM) Bluetooth Low Energy session, no hotspot.

blifi #

BLE-based Wi-Fi provisioning for ESP32 - hand Wi-Fi credentials to a device over an encrypted Bluetooth Low Energy session instead of a hotspot/captive portal. This Dart package is the phone side; it interoperates byte-for-byte with the blifi ESP-IDF firmware component.

  • 🔒 Encrypted: X25519 key agreement + AES-256-GCM, with a Proof-of-Possession so credentials are never exposed and an active MITM can't succeed.
  • 📶 Full flow: scan for devices, connect, list the device's Wi-Fi networks, send credentials, and stream live connection status.
  • 🧩 Small, typed API with typed exceptions - no string-matching errors.

Install #

dependencies:
  blifi: ^0.1.0

Permissions #

This package uses flutter_blue_plus for BLE. Add the platform permissions and request them at runtime (e.g. with permission_handler).

Android - android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Android 11 and below -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />

iOS - ios/Runner/Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>Connect to your device to set up Wi-Fi.</string>

BlifiProvisioning throws BleUnavailableException if Bluetooth is off or unsupported, so you never fail silently.

Usage #

import 'package:blifi/blifi.dart';

final blifi = BlifiProvisioning();

// 1. Discover a device.
final device = await blifi.scanForDevices().first;

// 2. Connect and complete the secure handshake with the device's PoP.
final session = await blifi.connect(device, proofOfPossession: 'K7M2QP9X');

// 3. List the device's visible Wi-Fi networks.
final networks = await session.scanWifiNetworks();

// 4. Send credentials and watch progress.
session.statusStream.listen((s) {
  print('${s.state}${s.ipAddress != null ? ' @ ${s.ipAddress}' : ''}');
});
await session.sendCredentials('HomeWiFi', 'password');

// Or await a single terminal result instead of watching the stream:
final ip = await session.awaitProvisioned(); // throws if the link drops first

// 5. Done.
await session.disconnect();

Errors are typed: catch AuthenticationException (wrong PoP), WifiConnectionException (with a ProvisioningState), BleConnectionException, or ProvisioningTimeoutException - all subtypes of BlifiException.

After success #

A BLE disconnect that follows wifiConnected is treated as a clean end: statusStream closes via onDone with no error (a disconnect before success still raises BleConnectionException). This matches firmware built with stop-BLE-after-provisioning, which drops the link once the phone has the IP. session.ipAddress stays readable after the link drops - it is your last chance to learn the address; after this the device is reachable only over the network. disconnect() is idempotent, so it is safe to call from dispose().

See example/ for a runnable app.

License #

MIT.

0
likes
140
points
55
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

BLE-based Wi-Fi provisioning for ESP32: send Wi-Fi credentials over an encrypted (X25519 + AES-256-GCM) Bluetooth Low Energy session, no hotspot.

Repository (GitHub)
View/report issues
Contributing

Topics

#bluetooth #ble #esp32 #wifi #provisioning

License

MIT (license)

Dependencies

cryptography, flutter, flutter_blue_plus

More

Packages that depend on blifi