Flutter ESP32 BLE配网插件esp_ble_prov_wifi的使用

Flutter ESP32 BLE配网插件esp_ble_prov_wifi的使用

esp_ble_prov_wifi

该库用于通过蓝牙低功耗(BLE)为ESP32设备进行配置。

此库使用Espressif提供的配置库来实现其自定义的BLE协议。

查看示例。

需求

iOS
  • iOS 13.0+

在您的Info.plist文件中添加蓝牙权限:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>我们的应用使用蓝牙来查找、连接和传输不同设备之间的数据。</string>
Android

在您的android/app/build.gradle文件中确保minSdkVersion至少为23。

android/build.gradle文件的repositories部分添加以下仓库:

allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io/' }
    }
}

Android对蓝牙权限的要求在S (31)版本后有所改变,因此需要在清单文件中进行一些特殊处理。这些信息可以在官方文档中找到,该库会为您请求这些权限。

注意事项

库嵌入

目前我们嵌入了Espressif的Android库到libs目录中,因为Jitpack无法正常获取该库。

完整示例Demo

以下是完整的示例代码:

import 'package:esp_ble_prov_wifi/esp_ble_prov_wifi_models.dart';
import 'package:flutter/material.dart';
import 'dart:async';

import 'package:esp_ble_prov_wifi/esp_ble_prov_wifi.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _espBleProvWifiPlugin = EspBleProvWifi();

  final defaultPadding = 12.0;
  final defaultDevicePrefix = 'RT';

  List<Device> devices = [];
  List<Network> networks = [];

  String selectedDeviceName = '';
  String selectedSsid = '';
  String feedbackMessage = '';

  final prefixController = TextEditingController(text: 'RT');
  final proofOfPossessionController =
      TextEditingController(text: 'RUMITANK123');
  final passphraseController = TextEditingController();

  Future scanBleDevices() async {
    final prefix = prefixController.text;
    final scannedDevices = await _espBleProvWifiPlugin.scanBleDevices(prefix);
    setState(() {
      devices = scannedDevices;
    });
    pushFeedback('成功:扫描到了BLE设备');
  }

  Future scanWifiNetworks() async {
    final proofOfPossession = proofOfPossessionController.text;
    try {
      final scannedNetworks = await _espBleProvWifiPlugin.scanWifiNetworks(
          selectedDeviceName, proofOfPossession);
      setState(() {
        networks = scannedNetworks;
      });
      pushFeedback('成功:在$selectedDeviceName上扫描到了WiFi网络');
    } catch (e) {
      pushFeedback('错误:$e');
    }
  }

  Future provisionWifi() async {
    final proofOfPossession = proofOfPossessionController.text;
    final passphrase = passphraseController.text;
    await _espBleProvWifiPlugin.provisionWifi(
        selectedDeviceName, proofOfPossession, selectedSsid, passphrase);
    pushFeedback(
        '成功:在$selectedDeviceName上配置了WiFi网络$selectedSsid');
  }

  pushFeedback(String msg) {
    setState(() {
      feedbackMessage = '$feedbackMessage\n$msg';
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('ESP BLE 配置示例'),
          actions: [
            IconButton(
                icon: const Icon(Icons.bluetooth),
                onPressed: () async {
                  await scanBleDevices();
                }),
          ],
        ),
        bottomSheet: SafeArea(
          child: Container(
            width: double.infinity,
            color: Colors.black87,
            padding: EdgeInsets.all(defaultPadding),
            child: Text(
              feedbackMessage,
              style: TextStyle(
                  fontWeight: FontWeight.bold, color: Colors.green.shade600),
            ),
          ),
        ),
        body: SafeArea(
          child: Container(
            padding: EdgeInsets.all(defaultPadding),
            child: Column(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Flexible(
                  child: Container(
                    padding: EdgeInsets.all(defaultPadding),
                    child: Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        const Flexible(
                          child: Text('设备前缀'),
                        ),
                        Expanded(
                          child: TextField(
                            controller: prefixController,
                            decoration: const InputDecoration(
                                hintText: '输入设备前缀'),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
                Flexible(
                  child: Container(
                    padding: EdgeInsets.all(defaultPadding),
                    child: const Text('BLE设备'),
                  ),
                ),
                Expanded(
                  child: ListView.builder(
                    itemCount: devices.length,
                    itemBuilder: (context, i) {
                      return ListTile(
                        title: Text(
                          devices[i].name,
                          style: TextStyle(
                            color: Colors.blue.shade700,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        onTap: () async {
                          selectedDeviceName = devices[i].name;
                          await scanWifiNetworks();
                        },
                      );
                    },
                  ),
                ),
                Flexible(
                  child: Container(
                    padding: EdgeInsets.all(defaultPadding),
                    child: Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        const Flexible(
                          child: Text('证明拥有权字符串'),
                        ),
                        Expanded(
                          child: TextField(
                            controller: proofOfPossessionController,
                            decoration: const InputDecoration(
                                hintText: '输入证明拥有权字符串'),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
                Flexible(
                  child: Container(
                    padding: EdgeInsets.all(defaultPadding),
                    child: const Text('WiFi网络'),
                  ),
                ),
                Expanded(
                  child: ListView.builder(
                    itemCount: networks.length,
                    itemBuilder: (context, i) {
                      return ListTile(
                        title: Text(
                          networks[i].ssid,
                          style: TextStyle(
                            color: Colors.green.shade700,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        onTap: () async {
                          selectedSsid = networks[i].ssid;
                          await provisionWifi();
                        },
                      );
                    },
                  ),
                ),
                Flexible(
                  child: Container(
                    padding: EdgeInsets.all(defaultPadding),
                    child: Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        const Flexible(
                          child: Text('WiFi密码'),
                        ),
                        Expanded(
                          child: TextField(
                            controller: passphraseController,
                            decoration: const InputDecoration(
                                hintText: '输入密码'),
                            obscureText: true,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter ESP32 BLE配网插件esp_ble_prov_wifi的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter ESP32 BLE配网插件esp_ble_prov_wifi的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在使用 Flutter 与 ESP32 进行 BLE 配网时,可以使用 esp_ble_prov_wifi 插件。以下是使用该插件的基本步骤和示例代码。

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 esp_ble_prov_wifi 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  esp_ble_prov_wifi: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 初始化插件

在你的 Flutter 应用中初始化 esp_ble_prov_wifi 插件。

import 'package:esp_ble_prov_wifi/esp_ble_prov_wifi.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EspBleProvWifi().init();
  runApp(MyApp());
}

3. 扫描设备

使用 scanDevices 方法来扫描可用的 ESP32 设备。

List<BleDevice> devices = await EspBleProvWifi().scanDevices();

4. 连接设备

选择一个设备并连接。

BleDevice selectedDevice = devices[0];
await EspBleProvWifi().connect(selectedDevice);

5. 配网

使用 provision 方法将 WiFi 信息发送到 ESP32 设备。

String ssid = 'your_wifi_ssid';
String password = 'your_wifi_password';

await EspBleProvWifi().provision(ssid: ssid, password: password);

6. 断开连接

配网完成后,断开与设备的连接。

await EspBleProvWifi().disconnect();

完整示例代码

import 'package:flutter/material.dart';
import 'package:esp_ble_prov_wifi/esp_ble_prov_wifi.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EspBleProvWifi().init();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('ESP32 BLE WiFi Provisioning'),
        ),
        body: Center(
          child: ProvisionButton(),
        ),
      ),
    );
  }
}

class ProvisionButton extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () async {
        try {
          // 扫描设备
          List<BleDevice> devices = await EspBleProvWifi().scanDevices();
          if (devices.isEmpty) {
            print('No devices found');
            return;
          }

          // 连接设备
          BleDevice selectedDevice = devices[0];
          await EspBleProvWifi().connect(selectedDevice);

          // 配网
          String ssid = 'your_wifi_ssid';
          String password = 'your_wifi_password';
          await EspBleProvWifi().provision(ssid: ssid, password: password);

          // 断开连接
          await EspBleProvWifi().disconnect();

          print('WiFi provisioning successful');
        } catch (e) {
          print('Error: $e');
        }
      },
      child: Text('Start Provisioning'),
    );
  }
}
回到顶部