//////////////////main.dart////////////////////// // // code from: https://github.com/0015/IdeasNProjects/tree/master/ESP32_MICROPHONE/ESP32_INMP441_FLUTTER_BLE_APP/flutter_app_slm // // youtube - https://www.youtube.com/watch?v=CcLt-nBLWJU&feature=youtu.be import 'package:flutter/material.dart'; import 'package:flutter_blue/flutter_blue.dart'; import 'package:flutter_progress_dialog/flutter_progress_dialog.dart'; import './device_view.dart'; void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { @override Widget build(BuildContext context) { return ProgressDialog( orientation: ProgressOrientation.vertical, child: MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( brightness: Brightness.light, primaryColor: Color.fromRGBO(58, 66, 86, 1)), home: StreamBuilder( stream: FlutterBlue.instance.state, initialData: BluetoothState.unknown, builder: (c, snapshot) { final state = snapshot.data; if (state == BluetoothState.on) { return BluetoothOnScreen(); } else { return BluetoothOffScreen( state: state, ); } }, ), ), ); } } class BluetoothOnScreen extends StatefulWidget { @override _BluetoothOnScreenState createState() => _BluetoothOnScreenState(); } class _BluetoothOnScreenState extends State { static String targetDeviceName = 'Adafruit Bluefruit LE'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Sound Level Meter'), ), body: Center( child: RaisedButton( child: Text('Connect to $targetDeviceName'), onPressed: _deviceSearchingStart, ), ), ); } _deviceSearchingStart() { showProgressDialog(loadingText: 'Searching Device...'); FlutterBlue.instance .startScan(timeout: Duration(seconds: 3)) .whenComplete(() { FlutterBlue.instance.stopScan(); _scanResult(); dismissProgressDialog(); }); } _scanResult() { FlutterBlue.instance.scanResults.first.then((element) { print('Device Num: ${element.length}'); element.forEach((value) { print('**** ${value.device.id} / ${value.device.name} ****'); if (value.device.name == targetDeviceName) { print('**** FOUND Target Device ****'); _connectDevice(value.device); } }); }); } _connectDevice(BluetoothDevice _device) { _device.connect().whenComplete(() { Navigator.of(context).push(MaterialPageRoute( builder: (context) => DeviceView( device: _device, ))); }); } } class BluetoothOffScreen extends StatelessWidget { const BluetoothOffScreen({Key key, this.state}) : super(key: key); final BluetoothState state; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.bluetooth_disabled, size: 200, color: Colors.black, ), Text( 'Bluetooth Adapter is ${state.toString().substring(15)}', style: Theme.of(context) .primaryTextTheme .subtitle1 .copyWith(color: Colors.black), ) ], ), ), ); } } //////////////////////////////////////////////// /////////////////device_view.dart/////////////// //////////////////////////////////////////////// import 'dart:convert' show utf8; import 'package:flutter/material.dart'; import 'package:flutter_blue/flutter_blue.dart'; class DeviceView extends StatefulWidget { const DeviceView({Key key, this.device}) : super(key: key); final BluetoothDevice device; @override _DeviceViewState createState() => _DeviceViewState(); } class _DeviceViewState extends State { static final String baseUuid = "-b5a3-f393-e0a9-e50e24dcca9e"; static final String serviceUuid = "6e400001" + baseUuid; static final String characteristicUuid = "6e400003" + baseUuid; Stream> stream; bool isReady; String receivedText; double dBAValue = 0; String dBAStringValue; List points = [50]; @override void initState() { super.initState(); isReady = false; _discoverServices(); } _disconnectFromDevice() { if (widget.device == null) { _pop(); return; } widget.device.disconnect().whenComplete(() => _pop()); } _discoverServices() async { if (widget.device == null) { _pop(); return; } List services = await widget.device.discoverServices(); services.forEach((service) { if (service.uuid.toString() == serviceUuid) { service.characteristics.forEach((characteristic) { if (characteristic.uuid.toString() == characteristicUuid) { characteristic.setNotifyValue(true); stream = characteristic.value; setState(() { isReady = true; }); } }); } }); } _pop() { Navigator.of(context).pop(true); } Future _onWillPop() { return showDialog( context: context, builder: (context) => AlertDialog( title: Text('Are you sure?'), content: Text('Do you want to disconnect the device and go back?'), actions: [ FlatButton( onPressed: () => Navigator.of(context).pop(false), child: Text('No'), ), FlatButton( onPressed: () => _disconnectFromDevice(), child: Text('Yes'), ) ], ) ?? false); } String _dataParser(List dataFromDevice) { return utf8.decode(dataFromDevice); } _streamBody(AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.active) { var currentValue = _dataParser(snapshot.data); dBAValue = double.tryParse(currentValue) ?? 0; dBAStringValue = dBAValue > 100 ? '' + dBAValue.toString() : '0' + dBAValue.toString(); return Text(dBAStringValue); } else { return Center( child: Text( 'ConnectionState is not active', style: TextStyle(fontSize: 24, color: Colors.white), ), ); } } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: _onWillPop, child: Scaffold( appBar: AppBar( title: Text('Demo'), ), body: Container( child: !isReady ? Center( child: Text( 'Waiting...', style: TextStyle(fontSize: 24, color: Colors.white), ), ) : Container( child: StreamBuilder>( stream: stream, builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } return _streamBody(snapshot); }, ), ))), ); } }