2.0.1 (#10)
* fix: 修复 iOS 和 macOS 断开后 GATT 被清理导致操作无法完成的问题 * fix: 调整 GATT 缓存 * fix: 修改 iOS 蓝牙使用描述 * fix: 修复无法通过设备地址生成 UUID 的问题,修复由于 bluez 未重写 hashCode 和 equals 导致无法比较缓存实例的问题 * fix: 修改版本信息 * fix: 修复BUG * fix: 调整示例程序 * fix: 优化代码 * fix: 修改版本号 * fix: 更新 REDEME.md * fix: 更新依赖项 * fix: 项目调整 --------- Co-authored-by: jetson2 <jetson2@const.cc>
This commit is contained in:
@ -1,3 +1,9 @@
|
||||
## 2.0.1
|
||||
|
||||
- Fix the issue that GATTs is cleared after peripheral disconnected on iOS and macOS.
|
||||
- Fix the issue that create UUID form peripheral's address failed on Linux.
|
||||
- Fix the issue that instance match failed on Linux.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Rewrite the whole project with federated plugins.
|
||||
|
@ -40,7 +40,7 @@ According to Apple's [documents](https://developer.apple.com/documentation/coreb
|
||||
|
||||
### Linux
|
||||
|
||||
Not tested yet, if you occured any problems, file an issue to let me know about it, i will fix it as soon as possible.
|
||||
Not tested enough, if you occured any problems, file an issue to let me know about it, i will fix it as soon as possible.
|
||||
|
||||
### Windows
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>Hello Bluetooth Low Energy!</string>
|
||||
<string>Hello Bluetooth LowEnergy!</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
@ -162,9 +162,10 @@ class _HomeViewState extends State<HomeView> {
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: discoveredEventArgs,
|
||||
builder: (context, discoveredEventArgs, child) {
|
||||
final items = discoveredEventArgs
|
||||
.where((eventArgs) => eventArgs.advertisement.name != null)
|
||||
.toList();
|
||||
// final items = discoveredEventArgs
|
||||
// .where((eventArgs) => eventArgs.advertisement.name != null)
|
||||
// .toList();
|
||||
final items = discoveredEventArgs;
|
||||
return ListView.separated(
|
||||
itemBuilder: (context, i) {
|
||||
final theme = Theme.of(context);
|
||||
@ -248,7 +249,7 @@ class _HomeViewState extends State<HomeView> {
|
||||
},
|
||||
);
|
||||
},
|
||||
title: Text(name ?? '<EMPTY NAME>'),
|
||||
title: Text(name ?? 'N/A'),
|
||||
subtitle: Text(
|
||||
'$uuid',
|
||||
style: theme.textTheme.bodySmall,
|
||||
|
@ -23,55 +23,55 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
bluetooth_low_energy_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bluetooth_low_energy_android
|
||||
sha256: f2a91728df49d52a77af9c8fb294a7afc173e2ce94abb6f9586949827b88a320
|
||||
sha256: e4a14243be6b4556836a734e53e813a1c5f4f6c8e380ca49ebf8d02e5b3f37dc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
bluetooth_low_energy_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bluetooth_low_energy_ios
|
||||
sha256: bf940f40321d1c3284957dbf7ff15587b4851bd722858798d77314d8f188b94f
|
||||
sha256: "38401d8e50d6f96b3e63f2c7e6fc32d6a1ae7d99dc60520fcb4162eb39ba2dd4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
bluetooth_low_energy_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bluetooth_low_energy_linux
|
||||
sha256: ff162bbf375240a615ee3539484438742c3c334c5ac6750db27a1e458cce8135
|
||||
sha256: c88363e296ecb3a4b936e6d02f21214cf4e894d694c9996b523811b65e2d0eb0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
bluetooth_low_energy_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bluetooth_low_energy_macos
|
||||
sha256: "0e454bde70f8d26a78156a2ffc7193c174f7bd04f8ff52eabfd21385fdcb22f9"
|
||||
sha256: b816568cc943d419bb395fbeb4b7aad66295c5e25e2f5b3e06532394dc27522e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
bluetooth_low_energy_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bluetooth_low_energy_platform_interface
|
||||
sha256: e07eb812e320cb167a2b9a59417fe1e632d23b031595dd8a9b72069243045900
|
||||
sha256: "090b642fa738c04e899c4f4a78e88fa43a7dfa7f5b99f1c882cadad10a68e8fb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
bluetooth_low_energy_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bluetooth_low_energy_windows
|
||||
sha256: "6f28d9d7ce35e795207428f2c493a16759cbee34a74e9b254a29672dc8385205"
|
||||
sha256: ddd66c36811ad3fd347efaaba132e7bb27cdc446afc3e8cd3880c5f26a0d3b54
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
bluez:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
38
bluetooth_low_energy/ios/.gitignore
vendored
38
bluetooth_low_energy/ios/.gitignore
vendored
@ -1,38 +0,0 @@
|
||||
.idea/
|
||||
.vagrant/
|
||||
.sconsign.dblite
|
||||
.svn/
|
||||
|
||||
.DS_Store
|
||||
*.swp
|
||||
profile
|
||||
|
||||
DerivedData/
|
||||
build/
|
||||
GeneratedPluginRegistrant.h
|
||||
GeneratedPluginRegistrant.m
|
||||
|
||||
.generated/
|
||||
|
||||
*.pbxuser
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.perspectivev3
|
||||
|
||||
!default.pbxuser
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.perspectivev3
|
||||
|
||||
xcuserdata
|
||||
|
||||
*.moved-aside
|
||||
|
||||
*.pyc
|
||||
*sync/
|
||||
Icon?
|
||||
.tags*
|
||||
|
||||
/Flutter/Generated.xcconfig
|
||||
/Flutter/ephemeral/
|
||||
/Flutter/flutter_export_environment.sh
|
@ -1,19 +0,0 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
public class BluetoothLowEnergyPlugin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let channel = FlutterMethodChannel(name: "bluetooth_low_energy", binaryMessenger: registrar.messenger())
|
||||
let instance = BluetoothLowEnergyPlugin()
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
switch call.method {
|
||||
case "getPlatformVersion":
|
||||
result("iOS " + UIDevice.current.systemVersion)
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
# The Flutter tooling requires that developers have CMake 3.10 or later
|
||||
# installed. You should not increase this version, as doing so will cause
|
||||
# the plugin to fail to compile for some customers of the plugin.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Project-level configuration.
|
||||
set(PROJECT_NAME "bluetooth_low_energy")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
# This value is used when generating builds using this plugin, so it must
|
||||
# not be changed.
|
||||
set(PLUGIN_NAME "bluetooth_low_energy_plugin")
|
||||
|
||||
# Any new source files that you add to the plugin should be added here.
|
||||
list(APPEND PLUGIN_SOURCES
|
||||
"bluetooth_low_energy_plugin.cc"
|
||||
)
|
||||
|
||||
# Define the plugin library target. Its name must not be changed (see comment
|
||||
# on PLUGIN_NAME above).
|
||||
add_library(${PLUGIN_NAME} SHARED
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
|
||||
# Apply a standard set of build settings that are configured in the
|
||||
# application-level CMakeLists.txt. This can be removed for plugins that want
|
||||
# full control over build settings.
|
||||
apply_standard_settings(${PLUGIN_NAME})
|
||||
|
||||
# Symbols are hidden by default to reduce the chance of accidental conflicts
|
||||
# between plugins. This should not be removed; any symbols that should be
|
||||
# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
||||
|
||||
# Source include directories and library dependencies. Add any plugin-specific
|
||||
# dependencies here.
|
||||
target_include_directories(${PLUGIN_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
|
||||
|
||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||
# This list could contain prebuilt libraries, or libraries created by an
|
||||
# external build triggered from this build file.
|
||||
set(bluetooth_low_energy_bundled_libraries
|
||||
""
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
# === Tests ===
|
||||
# These unit tests can be run from a terminal after building the example.
|
||||
|
||||
# Only enable test builds when building the example (which sets this variable)
|
||||
# so that plugin clients aren't building the tests.
|
||||
if (${include_${PROJECT_NAME}_tests})
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.11.0")
|
||||
message("Unit tests require CMake 3.11.0 or later")
|
||||
else()
|
||||
set(TEST_RUNNER "${PROJECT_NAME}_test")
|
||||
enable_testing()
|
||||
|
||||
# Add the Google Test dependency.
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
||||
)
|
||||
# Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
# Disable install commands for gtest so it doesn't end up in the bundle.
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE)
|
||||
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# The plugin's exported API is not very useful for unit testing, so build the
|
||||
# sources directly into the test binary rather than using the shared library.
|
||||
add_executable(${TEST_RUNNER}
|
||||
test/bluetooth_low_energy_plugin_test.cc
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
apply_standard_settings(${TEST_RUNNER})
|
||||
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE flutter)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
|
||||
|
||||
# Enable automatic test discovery.
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(${TEST_RUNNER})
|
||||
|
||||
endif() # CMake version check
|
||||
endif() # include_${PROJECT_NAME}_tests
|
@ -1,76 +0,0 @@
|
||||
#include "include/bluetooth_low_energy/bluetooth_low_energy_plugin.h"
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "bluetooth_low_energy_plugin_private.h"
|
||||
|
||||
#define BLUETOOTH_LOW_ENERGY_PLUGIN(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), bluetooth_low_energy_plugin_get_type(), \
|
||||
BluetoothLowEnergyPlugin))
|
||||
|
||||
struct _BluetoothLowEnergyPlugin {
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(BluetoothLowEnergyPlugin, bluetooth_low_energy_plugin, g_object_get_type())
|
||||
|
||||
// Called when a method call is received from Flutter.
|
||||
static void bluetooth_low_energy_plugin_handle_method_call(
|
||||
BluetoothLowEnergyPlugin* self,
|
||||
FlMethodCall* method_call) {
|
||||
g_autoptr(FlMethodResponse) response = nullptr;
|
||||
|
||||
const gchar* method = fl_method_call_get_name(method_call);
|
||||
|
||||
if (strcmp(method, "getPlatformVersion") == 0) {
|
||||
response = get_platform_version();
|
||||
} else {
|
||||
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
|
||||
}
|
||||
|
||||
fl_method_call_respond(method_call, response, nullptr);
|
||||
}
|
||||
|
||||
FlMethodResponse* get_platform_version() {
|
||||
struct utsname uname_data = {};
|
||||
uname(&uname_data);
|
||||
g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version);
|
||||
g_autoptr(FlValue) result = fl_value_new_string(version);
|
||||
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
|
||||
}
|
||||
|
||||
static void bluetooth_low_energy_plugin_dispose(GObject* object) {
|
||||
G_OBJECT_CLASS(bluetooth_low_energy_plugin_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void bluetooth_low_energy_plugin_class_init(BluetoothLowEnergyPluginClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = bluetooth_low_energy_plugin_dispose;
|
||||
}
|
||||
|
||||
static void bluetooth_low_energy_plugin_init(BluetoothLowEnergyPlugin* self) {}
|
||||
|
||||
static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call,
|
||||
gpointer user_data) {
|
||||
BluetoothLowEnergyPlugin* plugin = BLUETOOTH_LOW_ENERGY_PLUGIN(user_data);
|
||||
bluetooth_low_energy_plugin_handle_method_call(plugin, method_call);
|
||||
}
|
||||
|
||||
void bluetooth_low_energy_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
|
||||
BluetoothLowEnergyPlugin* plugin = BLUETOOTH_LOW_ENERGY_PLUGIN(
|
||||
g_object_new(bluetooth_low_energy_plugin_get_type(), nullptr));
|
||||
|
||||
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
|
||||
g_autoptr(FlMethodChannel) channel =
|
||||
fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
|
||||
"bluetooth_low_energy",
|
||||
FL_METHOD_CODEC(codec));
|
||||
fl_method_channel_set_method_call_handler(channel, method_call_cb,
|
||||
g_object_ref(plugin),
|
||||
g_object_unref);
|
||||
|
||||
g_object_unref(plugin);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
#include "include/bluetooth_low_energy/bluetooth_low_energy_plugin.h"
|
||||
|
||||
// This file exposes some plugin internals for unit testing. See
|
||||
// https://github.com/flutter/flutter/issues/88724 for current limitations
|
||||
// in the unit-testable API.
|
||||
|
||||
// Handles the getPlatformVersion method call.
|
||||
FlMethodResponse *get_platform_version();
|
@ -1,26 +0,0 @@
|
||||
#ifndef FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_PLUGIN_H_
|
||||
#define FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_PLUGIN_H_
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifdef FLUTTER_PLUGIN_IMPL
|
||||
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define FLUTTER_PLUGIN_EXPORT
|
||||
#endif
|
||||
|
||||
typedef struct _BluetoothLowEnergyPlugin BluetoothLowEnergyPlugin;
|
||||
typedef struct {
|
||||
GObjectClass parent_class;
|
||||
} BluetoothLowEnergyPluginClass;
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT GType bluetooth_low_energy_plugin_get_type();
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void bluetooth_low_energy_plugin_register_with_registrar(
|
||||
FlPluginRegistrar* registrar);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_PLUGIN_H_
|
@ -1,31 +0,0 @@
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "include/bluetooth_low_energy/bluetooth_low_energy_plugin.h"
|
||||
#include "bluetooth_low_energy_plugin_private.h"
|
||||
|
||||
// This demonstrates a simple unit test of the C portion of this plugin's
|
||||
// implementation.
|
||||
//
|
||||
// Once you have built the plugin's example app, you can run these tests
|
||||
// from the command line. For instance, for a plugin called my_plugin
|
||||
// built for x64 debug, run:
|
||||
// $ build/linux/x64/debug/plugins/my_plugin/my_plugin_test
|
||||
|
||||
namespace bluetooth_low_energy {
|
||||
namespace test {
|
||||
|
||||
TEST(BluetoothLowEnergyPlugin, GetPlatformVersion) {
|
||||
g_autoptr(FlMethodResponse) response = get_platform_version();
|
||||
ASSERT_NE(response, nullptr);
|
||||
ASSERT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
|
||||
FlValue* result = fl_method_success_response_get_result(
|
||||
FL_METHOD_SUCCESS_RESPONSE(response));
|
||||
ASSERT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING);
|
||||
// The full string varies, so just validate that it has the right format.
|
||||
EXPECT_THAT(fl_value_get_string(result), testing::StartsWith("Linux "));
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace bluetooth_low_energy
|
@ -1,19 +0,0 @@
|
||||
import Cocoa
|
||||
import FlutterMacOS
|
||||
|
||||
public class BluetoothLowEnergyPlugin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let channel = FlutterMethodChannel(name: "bluetooth_low_energy", binaryMessenger: registrar.messenger)
|
||||
let instance = BluetoothLowEnergyPlugin()
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
switch call.method {
|
||||
case "getPlatformVersion":
|
||||
result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
name: bluetooth_low_energy
|
||||
description: A Flutter plugin for controlling the bluetooth low energy.
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
@ -10,12 +10,12 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface: ^2.0.0
|
||||
bluetooth_low_energy_android: ^2.0.0
|
||||
bluetooth_low_energy_ios: ^2.0.0
|
||||
bluetooth_low_energy_macos: ^2.0.0
|
||||
bluetooth_low_energy_linux: ^2.0.0
|
||||
bluetooth_low_energy_windows: ^2.0.0
|
||||
bluetooth_low_energy_platform_interface: ^2.0.1
|
||||
bluetooth_low_energy_android: ^2.0.1
|
||||
bluetooth_low_energy_ios: ^2.0.1
|
||||
bluetooth_low_energy_macos: ^2.0.1
|
||||
bluetooth_low_energy_linux: ^2.0.1
|
||||
bluetooth_low_energy_windows: ^2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
17
bluetooth_low_energy/windows/.gitignore
vendored
17
bluetooth_low_energy/windows/.gitignore
vendored
@ -1,17 +0,0 @@
|
||||
flutter/
|
||||
|
||||
# Visual Studio user-specific files.
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Visual Studio build-related files.
|
||||
x64/
|
||||
x86/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
@ -1,96 +0,0 @@
|
||||
# The Flutter tooling requires that developers have a version of Visual Studio
|
||||
# installed that includes CMake 3.14 or later. You should not increase this
|
||||
# version, as doing so will cause the plugin to fail to compile for some
|
||||
# customers of the plugin.
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
# Project-level configuration.
|
||||
set(PROJECT_NAME "bluetooth_low_energy")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
# This value is used when generating builds using this plugin, so it must
|
||||
# not be changed
|
||||
set(PLUGIN_NAME "bluetooth_low_energy_plugin")
|
||||
|
||||
# Any new source files that you add to the plugin should be added here.
|
||||
list(APPEND PLUGIN_SOURCES
|
||||
"bluetooth_low_energy_plugin.cpp"
|
||||
"bluetooth_low_energy_plugin.h"
|
||||
)
|
||||
|
||||
# Define the plugin library target. Its name must not be changed (see comment
|
||||
# on PLUGIN_NAME above).
|
||||
add_library(${PLUGIN_NAME} SHARED
|
||||
"include/bluetooth_low_energy/bluetooth_low_energy_plugin_c_api.h"
|
||||
"bluetooth_low_energy_plugin_c_api.cpp"
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
|
||||
# Apply a standard set of build settings that are configured in the
|
||||
# application-level CMakeLists.txt. This can be removed for plugins that want
|
||||
# full control over build settings.
|
||||
apply_standard_settings(${PLUGIN_NAME})
|
||||
|
||||
# Symbols are hidden by default to reduce the chance of accidental conflicts
|
||||
# between plugins. This should not be removed; any symbols that should be
|
||||
# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro.
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
||||
|
||||
# Source include directories and library dependencies. Add any plugin-specific
|
||||
# dependencies here.
|
||||
target_include_directories(${PLUGIN_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
|
||||
|
||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||
# This list could contain prebuilt libraries, or libraries created by an
|
||||
# external build triggered from this build file.
|
||||
set(bluetooth_low_energy_bundled_libraries
|
||||
""
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
# === Tests ===
|
||||
# These unit tests can be run from a terminal after building the example, or
|
||||
# from Visual Studio after opening the generated solution file.
|
||||
|
||||
# Only enable test builds when building the example (which sets this variable)
|
||||
# so that plugin clients aren't building the tests.
|
||||
if (${include_${PROJECT_NAME}_tests})
|
||||
set(TEST_RUNNER "${PROJECT_NAME}_test")
|
||||
enable_testing()
|
||||
|
||||
# Add the Google Test dependency.
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
||||
)
|
||||
# Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
# Disable install commands for gtest so it doesn't end up in the bundle.
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# The plugin's C API is not very useful for unit testing, so build the sources
|
||||
# directly into the test binary rather than using the DLL.
|
||||
add_executable(${TEST_RUNNER}
|
||||
test/bluetooth_low_energy_plugin_test.cpp
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
apply_standard_settings(${TEST_RUNNER})
|
||||
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
|
||||
# flutter_wrapper_plugin has link dependencies on the Flutter DLL.
|
||||
add_custom_command(TARGET ${TEST_RUNNER} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${FLUTTER_LIBRARY}" $<TARGET_FILE_DIR:${TEST_RUNNER}>
|
||||
)
|
||||
|
||||
# Enable automatic test discovery.
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(${TEST_RUNNER})
|
||||
endif()
|
@ -1,3 +1,9 @@
|
||||
## 2.0.1
|
||||
|
||||
- Fix the issue that GATTs is cleared after peripheral disconnected on iOS and macOS.
|
||||
- Fix the issue that create UUID form peripheral's address failed on Linux.
|
||||
- Fix the issue that instance match failed on Linux.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Rewrite the whole project with federated plugins.
|
||||
|
@ -282,11 +282,11 @@ interface MyCentralControllerHostApi {
|
||||
fun getServices(myPeripheralKey: Long): List<MyGattServiceArgs>
|
||||
fun getCharacteristics(myServiceKey: Long): List<MyGattCharacteristicArgs>
|
||||
fun getDescriptors(myCharacteristicKey: Long): List<MyGattDescriptorArgs>
|
||||
fun readCharacteristic(myPeripheralKey: Long, myCharacteristicKey: Long, callback: (Result<ByteArray>) -> Unit)
|
||||
fun writeCharacteristic(myPeripheralKey: Long, myCharacteristicKey: Long, value: ByteArray, myTypeNumber: Long, callback: (Result<Unit>) -> Unit)
|
||||
fun notifyCharacteristic(myPeripheralKey: Long, myCharacteristicKey: Long, state: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
fun readDescriptor(myPeripheralKey: Long, myDescriptorKey: Long, callback: (Result<ByteArray>) -> Unit)
|
||||
fun writeDescriptor(myPeripheralKey: Long, myDescriptorKey: Long, value: ByteArray, callback: (Result<Unit>) -> Unit)
|
||||
fun readCharacteristic(myPeripheralKey: Long, myServiceKey: Long, myCharacteristicKey: Long, callback: (Result<ByteArray>) -> Unit)
|
||||
fun writeCharacteristic(myPeripheralKey: Long, myServiceKey: Long, myCharacteristicKey: Long, value: ByteArray, myTypeNumber: Long, callback: (Result<Unit>) -> Unit)
|
||||
fun notifyCharacteristic(myPeripheralKey: Long, myServiceKey: Long, myCharacteristicKey: Long, state: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
fun readDescriptor(myPeripheralKey: Long, myCharacteristicKey: Long, myDescriptorKey: Long, callback: (Result<ByteArray>) -> Unit)
|
||||
fun writeDescriptor(myPeripheralKey: Long, myCharacteristicKey: Long, myDescriptorKey: Long, value: ByteArray, callback: (Result<Unit>) -> Unit)
|
||||
|
||||
companion object {
|
||||
/** The codec used by MyCentralControllerHostApi. */
|
||||
@ -482,8 +482,9 @@ interface MyCentralControllerHostApi {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val myPeripheralKeyArg = args[0].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myCharacteristicKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
api.readCharacteristic(myPeripheralKeyArg, myCharacteristicKeyArg) { result: Result<ByteArray> ->
|
||||
val myServiceKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myCharacteristicKeyArg = args[2].let { if (it is Int) it.toLong() else it as Long }
|
||||
api.readCharacteristic(myPeripheralKeyArg, myServiceKeyArg, myCharacteristicKeyArg) { result: Result<ByteArray> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
@ -503,10 +504,11 @@ interface MyCentralControllerHostApi {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val myPeripheralKeyArg = args[0].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myCharacteristicKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
val valueArg = args[2] as ByteArray
|
||||
val myTypeNumberArg = args[3].let { if (it is Int) it.toLong() else it as Long }
|
||||
api.writeCharacteristic(myPeripheralKeyArg, myCharacteristicKeyArg, valueArg, myTypeNumberArg) { result: Result<Unit> ->
|
||||
val myServiceKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myCharacteristicKeyArg = args[2].let { if (it is Int) it.toLong() else it as Long }
|
||||
val valueArg = args[3] as ByteArray
|
||||
val myTypeNumberArg = args[4].let { if (it is Int) it.toLong() else it as Long }
|
||||
api.writeCharacteristic(myPeripheralKeyArg, myServiceKeyArg, myCharacteristicKeyArg, valueArg, myTypeNumberArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
@ -525,9 +527,10 @@ interface MyCentralControllerHostApi {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val myPeripheralKeyArg = args[0].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myCharacteristicKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
val stateArg = args[2] as Boolean
|
||||
api.notifyCharacteristic(myPeripheralKeyArg, myCharacteristicKeyArg, stateArg) { result: Result<Unit> ->
|
||||
val myServiceKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myCharacteristicKeyArg = args[2].let { if (it is Int) it.toLong() else it as Long }
|
||||
val stateArg = args[3] as Boolean
|
||||
api.notifyCharacteristic(myPeripheralKeyArg, myServiceKeyArg, myCharacteristicKeyArg, stateArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
@ -546,8 +549,9 @@ interface MyCentralControllerHostApi {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val myPeripheralKeyArg = args[0].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myDescriptorKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
api.readDescriptor(myPeripheralKeyArg, myDescriptorKeyArg) { result: Result<ByteArray> ->
|
||||
val myCharacteristicKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myDescriptorKeyArg = args[2].let { if (it is Int) it.toLong() else it as Long }
|
||||
api.readDescriptor(myPeripheralKeyArg, myCharacteristicKeyArg, myDescriptorKeyArg) { result: Result<ByteArray> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
@ -567,9 +571,10 @@ interface MyCentralControllerHostApi {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val myPeripheralKeyArg = args[0].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myDescriptorKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
val valueArg = args[2] as ByteArray
|
||||
api.writeDescriptor(myPeripheralKeyArg, myDescriptorKeyArg, valueArg) { result: Result<Unit> ->
|
||||
val myCharacteristicKeyArg = args[1].let { if (it is Int) it.toLong() else it as Long }
|
||||
val myDescriptorKeyArg = args[2].let { if (it is Int) it.toLong() else it as Long }
|
||||
val valueArg = args[3] as ByteArray
|
||||
api.writeDescriptor(myPeripheralKeyArg, myCharacteristicKeyArg, myDescriptorKeyArg, valueArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(wrapError(error))
|
||||
|
@ -27,7 +27,8 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
companion object {
|
||||
// const val DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xff.toByte()
|
||||
private const val REQUEST_CODE = 443
|
||||
// private val UUID_HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")
|
||||
|
||||
// private val UUID_HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")
|
||||
private val UUID_CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
|
||||
}
|
||||
|
||||
@ -44,11 +45,11 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
private val myScanCallback = MyScanCallback(this)
|
||||
private val myGattCallback = MyBluetoothGattCallback(this, executor)
|
||||
|
||||
private val devices = mutableMapOf<Int, BluetoothDevice>()
|
||||
private val gatts = mutableMapOf<Int, BluetoothGatt>()
|
||||
private val services = mutableMapOf<Int, BluetoothGattService>()
|
||||
private val characteristics = mutableMapOf<Int, BluetoothGattCharacteristic>()
|
||||
private val descriptors = mutableMapOf<Int, BluetoothGattDescriptor>()
|
||||
private val cachedDevices = mutableMapOf<Int, BluetoothDevice>()
|
||||
private val cachedGATTs = mutableMapOf<Int, BluetoothGatt>()
|
||||
private val cachedServices = mutableMapOf<Int, Map<Int, BluetoothGattService>>()
|
||||
private val cachedCharacteristics = mutableMapOf<Int, Map<Int, BluetoothGattCharacteristic>>()
|
||||
private val cachedDescriptors = mutableMapOf<Int, Map<Int, BluetoothGattDescriptor>>()
|
||||
|
||||
private var registered = false
|
||||
private var discovering = false
|
||||
@ -95,14 +96,14 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
if (discovering) {
|
||||
stopDiscovery()
|
||||
}
|
||||
for (gatt in gatts.values) {
|
||||
for (gatt in cachedGATTs.values) {
|
||||
gatt.disconnect()
|
||||
}
|
||||
devices.clear()
|
||||
gatts.clear()
|
||||
services.clear()
|
||||
characteristics.clear()
|
||||
descriptors.clear()
|
||||
cachedDevices.clear()
|
||||
cachedGATTs.clear()
|
||||
cachedServices.clear()
|
||||
cachedCharacteristics.clear()
|
||||
cachedDescriptors.clear()
|
||||
}
|
||||
|
||||
private fun register() {
|
||||
@ -148,9 +149,9 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
if (unfinishedCallback != null) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
val device = devices[deviceKey] as BluetoothDevice
|
||||
val device = cachedDevices[deviceKey] as BluetoothDevice
|
||||
val autoConnect = false
|
||||
gatts[deviceKey] = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
cachedGATTs[deviceKey] = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val transport = BluetoothDevice.TRANSPORT_LE
|
||||
device.connectGatt(context, autoConnect, myGattCallback, transport)
|
||||
} else {
|
||||
@ -169,7 +170,7 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
if (unfinishedCallback != null) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
val gatt = gatts[deviceKey] as BluetoothGatt
|
||||
val gatt = cachedGATTs[deviceKey] as BluetoothGatt
|
||||
gatt.disconnect()
|
||||
disconnectCallbacks[deviceKey] = callback
|
||||
} catch (e: Throwable) {
|
||||
@ -184,7 +185,7 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
if (unfinishedCallback != null) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
val gatt = gatts[deviceKey] as BluetoothGatt
|
||||
val gatt = cachedGATTs[deviceKey] as BluetoothGatt
|
||||
val discovering = gatt.discoverServices()
|
||||
if (!discovering) {
|
||||
throw IllegalStateException()
|
||||
@ -197,53 +198,35 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
|
||||
override fun getServices(myPeripheralKey: Long): List<MyGattServiceArgs> {
|
||||
val deviceKey = myPeripheralKey.toInt()
|
||||
val gatt = gatts[deviceKey] as BluetoothGatt
|
||||
val services = gatt.services
|
||||
return services.map { service ->
|
||||
val serviceKey = service.hashCode()
|
||||
if (this.services[serviceKey] == null) {
|
||||
this.services[serviceKey] = service
|
||||
}
|
||||
return@map service.toMyArgs()
|
||||
}
|
||||
val services = cachedServices[deviceKey] ?: throw IllegalStateException()
|
||||
return services.values.map { service -> service.toMyArgs() }
|
||||
}
|
||||
|
||||
override fun getCharacteristics(myServiceKey: Long): List<MyGattCharacteristicArgs> {
|
||||
val serviceKey = myServiceKey.toInt()
|
||||
val service = services[serviceKey] as BluetoothGattService
|
||||
val characteristics = service.characteristics
|
||||
return characteristics.map { characteristic ->
|
||||
val characteristicKey = characteristic.hashCode()
|
||||
if (this.characteristics[characteristicKey] == null) {
|
||||
this.characteristics[characteristicKey] = characteristic
|
||||
}
|
||||
return@map characteristic.toMyArgs()
|
||||
}
|
||||
val characteristics = cachedCharacteristics[serviceKey] ?: throw IllegalStateException()
|
||||
return characteristics.values.map { characteristic -> characteristic.toMyArgs() }
|
||||
}
|
||||
|
||||
override fun getDescriptors(myCharacteristicKey: Long): List<MyGattDescriptorArgs> {
|
||||
val characteristicKey = myCharacteristicKey.toInt()
|
||||
val characteristic = characteristics[characteristicKey] as BluetoothGattCharacteristic
|
||||
val descriptors = characteristic.descriptors
|
||||
return descriptors.map { descriptor ->
|
||||
val descriptorKey = descriptor.hashCode()
|
||||
if (this.descriptors[descriptorKey] == null) {
|
||||
this.descriptors[descriptorKey] = descriptor
|
||||
}
|
||||
return@map descriptor.toMyArgs()
|
||||
}
|
||||
val descriptors = cachedDescriptors[characteristicKey] ?: throw IllegalStateException()
|
||||
return descriptors.values.map { descriptor -> descriptor.toMyArgs() }
|
||||
}
|
||||
|
||||
override fun readCharacteristic(myPeripheralKey: Long, myCharacteristicKey: Long, callback: (Result<ByteArray>) -> Unit) {
|
||||
override fun readCharacteristic(myPeripheralKey: Long, myServiceKey: Long, myCharacteristicKey: Long, callback: (Result<ByteArray>) -> Unit) {
|
||||
try {
|
||||
val deviceKey = myPeripheralKey.toInt()
|
||||
val gatt = cachedGATTs[deviceKey] as BluetoothGatt
|
||||
val serviceKey = myServiceKey.toInt()
|
||||
val characteristics = cachedCharacteristics[serviceKey]
|
||||
?: throw IllegalArgumentException()
|
||||
val characteristicKey = myCharacteristicKey.toInt()
|
||||
val characteristic = characteristics[characteristicKey] as BluetoothGattCharacteristic
|
||||
val unfinishedCallback = readCharacteristicCallbacks[characteristicKey]
|
||||
if (unfinishedCallback != null) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
val gatt = gatts[deviceKey] as BluetoothGatt
|
||||
val characteristic = characteristics[characteristicKey] as BluetoothGattCharacteristic
|
||||
val reading = gatt.readCharacteristic(characteristic)
|
||||
if (!reading) {
|
||||
throw IllegalStateException()
|
||||
@ -254,16 +237,19 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeCharacteristic(myPeripheralKey: Long, myCharacteristicKey: Long, value: ByteArray, myTypeNumber: Long, callback: (Result<Unit>) -> Unit) {
|
||||
override fun writeCharacteristic(myPeripheralKey: Long, myServiceKey: Long, myCharacteristicKey: Long, value: ByteArray, myTypeNumber: Long, callback: (Result<Unit>) -> Unit) {
|
||||
try {
|
||||
val deviceKey = myPeripheralKey.toInt()
|
||||
val gatt = cachedGATTs[deviceKey] as BluetoothGatt
|
||||
val serviceKey = myServiceKey.toInt()
|
||||
val characteristics = cachedCharacteristics[serviceKey]
|
||||
?: throw IllegalArgumentException()
|
||||
val characteristicKey = myCharacteristicKey.toInt()
|
||||
val characteristic = characteristics[characteristicKey] as BluetoothGattCharacteristic
|
||||
val unfinishedCallback = writeCharacteristicCallbacks[characteristicKey]
|
||||
if (unfinishedCallback != null) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
val gatt = gatts[deviceKey] as BluetoothGatt
|
||||
val characteristic = characteristics[characteristicKey] as BluetoothGattCharacteristic
|
||||
val myTypeArgs = myTypeNumber.toMyGattCharacteristicTypeArgs()
|
||||
val writeType = myTypeArgs.toType()
|
||||
characteristic.value = value
|
||||
@ -278,11 +264,14 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
}
|
||||
}
|
||||
|
||||
override fun notifyCharacteristic(myPeripheralKey: Long, myCharacteristicKey: Long, state: Boolean, callback: (Result<Unit>) -> Unit) {
|
||||
override fun notifyCharacteristic(myPeripheralKey: Long, myServiceKey: Long, myCharacteristicKey: Long, state: Boolean, callback: (Result<Unit>) -> Unit) {
|
||||
try {
|
||||
val deviceKey = myPeripheralKey.toInt()
|
||||
val gatt = cachedGATTs[deviceKey] as BluetoothGatt
|
||||
val serviceKey = myServiceKey.toInt()
|
||||
val characteristics = cachedCharacteristics[serviceKey]
|
||||
?: throw IllegalArgumentException()
|
||||
val characteristicKey = myCharacteristicKey.toInt()
|
||||
val gatt = gatts[deviceKey] as BluetoothGatt
|
||||
val characteristic = characteristics[characteristicKey] as BluetoothGattCharacteristic
|
||||
val notifying = gatt.setCharacteristicNotification(characteristic, state)
|
||||
if (!notifying) {
|
||||
@ -314,16 +303,19 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
}
|
||||
}
|
||||
|
||||
override fun readDescriptor(myPeripheralKey: Long, myDescriptorKey: Long, callback: (Result<ByteArray>) -> Unit) {
|
||||
override fun readDescriptor(myPeripheralKey: Long, myCharacteristicKey: Long, myDescriptorKey: Long, callback: (Result<ByteArray>) -> Unit) {
|
||||
try {
|
||||
val deviceKey = myPeripheralKey.toInt()
|
||||
val gatt = cachedGATTs[deviceKey] as BluetoothGatt
|
||||
val characteristicKey = myCharacteristicKey.toInt()
|
||||
val descriptors = cachedDescriptors[characteristicKey]
|
||||
?: throw IllegalArgumentException()
|
||||
val descriptorKey = myDescriptorKey.toInt()
|
||||
val descriptor = descriptors[descriptorKey] as BluetoothGattDescriptor
|
||||
val unfinishedCallback = readDescriptorCallbacks[descriptorKey]
|
||||
if (unfinishedCallback != null) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
val gatt = gatts[deviceKey] as BluetoothGatt
|
||||
val descriptor = descriptors[descriptorKey] as BluetoothGattDescriptor
|
||||
val reading = gatt.readDescriptor(descriptor)
|
||||
if (!reading) {
|
||||
throw IllegalStateException()
|
||||
@ -334,16 +326,19 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeDescriptor(myPeripheralKey: Long, myDescriptorKey: Long, value: ByteArray, callback: (Result<Unit>) -> Unit) {
|
||||
override fun writeDescriptor(myPeripheralKey: Long, myCharacteristicKey: Long, myDescriptorKey: Long, value: ByteArray, callback: (Result<Unit>) -> Unit) {
|
||||
try {
|
||||
val deviceKey = myPeripheralKey.toInt()
|
||||
val gatt = cachedGATTs[deviceKey] as BluetoothGatt
|
||||
val characteristicKey = myCharacteristicKey.toInt()
|
||||
val descriptors = cachedDescriptors[characteristicKey]
|
||||
?: throw IllegalArgumentException()
|
||||
val descriptorKey = myDescriptorKey.toInt()
|
||||
val descriptor = descriptors[descriptorKey] as BluetoothGattDescriptor
|
||||
val unfinishedCallback = writeDescriptorCallbacks[descriptorKey]
|
||||
if (unfinishedCallback != null) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
val gatt = gatts[deviceKey] as BluetoothGatt
|
||||
val descriptor = descriptors[descriptorKey] as BluetoothGattDescriptor
|
||||
descriptor.value = value
|
||||
val writing = gatt.writeDescriptor(descriptor)
|
||||
if (!writing) {
|
||||
@ -407,9 +402,7 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
fun onScanResult(result: ScanResult) {
|
||||
val device = result.device
|
||||
val deviceKey = device.hashCode()
|
||||
if (devices[deviceKey] == null) {
|
||||
devices[deviceKey] = device
|
||||
}
|
||||
cachedDevices[deviceKey] = device
|
||||
val myPeripheralArgs = device.toMyArgs()
|
||||
val rssi = result.rssi.toLong()
|
||||
val myAdvertisementArgs = result.myAdvertisementArgs
|
||||
@ -422,27 +415,28 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
val myPeripheralKey = deviceKey.toLong()
|
||||
if (newState != BluetoothProfile.STATE_CONNECTED) {
|
||||
gatt.close()
|
||||
gatts.remove(deviceKey)
|
||||
cachedGATTs.remove(deviceKey)
|
||||
val error = IllegalStateException("GATT is disconnected with status: $status")
|
||||
val discoverGattCallback = discoverGattCallbacks.remove(deviceKey)
|
||||
if (discoverGattCallback != null) {
|
||||
discoverGattCallback(Result.failure(error))
|
||||
}
|
||||
for (service in gatt.services) {
|
||||
for (characteristic in service.characteristics) {
|
||||
val characteristicKey = characteristic.hashCode()
|
||||
val readCharacteristicCallback = readCharacteristicCallbacks.remove(characteristicKey)
|
||||
val writeCharacteristicCallback = writeCharacteristicCallbacks.remove(characteristicKey)
|
||||
val services = cachedServices[deviceKey] ?: emptyMap()
|
||||
for (service in services) {
|
||||
val characteristics = cachedCharacteristics[service.key] ?: emptyMap()
|
||||
for (characteristic in characteristics) {
|
||||
val readCharacteristicCallback = readCharacteristicCallbacks.remove(characteristic.key)
|
||||
val writeCharacteristicCallback = writeCharacteristicCallbacks.remove(characteristic.key)
|
||||
if (readCharacteristicCallback != null) {
|
||||
readCharacteristicCallback(Result.failure(error))
|
||||
}
|
||||
if (writeCharacteristicCallback != null) {
|
||||
writeCharacteristicCallback(Result.failure(error))
|
||||
}
|
||||
for (descriptor in characteristic.descriptors) {
|
||||
val descriptorKey = descriptor.hashCode()
|
||||
val readDescriptorCallback = readDescriptorCallbacks.remove(descriptorKey)
|
||||
val writeDescriptorCallback = writeDescriptorCallbacks.remove(descriptorKey)
|
||||
val descriptors = cachedDescriptors[characteristic.key] ?: emptyMap()
|
||||
for (descriptor in descriptors) {
|
||||
val readDescriptorCallback = readDescriptorCallbacks.remove(descriptor.key)
|
||||
val writeDescriptorCallback = writeDescriptorCallbacks.remove(descriptor.key)
|
||||
if (readDescriptorCallback != null) {
|
||||
readDescriptorCallback(Result.failure(error))
|
||||
}
|
||||
@ -490,6 +484,24 @@ class MyCentralController(private val context: Context, binaryMessenger: BinaryM
|
||||
val deviceKey = device.hashCode()
|
||||
val callback = discoverGattCallbacks.remove(deviceKey) ?: return
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
val cachedServices = mutableMapOf<Int, BluetoothGattService>()
|
||||
for (service in gatt.services) {
|
||||
val serviceKey = service.hashCode()
|
||||
cachedServices[serviceKey] = service
|
||||
val cachedCharacteristics = mutableMapOf<Int, BluetoothGattCharacteristic>()
|
||||
for (characteristic in service.characteristics) {
|
||||
val characteristicKey = characteristic.hashCode()
|
||||
cachedCharacteristics[characteristicKey] = characteristic
|
||||
val cachedDescriptors = mutableMapOf<Int, BluetoothGattDescriptor>()
|
||||
for (descriptor in characteristic.descriptors) {
|
||||
val descriptorKey = descriptor.hashCode()
|
||||
cachedDescriptors[descriptorKey] = descriptor
|
||||
}
|
||||
this.cachedDescriptors[characteristicKey] = cachedDescriptors
|
||||
}
|
||||
this.cachedCharacteristics[serviceKey] = cachedCharacteristics
|
||||
}
|
||||
this.cachedServices[deviceKey] = cachedServices
|
||||
callback(Result.success(Unit))
|
||||
} else {
|
||||
val error = IllegalStateException("Discover GATT failed with status: $status")
|
||||
|
@ -483,12 +483,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey) async {
|
||||
Future<Uint8List> readCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralControllerHostApi.readCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -510,12 +510,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey, Uint8List arg_value, int arg_myTypeNumber) async {
|
||||
Future<void> writeCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey, Uint8List arg_value, int arg_myTypeNumber) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralControllerHostApi.writeCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_value, arg_myTypeNumber]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey, arg_value, arg_myTypeNumber]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -532,12 +532,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> notifyCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey, bool arg_state) async {
|
||||
Future<void> notifyCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey, bool arg_state) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralControllerHostApi.notifyCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_state]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey, arg_state]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -554,12 +554,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readDescriptor(int arg_myPeripheralKey, int arg_myDescriptorKey) async {
|
||||
Future<Uint8List> readDescriptor(int arg_myPeripheralKey, int arg_myCharacteristicKey, int arg_myDescriptorKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralControllerHostApi.readDescriptor', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myDescriptorKey]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_myDescriptorKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -581,12 +581,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeDescriptor(int arg_myPeripheralKey, int arg_myDescriptorKey, Uint8List arg_value) async {
|
||||
Future<void> writeDescriptor(int arg_myPeripheralKey, int arg_myCharacteristicKey, int arg_myDescriptorKey, Uint8List arg_value) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_android.MyCentralControllerHostApi.writeDescriptor', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myDescriptorKey, arg_value]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_myDescriptorKey, arg_value]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
|
@ -126,18 +126,16 @@ class MyCentralController extends CentralController
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final myServiceArgses = await _myApi.getServices(myPeripheral.hashCode);
|
||||
return myServiceArgses
|
||||
.cast<MyGattServiceArgs>()
|
||||
.map(
|
||||
(myServiceArgs) => _myServices.putIfAbsent(
|
||||
myServiceArgs.key,
|
||||
() => MyGattService.fromMyArgs(
|
||||
myPeripheral,
|
||||
myServiceArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myServiceArgses.cast<MyGattServiceArgs>().map(
|
||||
(myServiceArgs) {
|
||||
final myService = MyGattService.fromMyArgs(
|
||||
myPeripheral,
|
||||
myServiceArgs,
|
||||
);
|
||||
_myServices[myService.hashCode] = myService;
|
||||
return myService;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -149,18 +147,16 @@ class MyCentralController extends CentralController
|
||||
final myCharactersiticArgses = await _myApi.getCharacteristics(
|
||||
myService.hashCode,
|
||||
);
|
||||
return myCharactersiticArgses
|
||||
.cast<MyGattCharacteristicArgs>()
|
||||
.map(
|
||||
(myCharacteristicArgs) => _myCharacteristics.putIfAbsent(
|
||||
myCharacteristicArgs.key,
|
||||
() => MyGattCharacteristic.fromMyArgs(
|
||||
myService,
|
||||
myCharacteristicArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myCharactersiticArgses.cast<MyGattCharacteristicArgs>().map(
|
||||
(myCharacteristicArgs) {
|
||||
final myCharacteristic = MyGattCharacteristic.fromMyArgs(
|
||||
myService,
|
||||
myCharacteristicArgs,
|
||||
);
|
||||
_myCharacteristics[myCharacteristic.hashCode] = myCharacteristic;
|
||||
return myCharacteristic;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -172,18 +168,16 @@ class MyCentralController extends CentralController
|
||||
final myDescriptorArgses = await _myApi.getDescriptors(
|
||||
myCharacteristic.hashCode,
|
||||
);
|
||||
return myDescriptorArgses
|
||||
.cast<MyGattDescriptorArgs>()
|
||||
.map(
|
||||
(myDescriptorArgs) => _myDescriptors.putIfAbsent(
|
||||
myDescriptorArgs.key,
|
||||
() => MyGattDescriptor.fromMyArgs(
|
||||
myCharacteristic,
|
||||
myDescriptorArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myDescriptorArgses.cast<MyGattDescriptorArgs>().map(
|
||||
(myDescriptorArgs) {
|
||||
final myDescriptor = MyGattDescriptor.fromMyArgs(
|
||||
myCharacteristic,
|
||||
myDescriptorArgs,
|
||||
);
|
||||
_myDescriptors[myDescriptor.hashCode] = myDescriptor;
|
||||
return myDescriptor;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -195,6 +189,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final value = await _myApi.readCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
);
|
||||
return value;
|
||||
@ -214,6 +209,7 @@ class MyCentralController extends CentralController
|
||||
final typeNumber = typeArgs.index;
|
||||
await _myApi.writeCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
value,
|
||||
typeNumber,
|
||||
@ -231,6 +227,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
await _myApi.notifyCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
state,
|
||||
);
|
||||
@ -245,6 +242,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final value = await _myApi.readDescriptor(
|
||||
myPeripheral.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
myDescriptor.hashCode,
|
||||
);
|
||||
return value;
|
||||
@ -262,6 +260,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
await _myApi.writeDescriptor(
|
||||
myPeripheral.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
myDescriptor.hashCode,
|
||||
value,
|
||||
);
|
||||
@ -285,10 +284,8 @@ class MyCentralController extends CentralController
|
||||
int rssi,
|
||||
MyAdvertisementArgs myAdvertisementArgs,
|
||||
) {
|
||||
final myPeripheral = _myPeripherals.putIfAbsent(
|
||||
myPeripheralArgs.key,
|
||||
() => MyPeripheral.fromMyArgs(myPeripheralArgs),
|
||||
);
|
||||
final myPeripheral = MyPeripheral.fromMyArgs(myPeripheralArgs);
|
||||
_myPeripherals[myPeripheral.hashCode] = myPeripheral;
|
||||
final advertisement = myAdvertisementArgs.toAdvertisement();
|
||||
final eventArgs = CentralDiscoveredEventArgs(
|
||||
myPeripheral,
|
||||
|
@ -29,10 +29,15 @@ abstract class MyCentralControllerHostApi {
|
||||
List<MyGattCharacteristicArgs> getCharacteristics(int myServiceKey);
|
||||
List<MyGattDescriptorArgs> getDescriptors(int myCharacteristicKey);
|
||||
@async
|
||||
Uint8List readCharacteristic(int myPeripheralKey, int myCharacteristicKey);
|
||||
Uint8List readCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
);
|
||||
@async
|
||||
void writeCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
Uint8List value,
|
||||
int myTypeNumber,
|
||||
@ -40,14 +45,20 @@ abstract class MyCentralControllerHostApi {
|
||||
@async
|
||||
void notifyCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
bool state,
|
||||
);
|
||||
@async
|
||||
Uint8List readDescriptor(int myPeripheralKey, int myDescriptorKey);
|
||||
Uint8List readDescriptor(
|
||||
int myPeripheralKey,
|
||||
int myCharacteristicKey,
|
||||
int myDescriptorKey,
|
||||
);
|
||||
@async
|
||||
void writeDescriptor(
|
||||
int myPeripheralKey,
|
||||
int myCharacteristicKey,
|
||||
int myDescriptorKey,
|
||||
Uint8List value,
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: bluetooth_low_energy_android
|
||||
description: Android implementation of the bluetooth_low_energy plugin.
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
@ -10,7 +10,7 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface: ^2.0.0
|
||||
bluetooth_low_energy_platform_interface: ^2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -1,3 +1,9 @@
|
||||
## 2.0.1
|
||||
|
||||
- Fix the issue that GATTs is cleared after peripheral disconnected on iOS and macOS.
|
||||
- Fix the issue that create UUID form peripheral's address failed on Linux.
|
||||
- Fix the issue that instance match failed on Linux.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Rewrite the whole project with federated plugins.
|
||||
|
@ -258,11 +258,11 @@ protocol MyCentralControllerHostApi {
|
||||
func getServices(myPeripheralKey: Int64) throws -> [MyGattServiceArgs]
|
||||
func getCharacteristics(myServiceKey: Int64) throws -> [MyGattCharacteristicArgs]
|
||||
func getDescriptors(myCharacteristicKey: Int64) throws -> [MyGattDescriptorArgs]
|
||||
func readCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readDescriptor(myPeripheralKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeDescriptor(myPeripheralKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@ -426,8 +426,9 @@ class MyCentralControllerHostApiSetup {
|
||||
readCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.readCharacteristic(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg) { result in
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
api.readCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -444,10 +445,11 @@ class MyCentralControllerHostApiSetup {
|
||||
writeCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let valueArg = args[2] as! FlutterStandardTypedData
|
||||
let myTypeNumberArg = args[3] is Int64 ? args[3] as! Int64 : Int64(args[3] as! Int32)
|
||||
api.writeCharacteristic(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, value: valueArg, myTypeNumber: myTypeNumberArg) { result in
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let valueArg = args[3] as! FlutterStandardTypedData
|
||||
let myTypeNumberArg = args[4] is Int64 ? args[4] as! Int64 : Int64(args[4] as! Int32)
|
||||
api.writeCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg, value: valueArg, myTypeNumber: myTypeNumberArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -464,9 +466,10 @@ class MyCentralControllerHostApiSetup {
|
||||
notifyCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let stateArg = args[2] as! Bool
|
||||
api.notifyCharacteristic(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, state: stateArg) { result in
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let stateArg = args[3] as! Bool
|
||||
api.notifyCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg, state: stateArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -483,8 +486,9 @@ class MyCentralControllerHostApiSetup {
|
||||
readDescriptorChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myDescriptorKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.readDescriptor(myPeripheralKey: myPeripheralKeyArg, myDescriptorKey: myDescriptorKeyArg) { result in
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myDescriptorKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
api.readDescriptor(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, myDescriptorKey: myDescriptorKeyArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -501,9 +505,10 @@ class MyCentralControllerHostApiSetup {
|
||||
writeDescriptorChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myDescriptorKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let valueArg = args[2] as! FlutterStandardTypedData
|
||||
api.writeDescriptor(myPeripheralKey: myPeripheralKeyArg, myDescriptorKey: myDescriptorKeyArg, value: valueArg) { result in
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myDescriptorKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let valueArg = args[3] as! FlutterStandardTypedData
|
||||
api.writeDescriptor(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, myDescriptorKey: myDescriptorKeyArg, value: valueArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
|
@ -19,10 +19,10 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
private lazy var myPeripheralDelegate = MyPeripheralDelegate(self)
|
||||
private let centralManager = CBCentralManager()
|
||||
|
||||
private var peripherals = [Int: CBPeripheral]()
|
||||
private var services = [Int: CBService]()
|
||||
private var characteristics = [Int: CBCharacteristic]()
|
||||
private var descriptors = [Int: CBDescriptor]()
|
||||
private var cachedPeripherals = [Int: CBPeripheral]()
|
||||
private var cachedServices = [Int: [Int: CBService]]()
|
||||
private var cachedCharacteristics = [Int: [Int: CBCharacteristic]]()
|
||||
private var cachedDescriptors = [Int: [Int: CBDescriptor]]()
|
||||
|
||||
var setUpCompletion: ((Result<MyCentralControllerArgs, Error>) -> Void)?
|
||||
var connectCompletions = [Int: (Result<Void, Error>) -> Void]()
|
||||
@ -61,16 +61,16 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
if(centralManager.isScanning) {
|
||||
centralManager.stopScan()
|
||||
}
|
||||
for peripheral in peripherals.values {
|
||||
for peripheral in cachedPeripherals.values {
|
||||
peripheral.delegate = nil
|
||||
if peripheral.state != .disconnected {
|
||||
centralManager.cancelPeripheralConnection(peripheral)
|
||||
}
|
||||
}
|
||||
peripherals.removeAll()
|
||||
services.removeAll()
|
||||
characteristics.removeAll()
|
||||
descriptors.removeAll()
|
||||
cachedPeripherals.removeAll()
|
||||
cachedServices.removeAll()
|
||||
cachedCharacteristics.removeAll()
|
||||
cachedDescriptors.removeAll()
|
||||
}
|
||||
|
||||
func startDiscovery() throws {
|
||||
@ -89,7 +89,7 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
centralManager.connect(peripheral)
|
||||
@ -106,7 +106,7 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
centralManager.cancelPeripheralConnection(peripheral)
|
||||
@ -123,7 +123,7 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.discoverServices(nil)
|
||||
@ -135,53 +135,42 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
|
||||
func getServices(myPeripheralKey: Int64) throws -> [MyGattServiceArgs] {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let services = cachedServices[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let services = peripheral.services ?? []
|
||||
return services.map { service in
|
||||
let serviceKey = service.hash
|
||||
if self.services[serviceKey] == nil {
|
||||
self.services[serviceKey] = service
|
||||
}
|
||||
return services.map { (key, service) in
|
||||
return service.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func getCharacteristics(myServiceKey: Int64) throws -> [MyGattCharacteristicArgs] {
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let service = services[serviceKey] else {
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristics = service.characteristics ?? []
|
||||
return characteristics.map { characteristic in
|
||||
let characteristicKey = characteristic.hash
|
||||
if self.characteristics[characteristicKey] == nil {
|
||||
self.characteristics[characteristicKey] = characteristic
|
||||
}
|
||||
return characteristics.map { (key, characteristic) in
|
||||
return characteristic.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func getDescriptors(myCharacteristicKey: Int64) throws -> [MyGattDescriptorArgs] {
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let characteristic = characteristics[characteristicKey] else {
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let descritors = characteristic.descriptors ?? []
|
||||
return descritors.map { descriptor in
|
||||
let descriptorKey = descriptor.hash
|
||||
if self.descriptors[descriptorKey] == nil {
|
||||
self.descriptors[descriptorKey] = descriptor
|
||||
}
|
||||
return descriptors.map { (key, descriptor) in
|
||||
return descriptor.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func readCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
func readCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
@ -199,10 +188,14 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
@ -226,10 +219,14 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
@ -247,10 +244,14 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func readDescriptor(myPeripheralKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
func readDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let descriptorKey = Int(myDescriptorKey)
|
||||
@ -268,10 +269,14 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func writeDescriptor(myPeripheralKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func writeDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let descriptorKey = Int(myDescriptorKey)
|
||||
@ -307,9 +312,9 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
|
||||
func didDiscover(_ peripheral: CBPeripheral, _ advertisementData: [String : Any], _ rssiNumber: NSNumber) {
|
||||
let peripheralKey = peripheral.hash
|
||||
if peripherals[peripheralKey] == nil {
|
||||
if cachedPeripherals[peripheralKey] == nil {
|
||||
peripheral.delegate = myPeripheralDelegate
|
||||
peripherals[peripheralKey] = peripheral
|
||||
cachedPeripherals[peripheralKey] = peripheral
|
||||
}
|
||||
let myPeripheralArgs = peripheral.toMyArgs()
|
||||
let rssi = rssiNumber.int64Value
|
||||
@ -368,26 +373,24 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
let myPeripheralKey = Int64(peripheralKey)
|
||||
let discoverGattCompletion = discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
if discoverGattCompletion != nil {
|
||||
discoverGattCompletion!(.failure(error ?? MyError.illegalState))
|
||||
didDiscoverGATT(peripheral, error ?? MyError.unknown)
|
||||
}
|
||||
let services = peripheral.services ?? []
|
||||
let services = cachedServices[peripheralKey] ?? [:]
|
||||
for service in services {
|
||||
let characteristics = service.characteristics ?? []
|
||||
let characteristics = cachedCharacteristics[service.key] ?? [:]
|
||||
for characteristic in characteristics {
|
||||
let characteristicKey = characteristic.hash
|
||||
let readCharacteristicCompletion = readCharacteristicCompletions.removeValue(forKey: characteristicKey)
|
||||
let writeCharacteristicCompletion = writeCharacteristicCompletions.removeValue(forKey: characteristicKey)
|
||||
let readCharacteristicCompletion = readCharacteristicCompletions.removeValue(forKey: characteristic.key)
|
||||
let writeCharacteristicCompletion = writeCharacteristicCompletions.removeValue(forKey: characteristic.key)
|
||||
if readCharacteristicCompletion != nil {
|
||||
readCharacteristicCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
if writeCharacteristicCompletion != nil {
|
||||
writeCharacteristicCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
let descriptors = characteristic.descriptors ?? []
|
||||
let descriptors = cachedDescriptors[characteristic.key] ?? [:]
|
||||
for descriptor in descriptors {
|
||||
let descriptorKey = descriptor.hash
|
||||
let readDescriptorCompletion = readDescriptorCompletions.removeValue(forKey: descriptorKey)
|
||||
let writeDescriptorCompletion = writeDescriptorCompletions.removeValue(forKey: descriptorKey)
|
||||
let readDescriptorCompletion = readDescriptorCompletions.removeValue(forKey: descriptor.key)
|
||||
let writeDescriptorCompletion = writeDescriptorCompletions.removeValue(forKey: descriptor.key)
|
||||
if readDescriptorCompletion != nil {
|
||||
readDescriptorCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
@ -411,37 +414,28 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
|
||||
func didDiscoverServices(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
guard let completion = discoverGattCompletions[peripheralKey] else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
var services = peripheral.services ?? []
|
||||
if services.isEmpty {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
completion(.success(()))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
peripheral.discoverCharacteristics(nil, for: service)
|
||||
}
|
||||
} else {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
completion(.failure(error!))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
func didDiscoverCharacteristics(_ peripheral: CBPeripheral, _ service: CBService, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
guard let completion = discoverGattCompletions[peripheralKey] else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
var characteristics = service.characteristics ?? []
|
||||
if characteristics.isEmpty {
|
||||
var services = unfinishedServices.removeValue(forKey: peripheralKey) ?? []
|
||||
if services.isEmpty {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
completion(.success(()))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
@ -453,24 +447,18 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
peripheral.discoverDescriptors(for: characteristic)
|
||||
}
|
||||
} else {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
unfinishedServices.removeValue(forKey: peripheralKey)
|
||||
completion(.failure(error!))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
func didDiscoverDescriptors(_ peripheral: CBPeripheral, _ characteristic: CBCharacteristic, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
guard let completion = discoverGattCompletions[peripheralKey] else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
var characteristics = unfinishedCharacteristics.removeValue(forKey: peripheralKey) ?? []
|
||||
if (characteristics.isEmpty) {
|
||||
var services = unfinishedServices.removeValue(forKey: peripheralKey) ?? []
|
||||
if services.isEmpty {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
completion(.success(()))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
@ -482,9 +470,41 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
peripheral.discoverDescriptors(for: characteristic)
|
||||
}
|
||||
} else {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
unfinishedServices.removeValue(forKey: peripheralKey)
|
||||
unfinishedCharacteristics.removeValue(forKey: peripheralKey)
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
private func didDiscoverGATT(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
unfinishedServices.removeValue(forKey: peripheralKey)
|
||||
unfinishedCharacteristics.removeValue(forKey: peripheralKey)
|
||||
guard let completion = discoverGattCompletions.removeValue(forKey: peripheralKey) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
let services = peripheral.services ?? []
|
||||
var cachedServices = [Int: CBService]()
|
||||
for service in services {
|
||||
let serviceKey = service.hash
|
||||
cachedServices[serviceKey] = service
|
||||
let characteristics = service.characteristics ?? []
|
||||
var cachedCharacteristics = [Int: CBCharacteristic]()
|
||||
for characteristic in characteristics {
|
||||
let characteristicKey = characteristic.hash
|
||||
cachedCharacteristics[characteristicKey] = characteristic
|
||||
let descriptors = characteristic.descriptors ?? []
|
||||
var cachedDescriptors = [Int: CBDescriptor]()
|
||||
for descriptor in descriptors {
|
||||
let descriptorKey = descriptor.hash
|
||||
cachedDescriptors[descriptorKey] = descriptor
|
||||
}
|
||||
self.cachedDescriptors[characteristicKey] = cachedDescriptors
|
||||
}
|
||||
self.cachedCharacteristics[serviceKey] = cachedCharacteristics
|
||||
}
|
||||
self.cachedServices[peripheralKey] = cachedServices
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint bluetooth_low_energy_ios.podspec` to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'bluetooth_low_energy_ios'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'A new Flutter plugin project.'
|
||||
s.description = <<-DESC
|
||||
A new Flutter plugin project.
|
||||
DESC
|
||||
s.homepage = 'http://example.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Your Company' => 'email@example.com' }
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.dependency 'Flutter'
|
||||
s.platform = :ios, '9.0'
|
||||
|
||||
# Flutter.framework does not contain a i386 slice.
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
|
||||
s.swift_version = '5.0'
|
||||
end
|
@ -483,12 +483,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey) async {
|
||||
Future<Uint8List> readCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_ios.MyCentralControllerHostApi.readCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -510,12 +510,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey, Uint8List arg_value, int arg_myTypeNumber) async {
|
||||
Future<void> writeCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey, Uint8List arg_value, int arg_myTypeNumber) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_ios.MyCentralControllerHostApi.writeCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_value, arg_myTypeNumber]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey, arg_value, arg_myTypeNumber]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -532,12 +532,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> notifyCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey, bool arg_state) async {
|
||||
Future<void> notifyCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey, bool arg_state) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_ios.MyCentralControllerHostApi.notifyCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_state]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey, arg_state]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -554,12 +554,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readDescriptor(int arg_myPeripheralKey, int arg_myDescriptorKey) async {
|
||||
Future<Uint8List> readDescriptor(int arg_myPeripheralKey, int arg_myCharacteristicKey, int arg_myDescriptorKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_ios.MyCentralControllerHostApi.readDescriptor', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myDescriptorKey]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_myDescriptorKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -581,12 +581,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeDescriptor(int arg_myPeripheralKey, int arg_myDescriptorKey, Uint8List arg_value) async {
|
||||
Future<void> writeDescriptor(int arg_myPeripheralKey, int arg_myCharacteristicKey, int arg_myDescriptorKey, Uint8List arg_value) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_ios.MyCentralControllerHostApi.writeDescriptor', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myDescriptorKey, arg_value]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_myDescriptorKey, arg_value]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
|
@ -126,18 +126,16 @@ class MyCentralController extends CentralController
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final myServiceArgses = await _myApi.getServices(myPeripheral.hashCode);
|
||||
return myServiceArgses
|
||||
.cast<MyGattServiceArgs>()
|
||||
.map(
|
||||
(myServiceArgs) => _myServices.putIfAbsent(
|
||||
myServiceArgs.key,
|
||||
() => MyGattService.fromMyArgs(
|
||||
myPeripheral,
|
||||
myServiceArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myServiceArgses.cast<MyGattServiceArgs>().map(
|
||||
(myServiceArgs) {
|
||||
final myService = MyGattService.fromMyArgs(
|
||||
myPeripheral,
|
||||
myServiceArgs,
|
||||
);
|
||||
_myServices[myService.hashCode] = myService;
|
||||
return myService;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -149,18 +147,16 @@ class MyCentralController extends CentralController
|
||||
final myCharactersiticArgses = await _myApi.getCharacteristics(
|
||||
myService.hashCode,
|
||||
);
|
||||
return myCharactersiticArgses
|
||||
.cast<MyGattCharacteristicArgs>()
|
||||
.map(
|
||||
(myCharacteristicArgs) => _myCharacteristics.putIfAbsent(
|
||||
myCharacteristicArgs.key,
|
||||
() => MyGattCharacteristic.fromMyArgs(
|
||||
myService,
|
||||
myCharacteristicArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myCharactersiticArgses.cast<MyGattCharacteristicArgs>().map(
|
||||
(myCharacteristicArgs) {
|
||||
final myCharacteristic = MyGattCharacteristic.fromMyArgs(
|
||||
myService,
|
||||
myCharacteristicArgs,
|
||||
);
|
||||
_myCharacteristics[myCharacteristic.hashCode] = myCharacteristic;
|
||||
return myCharacteristic;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -172,18 +168,16 @@ class MyCentralController extends CentralController
|
||||
final myDescriptorArgses = await _myApi.getDescriptors(
|
||||
myCharacteristic.hashCode,
|
||||
);
|
||||
return myDescriptorArgses
|
||||
.cast<MyGattDescriptorArgs>()
|
||||
.map(
|
||||
(myDescriptorArgs) => _myDescriptors.putIfAbsent(
|
||||
myDescriptorArgs.key,
|
||||
() => MyGattDescriptor.fromMyArgs(
|
||||
myCharacteristic,
|
||||
myDescriptorArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myDescriptorArgses.cast<MyGattDescriptorArgs>().map(
|
||||
(myDescriptorArgs) {
|
||||
final myDescriptor = MyGattDescriptor.fromMyArgs(
|
||||
myCharacteristic,
|
||||
myDescriptorArgs,
|
||||
);
|
||||
_myDescriptors[myDescriptor.hashCode] = myDescriptor;
|
||||
return myDescriptor;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -196,6 +190,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final value = await _myApi.readCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
);
|
||||
return value;
|
||||
@ -215,6 +210,7 @@ class MyCentralController extends CentralController
|
||||
final typeNumber = typeArgs.index;
|
||||
await _myApi.writeCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
value,
|
||||
typeNumber,
|
||||
@ -232,6 +228,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
await _myApi.notifyCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
state,
|
||||
);
|
||||
@ -246,6 +243,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final value = await _myApi.readDescriptor(
|
||||
myPeripheral.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
myDescriptor.hashCode,
|
||||
);
|
||||
return value;
|
||||
@ -263,6 +261,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
await _myApi.writeDescriptor(
|
||||
myPeripheral.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
myDescriptor.hashCode,
|
||||
value,
|
||||
);
|
||||
@ -286,10 +285,8 @@ class MyCentralController extends CentralController
|
||||
int rssi,
|
||||
MyAdvertisementArgs myAdvertisementArgs,
|
||||
) {
|
||||
final myPeripheral = _myPeripherals.putIfAbsent(
|
||||
myPeripheralArgs.key,
|
||||
() => MyPeripheral.fromMyArgs(myPeripheralArgs),
|
||||
);
|
||||
final myPeripheral = MyPeripheral.fromMyArgs(myPeripheralArgs);
|
||||
_myPeripherals[myPeripheral.hashCode] = myPeripheral;
|
||||
final advertisement = myAdvertisementArgs.toAdvertisement();
|
||||
final eventArgs = CentralDiscoveredEventArgs(
|
||||
myPeripheral,
|
||||
|
@ -25,10 +25,15 @@ abstract class MyCentralControllerHostApi {
|
||||
List<MyGattCharacteristicArgs> getCharacteristics(int myServiceKey);
|
||||
List<MyGattDescriptorArgs> getDescriptors(int myCharacteristicKey);
|
||||
@async
|
||||
Uint8List readCharacteristic(int myPeripheralKey, int myCharacteristicKey);
|
||||
Uint8List readCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
);
|
||||
@async
|
||||
void writeCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
Uint8List value,
|
||||
int myTypeNumber,
|
||||
@ -36,14 +41,20 @@ abstract class MyCentralControllerHostApi {
|
||||
@async
|
||||
void notifyCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
bool state,
|
||||
);
|
||||
@async
|
||||
Uint8List readDescriptor(int myPeripheralKey, int myDescriptorKey);
|
||||
Uint8List readDescriptor(
|
||||
int myPeripheralKey,
|
||||
int myCharacteristicKey,
|
||||
int myDescriptorKey,
|
||||
);
|
||||
@async
|
||||
void writeDescriptor(
|
||||
int myPeripheralKey,
|
||||
int myCharacteristicKey,
|
||||
int myDescriptorKey,
|
||||
Uint8List value,
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: bluetooth_low_energy_ios
|
||||
description: iOS implementation of the bluetooth_low_energy plugin.
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
@ -10,7 +10,7 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface: ^2.0.0
|
||||
bluetooth_low_energy_platform_interface: ^2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -1,3 +1,9 @@
|
||||
## 2.0.1
|
||||
|
||||
- Fix the issue that GATTs is cleared after peripheral disconnected on iOS and macOS.
|
||||
- Fix the issue that create UUID form peripheral's address failed on Linux.
|
||||
- Fix the issue that instance match failed on Linux.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Rewrite the whole project with federated plugins.
|
||||
|
@ -13,10 +13,11 @@ extension MyBlueZDevice on BlueZDevice {
|
||||
BlueZUUID get uuid {
|
||||
final node = address.replaceAll(':', '');
|
||||
// We don't know the timestamp of the bluetooth device, use nil UUID as prefix.
|
||||
return BlueZUUID.fromString("00000000-0000-0000-$node");
|
||||
return BlueZUUID.fromString("00000000-0000-0000-0000-$node");
|
||||
}
|
||||
|
||||
Advertisement get advertisement {
|
||||
final name = this.name.isNotEmpty ? this.name : null;
|
||||
final manufacturerSpecificData = manufacturerData.map((key, value) {
|
||||
final id = key.id;
|
||||
final data = Uint8List.fromList(value);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bluetooth_low_energy_linux/src/my_event_args.dart';
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:bluez/bluez.dart';
|
||||
|
||||
@ -17,7 +18,7 @@ class MyCentralController extends CentralController {
|
||||
_discoveredController = StreamController.broadcast(),
|
||||
_peripheralStateChangedController = StreamController.broadcast(),
|
||||
_characteristicValueChangedController = StreamController.broadcast(),
|
||||
_servicesResolvedController = StreamController.broadcast(),
|
||||
_myPeripheralDiscoveredController = StreamController.broadcast(),
|
||||
_devicePropertiesChangedSubscriptions = {},
|
||||
_characteristicPropertiesChangedSubscriptions = {},
|
||||
_myPeripherals = {},
|
||||
@ -33,15 +34,16 @@ class MyCentralController extends CentralController {
|
||||
_peripheralStateChangedController;
|
||||
final StreamController<GattCharacteristicValueChangedEventArgs>
|
||||
_characteristicValueChangedController;
|
||||
final StreamController<int> _servicesResolvedController;
|
||||
final StreamController<MyPeripheralDiscoveredEventArgs>
|
||||
_myPeripheralDiscoveredController;
|
||||
final Map<int, StreamSubscription<List<String>>>
|
||||
_devicePropertiesChangedSubscriptions;
|
||||
final Map<int, StreamSubscription<List<String>>>
|
||||
_characteristicPropertiesChangedSubscriptions;
|
||||
final Map<int, MyPeripheral> _myPeripherals;
|
||||
final Map<int, MyGattService> _myServices;
|
||||
final Map<int, MyGattCharacteristic> _myCharacteristics;
|
||||
final Map<int, MyGattDescriptor> _myDescriptors;
|
||||
final Map<int, Map<int, MyGattService>> _myServices;
|
||||
final Map<int, Map<int, MyGattCharacteristic>> _myCharacteristics;
|
||||
final Map<int, Map<int, MyGattDescriptor>> _myDescriptors;
|
||||
|
||||
BlueZAdapter get _adapter => _client.adapters.first;
|
||||
CentralState _state;
|
||||
@ -61,7 +63,8 @@ class MyCentralController extends CentralController {
|
||||
Stream<GattCharacteristicValueChangedEventArgs>
|
||||
get characteristicValueChanged =>
|
||||
_characteristicValueChangedController.stream;
|
||||
Stream<int> get _servicesResolved => _servicesResolvedController.stream;
|
||||
Stream<MyPeripheralDiscoveredEventArgs> get _myPeripheralDiscovered =>
|
||||
_myPeripheralDiscoveredController.stream;
|
||||
|
||||
late StreamSubscription<List<String>> _adapterPropertiesChangedSubscription;
|
||||
late StreamSubscription<BlueZDevice> _deviceAddedSubscription;
|
||||
@ -91,7 +94,7 @@ class MyCentralController extends CentralController {
|
||||
return;
|
||||
}
|
||||
for (var device in _client.devices) {
|
||||
if (device.adapter != _adapter) {
|
||||
if (device.adapter.address != _adapter.address) {
|
||||
continue;
|
||||
}
|
||||
_beginDevicePropertiesChangedListener(device);
|
||||
@ -120,7 +123,7 @@ class MyCentralController extends CentralController {
|
||||
_myCharacteristics.clear();
|
||||
_myDescriptors.clear();
|
||||
for (var device in _client.devices) {
|
||||
if (device.adapter != _adapter) {
|
||||
if (device.adapter.address != _adapter.address) {
|
||||
continue;
|
||||
}
|
||||
_endDevicePropertiesChangedListener(device);
|
||||
@ -171,8 +174,8 @@ class MyCentralController extends CentralController {
|
||||
if (device.servicesResolved) {
|
||||
return;
|
||||
}
|
||||
await _servicesResolved.firstWhere(
|
||||
(hashCode) => hashCode == peripheral.hashCode,
|
||||
await _myPeripheralDiscovered.firstWhere(
|
||||
(eventArgs) => eventArgs.myPeripheral == myPeripheral,
|
||||
);
|
||||
}
|
||||
|
||||
@ -180,15 +183,11 @@ class MyCentralController extends CentralController {
|
||||
Future<List<GattService>> getServices(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final blueZDevice = myPeripheral.device;
|
||||
return blueZDevice.gattServices
|
||||
.map(
|
||||
(service) => _myServices.putIfAbsent(
|
||||
service.hashCode,
|
||||
() => MyGattService(service),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final myServices = _myServices[myPeripheral.hashCode];
|
||||
if (myServices == null) {
|
||||
throw ArgumentError();
|
||||
}
|
||||
return myServices.values.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -197,15 +196,11 @@ class MyCentralController extends CentralController {
|
||||
) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myService = service as MyGattService;
|
||||
final blueZService = myService.service;
|
||||
return blueZService.characteristics
|
||||
.map(
|
||||
(characteristic) => _myCharacteristics.putIfAbsent(
|
||||
characteristic.hashCode,
|
||||
() => MyGattCharacteristic(characteristic),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final myCharacteristics = _myCharacteristics[myService.hashCode];
|
||||
if (myCharacteristics == null) {
|
||||
throw ArgumentError();
|
||||
}
|
||||
return myCharacteristics.values.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -214,15 +209,11 @@ class MyCentralController extends CentralController {
|
||||
) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final blueZCharacteristic = myCharacteristic.characteristic;
|
||||
return blueZCharacteristic.descriptors
|
||||
.map(
|
||||
(descriptor) => _myDescriptors.putIfAbsent(
|
||||
descriptor.hashCode,
|
||||
() => MyGattDescriptor(descriptor),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final myDescriptors = _myDescriptors[myCharacteristic.hashCode];
|
||||
if (myDescriptors == null) {
|
||||
throw ArgumentError();
|
||||
}
|
||||
return myDescriptors.values.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -305,7 +296,7 @@ class MyCentralController extends CentralController {
|
||||
}
|
||||
|
||||
void _onDeviceAdded(BlueZDevice device) {
|
||||
if (device.adapter != _adapter) {
|
||||
if (device.adapter.address != _adapter.address) {
|
||||
return;
|
||||
}
|
||||
_onDiscovered(device);
|
||||
@ -313,17 +304,15 @@ class MyCentralController extends CentralController {
|
||||
}
|
||||
|
||||
void _onDeviceRemoved(BlueZDevice device) {
|
||||
if (device.adapter != _adapter) {
|
||||
if (device.adapter.address != _adapter.address) {
|
||||
return;
|
||||
}
|
||||
_endDevicePropertiesChangedListener(device);
|
||||
}
|
||||
|
||||
void _onDiscovered(BlueZDevice device) {
|
||||
final myPeripheral = _myPeripherals.putIfAbsent(
|
||||
device.hashCode,
|
||||
() => MyPeripheral(device),
|
||||
);
|
||||
final myPeripheral = MyPeripheral(device);
|
||||
_myPeripherals[myPeripheral.hashCode] = myPeripheral;
|
||||
final rssi = device.rssi;
|
||||
final advertisement = device.advertisement;
|
||||
final eventArgs = CentralDiscoveredEventArgs(
|
||||
@ -335,11 +324,6 @@ class MyCentralController extends CentralController {
|
||||
}
|
||||
|
||||
void _beginDevicePropertiesChangedListener(BlueZDevice device) {
|
||||
for (var service in device.gattServices) {
|
||||
for (var characteristic in service.characteristics) {
|
||||
_beginCharacteristicPropertiesChangedListener(characteristic);
|
||||
}
|
||||
}
|
||||
final subscription = device.propertiesChanged.listen((properties) {
|
||||
for (var property in properties) {
|
||||
switch (property) {
|
||||
@ -360,12 +344,33 @@ class MyCentralController extends CentralController {
|
||||
break;
|
||||
case 'ServicesResolved':
|
||||
if (device.servicesResolved) {
|
||||
final myPeripheral =
|
||||
_myPeripherals[device.hashCode] as MyPeripheral;
|
||||
final myServices = <int, MyGattService>{};
|
||||
for (var service in device.gattServices) {
|
||||
final myService = MyGattService(service);
|
||||
myServices[myService.hashCode] = myService;
|
||||
final myCharacteristics = <int, MyGattCharacteristic>{};
|
||||
for (var characteristic in service.characteristics) {
|
||||
_beginCharacteristicPropertiesChangedListener(characteristic);
|
||||
final myCharacteristic = MyGattCharacteristic(characteristic);
|
||||
myCharacteristics[myCharacteristic.hashCode] =
|
||||
myCharacteristic;
|
||||
_beginCharacteristicPropertiesChangedListener(
|
||||
service,
|
||||
characteristic,
|
||||
);
|
||||
final myDescriptors = <int, MyGattDescriptor>{};
|
||||
for (var descriptor in characteristic.descriptors) {
|
||||
final myDescriptor = MyGattDescriptor(descriptor);
|
||||
myDescriptors[myDescriptor.hashCode] = myDescriptor;
|
||||
}
|
||||
_myDescriptors[myCharacteristic.hashCode] = myDescriptors;
|
||||
}
|
||||
_myCharacteristics[myService.hashCode] = myCharacteristics;
|
||||
}
|
||||
_servicesResolvedController.add(device.hashCode);
|
||||
_myServices[myPeripheral.hashCode] = myServices;
|
||||
final eventArgs = MyPeripheralDiscoveredEventArgs(myPeripheral);
|
||||
_myPeripheralDiscoveredController.add(eventArgs);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -389,16 +394,19 @@ class MyCentralController extends CentralController {
|
||||
}
|
||||
|
||||
void _beginCharacteristicPropertiesChangedListener(
|
||||
BlueZGattService service,
|
||||
BlueZGattCharacteristic characteristic,
|
||||
) {
|
||||
final subscription = characteristic.propertiesChanged.listen((properties) {
|
||||
for (var property in properties) {
|
||||
switch (property) {
|
||||
case 'Value':
|
||||
final instance = _myCharacteristics[characteristic.hashCode];
|
||||
final myCharacteristic = instance is MyGattCharacteristic
|
||||
? instance
|
||||
: MyGattCharacteristic(characteristic);
|
||||
final myCharacteristics = _myCharacteristics[service.hashCode];
|
||||
if (myCharacteristics == null) {
|
||||
throw ArgumentError();
|
||||
}
|
||||
final myCharacteristic = myCharacteristics[characteristic.hashCode]
|
||||
as MyGattCharacteristic;
|
||||
final value = Uint8List.fromList(characteristic.value);
|
||||
final eventArgs = GattCharacteristicValueChangedEventArgs(
|
||||
myCharacteristic,
|
||||
|
9
bluetooth_low_energy_linux/lib/src/my_event_args.dart
Normal file
9
bluetooth_low_energy_linux/lib/src/my_event_args.dart
Normal file
@ -0,0 +1,9 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_peripheral.dart';
|
||||
|
||||
class MyPeripheralDiscoveredEventArgs extends EventArgs {
|
||||
final MyPeripheral myPeripheral;
|
||||
|
||||
MyPeripheralDiscoveredEventArgs(this.myPeripheral);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
name: bluetooth_low_energy_linux
|
||||
description: Linux implementation of the bluetooth_low_energy plugin.
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
@ -10,7 +10,7 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface: ^2.0.0
|
||||
bluetooth_low_energy_platform_interface: ^2.0.1
|
||||
bluez: ^0.8.1
|
||||
|
||||
dev_dependencies:
|
||||
|
@ -1,3 +1,9 @@
|
||||
## 2.0.1
|
||||
|
||||
- Fix the issue that GATTs is cleared after peripheral disconnected on iOS and macOS.
|
||||
- Fix the issue that create UUID form peripheral's address failed on Linux.
|
||||
- Fix the issue that instance match failed on Linux.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Rewrite the whole project with federated plugins.
|
||||
|
@ -483,12 +483,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey) async {
|
||||
Future<Uint8List> readCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_macos.MyCentralControllerHostApi.readCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -510,12 +510,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey, Uint8List arg_value, int arg_myTypeNumber) async {
|
||||
Future<void> writeCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey, Uint8List arg_value, int arg_myTypeNumber) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_macos.MyCentralControllerHostApi.writeCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_value, arg_myTypeNumber]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey, arg_value, arg_myTypeNumber]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -532,12 +532,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> notifyCharacteristic(int arg_myPeripheralKey, int arg_myCharacteristicKey, bool arg_state) async {
|
||||
Future<void> notifyCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey, bool arg_state) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_macos.MyCentralControllerHostApi.notifyCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_state]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey, arg_state]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -554,12 +554,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readDescriptor(int arg_myPeripheralKey, int arg_myDescriptorKey) async {
|
||||
Future<Uint8List> readDescriptor(int arg_myPeripheralKey, int arg_myCharacteristicKey, int arg_myDescriptorKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_macos.MyCentralControllerHostApi.readDescriptor', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myDescriptorKey]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_myDescriptorKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -581,12 +581,12 @@ class MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeDescriptor(int arg_myPeripheralKey, int arg_myDescriptorKey, Uint8List arg_value) async {
|
||||
Future<void> writeDescriptor(int arg_myPeripheralKey, int arg_myCharacteristicKey, int arg_myDescriptorKey, Uint8List arg_value) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_macos.MyCentralControllerHostApi.writeDescriptor', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myDescriptorKey, arg_value]) as List<Object?>?;
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_myDescriptorKey, arg_value]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
|
@ -126,18 +126,16 @@ class MyCentralController extends CentralController
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final myServiceArgses = await _myApi.getServices(myPeripheral.hashCode);
|
||||
return myServiceArgses
|
||||
.cast<MyGattServiceArgs>()
|
||||
.map(
|
||||
(myServiceArgs) => _myServices.putIfAbsent(
|
||||
myServiceArgs.key,
|
||||
() => MyGattService.fromMyArgs(
|
||||
myPeripheral,
|
||||
myServiceArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myServiceArgses.cast<MyGattServiceArgs>().map(
|
||||
(myServiceArgs) {
|
||||
final myService = MyGattService.fromMyArgs(
|
||||
myPeripheral,
|
||||
myServiceArgs,
|
||||
);
|
||||
_myServices[myService.hashCode] = myService;
|
||||
return myService;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -149,18 +147,16 @@ class MyCentralController extends CentralController
|
||||
final myCharactersiticArgses = await _myApi.getCharacteristics(
|
||||
myService.hashCode,
|
||||
);
|
||||
return myCharactersiticArgses
|
||||
.cast<MyGattCharacteristicArgs>()
|
||||
.map(
|
||||
(myCharacteristicArgs) => _myCharacteristics.putIfAbsent(
|
||||
myCharacteristicArgs.key,
|
||||
() => MyGattCharacteristic.fromMyArgs(
|
||||
myService,
|
||||
myCharacteristicArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myCharactersiticArgses.cast<MyGattCharacteristicArgs>().map(
|
||||
(myCharacteristicArgs) {
|
||||
final myCharacteristic = MyGattCharacteristic.fromMyArgs(
|
||||
myService,
|
||||
myCharacteristicArgs,
|
||||
);
|
||||
_myCharacteristics[myCharacteristic.hashCode] = myCharacteristic;
|
||||
return myCharacteristic;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -172,18 +168,16 @@ class MyCentralController extends CentralController
|
||||
final myDescriptorArgses = await _myApi.getDescriptors(
|
||||
myCharacteristic.hashCode,
|
||||
);
|
||||
return myDescriptorArgses
|
||||
.cast<MyGattDescriptorArgs>()
|
||||
.map(
|
||||
(myDescriptorArgs) => _myDescriptors.putIfAbsent(
|
||||
myDescriptorArgs.key,
|
||||
() => MyGattDescriptor.fromMyArgs(
|
||||
myCharacteristic,
|
||||
myDescriptorArgs,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return myDescriptorArgses.cast<MyGattDescriptorArgs>().map(
|
||||
(myDescriptorArgs) {
|
||||
final myDescriptor = MyGattDescriptor.fromMyArgs(
|
||||
myCharacteristic,
|
||||
myDescriptorArgs,
|
||||
);
|
||||
_myDescriptors[myDescriptor.hashCode] = myDescriptor;
|
||||
return myDescriptor;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -196,6 +190,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final value = await _myApi.readCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
);
|
||||
return value;
|
||||
@ -215,6 +210,7 @@ class MyCentralController extends CentralController
|
||||
final typeNumber = typeArgs.index;
|
||||
await _myApi.writeCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
value,
|
||||
typeNumber,
|
||||
@ -232,6 +228,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
await _myApi.notifyCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
state,
|
||||
);
|
||||
@ -246,6 +243,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final value = await _myApi.readDescriptor(
|
||||
myPeripheral.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
myDescriptor.hashCode,
|
||||
);
|
||||
return value;
|
||||
@ -263,6 +261,7 @@ class MyCentralController extends CentralController
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
await _myApi.writeDescriptor(
|
||||
myPeripheral.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
myDescriptor.hashCode,
|
||||
value,
|
||||
);
|
||||
@ -286,10 +285,8 @@ class MyCentralController extends CentralController
|
||||
int rssi,
|
||||
MyAdvertisementArgs myAdvertisementArgs,
|
||||
) {
|
||||
final myPeripheral = _myPeripherals.putIfAbsent(
|
||||
myPeripheralArgs.key,
|
||||
() => MyPeripheral.fromMyArgs(myPeripheralArgs),
|
||||
);
|
||||
final myPeripheral = MyPeripheral.fromMyArgs(myPeripheralArgs);
|
||||
_myPeripherals[myPeripheral.hashCode] = myPeripheral;
|
||||
final advertisement = myAdvertisementArgs.toAdvertisement();
|
||||
final eventArgs = CentralDiscoveredEventArgs(
|
||||
myPeripheral,
|
||||
|
@ -258,11 +258,11 @@ protocol MyCentralControllerHostApi {
|
||||
func getServices(myPeripheralKey: Int64) throws -> [MyGattServiceArgs]
|
||||
func getCharacteristics(myServiceKey: Int64) throws -> [MyGattCharacteristicArgs]
|
||||
func getDescriptors(myCharacteristicKey: Int64) throws -> [MyGattDescriptorArgs]
|
||||
func readCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readDescriptor(myPeripheralKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeDescriptor(myPeripheralKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@ -426,8 +426,9 @@ class MyCentralControllerHostApiSetup {
|
||||
readCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.readCharacteristic(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg) { result in
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
api.readCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -444,10 +445,11 @@ class MyCentralControllerHostApiSetup {
|
||||
writeCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let valueArg = args[2] as! FlutterStandardTypedData
|
||||
let myTypeNumberArg = args[3] is Int64 ? args[3] as! Int64 : Int64(args[3] as! Int32)
|
||||
api.writeCharacteristic(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, value: valueArg, myTypeNumber: myTypeNumberArg) { result in
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let valueArg = args[3] as! FlutterStandardTypedData
|
||||
let myTypeNumberArg = args[4] is Int64 ? args[4] as! Int64 : Int64(args[4] as! Int32)
|
||||
api.writeCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg, value: valueArg, myTypeNumber: myTypeNumberArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -464,9 +466,10 @@ class MyCentralControllerHostApiSetup {
|
||||
notifyCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let stateArg = args[2] as! Bool
|
||||
api.notifyCharacteristic(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, state: stateArg) { result in
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let stateArg = args[3] as! Bool
|
||||
api.notifyCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg, state: stateArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -483,8 +486,9 @@ class MyCentralControllerHostApiSetup {
|
||||
readDescriptorChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myDescriptorKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.readDescriptor(myPeripheralKey: myPeripheralKeyArg, myDescriptorKey: myDescriptorKeyArg) { result in
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myDescriptorKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
api.readDescriptor(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, myDescriptorKey: myDescriptorKeyArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -501,9 +505,10 @@ class MyCentralControllerHostApiSetup {
|
||||
writeDescriptorChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myDescriptorKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let valueArg = args[2] as! FlutterStandardTypedData
|
||||
api.writeDescriptor(myPeripheralKey: myPeripheralKeyArg, myDescriptorKey: myDescriptorKeyArg, value: valueArg) { result in
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myDescriptorKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let valueArg = args[3] as! FlutterStandardTypedData
|
||||
api.writeDescriptor(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, myDescriptorKey: myDescriptorKeyArg, value: valueArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
|
@ -19,10 +19,10 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
private lazy var myPeripheralDelegate = MyPeripheralDelegate(self)
|
||||
private let centralManager = CBCentralManager()
|
||||
|
||||
private var peripherals = [Int: CBPeripheral]()
|
||||
private var services = [Int: CBService]()
|
||||
private var characteristics = [Int: CBCharacteristic]()
|
||||
private var descriptors = [Int: CBDescriptor]()
|
||||
private var cachedPeripherals = [Int: CBPeripheral]()
|
||||
private var cachedServices = [Int: [Int: CBService]]()
|
||||
private var cachedCharacteristics = [Int: [Int: CBCharacteristic]]()
|
||||
private var cachedDescriptors = [Int: [Int: CBDescriptor]]()
|
||||
|
||||
var setUpCompletion: ((Result<MyCentralControllerArgs, Error>) -> Void)?
|
||||
var connectCompletions = [Int: (Result<Void, Error>) -> Void]()
|
||||
@ -61,16 +61,16 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
if(centralManager.isScanning) {
|
||||
centralManager.stopScan()
|
||||
}
|
||||
for peripheral in peripherals.values {
|
||||
for peripheral in cachedPeripherals.values {
|
||||
peripheral.delegate = nil
|
||||
if peripheral.state != .disconnected {
|
||||
centralManager.cancelPeripheralConnection(peripheral)
|
||||
}
|
||||
}
|
||||
peripherals.removeAll()
|
||||
services.removeAll()
|
||||
characteristics.removeAll()
|
||||
descriptors.removeAll()
|
||||
cachedPeripherals.removeAll()
|
||||
cachedServices.removeAll()
|
||||
cachedCharacteristics.removeAll()
|
||||
cachedDescriptors.removeAll()
|
||||
}
|
||||
|
||||
func startDiscovery() throws {
|
||||
@ -89,7 +89,7 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
centralManager.connect(peripheral)
|
||||
@ -106,7 +106,7 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
centralManager.cancelPeripheralConnection(peripheral)
|
||||
@ -123,7 +123,7 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.discoverServices(nil)
|
||||
@ -135,53 +135,42 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
|
||||
func getServices(myPeripheralKey: Int64) throws -> [MyGattServiceArgs] {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let services = cachedServices[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let services = peripheral.services ?? []
|
||||
return services.map { service in
|
||||
let serviceKey = service.hash
|
||||
if self.services[serviceKey] == nil {
|
||||
self.services[serviceKey] = service
|
||||
}
|
||||
return services.map { (key, service) in
|
||||
return service.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func getCharacteristics(myServiceKey: Int64) throws -> [MyGattCharacteristicArgs] {
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let service = services[serviceKey] else {
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristics = service.characteristics ?? []
|
||||
return characteristics.map { characteristic in
|
||||
let characteristicKey = characteristic.hash
|
||||
if self.characteristics[characteristicKey] == nil {
|
||||
self.characteristics[characteristicKey] = characteristic
|
||||
}
|
||||
return characteristics.map { (key, characteristic) in
|
||||
return characteristic.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func getDescriptors(myCharacteristicKey: Int64) throws -> [MyGattDescriptorArgs] {
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let characteristic = characteristics[characteristicKey] else {
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let descritors = characteristic.descriptors ?? []
|
||||
return descritors.map { descriptor in
|
||||
let descriptorKey = descriptor.hash
|
||||
if self.descriptors[descriptorKey] == nil {
|
||||
self.descriptors[descriptorKey] = descriptor
|
||||
}
|
||||
return descriptors.map { (key, descriptor) in
|
||||
return descriptor.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func readCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
func readCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
@ -199,10 +188,14 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
@ -226,10 +219,14 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
@ -247,10 +244,14 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func readDescriptor(myPeripheralKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
func readDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let descriptorKey = Int(myDescriptorKey)
|
||||
@ -268,10 +269,14 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func writeDescriptor(myPeripheralKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func writeDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = peripherals[peripheralKey] else {
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let descriptorKey = Int(myDescriptorKey)
|
||||
@ -307,9 +312,9 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
|
||||
func didDiscover(_ peripheral: CBPeripheral, _ advertisementData: [String : Any], _ rssiNumber: NSNumber) {
|
||||
let peripheralKey = peripheral.hash
|
||||
if peripherals[peripheralKey] == nil {
|
||||
if cachedPeripherals[peripheralKey] == nil {
|
||||
peripheral.delegate = myPeripheralDelegate
|
||||
peripherals[peripheralKey] = peripheral
|
||||
cachedPeripherals[peripheralKey] = peripheral
|
||||
}
|
||||
let myPeripheralArgs = peripheral.toMyArgs()
|
||||
let rssi = rssiNumber.int64Value
|
||||
@ -368,26 +373,24 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
let myPeripheralKey = Int64(peripheralKey)
|
||||
let discoverGattCompletion = discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
if discoverGattCompletion != nil {
|
||||
discoverGattCompletion!(.failure(error ?? MyError.illegalState))
|
||||
didDiscoverGATT(peripheral, error ?? MyError.unknown)
|
||||
}
|
||||
let services = peripheral.services ?? []
|
||||
let services = cachedServices[peripheralKey] ?? [:]
|
||||
for service in services {
|
||||
let characteristics = service.characteristics ?? []
|
||||
let characteristics = cachedCharacteristics[service.key] ?? [:]
|
||||
for characteristic in characteristics {
|
||||
let characteristicKey = characteristic.hash
|
||||
let readCharacteristicCompletion = readCharacteristicCompletions.removeValue(forKey: characteristicKey)
|
||||
let writeCharacteristicCompletion = writeCharacteristicCompletions.removeValue(forKey: characteristicKey)
|
||||
let readCharacteristicCompletion = readCharacteristicCompletions.removeValue(forKey: characteristic.key)
|
||||
let writeCharacteristicCompletion = writeCharacteristicCompletions.removeValue(forKey: characteristic.key)
|
||||
if readCharacteristicCompletion != nil {
|
||||
readCharacteristicCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
if writeCharacteristicCompletion != nil {
|
||||
writeCharacteristicCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
let descriptors = characteristic.descriptors ?? []
|
||||
let descriptors = cachedDescriptors[characteristic.key] ?? [:]
|
||||
for descriptor in descriptors {
|
||||
let descriptorKey = descriptor.hash
|
||||
let readDescriptorCompletion = readDescriptorCompletions.removeValue(forKey: descriptorKey)
|
||||
let writeDescriptorCompletion = writeDescriptorCompletions.removeValue(forKey: descriptorKey)
|
||||
let readDescriptorCompletion = readDescriptorCompletions.removeValue(forKey: descriptor.key)
|
||||
let writeDescriptorCompletion = writeDescriptorCompletions.removeValue(forKey: descriptor.key)
|
||||
if readDescriptorCompletion != nil {
|
||||
readDescriptorCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
@ -411,37 +414,28 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
|
||||
func didDiscoverServices(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
guard let completion = discoverGattCompletions[peripheralKey] else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
var services = peripheral.services ?? []
|
||||
if services.isEmpty {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
completion(.success(()))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
peripheral.discoverCharacteristics(nil, for: service)
|
||||
}
|
||||
} else {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
completion(.failure(error!))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
func didDiscoverCharacteristics(_ peripheral: CBPeripheral, _ service: CBService, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
guard let completion = discoverGattCompletions[peripheralKey] else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
var characteristics = service.characteristics ?? []
|
||||
if characteristics.isEmpty {
|
||||
var services = unfinishedServices.removeValue(forKey: peripheralKey) ?? []
|
||||
if services.isEmpty {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
completion(.success(()))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
@ -453,24 +447,18 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
peripheral.discoverDescriptors(for: characteristic)
|
||||
}
|
||||
} else {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
unfinishedServices.removeValue(forKey: peripheralKey)
|
||||
completion(.failure(error!))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
func didDiscoverDescriptors(_ peripheral: CBPeripheral, _ characteristic: CBCharacteristic, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
guard let completion = discoverGattCompletions[peripheralKey] else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
var characteristics = unfinishedCharacteristics.removeValue(forKey: peripheralKey) ?? []
|
||||
if (characteristics.isEmpty) {
|
||||
var services = unfinishedServices.removeValue(forKey: peripheralKey) ?? []
|
||||
if services.isEmpty {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
completion(.success(()))
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
@ -482,9 +470,41 @@ class MyCentralController: MyCentralControllerHostApi {
|
||||
peripheral.discoverDescriptors(for: characteristic)
|
||||
}
|
||||
} else {
|
||||
discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
unfinishedServices.removeValue(forKey: peripheralKey)
|
||||
unfinishedCharacteristics.removeValue(forKey: peripheralKey)
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
private func didDiscoverGATT(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
unfinishedServices.removeValue(forKey: peripheralKey)
|
||||
unfinishedCharacteristics.removeValue(forKey: peripheralKey)
|
||||
guard let completion = discoverGattCompletions.removeValue(forKey: peripheralKey) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
let services = peripheral.services ?? []
|
||||
var cachedServices = [Int: CBService]()
|
||||
for service in services {
|
||||
let serviceKey = service.hash
|
||||
cachedServices[serviceKey] = service
|
||||
let characteristics = service.characteristics ?? []
|
||||
var cachedCharacteristics = [Int: CBCharacteristic]()
|
||||
for characteristic in characteristics {
|
||||
let characteristicKey = characteristic.hash
|
||||
cachedCharacteristics[characteristicKey] = characteristic
|
||||
let descriptors = characteristic.descriptors ?? []
|
||||
var cachedDescriptors = [Int: CBDescriptor]()
|
||||
for descriptor in descriptors {
|
||||
let descriptorKey = descriptor.hash
|
||||
cachedDescriptors[descriptorKey] = descriptor
|
||||
}
|
||||
self.cachedDescriptors[characteristicKey] = cachedDescriptors
|
||||
}
|
||||
self.cachedCharacteristics[serviceKey] = cachedCharacteristics
|
||||
}
|
||||
self.cachedServices[peripheralKey] = cachedServices
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint bluetooth_low_energy_macos.podspec` to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'bluetooth_low_energy_macos'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'A new Flutter plugin project.'
|
||||
s.description = <<-DESC
|
||||
A new Flutter plugin project.
|
||||
DESC
|
||||
s.homepage = 'http://example.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Your Company' => 'email@example.com' }
|
||||
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.dependency 'FlutterMacOS'
|
||||
|
||||
s.platform = :osx, '10.11'
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
||||
s.swift_version = '5.0'
|
||||
end
|
@ -25,10 +25,15 @@ abstract class MyCentralControllerHostApi {
|
||||
List<MyGattCharacteristicArgs> getCharacteristics(int myServiceKey);
|
||||
List<MyGattDescriptorArgs> getDescriptors(int myCharacteristicKey);
|
||||
@async
|
||||
Uint8List readCharacteristic(int myPeripheralKey, int myCharacteristicKey);
|
||||
Uint8List readCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
);
|
||||
@async
|
||||
void writeCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
Uint8List value,
|
||||
int myTypeNumber,
|
||||
@ -36,14 +41,20 @@ abstract class MyCentralControllerHostApi {
|
||||
@async
|
||||
void notifyCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
bool state,
|
||||
);
|
||||
@async
|
||||
Uint8List readDescriptor(int myPeripheralKey, int myDescriptorKey);
|
||||
Uint8List readDescriptor(
|
||||
int myPeripheralKey,
|
||||
int myCharacteristicKey,
|
||||
int myDescriptorKey,
|
||||
);
|
||||
@async
|
||||
void writeDescriptor(
|
||||
int myPeripheralKey,
|
||||
int myCharacteristicKey,
|
||||
int myDescriptorKey,
|
||||
Uint8List value,
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: bluetooth_low_energy_macos
|
||||
description: macOS implementation of the bluetooth_low_energy plugin.
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
@ -10,7 +10,7 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface: ^2.0.0
|
||||
bluetooth_low_energy_platform_interface: ^2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -1,3 +1,9 @@
|
||||
## 2.0.1
|
||||
|
||||
- Fix the issue that GATTs is cleared after peripheral disconnected on iOS and macOS.
|
||||
- Fix the issue that create UUID form peripheral's address failed on Linux.
|
||||
- Fix the issue that instance match failed on Linux.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Rewrite the whole project with federated plugins.
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: bluetooth_low_energy_platform_interface
|
||||
description: A common platform interface for the bluetooth_low_energy plugin.
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
|
@ -1,3 +1,9 @@
|
||||
## 2.0.1
|
||||
|
||||
- Fix the issue that GATTs is cleared after peripheral disconnected on iOS and macOS.
|
||||
- Fix the issue that create UUID form peripheral's address failed on Linux.
|
||||
- Fix the issue that instance match failed on Linux.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Rewrite the whole project with federated plugins.
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: bluetooth_low_energy_windows
|
||||
description: Windows implementation of the bluetooth_low_energy plugin.
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
@ -10,7 +10,7 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface: ^2.0.0
|
||||
bluetooth_low_energy_platform_interface: ^2.0.1
|
||||
win32: ^5.0.6
|
||||
|
||||
dev_dependencies:
|
||||
@ -23,5 +23,5 @@ flutter:
|
||||
implements: bluetooth_low_energy
|
||||
platforms:
|
||||
windows:
|
||||
pluginClass: BluetoothLowEnergyWindowsPluginCApi
|
||||
pluginClass: BluetoothLowEnergyPluginCApi
|
||||
dartPluginClass: BluetoothLowEnergyWindows
|
||||
|
@ -5,24 +5,24 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
# Project-level configuration.
|
||||
set(PROJECT_NAME "bluetooth_low_energy_windows")
|
||||
set(PROJECT_NAME "bluetooth_low_energy")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
|
||||
# This value is used when generating builds using this plugin, so it must
|
||||
# not be changed
|
||||
set(PLUGIN_NAME "bluetooth_low_energy_windows_plugin")
|
||||
set(PLUGIN_NAME "bluetooth_low_energy_plugin")
|
||||
|
||||
# Any new source files that you add to the plugin should be added here.
|
||||
list(APPEND PLUGIN_SOURCES
|
||||
"bluetooth_low_energy_windows_plugin.cpp"
|
||||
"bluetooth_low_energy_windows_plugin.h"
|
||||
"bluetooth_low_energy_plugin.cpp"
|
||||
"bluetooth_low_energy_plugin.h"
|
||||
)
|
||||
|
||||
# Define the plugin library target. Its name must not be changed (see comment
|
||||
# on PLUGIN_NAME above).
|
||||
add_library(${PLUGIN_NAME} SHARED
|
||||
"include/bluetooth_low_energy_windows/bluetooth_low_energy_windows_plugin_c_api.h"
|
||||
"bluetooth_low_energy_windows_plugin_c_api.cpp"
|
||||
"include/bluetooth_low_energy/bluetooth_low_energy_plugin_c_api.h"
|
||||
"bluetooth_low_energy_plugin_c_api.cpp"
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
|
||||
@ -47,7 +47,50 @@ target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
|
||||
# List of absolute paths to libraries that should be bundled with the plugin.
|
||||
# This list could contain prebuilt libraries, or libraries created by an
|
||||
# external build triggered from this build file.
|
||||
set(bluetooth_low_energy_windows_bundled_libraries
|
||||
set(bluetooth_low_energy_bundled_libraries
|
||||
""
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
# === Tests ===
|
||||
# These unit tests can be run from a terminal after building the example, or
|
||||
# from Visual Studio after opening the generated solution file.
|
||||
|
||||
# Only enable test builds when building the example (which sets this variable)
|
||||
# so that plugin clients aren't building the tests.
|
||||
if (${include_${PROJECT_NAME}_tests})
|
||||
set(TEST_RUNNER "${PROJECT_NAME}_test")
|
||||
enable_testing()
|
||||
|
||||
# Add the Google Test dependency.
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
||||
)
|
||||
# Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
# Disable install commands for gtest so it doesn't end up in the bundle.
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# The plugin's C API is not very useful for unit testing, so build the sources
|
||||
# directly into the test binary rather than using the DLL.
|
||||
add_executable(${TEST_RUNNER}
|
||||
test/bluetooth_low_energy_plugin_test.cpp
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
apply_standard_settings(${TEST_RUNNER})
|
||||
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin)
|
||||
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
|
||||
# flutter_wrapper_plugin has link dependencies on the Flutter DLL.
|
||||
add_custom_command(TARGET ${TEST_RUNNER} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${FLUTTER_LIBRARY}" $<TARGET_FILE_DIR:${TEST_RUNNER}>
|
||||
)
|
||||
|
||||
# Enable automatic test discovery.
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(${TEST_RUNNER})
|
||||
endif()
|
||||
|
@ -1,59 +0,0 @@
|
||||
#include "bluetooth_low_energy_windows_plugin.h"
|
||||
|
||||
// This must be included before many other Windows headers.
|
||||
#include <windows.h>
|
||||
|
||||
// For getPlatformVersion; remove unless needed for your plugin implementation.
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#include <flutter/method_channel.h>
|
||||
#include <flutter/plugin_registrar_windows.h>
|
||||
#include <flutter/standard_method_codec.h>
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace bluetooth_low_energy_windows {
|
||||
|
||||
// static
|
||||
void BluetoothLowEnergyWindowsPlugin::RegisterWithRegistrar(
|
||||
flutter::PluginRegistrarWindows *registrar) {
|
||||
auto channel =
|
||||
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
|
||||
registrar->messenger(), "bluetooth_low_energy_windows",
|
||||
&flutter::StandardMethodCodec::GetInstance());
|
||||
|
||||
auto plugin = std::make_unique<BluetoothLowEnergyWindowsPlugin>();
|
||||
|
||||
channel->SetMethodCallHandler(
|
||||
[plugin_pointer = plugin.get()](const auto &call, auto result) {
|
||||
plugin_pointer->HandleMethodCall(call, std::move(result));
|
||||
});
|
||||
|
||||
registrar->AddPlugin(std::move(plugin));
|
||||
}
|
||||
|
||||
BluetoothLowEnergyWindowsPlugin::BluetoothLowEnergyWindowsPlugin() {}
|
||||
|
||||
BluetoothLowEnergyWindowsPlugin::~BluetoothLowEnergyWindowsPlugin() {}
|
||||
|
||||
void BluetoothLowEnergyWindowsPlugin::HandleMethodCall(
|
||||
const flutter::MethodCall<flutter::EncodableValue> &method_call,
|
||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
|
||||
if (method_call.method_name().compare("getPlatformVersion") == 0) {
|
||||
std::ostringstream version_stream;
|
||||
version_stream << "Windows ";
|
||||
if (IsWindows10OrGreater()) {
|
||||
version_stream << "10+";
|
||||
} else if (IsWindows8OrGreater()) {
|
||||
version_stream << "8";
|
||||
} else if (IsWindows7OrGreater()) {
|
||||
version_stream << "7";
|
||||
}
|
||||
result->Success(flutter::EncodableValue(version_stream.str()));
|
||||
} else {
|
||||
result->NotImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bluetooth_low_energy_windows
|
@ -1,32 +0,0 @@
|
||||
#ifndef FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_WINDOWS_PLUGIN_H_
|
||||
#define FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_WINDOWS_PLUGIN_H_
|
||||
|
||||
#include <flutter/method_channel.h>
|
||||
#include <flutter/plugin_registrar_windows.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace bluetooth_low_energy_windows {
|
||||
|
||||
class BluetoothLowEnergyWindowsPlugin : public flutter::Plugin {
|
||||
public:
|
||||
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar);
|
||||
|
||||
BluetoothLowEnergyWindowsPlugin();
|
||||
|
||||
virtual ~BluetoothLowEnergyWindowsPlugin();
|
||||
|
||||
// Disallow copy and assign.
|
||||
BluetoothLowEnergyWindowsPlugin(const BluetoothLowEnergyWindowsPlugin&) = delete;
|
||||
BluetoothLowEnergyWindowsPlugin& operator=(const BluetoothLowEnergyWindowsPlugin&) = delete;
|
||||
|
||||
private:
|
||||
// Called when a method is called on this plugin's channel from Dart.
|
||||
void HandleMethodCall(
|
||||
const flutter::MethodCall<flutter::EncodableValue> &method_call,
|
||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
|
||||
};
|
||||
|
||||
} // namespace bluetooth_low_energy_windows
|
||||
|
||||
#endif // FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_WINDOWS_PLUGIN_H_
|
@ -1,12 +0,0 @@
|
||||
#include "include/bluetooth_low_energy_windows/bluetooth_low_energy_windows_plugin_c_api.h"
|
||||
|
||||
#include <flutter/plugin_registrar_windows.h>
|
||||
|
||||
#include "bluetooth_low_energy_windows_plugin.h"
|
||||
|
||||
void BluetoothLowEnergyWindowsPluginCApiRegisterWithRegistrar(
|
||||
FlutterDesktopPluginRegistrarRef registrar) {
|
||||
bluetooth_low_energy_windows::BluetoothLowEnergyWindowsPlugin::RegisterWithRegistrar(
|
||||
flutter::PluginRegistrarManager::GetInstance()
|
||||
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
#ifndef FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_WINDOWS_PLUGIN_C_API_H_
|
||||
#define FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_WINDOWS_PLUGIN_C_API_H_
|
||||
|
||||
#include <flutter_plugin_registrar.h>
|
||||
|
||||
#ifdef FLUTTER_PLUGIN_IMPL
|
||||
#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void BluetoothLowEnergyWindowsPluginCApiRegisterWithRegistrar(
|
||||
FlutterDesktopPluginRegistrarRef registrar);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // FLUTTER_PLUGIN_BLUETOOTH_LOW_ENERGY_WINDOWS_PLUGIN_C_API_H_
|
Reference in New Issue
Block a user