//////////////////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);
},
),
))),
);
}
}