esp_flutter_sdk 1.0.0 copy "esp_flutter_sdk: ^1.0.0" to clipboard
esp_flutter_sdk: ^1.0.0 copied to clipboard

ESP Flutter SDK for provisioning ESP devices via BLE and WiFi. Provides APIs for device discovery, connection, and network configuration with support for Security 0/1/2.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ESP配网示例',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final espManager = ESPProvisioningManager.getInstance();
  final List<BleDevice> bleDevices = [];
  final List<WiFiAccessPoint> wifiNetworks = [];
  ESPDevice? currentDevice;
  bool isScanning = false;
  String statusMessage = '准备就绪';

  @override
  void initState() {
    super.initState();
    setupCallbacks();
  }

  void setupCallbacks() {
    // BLE扫描回调
    espManager.onBleDeviceFound((device) {
      setState(() {
        // 避免重复添加
        if (!bleDevices.any((d) => d.address == device.address)) {
          bleDevices.add(device);
        }
      });
    });

    espManager.onBleScanCompleted(() {
      setState(() {
        isScanning = false;
        statusMessage = 'BLE扫描完成';
      });
    });

    espManager.onBleScanFailed((error) {
      setState(() {
        isScanning = false;
        statusMessage = 'BLE扫描失败: $error';
      });
      showErrorDialog('BLE扫描失败', error);
    });

    // 设备连接回调
    espManager.onDeviceConnected(() {
      setState(() {
        statusMessage = '设备已连接';
      });
    });

    espManager.onDeviceConnectionFailed((error) {
      setState(() {
        statusMessage = '设备连接失败: $error';
      });
      showErrorDialog('连接失败', error);
    });

    // 配网回调
    espManager.onWifiConfigSent(() {
      setState(() {
        statusMessage = 'WiFi配置已发送';
      });
    });

    espManager.onWifiConfigApplied(() {
      setState(() {
        statusMessage = 'WiFi配置已应用';
      });
    });

    espManager.onProvisioningSuccess(() {
      setState(() {
        statusMessage = '配网成功!';
      });
      showSuccessDialog('配网成功', '设备已成功连接到WiFi网络');
    });

    espManager.onProvisioningFailed((error, reason) {
      String reasonText = '';
      if (reason != null) {
        switch (reason) {
          case ProvisionFailureReason.authFailed:
            reasonText = '认证失败';
            break;
          case ProvisionFailureReason.networkNotFound:
            reasonText = '网络未找到';
            break;
          case ProvisionFailureReason.deviceDisconnected:
            reasonText = '设备断开连接';
            break;
          case ProvisionFailureReason.unknown:
            reasonText = '未知错误';
            break;
        }
      }
      setState(() {
        statusMessage = '配网失败: $error ${reasonText.isNotEmpty ? "($reasonText)" : ""}';
      });
      showErrorDialog('配网失败', '$error ${reasonText.isNotEmpty ? "\n原因: $reasonText" : ""}');
    });
  }

  Future<void> startBleScan() async {
    try {
      setState(() {
        isScanning = true;
        bleDevices.clear();
        statusMessage = '正在扫描BLE设备...';
      });
      await espManager.searchBleEspDevices(prefix: 'PROV_');
    } catch (e) {
      setState(() {
        isScanning = false;
        statusMessage = '启动扫描失败: $e';
      });
      showErrorDialog('扫描失败', e.toString());
    }
  }

  Future<void> stopBleScan() async {
    try {
      await espManager.stopBleScan();
      setState(() {
        isScanning = false;
        statusMessage = 'BLE扫描已停止';
      });
    } catch (e) {
      showErrorDialog('停止扫描失败', e.toString());
    }
  }

  Future<void> connectToBleDevice(BleDevice bleDevice) async {
    try {
      setState(() {
        statusMessage = '正在连接到 ${bleDevice.name}...';
      });

      // 创建设备
      currentDevice = await espManager.createESPDevice(
        transportType: TransportType.ble,
        securityType: SecurityType.security2,
      );

      // 设置POP(如果需要)
      currentDevice!.setProofOfPossession('abcd1234');

      // 连接设备
      await currentDevice!.connectBLEDevice(
        bleDevice.address,
        bleDevice.primaryServiceUuid ?? '',
      );

      // 扫描WiFi网络
      await scanWifiNetworks();
    } catch (e) {
      setState(() {
        statusMessage = '连接失败: $e';
      });
      showErrorDialog('连接失败', e.toString());
    }
  }

  Future<void> scanWifiNetworks() async {
    try {
      setState(() {
        statusMessage = '正在扫描WiFi网络...';
      });

      if (currentDevice == null) {
        showErrorDialog('错误', '设备未连接');
        return;
      }

      final networks = await currentDevice!.scanNetworks();
      setState(() {
        wifiNetworks.clear();
        wifiNetworks.addAll(networks);
        statusMessage = '找到 ${networks.length} 个WiFi网络';
      });

      // 显示WiFi列表对话框
      if (mounted) {
        showWiFiListDialog();
      }
    } catch (e) {
      setState(() {
        statusMessage = '扫描WiFi网络失败: $e';
      });
      showErrorDialog('WiFi扫描失败', e.toString());
    }
  }

  Future<void> provisionDevice(String ssid, String password) async {
    try {
      if (currentDevice == null) {
        showErrorDialog('错误', '设备未连接');
        return;
      }

      setState(() {
        statusMessage = '正在配网...';
      });

      await currentDevice!.provision(ssid, password);
    } catch (e) {
      setState(() {
        statusMessage = '配网失败: $e';
      });
      showErrorDialog('配网失败', e.toString());
    }
  }

  void showWiFiListDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('选择WiFi网络'),
        content: SizedBox(
          width: double.maxFinite,
          child: ListView.builder(
            shrinkWrap: true,
            itemCount: wifiNetworks.length,
            itemBuilder: (context, index) {
              final network = wifiNetworks[index];
              return ListTile(
                leading: Icon(
                  Icons.wifi,
                  color: network.rssi > -60 ? Colors.green : Colors.orange,
                ),
                title: Text(network.wifiName),
                subtitle: Text('RSSI: ${network.rssi} dBm'),
                trailing: Icon(
                  network.security != 0 ? Icons.lock : Icons.lock_open,
                ),
                onTap: () {
                  Navigator.pop(context);
                  showPasswordDialog(network.wifiName);
                },
              );
            },
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('取消'),
          ),
        ],
      ),
    );
  }

  void showPasswordDialog(String ssid) {
    final passwordController = TextEditingController();
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('连接到 $ssid'),
        content: TextField(
          controller: passwordController,
          decoration: const InputDecoration(
            labelText: 'WiFi密码',
            border: OutlineInputBorder(),
          ),
          obscureText: true,
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('取消'),
          ),
          ElevatedButton(
            onPressed: () {
              Navigator.pop(context);
              provisionDevice(ssid, passwordController.text);
            },
            child: const Text('连接'),
          ),
        ],
      ),
    );
  }

  void showErrorDialog(String title, String message) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(title),
        content: Text(message),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('确定'),
          ),
        ],
      ),
    );
  }

  void showSuccessDialog(String title, String message) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Row(
          children: [
            const Icon(Icons.check_circle, color: Colors.green),
            const SizedBox(width: 8),
            Text(title),
          ],
        ),
        content: Text(message),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.pop(context);
              // 重置状态
              setState(() {
                currentDevice = null;
                bleDevices.clear();
                wifiNetworks.clear();
                statusMessage = '准备就绪';
              });
            },
            child: const Text('确定'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('ESP设备配网'),
      ),
      body: Column(
        children: [
          // 状态栏
          Container(
            width: double.infinity,
            padding: const EdgeInsets.all(16),
            color: Colors.blue.shade50,
            child: Text(
              statusMessage,
              style: const TextStyle(fontSize: 16),
              textAlign: TextAlign.center,
            ),
          ),
          // BLE设备列表
          Expanded(
            child: bleDevices.isEmpty
                ? Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.bluetooth_searching,
                          size: 64,
                          color: Colors.grey.shade400,
                        ),
                        const SizedBox(height: 16),
                        Text(
                          isScanning ? '正在扫描...' : '点击下方按钮开始扫描BLE设备',
                          style: TextStyle(
                            fontSize: 16,
                            color: Colors.grey.shade600,
                          ),
                        ),
                      ],
                    ),
                  )
                : ListView.builder(
                    itemCount: bleDevices.length,
                    itemBuilder: (context, index) {
                      final device = bleDevices[index];
                      return Card(
                        margin: const EdgeInsets.symmetric(
                          horizontal: 16,
                          vertical: 8,
                        ),
                        child: ListTile(
                          leading: Icon(
                            Icons.bluetooth,
                            color: device.rssi > -60
                                ? Colors.blue
                                : Colors.orange,
                            size: 32,
                          ),
                          title: Text(
                            device.name,
                            style: const TextStyle(fontWeight: FontWeight.bold),
                          ),
                          subtitle: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text('地址: ${device.address}'),
                              Text('RSSI: ${device.rssi} dBm'),
                            ],
                          ),
                          trailing: ElevatedButton(
                            onPressed: () => connectToBleDevice(device),
                            child: const Text('连接'),
                          ),
                        ),
                      );
                    },
                  ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: isScanning ? stopBleScan : startBleScan,
        icon: Icon(isScanning ? Icons.stop : Icons.search),
        label: Text(isScanning ? '停止扫描' : '开始扫描'),
      ),
    );
  }

  @override
  void dispose() {
    espManager.dispose();
    super.dispose();
  }
}
0
likes
140
points
185
downloads

Publisher

unverified uploader

Weekly Downloads

ESP Flutter SDK for provisioning ESP devices via BLE and WiFi. Provides APIs for device discovery, connection, and network configuration with support for Security 0/1/2.

Repository (GitHub)
View/report issues

Documentation

API reference

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on esp_flutter_sdk

Packages that implement esp_flutter_sdk