[Flutter] 플러터 블루투스 연결 구현 #4 플러터를 사용한 블루투스 연결
1. 블루투스를 연결하기 위해 필요한것.
- 블루투스 용어정리
- 블루투스 라이브러리
2. 블루투스 연결
- 아두이노 코드분석
- 모바일(플러터)에서 확인
3. 데이터 송수신
오랜만에 들어가보니 상당히 많이 변했다. 1.30.7 기준 연결방법은 아래에!
2023.12.26 - [Study/Flutter] - [Flutter] Flutter blue Plus 1.30.7 버전 기준 연결 예제
지금까지 정리를 조금 해보자
라이브러리는 flutter_blue_plus 를 사용하기로 결정했다.
아두이노에서 서비스 UUID 와 캐릭터리스틱 UUID 그리고 Write시 어떻게 송수신 해야하는지를 알았다.
이제 플러터에서 기본적인 사용법에 대해서는 readme에 있다.
https://pub.dev/packages/flutter_blue_plus
블루투스 사용 단계는 간략하게 나누면
- scan
- connect
- discorver services
- data transfer (write, notify, read 등)
이정도로 나눌수 있다.
한 단계씩 수행해보자
**전체 코드는 최하단에 작성해두었다.
scan
스캔 단계에서는 플러터에서 블루투스기기를 스캔하면 되는데
스캔 단계는
1. startScan, stopScan 함수 작성
void startScan() async {
setState(() {
isScanning = true;
scanResults.clear();
});
try {
flutterBlue.scan().listen((scanResult) {
setState(() {
scanResults.add(scanResult);
});
});
} catch (e) {
print('error : ${e.toString()}');
}
}
Future<void> stopScan() async {
setState(() {
isScanning = false;
});
await flutterBlue.stopScan();
}
2. 버튼을 클릭하여 혹은 다른 방법으로든 StartScan() 함수 호출.
ElevatedButton(
onPressed: isScanning ? null : startScan,
child: Text(isScanning ? 'Scanning...' : 'Scan'),
),
Eleveated Button 을 사용해서 호출하였다.
RefreshIndicator(
onRefresh: () => stopScan().then((_) => startScan()),
child:
)
refreshIndicator를 사용해 리스트 새로고침 구현하였음
3. scanList를 뿌려준다.
Scan결과를 가져오고 가져온 결과값을 ListView를 사용해 그려주었다.
ListView.builder(
itemCount: scanResults.length,
itemBuilder: (BuildContext context, int index) {
var scanResult = scanResults[index];
if (scanResult.device.name.isNotEmpty) {
return Container(
// .....
);
} else {
return Container();
}
},
)
4. 뿌려준 리스트중 선택하여 connect한다.
scanResult.device.connect();
해당 사항을 전부 구현한 예제 화면
class BluetoothScreen extends StatefulWidget {
@override
_BluetoothScreenState createState() => _BluetoothScreenState();
}
class _BluetoothScreenState extends State<BluetoothScreen> {
FlutterBluePlus flutterBlue = FlutterBluePlus.instance;
List<BluetoothDevice> connectedDevices = [];
bool isScanning = false;
List<ScanResult> scanResults = [];
@override
void initState() {
super.initState();
// TODO: Connect to previously connected device (if any)
getConnectedDevice();
}
void getConnectedDevice() async {
connectedDevices = await flutterBlue.connectedDevices;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bluetooth Screen'),
),
body: Column(
children: [
Flexible(
flex: 1,
child: ConnectedDevices(),
),
Flexible(
flex: 4,
child: ScanningDevices(),
),
],
),
);
}
Widget ConnectedDevices() {
return Column(
children: [
Container(
alignment: Alignment.centerLeft,
child: const Text(
'Connected Devices',
style: TextStyle(
color: Colors.Blue[300], fontSize: 18, fontWeight: FontWeight.w700),
),
),
Expanded(
child: ListView.builder(
itemCount: connectedDevices.length,
itemBuilder: (context, index) {
var connectedDevice = connectedDevices[index];
return Container(
margin:
const EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.lightBlue[100],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.bluetooth),
const SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
connectedDevice!.name,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
'ID : [${connectedDevice!.id.toString()}]',
style: const TextStyle(
fontSize: 10,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
children: [
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.lightBlue[50]),
),
onPressed: () {
// TODO: Connect to selected device
print('ID [ ${connectedDevice!.id}]');
print('Name [ ${connectedDevice!.name}]');
connectedDevice!.disconnect();
setState(() {
connectedDevices.remove(connectedDevice);
});
},
child: const Text('disConnect'),
),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Colors.orangeAccent[700]),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DeviceScreen(device: connectedDevice)),
);
},
child: const Text('Device..'),
)
],
),
],
),
);
},
),
),
],
);
}
Widget ScanningDevices() {
return Column(
children: [
Row(
children: [
ElevatedButton(
onPressed: isScanning ? null : startScan,
child: Text(isScanning ? 'Scanning...' : 'Scan'),
),
ElevatedButton(
onPressed: stopScan,
child: Text('Stop!'),
),
],
),
Container(
alignment: Alignment.centerLeft,
child: const Text(
'Scanning Devices',
style: TextStyle(
color: Colors.Blue[300], fontSize: 18, fontWeight: FontWeight.w700),
),
),
const SizedBox(height: 10),
Expanded(
child: RefreshIndicator(
onRefresh: () => stopScan().then((_) => startScan()),
child: ListView.builder(
itemCount: scanResults.length,
itemBuilder: (BuildContext context, int index) {
var scanResult = scanResults[index];
if (scanResult.device.name.isNotEmpty) {
return Container(
margin: const EdgeInsets.symmetric(
horizontal: 5.0, vertical: 5.0),
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey[200],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.bluetooth),
const SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
scanResult.device.name,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
'ID : [${scanResult.device.id.toString()}]',
style: const TextStyle(
fontSize: 10,
),
),
],
),
const SizedBox(
width: 20,
),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Colors.lightBlue[50]),
foregroundColor:
MaterialStateProperty.all(Colors.black)),
onPressed: () {
// TODO: Connect to selected device
scanResult.device.connect();
print('ID [ ${scanResult.device.id}]');
print('Name [ ${scanResult.device.name}]');
setState(() {
scanResults.remove(scanResult.device);
connectedDevices.add(scanResult.device);
});
},
child: const Text('Connect'),
),
],
),
);
} else {
return Container();
}
},
),
),
),
],
);
}
void startScan() async {
setState(() {
isScanning = true;
scanResults.clear();
});
try {
flutterBlue.scan().listen((scanResult) {
setState(() {
scanResults.add(scanResult);
});
});
} catch (e) {
print('error : ${e.toString()}');
}
}
Future<void> stopScan() async {
setState(() {
isScanning = false;
});
await flutterBlue.stopScan();
}
}
'Study > Flutter' 카테고리의 다른 글
[Flutter] 다국어 지원 (0) | 2023.07.05 |
---|---|
[Flutter] 플러터 블루투스 연결 구현 #5 Notify, Write 구현 (0) | 2023.03.10 |
[Flutter] 플러터 블루투스 연결 구현 #3 아두이노 코드 분석 (0) | 2023.03.03 |
[Flutter] 플러터 블루투스 연결 구현 #2 플러터에서 사용할 블루투스 라이브러리 정리 (0) | 2023.03.02 |
[Flutter] 플러터 블루투스 연결 구현 #1 개요 및 용어정리 (0) | 2023.03.01 |
댓글