提交蓝牙插件及封装
This commit is contained in:
parent
681ed316bc
commit
32b7f4cb52
@ -1,5 +1,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.star_lock">
|
||||
package="com.example.star_lock"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
@ -8,4 +9,12 @@
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
|
||||
tools:remove="android:usesPermissionFlags"
|
||||
tools:targetApi="s" />
|
||||
</manifest>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '11.0'
|
||||
|
||||
#use_modular_headers!
|
||||
use_frameworks! :linkage => :static
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
|
||||
@ -11,6 +11,12 @@ PODS:
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Protobuf (3.23.4)
|
||||
- reactive_ble_mobile (0.0.1):
|
||||
- Flutter
|
||||
- Protobuf (~> 3.5)
|
||||
- SwiftProtobuf (~> 1.0)
|
||||
- SwiftProtobuf (1.22.0)
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
|
||||
@ -21,8 +27,14 @@ DEPENDENCIES:
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- reactive_ble_mobile (from `.symlinks/plugins/reactive_ble_mobile/ios`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Protobuf
|
||||
- SwiftProtobuf
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
@ -36,6 +48,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
reactive_ble_mobile:
|
||||
:path: ".symlinks/plugins/reactive_ble_mobile/ios"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
|
||||
@ -45,9 +59,12 @@ SPEC CHECKSUMS:
|
||||
flutter_native_contact_picker: bd430ba0fbf82768bb50c2c52a69a65759a8f907
|
||||
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
|
||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
Protobuf: c6bc59bbab3d38a71c67f62d7cb7ca8f8ea4eca1
|
||||
reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c
|
||||
SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
|
||||
PODFILE CHECKSUM: 663715e941f9adb426e33bf9376914006f9ea95b
|
||||
PODFILE CHECKSUM: 2f695eae20a86ca77f41095e9bd74ba52bd6304c
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
3ED61D98CC08F93BC18EEFD0 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B7537A79A618D0BBB434A17B /* libPods-Runner.a */; };
|
||||
3EF1E85D6F1EE0C0DCF8449F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09D8B2FA2B26BA5BFF31AB2A /* Pods_Runner.framework */; };
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
@ -31,6 +31,7 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
09D8B2FA2B26BA5BFF31AB2A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
@ -46,7 +47,6 @@
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
99F6494C6B1A24363CCC6D32 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
B7537A79A618D0BBB434A17B /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
BDB5B400176768766E85D5EB /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
DC20461C9C4624BEB2DCD779 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -56,7 +56,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3ED61D98CC08F93BC18EEFD0 /* libPods-Runner.a in Frameworks */,
|
||||
3EF1E85D6F1EE0C0DCF8449F /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -76,7 +76,7 @@
|
||||
9304F75C378DB3447BB2408C /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B7537A79A618D0BBB434A17B /* libPods-Runner.a */,
|
||||
09D8B2FA2B26BA5BFF31AB2A /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@ -349,6 +349,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 7NLFRKNVY3;
|
||||
@ -475,6 +476,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 7NLFRKNVY3;
|
||||
@ -494,6 +496,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 7NLFRKNVY3;
|
||||
|
||||
@ -14,6 +14,10 @@
|
||||
</array>
|
||||
<key>NSContactsUsageDescription</key>
|
||||
<string>Reason we need access to the contact list</string>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>The app uses bluetooth to find, connect and transfer data between different devices</string>
|
||||
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||
<string>The app uses bluetooth to find, connect and transfer data between different devices</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
||||
@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_core/src/get_main.dart';
|
||||
import 'package:star_lock/tools/app_manager.dart';
|
||||
import 'package:star_lock/tools/device_info_service.dart';
|
||||
import 'package:star_lock/tools/platform_info_services.dart';
|
||||
import 'package:star_lock/tools/reactiveBlueTool/getx_ble.dart';
|
||||
import 'package:star_lock/tools/store_service.dart';
|
||||
import 'package:star_lock/translations/app_dept.dart';
|
||||
import 'package:star_lock/translations/trans_lib.dart';
|
||||
@ -19,6 +19,8 @@ void main() async {
|
||||
// 设置国际化信息
|
||||
await _initTranslation();
|
||||
|
||||
GetxBle();
|
||||
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,8 @@ class _UnlockQRCodePageState extends State<UnlockQRCodePage> {
|
||||
// data:'二维码',
|
||||
// size:300,
|
||||
// ),
|
||||
QrImage(data: 'www.baidu.com', size: 300.w),
|
||||
// QrImage(data: 'www.baidu.com', size: 300.w),
|
||||
QrImageView(data: 'www.baidu.com', size: 300.w),
|
||||
SizedBox(height: 50.w,),
|
||||
SubmitBtn(btnName: TranslationLoader.lanKeys!.share!.tr,
|
||||
borderRadius: 20.w,
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/app_settings/app_colors.dart';
|
||||
@ -7,6 +10,7 @@ import 'package:star_lock/mine/mineSet/mineSet_page.dart';
|
||||
import '../../appRouters.dart';
|
||||
import '../../baseWidget.dart';
|
||||
import '../../mine/mine_page.dart';
|
||||
import '../../tools/reactiveBlueTool/getx_ble.dart';
|
||||
import '../../tools/titleAppBar.dart';
|
||||
import '../../translations/trans_lib.dart';
|
||||
|
||||
@ -18,6 +22,26 @@ class StarLockMain extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _StarLockMainState extends State<StarLockMain> with BaseWidget{
|
||||
// final logic = Get.put(GetxBle());
|
||||
|
||||
StreamSubscription<DiscoveredDevice>? _streamSubscription;
|
||||
StreamSubscription<ConnectionStateUpdate>? _connectionStreamSubscription;
|
||||
final flutterReactiveBle = FlutterReactiveBle();
|
||||
List<DiscoveredDevice> deviceList = [];
|
||||
|
||||
@override
|
||||
void setState(VoidCallback fn) {
|
||||
// TODO: implement setState
|
||||
super.setState(fn);
|
||||
|
||||
// BleScanner.to.startScan([
|
||||
//
|
||||
// ]);
|
||||
|
||||
GetxBle.call.scanner.startScan([]);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class BleDeviceConnector extends GetxController {
|
||||
BleDeviceConnector({
|
||||
required FlutterReactiveBle ble,
|
||||
required void Function(String message) logMessage,
|
||||
}) : _ble = ble,
|
||||
_logMessage = logMessage {
|
||||
rxBleConnectionState.bindStream(_deviceConnectionController.stream);
|
||||
}
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
|
||||
final void Function(String message) _logMessage;
|
||||
|
||||
final rxBleConnectionState = Rx<ConnectionStateUpdate>(
|
||||
const ConnectionStateUpdate(
|
||||
deviceId: "",
|
||||
connectionState: DeviceConnectionState.disconnected,
|
||||
failure: null));
|
||||
|
||||
final _deviceConnectionController = StreamController<ConnectionStateUpdate>();
|
||||
|
||||
late StreamSubscription<ConnectionStateUpdate> _connection;
|
||||
|
||||
Future<void> connect(String deviceMAC) async {
|
||||
_logMessage('Start connecting to $deviceMAC');
|
||||
_connection = _ble.connectToDevice(id: deviceMAC).listen(
|
||||
(update) {
|
||||
_logMessage(
|
||||
'ConnectionState for device $deviceMAC : ${update.connectionState}');
|
||||
_deviceConnectionController.add(update);
|
||||
},
|
||||
onError: (Object e) =>
|
||||
_logMessage('Connecting to device $deviceMAC resulted in error $e'),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> disconnect(String deviceMAC) async {
|
||||
try {
|
||||
_logMessage('disconnecting to device: $deviceMAC');
|
||||
await _connection.cancel();
|
||||
} on Exception catch (e, _) {
|
||||
_logMessage("Error disconnecting from a device: $e");
|
||||
} finally {
|
||||
// Since [_connection] subscription is terminated, the "disconnected" state cannot be received and propagated
|
||||
_deviceConnectionController.add(
|
||||
ConnectionStateUpdate(
|
||||
deviceId: deviceMAC,
|
||||
connectionState: DeviceConnectionState.disconnected,
|
||||
failure: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onClose() async {
|
||||
rxBleConnectionState.close();
|
||||
await _deviceConnectionController.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class BleDeviceInteractor extends GetxController {
|
||||
BleDeviceInteractor({
|
||||
required FlutterReactiveBle ble,
|
||||
required void Function(String message) logMessage,
|
||||
}) : _ble = ble,
|
||||
_logMessage = logMessage;
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
|
||||
final void Function(String message) _logMessage;
|
||||
|
||||
Future<List<DiscoveredService>> discoverServices(String deviceId) async {
|
||||
try {
|
||||
_logMessage('Start discovering services for: $deviceId');
|
||||
final result = await _ble.discoverServices(deviceId);
|
||||
_logMessage('Discovering services finished');
|
||||
return result;
|
||||
} on Exception catch (e) {
|
||||
_logMessage('Error occurred when discovering services: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<int>> readCharacteristic(
|
||||
QualifiedCharacteristic characteristic) async {
|
||||
try {
|
||||
final result = await _ble.readCharacteristic(characteristic);
|
||||
_logMessage('Read ${characteristic.characteristicId}: value = $result');
|
||||
return result;
|
||||
} on Exception catch (e, s) {
|
||||
_logMessage(
|
||||
'Error occurred when reading ${characteristic.characteristicId} : $e',
|
||||
);
|
||||
// ignore: avoid_print
|
||||
print(s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeCharacteristicWithResponse(
|
||||
QualifiedCharacteristic characteristic, List<int> value) async {
|
||||
try {
|
||||
_logMessage(
|
||||
'Write with response value : $value to ${characteristic.characteristicId}');
|
||||
await _ble.writeCharacteristicWithResponse(characteristic, value: value);
|
||||
} on Exception catch (e, s) {
|
||||
_logMessage(
|
||||
'Error occurred when writing ${characteristic.characteristicId} : $e',
|
||||
);
|
||||
// ignore: avoid_print
|
||||
print(s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeCharacteristicWithoutResponse(
|
||||
QualifiedCharacteristic characteristic, List<int> value) async {
|
||||
try {
|
||||
await _ble.writeCharacteristicWithoutResponse(characteristic,
|
||||
value: value);
|
||||
_logMessage(
|
||||
'Write without response value: $value to ${characteristic.characteristicId}');
|
||||
} on Exception catch (e, s) {
|
||||
_logMessage(
|
||||
'Error occurred when writing ${characteristic.characteristicId} : $e',
|
||||
);
|
||||
// ignore: avoid_print
|
||||
print(s);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Stream<List<int>> subScribeToCharacteristic(
|
||||
QualifiedCharacteristic characteristic) {
|
||||
_logMessage('Subscribing to: ${characteristic.characteristicId} ');
|
||||
return _ble.subscribeToCharacteristic(characteristic);
|
||||
}
|
||||
}
|
||||
28
star_lock/lib/tools/reactiveBlueTool/ble_logger.dart
Normal file
28
star_lock/lib/tools/reactiveBlueTool/ble_logger.dart
Normal file
@ -0,0 +1,28 @@
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class BleLogger extends GetxController {
|
||||
BleLogger({
|
||||
required FlutterReactiveBle ble,
|
||||
}) : _ble = ble;
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
final Rx<List<String>> rxMessages = Rx<List<String>>([]);
|
||||
final RxBool rxVerboseLogging = false.obs;
|
||||
|
||||
void addToLog(String message) {
|
||||
final now = DateTime.now();
|
||||
final formattedDate = '${now.year}-${now.month}-${now.day} ${now.hour}:${now.minute}:${now.second}';
|
||||
rxMessages.value.add('$formattedDate - $message');
|
||||
}
|
||||
|
||||
void clearLogs() => rxMessages.value.clear();
|
||||
|
||||
void verboseLoggingUpdate() {
|
||||
if (rxVerboseLogging.value) {
|
||||
_ble.logLevel = LogLevel.verbose;
|
||||
} else {
|
||||
_ble.logLevel = LogLevel.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
114
star_lock/lib/tools/reactiveBlueTool/ble_scanner.dart
Normal file
114
star_lock/lib/tools/reactiveBlueTool/ble_scanner.dart
Normal file
@ -0,0 +1,114 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// 这个类负责开启和关闭蓝牙扫描器并输出扫描结果
|
||||
class BleScanner extends GetxController {
|
||||
BleScanner({
|
||||
required FlutterReactiveBle ble,
|
||||
required void Function(String message) logMessage,
|
||||
}) : _ble = ble,
|
||||
_logMessage = logMessage {
|
||||
rxBleScannerState.bindStream(_stateStreamController.stream);
|
||||
}
|
||||
|
||||
// static BleScanner get to => Get.find<BleScanner>();
|
||||
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
|
||||
/// 输入 FlutterReactiveBle 来获取结果及功能
|
||||
final void Function(String message) _logMessage;
|
||||
|
||||
/// 输入日志函数来输出日志
|
||||
final StreamController<BleScannerState> _stateStreamController =
|
||||
StreamController();
|
||||
|
||||
StreamSubscription? _subscription;
|
||||
|
||||
/// 使用 Getx 的 Rx 来监听扫描结果
|
||||
final rxBleScannerState = Rx<BleScannerState>(
|
||||
const BleScannerState(discoveredDevices: [], scanIsInProgress: false));
|
||||
|
||||
final _devices = <DiscoveredDevice>[];
|
||||
|
||||
/// 开始扫描蓝牙设备
|
||||
void startScan(List<Uuid> serviceIds) {
|
||||
_logMessage('Start ble discovery');
|
||||
_devices.clear();
|
||||
_subscription?.cancel();
|
||||
_subscription = _ble.scanForDevices(withServices: serviceIds).listen((device) {
|
||||
final knownDeviceIndex = _devices.indexWhere((d) => d.id == device.id);
|
||||
|
||||
if (knownDeviceIndex >= 0) {
|
||||
_devices[knownDeviceIndex] = device;
|
||||
} else {
|
||||
// if (device.name.toLowerCase().contains((filter.name ?? "".toLowerCase()))) {
|
||||
// if (device.id.contains((filter.mac ?? ""))) {
|
||||
// if (device.rssi >= (filter.rssi ?? -100)) {
|
||||
_devices.add(device);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
_pushState();
|
||||
}, onError: (Object e) => _logMessage('Device scan fails with error: $e'));
|
||||
_pushState();
|
||||
}
|
||||
|
||||
/// 更新扫描结果
|
||||
void _pushState() {
|
||||
_stateStreamController.add(
|
||||
BleScannerState(
|
||||
discoveredDevices: _devices,
|
||||
scanIsInProgress: _subscription != null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 停止扫描蓝牙设备
|
||||
Future<void> stopScan() async {
|
||||
_logMessage('Stop ble discovery');
|
||||
|
||||
await _subscription?.cancel();
|
||||
_subscription = null;
|
||||
_pushState();
|
||||
}
|
||||
|
||||
/// GetxController 的生命周期函数,当页面关闭时,关闭扫描器
|
||||
@override
|
||||
Future<void> onClose() async {
|
||||
rxBleScannerState.close();
|
||||
await _stateStreamController.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
/// 这个类用来存储扫描到的蓝牙设备以及扫描器状态
|
||||
@immutable
|
||||
class BleScannerState {
|
||||
const BleScannerState({
|
||||
required this.discoveredDevices,
|
||||
required this.scanIsInProgress,
|
||||
});
|
||||
|
||||
final List<DiscoveredDevice> discoveredDevices;
|
||||
final bool scanIsInProgress;
|
||||
}
|
||||
|
||||
/// 这个类用来存储扫描器的过滤器
|
||||
class BleScannerFilter {
|
||||
String? name;
|
||||
String? mac;
|
||||
List<Uuid>? serviceId;
|
||||
int? rssi;
|
||||
|
||||
BleScannerFilter({
|
||||
this.name,
|
||||
this.mac,
|
||||
this.serviceId,
|
||||
this.rssi,
|
||||
});
|
||||
}
|
||||
485
star_lock/lib/tools/reactiveBlueTool/ble_sig_gatt_uuids.dart
Normal file
485
star_lock/lib/tools/reactiveBlueTool/ble_sig_gatt_uuids.dart
Normal file
@ -0,0 +1,485 @@
|
||||
class BleSigGattUuids {
|
||||
static const Map serviceUuids = {
|
||||
"1800": "Generic Access",
|
||||
"1811": "Alert Notification Service",
|
||||
"1815": "Automation IO",
|
||||
"180F": "Battery Service",
|
||||
"1810": "Blood Pressure",
|
||||
"181B": "Body Composition",
|
||||
"181E": "Bond Management Service",
|
||||
"181F": "Continuous Glucose Monitoring",
|
||||
"1805": "Current Time Service",
|
||||
"1818": "Cycling Power",
|
||||
"1816": "Cycling Speed and Cadence",
|
||||
"180A": "Device Information",
|
||||
"181A": "Environmental Sensing",
|
||||
"1826": "Fitness Machine",
|
||||
"1801": "Generic Attribute",
|
||||
"1808": "Glucose",
|
||||
"1809": "Health Thermometer",
|
||||
"180D": "Heart Rate",
|
||||
"1823": "HTTP Proxy",
|
||||
"1812": "Human Interface Device",
|
||||
"1802": "Immediate Alert",
|
||||
"1821": "Indoor Positioning",
|
||||
"183A": "Insulin Delivery",
|
||||
"1820": "Internet Protocol Support Service",
|
||||
"1803": "Link Loss",
|
||||
"1819": "Location and Navigation",
|
||||
"1827": "Mesh Provisioning Service",
|
||||
"1828": "Mesh Proxy Service",
|
||||
"1807": "Next DST Change Service",
|
||||
"1825": "Object Transfer Service",
|
||||
"180E": "Phone Alert Status Service",
|
||||
"1822": "Pulse Oximeter Service",
|
||||
"1829": "Reconnection Configuration",
|
||||
"1806": "Reference Time Update Service",
|
||||
"1814": "Running Speed and Cadence",
|
||||
"1813": "Scan Parameters",
|
||||
"1824": "Transport Discovery",
|
||||
"1804": "Tx Power",
|
||||
"181C": "User Data",
|
||||
"181D": "Weight Scale",
|
||||
"183B": "Binary Sensor",
|
||||
"183C": "Emergency Configuration",
|
||||
"183E": "Physical Activity Monitor",
|
||||
"1843": "Audio Input Control",
|
||||
"1844": "Volume Control",
|
||||
"1845": "Volume Offset Control",
|
||||
"1846": "Coordinated Set Identification",
|
||||
"1847": "Device Time",
|
||||
"1848": "Media Control",
|
||||
"1849": "Generic Media Control",
|
||||
"184A": "Constant Tone Extension",
|
||||
"184B": "Telephone Bearer",
|
||||
"184C": "Generic Telephone Bearer",
|
||||
"184D": "Microphone Control",
|
||||
"184E": "Audio Stream Control",
|
||||
"184F": "Broadcast Audio Scan",
|
||||
"1850": "Published Audio Capabilities",
|
||||
"1851": "Published Audio Data",
|
||||
"1852": "Broadcast Audio Announcement",
|
||||
"1853": "Common Audio",
|
||||
"1854": "Hearing Access",
|
||||
"1855": "TMAS"
|
||||
};
|
||||
|
||||
static const Map characteristicUuids = {
|
||||
"2A7E": "Aerobic Heart Rate Lower Limit",
|
||||
"2A84": "Aerobic Heart Rate Upper Limit",
|
||||
"2A7F": "Aerobic Threshold",
|
||||
"2A80": "Age",
|
||||
"2A5A": "Aggregate",
|
||||
"2A43": "Alert Category ID",
|
||||
"2A42": "Alert Category ID Bit Mask",
|
||||
"2A06": "Alert Level",
|
||||
"2A44": "Alert Notification Control Point",
|
||||
"2A3F": "Alert Status",
|
||||
"2AB3": "Altitude",
|
||||
"2A81": "Anaerobic Heart Rate Lower Limit",
|
||||
"2A82": "Anaerobic Heart Rate Upper Limit",
|
||||
"2A83": "Anaerobic Threshold",
|
||||
"2A58": "Analog",
|
||||
"2A59": "Analog Output",
|
||||
"2A73": "Apparent Wind Direction",
|
||||
"2A72": "Apparent Wind Speed",
|
||||
"2A01": "Appearance",
|
||||
"2AA3": "Barometric Pressure Trend",
|
||||
"2A19": "Battery Level",
|
||||
"2A1B": "Battery Level State",
|
||||
"2A1A": "Battery Power State",
|
||||
"2A49": "Blood Pressure Feature",
|
||||
"2A35": "Blood Pressure Measurement",
|
||||
"2A9B": "Body Composition Feature",
|
||||
"2A9C": "Body Composition Measurement",
|
||||
"2A38": "Body Sensor Location",
|
||||
"2AA4": "Bond Management Control Point",
|
||||
"2AA5": "Bond Management Features",
|
||||
"2A22": "Boot Keyboard Input Report",
|
||||
"2A32": "Boot Keyboard Output Report",
|
||||
"2A33": "Boot Mouse Input Report",
|
||||
"2AA6": "Central Address Resolution",
|
||||
"2AA8": "CGM Feature",
|
||||
"2AA7": "CGM Measurement",
|
||||
"2AAB": "CGM Session Run Time",
|
||||
"2AAA": "CGM Session Start Time",
|
||||
"2AAC": "CGM Specific Ops Control Point",
|
||||
"2AA9": "CGM Status",
|
||||
"2ACE": "Cross Trainer Data",
|
||||
"2A5C": "CSC Feature",
|
||||
"2A5B": "CSC Measurement",
|
||||
"2A2B": "Current Time",
|
||||
"2A66": "Cycling Power Control Point",
|
||||
"2A65": "Cycling Power Feature",
|
||||
"2A63": "Cycling Power Measurement",
|
||||
"2A64": "Cycling Power Vector",
|
||||
"2A99": "Database Change Increment",
|
||||
"2A85": "Date of Birth",
|
||||
"2A86": "Date of Threshold Assessment",
|
||||
"2A08": "Date Time",
|
||||
"2A0A": "Day Date Time",
|
||||
"2A09": "Day of Week",
|
||||
"2A7D": "Descriptor Value Changed",
|
||||
"2A00": "Device Name",
|
||||
"2A7B": "Dew Point",
|
||||
"2A56": "Digital",
|
||||
"2A57": "Digital Output",
|
||||
"2A0D": "DST Offset",
|
||||
"2A6C": "Elevation",
|
||||
"2A87": "Email Address",
|
||||
"2A0B": "Exact Time 100",
|
||||
"2A0C": "Exact Time 256",
|
||||
"2A88": "Fat Burn Heart Rate Lower Limit",
|
||||
"2A89": "Fat Burn Heart Rate Upper Limit",
|
||||
"2A26": "Firmware Revision String",
|
||||
"2A8A": "First Name",
|
||||
"2AD9": "Fitness Machine Control Point",
|
||||
"2ACC": "Fitness Machine Feature",
|
||||
"2ADA": "Fitness Machine Status",
|
||||
"2A8B": "Five Zone Heart Rate Limits",
|
||||
"2AB2": "Floor Number",
|
||||
"2A8C": "Gender",
|
||||
"2A51": "Glucose Feature",
|
||||
"2A18": "Glucose Measurement",
|
||||
"2A34": "Glucose Measurement Context",
|
||||
"2A74": "Gust Factor",
|
||||
"2A27": "Hardware Revision String",
|
||||
"2A39": "Heart Rate Control Point",
|
||||
"2A8D": "Heart Rate Max",
|
||||
"2A37": "Heart Rate Measurement",
|
||||
"2A7A": "Heat Index",
|
||||
"2A8E": "Height",
|
||||
"2A4C": "HID Control Point",
|
||||
"2A4A": "HID Information",
|
||||
"2A8F": "Hip Circumference",
|
||||
"2ABA": "HTTP Control Point",
|
||||
"2AB9": "HTTP Entity Body",
|
||||
"2AB7": "HTTP Headers",
|
||||
"2AB8": "HTTP Status Code",
|
||||
"2ABB": "HTTPS Security",
|
||||
"2A6F": "Humidity",
|
||||
"2B22": "IDD Annunciation Status",
|
||||
"2B25": "IDD Command Control Point",
|
||||
"2B26": "IDD Command Data",
|
||||
"2B23": "IDD Features",
|
||||
"2B28": "IDD History Data",
|
||||
"2B27": "IDD Record Access Control Point",
|
||||
"2B21": "IDD Status",
|
||||
"2B20": "IDD Status Changed",
|
||||
"2B24": "IDD Status Reader Control Point",
|
||||
"2A2A": "IEEE 11073-20601 Regulatory Certification Data List",
|
||||
"2AD2": "Indoor Bike Data",
|
||||
"2AAD": "Indoor Positioning Configuration",
|
||||
"2A36": "Intermediate Cuff Pressure",
|
||||
"2A1E": "Intermediate Temperature",
|
||||
"2A77": "Irradiance",
|
||||
"2AA2": "Language",
|
||||
"2A90": "Last Name",
|
||||
"2AAE": "Latitude",
|
||||
"2A6B": "LN Control Point",
|
||||
"2A6A": "LN Feature",
|
||||
"2AB1": "Local East Coordinate",
|
||||
"2AB0": "Local North Coordinate",
|
||||
"2A0F": "Local Time Information",
|
||||
"2A67": "Location and Speed Characteristic",
|
||||
"2AB5": "Location Name",
|
||||
"2AAF": "Longitude",
|
||||
"2A2C": "Magnetic Declination",
|
||||
"2AA0": "Magnetic Flux Density - 2D",
|
||||
"2AA1": "Magnetic Flux Density - 3D",
|
||||
"2A29": "Manufacturer Name String",
|
||||
"2A91": "Maximum Recommended Heart Rate",
|
||||
"2A21": "Measurement Interval",
|
||||
"2A24": "Model Number String",
|
||||
"2A68": "Navigation",
|
||||
"2A3E": "Network Availability",
|
||||
"2A46": "New Alert",
|
||||
"2AC5": "Object Action Control Point",
|
||||
"2AC8": "Object Changed",
|
||||
"2AC1": "Object First-Created",
|
||||
"2AC3": "Object ID",
|
||||
"2AC2": "Object Last-Modified",
|
||||
"2AC6": "Object List Control Point",
|
||||
"2AC7": "Object List Filter",
|
||||
"2ABE": "Object Name",
|
||||
"2AC4": "Object Properties",
|
||||
"2AC0": "Object Size",
|
||||
"2ABF": "Object Type",
|
||||
"2ABD": "OTS Feature",
|
||||
"2A04": "Peripheral Preferred Connection Parameters",
|
||||
"2A02": "Peripheral Privacy Flag",
|
||||
"2A5F": "PLX Continuous Measurement Characteristic",
|
||||
"2A60": "PLX Features",
|
||||
"2A5E": "PLX Spot-Check Measurement",
|
||||
"2A50": "PnP ID",
|
||||
"2A75": "Pollen Concentration",
|
||||
"2A2F": "Position 2D",
|
||||
"2A30": "Position 3D",
|
||||
"2A69": "Position Quality",
|
||||
"2A6D": "Pressure",
|
||||
"2A4E": "Protocol Mode",
|
||||
"2A62": "Pulse Oximetry Control Point",
|
||||
"2A78": "Rainfall",
|
||||
"2B1D": "RC Feature",
|
||||
"2B1E": "RC Settings",
|
||||
"2A03": "Reconnection Address",
|
||||
"2B1F": "Reconnection Configuration Control Point",
|
||||
"2A52": "Record Access Control Point",
|
||||
"2A14": "Reference Time Information",
|
||||
"2A3A": "Removable",
|
||||
"2A4D": "Report",
|
||||
"2A4B": "Report Map",
|
||||
"2AC9": "Resolvable Private Address Only",
|
||||
"2A92": "Resting Heart Rate",
|
||||
"2A40": "Ringer Control point",
|
||||
"2A41": "Ringer Setting",
|
||||
"2AD1": "Rower Data",
|
||||
"2A54": "RSC Feature",
|
||||
"2A53": "RSC Measurement",
|
||||
"2A55": "SC Control Point",
|
||||
"2A4F": "Scan Interval Window",
|
||||
"2A31": "Scan Refresh",
|
||||
"2A3C": "Scientific Temperature Celsius",
|
||||
"2A10": "Secondary Time Zone",
|
||||
"2A5D": "Sensor Location",
|
||||
"2A05": "Service Changed",
|
||||
"2A0E": "Time Zone",
|
||||
"2A11": "Time with DST",
|
||||
"2A12": "Time Accuracy",
|
||||
"2A13": "Time Source",
|
||||
"2A15": "Time Broadcast",
|
||||
"2A16": "Time Update Control Point",
|
||||
"2A17": "Time Update State",
|
||||
"2A25": "Serial Number String",
|
||||
"2A3B": "Service Required",
|
||||
"2A28": "Software Revision String",
|
||||
"2A93": "Sport Type for Aerobic and Anaerobic Thresholds",
|
||||
"2AD0": "Stair Climber Data",
|
||||
"2ACF": "Step Climber Data",
|
||||
"2A3D": "String",
|
||||
"2AD7": "Supported Heart Rate Range",
|
||||
"2AD5": "Supported Inclination Range",
|
||||
"2A47": "Supported New Alert Category",
|
||||
"2AD8": "Supported Power Range",
|
||||
"2AD6": "Supported Resistance Level Range",
|
||||
"2AD4": "Supported Speed Range",
|
||||
"2A48": "Supported Unread Alert Category",
|
||||
"2A23": "System ID",
|
||||
"2ABC": "TDS Control Point",
|
||||
"2A6E": "Temperature",
|
||||
"2A1F": "Temperature Celsius",
|
||||
"2A20": "Temperature Fahrenheit",
|
||||
"2A1C": "Temperature Measurement",
|
||||
"2A1D": "Temperature Type",
|
||||
"2A94": "Three Zone Heart Rate Limits",
|
||||
"2A70": "True Wind Speed",
|
||||
"2A71": "True Wind Direction",
|
||||
"2A95": "Two Zone Heart Rate Limit",
|
||||
"2A07": "Tx Power Level",
|
||||
"2AB4": "Uncertainty",
|
||||
"2A45": "Unread Alert Status",
|
||||
"2AB6": "URI",
|
||||
"2A9F": "User Control Point",
|
||||
"2A9A": "User Index",
|
||||
"2A76": "UV Index",
|
||||
"2A79": "Wind Chill",
|
||||
"2A96": "VO2 Max",
|
||||
"2A97": "Waist Circumference",
|
||||
"2A98": "Weight",
|
||||
"2A9D": "Weight Measurement",
|
||||
"2A9E": "Weight Scale Feature",
|
||||
"2ACD": "Treadmill Data",
|
||||
"2AD3": "Training Status",
|
||||
"2AE0": "Average Current",
|
||||
"2AE1": "Average Voltage",
|
||||
"2AE2": "Boolean",
|
||||
"2AE3": "Chromatic Distance From Planckian",
|
||||
"2AE4": "Chromaticity Coordinates",
|
||||
"2AE5": "Chromaticity In CCT And Duv Values",
|
||||
"2AE6": "Chromaticity Tolerance",
|
||||
"2AE7": "CIE 13.3-1995 Color Rendering Index",
|
||||
"2AE8": "Coefficient",
|
||||
"2AE9": "Correlated Color Temperature",
|
||||
"2AEA": "Count 16",
|
||||
"2AEB": "Count 24",
|
||||
"2AEC": "Country Code",
|
||||
"2AED": "Date UTC",
|
||||
"2AEE": "Electric Current",
|
||||
"2AEF": "Electric Current Range",
|
||||
"2AF0": "Electric Current Specification",
|
||||
"2AF1": "Electric Current Statistics",
|
||||
"2AF2": "Energy",
|
||||
"2AF3": "Energy In A Period Of Day",
|
||||
"2AF4": "Event Statistics",
|
||||
"2AF5": "Fixed String 16",
|
||||
"2AF6": "Fixed String 24",
|
||||
"2AF7": "Fixed String 36",
|
||||
"2AF8": "Fixed String 8",
|
||||
"2AF9": "Generic Level",
|
||||
"2AFA": "Global Trade Item Number",
|
||||
"2AFB": "Illuminance",
|
||||
"2AFC": "Luminous Efficacy",
|
||||
"2AFD": "Luminous Energy",
|
||||
"2AFE": "Luminous Exposure",
|
||||
"2AFF": "Luminous Flux",
|
||||
"2B00": "Luminous Flux Range",
|
||||
"2B01": "Luminous Intensity",
|
||||
"2B02": "B02 Mass Flow",
|
||||
"2B03": "Perceived Lightness",
|
||||
"2B04": "Percentage 8",
|
||||
"2B05": "Power",
|
||||
"2B06": "Power Specification",
|
||||
"2B07": "Relative Runtime In A Current Range",
|
||||
"2B08": "Relative Runtime In A Generic Level Range",
|
||||
"2B09": "Relative Value In A Voltage Range",
|
||||
"2B0A": "Relative Value In An Illuminance Range",
|
||||
"2B0B": "Relative Value In A Period Of Day",
|
||||
"2B0C": "Relative Value In A Temperature Range",
|
||||
"2B0D": "Temperature 8",
|
||||
"2B0E": "Temperature 8 In A Period Of Day",
|
||||
"2B0F": "Temperature 8 Statistics",
|
||||
"2B10": "Temperature Range",
|
||||
"2B11": "Temperature Statistics",
|
||||
"2B12": "Time Decihour 8",
|
||||
"2B13": "Time Exponential 8",
|
||||
"2B14": "Time Hour 24",
|
||||
"2B15": "Time Millisecond 24",
|
||||
"2B16": "Time Second 16",
|
||||
"2B17": "Time Second 8",
|
||||
"2B18": "Voltage",
|
||||
"2B19": "Voltage Specification",
|
||||
"2B1A": "Volume Flow",
|
||||
"2B1B": "Volume Flow",
|
||||
"2B1C": "Volume Flow In A Period Of Day",
|
||||
"2B29": "Client Supported Features",
|
||||
"2B2A": "Database Hash",
|
||||
"2B2B": "BSS Control Point",
|
||||
"2B2C": "BSS Response",
|
||||
"2B2D": "Emergency ID",
|
||||
"2B2E": "Emergency Text",
|
||||
"2B34": "Enhanced Blood Pressure Measurement",
|
||||
"2B35": "Enhanced Intermediate Cuff Pressure",
|
||||
"2B36": "Blood Pressure Record",
|
||||
"2B38": "BR-EDR Handover Data",
|
||||
"2B39": "Bluetooth SIG Data",
|
||||
"2B3A": "Server Supported Features",
|
||||
"2B3B": "Physical Activity Monitor Features",
|
||||
"2B3C": "General Activity Instantaneous Data",
|
||||
"2B3D": "General Activity Summary Data",
|
||||
"2B3E": "CardioRespiratory Activity Instantaneous Data",
|
||||
"2B3F": "CardioRespiratory Activity Summary Data",
|
||||
"2B40": "Step Counter Activity Summary Data",
|
||||
"2B41": "Sleep Activity Instantaneous Data",
|
||||
"2B42": "Sleep Activity Summary Data",
|
||||
"2B43": "Physical Activity Monitor Control Point",
|
||||
"2B44": "Activity Current Session",
|
||||
"2B45": "Physical Activity Session Descriptor",
|
||||
"2B46": "Preferred Units",
|
||||
"2B47": "High Resolution Height",
|
||||
"2B48": "Middle Name",
|
||||
"2B49": "Stride Length",
|
||||
"2B4A": "Handedness",
|
||||
"2B4B": "Device Wearing Position",
|
||||
"2B4C": "Four Zone Heart Rate Limits",
|
||||
"2B4D": "High Intensity Exercise Threshold",
|
||||
"2B4E": "Activity Goal",
|
||||
"2B4F": "Sedentary Interval Notification",
|
||||
"2B50": "Caloric Intake",
|
||||
"2B51": "TMAP Role",
|
||||
"2B77": "Audio Input State",
|
||||
"2B78": "Audio Input Control Point",
|
||||
"2B79": "Audio Input Type",
|
||||
"2B7A": "Audio Input Status",
|
||||
"2B7B": "Audio Input Control Point",
|
||||
"2B7C": "Audio Input Description",
|
||||
"2B7D": "Volume State",
|
||||
"2B7E": "Volume Control Point",
|
||||
"2B7F": "Volume Flags",
|
||||
"2B80": "Volume Offset State",
|
||||
"2B81": "Audio Location",
|
||||
"2B82": "Volume Offset Control Point",
|
||||
"2B83": "Audio Output State",
|
||||
"2B84": "Set Identity Resolving Key",
|
||||
"2B85": "Coordinated Set Size",
|
||||
"2B86": "Set Member Lock",
|
||||
"2B87": "Set Member Rank",
|
||||
"2B8E": "Device Time Feature",
|
||||
"2B8F": "Device Time Parameters",
|
||||
"2B90": "Device Time",
|
||||
"2B91": "Device Time Control Point",
|
||||
"2B92": "Time Change Log Data",
|
||||
"2B93": "Media Player Name",
|
||||
"2B94": "Media Player Icon Object ID",
|
||||
"2B95": "Media Player Icon URL",
|
||||
"2B96": "Track Changed",
|
||||
"2B97": "Track Title",
|
||||
"2B98": "Track Duration",
|
||||
"2B99": "Track Position",
|
||||
"2B9A": "Playback Speed",
|
||||
"2B9B": "Seeking Speed",
|
||||
"2B9C": "Current Track Segments Object ID",
|
||||
"2B9D": "Current Track Object ID",
|
||||
"2B9E": "Next Track Object ID",
|
||||
"2B9F": "Parent Group Object ID",
|
||||
"2BA0": "Current Group Object ID",
|
||||
"2BA1": "Playing Order",
|
||||
"2BA2": "Playing Orders Supported",
|
||||
"2BA3": "Media State",
|
||||
"2BA4": "Media Control Point",
|
||||
"2BA5": "Media Control Point Opcodes Supported",
|
||||
"2BA6": "Search Results Object ID",
|
||||
"2BA7": "Search Control Point",
|
||||
"2BA9": "Media Player Icon Object Type",
|
||||
"2BAA": "Track Segments Object Type",
|
||||
"2BAB": "Track Object Type",
|
||||
"2BAC": "Group Object Type",
|
||||
"2BAD": "Constant Tone Extension Enable",
|
||||
"2BAE": "Advertising Constant Tone Extension Minimum Length",
|
||||
"2BAF": "Advertising Constant Tone Extension Minimum Transmit Count",
|
||||
"2BB0": "Advertising Constant Tone Extension Transmit Duration",
|
||||
"2BB1": "Advertising Constant Tone Extension Interval",
|
||||
"2BB2": "Advertising Constant Tone Extension PHY",
|
||||
"2BB3": "Bearer Provider Name",
|
||||
"2BB4": "Bearer UCI",
|
||||
"2BB5": "Bearer Technology",
|
||||
"2BB6": "Bearer URI Schemes Supported List",
|
||||
"2BB7": "Bearer Signal Strength",
|
||||
"2BB8": "Bearer Signal Strength Reporting Interval",
|
||||
"2BB9": "Bearer List Current Calls",
|
||||
"2BBA": "Content Control ID",
|
||||
"2BBB": "Status Flags",
|
||||
"2BBC": "Incoming Call Target Bearer URI",
|
||||
"2BBD": "Call State",
|
||||
"2BBE": "Call Control Point",
|
||||
"2BBF": "Call Control Point Optional Opcodes",
|
||||
"2BC0": "Termination Reason",
|
||||
"2BC1": "Incoming Call",
|
||||
"2BC2": "Call Friendly Name",
|
||||
"2BC3": "Mute",
|
||||
"2BC4": "Sink ASE",
|
||||
"2BC5": "Source ASE",
|
||||
"2BC6": "ASE Control Point",
|
||||
"2BC7": "Broadcast Audio Scan Control Point",
|
||||
"2BC8": "Broadcast Receive State",
|
||||
"2BC9": "Sink PAC",
|
||||
"2BCA": "Sink Audio Locations",
|
||||
"2BCB": "Source PAC",
|
||||
"2BCC": "Source Audio Locations",
|
||||
"2BCD": "Available Audio Contexts",
|
||||
"2BCE": "Supported Audio Contexts",
|
||||
"2BCF": "Ammonia Concentration",
|
||||
"2BD0": "Carbon Monoxide Concentration",
|
||||
"2BD1": "Nitrogen Dioxide Concentration",
|
||||
"2BD2": "Nitrogen Dioxide Concentration",
|
||||
"2BD3": "Non-Methane Volatile Organic Compounds Concentration",
|
||||
"2BD4": "Ozone Concentration",
|
||||
"2BD5": "Particulate Matter - PM1 Concentration",
|
||||
"2BD6": "Particulate Matter - PM2.5 Concentration",
|
||||
"2BD7": "Particulate Matter - PM10 Concentration",
|
||||
"2BD8": "Sulfur Dioxide Concentration",
|
||||
"2BD9": "Sulfur Hexafluoride Concentration",
|
||||
"2BDA": "Hearing Aid Features",
|
||||
"2BDB": "Hearing Aid Preset Control Point",
|
||||
"2BDC": "Hearing Aid Preset",
|
||||
};
|
||||
}
|
||||
12
star_lock/lib/tools/reactiveBlueTool/ble_status_monitor.dart
Normal file
12
star_lock/lib/tools/reactiveBlueTool/ble_status_monitor.dart
Normal file
@ -0,0 +1,12 @@
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class BleStatusMonitor extends GetxController {
|
||||
BleStatusMonitor(this._ble) {
|
||||
rxBleStatus.bindStream(_ble.statusStream);
|
||||
}
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
|
||||
final Rx<BleStatus> rxBleStatus = BleStatus.unknown.obs;
|
||||
}
|
||||
34
star_lock/lib/tools/reactiveBlueTool/getx_ble.dart
Normal file
34
star_lock/lib/tools/reactiveBlueTool/getx_ble.dart
Normal file
@ -0,0 +1,34 @@
|
||||
library getx_ble;
|
||||
|
||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||
import 'ble_device_connector.dart';
|
||||
import 'ble_device_interactor.dart';
|
||||
import 'ble_logger.dart';
|
||||
import 'ble_scanner.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'ble_status_monitor.dart';
|
||||
|
||||
export 'ble_device_connector.dart';
|
||||
export 'ble_device_interactor.dart';
|
||||
export 'ble_logger.dart';
|
||||
export 'ble_scanner.dart';
|
||||
export 'ble_status_monitor.dart';
|
||||
|
||||
class GetxBle extends GetxController {
|
||||
static GetxBle get call => Get.find<GetxBle>();
|
||||
|
||||
final ble = FlutterReactiveBle();
|
||||
late final BleLogger bleLogger;
|
||||
late final BleStatusMonitor bleStatusMonitor;
|
||||
late final BleScanner scanner;
|
||||
late final BleDeviceConnector connector;
|
||||
late final BleDeviceInteractor interactor;
|
||||
|
||||
GetxBle() {
|
||||
bleLogger = BleLogger(ble: ble);
|
||||
bleStatusMonitor = BleStatusMonitor(ble);
|
||||
scanner = BleScanner(ble: ble, logMessage: bleLogger.addToLog);
|
||||
connector = BleDeviceConnector(ble: ble, logMessage: bleLogger.addToLog);
|
||||
interactor = BleDeviceInteractor(ble: ble, logMessage: bleLogger.addToLog);
|
||||
}
|
||||
}
|
||||
@ -57,7 +57,7 @@ dependencies:
|
||||
#底部弹出选择器
|
||||
flutter_picker: ^2.1.0
|
||||
#生成二维码
|
||||
qr_flutter: ^4.0.0
|
||||
qr_flutter: ^4.1.0
|
||||
#底部选择
|
||||
flutter_pickers: ^2.1.9
|
||||
#万年历
|
||||
@ -66,6 +66,10 @@ dependencies:
|
||||
image_picker: ^1.0.1
|
||||
#跳转到外部
|
||||
url_launcher: ^6.1.12
|
||||
#蓝牙
|
||||
flutter_reactive_ble: ^5.1.1
|
||||
# flutter_blue_plus: ^1.10.5
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user