Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in
Toggle navigation
A
anchor_collect_flutter
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
hywang
anchor_collect_flutter
Commits
5f699b5a
Commit
5f699b5a
authored
Dec 24, 2023
by
18600395998
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改蓝牙读写功能
parent
16cc47d9
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
99 additions
and
149 deletions
+99
-149
ble_service.dart
lib/controllers/ble_service.dart
+99
-149
No files found.
lib/controllers/ble_service.dart
View file @
5f699b5a
import
'dart:async'
;
import
'dart:io'
;
import
'package:anchor_collect_flutter/utils/dialog_utils.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_
reactive_ble/flutter_reactive_ble
.dart'
;
import
'package:flutter_
blue_plus/flutter_blue_plus
.dart'
;
import
'package:get/get.dart'
;
import
'package:isar/isar.dart'
;
import
'package:permission_handler/permission_handler.dart'
;
import
'package:uuid/uuid.dart'
;
import
'../models/cattle_resume_entity.dart'
;
import
'../models/dict_entity.dart'
;
...
...
@@ -21,34 +23,39 @@ class BleService extends GetxService {
late
DiscoveredCallback
?
discoveredCallback
;
late
ConnectCallback
?
connectCallback
;
// 添加一个 StreamController
final
_readController
=
StreamController
<
List
<
int
>>();
late
BluetoothService
_service
;
late
BluetoothCharacteristic
_writeCharacteristic
;
late
BluetoothCharacteristic
_notifyCharacteristic
;
Stream
<
List
<
int
>>
get
readStream
=>
_readController
.
stream
;
late
late
Uuid
_serviceId
;
late
Uuid
_writeCharacteristicId
;
late
Uuid
_notifiCharacteristicId
;
// 读取数据的 Stream
List
<
BluetoothDevice
>
_systemDevices
=
[];
// 添加一个标志,用于控制读取循环是否应该继续
bool
_shouldContinueReading
=
false
;
//
List
<
ScanResult
>
_scanResults
=
[];
RxBool
isScanning
=
false
.
obs
;
late
StreamSubscription
<
List
<
ScanResult
>>
_scanResultsSubscription
;
late
StreamSubscription
<
bool
>
_isScanningSubscription
;
var
isScanning
=
false
.
obs
;
final
ble
=
FlutterReactiveBle
()
;
late
StreamSubscription
<
BluetoothConnectionState
>
_connectionStateSubscription
;
//判断是否正在扫描
StreamSubscription
<
DiscoveredDevice
>?
scan
Subscription
;
late
StreamSubscription
<
List
<
int
>>
_lastValueSubscription
;
late
StreamSubscription
<
List
<
int
>>
_valueReceived
Subscription
;
//判断设备选中状态
final
selectedDevice
=
Rx
<
DiscoveredDevice
?>(
null
);
//判断设备连接状态
String
deviceStatus
=
''
;
// ignore: cancel_subscriptions
late
StreamSubscription
<
ConnectionStateUpdate
>
streamSubscriptionConnection
;
late
BluetoothDevice
selectedDevice
;
Future
<
BleService
>
init
()
async
{
_isScanningSubscription
=
FlutterBluePlus
.
isScanning
.
listen
((
state
)
{
isScanning
.
value
=
state
;
});
_scanResultsSubscription
=
FlutterBluePlus
.
scanResults
.
listen
((
results
)
{
_scanResults
=
results
;
},
onError:
(
e
)
{
DialogUtils
.
showToast
(
'扫描错误'
);
});
return
this
;
}
...
...
@@ -56,7 +63,7 @@ class BleService extends GetxService {
Future
<
void
>
toggleScan
(
DiscoveredCallback
callback
)
async
{
discoveredCallback
=
callback
;
if
(
isScanning
.
value
)
{
await
scanSubscription
?.
cancel
();
FlutterBluePlus
.
stopScan
();
isScanning
.
value
=
false
;
}
else
{
await
scanDevices
();
...
...
@@ -68,130 +75,93 @@ class BleService extends GetxService {
// 检查权限
bool
permissionsGranted
=
await
requestBlePermissions
();
if
(!
permissionsGranted
)
{
Get
.
snackbar
(
'Permissions required'
,
'Please grant all necessary permissions
'
);
DialogUtils
.
showToast
(
'请授予所有必要的权限
'
);
return
;
}
// 扫描开始时,设置 isScanning 为 true
isScanning
.
value
=
true
;
// 扫描设备
final
scanStream
=
ble
.
scanForDevices
(
withServices:
[],
//scanMode: ScanMode.balanced, // 将 scanMode 设置为 balanced 功耗均衡,扫描慢
scanMode:
ScanMode
.
lowLatency
,
// 将 scanMode 设置为 lowLatency 功耗大 扫描快
);
// 监听扫描结果
scanSubscription
=
scanStream
.
listen
((
device
)
{
// 如果设备名称不为空,且列表中没有该设备,则添加到列表中
if
(
device
.
name
!=
null
&&
device
.
name
!.
isNotEmpty
)
{
if
(
discoveredCallback
!=
null
)
{
discoveredCallback
!(
device
);
}
}
});
try
{
// android is slow when asking for all advertisments,
// so instead we only ask for 1/8 of them
int
divisor
=
Platform
.
isAndroid
?
8
:
1
;
await
FlutterBluePlus
.
startScan
(
timeout:
const
Duration
(
seconds:
15
),
continuousUpdates:
true
,
continuousDivisor:
divisor
);
}
catch
(
e
)
{
DialogUtils
.
showToast
(
'扫描错误'
);
}
///扫描10秒
Future
.
delayed
(
const
Duration
(
seconds:
15
),
()
async
{
await
scanSubscription
?.
cancel
();
isScanning
.
value
=
false
;
DialogUtils
.
showToast
(
'自动停止扫描'
);
});
//
Future.delayed(const Duration(seconds: 15), () async {
// FlutterBluePlus.stopScan
();
//
isScanning.value = false;
//
DialogUtils.showToast('自动停止扫描');
//
});
}
// 连接设备
Future
<
void
>
connectToDevice
(
Discovered
Device
device
,
BuildContext
context
,
ConnectCallback
callback
)
async
{
Future
<
void
>
connectToDevice
(
Bluetooth
Device
device
,
BuildContext
context
,
ConnectCallback
callback
)
async
{
connectCallback
=
callback
;
selectedDevice
.
value
=
device
;
// 设置当前选中的设备
selectedDevice
=
device
;
// 设置当前选中的设备
await
scanSubscription
?.
cancel
();
// 在连接设备之前,停止扫描
// 在连接设备之前,停止扫描
await
FlutterBluePlus
.
stopScan
();
isScanning
.
value
=
false
;
// 设置 isScanning 为 false
DialogUtils
.
showLoadingDialog
(
'正在连接到
${device.name}
'
);
// 显示正在连接的对话框
// showDialog(
// context: context,
// barrierDismissible: false,
// builder: (BuildContext context) {
// return AlertDialog(
// title: Text('Connecting to ${device.name}'),
// content: CircularProgressIndicator(),
// );
// },
// );
// 连接设备
var
connection
=
ble
.
connectToDevice
(
id:
device
.
id
,
connectionTimeout:
const
Duration
(
milliseconds:
10000
),
servicesWithCharacteristicsToDiscover:
{},
);
// 监听连接状态
streamSubscriptionConnection
=
connection
.
listen
((
update
)
async
{
// 如果连接状态为 connected,则显示连接成功的提示
if
(
update
.
connectionState
==
DeviceConnectionState
.
connected
)
{
// 发现服务和特性
final
services
=
await
ble
.
discoverServices
(
device
.
id
);
for
(
final
service
in
services
)
{
if
(
service
.
serviceId
.
toString
()
==
'000180'
)
{
_serviceId
=
service
.
serviceId
;
if
(
kDebugMode
)
{
print
(
'Discovered service
${service.serviceId}
'
);
}
for
(
final
characteristic
in
service
.
characteristics
)
{
if
(
characteristic
.
isWritableWithoutResponse
)
{
_writeCharacteristicId
=
characteristic
.
characteristicId
;
if
(
kDebugMode
)
{
print
(
'WritableWithoutResponse characteristic
${characteristic.characteristicId}
of service
${service.serviceId}
'
);
}
// listen for disconnection
_connectionStateSubscription
=
device
.
connectionState
.
listen
((
BluetoothConnectionState
state
)
async
{
if
(
state
==
BluetoothConnectionState
.
disconnected
)
{
// 1. typically, start a periodic timer that tries to
// reconnect, or just call connect() again right now
// 2. you must always re-discover services after disconnection!
DialogUtils
.
showToast
(
'断开连接'
);
print
(
"
${device.disconnectReason!.code}
${device.disconnectReason!.description}
"
);
}
else
if
(
state
==
BluetoothConnectionState
.
connected
)
{
// Note: You must call discoverServices after every re-connection!
List
<
BluetoothService
>
services
=
await
device
.
discoverServices
();
services
.
forEach
((
service
)
{
//打印所有服务的 uuid
print
(
'service uuid:
${service.uuid}
'
);
if
(!
service
.
serviceUuid
.
toString
().
contains
(
'000180'
))
{
_service
=
service
;
//打印 service uuid
print
(
'service uuid:
${service.uuid}
'
);
var
characteristics
=
service
.
characteristics
;
for
(
BluetoothCharacteristic
c
in
characteristics
)
{
if
(
c
.
properties
.
write
)
{
//打印写的特征值 uuid
print
(
'write characteristic uuid:
${c.uuid}
'
);
_writeCharacteristic
=
c
;
}
if
(
characteristic
.
isNotifiable
)
{
_notifiCharacteristicId
=
characteristic
.
characteristicId
;
if
(
kDebugMode
)
{
print
(
'Notifiable characteristic
${characteristic.characteristicId}
of service
${service.serviceId}
'
);
}
if
(
c
.
properties
.
notify
)
{
//打印通知的特征值 uuid
print
(
'notify characteristic uuid:
${c.uuid}
'
);
_notifyCharacteristic
=
c
;
c
.
setNotifyValue
(
true
);
// _lastValueSubscription = c.lastValueStream.listen((value) {
// print(value);
// });
_valueReceivedSubscription
=
c
.
onValueReceived
.
listen
((
value
)
{
print
(
value
);
});
}
}
}
}
// 设置最大传输单元
await
ble
.
requestMtu
(
deviceId:
device
.
id
,
mtu:
512
);
await
Future
.
delayed
(
const
Duration
(
seconds:
1
));
// 添加延迟
deviceStatus
=
'Connected'
;
// 更新设备的连接状态
// Get.snackbar('Connected', 'Connected to ${device.name}');
// Navigator.of(context).pop();
if
(
connectCallback
!=
null
)
{
connectCallback
!(
device
);
}
// 关闭对话框
DialogUtils
.
dismissDialog
();
}
else
if
(
update
.
connectionState
==
DeviceConnectionState
.
connecting
)
{
DialogUtils
.
showToast
(
'设备连接中'
);
}
else
{
DialogUtils
.
dismissDialog
();
DialogUtils
.
showToast
(
'连接设备失败'
);
deviceStatus
=
'Disconnected'
;
// 更新设备的连接状态
});
}
else
if
(
state
==
BluetoothConnectionState
.
connecting
)
{
DialogUtils
.
showToast
(
'正在连接'
);
}
});
}
// 读取数据
Future
<
List
<
int
>>
readData
()
async
{
if
(
selectedDevice
.
value
==
null
)
{
throw
Exception
(
'No device connected'
);
}
final
characteristic
=
QualifiedCharacteristic
(
deviceId:
selectedDevice
.
value
!.
id
,
serviceId:
_serviceId
,
characteristicId:
_writeCharacteristicId
,
);
final
result
=
await
ble
.
readCharacteristic
(
characteristic
);
return
result
;
// 连接设备
await
device
.
connect
().
catchError
((
onError
)
{
DialogUtils
.
showToast
(
'连接设备失败
$onError
'
);
});
}
// 写入数据
...
...
@@ -209,31 +179,6 @@ class BleService extends GetxService {
await
ble
.
writeCharacteristicWithResponse
(
characteristic
,
value:
data
);
}
// 启动循环读取数据
Future
<
void
>
startReading
()
async
{
_shouldContinueReading
=
true
;
while
(
_shouldContinueReading
)
{
// 读取数据
final
data
=
await
readData
();
// 将数据添加到 Stream 中
_readController
.
add
(
data
);
// 等待一段时间,然后再次读取数据
await
Future
.
delayed
(
const
Duration
(
seconds:
1
));
}
}
// 停止循环读取数据
void
stopReading
()
{
_shouldContinueReading
=
false
;
}
@override
void
onClose
()
{
_readController
.
close
();
super
.
onClose
();
}
// 检查权限
Future
<
bool
>
requestBlePermissions
()
async
{
var
isLocationGranted
=
await
Permission
.
locationWhenInUse
.
request
();
...
...
@@ -253,4 +198,9 @@ class BleService extends GetxService {
isBleConnectGranted
==
PermissionStatus
.
granted
&&
isBleAdvertiseGranted
==
PermissionStatus
.
granted
;
}
dipose
()
{
_isScanningSubscription
.
cancel
();
_scanResultsSubscription
.
cancel
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment