### Install Application Executable Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Installs the main application executable to the specified runtime destination. This makes the executable available after the installation step. ```cmake install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) ``` -------------------------------- ### Installation Bundle Configuration Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Configures the installation prefix to create a relocatable bundle in the build directory. Cleans the bundle directory before installation. ```cmake set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() install(CODE " file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") " COMPONENT Runtime) ``` -------------------------------- ### Install Bundled Plugin Libraries Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Installs any bundled plugin libraries to the bundle directory. This ensures that all necessary plugin code is available at runtime. ```cmake if(PLUGIN_BUNDLED_LIBRARIES) install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Set Installation Directory for Runtime Components Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Configures the installation prefix to be next to the executable for runtime components. This allows the application to run directly from the build directory. ```cmake set(BUILD_BUNDLE_DIR "$") set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") ``` -------------------------------- ### Installing Application Components Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Installs the application executable, ICU data, Flutter library, and bundled plugin libraries into the specified bundle directories. ```cmake set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) install(FILES "${bundled_library}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endforeach(bundled_library) ``` -------------------------------- ### Install dependencies Source: https://github.com/navideck/universal_ble/blob/main/CONTRIBUTING.md Run this command from the repository root to fetch project dependencies. ```sh flutter pub get ``` -------------------------------- ### Install Flutter Library Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Installs the main Flutter library file to the root of the bundle directory. This is a core component required for the Flutter engine. ```cmake install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Install Flutter Assets with CMake Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Installs Flutter assets by first removing any existing directory and then copying the new assets. This is useful for ensuring a clean installation of application assets. ```cmake set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install( CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Configure Advertising Source: https://github.com/navideck/universal_ble/blob/main/README.md Start advertising the peripheral with specific services and manufacturer data. Note that Windows has specific limitations regarding local names and manufacturer data. ```dart import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:universal_ble/universal_ble.dart'; // Uses batteryService from Service Management above. final isWindows = !kIsWeb && defaultTargetPlatform == TargetPlatform.windows; final caps = await UniversalBlePeripheral.getCapabilities(); await UniversalBlePeripheral.startAdvertising( services: [batteryService], localName: isWindows ? null : 'UniversalBlePeripheral', manufacturerData: isWindows || !caps.supportsManufacturerDataInAdvertisement ? null : ManufacturerData( 0x012d, Uint8List.fromList([0x03, 0x00, 0x64, 0x00]), ), platformConfig: PeripheralPlatformConfig( android: PeripheralAndroidOptions( addManufacturerDataInScanResponse: false, ), ), ); final advertisingState = await UniversalBlePeripheral.getAdvertisingState(); if (advertisingState == PeripheralAdvertisingState.advertising) { // Peripheral is advertising. } await UniversalBlePeripheral.stopAdvertising(); ``` -------------------------------- ### Initialize Peripheral Mode Source: https://github.com/navideck/universal_ble/blob/main/README.md Check device capabilities and readiness before starting peripheral operations. ```dart import 'package:universal_ble/universal_ble.dart'; final caps = await UniversalBlePeripheral.getCapabilities(); if (!caps.supportsPeripheralMode) return; final readiness = await UniversalBlePeripheral.getAvailabilityState(); if (readiness != PeripheralReadinessState.ready) return; ``` -------------------------------- ### Install Flutter Assets Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Installs the Flutter assets directory, ensuring that all application assets (images, fonts, etc.) are copied to the correct location. The assets directory is removed and re-copied on each build to prevent stale files. ```cmake set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Install AOT Library for Release/Profile Builds Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Installs the Ahead-Of-Time (AOT) compiled library only for Profile and Release configurations. This optimizes performance for non-debug builds. ```cmake install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" CONFIGURATIONS Profile;Release COMPONENT Runtime) ``` -------------------------------- ### Install ICU Data File Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Installs the ICU data file to the data directory within the bundle. This file is necessary for internationalization support. ```cmake install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Retrieve System Devices Source: https://github.com/navideck/universal_ble/blob/main/README.md Get devices already connected to the system. ```dart // Get already connected devices. // You can set `withServices` to narrow down the results. // On `Apple`, `withServices` is required to get any connected devices. If not passed, several [18XX] generic services will be set by default. List devices = await UniversalBle.getSystemDevices(withServices: []); ``` -------------------------------- ### Define Scan Filters Source: https://github.com/navideck/universal_ble/blob/main/README.md Examples of various scan filter configurations. ```dart List withServices; ``` ```dart List withManufacturerData = [ManufacturerDataFilter( companyIdentifier: 0x004c, payloadPrefix: Uint8List.fromList([0x001D,0x001A]), payloadMask: Uint8List.fromList([1,0,1,1])) ]; ``` ```dart List withNamePrefix; ``` ```dart exclusionFilters: [ ExclusionFilter( namePrefix: 'EXCLUDED_NAME', services: ['EXCLUDED_SERVICE_UUID'], manufacturerDataFilter: [ManufacturerDataFilter(companyIdentifier: 0x004c)], ), ] ``` -------------------------------- ### Set Minimum CMake Version and Project Name Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Specifies the minimum required CMake version and names the project. This is a standard starting point for any CMake project. ```cmake cmake_minimum_required(VERSION 3.14) project(universal_ble_example LANGUAGES CXX) ``` -------------------------------- ### Conditional AOT Library Installation with CMake Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Installs the AOT (Ahead-Of-Time) library only for non-Debug build types. This ensures that performance-critical libraries are included in release builds but not in debug builds. ```cmake if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Handle Pairing State Changes Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Get updates on pairing state changes for a specific device or all devices via a stream or a callback. ```dart // Get pairing state updates using stream UniversalBle.pairingStateStream(deviceId).listen((bool paired) { // Handle pairing state change }); // Or set a handler to get pairing state updates of all devices UniversalBle.onPairingStateChange = (String deviceId, bool paired) {} ``` -------------------------------- ### Get Connection State Source: https://github.com/navideck/universal_ble/blob/main/README.md Retrieves the detailed connection state, which can be connected, disconnected, connecting, or disconnecting. ```dart // Can be connected, disconnected, connecting or disconnecting BleConnectionState connectionState = await bleDevice.connectionState; ``` -------------------------------- ### UniversalBle.startScan Source: https://github.com/navideck/universal_ble/blob/main/README.md Initiates a BLE scan. Permissions are automatically requested unless configured otherwise via platform-specific options. ```APIDOC ## UniversalBle.startScan ### Description Starts scanning for BLE devices. Permissions are requested automatically by default. ### Parameters - **platformConfig** (PlatformConfig) - Optional - Configuration object for platform-specific settings, such as AndroidOptions. ``` -------------------------------- ### Declare Linux Snap Plug Source: https://github.com/navideck/universal_ble/blob/main/README.md Include the bluez plug in your snapcraft.yaml file for Linux applications. ```yaml ... plugs: - bluez ``` -------------------------------- ### UniversalBle.setInstance Source: https://github.com/navideck/universal_ble/blob/main/README.md Overrides the default platform implementation with a custom implementation. ```APIDOC ## UniversalBle.setInstance ### Description Sets a custom implementation for the Universal BLE platform by providing an instance that extends UniversalBlePlatform. ### Parameters - **instance** (UniversalBlePlatform) - Required - The custom implementation instance. ``` -------------------------------- ### Apply Standard Build Settings Source: https://github.com/navideck/universal_ble/blob/main/example/windows/runner/CMakeLists.txt Applies a predefined set of standard build settings to the specified target. This can be removed if the application requires custom build configurations. ```cmake apply_standard_settings(${BINARY_NAME}) ``` -------------------------------- ### Find and check GTK, GLIB, and GIO modules Source: https://github.com/navideck/universal_ble/blob/main/example/linux/flutter/CMakeLists.txt Uses PkgConfig to find and check for the required GTK, GLIB, and GIO development libraries. This ensures that the necessary system dependencies are available for the Flutter application. ```cmake find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) ``` -------------------------------- ### Runtime Output Directory Configuration Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Configures the runtime output directory for the executable to a subdirectory within the build directory to ensure correct resource loading. ```cmake set_target_properties(${BINARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) ``` -------------------------------- ### bleDevice.discoverServices() Source: https://github.com/navideck/universal_ble/blob/main/README.md Discovers all services offered by the device and updates the internal cache. ```APIDOC ## Future> discoverServices() ### Description Discovers the services offered by the device. Returns a list of available services. ### Example ```dart List services = await bleDevice.discoverServices(); ``` ``` -------------------------------- ### Import Package Source: https://github.com/navideck/universal_ble/blob/main/README.md Import the library in your Dart files. ```dart import 'dart:typed_data'; import 'package:universal_ble/universal_ble.dart'; ``` -------------------------------- ### Set Flutter Build Variables Source: https://github.com/navideck/universal_ble/blob/main/example/windows/flutter/CMakeLists.txt Sets essential variables like FLUTTER_LIBRARY, FLUTTER_ICU_DATA_FILE, PROJECT_BUILD_DIR, and AOT_LIBRARY, which are crucial for the Flutter build process. These are published to the parent scope for use in the install step. ```cmake set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") # Configuration provided via flutter tool. include(${EPHEMERAL_DIR}/generated_config.cmake) # TODO: Move the rest of this into files in ephemeral. See # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") # Set fallback configurations for older versions of the flutter tool. if (NOT DEFINED FLUTTER_TARGET_PLATFORM) set(FLUTTER_TARGET_PLATFORM "windows-x64") endif() # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") # Published to parent scope for install step. set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) ``` -------------------------------- ### Project and Build Configuration Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Sets the minimum CMake version, project name, executable name, and application ID. It also configures build type and modern CMake behaviors. ```cmake cmake_minimum_required(VERSION 3.10) project(runner LANGUAGES CXX) set(BINARY_NAME "universal_ble_example") set(APPLICATION_ID "com.navideck.universal_ble") cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") if(FLUTTER_TARGET_PLATFORM_SYSROOT) set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) endif() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Flutter build mode" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Profile" "Release") endif() ``` -------------------------------- ### Run project checks Source: https://github.com/navideck/universal_ble/blob/main/CONTRIBUTING.md Execute these commands to verify code quality and run tests across platforms before submitting a pull request. ```sh flutter analyze flutter test flutter test --platform chrome ``` -------------------------------- ### Flutter and System Dependencies Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Includes the Flutter managed directory and finds system-level dependencies like GTK using PkgConfig. Defines the application ID as a preprocessor macro. ```cmake set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") add_subdirectory(${FLUTTER_MANAGED_DIR}) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") ``` -------------------------------- ### Add Dependency Source: https://github.com/navideck/universal_ble/blob/main/README.md Add the package to your pubspec.yaml file. ```yaml dependencies: universal_ble: ``` -------------------------------- ### Application Executable Definition Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Defines the main executable target for the application, listing its source files including generated plugin registration. Applies standard build settings. ```cmake add_executable(${BINARY_NAME} "main.cc" "my_application.cc" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) ``` -------------------------------- ### Configure iOS/macOS Bluetooth Permissions Source: https://github.com/navideck/universal_ble/blob/main/README.md Add these keys to your Info.plist to explain Bluetooth usage to the user. ```xml NSBluetoothAlwaysUsageDescription This app uses Bluetooth to scan, connect, and advertise to nearby devices. NSBluetoothPeripheralUsageDescription This app uses Bluetooth to advertise services to nearby devices. ``` -------------------------------- ### Enable Unicode Support Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Adds preprocessor definitions to enable Unicode support in the project. This is important for handling international characters correctly. ```cmake add_definitions(-DUNICODE -D_UNICODE) ``` -------------------------------- ### Configure per-device command queue Source: https://github.com/navideck/universal_ble/blob/main/README.md Sets the queue type to per-device to allow parallel command execution across different devices. ```dart // Create a separate queue for each device. UniversalBle.queueType = QueueType.perDevice; ``` -------------------------------- ### Customizing Platform Implementation Source: https://github.com/navideck/universal_ble/blob/main/README.md Override the default BLE implementation by extending UniversalBlePlatform and registering the custom instance. ```dart // Create a class that extends UniversalBlePlatform class UniversalBleMock extends UniversalBlePlatform { // Implement all commands } UniversalBle.setInstance(UniversalBleMock()); ``` -------------------------------- ### Configure BLE Logging Source: https://github.com/navideck/universal_ble/blob/main/README.md Set the global log level during app initialization to monitor BLE operations. ```dart void main() async { WidgetsFlutterBinding.ensureInitialized(); // Enable verbose logging to see all BLE operations await UniversalBle.setLogLevel(BleLogLevel.verbose); runApp(MyApp()); } ``` -------------------------------- ### Configure Android Manifest Permissions Source: https://github.com/navideck/universal_ble/blob/main/README.md Standard Bluetooth permissions for Android applications. ```xml ``` -------------------------------- ### Configure Web Scan Filters Source: https://github.com/navideck/universal_ble/blob/main/README.md Use the withServices parameter to define service filters, adjusting for web-specific requirements. ```dart ScanFilter( withServices: kIsWeb ? ["SERVICE_UUID"] : [], ) ``` -------------------------------- ### Configure Web Optional Services Source: https://github.com/navideck/universal_ble/blob/main/README.md Use PlatformConfig to specify optional services for web connections without applying filters. ```dart UniversalBle.startScan( platformConfig: PlatformConfig( web: WebOptions( optionalServices: ["SERVICE_UUID"] ) ) ) ``` -------------------------------- ### Link Dependencies and Include Directories Source: https://github.com/navideck/universal_ble/blob/main/example/windows/runner/CMakeLists.txt Links the application target against necessary libraries, including Flutter's core libraries and wrapper, and adds the source directory to the include path for header resolution. Application-specific dependencies should be added here. ```cmake target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) ``` ```cmake target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") ``` ```cmake target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") ``` -------------------------------- ### UniversalBle.getBluetoothAvailabilityState() Source: https://github.com/navideck/universal_ble/blob/main/README.md Retrieves the current state of the Bluetooth adapter. ```APIDOC ### UniversalBle.getBluetoothAvailabilityState() Returns the current AvailabilityState (e.g., poweredOn, poweredOff). ``` -------------------------------- ### bleDevice.connect() Source: https://github.com/navideck/universal_ble/blob/main/README.md Initiates a connection to the Bluetooth device. Supports optional auto-reconnection and platform-specific background connection configurations. ```APIDOC ## Future connect({bool autoConnect, ConnectionPlatformConfig platformConfig}) ### Description Connects to the BLE device. This method initiates a connection to the Bluetooth device. ### Parameters - **autoConnect** (bool) - Optional - Enables automatic reconnection when the device becomes available. - **platformConfig** (ConnectionPlatformConfig) - Optional - Platform-specific configuration, such as AppleConnectionOptions for background events. ### Example ```dart await bleDevice.connect(autoConnect: true); ``` ``` -------------------------------- ### Handling Connection Parameter Changes Source: https://github.com/navideck/universal_ble/blob/main/README.md Monitor connection parameter updates to re-request high priority if the OS reverts to power-saving intervals. Debounce this logic to avoid conflicting with the OS power manager. ```dart UniversalBle.onConnectionParametersChange = (update) { if (update.deviceId != deviceId || !update.isSuccess) return; // Prefer intervalMs for throughput decisions; estimatedPriority is approximate. if (update.intervalMs > 50) { UniversalBle.requestConnectionPriority( deviceId, BleConnectionPriority.highPerformance, ); } }; ``` -------------------------------- ### Request Permissions for Background Scanning Source: https://github.com/navideck/universal_ble/blob/main/README.md Best practice for requesting permissions in the foreground before initiating background scanning. ```dart // Request permissions in foreground (e.g., during app setup) await UniversalBle.requestPermissions(); // Later, in your ForegroundTask, scanning will work if permissions were granted await UniversalBle.startScan(); ``` -------------------------------- ### Configure Build Types for Multi-Config Generators Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Sets the available build configurations (Debug, Profile, Release) when using a multi-configuration generator (e.g., Visual Studio). ```cmake set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" CACHE STRING "" FORCE) ``` -------------------------------- ### Define Flutter Wrapper App Library Source: https://github.com/navideck/universal_ble/blob/main/example/windows/flutter/CMakeLists.txt Creates a STATIC library for the Flutter wrapper used by the runner application. It includes core and app-specific wrapper sources and links against the Flutter library. ```cmake # Wrapper sources needed for the runner. add_library(flutter_wrapper_app STATIC ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_APP} ) apply_standard_settings(flutter_wrapper_app) target_link_libraries(flutter_wrapper_app PUBLIC flutter) target_include_directories(flutter_wrapper_app PUBLIC "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_app flutter_assemble) ``` -------------------------------- ### Pair Device (Android, Windows, Linux) Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Trigger pairing with a device on Android, Windows, or Linux. This is a direct call to initiate the pairing process. ```dart await UniversalBle.pair(deviceId); ``` -------------------------------- ### Opt-in to Modern CMake Behaviors Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Explicitly enables modern CMake behaviors to avoid warnings in newer CMake versions. This ensures compatibility and adherence to current best practices. ```cmake cmake_policy(VERSION 3.14...3.25) ``` -------------------------------- ### Define Flutter Wrapper Plugin Library Source: https://github.com/navideck/universal_ble/blob/main/example/windows/flutter/CMakeLists.txt Creates a STATIC library for the Flutter wrapper used by plugins. It includes core and plugin-specific wrapper sources and links against the Flutter library. ```cmake list(APPEND CPP_WRAPPER_SOURCES_CORE "core_implementations.cc" "standard_codec.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_PLUGIN "plugin_registrar.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_APP "flutter_engine.cc" "flutter_view_controller.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") # Wrapper sources needed for a plugin. add_library(flutter_wrapper_plugin STATIC ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ) apply_standard_settings(flutter_wrapper_plugin) set_target_properties(flutter_wrapper_plugin PROPERTIES POSITION_INDEPENDENT_CODE ON) set_target_properties(flutter_wrapper_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) target_include_directories(flutter_wrapper_plugin PUBLIC "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_plugin flutter_assemble) ``` -------------------------------- ### UniversalBle.requestPermissions Source: https://github.com/navideck/universal_ble/blob/main/README.md Manually requests necessary BLE permissions. This is optional as permissions are automatically requested during scanning, but can be used to handle permissions before other operations. ```APIDOC ## UniversalBle.requestPermissions ### Description Manually requests BLE permissions. Returns successfully if permissions are granted, or throws a UniversalBleException if denied. Always succeeds on Windows, Linux, and Web. ### Parameters - **withAndroidFineLocation** (bool) - Optional - Whether to request Android fine location permission. ``` -------------------------------- ### Configure Flutter Interface Library Source: https://github.com/navideck/universal_ble/blob/main/example/linux/flutter/CMakeLists.txt Defines an INTERFACE library target named 'flutter' and sets up include directories and link libraries. This target includes Flutter's header files and links against the Flutter shared library and GTK, GLIB, and GIO. ```cmake add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE PkgConfig::GTK PkgConfig::GLIB PkgConfig::GIO ) add_dependencies(flutter flutter_assemble) ``` -------------------------------- ### Discover Services Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Discover all services and their characteristics for a connected device. This must be done before reading or writing data. ```dart // Discover services of a specific device UniversalBle.discoverServices(deviceId); ``` -------------------------------- ### Set Executable Binary Name Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Defines the name of the executable file that will be generated. This allows for easy customization of the application's on-disk name. ```cmake set(BINARY_NAME "universal_ble_example") ``` -------------------------------- ### Include Runner Application Build Rules Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Includes the CMake build rules for the application's runner. This directs CMake to build the main application executable. ```cmake add_subdirectory("runner") ``` -------------------------------- ### Define Profile Build Mode Linker and Compiler Flags Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Copies release linker and compiler flags to the profile build mode. This ensures consistent performance characteristics between Release and Profile builds. ```cmake set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") ``` -------------------------------- ### UniversalBlePeripheral Event Streams Source: https://github.com/navideck/universal_ble/blob/main/README.md Available event streams for monitoring peripheral state changes. ```APIDOC ## Event Streams - **advertisingStateStream**: Emits BlePeripheralAdvertisingStateChanged events. - **characteristicSubscriptionStream**: Emits BlePeripheralCharacteristicSubscriptionChanged events. - **connectionStateStream**: Emits BlePeripheralConnectionStateChanged events. - **serviceAddedStream**: Emits BlePeripheralServiceAdded events. - **mtuChangedStream**: Emits BlePeripheralMtuChanged events. ``` -------------------------------- ### Custom command to build Flutter library and headers Source: https://github.com/navideck/universal_ble/blob/main/example/linux/flutter/CMakeLists.txt A custom CMake command that executes the Flutter tool backend script to generate the Flutter library and its associated header files. It uses a phony target to ensure the command runs on every build. ```cmake add_custom_command( OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/_phony_ COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} VERBATIM ) ``` -------------------------------- ### Generated Plugin Rules Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Includes the CMake script responsible for building generated plugins and integrating them into the application. ```cmake include(flutter/generated_plugins.cmake) ``` -------------------------------- ### bleDevice.pair() Source: https://github.com/navideck/universal_ble/blob/main/README.md Triggers the pairing process for a BLE device. ```APIDOC ### bleDevice.pair(pairingCommand) Initiates pairing with the device. #### Parameters - **pairingCommand** (BleCommand) - Optional - Specific service and characteristic to use for pairing on Apple/Web platforms. ``` -------------------------------- ### Configure Android Bluetooth Advertise Permission Source: https://github.com/navideck/universal_ble/blob/main/README.md Required permission for apps that perform peripheral advertising. ```xml ``` -------------------------------- ### Apply Standard Compilation Settings Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt A CMake function to apply common compilation settings to a target. It enforces C++17 standard, sets warning levels, and defines specific preprocessor macros. ```cmake function(APPLY_STANDARD_SETTINGS TARGET) target_compile_features(${TARGET} PUBLIC cxx_std_17) target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") target_compile_options(${TARGET} PRIVATE /EHsc) target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() ``` -------------------------------- ### Perform BLE Scanning Source: https://github.com/navideck/universal_ble/blob/main/README.md Methods for discovering devices, including stream listeners, handlers, and filtering options. ```dart // Get scan updates from stream UniversalBle.scanStream.listen((BleDevice bleDevice) { // e.g. Use BleDevice ID to connect }); // Or set a handler UniversalBle.onScanResult = (bleDevice) {} // Perform a scan UniversalBle.startScan(); // Or optionally add a scan filter UniversalBle.startScan( scanFilter: ScanFilter( withServices: ["SERVICE_UUID"], withManufacturerData: [ManufacturerDataFilter(companyIdentifier: 0x004c)], withNamePrefix: ["NAME_PREFIX"], ) ); // Stop scanning UniversalBle.stopScan(); // Check if scanning UniversalBle.isScanning(); ``` -------------------------------- ### bleDevice.getService() Source: https://github.com/navideck/universal_ble/blob/main/README.md Retrieves a specific service by its UUID. ```APIDOC ## Future getService(String service, {bool preferCached}) ### Description Retrieves a specific service. If preferCached is true (default), cached services are used. ### Parameters - **service** (String) - Required - The UUID of the service. - **preferCached** (bool) - Optional - Whether to use cached services. ### Example ```dart BleService service = await bleDevice.getService('180a'); ``` ``` -------------------------------- ### Include Flutter Managed Directory Source: https://github.com/navideck/universal_ble/blob/main/example/windows/CMakeLists.txt Adds the Flutter managed directory to the build. This is typically where Flutter's build system resides. ```cmake set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") add_subdirectory(${FLUTTER_MANAGED_DIR}) ``` -------------------------------- ### Flutter Tool Backend Custom Command Source: https://github.com/navideck/universal_ble/blob/main/example/windows/flutter/CMakeLists.txt Configures a custom command to run the Flutter tool backend script. This command generates necessary build artifacts like the Flutter library and headers, and it's triggered by the flutter_assemble custom target. ```cmake # _phony_ is a non-existent file to force this command to run every time, # since currently there's no way to get a full input/output list from the # flutter tool. set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ${CPP_WRAPPER_SOURCES_APP} ${PHONY_OUTPUT} COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" ${FLUTTER_LIBRARY_HEADERS} ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ${CPP_WRAPPER_SOURCES_APP} ) ``` -------------------------------- ### Subscribe to indications Source: https://github.com/navideck/universal_ble/blob/main/README.md Enables indications for the characteristic. Throws an exception if not supported. ```dart await characteristic.indications.subscribe(); ``` -------------------------------- ### Manually Requesting BLE Permissions Source: https://github.com/navideck/universal_ble/blob/main/README.md Use this to request permissions before scanning or other operations. Note that this is optional as permissions are requested automatically during startScan. ```dart // Optional: Manually request permissions UniversalBle.requestPermissions( withAndroidFineLocation: false, ); ``` -------------------------------- ### Check Pairing Status (Android, Windows, Linux) Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Check the current pairing state of a device on Android, Windows, or Linux. Returns a boolean or null if the state is unknown. ```dart // Check current pairing state bool? isPaired = UniversalBle.isPaired(deviceId); ``` -------------------------------- ### Linking Dependencies Source: https://github.com/navideck/universal_ble/blob/main/example/linux/CMakeLists.txt Links the application executable against the Flutter library and GTK. Also adds a dependency on the Flutter assemble target. ```cmake target_link_libraries(${BINARY_NAME} PRIVATE flutter) target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) add_dependencies(${BINARY_NAME} flutter_assemble) ``` -------------------------------- ### Discover Services Source: https://github.com/navideck/universal_ble/blob/main/README.md Discovers and caches all services offered by the device. ```dart List services = await bleDevice.discoverServices(); for (var service in services) { debugPrint('Service UUID: ${service.uuid}'); } ``` -------------------------------- ### Connecting and Disconnecting Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Functions to establish and terminate connections with BLE devices, and to receive connection status updates. ```APIDOC ## Connecting and Disconnecting ### Description Connect to a device using its `deviceId` and disconnect from it. Also, provides streams and handlers for connection status changes. ### Methods - `connect(String deviceId)` - `disconnect(String deviceId)` - `connectionStream(String deviceId)` - `onConnectionChange` (handler) ### Parameters - `deviceId` (String): The unique identifier of the BLE device. - `isConnected` (bool): The connection status of the device. - `error` (String?): An error message if the connection failed. ### Usage Examples ```dart // Connect to a device String deviceId = bleDevice.deviceId; UniversalBle.connect(deviceId); // Disconnect from a device UniversalBle.disconnect(deviceId); // Get connection/disconnection updates using stream UniversalBle.connectionStream(deviceId).listen((bool isConnected) { debugPrint('Is device $deviceId connected?: $isConnected'); }); // Set a handler for all connection changes UniversalBle.onConnectionChange = (String deviceId, bool isConnected, String? error) { debugPrint('Is device $deviceId connected?: $isConnected. Error: $error'); }; ``` ``` -------------------------------- ### UniversalBlePeripheral.getSubscribedClients Source: https://github.com/navideck/universal_ble/blob/main/README.md Retrieves a list of device IDs currently subscribed to a specific characteristic. ```APIDOC ## getSubscribedClients ### Description Returns a list of device IDs that are currently subscribed to the specified characteristic. ### Parameters - **characteristicId** (String) - Required - The ID of the characteristic to check for subscriptions. ``` -------------------------------- ### Listen to Connection Stream Source: https://github.com/navideck/universal_ble/blob/main/README.md Subscribes to the connection stream to monitor device connectivity status. ```dart bleDevice.connectionStream.listen((isConnected) { debugPrint('Is device connected?: $isConnected'); }); ``` -------------------------------- ### Configure Android Scan Options Source: https://github.com/navideck/universal_ble/blob/main/README.md Sets scan parameters including legacy support for older BLE devices. ```dart UniversalBle.startScan( platformConfig: PlatformConfig( android: AndroidOptions( legacy: true, // omit for extended BLE 5 (default) scanMode: AndroidScanMode.lowLatency, callbackType: [AndroidScanCallbackType.allMatches], requestLocationPermission: false, ), ), ); ``` -------------------------------- ### Configure Android Location Permissions for iBeacons Source: https://github.com/navideck/universal_ble/blob/main/README.md Alternative permissions required when using iBeacons or location-based scanning. ```xml ``` -------------------------------- ### Define list_prepend function for CMake < 3.10 Source: https://github.com/navideck/universal_ble/blob/main/example/linux/flutter/CMakeLists.txt This custom function prepends a prefix to each element in a list, serving as a workaround for the missing list(TRANSFORM ... PREPEND ...) command in CMake version 3.10. ```cmake function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") foreach(element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") endforeach(element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() ``` -------------------------------- ### Manage GATT Services Source: https://github.com/navideck/universal_ble/blob/main/README.md Define and register GATT services, characteristics, and descriptors. Use these methods to add, retrieve, or remove services from the peripheral. ```dart import 'package:universal_ble/universal_ble.dart'; const batteryService = '0000180f-0000-1000-8000-00805f9b34fb'; const batteryLevelChar = '00002a19-0000-1000-8000-00805f9b34fb'; const heartRateService = '0000180d-0000-1000-8000-00805f9b34fb'; const heartRateChar = '00002a37-0000-1000-8000-00805f9b34fb'; await UniversalBlePeripheral.addService( BlePeripheralService( uuid: batteryService, primary: true, characteristics: [ BlePeripheralCharacteristic( uuid: batteryLevelChar, properties: [ CharacteristicProperty.read, CharacteristicProperty.notify, ], permissions: [ PeripheralAttributePermission.readable, PeripheralAttributePermission.writeable, ], descriptors: [ BlePeripheralDescriptor(uuid: '00002902-0000-1000-8000-00805f9b34fb'), ], ), ], ), ); await UniversalBlePeripheral.addService( BlePeripheralService( uuid: heartRateService, characteristics: [ BlePeripheralCharacteristic( uuid: heartRateChar, properties: [ CharacteristicProperty.read, CharacteristicProperty.notify, CharacteristicProperty.write, ], permissions: [ PeripheralAttributePermission.readable, PeripheralAttributePermission.writeable, ], ), ], ), ); final services = await UniversalBlePeripheral.getServices(); await UniversalBlePeripheral.removeService(heartRateService); await UniversalBlePeripheral.clearServices(); ``` -------------------------------- ### Connect to BLE Device Source: https://github.com/navideck/universal_ble/blob/main/README.md Initiates a connection to the Bluetooth device. ```dart await bleDevice.connect(); ``` -------------------------------- ### Clear command queues Source: https://github.com/navideck/universal_ble/blob/main/README.md Provides various methods to clear global, per-device, custom, or all command queues. ```dart // Clear global queue UniversalBle.clearQueue(BleCommandQueue.globalQueueId); // Clear a per-device queue (when queueType is perDevice) UniversalBle.clearQueue(deviceId); // Clear a custom queue (same string passed as queueId to read/write/etc.) UniversalBle.clearQueue('customQueueId'); // Clear all queues UniversalBle.clearQueue(); ``` -------------------------------- ### Format Dart code Source: https://github.com/navideck/universal_ble/blob/main/CONTRIBUTING.md Use the SDK formatter to ensure code style consistency. ```sh dart format . ``` -------------------------------- ### Pairing Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Functions to initiate pairing with a BLE device, check pairing status, and handle pairing state changes. ```APIDOC ## Pairing ### Description Initiate pairing with a BLE device, check its pairing status, and subscribe to pairing state changes. Pairing behavior differs between platforms. ### Methods - `pair(String deviceId, {BleCommand? pairingCommand})` - `isPaired(String deviceId, {BleCommand? pairingCommand})` - `pairingStateStream(String deviceId)` - `onPairingStateChange` (handler) - `unpair(String deviceId)` ### Parameters - `deviceId` (String): The unique identifier of the BLE device. - `pairingCommand` (BleCommand?): Optional command specifying the service and characteristic to use for pairing, especially on Apple/Web. - `paired` (bool): The pairing status of the device. ### Usage Examples ```dart // Trigger pairing (Android, Windows, Linux) await UniversalBle.pair(deviceId); // Trigger pairing with a specific characteristic (Apple, Web) UniversalBle.pair(deviceId, pairingCommand: BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC")); // Check pairing status (Android, Windows, Linux) bool? isPaired = UniversalBle.isPaired(deviceId); // Check pairing status (Apple, Web) bool? isPaired = await UniversalBle.isPaired(deviceId, pairingCommand: BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC")); // Get pairing state updates using stream UniversalBle.pairingStateStream(deviceId).listen((bool paired) { // Handle pairing state change }); // Set a handler for all pairing state changes UniversalBle.onPairingStateChange = (String deviceId, bool paired) {} // Unpair a device UniversalBle.unpair(deviceId); ``` ### Note on Apple and Web Pairing For Apple and Web, pairing is often triggered automatically by the OS when interacting with an encrypted characteristic. The `pair` and `isPaired` methods can optionally take a `pairingCommand` to specify which characteristic to use for this interaction. If no `pairingCommand` is provided, `pair` might not initiate pairing, and `isPaired` might return `null` if the device doesn't have a default encrypted read characteristic. ``` -------------------------------- ### Pair Device (Apple, Web) Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Pairing on Apple and Web is often automatic when accessing encrypted characteristics. Explicitly calling `pair` may trigger it, especially if a specific encrypted characteristic is provided. ```dart UniversalBle.pair(deviceId, pairingCommand: BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC")); ``` -------------------------------- ### Check Pairing Status (Apple, Web) Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Check the pairing status on Apple and Web, which requires specifying a `pairingCommand` with an encrypted characteristic. Returns null if no such characteristic is provided or found. ```dart bool? isPaired = await UniversalBle.isPaired(deviceId, pairingCommand: BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC")); ``` -------------------------------- ### Execute commands with custom queue IDs Source: https://github.com/navideck/universal_ble/blob/main/README.md Uses specific queue IDs to serialize commands independently while allowing parallel execution across different queues. ```dart UniversalBle.write(deviceId, service, char, value1, queueId: '1'); UniversalBle.write(deviceId, service, char, value2, queueId: '2'); ``` -------------------------------- ### Add Version Preprocessor Definitions Source: https://github.com/navideck/universal_ble/blob/main/example/windows/runner/CMakeLists.txt Adds preprocessor definitions to the compile command for the application target, embedding Flutter version information directly into the build. This allows the application to access version details at compile time. ```cmake target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") ``` ```cmake target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") ``` ```cmake target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") ``` ```cmake target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") ``` ```cmake target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") ``` -------------------------------- ### Check Bluetooth Availability Source: https://github.com/navideck/universal_ble/blob/main/README.md Verify Bluetooth state before initiating scans. ```dart AvailabilityState state = await UniversalBle.getBluetoothAvailabilityState(); // Start scan only if Bluetooth is powered on if (state == AvailabilityState.poweredOn) { UniversalBle.startScan(); } // Listen to bluetooth availability changes using stream UniversalBle.availabilityStream.listen((state) { if (state == AvailabilityState.poweredOn) { UniversalBle.startScan(); } }); // Or set a handler UniversalBle.onAvailabilityChange = (state) {}; ``` -------------------------------- ### Manage Subscribed Clients and Notify Length Source: https://github.com/navideck/universal_ble/blob/main/README.md Retrieves a list of subscribed clients and their maximum notify length to restore state after a restart. ```dart import 'package:universal_ble/universal_ble.dart'; final subscribers = await UniversalBlePeripheral.getSubscribedClients( batteryLevelChar, ); for (final deviceId in subscribers) { final maxNotifyLength = await UniversalBlePeripheral.getMaximumNotifyLength(deviceId); // maxNotifyLength is null when unknown for this device. } ``` -------------------------------- ### Configuring Scan Permissions Source: https://github.com/navideck/universal_ble/blob/main/README.md Configure location permission requests specifically for Android during the scanning process. ```dart UniversalBle.startScan( platformConfig: PlatformConfig( android: AndroidOptions( requestLocationPermission: false, ), ), ); ``` -------------------------------- ### Discovering Services Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Function to discover all services and their characteristics for a connected BLE device. ```APIDOC ## Discovering Services ### Description After establishing a connection, discover all services and their characteristics for a given device. ### Method - `discoverServices(String deviceId)` ### Parameters - `deviceId` (String): The unique identifier of the BLE device. ### Usage Example ```dart // Discover services of a specific device UniversalBle.discoverServices(deviceId); ``` ``` -------------------------------- ### characteristic.write() Source: https://github.com/navideck/universal_ble/blob/main/README.md Writes data to a BLE characteristic. ```APIDOC ### characteristic.write(value, withResponse) Writes a list of bytes to the characteristic. #### Parameters - **value** (List) - Required - The data to write. - **withResponse** (bool) - Optional - Whether to wait for a response from the device (default: true). ``` -------------------------------- ### Read, Write, and Subscribe to Characteristics Source: https://github.com/navideck/universal_ble/blob/main/README.low_level.md Read data from, write data to, or subscribe to notifications/indications from a device's characteristics. Ensure services are discovered first. Updates can be streamed or handled via a callback. ```dart // Read data from a characteristic UniversalBle.read(deviceId, serviceId, characteristicId); // Write data to a characteristic UniversalBle.write(deviceId, serviceId, characteristicId, value); // Subscribe to a characteristic notifications UniversalBle.subscribeNotifications(deviceId, serviceId, characteristicId); // Subscribe to a characteristic indications UniversalBle.subscribeIndications(deviceId, serviceId, characteristicId); // Get characteristic notifications/indications updates using stream UniversalBle.characteristicValueStream(deviceId, characteristicId).listen((Uint8List value) { debugPrint('OnValueChange $deviceId, $characteristicId, ${hex.encode(value)}'); }); // Or set a handler to get updates of all characteristics UniversalBle.onValueChange = (String deviceId, String characteristicId, Uint8List value) { debugPrint('onValueChange $deviceId, $characteristicId, ${hex.encode(value)}'); } // Unsubscribe from notifications/indications UniversalBle.unsubscribe(deviceId, serviceId, characteristicId); ``` -------------------------------- ### Handle BLE Exceptions Source: https://github.com/navideck/universal_ble/blob/main/README.md Implement type-safe error handling using UniversalBleException and UniversalBleErrorCode to manage platform-specific errors consistently. ```dart try { await bleDevice.connect(); } on ConnectionException catch (e) { // Handle connection-specific errors switch (e.code) { case UniversalBleErrorCode.connectionTimeout: // Handle timeout break; case UniversalBleErrorCode.connectionFailed: // Handle connection failure break; case UniversalBleErrorCode.deviceDisconnected: // Handle disconnection break; default: // Handle other connection errors } } on UniversalBleException catch (e) { // Handle other BLE errors print('Error code: ${e.code}, Message: ${e.message}'); } ``` -------------------------------- ### Configure Flutter Library Interface Source: https://github.com/navideck/universal_ble/blob/main/example/windows/flutter/CMakeLists.txt Defines the Flutter library as an INTERFACE library, setting include directories and linking against the Flutter library. It also adds a dependency on flutter_assemble. ```cmake list(APPEND FLUTTER_LIBRARY_HEADERS "flutter_export.h" "flutter_windows.h" "flutter_messenger.h" "flutter_plugin_registrar.h" "flutter_texture_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") add_dependencies(flutter flutter_assemble) ``` -------------------------------- ### Enable Auto-connect Source: https://github.com/navideck/universal_ble/blob/main/README.md Enables automatic reconnection when the device becomes available again. ```dart await bleDevice.connect(autoConnect: true); ``` -------------------------------- ### Monitor Peripheral Event Streams Source: https://github.com/navideck/universal_ble/blob/main/README.md Listens to various streams to track advertising, subscription, connection, service, and MTU changes. ```dart import 'package:universal_ble/universal_ble.dart'; UniversalBlePeripheral.advertisingStateStream.listen( (BlePeripheralAdvertisingStateChanged event) { // event.state, event.error }, ); UniversalBlePeripheral.characteristicSubscriptionStream.listen( (BlePeripheralCharacteristicSubscriptionChanged event) { // event.deviceId, event.characteristicId, event.isSubscribed, event.name }, ); UniversalBlePeripheral.connectionStateStream.listen( (BlePeripheralConnectionStateChanged event) { // event.deviceId, event.connected }, ); UniversalBlePeripheral.serviceAddedStream.listen( (BlePeripheralServiceAdded event) { // event.serviceId, event.error }, ); UniversalBlePeripheral.mtuChangedStream.listen( (BlePeripheralMtuChanged event) { // event.deviceId, event.mtu }, ); ```