import 'dart:async'; import 'package:esp_smartconfig/esp_smartconfig.dart'; import '../models/wiz_provisioning_device.dart'; abstract class WizSmartPairingService { Stream startProvisioning({ required String ssid, required String password, String? bssid, }); Future stopProvisioning(); } class EspTouchWizSmartPairingService implements WizSmartPairingService { Provisioner? _provisioner; StreamSubscription? _subscription; StreamController? _controller; @override Stream startProvisioning({ required String ssid, required String password, String? bssid, }) { if (_provisioner != null || _controller != null) { throw StateError('Provisioning is already running'); } final provisioner = Provisioner.espTouch(); final controller = StreamController.broadcast(); _provisioner = provisioner; _controller = controller; _subscription = provisioner.listen( (response) { controller.add( WizProvisioningDevice( bssid: response.bssidText, ipAddress: response.ipAddressText, ), ); }, onError: controller.addError, onDone: () async { if (!controller.isClosed) { await controller.close(); } }, ); final request = ProvisioningRequest.fromStrings( ssid: ssid, bssid: (bssid == null || bssid.trim().isEmpty) ? '00:00:00:00:00:00' : bssid.trim(), password: password.isEmpty ? null : password, ); unawaited( provisioner.start(request).catchError(( Object error, StackTrace stack, ) async { if (!controller.isClosed) { controller.addError(error, stack); await controller.close(); } }), ); return controller.stream; } @override Future stopProvisioning() async { final provisioner = _provisioner; _provisioner = null; try { provisioner?.stop(); } finally { await _subscription?.cancel(); _subscription = null; if (_controller != null && !_controller!.isClosed) { await _controller!.close(); } _controller = null; } } }