diff --git a/pubspec.lock b/pubspec.lock index 7f09b08..fcc3902 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -495,10 +495,11 @@ packages: universal_ble: dependency: "direct main" description: - path: universal_ble - relative: true - source: path - version: "0.18.0" + name: universal_ble + sha256: "35d210e93a5938c6a6d1fd3c710cf4ac90b1bdd1b11c8eb2beeb32600672e6e6" + url: "https://pub.dev" + source: hosted + version: "0.17.0" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index b786850..54d65ad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,8 +12,7 @@ dependencies: url_launcher: ^6.3.1 flutter_local_notifications: ^19.0.0 - universal_ble: - path: universal_ble + universal_ble: any protobuf: ^3.1.0 dartx: any pointycastle: any diff --git a/universal_ble/.github/FUNDING.yml b/universal_ble/.github/FUNDING.yml deleted file mode 100644 index d782bf9..0000000 --- a/universal_ble/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: navideck diff --git a/universal_ble/.github/workflows/build_web_app.yml b/universal_ble/.github/workflows/build_web_app.yml deleted file mode 100644 index 8a73d69..0000000 --- a/universal_ble/.github/workflows/build_web_app.yml +++ /dev/null @@ -1,36 +0,0 @@ - -name: Build web app - -on: - push: - branches: [ "main" ] - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Setup Flutter - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - - run: flutter --version - - - name: Cache pub dependencies - uses: actions/cache@v2 - with: - path: ${{ env.FLUTTER_HOME }}/.pub-cache - key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }} - restore-keys: ${{ runner.os }}-pub- - - - name: Download pub dependencies - run: flutter pub get - - - name: Build Web App - run: cd example && flutter build web --base-href=/universal_ble/ - - - name: Deploy to GitHub Pages šŸš€ - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: example/build/web diff --git a/universal_ble/.github/workflows/test_ble_uuid_parser.yml b/universal_ble/.github/workflows/test_ble_uuid_parser.yml deleted file mode 100644 index 5acc44c..0000000 --- a/universal_ble/.github/workflows/test_ble_uuid_parser.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: BleUuidParser Tests - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Set up Flutter - uses: subosito/flutter-action@v2 - with: - channel: stable - - - name: Install dependencies - run: flutter pub get - - - name: Analyze project source - run: flutter analyze - - - name: Run Flutter tests - run: flutter test - - - name: Install Chrome - uses: browser-actions/setup-chrome@latest - - - name: Run Flutter tests on Chrome - uses: coactions/setup-xvfb@v1 - with: - run: flutter test --platform chrome \ No newline at end of file diff --git a/universal_ble/.gitignore b/universal_ble/.gitignore deleted file mode 100644 index 96486fd..0000000 --- a/universal_ble/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.packages -build/ diff --git a/universal_ble/.metadata b/universal_ble/.metadata deleted file mode 100644 index e4874b0..0000000 --- a/universal_ble/.metadata +++ /dev/null @@ -1,42 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "d211f42860350d914a5ad8102f9ec32764dc6d06" - channel: "stable" - -project_type: plugin - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - - platform: android - create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - - platform: ios - create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - - platform: linux - create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - - platform: macos - create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - - platform: windows - create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/universal_ble/.vscode/c_cpp_properties.json b/universal_ble/.vscode/c_cpp_properties.json deleted file mode 100644 index a33045a..0000000 --- a/universal_ble/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "configurations": [ - { - "name": "Win32", - "includePath": [ - "${workspaceFolder}/**" - ], - "defines": [ - "_DEBUG", - "UNICODE", - "_UNICODE" - ], - "windowsSdkVersion": "10.0.20348.0", - "compilerPath": "cl.exe", - "cStandard": "c17", - "cppStandard": "c++20", - "intelliSenseMode": "windows-msvc-x64" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/universal_ble/.vscode/launch.json b/universal_ble/.vscode/launch.json deleted file mode 100644 index ccb1785..0000000 --- a/universal_ble/.vscode/launch.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "example", - "cwd": "example", - "request": "launch", - "type": "dart" - }, - { - "name": "example release", - "cwd": "example", - "request": "launch", - "type": "dart", - "flutterMode": "release" - }, - { - "name": "example_mock", - "cwd": "example", - "request": "launch", - "type": "dart", - "args": [ - "--dart-define", - "MOCK=true", - ] - }, - { - "name": "example_web", - "cwd": "example", - "request": "launch", - "type": "dart", - "program": "lib/main.dart", - "args": [ - "-d", - "web-server", - "--web-hostname=127.0.0.1", - "--web-port=8080" - ], - }, - ], -} \ No newline at end of file diff --git a/universal_ble/.vscode/settings.json b/universal_ble/.vscode/settings.json deleted file mode 100644 index c6bb3ee..0000000 --- a/universal_ble/.vscode/settings.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "cSpell.words": [ - "bluez", - "BTLE", - "BTNHIGHLIGHT", - "bytevc", - "cccd", - "connnection", - "Cupertino", - "DFACE", - "HFONT", - "HINSTANCE", - "HMENU", - "hresult", - "hstring", - "HWND", - "Inspectable", - "LOWORD", - "LPARAM", - "lpfn", - "LPOSVERSIONINFO", - "lpsz", - "LRESULT", - "MAXIMIZEBOX", - "microtask", - "MINIMIZEBOX", - "modalias", - "msix", - "navideck", - "NOMOVE", - "NOSIZE", - "NSUUID", - "NTDDI", - "ntdll", - "NTSTATUS", - "OSVERSIONINFOW", - "osvi", - "OVERLAPPEDWINDOW", - "pairable", - "PNTSTATUS", - "PRTL", - "pubspec", - "RRSI", - "rssi", - "SETFONT", - "SETTEXT", - "subdata", - "sublist", - "THICKFRAME", - "unawaited", - "UNIVERSALBLE", - "Unpair", - "Unpairing", - "unwatch", - "uuidstr", - "winrt", - "WNDCLASS", - "WPARAM", - "ZUUID" - ], - "cmake.configureOnOpen": false, - "files.associations": { - "xstring": "cpp", - "chrono": "cpp", - "xlocale": "cpp", - "optional": "cpp", - "memory": "cpp", - "algorithm": "cpp", - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", - "cctype": "cpp", - "charconv": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "compare": "cpp", - "concepts": "cpp", - "condition_variable": "cpp", - "coroutine": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "exception": "cpp", - "format": "cpp", - "forward_list": "cpp", - "functional": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "ios": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "iterator": "cpp", - "limits": "cpp", - "list": "cpp", - "locale": "cpp", - "map": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "ratio": "cpp", - "set": "cpp", - "shared_mutex": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "stop_token": "cpp", - "streambuf": "cpp", - "string": "cpp", - "system_error": "cpp", - "thread": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "typeinfo": "cpp", - "unordered_map": "cpp", - "utility": "cpp", - "variant": "cpp", - "vector": "cpp", - "xfacet": "cpp", - "xhash": "cpp", - "xiosbase": "cpp", - "xlocbuf": "cpp", - "xlocinfo": "cpp", - "xlocmes": "cpp", - "xlocmon": "cpp", - "xlocnum": "cpp", - "xloctime": "cpp", - "xmemory": "cpp", - "xtr1common": "cpp", - "xtree": "cpp", - "xutility": "cpp", - "deque": "cpp", - "fstream": "cpp", - "unordered_set": "cpp", - "complex": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "filesystem": "cpp", - "ranges": "cpp", - "span": "cpp", - "stack": "cpp", - "typeindex": "cpp", - "future": "cpp", - "regex": "cpp" - } -} \ No newline at end of file diff --git a/universal_ble/CHANGELOG.md b/universal_ble/CHANGELOG.md deleted file mode 100644 index 57765ad..0000000 --- a/universal_ble/CHANGELOG.md +++ /dev/null @@ -1,171 +0,0 @@ -## 0.18.0 -* Improve docs for isPaired - -## 0.17.0 -* Fix Windows crash when calling pair APIs with an unknown deviceId -* Fix Windows crash when calling startScan again after some time -* Fix Windows warning `Unable to establish connection on channel` when hot restarting -* Refactor native Windows code -* Improve Android permission documentation - -## 0.16.0 -* BREAKING CHANGE: `payload` is now `payloadPrefix` -* BREAKING CHANGE: `mask` is now `payloadMask` -* Bump bluez to 0.8.3 -* Do not normalize UUIDs on native side -* Reverse _permissionStatus return values in example app -* Improve readme -* Improve ManufacturerDataFilter - -## 0.15.0 -* `getSystemDevices(withServices:)` now sets several generic services by default as filter -* `getConnectionState` on Android will now return `BleConnectionState.disconnected` if device is connected to the system but not to the app -* Improve callback error handling - -## 0.14.0 -* BREAKING CHANGE: `bleDevice.name` now filters out non-printable characters -* Add `bleDevice.rawName` -* Add `disableBluetooth` API -* Fix Apple CBCentralManager lazy initialization on `startScan` -* Fix Android error `scan too frequently` and auto retry scan once sufficient time has passed -* Fix duplicate `onValueChanged` events on Android 11 or earlier -* Fix Windows `withServices` filter -* Fix Windows Bluetooth availability state in release builds -* Throw error on Apple if Bluetooth permission is denied on `startScan` -* Do not throw `Characteristic already notifying` error. Subscribing to characteristic notifications multiple times is now handled safely -* Bump flutter_web_bluetooth to 1.0.0 - -## 0.13.0 -* BREAKING CHANGE: `scanFilter` filters are now in OR relation -* BREAKING CHANGE: `manufacturerDataHead` is removed from `BleDevice` -* BREAKING CHANGE: `WebConfig` is now `WebOptions` -* BREAKING CHANGE: `ManufacturerDataFilter.data` is now `ManufacturerDataFilter.payload` -* BREAKING CHANGE: `connect()` does not return a boolean anymore. It will throw error on connection failure -* BREAKING CHANGE: `pair()` does not return a boolean anymore. It will throw error on connection failure -* BREAKING CHANGE: `onConnectionChange` returns error as well -* BREAKING CHANGE: rename in-app pairing capabilities -* Deprecation: `manufacturerData` is deprecated in BleDevice and will be removed in the future -* Improve `scanFilter` handling -* Use `ManufacturerData` object instead of `Uint8List` for manufacturerData -* Add `manufacturerDataList` as `List` in `BleDevice` -* Auto convert all services passed to `getSystemDevices()` -* Return false for receivesAdvertisements on Linux/Web -* Add 1s delay in discoverServices on Linux -* Add `connectionStream` API to get connection updates as stream - -## 0.12.0 -* BREAKING CHANGE: `unPair` is now `unpair` -* BREAKING CHANGE: `onPairingStateChange` does not return error anymore -* Add `pair()`, `isPaired` and `onPairingStateChange` support for Apple and web -* `connect()` and `pair()` now return a bool result -* Add `PlatformConfig` property in `StartScan` -* Add `WebConfig` property in `PlatformConfig` -* Fix notifications for characteristics without cccd on Android -* Promote Linux to stable - -## 0.11.1 -* Trim spaces in UUIDs -* Receive advertisement events on web -* Improve cleanup after disconnection on web - -## 0.11.0 -* Unify UUID format across all platforms, 128-bit lowercase -* Add BleUuidParser utility methods for UUID parsing - -## 0.10.1 -* Improve Android error handling -* Fix Android disconnection events sometimes missed -* Improve cleanup after disconnection on Apple and Android -* Support pairing on Apple -* Improve code level documentation - -## 0.10.0 -* BREAKING CHANGE: `ScanResult` is now `BleDevice` -* BREAKING CHANGE: `getConnectedDevices` is now `getSystemDevices` -* BREAKING CHANGE: `isPaired` is now nullable -* BREAKING CHANGE: `onValueChanged` is now `onValueChange` -* BREAKING CHANGE: `onConnectionChanged` is now `onConnectionChange` -* Add `connectionState` property to BleDevice -* Add `isSystemDevice` property to BleDevice -* Add `.perDevice` queue -* Support "ProvidePin" pairing on Windows 10/11 -* Get RRSI updates on Apple platforms -* Improve enum parsing performance -* Improve code level documentation - -## 0.9.11 -* Add device name prefix filtering - -## 0.9.10 -* Fix Windows scan filter -* Remove scan result caching on Windows -* Improve service discovery on Linux -* Use asynchronous callbacks for SetNotifiable -* Remove dependency on `convert` -* Remove dependency on `collection` -* Update Android example app Gradle - -## 0.9.9 -* Improve service discovery on Apple -* Improve reconnection on Apple -* Persist long scan result name on Windows -* Fix Android serviceUuids in scanResults -* Example app improvements - -## 0.9.8 -* Improve manufacturer data discovery on Windows -* Example app improvements - -## 0.9.7 -* Fix characteristic keying on linux allowing receiving data from multiple BLE devices at the same time - -## 0.9.6 -* Fix a Windows issue where characteristics of certain services would not be discovered -* Improve readme - -## 0.9.5 -* Windows support has graduated from beta to stable -* Support filtering by manufacturer data -* Unify web's optionalServices API with filtering API -* Implement requestMtu in Linux -* Fix wrong manufacturer data in Windows release builds -* Improve logging - -## 0.9.4 -* Fix Windows crash when no Bluetooth adapter is present - -## 0.9.3 -* Add scan filter (withServices:) in `startScan()` -* Add service UUIDs from advertisements in `BleScanResult` -* Fix Windows release build compilation - -## 0.9.2 -* Add command queue -* Improve error handling on Android, iOS, macOS, Windows, Linux and web - -## 0.9.1 -* Improve logging - -## 0.9.0 -* Improve windows device name discovery -* Improve linux implementation -* Improve titles in example app - -## 0.8.4 -* Add `WebRequestOptionsBuilder.defaultServices` for convenience when setting `optionalServices` when scanning on web -* Add "try online" URL in readme -* Improve readme -* Improve example app - -## 0.8.3 -* Rename onPairStateChange *> onPairingStateChange -* Improve readme - -## 0.8.2 -* Improve readme - -## 0.8.1 -* Update supported platforms - -## 0.8.0 -* Initial release diff --git a/universal_ble/LICENSE b/universal_ble/LICENSE deleted file mode 100644 index 77b395a..0000000 --- a/universal_ble/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2024, Navideck Labs OÜ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -Copyright (c) 2020, Woodemi Co,Ltd. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/universal_ble/README.md b/universal_ble/README.md deleted file mode 100644 index b279204..0000000 --- a/universal_ble/README.md +++ /dev/null @@ -1,448 +0,0 @@ -# UniversalBLE - -[![universal_ble version](https://img.shields.io/pub/v/universal_ble?label=universal_ble)](https://pub.dev/packages/universal_ble) - -A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter. - -[Try it online](https://navideck.github.io/universal_ble/), provided your browser supports [Web Bluetooth](https://caniuse.com/web-bluetooth). - -## Features - -- [Scanning](#scanning) -- [Connecting](#connecting) -- [Discovering Services](#discovering-services) -- [Reading & Writing data](#reading--writing-data) -- [Pairing](#pairing) -- [Bluetooth Availability](#bluetooth-availability) -- [Command Queue](#command-queue) -- [Timeout](#timeout) -- [UUID Format Agnostic](#uuid-format-agnostic) - -## Usage - -### API Support Matrix - -| API | Android | iOS | macOS | Windows | Linux | Web | -| :------------------- | :-----: | :-: | :---: | :-----: | :----------: | :-: | -| startScan/stopScan | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | -| connect/disconnect | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | -| getSystemDevices | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āŒ | -| discoverServices | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | -| readValue | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | -| writeValue | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | -| setNotifiable | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | -| pair | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āŗ | -| unpair | āœ”ļø | āŒ | āŒ | āœ”ļø | āœ”ļø | āŒ | -| isPaired | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | -| onPairingStateChange | āœ”ļø | āŗ | āŗ | āœ”ļø | āœ”ļø | āŗ | -| getBluetoothAvailabilityState | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āŒ | -| enable/disable Bluetooth | āœ”ļø | āŒ | āŒ | āœ”ļø | āœ”ļø | āŒ | -| onAvailabilityChange | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | -| requestMtu | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āœ”ļø | āŒ | - -## Getting Started - -Add universal_ble in your pubspec.yaml: - -```yaml -dependencies: - universal_ble: -``` - -and import it wherever you want to use it: - -```dart -import 'package:universal_ble/universal_ble.dart'; -``` - -### Scanning - -```dart -// Set a scan result handler -UniversalBle.onScanResult = (bleDevice) { - // e.g. Use BleDevice ID to connect -} - -// 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(); -``` - -Before initiating a scan, ensure that Bluetooth is available: - -```dart -AvailabilityState state = await UniversalBle.getBluetoothAvailabilityState(); -// Start scan only if Bluetooth is powered on -if (state == AvailabilityState.poweredOn) { - UniversalBle.startScan(); -} - -// Or listen to bluetooth availability changes -UniversalBle.onAvailabilityChange = (state) { - if (state == AvailabilityState.poweredOn) { - UniversalBle.startScan(); - } -}; -``` - -See the [Bluetooth Availability](#bluetooth-availability) section for more. - -#### System Devices - -Already connected devices, connected either through previous sessions, other apps or through system settings, won't show up as scan results. You can get those using `getSystemDevices()`. - -```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: []); -``` - -For each such device the `isSystemDevice` property will be `true`. - -You still need to explicitly [connect](#connecting) to them before being able to use them. - -#### Scan Filter - -You can optionally set a filter when scanning. A filter can have multiple conditions (services, manufacturerData, namePrefix) and all conditions are in `OR` relation, returning results that match any of the given conditions. - -##### With Services - -When setting this parameter, the scan results will only include devices that advertise any of the specified services. - -```dart -List withServices; -``` - -Note: On web **you have to** specify services before you are able to use them. See the [web](#web) section for more details. - -##### With ManufacturerData - -Use the `withManufacturerData` parameter to filter devices by manufacturer data. When you pass a list of `ManufacturerDataFilter` objects to this parameter, the scan results will only include devices that contain any of the specified manufacturer data. - -You can filter manufacturer data by company identifier, payload prefix, or payload mask. - -```dart -List withManufacturerData = [ManufacturerDataFilter( - companyIdentifier: 0x004c, - payloadPrefix: Uint8List.fromList([0x001D,0x001A]), - payloadMask: Uint8List.fromList([1,0,1,1])) - ]; -``` - -##### With namePrefix - -Use the `withNamePrefix` parameter to filter devices by names (case sensitive). When you pass a list of names, the scan results will only include devices that have this name or start with the provided parameter. - -```dart -List withNamePrefix; -``` - -### Connecting - -```dart -// Connect to a device using the `deviceId` of the BleDevice received from `UniversalBle.onScanResult` -String deviceId = bleDevice.deviceId; -UniversalBle.connect(deviceId); - -// Disconnect from a device -UniversalBle.disconnect(deviceId); - -// Get connection/disconnection updates -UniversalBle.onConnectionChange = (String deviceId, bool isConnected, String? error) { - debugPrint('OnConnectionChange $deviceId, $isConnected Error: $error'); -} - -// Get current connection state -// Can be connected, disconnected, connecting or disconnecting -BleConnectionState connectionState = await bleDevice.connectionState; -``` - -### Discovering Services - -After establishing a connection, you need to discover services. This method will discover all services and their characteristics. - -```dart -// Discover services of a specific device -UniversalBle.discoverServices(deviceId); -``` - -### Reading & Writing data - -You need to first [discover services](#discovering-services) before you are able to read and write to characteristics. - -```dart -// Read data from a characteristic -UniversalBle.readValue(deviceId, serviceId, characteristicId); - -// Write data to a characteristic -UniversalBle.writeValue(deviceId, serviceId, characteristicId, value); - -// Subscribe to a characteristic -UniversalBle.setNotifiable(deviceId, serviceId, characteristicId, BleInputProperty.notification); - -// Get characteristic updates in `onValueChange` -UniversalBle.onValueChange = (String deviceId, String characteristicId, Uint8List value) { - debugPrint('onValueChange $deviceId, $characteristicId, ${hex.encode(value)}'); -} - -// Unsubscribe from a characteristic -UniversalBle.setNotifiable(deviceId, serviceId, characteristicId, BleInputProperty.disabled); -``` - -### Pairing - -#### Trigger pairing - -##### Pair on Android, Windows, Linux - -```dart -await UniversalBle.pair(deviceId); -``` - -##### Pair on Apple and web -For Apple and Web, pairing support depends on the device. Pairing is triggered automatically by the OS when you try to read/write from/to an encrypted characteristic. - -Calling `UniversalBle.pair(deviceId)` will only trigger pairing if the device has an *encrypted read characteristic*. - -If your device only has encrypted write characteristics or you happen to know which encrypted read characteristic you want to use, you can pass it with a `pairingCommand`. - -```dart -UniversalBle.pair(deviceId, pairingCommand: BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC")); -``` -After pairing you can check the pairing status. - -#### Pairing status - -##### Pair on Android, Windows, Linux - -```dart -// Check current pairing state -bool? isPaired = UniversalBle.isPaired(deviceId); -``` - -##### Pair on Apple and web - -For `Apple` and `Web`, you have to pass a "pairingCommand" with an encrypted read or write characteristic. If you don't pass it then it will return `null`. - -```dart -bool? isPaired = await UniversalBle.isPaired(deviceId, pairingCommand: BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC")); -``` - -##### Discovering encrypted characteristic -To discover encrypted characteristics, make sure your device is not paired and use the example app to read/write to all discovered characteristics one by one. If one of them triggers pairing, that means it is encrypted and you can use it to construct `BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC")`. - -#### Pairing state changes - -```dart -UniversalBle.onPairingStateChange = (String deviceId, bool isPaired) { - // Handle pairing state change -} -``` - -#### Unpair -```dart -UniversalBle.unpair(deviceId); -``` - -### Bluetooth Availability - -```dart -// Get current Bluetooth availability state -AvailabilityState availabilityState = UniversalBle.getBluetoothAvailabilityState(); // e.g. poweredOff or poweredOn, - -// Receive Bluetooth availability changes -UniversalBle.onAvailabilityChange = (state) { - // Handle the new Bluetooth availability state -}; - -// Enable Bluetooth programmatically -UniversalBle.enableBluetooth(); - -// Disable Bluetooth programmatically -UniversalBle.disableBluetooth(); -``` - -### Request MTU - -This method will **attempt** to set the MTU (Maximum Transmission Unit) but it is not guaranteed to succeed due to platform limitations. It will always return the current MTU. - -```dart -int mtu = await UniversalBle.requestMtu(widget.deviceId, 247); -``` - -#### Platform Limitations - -On most platforms, the MTU can only be queried but not manually set: - -- **iOS/macOS**: System automatically sets MTU to 185 bytes maximum -- **Android 14+**: System automatically sets MTU to 517 bytes for the first GATT client -- **Windows**: MTU can only be queried -- **Linux**: MTU can only be queried -- **Web**: No mechanism to query or modify MTU size - -#### Best Practices - -When developing cross-platform BLE applications and devices: - -- Design for default MTU size (23 bytes) as default -- Dynamically adapt to use larger packet sizes when the system provides them -- Take advantage of the increased throughput when available without requiring it -- Implement data fragmentation for larger transfers -- Handle platform-specific MTU size based on current value - -## Command Queue - -By default, all commands are executed in a global queue (`QueueType.global`), with each command waiting for the previous one to finish. - -If you want to parallelize commands between multiple devices, you can set: - -```dart -// Create a separate queue for each device. -UniversalBle.queueType = QueueType.perDevice; -``` - -You can also disable the queue completely and parallelize all commands, even for the same device, by using: - -```dart -// Disable queue -UniversalBle.queueType = QueueType.none; -``` - -Keep in mind that some platforms (e.g. Android) may not handle well devices that fail to process consecutive commands without a minimum interval. Therefore, it is not advised to set `queueType` to `none`. - -You can get queue updates by setting: - -```dart -// Get queue state updates -UniversalBle.onQueueUpdate = (String id, int remainingItems) { - debugPrint("Queue: $id Remaining: $remainingItems"); -}; -``` - -## Timeout - -By default, all commands have a timeout of 10 seconds. - -```dart -// Change timeout -UniversalBle.timeout = const Duration(seconds: 10); - -// Disable timeout -UniversalBle.timeout = null; -``` - -## UUID Format Agnostic - -UniversalBLE is agnostic to the UUID format of services and characteristics regardless of the platform the app runs on. When passing a UUID, you can pass it in any format (long/short) or character case (upper/lower case) you want. UniversalBLE will take care of necessary conversions, across all platforms, so that you don't need to worry about underlying platform differences. - -For consistency, all characteristic and service UUIDs will be returned in **lowercase 128-bit format**, across all platforms, e.g. `0000180a-0000-1000-8000-00805f9b34fb`. - -### Utility Methods - -If you need to convert any UUIDs in your app you can use the following methods. - -- `BleUuidParser.string()` converts a string to a 128-bit UUID formatted string: - -```dart -BleUuidParser.string("180A"); // "0000180a-0000-1000-8000-00805f9b34fb" - -BleUuidParser.string("0000180A-0000-1000-8000-00805F9B34FB"); // "0000180a-0000-1000-8000-00805f9b34fb" -``` - -- `BleUuidParser.number()` converts a number to a 128-bit UUID formatted string: - -```dart -BleUuidParser.number(0x180A); // "0000180a-0000-1000-8000-00805f9b34fb" -``` - -- `BleUuidParser.compare()` compares two differently formatted UUIDs: - -```dart -BleUuidParser.compare("180a","0000180A-0000-1000-8000-00805F9B34FB"); // true -``` - -## Platform-specific Setup - -### Android - -Add the following permissions to your AndroidManifest.xml file: - -```xml - - - - - - -``` - -If your app uses iBeacons or BLUETOOTH_SCAN to determine location, change the last 2 permissions to: - -```xml - - -``` - -### iOS / macOS - -Add `NSBluetoothPeripheralUsageDescription` and `NSBluetoothAlwaysUsageDescription` to Info.plist of your iOS and macOS app. - -Add the `Bluetooth` capability to the macOS app from Xcode. - -### Windows / Linux - -Your Bluetooth adapter needs to support at least Bluetooth 4.0. If you have more than 1 adapters, the first one returned from the system will be picked. - -When publishing on Windows, you need to declare the following [capabilities](https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations): `bluetooth, radios`. - -When publishing on Linux as a snap, you need to declare the `bluez` plug in `snapcraft.yaml`. -``` -... - plugs: - - bluez -``` - -### Web - -On web, the `withServices` parameter in the ScanFilter is used as [optional_services](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice#optionalservices) as well as a services filter. You have to set this parameter to ensure that you can access the specified services after connecting to the device. You can leave it empty for the rest of the platforms if your device does not advertise services. - -```dart -ScanFilter( - withServices: kIsWeb ? ["SERVICE_UUID"] : [], -) -``` - -If you don't want to apply any filter for these services but still want to access them, after connection, use `PlatformConfig`. - -```dart -UniversalBle.startScan( - platformConfig: PlatformConfig( - web: WebOptions( - optionalServices: ["SERVICE_UUID"] - ) - ) -) -``` - -## Customizing Platform Implementation of UniversalBle - -```dart -// Create a class that extends UniversalBlePlatform -class UniversalBleMock extends UniversalBlePlatform { - // Implement all commands -} - -UniversalBle.setInstance(UniversalBleMock()); -``` diff --git a/universal_ble/analysis_options.yaml b/universal_ble/analysis_options.yaml deleted file mode 100644 index a5744c1..0000000 --- a/universal_ble/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/universal_ble/android/.gitignore b/universal_ble/android/.gitignore deleted file mode 100644 index 161bdcd..0000000 --- a/universal_ble/android/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures -.cxx diff --git a/universal_ble/android/build.gradle b/universal_ble/android/build.gradle deleted file mode 100644 index 086e44c..0000000 --- a/universal_ble/android/build.gradle +++ /dev/null @@ -1,68 +0,0 @@ -group 'com.navideck.universal_ble' -version '1.0-SNAPSHOT' - -buildscript { - ext.kotlin_version = '1.7.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.3.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - -android { - if (project.android.hasProperty("namespace")) { - namespace 'com.navideck.universal_ble' - } - - compileSdkVersion 34 - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - test.java.srcDirs += 'src/test/kotlin' - } - - defaultConfig { - minSdkVersion 21 - } - - dependencies { - testImplementation 'org.jetbrains.kotlin:kotlin-test' - testImplementation 'org.mockito:mockito-core:5.0.0' - } - - testOptions { - unitTests.all { - useJUnitPlatform() - - testLogging { - events "passed", "skipped", "failed", "standardOut", "standardError" - outputs.upToDateWhen {false} - showStandardStreams = true - } - } - } -} diff --git a/universal_ble/android/settings.gradle b/universal_ble/android/settings.gradle deleted file mode 100644 index 2f6c0d8..0000000 --- a/universal_ble/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'universal_ble' diff --git a/universal_ble/android/src/main/AndroidManifest.xml b/universal_ble/android/src/main/AndroidManifest.xml deleted file mode 100644 index 067f1cb..0000000 --- a/universal_ble/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/SafeScanner.kt b/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/SafeScanner.kt deleted file mode 100644 index e0458a8..0000000 --- a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/SafeScanner.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.navideck.universal_ble - -import android.annotation.SuppressLint -import android.bluetooth.BluetoothManager -import android.bluetooth.le.BluetoothLeScanner -import android.bluetooth.le.ScanCallback -import android.bluetooth.le.ScanFilter -import android.bluetooth.le.ScanSettings -import android.os.Build -import android.os.Handler -import android.os.Looper -import android.util.Log -import java.util.LinkedList - -private const val NUM_SCAN_DURATIONS_KEPT = 5 -private const val EXCESSIVE_SCANNING_PERIOD_MS = 30 * 1000L -private const val TAG = "UniversalBlePlugin" - -/** - * A safe wrapper for Bluetooth LE scanning operations that prevents excessive scanning. - * - * This class manages BLE scanning while adhering to Android's scanning frequency limits by: - * - Tracking scan start times over a 30-second window - * - Limiting to 5 scan operations within this window - * - Automatically scheduling delayed scans when frequency limits are exceeded - * - Providing safe start/stop scan operations with error handling - * - * The scanner will automatically delay new scan requests if the frequency limit is reached, - * and will retry once sufficient time has passed. This helps prevent scan failure errors - * and ensures compliance with Android's scanning restrictions. - * - * @property bluetoothManager The system's BluetoothManager used for scanning operations - */ -@SuppressLint("MissingPermission") -class SafeScanner(private val bluetoothManager: BluetoothManager) { - private val handler = Handler(Looper.myLooper()!!) - private val startTimes = LinkedList() - private var awaitingScan = false - - fun startScan(filters: List, settings: ScanSettings, callback: ScanCallback) { - val now = System.currentTimeMillis() - startTimes.removeAll { now - it > EXCESSIVE_SCANNING_PERIOD_MS } - - if (startTimes.size >= NUM_SCAN_DURATIONS_KEPT) { - if (awaitingScan) { - Log.e(TAG, "startScan: too frequent, awaiting scan..") - return - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - callback.onScanFailed(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY) - } - - awaitingScan = true - val delay = startTimes.first + EXCESSIVE_SCANNING_PERIOD_MS - now + 2_000 - Log.e(TAG, "startScan: too frequent, schedule auto-start after $delay ms $startTimes") - - handler.postDelayed({ - Log.d(TAG, "Retrying scan after delay") - awaitingScan = false - startScan(filters, settings, callback) - }, delay) - } else { - awaitingScan = false - startTimes.addLast(now) - try { - bluetoothManager.adapter.bluetoothLeScanner?.startScan(filters, settings, callback) - } catch (e: Exception) { - Log.e(TAG, "Failed to start Scan : $e") - } - } - } - - fun stopScan(callback: ScanCallback) { - awaitingScan = false - handler.removeCallbacksAndMessages(null) - bluetoothManager.adapter.bluetoothLeScanner?.stopScan(callback) - } -} \ No newline at end of file diff --git a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBle.g.kt b/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBle.g.kt deleted file mode 100644 index 6d6a34f..0000000 --- a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBle.g.kt +++ /dev/null @@ -1,725 +0,0 @@ -// Autogenerated from Pigeon (v22.6.1), do not edit directly. -// See also: https://pub.dev/packages/pigeon -@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") - -package com.navideck.universal_ble - -import android.util.Log -import io.flutter.plugin.common.BasicMessageChannel -import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMessageCodec -import java.io.ByteArrayOutputStream -import java.nio.ByteBuffer - -private fun wrapResult(result: Any?): List { - return listOf(result) -} - -private fun wrapError(exception: Throwable): List { - return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) - } else { - listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) - } -} - -private fun createConnectionError(channelName: String): FlutterError { - return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "")} - -/** - * Error class for passing custom error details to Flutter via a thrown PlatformException. - * @property code The error code. - * @property message The error message. - * @property details The error details. Must be a datatype supported by the api codec. - */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null -) : Throwable() - -/** Generated class from Pigeon that represents data sent in messages. */ -data class UniversalBleScanResult ( - val deviceId: String, - val name: String? = null, - val isPaired: Boolean? = null, - val rssi: Long? = null, - val manufacturerDataList: List? = null, - val services: List? = null -) - { - companion object { - fun fromList(pigeonVar_list: List): UniversalBleScanResult { - val deviceId = pigeonVar_list[0] as String - val name = pigeonVar_list[1] as String? - val isPaired = pigeonVar_list[2] as Boolean? - val rssi = pigeonVar_list[3] as Long? - val manufacturerDataList = pigeonVar_list[4] as List? - val services = pigeonVar_list[5] as List? - return UniversalBleScanResult(deviceId, name, isPaired, rssi, manufacturerDataList, services) - } - } - fun toList(): List { - return listOf( - deviceId, - name, - isPaired, - rssi, - manufacturerDataList, - services, - ) - } -} - -/** Generated class from Pigeon that represents data sent in messages. */ -data class UniversalBleService ( - val uuid: String, - val characteristics: List? = null -) - { - companion object { - fun fromList(pigeonVar_list: List): UniversalBleService { - val uuid = pigeonVar_list[0] as String - val characteristics = pigeonVar_list[1] as List? - return UniversalBleService(uuid, characteristics) - } - } - fun toList(): List { - return listOf( - uuid, - characteristics, - ) - } -} - -/** Generated class from Pigeon that represents data sent in messages. */ -data class UniversalBleCharacteristic ( - val uuid: String, - val properties: List -) - { - companion object { - fun fromList(pigeonVar_list: List): UniversalBleCharacteristic { - val uuid = pigeonVar_list[0] as String - val properties = pigeonVar_list[1] as List - return UniversalBleCharacteristic(uuid, properties) - } - } - fun toList(): List { - return listOf( - uuid, - properties, - ) - } -} - -/** - * Scan Filters - * - * Generated class from Pigeon that represents data sent in messages. - */ -data class UniversalScanFilter ( - val withServices: List, - val withNamePrefix: List, - val withManufacturerData: List -) - { - companion object { - fun fromList(pigeonVar_list: List): UniversalScanFilter { - val withServices = pigeonVar_list[0] as List - val withNamePrefix = pigeonVar_list[1] as List - val withManufacturerData = pigeonVar_list[2] as List - return UniversalScanFilter(withServices, withNamePrefix, withManufacturerData) - } - } - fun toList(): List { - return listOf( - withServices, - withNamePrefix, - withManufacturerData, - ) - } -} - -/** Generated class from Pigeon that represents data sent in messages. */ -data class UniversalManufacturerDataFilter ( - val companyIdentifier: Long, - val data: ByteArray? = null, - val mask: ByteArray? = null -) - { - companion object { - fun fromList(pigeonVar_list: List): UniversalManufacturerDataFilter { - val companyIdentifier = pigeonVar_list[0] as Long - val data = pigeonVar_list[1] as ByteArray? - val mask = pigeonVar_list[2] as ByteArray? - return UniversalManufacturerDataFilter(companyIdentifier, data, mask) - } - } - fun toList(): List { - return listOf( - companyIdentifier, - data, - mask, - ) - } -} - -/** Generated class from Pigeon that represents data sent in messages. */ -data class UniversalManufacturerData ( - val companyIdentifier: Long, - val data: ByteArray -) - { - companion object { - fun fromList(pigeonVar_list: List): UniversalManufacturerData { - val companyIdentifier = pigeonVar_list[0] as Long - val data = pigeonVar_list[1] as ByteArray - return UniversalManufacturerData(companyIdentifier, data) - } - } - fun toList(): List { - return listOf( - companyIdentifier, - data, - ) - } -} -private open class UniversalBlePigeonCodec : StandardMessageCodec() { - override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return when (type) { - 129.toByte() -> { - return (readValue(buffer) as? List)?.let { - UniversalBleScanResult.fromList(it) - } - } - 130.toByte() -> { - return (readValue(buffer) as? List)?.let { - UniversalBleService.fromList(it) - } - } - 131.toByte() -> { - return (readValue(buffer) as? List)?.let { - UniversalBleCharacteristic.fromList(it) - } - } - 132.toByte() -> { - return (readValue(buffer) as? List)?.let { - UniversalScanFilter.fromList(it) - } - } - 133.toByte() -> { - return (readValue(buffer) as? List)?.let { - UniversalManufacturerDataFilter.fromList(it) - } - } - 134.toByte() -> { - return (readValue(buffer) as? List)?.let { - UniversalManufacturerData.fromList(it) - } - } - else -> super.readValueOfType(type, buffer) - } - } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - when (value) { - is UniversalBleScanResult -> { - stream.write(129) - writeValue(stream, value.toList()) - } - is UniversalBleService -> { - stream.write(130) - writeValue(stream, value.toList()) - } - is UniversalBleCharacteristic -> { - stream.write(131) - writeValue(stream, value.toList()) - } - is UniversalScanFilter -> { - stream.write(132) - writeValue(stream, value.toList()) - } - is UniversalManufacturerDataFilter -> { - stream.write(133) - writeValue(stream, value.toList()) - } - is UniversalManufacturerData -> { - stream.write(134) - writeValue(stream, value.toList()) - } - else -> super.writeValue(stream, value) - } - } -} - - -/** - * Flutter -> Native - * - * Generated interface from Pigeon that represents a handler of messages from Flutter. - */ -interface UniversalBlePlatformChannel { - fun getBluetoothAvailabilityState(callback: (Result) -> Unit) - fun enableBluetooth(callback: (Result) -> Unit) - fun disableBluetooth(callback: (Result) -> Unit) - fun startScan(filter: UniversalScanFilter?) - fun stopScan() - fun connect(deviceId: String) - fun disconnect(deviceId: String) - fun setNotifiable(deviceId: String, service: String, characteristic: String, bleInputProperty: Long, callback: (Result) -> Unit) - fun discoverServices(deviceId: String, callback: (Result>) -> Unit) - fun readValue(deviceId: String, service: String, characteristic: String, callback: (Result) -> Unit) - fun requestMtu(deviceId: String, expectedMtu: Long, callback: (Result) -> Unit) - fun writeValue(deviceId: String, service: String, characteristic: String, value: ByteArray, bleOutputProperty: Long, callback: (Result) -> Unit) - fun isPaired(deviceId: String, callback: (Result) -> Unit) - fun pair(deviceId: String, callback: (Result) -> Unit) - fun unPair(deviceId: String) - fun getSystemDevices(withServices: List, callback: (Result>) -> Unit) - fun getConnectionState(deviceId: String): Long - - companion object { - /** The codec used by UniversalBlePlatformChannel. */ - val codec: MessageCodec by lazy { - UniversalBlePigeonCodec() - } - /** Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binaryMessenger`. */ - @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: UniversalBlePlatformChannel?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - api.getBluetoothAvailabilityState{ result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - api.enableBluetooth{ result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disableBluetooth$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - api.disableBluetooth{ result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val filterArg = args[0] as UniversalScanFilter? - val wrapped: List = try { - api.startScan(filterArg) - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = try { - api.stopScan() - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - val wrapped: List = try { - api.connect(deviceIdArg) - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - val wrapped: List = try { - api.disconnect(deviceIdArg) - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - val serviceArg = args[1] as String - val characteristicArg = args[2] as String - val bleInputPropertyArg = args[3] as Long - api.setNotifiable(deviceIdArg, serviceArg, characteristicArg, bleInputPropertyArg) { result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - reply.reply(wrapResult(null)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - api.discoverServices(deviceIdArg) { result: Result> -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - val serviceArg = args[1] as String - val characteristicArg = args[2] as String - api.readValue(deviceIdArg, serviceArg, characteristicArg) { result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - val expectedMtuArg = args[1] as Long - api.requestMtu(deviceIdArg, expectedMtuArg) { result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - val serviceArg = args[1] as String - val characteristicArg = args[2] as String - val valueArg = args[3] as ByteArray - val bleOutputPropertyArg = args[4] as Long - api.writeValue(deviceIdArg, serviceArg, characteristicArg, valueArg, bleOutputPropertyArg) { result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - reply.reply(wrapResult(null)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - api.isPaired(deviceIdArg) { result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - api.pair(deviceIdArg) { result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - val wrapped: List = try { - api.unPair(deviceIdArg) - listOf(null) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val withServicesArg = args[0] as List - api.getSystemDevices(withServicesArg) { result: Result> -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(wrapResult(data)) - } - } - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val deviceIdArg = args[0] as String - val wrapped: List = try { - listOf(api.getConnectionState(deviceIdArg)) - } catch (exception: Throwable) { - wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - } - } -} -/** - * Native -> Flutter - * - * Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. - */ -class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger, private val messageChannelSuffix: String = "") { - companion object { - /** The codec used by UniversalBleCallbackChannel. */ - val codec: MessageCodec by lazy { - UniversalBlePigeonCodec() - } - } - fun onAvailabilityChanged(stateArg: Long, callback: (Result) -> Unit) -{ - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$separatedMessageChannelSuffix" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(stateArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(createConnectionError(channelName))) - } - } - } - fun onPairStateChange(deviceIdArg: String, isPairedArg: Boolean, errorArg: String?, callback: (Result) -> Unit) -{ - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$separatedMessageChannelSuffix" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(deviceIdArg, isPairedArg, errorArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(createConnectionError(channelName))) - } - } - } - fun onScanResult(resultArg: UniversalBleScanResult, callback: (Result) -> Unit) -{ - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$separatedMessageChannelSuffix" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(resultArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(createConnectionError(channelName))) - } - } - } - fun onValueChanged(deviceIdArg: String, characteristicIdArg: String, valueArg: ByteArray, callback: (Result) -> Unit) -{ - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$separatedMessageChannelSuffix" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(deviceIdArg, characteristicIdArg, valueArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(createConnectionError(channelName))) - } - } - } - fun onConnectionChanged(deviceIdArg: String, connectedArg: Boolean, errorArg: String?, callback: (Result) -> Unit) -{ - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$separatedMessageChannelSuffix" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(deviceIdArg, connectedArg, errorArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(createConnectionError(channelName))) - } - } - } -} diff --git a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleFilterUtil.kt b/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleFilterUtil.kt deleted file mode 100644 index a8a6da8..0000000 --- a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleFilterUtil.kt +++ /dev/null @@ -1,164 +0,0 @@ -package com.navideck.universal_ble - -import android.annotation.SuppressLint -import android.bluetooth.le.ScanFilter -import android.bluetooth.le.ScanResult -import android.os.ParcelUuid -import android.util.Log -import java.nio.ByteBuffer -import java.nio.ByteOrder -import java.util.UUID -import kotlin.experimental.and - -private const val TAG = "UniversalBlePlugin" - -@SuppressLint("MissingPermission") -class UniversalBleFilterUtil { - var scanFilter: UniversalScanFilter? = null - var serviceFilterUUIDS: List = emptyList() - - fun filterDevice( - name: String?, - manufacturerDataList: List, - serviceUuids: Array, - ): Boolean { - val filter = scanFilter ?: return true - - val hasNamePrefixFilter = filter.withNamePrefix.isNotEmpty() - val hasServiceFilter = filter.withServices.isNotEmpty() - val hasManufacturerDataFilter = filter.withManufacturerData.isNotEmpty() - - // If there is no filter at all, then allow device - if (!hasNamePrefixFilter && - !hasServiceFilter && - !hasManufacturerDataFilter - ) { - return true - } - - // For not, we only have DeviceName filter - return hasNamePrefixFilter && isNameMatchingFilters(filter, name) || - hasServiceFilter && isServicesMatchingFilters(serviceUuids) || - hasManufacturerDataFilter && isManufacturerDataMatchingFilters( - filter, - manufacturerDataList - ) - } - - private fun isNameMatchingFilters(scanFilter: UniversalScanFilter, name: String?): Boolean { - val namePrefixFilter = scanFilter.withNamePrefix.filterNotNull() - if (namePrefixFilter.isEmpty()) { - return true - } - if (name.isNullOrEmpty()) { - return false - } - return namePrefixFilter.any { name.startsWith(it) } - } - - private fun isServicesMatchingFilters( - serviceUuids: Array, - ): Boolean { - if (serviceFilterUUIDS.isEmpty()) { - return true - } - if (serviceUuids.isEmpty()) { - return false - } - return serviceFilterUUIDS.any { - serviceUuids.contains(it) - } - } - - private fun isManufacturerDataMatchingFilters( - scanFilter: UniversalScanFilter, - manufacturerDataList: List, - ): Boolean { - val filters = scanFilter.withManufacturerData.filterNotNull() - if (filters.isEmpty()) return true - if (manufacturerDataList.isEmpty()) return false - return manufacturerDataList.any { msd -> - filters.any { filter -> - msd.companyIdentifier == filter.companyIdentifier && - isDataMatching(filter.data, msd.data, filter.mask) - } - } - } - - private fun isDataMatching( - filterData: ByteArray?, - deviceData: ByteArray, - filterMask: ByteArray?, - ): Boolean { - if (filterData == null) return true - if (filterData.size > deviceData.size) return false - - val mask = filterMask ?: ByteArray(filterData.size) { 0xFF.toByte() } - if (filterData.size != mask.size) return false - - return filterData.indices.all { i -> - (filterData[i] and mask[i]) == (deviceData[i] and mask[i]) - } - } -} - -fun UniversalScanFilter.usesCustomFilters(): Boolean { - // NamePrefix Filtering is not supported in native filters - return withNamePrefix.isNotEmpty() -} - -// Convert UniversalScanFilter to ScanFilter -fun UniversalScanFilter.toScanFilters(serviceUuids: List): List { - val scanFilters: ArrayList = arrayListOf() - - // Add withServices Filter - for (service in serviceUuids) { - try { - service.let { - scanFilters.add( - ScanFilter.Builder().setServiceUuid(ParcelUuid(it)).build() - ) - Log.e(TAG, "scanFilters: $it") - } - } catch (e: Exception) { - Log.e(TAG, e.toString()) - throw FlutterError( - "illegalIllegalArgument", - "Invalid serviceId: $service", - e.toString() - ) - } - } - - // Add ManufacturerData Filter - for (manufacturerData in this.withManufacturerData) { - try { - manufacturerData?.companyIdentifier?.let { - val data: ByteArray = manufacturerData.data ?: ByteArray(0) - val mask: ByteArray? = manufacturerData.mask - if (mask == null) { - scanFilters.add( - ScanFilter.Builder().setManufacturerData( - it.toInt(), data - ).build() - ) - } else { - scanFilters.add( - ScanFilter.Builder().setManufacturerData( - it.toInt(), data, mask - ).build() - ) - } - } - } catch (e: Exception) { - Log.e(TAG, e.toString()) - throw FlutterError( - "illegalIllegalArgument", - "Invalid manufacturerData: ${manufacturerData?.companyIdentifier} ${manufacturerData?.data} ${manufacturerData?.mask}", - e.toString() - ) - } - } - - return scanFilters.toList() -} diff --git a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt b/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt deleted file mode 100644 index 806387c..0000000 --- a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt +++ /dev/null @@ -1,358 +0,0 @@ -package com.navideck.universal_ble - -import android.bluetooth.BluetoothAdapter -import android.bluetooth.BluetoothDevice -import android.bluetooth.BluetoothGatt -import android.bluetooth.BluetoothGattCharacteristic -import android.bluetooth.BluetoothStatusCodes -import android.bluetooth.le.ScanCallback.SCAN_FAILED_ALREADY_STARTED -import android.bluetooth.le.ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED -import android.bluetooth.le.ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED -import android.bluetooth.le.ScanCallback.SCAN_FAILED_INTERNAL_ERROR -import android.bluetooth.le.ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES -import android.bluetooth.le.ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY -import android.bluetooth.le.ScanResult -import android.util.Log -import android.util.SparseArray -import java.nio.ByteBuffer -import java.nio.ByteOrder -import java.util.UUID - -private const val TAG = "UniversalBlePlugin" - -private val knownGatts = mutableMapOf() -val ccdCharacteristic: UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb") - -enum class BleConnectionState(val value: Long) { - Connected(0), - Disconnected(1), - Connecting(2), - Disconnecting(3) -} - -enum class AvailabilityState(val value: Long) { - Unknown(0), - Resetting(1), - Unsupported(2), - Unauthorized(3), - PoweredOff(4), - PoweredOn(5); -} - -enum class BleInputProperty(val value: Long) { - Disabled(0), - Notification(1), - Indication(2); -} - -enum class BleOutputProperty(val value: Long) { - withResponse(0), - withoutResponse(1); -} - - -enum class CharacteristicProperty(val value: Long) { - Broadcast(0), - Read(1), - WriteWithoutResponse(2), - Write(3), - Notify(4), - Indicate(5), - AuthenticatedSignedWrites(6), - ExtendedProperties(7) -} - - -fun Int.toBleConnectionState(): BleConnectionState { - return when (this) { - BluetoothGatt.STATE_CONNECTED -> BleConnectionState.Connected - BluetoothGatt.STATE_CONNECTING -> BleConnectionState.Connecting - BluetoothGatt.STATE_DISCONNECTING -> BleConnectionState.Disconnecting - BluetoothGatt.STATE_DISCONNECTED -> BleConnectionState.Disconnected - else -> BleConnectionState.Disconnected - } -} - -fun List.toUUIDList(): List { - return this.map { UUID.fromString(it) } -} - - -fun String.toBluetoothGatt(): BluetoothGatt { - return this.findGatt() - ?: throw FlutterError("IllegalArgument", "Unknown deviceId: $this", null) -} - -fun String.isKnownGatt(): Boolean { - return this.findGatt() != null -} - -fun String.findGatt(): BluetoothGatt? { - return knownGatts[this] -} - -fun BluetoothGatt.saveCacheIfNeeded() { - knownGatts[this.device.address] = this -} - -fun BluetoothGatt.removeCache() { - knownGatts.remove(this.device.address) -} - - -fun Int.toAvailabilityState(): Long { - return when (this) { - BluetoothAdapter.STATE_OFF -> AvailabilityState.PoweredOff.value - BluetoothAdapter.STATE_ON -> AvailabilityState.PoweredOn.value - BluetoothAdapter.STATE_TURNING_ON -> AvailabilityState.Resetting.value - BluetoothAdapter.STATE_TURNING_OFF -> AvailabilityState.Resetting.value - else -> AvailabilityState.Unknown.value - } -} - -fun Int.parseScanErrorMessage(): String { - return when (this) { - SCAN_FAILED_ALREADY_STARTED -> "SCAN_FAILED_ALREADY_STARTED" - SCAN_FAILED_APPLICATION_REGISTRATION_FAILED -> "SCAN_FAILED_APPLICATION_REGISTRATION_FAILED" - SCAN_FAILED_FEATURE_UNSUPPORTED -> "SCAN_FAILED_FEATURE_UNSUPPORTED" - SCAN_FAILED_INTERNAL_ERROR -> "SCAN_FAILED_INTERNAL_ERROR" - SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES -> "SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES" - SCAN_FAILED_SCANNING_TOO_FREQUENTLY -> "SCAN_FAILED_SCANNING_TOO_FREQUENTLY" - else -> "ErrorCode: $this" - } -} - -fun Int.parseBluetoothStatusCodeError(): String? { - if (this == BluetoothStatusCodes.SUCCESS) return null - return when (this) { - BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED -> "ERROR_BLUETOOTH_NOT_ENABLED" - BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED -> "ERROR_BLUETOOTH_NOT_ALLOWED" - BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED -> "ERROR_DEVICE_NOT_BONDED" - BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED -> "ERROR_GATT_WRITE_NOT_ALLOWED" - BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY -> "ERROR_GATT_WRITE_REQUEST_BUSY" - BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION -> "ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION" - BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND -> "ERROR_PROFILE_SERVICE_NOT_BOUND" - BluetoothStatusCodes.ERROR_UNKNOWN -> "ERROR_UNKNOWN" - BluetoothStatusCodes.FEATURE_NOT_CONFIGURED -> "FEATURE_NOT_CONFIGURED" - BluetoothStatusCodes.FEATURE_NOT_SUPPORTED -> "FEATURE_NOT_SUPPORTED" - BluetoothStatusCodes.FEATURE_SUPPORTED -> "FEATURE_SUPPORTED" - else -> "ErrorCode: $this" - } -} - -fun Int.parseGattErrorCode(): String? { - return when (this) { - BluetoothGatt.GATT_SUCCESS -> null - BluetoothGatt.GATT_READ_NOT_PERMITTED -> "GATT_READ_NOT_PERMITTED" - BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> "GATT_WRITE_NOT_PERMITTED" - BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION -> "GATT_INSUFFICIENT_AUTHENTICATION" - BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED -> "GATT_REQUEST_NOT_SUPPORTED" - BluetoothGatt.GATT_INVALID_OFFSET -> "GATT_INVALID_OFFSET" - BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION -> "GATT_INSUFFICIENT_AUTHORIZATION" - BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH -> "GATT_INVALID_ATTRIBUTE_LENGTH" - BluetoothGatt.GATT_INSUFFICIENT_ENCRYPTION -> "GATT_INSUFFICIENT_ENCRYPTION" - BluetoothGatt.GATT_CONNECTION_CONGESTED -> "GATT_CONNECTION_CONGESTED" - BluetoothGatt.GATT_FAILURE -> "GATT_FAILURE" - 0x01 -> "GATT_INVALID_HANDLE" - 0x04 -> "GATT_INVALID_PDU" - 0x09 -> "GATT_PREPARE_QUEUE_FULL" - 0x0a -> "GATT_ATTR_NOT_FOUND" - 0x0b -> "GATT_ATTR_NOT_LONG" - 0x0c -> "GATT_INSUFFICIENT_KEY_SIZE" - 0x0e -> "GATT_UNLIKELY" - 0x10 -> "GATT_UNSUPPORTED_GROUP" - 0x11 -> "GATT_INSUFFICIENT_RESOURCES" - else -> "Unknown Error: $this" - } -} - -val ScanResult.manufacturerDataList: List - get() { - return scanRecord?.manufacturerSpecificData?.toList()?.map { (key, value) -> - UniversalManufacturerData(key.toLong(), value) - } ?: emptyList() - } - -fun SparseArray.toList(): List> { - return (0 until size()).map { index -> - keyAt(index) to valueAt(index) - } -} - -fun BluetoothGatt.getCharacteristic( - service: String, - characteristic: String, -): BluetoothGattCharacteristic? { - return getService(UUID.fromString(service))?.getCharacteristic(UUID.fromString(characteristic)) -} - -fun subscriptionFailedError(error: String? = null): Result { - return Result.failure( - FlutterError( - "Failed", - "Failed to update subscription state", - error - ) - ) -} - -fun BluetoothDevice.removeBond() { - try { - javaClass.getMethod("removeBond").invoke(this) - } catch (e: Exception) { - Log.e(TAG, "Removing bond failed. ${e.message}") - } -} - - -fun BluetoothGattCharacteristic.getPropertiesList(): ArrayList { - val propertiesList = arrayListOf() - if (properties and BluetoothGattCharacteristic.PROPERTY_BROADCAST > 0) { - propertiesList.add(CharacteristicProperty.Broadcast.value) - } - if (properties and BluetoothGattCharacteristic.PROPERTY_READ > 0) { - propertiesList.add(CharacteristicProperty.Read.value) - } - if (properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE > 0) { - propertiesList.add(CharacteristicProperty.WriteWithoutResponse.value) - } - if (properties and BluetoothGattCharacteristic.PROPERTY_WRITE > 0) { - propertiesList.add(CharacteristicProperty.Write.value) - } - if (properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) { - propertiesList.add(CharacteristicProperty.Notify.value) - } - if (properties and BluetoothGattCharacteristic.PROPERTY_INDICATE > 0) { - propertiesList.add(CharacteristicProperty.Indicate.value) - } - if (properties and BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE > 0) { - propertiesList.add(CharacteristicProperty.AuthenticatedSignedWrites.value) - } - if (properties and BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS > 0) { - propertiesList.add(CharacteristicProperty.ExtendedProperties.value) - } - return propertiesList -} - - -fun Short.toByteArray(byteOrder: ByteOrder = ByteOrder.LITTLE_ENDIAN): ByteArray = - ByteBuffer.allocate(2 /*Short.SIZE_BYTES*/).order(byteOrder).putShort(this).array() - -// Errors -fun unknownCharacteristicError(char: String) = - FlutterError("IllegalArgument", "Unknown error", null) - - -val DeviceDisconnectedError: FlutterError = FlutterError( - "DeviceDisconnected", - "Device Disconnected", - null -) - -fun Int.parseHciErrorCode(): String? { - return when (this) { - BluetoothGatt.GATT_SUCCESS -> null - 0x01 -> "Unknown HCI Command" - 0x02 -> "Unknown Connection Identifier" - 0x03 -> "Hardware Failure" - 0x04 -> "Page Timeout" - 0x05 -> "Authentication Failure" - 0x06 -> "PIN or Key Missing" - 0x07 -> "Memory Capacity Exceeded" - 0x08 -> "Connection Timeout" - 0x09 -> "Connection Limit Exceeded" - 0x0A -> "Synchronous Connection Limit To A Device Exceeded" - 0x0B -> "Connection Already Exists" - 0x0C -> "Command Disallowed" - 0x0D -> "Connection Rejected due to Limited Resources" - 0x0E -> "Connection Rejected Due To Security Reasons" - 0x0F -> "Connection Rejected due to Unacceptable BD_ADDR" - 0x10 -> "Connection Accept Timeout Exceeded" - 0x11 -> "Unsupported Feature or Parameter Value" - 0x12 -> "Invalid HCI Command Parameters" - 0x13 -> "Remote User Terminated Connection" - 0x14 -> "Remote Device Terminated Connection due to Low Resources" - 0x15 -> "Remote Device Terminated Connection due to Power Off" - 0x16 -> "Connection Terminated By Local Host" - 0x17 -> "Repeated Attempts" - 0x18 -> "Pairing Not Allowed" - 0x19 -> "Unknown LMP PDU" - 0x1A -> "Unsupported Remote Feature / Unsupported LMP Feature" - 0x1B -> "SCO Offset Rejected" - 0x1C -> "SCO Interval Rejected" - 0x1D -> "SCO Air Mode Rejected" - 0x1E -> "Invalid LMP Parameters / Invalid LL Parameters" - 0x1F -> "Unspecified Error" - 0x20 -> "Unsupported LMP Parameter Value / Unsupported LL Parameter Value" - 0x21 -> "Role Change Not Allowed" - 0x22 -> "LMP Response Timeout / LL Response Timeout" - 0x23 -> "LMP Error Transaction Collision / LL Procedure Collision" - 0x24 -> "LMP PDU Not Allowed" - 0x25 -> "Encryption Mode Not Acceptable" - 0x26 -> "Link Key cannot be Changed" - 0x27 -> "Requested QoS Not Supported" - 0x28 -> "Instant Passed" - 0x29 -> "Pairing With Unit Key Not Supported" - 0x2A -> "Different Transaction Collision" - 0x2B -> "Reserved for future use" - 0x2C -> "QoS Unacceptable Parameter" - 0x2D -> "QoS Rejected" - 0x2E -> "Channel Classification Not Supported" - 0x2F -> "Insufficient Security" - 0x30 -> "Parameter Out Of Mandatory Range" - 0x31 -> "Reserved for future use" - 0x32 -> "Role Switch Pending" - 0x33 -> "Reserved for future use" - 0x34 -> "Reserved Slot Violation" - 0x35 -> "Role Switch Failed" - 0x36 -> "Extended Inquiry Response Too Large" - 0x37 -> "Secure Simple Pairing Not Supported By Host" - 0x38 -> "Host Busy - Pairing" - 0x39 -> "Connection Rejected due to No Suitable Channel Found" - 0x3A -> "Controller Busy" - 0x3B -> "Unacceptable Connection Parameters" - 0x3C -> "Advertising Timeout" - 0x3D -> "Connection Terminated due to MIC Failure" - 0x3E -> "Connection Failed to be Established / Synchronization Timeout" - 0x3F -> "MAC Connection Failed" - 0x40 -> "Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging" - 0x41 -> "Type0 Submap Not Defined" - 0x42 -> "Unknown Advertising Identifier" - 0x43 -> "Limit Reached" - 0x44 -> "Operation Cancelled by Host" - 0x45 -> "Packet Too Long" - else -> "Unknown Error $this" - } -} - -// Future result classes -class DiscoverServicesFuture( - val deviceId: String, - val result: (Result>) -> Unit, -) - -class MtuResultFuture( - val deviceId: String, - val result: (Result) -> Unit, -) - -class ReadResultFuture( - val deviceId: String, - val characteristicId: String, - val serviceId: String, - val result: (Result) -> Unit, -) - -class WriteResultFuture( - val deviceId: String, - val characteristicId: String, - val serviceId: String, - val result: (Result) -> Unit, -) - -class SubscriptionResultFuture( - val deviceId: String, - val characteristicId: String, - val serviceId: String, - val result: (Result) -> Unit, -) \ No newline at end of file diff --git a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt b/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt deleted file mode 100644 index 3442916..0000000 --- a/universal_ble/android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt +++ /dev/null @@ -1,1045 +0,0 @@ -package com.navideck.universal_ble - -import android.annotation.SuppressLint -import android.app.Activity -import android.bluetooth.BluetoothAdapter -import android.bluetooth.BluetoothDevice -import android.bluetooth.BluetoothDevice.BOND_BONDED -import android.bluetooth.BluetoothGatt -import android.bluetooth.BluetoothGattCallback -import android.bluetooth.BluetoothGattCharacteristic -import android.bluetooth.BluetoothGattDescriptor -import android.bluetooth.BluetoothManager -import android.bluetooth.BluetoothProfile -import android.bluetooth.BluetoothStatusCodes -import android.bluetooth.le.ScanCallback -import android.bluetooth.le.ScanFilter -import android.bluetooth.le.ScanResult -import android.bluetooth.le.ScanSettings -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Context.RECEIVER_EXPORTED -import android.content.Intent -import android.content.IntentFilter -import android.os.Build -import android.os.Handler -import android.os.Looper -import android.util.Log -import io.flutter.embedding.engine.plugins.FlutterPlugin -import io.flutter.embedding.engine.plugins.activity.ActivityAware -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding -import io.flutter.plugin.common.PluginRegistry -import java.util.UUID -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit - - -private const val TAG = "UniversalBlePlugin" - -@SuppressLint("MissingPermission") -class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(), FlutterPlugin, - ActivityAware, PluginRegistry.ActivityResultListener { - private val bluetoothEnableRequestCode = 2342313 - private val bluetoothDisableRequestCode = 2342414 - private var callbackChannel: UniversalBleCallbackChannel? = null - private var mainThreadHandler: Handler? = null - private lateinit var context: Context - private var activity: Activity? = null - private lateinit var bluetoothManager: BluetoothManager - private lateinit var safeScanner: SafeScanner - private val cachedServicesMap = mutableMapOf>() - private val universalBleFilterUtil = UniversalBleFilterUtil() - - // Flutter Futures - private var bluetoothEnableRequestFuture: ((Result) -> Unit)? = null - private var bluetoothDisableRequestFuture: ((Result) -> Unit)? = null - private val discoverServicesFutureList = mutableListOf() - private val mtuResultFutureList = mutableListOf() - private val readResultFutureList = mutableListOf() - private val writeResultFutureList = mutableListOf() - private val subscriptionResultFutureList = mutableListOf() - private val pairResultFutures = mutableMapOf) -> Unit>() - - override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { - UniversalBlePlatformChannel.setUp(flutterPluginBinding.binaryMessenger, this) - callbackChannel = UniversalBleCallbackChannel(flutterPluginBinding.binaryMessenger) - context = flutterPluginBinding.applicationContext - mainThreadHandler = Handler(Looper.getMainLooper()) - bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - safeScanner = SafeScanner(bluetoothManager) - - val intentFilter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) - intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - context.registerReceiver(broadcastReceiver, intentFilter, RECEIVER_EXPORTED) - } else { - context.registerReceiver(broadcastReceiver, intentFilter) - } - cachedServicesMap.putAll(getCachedServicesMap()) - } - - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { - bluetoothManager.adapter.bluetoothLeScanner?.stopScan(scanCallback) - context.unregisterReceiver(broadcastReceiver) - callbackChannel = null - mainThreadHandler = null - } - - override fun getBluetoothAvailabilityState(callback: (Result) -> Unit) { - callback( - Result.success( - bluetoothManager.adapter?.state?.toAvailabilityState() - ?: AvailabilityState.Unknown.value - ) - ) - } - - override fun enableBluetooth(callback: (Result) -> Unit) { - if (bluetoothManager.adapter.isEnabled) { - callback(Result.success(true)) - return - } - if (bluetoothEnableRequestFuture != null) { - callback( - Result.failure( - FlutterError("Failed", "Bluetooth enable request in progress", null) - ) - ) - return - } - val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) - activity?.startActivityForResult(enableBtIntent, bluetoothEnableRequestCode) - bluetoothEnableRequestFuture = callback - } - - override fun disableBluetooth(callback: (Result) -> Unit) { - if (!bluetoothManager.adapter.isEnabled) { - callback(Result.success(true)) - return - } - if (bluetoothDisableRequestFuture != null) { - callback( - Result.failure( - FlutterError("Failed", "Bluetooth disable request in progress", null) - ) - ) - return - } - val disableBtIntent = Intent("android.bluetooth.adapter.action.REQUEST_DISABLE") - activity?.startActivityForResult(disableBtIntent, bluetoothDisableRequestCode) - bluetoothDisableRequestFuture = callback - } - - override fun startScan(filter: UniversalScanFilter?) { - if (!isBluetoothAvailable()) throw FlutterError( - "BluetoothNotEnabled", - "Bluetooth not enabled", - ) - - val builder = ScanSettings.Builder() - if (Build.VERSION.SDK_INT >= 26) { - builder.setPhy(ScanSettings.PHY_LE_ALL_SUPPORTED) - builder.setLegacy(false) - } - val settings = builder.build() - - val usesCustomFilters = filter?.usesCustomFilters() ?: false; - - try { - val filterServices = filter?.withServices?.filterNotNull()?.toUUIDList() ?: emptyList() - var scanFilters = emptyList() - - // Set custom scan filter only if required - if (usesCustomFilters) { - Log.e(TAG, "Using Custom Filters") - universalBleFilterUtil.scanFilter = filter - universalBleFilterUtil.serviceFilterUUIDS = filterServices - } else { - universalBleFilterUtil.scanFilter = null - scanFilters = filter?.toScanFilters(filterServices) ?: emptyList() - } - - safeScanner.startScan( - scanFilters, settings, scanCallback - ) - } catch (e: Exception) { - throw FlutterError( - "illegalIllegalArgument", - "Failed to start Scan", - e.toString() - ) - } - } - - override fun stopScan() { - if (!isBluetoothAvailable()) throw FlutterError( - "BluetoothNotEnabled", - "Bluetooth not enabled", - ) - // check if already scanning - safeScanner.stopScan(scanCallback) - } - - override fun connect(deviceId: String) { - // If already connected, send connected message, - // if connecting, do nothing - deviceId.findGatt()?.let { - val currentState = bluetoothManager.getConnectionState(it.device, BluetoothProfile.GATT) - if (currentState == BluetoothGatt.STATE_CONNECTED) { - Log.e(TAG, "$deviceId Already connected") - mainThreadHandler?.post { - callbackChannel?.onConnectionChanged(deviceId, true, null) {} - } - return - } else if (currentState == BluetoothGatt.STATE_CONNECTING) { - throw FlutterError("Connecting", "Connection already in progress", null) - } - } - - - val remoteDevice = bluetoothManager.adapter.getRemoteDevice(deviceId) - val gatt = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - remoteDevice.connectGatt( - context, - false, - this, - BluetoothDevice.TRANSPORT_LE - ) - } else { - remoteDevice.connectGatt(context, false, this) - } - gatt.saveCacheIfNeeded() - } - - override fun disconnect(deviceId: String) { - cleanConnection(deviceId.toBluetoothGatt()) - } - - override fun getConnectionState(deviceId: String): Long { - val connectionState = bluetoothManager.getConnectionState( - bluetoothManager.adapter.getRemoteDevice(deviceId), - BluetoothProfile.GATT - ) - - return if (deviceId.isKnownGatt() || connectionState == BluetoothGatt.STATE_DISCONNECTED || connectionState == BluetoothGatt.STATE_DISCONNECTING) { - connectionState.toBleConnectionState().value - } else { - // Might be connected with device, but not with app - Log.e(TAG, "Device might be connected but not known to this app") - BleConnectionState.Disconnected.value - } - } - - override fun discoverServices( - deviceId: String, - callback: (Result>) -> Unit, - ) { - try { - val gatt = deviceId.toBluetoothGatt() - if (gatt.discoverServices()) { - discoverServicesFutureList.add(DiscoverServicesFuture(deviceId, callback)) - } else { - callback( - Result.failure(FlutterError("Failed", "Failed to discover services", null)) - ) - } - } catch (e: FlutterError) { - callback(Result.failure(e)) - } - } - - override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { - if (status != BluetoothGatt.GATT_SUCCESS) { - discoverServicesFutureList.filter { it.deviceId == gatt.device.address }.forEach { - discoverServicesFutureList.remove(it) - it.result( - Result.failure(FlutterError("Failed", "Failed to discover services", null)) - ) - } - return - } - setCachedServices(gatt.device.address, gatt.services.map { it.uuid.toString() }) - val universalBleServices = gatt.services.map { service -> - UniversalBleService( - uuid = service.uuid.toString(), - characteristics = service.characteristics.map { - UniversalBleCharacteristic( - uuid = it.uuid.toString(), - properties = it.getPropertiesList() - ) - } - ) - } - discoverServicesFutureList.filter { it.deviceId == gatt.device.address }.forEach { - discoverServicesFutureList.remove(it) - it.result(Result.success(universalBleServices)) - } - } - - - override fun setNotifiable( - deviceId: String, - service: String, - characteristic: String, - bleInputProperty: Long, - callback: (Result) -> Unit, - ) { - try { - val gatt = deviceId.toBluetoothGatt() - val gattCharacteristic: BluetoothGattCharacteristic? = - gatt.getCharacteristic(service, characteristic) - - if (gattCharacteristic == null) { - callback(subscriptionFailedError("characteristic not found")) - return - } - - val descriptor: BluetoothGattDescriptor? = - gattCharacteristic.getDescriptor(ccdCharacteristic) - - val bleInputPropertyEnum: BleInputProperty = - BleInputProperty.values().first { it.value == bleInputProperty } - - val (value, enable) = when (bleInputPropertyEnum) { - BleInputProperty.Notification -> BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE to true - BleInputProperty.Indication -> BluetoothGattDescriptor.ENABLE_INDICATION_VALUE to true - else -> BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE to false - } - - if (descriptor != null) { - // Some devices do not need CCCD to update - @Suppress("DEPRECATION") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - if (gatt.writeDescriptor(descriptor, value) != BluetoothStatusCodes.SUCCESS) { - callback(subscriptionFailedError("Failed to update descriptor")) - return - } - } else { - descriptor.value = value - if (!gatt.writeDescriptor(descriptor)) { - callback(subscriptionFailedError("Failed to update descriptor")) - return - } - } - } else { - Log.d("UniversalBle", "CCCD Descriptor not found") - } - - if (gatt.setCharacteristicNotification(gattCharacteristic, enable)) { - if (descriptor != null) { - subscriptionResultFutureList.add( - SubscriptionResultFuture( - gatt.device.address, - gattCharacteristic.uuid.toString(), - gattCharacteristic.service.uuid.toString(), - callback - ) - ) - } else { - callback(Result.success(Unit)) - } - } else { - callback(subscriptionFailedError()) - } - } catch (e: FlutterError) { - callback(Result.failure(e)) - } catch (e: Exception) { - callback(subscriptionFailedError(e.toString())) - } - } - - override fun readValue( - deviceId: String, - service: String, - characteristic: String, - callback: (Result) -> Unit, - ) { - try { - val gatt = deviceId.toBluetoothGatt() - val gattCharacteristic = gatt.getCharacteristic(service, characteristic) - if (gattCharacteristic == null) { - callback( - Result.failure(FlutterError("IllegalArgument", "Unknown characteristic", null)) - ) - return - } - if (!gatt.readCharacteristic(gattCharacteristic)) { - callback( - Result.failure(unknownCharacteristicError(characteristic)) - ) - return - } - - readResultFutureList.add( - ReadResultFuture( - gatt.device.address, - gattCharacteristic.uuid.toString(), - gattCharacteristic.service.uuid.toString(), - callback - ) - ) - } catch (e: FlutterError) { - callback(Result.failure(e)) - } catch (e: Exception) { - callback( - Result.failure( - FlutterError( - "Failed", - "Failed to read value", - e.toString() - ) - ) - ) - } - } - - override fun onCharacteristicRead( - gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - value: ByteArray, - status: Int, - ) { - readResultFutureList.filter { - it.deviceId == gatt.device.address && - it.characteristicId == characteristic.uuid.toString() && - it.serviceId == characteristic.service.uuid.toString() - }.forEach { - readResultFutureList.remove(it) - if (status == BluetoothGatt.GATT_SUCCESS) { - it.result(Result.success(value)) - } else { - it.result( - Result.failure( - FlutterError( - status.toString(), - "Failed to read: (${status.parseGattErrorCode()})", - null, - ) - ) - ) - } - - } - } - - override fun writeValue( - deviceId: String, - service: String, - characteristic: String, - value: ByteArray, - bleOutputProperty: Long, - callback: (Result) -> Unit, - ) { - try { - val gatt = deviceId.toBluetoothGatt() - val gattCharacteristic = gatt.getCharacteristic(service, characteristic) - if (gattCharacteristic == null) { - callback(Result.failure(unknownCharacteristicError(characteristic))) - return - } - - var writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT - if (bleOutputProperty == BleOutputProperty.withResponse.value) { - if (gattCharacteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE == 0) { - callback( - Result.failure( - FlutterError( - "IllegalArgument", - "Characteristic does not support write withResponse", - null - ) - ) - ) - return - } - writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT - } else if (bleOutputProperty == BleOutputProperty.withoutResponse.value) { - if (gattCharacteristic.properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE == 0) { - callback( - Result.failure( - FlutterError( - "IllegalArgument", - "Characteristic does not support write withoutResponse", - null - ) - ) - ) - return - } - writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE - } - - val result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - val writeResult = gatt.writeCharacteristic(gattCharacteristic, value, writeType) - writeResult == BluetoothGatt.GATT_SUCCESS - } else { - @Suppress("DEPRECATION") - gattCharacteristic.value = value - gattCharacteristic.writeType = writeType - @Suppress("DEPRECATION") - gatt.writeCharacteristic(gattCharacteristic) - } - - if (!result) { - callback(Result.failure(FlutterError("Failed", "Failed to write", null))) - return - } - - if (writeType == BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT) { - // wait for the result - writeResultFutureList.add( - WriteResultFuture( - gatt.device.address, - gattCharacteristic.uuid.toString(), - gattCharacteristic.service.uuid.toString(), - callback - ) - ) - } else { - callback(Result.success(Unit)) - } - } catch (e: FlutterError) { - callback(Result.failure(e)) - } - } - - override fun onCharacteristicWrite( - gatt: BluetoothGatt?, - characteristic: BluetoothGattCharacteristic, - status: Int, - ) { - writeResultFutureList.filter { - it.deviceId == gatt?.device?.address && - it.characteristicId == characteristic.uuid.toString() && - it.serviceId == characteristic.service.uuid.toString() - }.forEach { - writeResultFutureList.remove(it) - if (status == BluetoothGatt.GATT_SUCCESS) { - it.result(Result.success(Unit)) - } else { - it.result( - Result.failure( - FlutterError( - status.toString(), - "Failed to write: (${status.parseGattErrorCode()})", - null, - ) - ) - ) - } - } - } - - - override fun requestMtu(deviceId: String, expectedMtu: Long, callback: (Result) -> Unit) { - try { - val gatt = deviceId.toBluetoothGatt() - gatt.requestMtu(expectedMtu.toInt()) - mtuResultFutureList.add(MtuResultFuture(deviceId, callback)) - } catch (e: FlutterError) { - callback(Result.failure(e)) - } - } - - override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) { - val deviceId = gatt?.device?.address ?: return - mtuResultFutureList.filter { it.deviceId == deviceId }.forEach { - mtuResultFutureList.remove(it) - if (status == BluetoothGatt.GATT_SUCCESS) { - it.result(Result.success(mtu.toLong())) - } else { - it.result(Result.failure(FlutterError("Failed to change MTU", null, null))) - } - } - } - - override fun isPaired(deviceId: String, callback: (Result) -> Unit) { - val remoteDevice: BluetoothDevice = - bluetoothManager.adapter.getRemoteDevice(deviceId) - callback(Result.success(remoteDevice.bondState == BOND_BONDED)) - } - - override fun pair(deviceId: String, callback: (Result) -> Unit) { - try { - val remoteDevice = bluetoothManager.adapter.getRemoteDevice(deviceId) - val pendingFuture = pairResultFutures.remove(deviceId) - - // If already paired, return and complete pending futures - if (remoteDevice.bondState == BOND_BONDED) { - pendingFuture?.let { it(Result.success(true)) } - callback(Result.success(true)) - return - } - - // throw error if we already have a pending future - if (pendingFuture != null) { - callback( - Result.failure( - FlutterError( - "InProgress", - "Pairing already in progress", - null - ) - ) - ) - return - } - - // Make a Pair request and complete future from Pair Update intent - if (remoteDevice.createBond()) { - pairResultFutures[deviceId] = callback - } else { - callback(Result.failure(FlutterError("Failed", "Failed to pair", null))) - } - } catch (e: Exception) { - callback( - Result.failure( - FlutterError("Failed", e.toString(), null) - ) - ) - } - - } - - override fun unPair(deviceId: String) { - val remoteDevice: BluetoothDevice = - bluetoothManager.adapter.getRemoteDevice(deviceId) - if (remoteDevice.bondState == BOND_BONDED) { - remoteDevice.removeBond() - } - } - - override fun getSystemDevices( - withServices: List, - callback: (Result>) -> Unit, - ) { - var devices: List = - bluetoothManager.getConnectedDevices(BluetoothProfile.GATT) - if (withServices.isNotEmpty()) { - devices = filterDevicesByServices(devices, withServices) - } - callback( - Result.success( - devices.map { - UniversalBleScanResult( - name = it.name, - deviceId = it.address, - isPaired = it.bondState == BOND_BONDED, - manufacturerDataList = null, - rssi = null, - ) - } - ) - ) - } - - private fun filterDevicesByServices( - devices: List, - withServices: List, - ): List { - // If all devices have cached services - if (devices.all { cachedServicesMap[it.address] != null }) { - return devices.filter { device -> - cachedServicesMap[device.address]?.any { uuid -> withServices.contains(uuid) } == true - } - } - - // Else discover services off already connected devices - val latch = CountDownLatch(devices.size) - val resultMap = mutableMapOf() - - devices.forEach { device -> - discoverServicesOffAlreadyConnectedDevice(device) { uuids -> - resultMap[device.address] = - uuids?.any { uuid -> withServices.contains(uuid) } == true - latch.countDown() - } - } - - try { - val timeout = (devices.size * 2).toLong() - latch.await(timeout, TimeUnit.SECONDS) - } catch (e: InterruptedException) { - Thread.currentThread().interrupt() - } - - return devices.filter { resultMap[it.address] == true } - } - - private fun discoverServicesOffAlreadyConnectedDevice( - device: BluetoothDevice, - callback: (List?) -> Unit, - ) { - // Check if already cached - cachedServicesMap[device.address]?.let { - callback(it) - return - } - - // To avoid duplicate callback - var isUpdated = false - fun updateCallback(uuids: List?) { - if (isUpdated) return - callback(uuids) - isUpdated = true - } - - // If its a known gatt, just discover services - device.address.findGatt()?.let { gatt -> - gatt.services?.let { services -> - updateCallback(services.map { service -> service.uuid.toString() }) - return - } - - if (gatt.discoverServices()) { - discoverServicesFutureList.add( - DiscoverServicesFuture(device.address) { uuids: Result> -> - if (uuids.isSuccess) { - updateCallback(uuids.getOrNull()?.map { it.uuid }) - } else { - updateCallback(null) - } - } - ) - return - } - } - - // Else connect to Gatt, discover services, then disconnect - val callbackHandler = object : BluetoothGattCallback() { - override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { - if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED) { - if (gatt?.discoverServices() != true) { - updateCallback(null) - if (!device.address.isKnownGatt()) { - gatt?.disconnect() - } - } - } else { - updateCallback(null) - } - } - - override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { - if (status == BluetoothGatt.GATT_SUCCESS) { - val uuids = gatt?.services?.map { it.uuid.toString() } - if (uuids != null) { - setCachedServices(device.address, uuids) - } - updateCallback(uuids) - } - if (!device.address.isKnownGatt()) { - gatt?.disconnect() - } - } - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - device.connectGatt(context, false, callbackHandler, BluetoothDevice.TRANSPORT_LE) - } else { - device.connectGatt(context, false, callbackHandler) - } - } - - private fun cleanConnection(gatt: BluetoothGatt) { - gatt.removeCache() - gatt.disconnect() - - readResultFutureList.removeAll { - if (it.deviceId == gatt.device.address) { - it.result(Result.failure(DeviceDisconnectedError)) - true - } else { - false - } - } - writeResultFutureList.removeAll { - if (it.deviceId == gatt.device.address) { - it.result(Result.failure(DeviceDisconnectedError)) - true - } else { - false - } - } - subscriptionResultFutureList.removeAll { - if (it.deviceId == gatt.device.address) { - it.result(Result.failure(DeviceDisconnectedError)) - true - } else { - false - } - } - mtuResultFutureList.removeAll { - if (it.deviceId == gatt.device.address) { - it.result(Result.failure(DeviceDisconnectedError)) - true - } else { - false - } - } - discoverServicesFutureList.removeAll { - if (it.deviceId == gatt.device.address) { - it.result(Result.failure(DeviceDisconnectedError)) - true - } else { - false - } - } - } - - private fun onBondStateUpdate(deviceId: String, bonded: Boolean, error: String? = null) { - val future = pairResultFutures.remove(deviceId) - future?.let { it(Result.success(bonded)) } - mainThreadHandler?.post { - callbackChannel?.onPairStateChange(deviceId, bonded, error) {} - } - } - - private val broadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - if (intent.action == BluetoothAdapter.ACTION_STATE_CHANGED) { - mainThreadHandler?.post { - callbackChannel?.onAvailabilityChanged( - bluetoothManager.adapter?.state?.toAvailabilityState() - ?: AvailabilityState.Unknown.value - ) {} - } - } else if (intent.action == BluetoothDevice.ACTION_BOND_STATE_CHANGED) { - val device: BluetoothDevice? = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - intent.getParcelableExtra( - BluetoothDevice.EXTRA_DEVICE, - BluetoothDevice::class.java - ) - } else { - @Suppress("DEPRECATION") - intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) - } - if (device == null) { - Log.e(TAG, "No device found in ACTION_BOND_STATE_CHANGED intent") - return - } - // get pairing failed error - when (intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR)) { - BluetoothDevice.BOND_BONDING -> { - Log.v(TAG, "${device.address} BOND_BONDING") - } - - BluetoothDevice.BOND_BONDED -> { - onBondStateUpdate(device.address, true) - } - - BluetoothDevice.ERROR -> { - onBondStateUpdate(device.address, false, "Failed to Pair") - } - - BluetoothDevice.BOND_NONE -> { - Log.e(TAG, "${device.address} BOND_NONE") - onBondStateUpdate(device.address, false) - } - } - } - } - } - - - private val scanCallback = object : ScanCallback() { - override fun onScanFailed(errorCode: Int) { - Log.e(TAG, "OnScanFailed: ${errorCode.parseScanErrorMessage()}") - } - - override fun onScanResult(callbackType: Int, result: ScanResult) { - - // Log.v(TAG, "onScanResult: $result") - var serviceUuids: Array = arrayOf() - result.device.uuids?.forEach { - serviceUuids += it.uuid - } - result.scanRecord?.serviceUuids?.forEach { - if (!serviceUuids.contains(it.uuid)) { - serviceUuids += it.uuid - } - } - - val name = result.device.name - val manufacturerDataList = result.manufacturerDataList - - if (!universalBleFilterUtil.filterDevice( - name, - manufacturerDataList, - serviceUuids - ) - ) return - - - mainThreadHandler?.post { - callbackChannel?.onScanResult( - UniversalBleScanResult( - name = result.device.name, - deviceId = result.device.address, - isPaired = result.device.bondState == BOND_BONDED, - manufacturerDataList = manufacturerDataList, - rssi = result.rssi.toLong(), - services = serviceUuids.map { it.toString() }.toList() - ) - ) {} - } - } - - override fun onBatchScanResults(results: MutableList?) { - Log.v(TAG, "onBatchScanResults: $results") - } - } - - - override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { - Log.d( - TAG, - "onConnectionStateChange-> Status: $status ${status.parseHciErrorCode()}, NewState: $newState" - ) - - if (newState == BluetoothGatt.STATE_CONNECTED) { - mainThreadHandler?.post { - callbackChannel?.onConnectionChanged( - gatt.device.address, true, status.parseHciErrorCode() - ) {} - } - } else if (newState == BluetoothGatt.STATE_DISCONNECTED) { - cleanConnection(gatt) - mainThreadHandler?.post { - callbackChannel?.onConnectionChanged( - gatt.device.address, false, status.parseHciErrorCode() - ) {} - } - Log.d(TAG, "Closing gatt for ${gatt.device.name}") - gatt.close() - } - } - - override fun onCharacteristicChanged( - gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - value: ByteArray, - ) { - mainThreadHandler?.post { - callbackChannel?.onValueChanged( - deviceIdArg = gatt.device.address, - characteristicIdArg = characteristic.uuid.toString(), - valueArg = value - ) {} - } - } - - override fun onDescriptorWrite( - gatt: BluetoothGatt?, - descriptor: BluetoothGattDescriptor?, - status: Int, - ) { - super.onDescriptorWrite(gatt, descriptor, status) - if (descriptor?.uuid.toString() == ccdCharacteristic.toString()) { - val char: String? = descriptor?.characteristic?.uuid?.toString() - val service: String? = descriptor?.characteristic?.service?.uuid?.toString() - val deviceId: String? = gatt?.device?.address; - if (deviceId != null && char != null && service != null) { - updateSubscriptionState(deviceId, char, service, status) - } - } - } - - private fun updateSubscriptionState( - deviceId: String, - characteristic: String, - service: String, - status: Int, - ) { - subscriptionResultFutureList.filter { - it.deviceId == deviceId && - it.characteristicId == characteristic && - it.serviceId == service - }.forEach { - subscriptionResultFutureList.remove(it) - val error: String? = status.parseGattErrorCode() - if (error != null) { - it.result( - Result.failure( - FlutterError( - status.toString(), - "Failed to update subscription state: $error", - null, - ) - ) - ) - } else { - it.result(Result.success(Unit)) - } - } - } - - private fun isBluetoothAvailable(): Boolean { - return bluetoothManager.adapter.isEnabled - } - - private fun setCachedServices(deviceId: String, services: List) { - val cachedServicesSharedPref = context.getSharedPreferences( - "com.navideck.universal_ble.services", - Context.MODE_PRIVATE - ) - cachedServicesSharedPref.edit().putStringSet(deviceId, services.toSet()).apply() - cachedServicesMap[deviceId] = services - } - - private fun getCachedServicesMap(): Map> { - val cachedServicesSharedPref = context.getSharedPreferences( - "com.navideck.universal_ble.services", - Context.MODE_PRIVATE - ) - return cachedServicesSharedPref.all.mapValues { (_, value) -> - (value as? Set<*>)?.map { it.toString() } ?: emptyList() - } - } - - /// Depreciated Members, ( Requires to support older android devices ) - @Suppress("OVERRIDE_DEPRECATION", "DEPRECATION") - override fun onCharacteristicRead( - gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - status: Int, - ) { - onCharacteristicRead(gatt, characteristic, characteristic.value, status) - } - - @Suppress("OVERRIDE_DEPRECATION", "DEPRECATION") - override fun onCharacteristicChanged( - gatt: BluetoothGatt, - characteristic: BluetoothGattCharacteristic, - ) { - onCharacteristicChanged(gatt, characteristic, characteristic.value) - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { - if (requestCode == bluetoothEnableRequestCode) { - val future = bluetoothEnableRequestFuture ?: return false - future(Result.success(resultCode == Activity.RESULT_OK)) - bluetoothEnableRequestFuture = null - return true - } else if (requestCode == bluetoothDisableRequestCode) { - val future = bluetoothDisableRequestFuture ?: return false - future(Result.success(resultCode == Activity.RESULT_OK)) - bluetoothDisableRequestFuture = null - return true - } - return false - } - - override fun onAttachedToActivity(binding: ActivityPluginBinding) { - activity = binding.activity - binding.addActivityResultListener(this) - } - - override fun onDetachedFromActivity() { - activity = null - } - - override fun onDetachedFromActivityForConfigChanges() {} - override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {} -} \ No newline at end of file diff --git a/universal_ble/android/src/test/kotlin/com/navideck/universal_ble/UniversalBlePluginTest.kt b/universal_ble/android/src/test/kotlin/com/navideck/universal_ble/UniversalBlePluginTest.kt deleted file mode 100644 index 2040143..0000000 --- a/universal_ble/android/src/test/kotlin/com/navideck/universal_ble/UniversalBlePluginTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.navideck.universal_ble - -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import kotlin.test.Test -import org.mockito.Mockito - -/* - * This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation. - * - * Once you have built the plugin's example app, you can run these tests from the command - * line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or - * you can run them directly from IDEs that support JUnit such as Android Studio. - */ - -internal class UniversalBlePluginTest { - @Test - fun onMethodCall_getPlatformVersion_returnsExpectedValue() { - val plugin = UniversalBlePlugin() - - val call = MethodCall("getPlatformVersion", null) - val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java) - plugin.onMethodCall(call, mockResult) - - Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE) - } -} diff --git a/universal_ble/darwin/.gitignore b/universal_ble/darwin/.gitignore deleted file mode 100644 index 0c88507..0000000 --- a/universal_ble/darwin/.gitignore +++ /dev/null @@ -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 \ No newline at end of file diff --git a/universal_ble/darwin/Assets/.gitkeep b/universal_ble/darwin/Assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/universal_ble/darwin/Classes/UniversalBle.g.swift b/universal_ble/darwin/Classes/UniversalBle.g.swift deleted file mode 100644 index eb5424e..0000000 --- a/universal_ble/darwin/Classes/UniversalBle.g.swift +++ /dev/null @@ -1,729 +0,0 @@ -// Autogenerated from Pigeon (v22.6.1), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -import Foundation - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -/// Error class for passing custom error details to Dart side. -final class PigeonError: Error { - let code: String - let message: String? - let details: Any? - - init(code: String, message: String?, details: Any?) { - self.code = code - self.message = message - self.details = details - } - - var localizedDescription: String { - return - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" - } -} - -private func wrapResult(_ result: Any?) -> [Any?] { - return [result] -} - -private func wrapError(_ error: Any) -> [Any?] { - if let pigeonError = error as? PigeonError { - return [ - pigeonError.code, - pigeonError.message, - pigeonError.details, - ] - } - if let flutterError = error as? FlutterError { - return [ - flutterError.code, - flutterError.message, - flutterError.details, - ] - } - return [ - "\(error)", - "\(type(of: error))", - "Stacktrace: \(Thread.callStackSymbols)", - ] -} - -private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") -} - -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} - -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} - -/// Generated class from Pigeon that represents data sent in messages. -struct UniversalBleScanResult { - var deviceId: String - var name: String? = nil - var isPaired: Bool? = nil - var rssi: Int64? = nil - var manufacturerDataList: [UniversalManufacturerData]? = nil - var services: [String]? = nil - - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleScanResult? { - let deviceId = pigeonVar_list[0] as! String - let name: String? = nilOrValue(pigeonVar_list[1]) - let isPaired: Bool? = nilOrValue(pigeonVar_list[2]) - let rssi: Int64? = nilOrValue(pigeonVar_list[3]) - let manufacturerDataList: [UniversalManufacturerData]? = nilOrValue(pigeonVar_list[4]) - let services: [String]? = nilOrValue(pigeonVar_list[5]) - - return UniversalBleScanResult( - deviceId: deviceId, - name: name, - isPaired: isPaired, - rssi: rssi, - manufacturerDataList: manufacturerDataList, - services: services - ) - } - func toList() -> [Any?] { - return [ - deviceId, - name, - isPaired, - rssi, - manufacturerDataList, - services, - ] - } -} - -/// Generated class from Pigeon that represents data sent in messages. -struct UniversalBleService { - var uuid: String - var characteristics: [UniversalBleCharacteristic]? = nil - - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleService? { - let uuid = pigeonVar_list[0] as! String - let characteristics: [UniversalBleCharacteristic]? = nilOrValue(pigeonVar_list[1]) - - return UniversalBleService( - uuid: uuid, - characteristics: characteristics - ) - } - func toList() -> [Any?] { - return [ - uuid, - characteristics, - ] - } -} - -/// Generated class from Pigeon that represents data sent in messages. -struct UniversalBleCharacteristic { - var uuid: String - var properties: [Int64] - - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> UniversalBleCharacteristic? { - let uuid = pigeonVar_list[0] as! String - let properties = pigeonVar_list[1] as! [Int64] - - return UniversalBleCharacteristic( - uuid: uuid, - properties: properties - ) - } - func toList() -> [Any?] { - return [ - uuid, - properties, - ] - } -} - -/// Scan Filters -/// -/// Generated class from Pigeon that represents data sent in messages. -struct UniversalScanFilter { - var withServices: [String] - var withNamePrefix: [String] - var withManufacturerData: [UniversalManufacturerDataFilter] - - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> UniversalScanFilter? { - let withServices = pigeonVar_list[0] as! [String] - let withNamePrefix = pigeonVar_list[1] as! [String] - let withManufacturerData = pigeonVar_list[2] as! [UniversalManufacturerDataFilter] - - return UniversalScanFilter( - withServices: withServices, - withNamePrefix: withNamePrefix, - withManufacturerData: withManufacturerData - ) - } - func toList() -> [Any?] { - return [ - withServices, - withNamePrefix, - withManufacturerData, - ] - } -} - -/// Generated class from Pigeon that represents data sent in messages. -struct UniversalManufacturerDataFilter { - var companyIdentifier: Int64 - var data: FlutterStandardTypedData? = nil - var mask: FlutterStandardTypedData? = nil - - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerDataFilter? { - let companyIdentifier = pigeonVar_list[0] as! Int64 - let data: FlutterStandardTypedData? = nilOrValue(pigeonVar_list[1]) - let mask: FlutterStandardTypedData? = nilOrValue(pigeonVar_list[2]) - - return UniversalManufacturerDataFilter( - companyIdentifier: companyIdentifier, - data: data, - mask: mask - ) - } - func toList() -> [Any?] { - return [ - companyIdentifier, - data, - mask, - ] - } -} - -/// Generated class from Pigeon that represents data sent in messages. -struct UniversalManufacturerData { - var companyIdentifier: Int64 - var data: FlutterStandardTypedData - - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> UniversalManufacturerData? { - let companyIdentifier = pigeonVar_list[0] as! Int64 - let data = pigeonVar_list[1] as! FlutterStandardTypedData - - return UniversalManufacturerData( - companyIdentifier: companyIdentifier, - data: data - ) - } - func toList() -> [Any?] { - return [ - companyIdentifier, - data, - ] - } -} - -private class UniversalBlePigeonCodecReader: FlutterStandardReader { - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 129: - return UniversalBleScanResult.fromList(self.readValue() as! [Any?]) - case 130: - return UniversalBleService.fromList(self.readValue() as! [Any?]) - case 131: - return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?]) - case 132: - return UniversalScanFilter.fromList(self.readValue() as! [Any?]) - case 133: - return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?]) - case 134: - return UniversalManufacturerData.fromList(self.readValue() as! [Any?]) - default: - return super.readValue(ofType: type) - } - } -} - -private class UniversalBlePigeonCodecWriter: FlutterStandardWriter { - override func writeValue(_ value: Any) { - if let value = value as? UniversalBleScanResult { - super.writeByte(129) - super.writeValue(value.toList()) - } else if let value = value as? UniversalBleService { - super.writeByte(130) - super.writeValue(value.toList()) - } else if let value = value as? UniversalBleCharacteristic { - super.writeByte(131) - super.writeValue(value.toList()) - } else if let value = value as? UniversalScanFilter { - super.writeByte(132) - super.writeValue(value.toList()) - } else if let value = value as? UniversalManufacturerDataFilter { - super.writeByte(133) - super.writeValue(value.toList()) - } else if let value = value as? UniversalManufacturerData { - super.writeByte(134) - super.writeValue(value.toList()) - } else { - super.writeValue(value) - } - } -} - -private class UniversalBlePigeonCodecReaderWriter: FlutterStandardReaderWriter { - override func reader(with data: Data) -> FlutterStandardReader { - return UniversalBlePigeonCodecReader(data: data) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return UniversalBlePigeonCodecWriter(data: data) - } -} - -class UniversalBlePigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = UniversalBlePigeonCodec(readerWriter: UniversalBlePigeonCodecReaderWriter()) -} - - -/// Flutter -> Native -/// -/// Generated protocol from Pigeon that represents a handler of messages from Flutter. -protocol UniversalBlePlatformChannel { - func getBluetoothAvailabilityState(completion: @escaping (Result) -> Void) - func enableBluetooth(completion: @escaping (Result) -> Void) - func disableBluetooth(completion: @escaping (Result) -> Void) - func startScan(filter: UniversalScanFilter?) throws - func stopScan() throws - func connect(deviceId: String) throws - func disconnect(deviceId: String) throws - func setNotifiable(deviceId: String, service: String, characteristic: String, bleInputProperty: Int64, completion: @escaping (Result) -> Void) - func discoverServices(deviceId: String, completion: @escaping (Result<[UniversalBleService], Error>) -> Void) - func readValue(deviceId: String, service: String, characteristic: String, completion: @escaping (Result) -> Void) - func requestMtu(deviceId: String, expectedMtu: Int64, completion: @escaping (Result) -> Void) - func writeValue(deviceId: String, service: String, characteristic: String, value: FlutterStandardTypedData, bleOutputProperty: Int64, completion: @escaping (Result) -> Void) - func isPaired(deviceId: String, completion: @escaping (Result) -> Void) - func pair(deviceId: String, completion: @escaping (Result) -> Void) - func unPair(deviceId: String) throws - func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void) - func getConnectionState(deviceId: String) throws -> Int64 -} - -/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. -class UniversalBlePlatformChannelSetup { - static var codec: FlutterStandardMessageCodec { UniversalBlePigeonCodec.shared } - /// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: UniversalBlePlatformChannel?, messageChannelSuffix: String = "") { - let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let getBluetoothAvailabilityStateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - getBluetoothAvailabilityStateChannel.setMessageHandler { _, reply in - api.getBluetoothAvailabilityState { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - getBluetoothAvailabilityStateChannel.setMessageHandler(nil) - } - let enableBluetoothChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - enableBluetoothChannel.setMessageHandler { _, reply in - api.enableBluetooth { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - enableBluetoothChannel.setMessageHandler(nil) - } - let disableBluetoothChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disableBluetooth\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - disableBluetoothChannel.setMessageHandler { _, reply in - api.disableBluetooth { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - disableBluetoothChannel.setMessageHandler(nil) - } - let startScanChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - startScanChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let filterArg: UniversalScanFilter? = nilOrValue(args[0]) - do { - try api.startScan(filter: filterArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - startScanChannel.setMessageHandler(nil) - } - let stopScanChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - stopScanChannel.setMessageHandler { _, reply in - do { - try api.stopScan() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - stopScanChannel.setMessageHandler(nil) - } - let connectChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - connectChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - do { - try api.connect(deviceId: deviceIdArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - connectChannel.setMessageHandler(nil) - } - let disconnectChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - disconnectChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - do { - try api.disconnect(deviceId: deviceIdArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - disconnectChannel.setMessageHandler(nil) - } - let setNotifiableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - setNotifiableChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - let serviceArg = args[1] as! String - let characteristicArg = args[2] as! String - let bleInputPropertyArg = args[3] as! Int64 - api.setNotifiable(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg, bleInputProperty: bleInputPropertyArg) { result in - switch result { - case .success: - reply(wrapResult(nil)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - setNotifiableChannel.setMessageHandler(nil) - } - let discoverServicesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - discoverServicesChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - api.discoverServices(deviceId: deviceIdArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - discoverServicesChannel.setMessageHandler(nil) - } - let readValueChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - readValueChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - let serviceArg = args[1] as! String - let characteristicArg = args[2] as! String - api.readValue(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - readValueChannel.setMessageHandler(nil) - } - let requestMtuChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - requestMtuChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - let expectedMtuArg = args[1] as! Int64 - api.requestMtu(deviceId: deviceIdArg, expectedMtu: expectedMtuArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - requestMtuChannel.setMessageHandler(nil) - } - let writeValueChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - writeValueChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - let serviceArg = args[1] as! String - let characteristicArg = args[2] as! String - let valueArg = args[3] as! FlutterStandardTypedData - let bleOutputPropertyArg = args[4] as! Int64 - api.writeValue(deviceId: deviceIdArg, service: serviceArg, characteristic: characteristicArg, value: valueArg, bleOutputProperty: bleOutputPropertyArg) { result in - switch result { - case .success: - reply(wrapResult(nil)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - writeValueChannel.setMessageHandler(nil) - } - let isPairedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - isPairedChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - api.isPaired(deviceId: deviceIdArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - isPairedChannel.setMessageHandler(nil) - } - let pairChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - pairChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - api.pair(deviceId: deviceIdArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - pairChannel.setMessageHandler(nil) - } - let unPairChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - unPairChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - do { - try api.unPair(deviceId: deviceIdArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - unPairChannel.setMessageHandler(nil) - } - let getSystemDevicesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - getSystemDevicesChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let withServicesArg = args[0] as! [String] - api.getSystemDevices(withServices: withServicesArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - getSystemDevicesChannel.setMessageHandler(nil) - } - let getConnectionStateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - getConnectionStateChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let deviceIdArg = args[0] as! String - do { - let result = try api.getConnectionState(deviceId: deviceIdArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - getConnectionStateChannel.setMessageHandler(nil) - } - } -} -/// Native -> Flutter -/// -/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. -protocol UniversalBleCallbackChannelProtocol { - func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result) -> Void) - func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result) -> Void) - func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result) -> Void) - func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) - func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, error errorArg: String?, completion: @escaping (Result) -> Void) -} -class UniversalBleCallbackChannel: UniversalBleCallbackChannelProtocol { - private let binaryMessenger: FlutterBinaryMessenger - private let messageChannelSuffix: String - init(binaryMessenger: FlutterBinaryMessenger, messageChannelSuffix: String = "") { - self.binaryMessenger = binaryMessenger - self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - } - var codec: UniversalBlePigeonCodec { - return UniversalBlePigeonCodec.shared - } - func onAvailabilityChanged(state stateArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged\(messageChannelSuffix)" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([stateArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(Void())) - } - } - } - func onPairStateChange(deviceId deviceIdArg: String, isPaired isPairedArg: Bool, error errorArg: String?, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange\(messageChannelSuffix)" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([deviceIdArg, isPairedArg, errorArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(Void())) - } - } - } - func onScanResult(result resultArg: UniversalBleScanResult, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult\(messageChannelSuffix)" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([resultArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(Void())) - } - } - } - func onValueChanged(deviceId deviceIdArg: String, characteristicId characteristicIdArg: String, value valueArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged\(messageChannelSuffix)" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([deviceIdArg, characteristicIdArg, valueArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(Void())) - } - } - } - func onConnectionChanged(deviceId deviceIdArg: String, connected connectedArg: Bool, error errorArg: String?, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged\(messageChannelSuffix)" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([deviceIdArg, connectedArg, errorArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(Void())) - } - } - } -} diff --git a/universal_ble/darwin/Classes/UniversalBleFilterUtil.swift b/universal_ble/darwin/Classes/UniversalBleFilterUtil.swift deleted file mode 100644 index 9994a8d..0000000 --- a/universal_ble/darwin/Classes/UniversalBleFilterUtil.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// UniversalBleFilterUtil.swift -// universal_ble -// -// Created by Rohit Sangwan on 23/08/24. -// - -import CoreBluetooth -import Foundation - -public class UniversalBleFilterUtil { - var scanFilter: UniversalScanFilter? - var scanFilterServicesUUID: [CBUUID] = [] - - func filterDevice(name: String?, manufacturerData: UniversalManufacturerData?, services: [CBUUID]?) -> Bool { - guard let filter = scanFilter else { - return true - } - - let hasNamePrefixFilter = !filter.withNamePrefix.isEmpty - let hasServiceFilter = !filter.withServices.isEmpty - let hasManufacturerDataFilter = !filter.withManufacturerData.isEmpty - - // If there is no filter at all, then allow device - if !hasNamePrefixFilter && !hasServiceFilter && !hasManufacturerDataFilter { - return true - } - - // Else check one of the filter passes - return hasNamePrefixFilter && isNameMatchingFilters(filter: filter, name: name) || - hasServiceFilter && isServicesMatchingFilters(services: services) || - hasManufacturerDataFilter && isManufacturerDataMatchingFilters(scanFilter: filter, msd: manufacturerData) - } - - func isNameMatchingFilters(filter: UniversalScanFilter, name: String?) -> Bool { - let prefixFilters = filter.withNamePrefix.compactMap { $0 }.filter { !$0.isEmpty } - - guard !prefixFilters.isEmpty else { - return true - } - - guard let name = name, !name.isEmpty else { - return false - } - - return prefixFilters.contains { name.hasPrefix($0) } - } - - func isServicesMatchingFilters(services: [CBUUID]?) -> Bool { - let serviceFilters = Set(scanFilterServicesUUID.compactMap { $0 }) - - guard !serviceFilters.isEmpty else { - return true - } - - guard let services = services, !services.isEmpty else { - return false - } - - return !Set(services).isDisjoint(with: serviceFilters) - } - - func isManufacturerDataMatchingFilters(scanFilter: UniversalScanFilter, msd: UniversalManufacturerData?) -> Bool { - let filters = scanFilter.withManufacturerData.compactMap { $0 } - if filters.isEmpty { - return true - } - - guard let msd = msd else { - return false - } - - for filter in filters { - let companyIdentifier: Int64 = filter.companyIdentifier - if msd.companyIdentifier == companyIdentifier && findData(find: filter.data?.toData(), inData: msd.data.toData(), usingMask: filter.mask?.toData()) { - return true - } - } - return false - } - - func findData(find: Data?, inData data: Data, usingMask mask: Data?) -> Bool { - if let find = find { - // If mask is null, use a default mask of all 1s - let mask = mask ?? Data(repeating: 0xFF, count: find.count) - - // Ensure find & mask are same length - guard find.count == mask.count else { - return false - } - - for i in 0 ..< find.count { - // Perform bitwise AND with mask and then compare - if (find[i] & mask[i]) != (data[i] & mask[i]) { - return false - } - } - } - return true - } -} - -extension UniversalScanFilter { - var usesCustomFilters: Bool { - return !withManufacturerData.isEmpty || !withNamePrefix.isEmpty - } -} diff --git a/universal_ble/darwin/Classes/UniversalBleHelper.swift b/universal_ble/darwin/Classes/UniversalBleHelper.swift deleted file mode 100644 index 6eb35f4..0000000 --- a/universal_ble/darwin/Classes/UniversalBleHelper.swift +++ /dev/null @@ -1,203 +0,0 @@ -// -// UniversalBleHelper.swift -// universal_ble -// -// Created by Rohit Sangwan on 25/10/23. -// - -import CoreBluetooth -import Foundation -#if os(iOS) - import Flutter -#elseif os(OSX) - import FlutterMacOS -#endif - -enum BleInputProperty: Int { - case disabled = 0 - case notification = 1 - case indication = 2 -} - -enum BleOutputProperty: Int { - case withResponse = 0 - case withoutResponse = 1 -} - -enum BlueConnectionState: Int64 { - case connected = 0 - case disconnected = 1 - case connecting = 2 - case disconnecting = 3 -} - -enum AvailabilityState: Int64 { - case unknown = 0 - case resetting = 1 - case unsupported = 2 - case unauthorized = 3 - case poweredOff = 4 - case poweredOn = 5 -} - -enum CharacteristicProperty: Int64 { - case broadcast = 0 - case read = 1 - case writeWithoutResponse = 2 - case write = 3 - case notify = 4 - case indicate = 5 - case authenticatedSignedWrites = 6 - case extendedProperties = 7 -} - -extension CBCharacteristicProperties { - var toCharacteristicProperty: [Int64] { - var properties = [Int64]() - if contains(.broadcast) { - properties.append(CharacteristicProperty.broadcast.rawValue) - } - if contains(.read) { - properties.append(CharacteristicProperty.read.rawValue) - } - if contains(.writeWithoutResponse) { - properties.append(CharacteristicProperty.writeWithoutResponse.rawValue) - } - if contains(.write) { - properties.append(CharacteristicProperty.write.rawValue) - } - if contains(.notify) { - properties.append(CharacteristicProperty.notify.rawValue) - } - if contains(.indicate) { - properties.append(CharacteristicProperty.indicate.rawValue) - } - if contains(.authenticatedSignedWrites) { - properties.append(CharacteristicProperty.authenticatedSignedWrites.rawValue) - } - if contains(.extendedProperties) { - properties.append(CharacteristicProperty.extendedProperties.rawValue) - } - return properties - } -} - -extension CBManagerState { - func toAvailabilityState() -> AvailabilityState { - switch self { - case .unknown: - return AvailabilityState.unknown - case .resetting: - return AvailabilityState.resetting - case .unsupported: - return AvailabilityState.unsupported - case .unauthorized: - return AvailabilityState.unauthorized - case .poweredOff: - return AvailabilityState.poweredOff - case .poweredOn: - return AvailabilityState.poweredOn - @unknown default: - return AvailabilityState.unknown - } - } -} - -extension Error { - func toPigeonError() -> PigeonError { - let nsError = self as NSError - let errorCode: String = .init(nsError.code) - let errorDescription: String = nsError.localizedDescription - return PigeonError(code: errorCode, message: errorDescription, details: nil) - } -} - -public extension CBUUID { - var uuidStr: String { - uuidString.lowercased() - } -} - -public extension CBPeripheral { - // FIXME: https://forums.developer.apple.com/thread/84375 - var uuid: UUID { - value(forKey: "identifier") as! NSUUID as UUID - } - - func getCharacteristic(_ characteristic: String, of service: String) -> CBCharacteristic? { - let GSS_SUFFIX = "0000-1000-8000-00805f9b34fb" - let s = services?.first { - $0.uuid.uuidStr.lowercased() == service.lowercased() || service.lowercased() == "0000\($0.uuid.uuidStr)-\(GSS_SUFFIX)".lowercased() - } - let c = s?.characteristics?.first { - $0.uuid.uuidStr.lowercased() == characteristic.lowercased() || characteristic.lowercased() == "0000\($0.uuid.uuidStr)-\(GSS_SUFFIX)".lowercased() - } - return c - } - - func setNotifiable(_ bleInputProperty: String, for characteristic: String, of service: String) { - guard let characteristic = getCharacteristic(characteristic, of: service) else { - return - } - setNotifyValue(bleInputProperty != "disabled", for: characteristic) - } -} - -extension FlutterStandardTypedData { - func toData() -> Data { - return Data(data) - } -} - -// Future classes -class CharacteristicReadFuture { - let deviceId: String - let characteristicId: String - let serviceId: String? - let result: (Result) -> Void - - init(deviceId: String, characteristicId: String, serviceId: String?, result: @escaping (Result) -> Void) { - self.deviceId = deviceId - self.characteristicId = characteristicId - self.serviceId = serviceId - self.result = result - } -} - -class CharacteristicWriteFuture { - let deviceId: String - let characteristicId: String - let serviceId: String? - let result: (Result) -> Void - - init(deviceId: String, characteristicId: String, serviceId: String?, result: @escaping (Result) -> Void) { - self.deviceId = deviceId - self.characteristicId = characteristicId - self.serviceId = serviceId - self.result = result - } -} - -class CharacteristicNotifyFuture { - let deviceId: String - let characteristicId: String - let serviceId: String? - let result: (Result) -> Void - - init(deviceId: String, characteristicId: String, serviceId: String?, result: @escaping (Result) -> Void) { - self.deviceId = deviceId - self.characteristicId = characteristicId - self.serviceId = serviceId - self.result = result - } -} - -class DiscoverServicesFuture { - let deviceId: String - let result: (Result<[UniversalBleService], Error>) -> Void - - init(deviceId: String, result: @escaping (Result<[UniversalBleService], Error>) -> Void) { - self.deviceId = deviceId - self.result = result - } -} diff --git a/universal_ble/darwin/Classes/UniversalBlePlugin.swift b/universal_ble/darwin/Classes/UniversalBlePlugin.swift deleted file mode 100644 index f3707ab..0000000 --- a/universal_ble/darwin/Classes/UniversalBlePlugin.swift +++ /dev/null @@ -1,501 +0,0 @@ -import CoreBluetooth - -#if os(iOS) - import Flutter - import UIKit -#elseif os(OSX) - import Cocoa - import FlutterMacOS -#endif - -public class UniversalBlePlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - var messenger: FlutterBinaryMessenger - #if os(iOS) - messenger = registrar.messenger() - #elseif os(macOS) - messenger = registrar.messenger - #endif - let callbackChannel = UniversalBleCallbackChannel(binaryMessenger: messenger) - let api = BleCentralDarwin(callbackChannel: callbackChannel) - UniversalBlePlatformChannelSetup.setUp(binaryMessenger: messenger, api: api) - } -} - -private var discoveredPeripherals = [String: CBPeripheral]() - -private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentralManagerDelegate, CBPeripheralDelegate { - var callbackChannel: UniversalBleCallbackChannel - private var universalBleFilterUtil = UniversalBleFilterUtil() - private lazy var manager: CBCentralManager = .init(delegate: self, queue: nil) - private var availabilityStateUpdateHandlers: [(Result) -> Void] = [] - private var discoveredServicesProgressMap: [String: [UniversalBleService]] = [:] - private var characteristicReadFutures = [CharacteristicReadFuture]() - private var characteristicWriteFutures = [CharacteristicWriteFuture]() - private var characteristicNotifyFutures = [CharacteristicNotifyFuture]() - private var discoverServicesFutures = [DiscoverServicesFuture]() - - init(callbackChannel: UniversalBleCallbackChannel) { - self.callbackChannel = callbackChannel - super.init() - } - - func getBluetoothAvailabilityState(completion: @escaping (Result) -> Void) { - if manager.state != .unknown { - completion(.success(manager.state.toAvailabilityState().rawValue)) - } else { - availabilityStateUpdateHandlers.append(completion) - _ = manager - } - } - - func enableBluetooth(completion: @escaping (Result) -> Void) { - completion(Result.failure(PigeonError(code: "NotSupported", message: nil, details: nil))) - } - - func disableBluetooth(completion: @escaping (Result) -> Void) { - completion(Result.failure(PigeonError(code: "NotSupported", message: nil, details: nil))) - } - - func startScan(filter: UniversalScanFilter?) throws { - // If filter has any other filter other than official one - let usesCustomFilters = filter?.usesCustomFilters ?? false - - // Apply services filter - var withServices: [CBUUID] = try filter?.withServices.compactMap { $0 }.toCBUUID() ?? [] - - if usesCustomFilters { - print("Using Custom Filters") - universalBleFilterUtil.scanFilter = filter - universalBleFilterUtil.scanFilterServicesUUID = withServices - withServices = [] - } else { - universalBleFilterUtil.scanFilter = nil - universalBleFilterUtil.scanFilterServicesUUID = [] - } - - let options = [CBCentralManagerScanOptionAllowDuplicatesKey: true] - - manager.scanForPeripherals(withServices: withServices, options: options) - } - - func stopScan() throws { - manager.stopScan() - } - - func connect(deviceId: String) throws { - let peripheral = try deviceId.getPeripheral(manager: manager) - peripheral.delegate = self - manager.connect(peripheral) - } - - func disconnect(deviceId: String) throws { - let peripheral = try deviceId.getPeripheral(manager: manager) - if peripheral.state != CBPeripheralState.disconnected { - manager.cancelPeripheralConnection(peripheral) - } - cleanUpConnection(deviceId: deviceId) - } - - func getConnectionState(deviceId: String) throws -> Int64 { - let peripheral = try deviceId.getPeripheral(manager: manager) - switch peripheral.state { - case .connecting: - return BlueConnectionState.connecting.rawValue - case .connected: - return BlueConnectionState.connected.rawValue - case .disconnecting: - return BlueConnectionState.disconnecting.rawValue - case .disconnected: - return BlueConnectionState.disconnected.rawValue - @unknown default: - fatalError() - } - } - - func cleanUpConnection(deviceId: String) { - characteristicReadFutures.removeAll { future in - if future.deviceId == deviceId { - future.result( - Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil)) - ) - return true - } - return false - } - characteristicWriteFutures.removeAll { future in - if future.deviceId == deviceId { - future.result( - Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil)) - ) - return true - } - return false - } - characteristicNotifyFutures.removeAll { future in - if future.deviceId == deviceId { - future.result( - Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil)) - ) - return true - } - return false - } - discoverServicesFutures.removeAll { future in - if future.deviceId == deviceId { - future.result( - Result.failure(PigeonError(code: "DeviceDisconnected", message: "Device Disconnected", details: nil)) - ) - return true - } - return false - } - discoveredServicesProgressMap[deviceId] = nil - } - - func discoverServices(deviceId: String, completion: @escaping (Result<[UniversalBleService], Error>) -> Void) { - guard let peripheral = deviceId.findPeripheral(manager: manager) else { - completion( - Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil)) - ) - return - } - - if discoveredServicesProgressMap[deviceId] != nil { - print("Services discovery already in progress for :\(deviceId), waiting for completion.") - discoverServicesFutures.append(DiscoverServicesFuture(deviceId: deviceId, result: completion)) - return - } - - if let cachedServices = peripheral.services { - // If services already discovered no need to discover again - if !cachedServices.isEmpty { - // print("Services already cached for this peripheral") - discoverServicesFutures.append(DiscoverServicesFuture(deviceId: deviceId, result: completion)) - self.peripheral(peripheral, didDiscoverServices: nil) - return - } - } - - peripheral.discoverServices(nil) - discoverServicesFutures.append(DiscoverServicesFuture(deviceId: deviceId, result: completion)) - } - - private func onServicesDiscovered(deviceId: String, services: [UniversalBleService]) { - discoverServicesFutures.removeAll { future in - if future.deviceId == deviceId { - future.result(Result.success(services)) - return true - } - return false - } - } - - func setNotifiable(deviceId: String, service: String, characteristic: String, bleInputProperty: Int64, completion: @escaping (Result) -> Void) { - guard let peripheral = deviceId.findPeripheral(manager: manager) else { - completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))) - return - } - - guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else { - completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil))) - return - } - - if bleInputProperty == BleInputProperty.notification.rawValue && !gattCharacteristic.properties.contains(.notify) { - completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support notify", details: nil))) - return - } - - if bleInputProperty == BleInputProperty.indication.rawValue && !gattCharacteristic.properties.contains(.indicate) { - /*completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support indicate", details: nil))) - return*/ - } - - let shouldNotify = bleInputProperty != BleInputProperty.disabled.rawValue - peripheral.setNotifyValue(shouldNotify, for: gattCharacteristic) - characteristicNotifyFutures.append(CharacteristicNotifyFuture(deviceId: deviceId, characteristicId: gattCharacteristic.uuid.uuidStr, serviceId: gattCharacteristic.service?.uuid.uuidStr, result: completion)) - } - - func readValue(deviceId: String, service: String, characteristic: String, completion: @escaping (Result) -> Void) { - guard let peripheral = deviceId.findPeripheral(manager: manager) else { - completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))) - return - } - guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else { - completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil))) - return - } - if !gattCharacteristic.properties.contains(.read) { - completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support read", details: nil))) - return - } - peripheral.readValue(for: gattCharacteristic) - characteristicReadFutures.append(CharacteristicReadFuture(deviceId: deviceId, characteristicId: gattCharacteristic.uuid.uuidStr, serviceId: gattCharacteristic.service?.uuid.uuidStr, result: completion)) - } - - func writeValue(deviceId: String, service: String, characteristic: String, value: FlutterStandardTypedData, bleOutputProperty: Int64, completion: @escaping (Result) -> Void) { - guard let peripheral = deviceId.findPeripheral(manager: manager) else { - completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))) - return - } - guard let gattCharacteristic = peripheral.getCharacteristic(characteristic, of: service) else { - completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown characteristic:\(characteristic)", details: nil))) - return - } - - let type = bleOutputProperty == BleOutputProperty.withoutResponse.rawValue ? CBCharacteristicWriteType.withoutResponse : CBCharacteristicWriteType.withResponse - - if type == CBCharacteristicWriteType.withResponse { - if !gattCharacteristic.properties.contains(.write) { - completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support write withResponse", details: nil))) - return - } - } else if type == CBCharacteristicWriteType.withoutResponse { - if !gattCharacteristic.properties.contains(.writeWithoutResponse) { - completion(Result.failure(PigeonError(code: "InvalidAction", message: "Characteristic does not support write withoutResponse", details: nil))) - return - } - } - peripheral.writeValue(value.data, for: gattCharacteristic, type: type) - - if type == CBCharacteristicWriteType.withResponse { - // Wait for future response - characteristicWriteFutures.append(CharacteristicWriteFuture(deviceId: deviceId, characteristicId: gattCharacteristic.uuid.uuidStr, serviceId: gattCharacteristic.service?.uuid.uuidStr, result: completion)) - } else { - completion(Result.success({}())) - } - } - - func requestMtu(deviceId: String, expectedMtu _: Int64, completion: @escaping (Result) -> Void) { - guard let peripheral = deviceId.findPeripheral(manager: manager) else { - completion(Result.failure(PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil))) - return - } - let mtu = peripheral.maximumWriteValueLength(for: CBCharacteristicWriteType.withoutResponse) - let GATT_HEADER_LENGTH = 3 - let mtuResult = Int64(mtu + GATT_HEADER_LENGTH) - completion(Result.success(mtuResult)) - } - - func isPaired(deviceId _: String, completion: @escaping (Result) -> Void) { - completion(Result.failure(PigeonError(code: "NotSupported", message: nil, details: nil))) - } - - func pair(deviceId _: String, completion: @escaping (Result) -> Void) { - completion(Result.failure(PigeonError(code: "Implemented in Dart", message: nil, details: nil))) - } - - func unPair(deviceId _: String) throws { - throw PigeonError(code: "NotSupported", message: nil, details: nil) - } - - func getSystemDevices(withServices: [String], completion: @escaping (Result<[UniversalBleScanResult], Error>) -> Void) { - var servicesFilter = withServices - if servicesFilter.isEmpty { - print("No services filter was set for getting system connected devices. Using default services...") - - // Add several generic services - servicesFilter = ["1800", "1801", "180A", "180D", "1810", "181B", "1808", "181D", "1816", "1814", "181A", "1802", "1803", "1804", "1815", "1805", "1807", "1806", "1848", "185E", "180F", "1812", "180E", "1813"] - } - var filterCBUUID = servicesFilter.map { CBUUID(string: $0) } - let bleDevices = manager.retrieveConnectedPeripherals(withServices: filterCBUUID) - bleDevices.forEach { $0.saveCache() } - completion(Result.success(bleDevices.map { - UniversalBleScanResult( - deviceId: $0.uuid.uuidString, - name: $0.name ?? "" - ) - })) - } - - func centralManagerDidUpdateState(_ central: CBCentralManager) { - let state = central.state.toAvailabilityState().rawValue - callbackChannel.onAvailabilityChanged(state: state) { _ in } - // Complete Pending state handler - availabilityStateUpdateHandlers.removeAll { handler in - handler(.success(state)) - return true - } - } - - public func centralManager(_: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) { - // Store the discovered peripheral using its UUID as the key - peripheral.saveCache() - - // Extract manufacturer data and service UUIDs from the advertisement data - let manufacturerData = advertisementData[CBAdvertisementDataManufacturerDataKey] as? Data - let services = (advertisementData[CBAdvertisementDataServiceUUIDsKey] as? [CBUUID]) - - var manufacturerDataList: [UniversalManufacturerData] = [] - var universalManufacturerData: UniversalManufacturerData? = nil - - if let msd = manufacturerData, msd.count > 2 { - let companyIdentifier = msd.prefix(2).withUnsafeBytes { $0.load(as: UInt16.self) } - let data = FlutterStandardTypedData(bytes: msd.suffix(from: 2)) - universalManufacturerData = UniversalManufacturerData(companyIdentifier: Int64(companyIdentifier), data: data) - manufacturerDataList.append(universalManufacturerData!) - } - - // Apply custom filters and return early if the peripheral doesn't match - if !universalBleFilterUtil.filterDevice(name: peripheral.name, manufacturerData: universalManufacturerData, services: services) { - return - } - - callbackChannel.onScanResult(result: UniversalBleScanResult( - deviceId: peripheral.uuid.uuidString, - name: peripheral.name, - isPaired: nil, - rssi: RSSI as? Int64, - manufacturerDataList: manufacturerDataList, - services: services?.map { $0.uuidStr } - )) { _ in } - } - - public func centralManager(_: CBCentralManager, didConnect peripheral: CBPeripheral) { - callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: true, error: nil) { _ in } - } - - public func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error _: Error?) { - callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false, error: nil) { _ in } - cleanUpConnection(deviceId: peripheral.uuid.uuidString) - } - - public func centralManager(_: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { - callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false, error: error?.localizedDescription) { _ in } - cleanUpConnection(deviceId: peripheral.uuid.uuidString) - } - - public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices _: Error?) { - let deviceId = peripheral.identifier.uuidString - guard let services = peripheral.services else { - onServicesDiscovered(deviceId: deviceId, services: []) - return - } - discoveredServicesProgressMap[deviceId] = services.map { UniversalBleService(uuid: $0.uuid.uuidString, characteristics: nil) } - for service in services { - if let cachedChar = service.characteristics { - if !cachedChar.isEmpty { - self.peripheral(peripheral, didDiscoverCharacteristicsFor: service, error: nil) - continue - } - } - peripheral.discoverCharacteristics(nil, for: service) - } - } - - public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error _: Error?) { - let deviceId = peripheral.identifier.uuidString - var universalBleCharacteristicsList: [UniversalBleCharacteristic] = [] - for characteristic in service.characteristics ?? [] { - universalBleCharacteristicsList.append( - UniversalBleCharacteristic(uuid: characteristic.uuid.uuidString, properties: characteristic.properties.toCharacteristicProperty)) - } - // Update discoveredServicesProgressMap - if let index = discoveredServicesProgressMap[deviceId]?.firstIndex(where: { $0.uuid == service.uuid.uuidString }) { - discoveredServicesProgressMap[deviceId]?[index] = UniversalBleService(uuid: service.uuid.uuidString, characteristics: universalBleCharacteristicsList) - } - // Check if all services and their characteristics have been discovered - if discoveredServicesProgressMap[deviceId]?.allSatisfy({ $0.characteristics != nil }) ?? false { - onServicesDiscovered(deviceId: deviceId, services: discoveredServicesProgressMap[deviceId] ?? []) - discoveredServicesProgressMap[deviceId] = nil - } - } - - public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { - characteristicWriteFutures.removeAll { future in - if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr { - if let pigeonError = error?.toPigeonError() { - future.result(Result.failure(pigeonError)) - } else { - future.result(Result.success({}())) - } - return true - } - return false - } - } - - public func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) { - characteristicNotifyFutures.removeAll { future in - if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr { - if let pigeonError = error?.toPigeonError() { - future.result(Result.failure(pigeonError)) - } else { - future.result(Result.success({}())) - } - return true - } - return false - } - } - - public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { - // Update callbackChannel if notifying - if characteristic.isNotifying { - if let characteristicValue = characteristic.value { - callbackChannel.onValueChanged(deviceId: peripheral.uuid.uuidString, characteristicId: characteristic.uuid.uuidStr, value: FlutterStandardTypedData(bytes: characteristicValue)) { _ in } - } - } - - if characteristicReadFutures.count == 0 { - return - } - - // Update futures for readValue - characteristicReadFutures.removeAll { future in - if future.deviceId == peripheral.uuid.uuidString && future.characteristicId == characteristic.uuid.uuidStr && future.serviceId == characteristic.service?.uuid.uuidStr { - if let pigeonError = error?.toPigeonError() { - future.result(Result.failure(pigeonError)) - } else { - if let characteristicValue = characteristic.value { - future.result(Result.success(FlutterStandardTypedData(bytes: characteristicValue))) - } else { - future.result(Result.failure(PigeonError(code: "ReadFailed", message: "No value", details: nil))) - } - } - return true - } - return false - } - } -} - -extension CBPeripheral { - func saveCache(){ - discoveredPeripherals[self.uuid.uuidString] = self - } -} - -extension String { - func getPeripheral(manager: CBCentralManager) throws -> CBPeripheral { - guard let peripheral = findPeripheral(manager: manager) else { - throw PigeonError(code: "IllegalArgument", message: "Unknown deviceId:\(self)", details: nil) - } - return peripheral - } - - func findPeripheral(manager: CBCentralManager) -> CBPeripheral? { - if let peripheral = discoveredPeripherals[self] { - return peripheral - } - if let uuid = UUID(uuidString: self) { - let peripherals = manager.retrievePeripherals(withIdentifiers: [uuid]) - if let peripheral = peripherals.first { - return peripheral - } - } - return nil - } -} - -extension [String] { - func toCBUUID() throws -> [CBUUID] { - return try compactMap { serviceUUID in - guard UUID(uuidString: serviceUUID) != nil else { - throw PigeonError(code: "IllegalArgument", message: "Invalid service UUID:\(serviceUUID)", details: nil) - } - return CBUUID(string: serviceUUID) - } - } -} diff --git a/universal_ble/darwin/universal_ble.podspec b/universal_ble/darwin/universal_ble.podspec deleted file mode 100644 index bbae355..0000000 --- a/universal_ble/darwin/universal_ble.podspec +++ /dev/null @@ -1,25 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint universal_ble.podspec` to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'universal_ble' - 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.ios.dependency 'Flutter' - s.osx.dependency 'FlutterMacOS' - s.ios.deployment_target = '9.0' - s.osx.deployment_target = '10.12' - - # 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 diff --git a/universal_ble/example/.gitignore b/universal_ble/example/.gitignore deleted file mode 100644 index 29a5418..0000000 --- a/universal_ble/example/.gitignore +++ /dev/null @@ -1,47 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -/build/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release -.metadata \ No newline at end of file diff --git a/universal_ble/example/README.md b/universal_ble/example/README.md deleted file mode 100644 index d991add..0000000 --- a/universal_ble/example/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# universal_ble_example - -Demonstrates how to use the universal_ble plugin. diff --git a/universal_ble/example/analysis_options.yaml b/universal_ble/example/analysis_options.yaml deleted file mode 100644 index 0d29021..0000000 --- a/universal_ble/example/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/universal_ble/example/android/.gitignore b/universal_ble/example/android/.gitignore deleted file mode 100644 index 6f56801..0000000 --- a/universal_ble/example/android/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app -key.properties -**/*.keystore -**/*.jks diff --git a/universal_ble/example/android/app/build.gradle b/universal_ble/example/android/app/build.gradle deleted file mode 100644 index c3cbcfb..0000000 --- a/universal_ble/example/android/app/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -android { - namespace "com.navideck.universal_ble_example" - compileSdkVersion 34 - ndkVersion flutter.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - applicationId "com.navideck.universal_ble_example" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion 21 - targetSdkVersion 34 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies {} diff --git a/universal_ble/example/android/app/src/debug/AndroidManifest.xml b/universal_ble/example/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 399f698..0000000 --- a/universal_ble/example/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/universal_ble/example/android/app/src/main/AndroidManifest.xml b/universal_ble/example/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 725af88..0000000 --- a/universal_ble/example/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/universal_ble/example/android/app/src/main/kotlin/com/navideck/universal_ble_example/MainActivity.kt b/universal_ble/example/android/app/src/main/kotlin/com/navideck/universal_ble_example/MainActivity.kt deleted file mode 100644 index cf1d443..0000000 --- a/universal_ble/example/android/app/src/main/kotlin/com/navideck/universal_ble_example/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.navideck.universal_ble_example - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} diff --git a/universal_ble/example/android/app/src/main/res/drawable-v21/launch_background.xml b/universal_ble/example/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f..0000000 --- a/universal_ble/example/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/universal_ble/example/android/app/src/main/res/drawable/launch_background.xml b/universal_ble/example/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f..0000000 --- a/universal_ble/example/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/universal_ble/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/universal_ble/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4..0000000 Binary files a/universal_ble/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/universal_ble/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/universal_ble/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b7..0000000 Binary files a/universal_ble/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/universal_ble/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/universal_ble/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 09d4391..0000000 Binary files a/universal_ble/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/universal_ble/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/universal_ble/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d..0000000 Binary files a/universal_ble/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/universal_ble/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/universal_ble/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372e..0000000 Binary files a/universal_ble/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/universal_ble/example/android/app/src/main/res/values-night/styles.xml b/universal_ble/example/android/app/src/main/res/values-night/styles.xml deleted file mode 100644 index 06952be..0000000 --- a/universal_ble/example/android/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/universal_ble/example/android/app/src/main/res/values/styles.xml b/universal_ble/example/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef88..0000000 --- a/universal_ble/example/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/universal_ble/example/android/app/src/profile/AndroidManifest.xml b/universal_ble/example/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f698..0000000 --- a/universal_ble/example/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/universal_ble/example/android/build.gradle b/universal_ble/example/android/build.gradle deleted file mode 100644 index bc157bd..0000000 --- a/universal_ble/example/android/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/universal_ble/example/android/gradle.properties b/universal_ble/example/android/gradle.properties deleted file mode 100644 index 94adc3a..0000000 --- a/universal_ble/example/android/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M -android.useAndroidX=true -android.enableJetifier=true diff --git a/universal_ble/example/android/gradle/wrapper/gradle-wrapper.properties b/universal_ble/example/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 3c472b9..0000000 --- a/universal_ble/example/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/universal_ble/example/android/settings.gradle b/universal_ble/example/android/settings.gradle deleted file mode 100644 index 7d06449..0000000 --- a/universal_ble/example/android/settings.gradle +++ /dev/null @@ -1,25 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false - id "org.jetbrains.kotlin.android" version "1.7.10" apply false -} - -include ":app" \ No newline at end of file diff --git a/universal_ble/example/ios/.gitignore b/universal_ble/example/ios/.gitignore deleted file mode 100644 index 7a7f987..0000000 --- a/universal_ble/example/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/universal_ble/example/ios/Flutter/AppFrameworkInfo.plist b/universal_ble/example/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 7c56964..0000000 --- a/universal_ble/example/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 12.0 - - diff --git a/universal_ble/example/ios/Flutter/Debug.xcconfig b/universal_ble/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6..0000000 --- a/universal_ble/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/universal_ble/example/ios/Flutter/Release.xcconfig b/universal_ble/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bf..0000000 --- a/universal_ble/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/universal_ble/example/ios/Podfile b/universal_ble/example/ios/Podfile deleted file mode 100644 index d97f17e..0000000 --- a/universal_ble/example/ios/Podfile +++ /dev/null @@ -1,44 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '12.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/universal_ble/example/ios/Podfile.lock b/universal_ble/example/ios/Podfile.lock deleted file mode 100644 index 1b112c7..0000000 --- a/universal_ble/example/ios/Podfile.lock +++ /dev/null @@ -1,41 +0,0 @@ -PODS: - - device_info_plus (0.0.1): - - Flutter - - Flutter (1.0.0) - - integration_test (0.0.1): - - Flutter - - permission_handler_apple (9.1.1): - - Flutter - - universal_ble (0.0.1): - - Flutter - - FlutterMacOS - -DEPENDENCIES: - - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - - Flutter (from `Flutter`) - - integration_test (from `.symlinks/plugins/integration_test/ios`) - - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - - universal_ble (from `.symlinks/plugins/universal_ble/darwin`) - -EXTERNAL SOURCES: - device_info_plus: - :path: ".symlinks/plugins/device_info_plus/ios" - Flutter: - :path: Flutter - integration_test: - :path: ".symlinks/plugins/integration_test/ios" - permission_handler_apple: - :path: ".symlinks/plugins/permission_handler_apple/ios" - universal_ble: - :path: ".symlinks/plugins/universal_ble/darwin" - -SPEC CHECKSUMS: - device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - integration_test: 13825b8a9334a850581300559b8839134b124670 - permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 - universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6 - -PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 - -COCOAPODS: 1.15.2 diff --git a/universal_ble/example/ios/Runner.xcodeproj/project.pbxproj b/universal_ble/example/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index ee051a4..0000000 --- a/universal_ble/example/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,724 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3C020DDC565FF8D37F3235C5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E92536821956EA00892DD639 /* Pods_Runner.framework */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - B2742FE9E6C1C51A78D26865 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AB88605F389EEED340E5872 /* Pods_RunnerTests.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0D9A3CA727A1375BDCCC70CF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 30B9BF32CD25D1ECB8BB5DCA /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 411AF23EC127806AE083685B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 4414252E2351EBDB7761F83A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 6CF659084054FE2807275A3A /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9AB88605F389EEED340E5872 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A11EED44BE0324AD23055698 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - E92536821956EA00892DD639 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 8EE4584064C335A1F66BB6D9 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - B2742FE9E6C1C51A78D26865 /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3C020DDC565FF8D37F3235C5 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 68033A1F47BF85C19A1ED513 /* Frameworks */ = { - isa = PBXGroup; - children = ( - E92536821956EA00892DD639 /* Pods_Runner.framework */, - 9AB88605F389EEED340E5872 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - FAF8A3758B0770B81319B3AE /* Pods */, - 68033A1F47BF85C19A1ED513 /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; - FAF8A3758B0770B81319B3AE /* Pods */ = { - isa = PBXGroup; - children = ( - 30B9BF32CD25D1ECB8BB5DCA /* Pods-Runner.debug.xcconfig */, - 4414252E2351EBDB7761F83A /* Pods-Runner.release.xcconfig */, - A11EED44BE0324AD23055698 /* Pods-Runner.profile.xcconfig */, - 411AF23EC127806AE083685B /* Pods-RunnerTests.debug.xcconfig */, - 0D9A3CA727A1375BDCCC70CF /* Pods-RunnerTests.release.xcconfig */, - 6CF659084054FE2807275A3A /* Pods-RunnerTests.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 7E79F47357B64513A488AC3E /* [CP] Check Pods Manifest.lock */, - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - 8EE4584064C335A1F66BB6D9 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 3CE2E408302E9BF272A3BE07 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 2F5EDC3CC74E7431E4CB95DF /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 2F5EDC3CC74E7431E4CB95DF /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 3CE2E408302E9BF272A3BE07 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 7E79F47357B64513A488AC3E /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = QQAZR43YM7; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 411AF23EC127806AE083685B /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0D9A3CA727A1375BDCCC70CF /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6CF659084054FE2807275A3A /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = QQAZR43YM7; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = QQAZR43YM7; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/universal_ble/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/universal_ble/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/universal_ble/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 8e3ca5d..0000000 --- a/universal_ble/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/universal_ble/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/universal_ble/example/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc1..0000000 --- a/universal_ble/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/universal_ble/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/universal_ble/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/universal_ble/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/universal_ble/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/universal_ble/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/universal_ble/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/universal_ble/example/ios/Runner/AppDelegate.swift b/universal_ble/example/ios/Runner/AppDelegate.swift deleted file mode 100644 index 70693e4..0000000 --- a/universal_ble/example/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import UIKit -import Flutter - -@UIApplicationMain -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fa..0000000 --- a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada4..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 7353c41..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 797d452..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 6ed2d93..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cd7b00..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index fe73094..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 321773c..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 797d452..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 502f463..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 0ec3034..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 0ec3034..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index e9f5fea..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 84ac32a..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 8953cba..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 0467bf1..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2..0000000 --- a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ diff --git a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725..0000000 --- a/universal_ble/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/universal_ble/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/universal_ble/example/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c..0000000 --- a/universal_ble/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/universal_ble/example/ios/Runner/Base.lproj/Main.storyboard b/universal_ble/example/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c2851..0000000 --- a/universal_ble/example/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/universal_ble/example/ios/Runner/Info.plist b/universal_ble/example/ios/Runner/Info.plist deleted file mode 100644 index 3087325..0000000 --- a/universal_ble/example/ios/Runner/Info.plist +++ /dev/null @@ -1,53 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Universal BLE - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - universal_ble_example - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - NSBluetoothAlwaysUsageDescription - Discover Bluetooth devices - NSBluetoothPeripheralUsageDescription - Discover Bluetooth devices - - diff --git a/universal_ble/example/ios/Runner/Runner-Bridging-Header.h b/universal_ble/example/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a5..0000000 --- a/universal_ble/example/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/universal_ble/example/ios/RunnerTests/RunnerTests.swift b/universal_ble/example/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 344ed3e..0000000 --- a/universal_ble/example/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,26 +0,0 @@ -import Flutter -import UIKit -import XCTest - -@testable import universal_ble - -// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. -// -// See https://developer.apple.com/documentation/xctest for more information about using XCTest. - -class RunnerTests: XCTestCase { - - func testGetPlatformVersion() { - let plugin = UniversalBlePlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) - } - -} diff --git a/universal_ble/example/lib/data/mock_universal_ble.dart b/universal_ble/example/lib/data/mock_universal_ble.dart deleted file mode 100644 index 233e8c6..0000000 --- a/universal_ble/example/lib/data/mock_universal_ble.dart +++ /dev/null @@ -1,124 +0,0 @@ -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:universal_ble/universal_ble.dart'; - -/// Mock implementation of [UniversalBlePlatform] for testing -class MockUniversalBle extends UniversalBlePlatform { - final _mockBleDevice = BleDevice( - name: 'MockDevice', - deviceId: 'MockDeviceId', - rssi: 50, - manufacturerDataList: [], - ); - - Uint8List _serviceValue = utf8.encode('Result'); - - final BleService _mockService = BleService('180', [ - BleCharacteristic('180A', [ - CharacteristicProperty.read, - CharacteristicProperty.write, - CharacteristicProperty.notify, - ]), - ]); - - @override - Future startScan({ - ScanFilter? scanFilter, - PlatformConfig? platformConfig, - }) async => - updateScanResult(_mockBleDevice); - - @override - Future stopScan() async {} - - @override - Future connect(String deviceId, {Duration? connectionTimeout}) async { - updateConnection(deviceId, true); - } - - @override - Future disconnect(String deviceId) async { - updateConnection(deviceId, false); - } - - @override - Future> discoverServices(String deviceId) async { - return [_mockService]; - } - - @override - Future enableBluetooth() async { - await Future.delayed(const Duration(milliseconds: 500)); - return true; - } - - @override - Future getBluetoothAvailabilityState() async { - return AvailabilityState.poweredOn; - } - - @override - Future> getSystemDevices(List? withServices) async { - return []; - } - - @override - Future readValue( - String deviceId, - String service, - String characteristic, { - final Duration? timeout, - }) async { - await Future.delayed(const Duration(milliseconds: 500)); - return _serviceValue; - } - - @override - Future writeValue( - String deviceId, - String service, - String characteristic, - Uint8List value, - BleOutputProperty bleOutputProperty) async { - await Future.delayed(const Duration(milliseconds: 500)); - _serviceValue = value; - } - - @override - Future requestMtu(String deviceId, int expectedMtu) async { - await Future.delayed(const Duration(seconds: 1)); - return 512; - } - - @override - Future setNotifiable(String deviceId, String service, - String characteristic, BleInputProperty bleInputProperty) async {} - - @override - Future isPaired(String deviceId) async { - await Future.delayed(const Duration(milliseconds: 500)); - return true; - } - - @override - Future pair(String deviceId) async { - updatePairingState(deviceId, true); - return true; - } - - @override - Future unpair(String deviceId) async { - updatePairingState(deviceId, false); - } - - @override - Future getConnectionState(String deviceId) { - throw UnimplementedError(); - } - - @override - Future disableBluetooth() { - throw UnimplementedError(); - } -} diff --git a/universal_ble/example/lib/data/permission_handler.dart b/universal_ble/example/lib/data/permission_handler.dart deleted file mode 100644 index c98d056..0000000 --- a/universal_ble/example/lib/data/permission_handler.dart +++ /dev/null @@ -1,101 +0,0 @@ -// ignore_for_file: avoid_print - -import 'dart:async'; -import 'dart:io'; - -import 'package:device_info_plus/device_info_plus.dart'; -import 'package:flutter/foundation.dart'; -import 'package:permission_handler/permission_handler.dart'; - -/* - Required Permissions : - <-----------> - IOS : - - Bluetooth - <-----------> - Android : - if AndroidVersions < 12 - - Location - - Bluetooth - else - - Bluetooth Scan - - Bluetooth Connect - <-----------> - Macos : - <-----------> - Windows : None - <-----------> - Linux : None - <-----------> - Web : - Check if Browser Supports Bluetooth - */ -class PermissionHandler { - static Future arePermissionsGranted() async { - if (!isMobilePlatform) return true; - - var status = await _permissionStatus; - bool blePermissionGranted = status[0]; - bool locationPermissionGranted = status[1]; - - if (locationPermissionGranted && blePermissionGranted) return true; - - if (!blePermissionGranted) { - PermissionStatus blePermissionCheck = - await Permission.bluetooth.request(); - if (blePermissionCheck.isPermanentlyDenied) { - print("Bluetooth Permission Permanently Denied"); - openAppSettings(); - } - return false; - } - - if (!locationPermissionGranted) { - PermissionStatus locationPermissionCheck = - await Permission.location.request(); - if (locationPermissionCheck.isPermanentlyDenied) { - print("Location Permission Permanently Denied"); - openAppSettings(); - } - return false; - } - - return false; - } - - static Future> get _permissionStatus async { - bool blePermissionGranted = false; - bool locationPermissionGranted = false; - - if (await requiresExplicitAndroidBluetoothPermissions) { - bool bleConnectPermission = - (await Permission.bluetoothConnect.request()).isGranted; - bool bleScanPermission = - (await Permission.bluetoothScan.request()).isGranted; - - blePermissionGranted = bleConnectPermission && bleScanPermission; - locationPermissionGranted = true; - } else { - PermissionStatus permissionStatus = await Permission.bluetooth.request(); - blePermissionGranted = permissionStatus.isGranted; - locationPermissionGranted = await requiresLocationPermission - ? (await Permission.locationWhenInUse.request()).isGranted - : true; - } - return [blePermissionGranted, locationPermissionGranted]; - } - - static bool get isMobilePlatform => - !kIsWeb && (Platform.isAndroid || Platform.isIOS); - - static Future get requiresLocationPermission async => - !kIsWeb && - Platform.isAndroid && - (!await requiresExplicitAndroidBluetoothPermissions); - - static Future get requiresExplicitAndroidBluetoothPermissions async { - if (kIsWeb || !Platform.isAndroid) return false; - AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo; - return androidInfo.version.sdkInt >= 31; - } -} diff --git a/universal_ble/example/lib/home/home.dart b/universal_ble/example/lib/home/home.dart deleted file mode 100644 index 502df92..0000000 --- a/universal_ble/example/lib/home/home.dart +++ /dev/null @@ -1,282 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:universal_ble/universal_ble.dart'; -import 'package:universal_ble_example/data/mock_universal_ble.dart'; -import 'package:universal_ble_example/home/widgets/scan_filter_widget.dart'; -import 'package:universal_ble_example/home/widgets/scanned_devices_placeholder_widget.dart'; -import 'package:universal_ble_example/home/widgets/scanned_item_widget.dart'; -import 'package:universal_ble_example/data/permission_handler.dart'; -import 'package:universal_ble_example/peripheral_details/peripheral_detail_page.dart'; -import 'package:universal_ble_example/widgets/platform_button.dart'; -import 'package:universal_ble_example/widgets/responsive_buttons_grid.dart'; - -class MyApp extends StatefulWidget { - const MyApp({Key? key}) : super(key: key); - - @override - State createState() => _MyAppState(); -} - -class _MyAppState extends State { - final _bleDevices = []; - bool _isScanning = false; - QueueType _queueType = QueueType.global; - TextEditingController servicesFilterController = TextEditingController(); - TextEditingController namePrefixController = TextEditingController(); - TextEditingController manufacturerDataController = TextEditingController(); - - AvailabilityState? bleAvailabilityState; - ScanFilter? scanFilter; - - @override - void initState() { - super.initState(); - - /// Set mock instance for testing - if (const bool.fromEnvironment('MOCK')) { - UniversalBle.setInstance(MockUniversalBle()); - } - - /// Setup queue and timeout - UniversalBle.queueType = _queueType; - UniversalBle.timeout = const Duration(seconds: 10); - - UniversalBle.onAvailabilityChange = (state) { - setState(() { - bleAvailabilityState = state; - }); - }; - - UniversalBle.onScanResult = (result) { - // log(result.toString()); - int index = _bleDevices.indexWhere((e) => e.deviceId == result.deviceId); - if (index == -1) { - _bleDevices.add(result); - } else { - if (result.name == null && _bleDevices[index].name != null) { - result.name = _bleDevices[index].name; - } - _bleDevices[index] = result; - } - setState(() {}); - }; - - // UniversalBle.onQueueUpdate = (String id, int remainingItems) { - // debugPrint("Queue: $id RemainingItems: $remainingItems"); - // }; - } - - Future startScan() async { - await UniversalBle.startScan( - scanFilter: scanFilter, - ); - } - - Future _getSystemDevices() async { - // For macOS and iOS, it is recommended to set a filter to get system devices - if (defaultTargetPlatform == TargetPlatform.macOS || - defaultTargetPlatform == TargetPlatform.iOS && - (scanFilter?.withServices ?? []).isEmpty) { - showSnackbar( - "No services filter was set for getting system connected devices. Using default services..."); - } - - List devices = await UniversalBle.getSystemDevices( - withServices: scanFilter?.withServices, - ); - if (devices.isEmpty) { - showSnackbar("No System Connected Devices Found"); - } - setState(() { - _bleDevices.clear(); - _bleDevices.addAll(devices); - }); - } - - void _showScanFilterBottomSheet() { - showModalBottomSheet( - isScrollControlled: true, - context: context, - builder: (context) { - return ScanFilterWidget( - servicesFilterController: servicesFilterController, - namePrefixController: namePrefixController, - manufacturerDataController: manufacturerDataController, - onScanFilter: (ScanFilter? filter) { - setState(() { - scanFilter = filter; - }); - }, - ); - }, - ); - } - - void showSnackbar(message) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message.toString())), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Universal BLE'), - elevation: 4, - actions: [ - if (_isScanning) - const Padding( - padding: EdgeInsets.all(8.0), - child: SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - )), - ), - ], - ), - body: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: ResponsiveButtonsGrid( - children: [ - PlatformButton( - text: 'Start Scan', - onPressed: () async { - setState(() { - _bleDevices.clear(); - _isScanning = true; - }); - try { - await startScan(); - } catch (e) { - setState(() { - _isScanning = false; - }); - showSnackbar(e); - } - }, - ), - PlatformButton( - text: 'Stop Scan', - onPressed: () async { - await UniversalBle.stopScan(); - setState(() { - _isScanning = false; - }); - }, - ), - if (BleCapabilities.supportsBluetoothEnableApi) - bleAvailabilityState != AvailabilityState.poweredOn - ? PlatformButton( - text: 'Enable Bluetooth', - onPressed: () async { - bool isEnabled = - await UniversalBle.enableBluetooth(); - showSnackbar("BluetoothEnabled: $isEnabled"); - }, - ) - : PlatformButton( - text: 'Disable Bluetooth', - onPressed: () async { - bool isDisabled = - await UniversalBle.disableBluetooth(); - showSnackbar("BluetoothDisabled: $isDisabled"); - }, - ), - if (BleCapabilities.requiresRuntimePermission) - PlatformButton( - text: 'Check Permissions', - onPressed: () async { - bool hasPermissions = - await PermissionHandler.arePermissionsGranted(); - if (hasPermissions) { - showSnackbar("Permissions granted"); - } - }, - ), - if (BleCapabilities.supportsConnectedDevicesApi) - PlatformButton( - text: 'System Devices', - onPressed: _getSystemDevices, - ), - PlatformButton( - text: 'Queue: ${_queueType.name}', - onPressed: () { - setState(() { - _queueType = switch (_queueType) { - QueueType.global => QueueType.perDevice, - QueueType.perDevice => QueueType.none, - QueueType.none => QueueType.global, - }; - UniversalBle.queueType = _queueType; - }); - }, - ), - PlatformButton( - text: 'Scan Filters', - onPressed: _showScanFilterBottomSheet, - ), - if (_bleDevices.isNotEmpty) - PlatformButton( - text: 'Clear List', - onPressed: () { - setState(() { - _bleDevices.clear(); - }); - }, - ), - ], - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - 'Ble Availability : ${bleAvailabilityState?.name}', - ), - ), - ], - ), - const Divider(color: Colors.blue), - Expanded( - child: _isScanning && _bleDevices.isEmpty - ? const Center(child: CircularProgressIndicator.adaptive()) - : !_isScanning && _bleDevices.isEmpty - ? const ScannedDevicesPlaceholderWidget() - : ListView.separated( - itemCount: _bleDevices.length, - separatorBuilder: (context, index) => const Divider(), - itemBuilder: (context, index) { - BleDevice device = - _bleDevices[_bleDevices.length - index - 1]; - return ScannedItemWidget( - bleDevice: device, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PeripheralDetailPage( - device.deviceId, - device.name ?? "Unknown Peripheral", - ), - )); - UniversalBle.stopScan(); - setState(() { - _isScanning = false; - }); - }, - ); - }, - ), - ), - ], - ), - ); - } -} diff --git a/universal_ble/example/lib/home/widgets/scan_filter_widget.dart b/universal_ble/example/lib/home/widgets/scan_filter_widget.dart deleted file mode 100644 index cd21487..0000000 --- a/universal_ble/example/lib/home/widgets/scan_filter_widget.dart +++ /dev/null @@ -1,172 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:universal_ble/universal_ble.dart'; -import 'package:universal_ble_example/widgets/platform_button.dart'; - -class ScanFilterWidget extends StatefulWidget { - final Function(ScanFilter? filter) onScanFilter; - final TextEditingController servicesFilterController; - final TextEditingController namePrefixController; - final TextEditingController manufacturerDataController; - - const ScanFilterWidget({ - super.key, - required this.onScanFilter, - required this.servicesFilterController, - required this.namePrefixController, - required this.manufacturerDataController, - }); - - @override - State createState() => _ScanFilterWidgetState(); -} - -class _ScanFilterWidgetState extends State { - String? error; - - void applyFilter() { - setState(() { - error = null; - }); - try { - List serviceUUids = []; - List namePrefixes = []; - List manufacturerDataFilters = []; - - // Parse Services - if (widget.servicesFilterController.text.isNotEmpty) { - List services = widget.servicesFilterController.text.split(','); - for (String service in services) { - try { - serviceUUids.add(BleUuidParser.string(service.trim())); - } on FormatException catch (_) { - throw Exception("Invalid Service UUID $service"); - } - } - } - - // Parse Name Prefix - String namePrefix = widget.namePrefixController.text; - if (namePrefix.isNotEmpty) { - namePrefixes = namePrefix.split(',').map((e) => e.trim()).toList(); - } - - // Parse Manufacturer Data - String manufacturerDataText = widget.manufacturerDataController.text; - if (manufacturerDataText.isNotEmpty) { - List manufacturerData = manufacturerDataText.split(','); - for (String manufacturer in manufacturerData) { - int? companyIdentifier = int.tryParse(manufacturer); - if (companyIdentifier == null) { - throw Exception("Invalid Manufacturer Data $manufacturer"); - } - manufacturerDataFilters.add( - ManufacturerDataFilter(companyIdentifier: companyIdentifier)); - } - } - - if (serviceUUids.isEmpty && - namePrefixes.isEmpty && - manufacturerDataFilters.isEmpty) { - widget.onScanFilter(null); - } else { - widget.onScanFilter( - ScanFilter( - withServices: serviceUUids, - withNamePrefix: namePrefixes, - withManufacturerData: manufacturerDataFilters, - ), - ); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("Filters Applied")), - ); - } - Navigator.pop(context); - } catch (e) { - setState(() { - error = e.toString(); - }); - } - } - - void clearFilter() { - widget.servicesFilterController.clear(); - widget.namePrefixController.clear(); - widget.manufacturerDataController.clear(); - widget.onScanFilter(null); - Navigator.pop(context); - } - - @override - Widget build(BuildContext context) { - return Padding( - padding: MediaQuery.of(context).viewInsets.copyWith(left: 20, right: 20), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox(height: 20), - Center( - child: Text( - "Scan Filters", - style: Theme.of(context).textTheme.titleLarge, - ), - ), - const Text("Use comma to add multiple values"), - const Divider(), - const SizedBox(height: 10), - TextFormField( - controller: widget.namePrefixController, - maxLines: 2, - decoration: const InputDecoration( - labelText: "Name Prefixes", - border: OutlineInputBorder(), - ), - ), - const SizedBox(height: 10), - TextFormField( - controller: widget.servicesFilterController, - maxLines: 2, - decoration: const InputDecoration( - labelText: "Services", - border: OutlineInputBorder(), - ), - ), - const SizedBox(height: 10), - TextFormField( - controller: widget.manufacturerDataController, - maxLines: 2, - decoration: const InputDecoration( - labelText: "Manufacturer Data Company IDs", - border: OutlineInputBorder(), - ), - ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Expanded( - child: PlatformButton( - text: 'Apply', - onPressed: applyFilter, - ), - ), - const SizedBox(width: 10), - Expanded( - child: PlatformButton( - text: 'Clear', - onPressed: clearFilter, - ), - ), - ], - ), - const SizedBox(height: 10), - if (error != null) - Text( - error!, - style: const TextStyle(color: Colors.red), - ), - const SizedBox(height: 10), - ], - ), - ); - } -} diff --git a/universal_ble/example/lib/home/widgets/scanned_devices_placeholder_widget.dart b/universal_ble/example/lib/home/widgets/scanned_devices_placeholder_widget.dart deleted file mode 100644 index b0643c5..0000000 --- a/universal_ble/example/lib/home/widgets/scanned_devices_placeholder_widget.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; - -class ScannedDevicesPlaceholderWidget extends StatelessWidget { - const ScannedDevicesPlaceholderWidget({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return const Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.all(8.0), - child: Icon( - Icons.bluetooth, - color: Colors.grey, - size: 100, - ), - ), - Text( - 'Scan For Devices', - style: TextStyle(color: Colors.grey, fontSize: 22), - ) - ], - ); - } -} diff --git a/universal_ble/example/lib/home/widgets/scanned_item_widget.dart b/universal_ble/example/lib/home/widgets/scanned_item_widget.dart deleted file mode 100644 index 0ce70c6..0000000 --- a/universal_ble/example/lib/home/widgets/scanned_item_widget.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:universal_ble/universal_ble.dart'; - -class ScannedItemWidget extends StatelessWidget { - final BleDevice bleDevice; - final VoidCallback? onTap; - const ScannedItemWidget({super.key, required this.bleDevice, this.onTap}); - - @override - Widget build(BuildContext context) { - String? name = bleDevice.name; - List rawManufacturerData = bleDevice.manufacturerDataList; - ManufacturerData? manufacturerData; - if (rawManufacturerData.isNotEmpty) { - manufacturerData = rawManufacturerData.first; - } - if (name == null || name.isEmpty) name = 'N/A'; - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Card( - child: ListTile( - title: Text( - '$name (${bleDevice.rssi})', - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(bleDevice.deviceId), - Visibility( - visible: manufacturerData != null, - child: Text(manufacturerData.toString()), - ), - bleDevice.isPaired == true - ? const Text( - "Paired", - style: TextStyle(color: Colors.green), - ) - : const Text( - "Not Paired", - style: TextStyle(color: Colors.red), - ), - ], - ), - trailing: const Icon(Icons.arrow_forward_ios), - onTap: onTap, - ), - ), - ); - } -} diff --git a/universal_ble/example/lib/main.dart b/universal_ble/example/lib/main.dart deleted file mode 100644 index f31ddb1..0000000 --- a/universal_ble/example/lib/main.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:universal_ble_example/home/home.dart'; - -void main() { - runApp( - MaterialApp( - title: 'Universal BLE', - debugShowCheckedModeBanner: false, - darkTheme: ThemeData.dark(), - themeMode: ThemeMode.system, - home: const MyApp(), - ), - ); -} diff --git a/universal_ble/example/lib/peripheral_details/peripheral_detail_page.dart b/universal_ble/example/lib/peripheral_details/peripheral_detail_page.dart deleted file mode 100644 index c705848..0000000 --- a/universal_ble/example/lib/peripheral_details/peripheral_detail_page.dart +++ /dev/null @@ -1,495 +0,0 @@ -// ignore_for_file: avoid_print, depend_on_referenced_packages - -import 'dart:async'; - -import 'package:convert/convert.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:universal_ble/universal_ble.dart'; -import 'package:universal_ble_example/peripheral_details/widgets/result_widget.dart'; -import 'package:universal_ble_example/peripheral_details/widgets/services_list_widget.dart'; -import 'package:universal_ble_example/widgets/platform_button.dart'; -import 'package:universal_ble_example/widgets/responsive_buttons_grid.dart'; -import 'package:universal_ble_example/widgets/responsive_view.dart'; - -class PeripheralDetailPage extends StatefulWidget { - final String deviceId; - final String deviceName; - const PeripheralDetailPage(this.deviceId, this.deviceName, {Key? key}) - : super(key: key); - - @override - State createState() { - return _PeripheralDetailPageState(); - } -} - -class _PeripheralDetailPageState extends State { - bool isConnected = false; - GlobalKey valueFormKey = GlobalKey(); - List discoveredServices = []; - final List _logs = []; - final binaryCode = TextEditingController(); - - ({ - BleService service, - BleCharacteristic characteristic - })? selectedCharacteristic; - - @override - void initState() { - super.initState(); - UniversalBle.onConnectionChange = _handleConnectionChange; - UniversalBle.onValueChange = _handleValueChange; - UniversalBle.onPairingStateChange = _handlePairingStateChange; - } - - @override - void dispose() { - super.dispose(); - UniversalBle.onConnectionChange = null; - UniversalBle.onValueChange = null; - // Disconnect when leaving the page - if (isConnected) UniversalBle.disconnect(widget.deviceId); - } - - void _addLog(String type, dynamic data) { - setState(() { - _logs.add('$type: ${data.toString()}'); - }); - } - - void _handleConnectionChange( - String deviceId, - bool isConnected, - String? error, - ) { - print( - '_handleConnectionChange $deviceId, $isConnected ${error != null ? 'Error: $error' : ''}', - ); - setState(() { - if (deviceId == widget.deviceId) { - this.isConnected = isConnected; - } - }); - _addLog('Connection', isConnected ? "Connected" : "Disconnected"); - // Auto Discover Services - if (this.isConnected) { - _discoverServices(); - } - } - - void _handleValueChange( - String deviceId, String characteristicId, Uint8List value) { - String s = String.fromCharCodes(value); - String data = '$s\nraw : ${value.toString()}'; - print('_handleValueChange $deviceId, $characteristicId, $s'); - _addLog("Value", data); - } - - void _handlePairingStateChange(String deviceId, bool isPaired) { - print('isPaired $deviceId, $isPaired'); - _addLog("PairingStateChange - isPaired", isPaired); - } - - Future _discoverServices() async { - const webWarning = - "Note: Only services added in ScanFilter or WebOptions will be discovered"; - try { - var services = await UniversalBle.discoverServices(widget.deviceId); - print('${services.length} services discovered'); - print(services); - discoveredServices.clear(); - setState(() { - discoveredServices = services; - }); - - if (kIsWeb) { - _addLog( - "DiscoverServices", - '${services.length} services discovered,\n$webWarning', - ); - } - } catch (e) { - _addLog("DiscoverServicesError", '$e\n${kIsWeb ? webWarning : ""}'); - } - } - - Future _readValue() async { - if (selectedCharacteristic == null) return; - try { - Uint8List value = await UniversalBle.readValue( - widget.deviceId, - selectedCharacteristic!.service.uuid, - selectedCharacteristic!.characteristic.uuid, - ); - String s = String.fromCharCodes(value); - String data = '$s\nraw : ${value.toString()}'; - _addLog('Read', data); - } catch (e) { - _addLog('ReadError', e); - } - } - - Future _writeValue() async { - if (selectedCharacteristic == null || - !valueFormKey.currentState!.validate() || - binaryCode.text.isEmpty) { - return; - } - - Uint8List value; - try { - value = Uint8List.fromList(hex.decode(binaryCode.text)); - } catch (e) { - _addLog('WriteError', "Error parsing hex $e"); - return; - } - - try { - await UniversalBle.writeValue( - widget.deviceId, - selectedCharacteristic!.service.uuid, - selectedCharacteristic!.characteristic.uuid, - value, - _hasSelectedCharacteristicProperty( - [CharacteristicProperty.writeWithoutResponse]) - ? BleOutputProperty.withoutResponse - : BleOutputProperty.withResponse, - ); - _addLog('Write', value); - } catch (e) { - print(e); - _addLog('WriteError', e); - } - } - - Future _setBleInputProperty(BleInputProperty inputProperty) async { - if (selectedCharacteristic == null) return; - try { - if (inputProperty != BleInputProperty.disabled) { - List properties = - selectedCharacteristic!.characteristic.properties; - if (properties.contains(CharacteristicProperty.notify)) { - inputProperty = BleInputProperty.notification; - } else if (properties.contains(CharacteristicProperty.indicate)) { - inputProperty = BleInputProperty.indication; - } else { - throw 'No notify or indicate property'; - } - } - await UniversalBle.setNotifiable( - widget.deviceId, - selectedCharacteristic!.service.uuid, - selectedCharacteristic!.characteristic.uuid, - inputProperty, - ); - _addLog('BleInputProperty', inputProperty); - } catch (e) { - _addLog('NotifyError', e); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text("${widget.deviceName} - ${widget.deviceId}"), - elevation: 4, - actions: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Icon( - isConnected - ? Icons.bluetooth_connected - : Icons.bluetooth_disabled, - color: isConnected ? Colors.greenAccent : Colors.red, - size: 20, - ), - ) - ], - ), - body: ResponsiveView(builder: (_, DeviceType deviceType) { - return Row( - children: [ - if (deviceType == DeviceType.desktop) - Expanded( - flex: 1, - child: Container( - color: Theme.of(context).secondaryHeaderColor, - child: discoveredServices.isEmpty - ? const Center( - child: Text('No Services Discovered'), - ) - : ServicesListWidget( - discoveredServices: discoveredServices, - scrollable: true, - onTap: (BleService service, - BleCharacteristic characteristic) { - setState(() { - selectedCharacteristic = ( - service: service, - characteristic: characteristic - ); - }); - }, - ), - ), - ), - Expanded( - flex: 3, - child: Align( - alignment: Alignment.topCenter, - child: SingleChildScrollView( - child: Column( - children: [ - // Top buttons - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - PlatformButton( - text: 'Connect', - enabled: !isConnected, - onPressed: () async { - try { - await UniversalBle.connect( - widget.deviceId, - ); - _addLog("ConnectionResult", true); - } catch (e) { - _addLog('ConnectError (${e.runtimeType})', e); - } - }, - ), - PlatformButton( - text: 'Disconnect', - enabled: isConnected, - onPressed: () { - UniversalBle.disconnect(widget.deviceId); - }, - ), - ], - ), - ), - selectedCharacteristic == null - ? Text(discoveredServices.isEmpty - ? "Please discover services" - : "Please select a characteristic") - : Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - ), - child: Card( - child: ListTile( - title: SelectableText( - "Characteristic: ${selectedCharacteristic!.characteristic.uuid}", - ), - subtitle: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SelectableText( - "Service: ${selectedCharacteristic!.service.uuid}", - ), - Text( - "Properties: ${selectedCharacteristic!.characteristic.properties.map((e) => e.name)}", - ), - ], - ), - ), - ), - ), - - if (_hasSelectedCharacteristicProperty([ - CharacteristicProperty.write, - CharacteristicProperty.writeWithoutResponse - ])) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Form( - key: valueFormKey, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: TextFormField( - controller: binaryCode, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter a value'; - } - try { - hex.decode(binaryCode.text); - return null; - } catch (e) { - return 'Please enter a valid hex value ( without spaces or 0x (e.g. F0BB) )'; - } - }, - decoration: const InputDecoration( - hintText: - "Enter Hex values without spaces or 0x (e.g. F0BB)", - border: OutlineInputBorder(), - ), - ), - ), - ), - ), - const Divider(), - Padding( - padding: const EdgeInsets.all(8.0), - child: ResponsiveButtonsGrid( - children: [ - PlatformButton( - onPressed: () async { - _discoverServices(); - }, - enabled: isConnected, - text: 'Discover Services', - ), - PlatformButton( - onPressed: () async { - _addLog( - 'ConnectionState', - await UniversalBle.getConnectionState( - widget.deviceId, - ), - ); - }, - text: 'Connection State', - ), - if (BleCapabilities.supportsRequestMtuApi) - PlatformButton( - enabled: isConnected, - onPressed: () async { - int mtu = await UniversalBle.requestMtu( - widget.deviceId, 247); - _addLog('MTU', mtu); - }, - text: 'Request Mtu', - ), - PlatformButton( - enabled: isConnected && - discoveredServices.isNotEmpty && - _hasSelectedCharacteristicProperty([ - CharacteristicProperty.read, - ]), - onPressed: _readValue, - text: 'Read', - ), - PlatformButton( - enabled: isConnected && - discoveredServices.isNotEmpty && - _hasSelectedCharacteristicProperty([ - CharacteristicProperty.write, - CharacteristicProperty.writeWithoutResponse - ]), - onPressed: _writeValue, - text: 'Write', - ), - PlatformButton( - enabled: isConnected && - discoveredServices.isNotEmpty && - _hasSelectedCharacteristicProperty([ - CharacteristicProperty.notify, - CharacteristicProperty.indicate - ]), - onPressed: () => _setBleInputProperty( - BleInputProperty.notification), - text: 'Subscribe', - ), - PlatformButton( - enabled: isConnected && - discoveredServices.isNotEmpty && - _hasSelectedCharacteristicProperty([ - CharacteristicProperty.notify, - CharacteristicProperty.indicate - ]), - onPressed: () => _setBleInputProperty( - BleInputProperty.disabled), - text: 'Unsubscribe', - ), - PlatformButton( - enabled: BleCapabilities.supportsAllPairingKinds, - onPressed: () async { - try { - await UniversalBle.pair( - widget.deviceId, - // pairingCommand: BleCommand( - // service: "", - // characteristic: "", - // ), - ); - _addLog("Pairing Result", true); - } catch (e) { - _addLog('PairError (${e.runtimeType})', e); - } - }, - text: 'Pair', - ), - PlatformButton( - onPressed: () async { - bool? isPaired = await UniversalBle.isPaired( - widget.deviceId, - // pairingCommand: BleCommand( - // service: "", - // characteristic: "", - // ), - ); - _addLog('IsPaired', isPaired); - }, - text: 'IsPaired', - ), - PlatformButton( - onPressed: () async { - await UniversalBle.unpair(widget.deviceId); - }, - text: 'Unpair', - ), - ], - ), - ), - // Services - if (deviceType != DeviceType.desktop) - ServicesListWidget( - discoveredServices: discoveredServices, - onTap: (BleService service, - BleCharacteristic characteristic) { - setState(() { - selectedCharacteristic = ( - service: service, - characteristic: characteristic - ); - }); - }, - ), - const Divider(), - ResultWidget( - results: _logs, - onClearTap: (int? index) { - setState(() { - if (index != null) { - _logs.removeAt(index); - } else { - _logs.clear(); - } - }); - }), - const SizedBox(height: 20), - ], - ), - ), - ), - ), - ], - ); - }), - ); - } - - bool _hasSelectedCharacteristicProperty( - List properties) => - properties.any((property) => - selectedCharacteristic?.characteristic.properties - .contains(property) ?? - false); -} diff --git a/universal_ble/example/lib/peripheral_details/widgets/result_widget.dart b/universal_ble/example/lib/peripheral_details/widgets/result_widget.dart deleted file mode 100644 index d34f281..0000000 --- a/universal_ble/example/lib/peripheral_details/widgets/result_widget.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:flutter/material.dart'; - -class ResultWidget extends StatelessWidget { - final List results; - final bool scrollable; - final Function(int? index) onClearTap; - const ResultWidget({ - required this.results, - required this.onClearTap, - this.scrollable = false, - super.key, - }); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - if (results.isNotEmpty) - Padding( - padding: const EdgeInsets.all(8.0), - child: ListTile( - tileColor: Theme.of(context).secondaryHeaderColor, - title: const Text("Logs"), - onTap: () { - onClearTap(null); - }, - trailing: const Icon(Icons.clear), - ), - ), - ListView.separated( - shrinkWrap: !scrollable, - physics: scrollable ? null : const NeverScrollableScrollPhysics(), - itemCount: results.length, - reverse: true, - itemBuilder: (BuildContext context, int index) { - return InkWell( - onTap: () => onClearTap(index), - child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 11, vertical: 2), - child: Text(results[index]), - ), - ); - }, - separatorBuilder: (_, __) => const Divider(), - ), - ], - ); - } -} diff --git a/universal_ble/example/lib/peripheral_details/widgets/services_list_widget.dart b/universal_ble/example/lib/peripheral_details/widgets/services_list_widget.dart deleted file mode 100644 index a72ab57..0000000 --- a/universal_ble/example/lib/peripheral_details/widgets/services_list_widget.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:expandable/expandable.dart'; -import 'package:flutter/material.dart'; -import 'package:universal_ble/universal_ble.dart'; - -class ServicesListWidget extends StatelessWidget { - final List discoveredServices; - final bool scrollable; - final Function(BleService service, BleCharacteristic characteristic)? onTap; - - const ServicesListWidget({ - super.key, - required this.discoveredServices, - this.onTap, - this.scrollable = false, - }); - - @override - Widget build(BuildContext context) { - return ListView.builder( - shrinkWrap: !scrollable, - physics: scrollable ? null : const NeverScrollableScrollPhysics(), - itemCount: discoveredServices.length, - itemBuilder: (BuildContext context, int index) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Card( - child: ExpandablePanel( - header: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - const Icon(Icons.arrow_forward_ios), - Expanded(child: Text(discoveredServices[index].uuid)), - ], - ), - ), - collapsed: const SizedBox(), - expanded: Column( - children: discoveredServices[index] - .characteristics - .map((e) => Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - InkWell( - onTap: () { - onTap?.call(discoveredServices[index], e); - }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Icon(Icons.arrow_right_outlined), - Expanded(child: Text(e.uuid)), - ], - ), - Text( - "Properties: ${e.properties.map((e) => e.name)}", - ) - ], - ), - ), - ], - ), - )) - .toList(), - ), - ), - ), - ); - }, - ); - } -} diff --git a/universal_ble/example/lib/widgets/platform_button.dart b/universal_ble/example/lib/widgets/platform_button.dart deleted file mode 100644 index 47ba7f8..0000000 --- a/universal_ble/example/lib/widgets/platform_button.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -class PlatformButton extends StatelessWidget { - final String text; - final Function()? onPressed; - final bool enabled; - - const PlatformButton({ - required this.text, - required this.onPressed, - this.enabled = true, - super.key, - }); - - @override - Widget build(BuildContext context) { - return (!kIsWeb && (Platform.isMacOS || Platform.isIOS)) - ? CupertinoButton.filled( - onPressed: enabled ? onPressed : null, - // color: Colors.blue, - padding: const EdgeInsets.symmetric(horizontal: 10), - disabledColor: Colors.grey, - child: Text(text), - ) - : ElevatedButton( - onPressed: enabled ? onPressed : null, - child: Text(text), - ); - } -} diff --git a/universal_ble/example/lib/widgets/responsive_buttons_grid.dart b/universal_ble/example/lib/widgets/responsive_buttons_grid.dart deleted file mode 100644 index f453087..0000000 --- a/universal_ble/example/lib/widgets/responsive_buttons_grid.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; - -class ResponsiveButtonsGrid extends StatelessWidget { - final List children; - const ResponsiveButtonsGrid({super.key, required this.children}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - const tileWidth = 150; - const tileHeight = 500; - final count = constraints.maxWidth ~/ tileWidth; - return GridView.count( - crossAxisCount: count, - crossAxisSpacing: 8, - mainAxisSpacing: 8, - childAspectRatio: tileHeight / tileWidth, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - children: children, - ); - }, - ); - } -} diff --git a/universal_ble/example/lib/widgets/responsive_view.dart b/universal_ble/example/lib/widgets/responsive_view.dart deleted file mode 100644 index 2e5a88d..0000000 --- a/universal_ble/example/lib/widgets/responsive_view.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:flutter/material.dart'; - -enum DeviceType { - mobile, - tablet, - desktop, -} - -class ResponsiveView extends StatelessWidget { - final Widget Function(BuildContext context, DeviceType deviceType) builder; - const ResponsiveView({super.key, required this.builder}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (ctx, constraints) { - return builder( - ctx, - constraints.maxWidth > 1000 - ? DeviceType.desktop - : constraints.maxWidth > 600 && constraints.maxWidth < 1000 - ? DeviceType.tablet - : DeviceType.mobile, - ); - }, - ); - } -} diff --git a/universal_ble/example/linux/.gitignore b/universal_ble/example/linux/.gitignore deleted file mode 100644 index d3896c9..0000000 --- a/universal_ble/example/linux/.gitignore +++ /dev/null @@ -1 +0,0 @@ -flutter/ephemeral diff --git a/universal_ble/example/linux/CMakeLists.txt b/universal_ble/example/linux/CMakeLists.txt deleted file mode 100644 index b375099..0000000 --- a/universal_ble/example/linux/CMakeLists.txt +++ /dev/null @@ -1,141 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.10) -project(runner LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "universal_ble_example") -# The unique GTK application identifier for this application. See: -# https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.navideck.universal_ble") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(SET CMP0063 NEW) - -# Load bundled libraries from the lib/ directory relative to the binary. -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Root filesystem for cross-building. -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() - -# Define build configuration options. -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() - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) - -add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") - -# Define the application target. To change its name, change BINARY_NAME above, -# not the value here, or `flutter run` will no longer work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add dependency libraries. Add any application-specific dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) - -# Only the install-generated bundle's copy of the executable will launch -# correctly, since the resources must in the right relative locations. To avoid -# people trying to run the unbundled copy, put it in a subdirectory instead of -# the default top-level location. -set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" -) - -# Enable the test target. -set(include_universal_ble_tests TRUE) - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# By default, "installing" just makes a relocatable bundle in the build -# directory. -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() - -# Start with a clean build bundle directory every time. -install(CODE " - file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") - " COMPONENT Runtime) - -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) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -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 the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() diff --git a/universal_ble/example/linux/flutter/CMakeLists.txt b/universal_ble/example/linux/flutter/CMakeLists.txt deleted file mode 100644 index d5bd016..0000000 --- a/universal_ble/example/linux/flutter/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.10) - -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. - -# Serves the same purpose as list(TRANSFORM ... PREPEND ...), -# which isn't available in 3.10. -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() - -# === Flutter Library === -# System-level dependencies. -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) - -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") - -# 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/lib/libapp.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" -) -list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") -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) - -# === Flutter tool backend === -# _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. -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 -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} -) diff --git a/universal_ble/example/linux/flutter/generated_plugin_registrant.cc b/universal_ble/example/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index e71a16d..0000000 --- a/universal_ble/example/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,11 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - - -void fl_register_plugins(FlPluginRegistry* registry) { -} diff --git a/universal_ble/example/linux/flutter/generated_plugin_registrant.h b/universal_ble/example/linux/flutter/generated_plugin_registrant.h deleted file mode 100644 index e0f0a47..0000000 --- a/universal_ble/example/linux/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/universal_ble/example/linux/flutter/generated_plugins.cmake b/universal_ble/example/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 2e1de87..0000000 --- a/universal_ble/example/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/universal_ble/example/linux/main.cc b/universal_ble/example/linux/main.cc deleted file mode 100644 index e7c5c54..0000000 --- a/universal_ble/example/linux/main.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include "my_application.h" - -int main(int argc, char** argv) { - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); -} diff --git a/universal_ble/example/linux/my_application.cc b/universal_ble/example/linux/my_application.cc deleted file mode 100644 index a3e4f92..0000000 --- a/universal_ble/example/linux/my_application.cc +++ /dev/null @@ -1,104 +0,0 @@ -#include "my_application.h" - -#include -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#include "flutter/generated_plugin_registrant.h" - -struct _MyApplication { - GtkApplication parent_instance; - char** dart_entrypoint_arguments; -}; - -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) - -// Implements GApplication::activate. -static void my_application_activate(GApplication* application) { - MyApplication* self = MY_APPLICATION(application); - GtkWindow* window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - - // Use a header bar when running in GNOME as this is the common style used - // by applications and is the setup most users will be using (e.g. Ubuntu - // desktop). - // If running on X and not using GNOME then just use a traditional title bar - // in case the window manager does more exotic layout, e.g. tiling. - // If running on Wayland assume the header bar will work (may need changing - // if future cases occur). - gboolean use_header_bar = TRUE; -#ifdef GDK_WINDOWING_X11 - GdkScreen* screen = gtk_window_get_screen(window); - if (GDK_IS_X11_SCREEN(screen)) { - const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); - if (g_strcmp0(wm_name, "GNOME Shell") != 0) { - use_header_bar = FALSE; - } - } -#endif - if (use_header_bar) { - GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "universal_ble_example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - } else { - gtk_window_set_title(window, "universal_ble_example"); - } - - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); - - FlView* view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); -} - -// Implements GApplication::local_command_line. -static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { - MyApplication* self = MY_APPLICATION(application); - // Strip out the first argument as it is the binary name. - self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); - - g_autoptr(GError) error = nullptr; - if (!g_application_register(application, nullptr, &error)) { - g_warning("Failed to register: %s", error->message); - *exit_status = 1; - return TRUE; - } - - g_application_activate(application); - *exit_status = 0; - - return TRUE; -} - -// Implements GObject::dispose. -static void my_application_dispose(GObject* object) { - MyApplication* self = MY_APPLICATION(object); - g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); - G_OBJECT_CLASS(my_application_parent_class)->dispose(object); -} - -static void my_application_class_init(MyApplicationClass* klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; - G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; - G_OBJECT_CLASS(klass)->dispose = my_application_dispose; -} - -static void my_application_init(MyApplication* self) {} - -MyApplication* my_application_new() { - return MY_APPLICATION(g_object_new(my_application_get_type(), - "application-id", APPLICATION_ID, - "flags", G_APPLICATION_NON_UNIQUE, - nullptr)); -} diff --git a/universal_ble/example/linux/my_application.h b/universal_ble/example/linux/my_application.h deleted file mode 100644 index 72271d5..0000000 --- a/universal_ble/example/linux/my_application.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FLUTTER_MY_APPLICATION_H_ -#define FLUTTER_MY_APPLICATION_H_ - -#include - -G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) - -/** - * my_application_new: - * - * Creates a new Flutter-based application. - * - * Returns: a new #MyApplication. - */ -MyApplication* my_application_new(); - -#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/universal_ble/example/macos/.gitignore b/universal_ble/example/macos/.gitignore deleted file mode 100644 index 746adbb..0000000 --- a/universal_ble/example/macos/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/dgph -**/xcuserdata/ diff --git a/universal_ble/example/macos/Flutter/Flutter-Debug.xcconfig b/universal_ble/example/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index 4b81f9b..0000000 --- a/universal_ble/example/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/universal_ble/example/macos/Flutter/Flutter-Release.xcconfig b/universal_ble/example/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index 5caa9d1..0000000 --- a/universal_ble/example/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/universal_ble/example/macos/Flutter/GeneratedPluginRegistrant.swift b/universal_ble/example/macos/Flutter/GeneratedPluginRegistrant.swift deleted file mode 100644 index b02da4c..0000000 --- a/universal_ble/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import device_info_plus -import universal_ble - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) - UniversalBlePlugin.register(with: registry.registrar(forPlugin: "UniversalBlePlugin")) -} diff --git a/universal_ble/example/macos/Podfile b/universal_ble/example/macos/Podfile deleted file mode 100644 index c795730..0000000 --- a/universal_ble/example/macos/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -platform :osx, '10.14' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/universal_ble/example/macos/Podfile.lock b/universal_ble/example/macos/Podfile.lock deleted file mode 100644 index 7ec7ff3..0000000 --- a/universal_ble/example/macos/Podfile.lock +++ /dev/null @@ -1,29 +0,0 @@ -PODS: - - device_info_plus (0.0.1): - - FlutterMacOS - - FlutterMacOS (1.0.0) - - universal_ble (0.0.1): - - Flutter - - FlutterMacOS - -DEPENDENCIES: - - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - - FlutterMacOS (from `Flutter/ephemeral`) - - universal_ble (from `Flutter/ephemeral/.symlinks/plugins/universal_ble/darwin`) - -EXTERNAL SOURCES: - device_info_plus: - :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos - FlutterMacOS: - :path: Flutter/ephemeral - universal_ble: - :path: Flutter/ephemeral/.symlinks/plugins/universal_ble/darwin - -SPEC CHECKSUMS: - device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f - FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6 - -PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 - -COCOAPODS: 1.16.2 diff --git a/universal_ble/example/macos/Runner.xcodeproj/project.pbxproj b/universal_ble/example/macos/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index ea4127b..0000000 --- a/universal_ble/example/macos/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,791 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXAggregateTarget section */ - 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; - buildPhases = ( - 33CC111E2044C6BF0003C045 /* ShellScript */, - ); - dependencies = ( - ); - name = "Flutter Assemble"; - productName = FLX; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 54A7291550390DBA7F60B398 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 095AF621C9B1EE27B63D82D1 /* Pods_RunnerTests.framework */; }; - BFFAEE386BA8C5023F9983AE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F517363F4B1C144EC77DADCD /* Pods_Runner.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC10EC2044A3C60003C045; - remoteInfo = Runner; - }; - 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC111A2044C6BA0003C045; - remoteInfo = FLX; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 095AF621C9B1EE27B63D82D1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 32ED472C70D6ED7C3CD8CE8B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* universal_ble_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = universal_ble_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; - 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; - 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; - 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 65CCC8CF23B15CA6818A0496 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - BF9EC7C1208428926C8C045E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - C5F6162E162B944885A4C57E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - D8A7E0EE9000B69937E2CAAF /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - F517363F4B1C144EC77DADCD /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - FF25EBD7FA998BE27A25C911 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 331C80D2294CF70F00263BE5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 54A7291550390DBA7F60B398 /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EA2044A3C60003C045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - BFFAEE386BA8C5023F9983AE /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 33BA886A226E78AF003329D5 /* Configs */ = { - isa = PBXGroup; - children = ( - 33E5194F232828860026EE4D /* AppInfo.xcconfig */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, - ); - path = Configs; - sourceTree = ""; - }; - 33CC10E42044A3C60003C045 = { - isa = PBXGroup; - children = ( - 33FAB671232836740065AC1E /* Runner */, - 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, - 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - 918B2BA59DA01E445579435F /* Pods */, - ); - sourceTree = ""; - }; - 33CC10EE2044A3C60003C045 /* Products */ = { - isa = PBXGroup; - children = ( - 33CC10ED2044A3C60003C045 /* universal_ble_example.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 33CC11242044D66E0003C045 /* Resources */ = { - isa = PBXGroup; - children = ( - 33CC10F22044A3C60003C045 /* Assets.xcassets */, - 33CC10F42044A3C60003C045 /* MainMenu.xib */, - 33CC10F72044A3C60003C045 /* Info.plist */, - ); - name = Resources; - path = ..; - sourceTree = ""; - }; - 33CEB47122A05771004F2AC0 /* Flutter */ = { - isa = PBXGroup; - children = ( - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - ); - path = Flutter; - sourceTree = ""; - }; - 33FAB671232836740065AC1E /* Runner */ = { - isa = PBXGroup; - children = ( - 33CC10F02044A3C60003C045 /* AppDelegate.swift */, - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, - 33E51913231747F40026EE4D /* DebugProfile.entitlements */, - 33E51914231749380026EE4D /* Release.entitlements */, - 33CC11242044D66E0003C045 /* Resources */, - 33BA886A226E78AF003329D5 /* Configs */, - ); - path = Runner; - sourceTree = ""; - }; - 918B2BA59DA01E445579435F /* Pods */ = { - isa = PBXGroup; - children = ( - FF25EBD7FA998BE27A25C911 /* Pods-Runner.debug.xcconfig */, - 65CCC8CF23B15CA6818A0496 /* Pods-Runner.release.xcconfig */, - 32ED472C70D6ED7C3CD8CE8B /* Pods-Runner.profile.xcconfig */, - D8A7E0EE9000B69937E2CAAF /* Pods-RunnerTests.debug.xcconfig */, - BF9EC7C1208428926C8C045E /* Pods-RunnerTests.release.xcconfig */, - C5F6162E162B944885A4C57E /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - F517363F4B1C144EC77DADCD /* Pods_Runner.framework */, - 095AF621C9B1EE27B63D82D1 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 0B773D64B309FE8B1C43C096 /* [CP] Check Pods Manifest.lock */, - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 33CC10EC2044A3C60003C045 /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 4DACA89469123DBF706A6DEC /* [CP] Check Pods Manifest.lock */, - 33CC10E92044A3C60003C045 /* Sources */, - 33CC10EA2044A3C60003C045 /* Frameworks */, - 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, - 3399D490228B24CF009A79C7 /* ShellScript */, - DB73DCCDE8FAA136C11B0BD8 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 33CC11202044C79F0003C045 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* universal_ble_example.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 33CC10E52044A3C60003C045 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C80D4294CF70F00263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 33CC10EC2044A3C60003C045; - }; - 33CC10EC2044A3C60003C045 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - 33CC111A2044C6BA0003C045 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 33CC10E42044A3C60003C045; - productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, - 33CC111A2044C6BA0003C045 /* Flutter Assemble */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C80D3294CF70F00263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EB2044A3C60003C045 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 0B773D64B309FE8B1C43C096 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; - 4DACA89469123DBF706A6DEC /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - DB73DCCDE8FAA136C11B0BD8 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C80D1294CF70F00263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10E92044A3C60003C045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC10EC2044A3C60003C045 /* Runner */; - targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; - }; - 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; - targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 33CC10F52044A3C60003C045 /* Base */, - ); - name = MainMenu.xib; - path = Runner; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D8A7E0EE9000B69937E2CAAF /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/universal_ble_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/universal_ble_example"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BF9EC7C1208428926C8C045E /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/universal_ble_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/universal_ble_example"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C5F6162E162B944885A4C57E /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/universal_ble_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/universal_ble_example"; - }; - name = Profile; - }; - 338D0CE9231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Profile; - }; - 338D0CEA231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Profile; - }; - 338D0CEB231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Profile; - }; - 33CC10F92044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 33CC10FA2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - 33CC10FC2044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 33CC10FD2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 33CC111C2044C6BA0003C045 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33CC111D2044C6BA0003C045 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10F92044A3C60003C045 /* Debug */, - 33CC10FA2044A3C60003C045 /* Release */, - 338D0CE9231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10FC2044A3C60003C045 /* Debug */, - 33CC10FD2044A3C60003C045 /* Release */, - 338D0CEA231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC111C2044C6BA0003C045 /* Debug */, - 33CC111D2044C6BA0003C045 /* Release */, - 338D0CEB231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 33CC10E52044A3C60003C045 /* Project object */; -} diff --git a/universal_ble/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/universal_ble/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/universal_ble/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/universal_ble/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/universal_ble/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 793b0cf..0000000 --- a/universal_ble/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/universal_ble/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/universal_ble/example/macos/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc1..0000000 --- a/universal_ble/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/universal_ble/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/universal_ble/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/universal_ble/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/universal_ble/example/macos/Runner/AppDelegate.swift b/universal_ble/example/macos/Runner/AppDelegate.swift deleted file mode 100644 index b3c1761..0000000 --- a/universal_ble/example/macos/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Cocoa -import FlutterMacOS - -@main -class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } -} diff --git a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a2ec33f..0000000 --- a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png deleted file mode 100644 index 82b6f9d..0000000 Binary files a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png and /dev/null differ diff --git a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png deleted file mode 100644 index 13b35eb..0000000 Binary files a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png and /dev/null differ diff --git a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png deleted file mode 100644 index 0a3f5fa..0000000 Binary files a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png and /dev/null differ diff --git a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png deleted file mode 100644 index bdb5722..0000000 Binary files a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png and /dev/null differ diff --git a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png deleted file mode 100644 index f083318..0000000 Binary files a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png and /dev/null differ diff --git a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png deleted file mode 100644 index 326c0e7..0000000 Binary files a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png and /dev/null differ diff --git a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png deleted file mode 100644 index 2f1632c..0000000 Binary files a/universal_ble/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png and /dev/null differ diff --git a/universal_ble/example/macos/Runner/Base.lproj/MainMenu.xib b/universal_ble/example/macos/Runner/Base.lproj/MainMenu.xib deleted file mode 100644 index 80e867a..0000000 --- a/universal_ble/example/macos/Runner/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/universal_ble/example/macos/Runner/Configs/AppInfo.xcconfig b/universal_ble/example/macos/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index d550e14..0000000 --- a/universal_ble/example/macos/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = universal_ble_example - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.navideck.universalBleExample - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright Ā© 2023 com.navideck. All rights reserved. diff --git a/universal_ble/example/macos/Runner/Configs/Debug.xcconfig b/universal_ble/example/macos/Runner/Configs/Debug.xcconfig deleted file mode 100644 index 36b0fd9..0000000 --- a/universal_ble/example/macos/Runner/Configs/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" -#include "Warnings.xcconfig" diff --git a/universal_ble/example/macos/Runner/Configs/Release.xcconfig b/universal_ble/example/macos/Runner/Configs/Release.xcconfig deleted file mode 100644 index dff4f49..0000000 --- a/universal_ble/example/macos/Runner/Configs/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Release.xcconfig" -#include "Warnings.xcconfig" diff --git a/universal_ble/example/macos/Runner/Configs/Warnings.xcconfig b/universal_ble/example/macos/Runner/Configs/Warnings.xcconfig deleted file mode 100644 index 42bcbf4..0000000 --- a/universal_ble/example/macos/Runner/Configs/Warnings.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings -GCC_WARN_UNDECLARED_SELECTOR = YES -CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_PRAGMA_PACK = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_COMMA = YES -GCC_WARN_STRICT_SELECTOR_MATCH = YES -CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -GCC_WARN_SHADOW = YES -CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/universal_ble/example/macos/Runner/DebugProfile.entitlements b/universal_ble/example/macos/Runner/DebugProfile.entitlements deleted file mode 100644 index 14a39b7..0000000 --- a/universal_ble/example/macos/Runner/DebugProfile.entitlements +++ /dev/null @@ -1,14 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - com.apple.security.device.bluetooth - - com.apple.security.network.server - - - diff --git a/universal_ble/example/macos/Runner/Info.plist b/universal_ble/example/macos/Runner/Info.plist deleted file mode 100644 index d24dbb7..0000000 --- a/universal_ble/example/macos/Runner/Info.plist +++ /dev/null @@ -1,36 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - NSBluetoothAlwaysUsageDescription - Discover Bluetooth devices - NSBluetoothPeripheralUsageDescription - Discover Bluetooth devices - - diff --git a/universal_ble/example/macos/Runner/MainFlutterWindow.swift b/universal_ble/example/macos/Runner/MainFlutterWindow.swift deleted file mode 100644 index 3cc05eb..0000000 --- a/universal_ble/example/macos/Runner/MainFlutterWindow.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Cocoa -import FlutterMacOS - -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - - RegisterGeneratedPlugins(registry: flutterViewController) - - super.awakeFromNib() - } -} diff --git a/universal_ble/example/macos/Runner/Release.entitlements b/universal_ble/example/macos/Runner/Release.entitlements deleted file mode 100644 index c63c951..0000000 --- a/universal_ble/example/macos/Runner/Release.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.device.bluetooth - - com.apple.security.network.server - - - diff --git a/universal_ble/example/macos/RunnerTests/RunnerTests.swift b/universal_ble/example/macos/RunnerTests/RunnerTests.swift deleted file mode 100644 index e0c61cb..0000000 --- a/universal_ble/example/macos/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,27 +0,0 @@ -import FlutterMacOS -import Cocoa -import XCTest - -@testable import universal_ble - -// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. -// -// See https://developer.apple.com/documentation/xctest for more information about using XCTest. - -class RunnerTests: XCTestCase { - - func testGetPlatformVersion() { - let plugin = UniversalBlePlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual(result as! String, - "macOS " + ProcessInfo.processInfo.operatingSystemVersionString) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) - } - -} diff --git a/universal_ble/example/pubspec.lock b/universal_ble/example/pubspec.lock deleted file mode 100644 index 3ef07d5..0000000 --- a/universal_ble/example/pubspec.lock +++ /dev/null @@ -1,456 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - args: - dependency: transitive - description: - name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" - url: "https://pub.dev" - source: hosted - version: "2.5.0" - async: - dependency: transitive - description: - name: async - sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 - url: "https://pub.dev" - source: hosted - version: "2.12.0" - bluez: - dependency: transitive - description: - name: bluez - sha256: "61a7204381925896a374301498f2f5399e59827c6498ae1e924aaa598751b545" - url: "https://pub.dev" - source: hosted - version: "0.8.3" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - convert: - dependency: "direct main" - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - dbus: - dependency: transitive - description: - name: dbus - sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" - url: "https://pub.dev" - source: hosted - version: "0.7.11" - device_info_plus: - dependency: "direct main" - description: - name: device_info_plus - sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" - url: "https://pub.dev" - source: hosted - version: "9.1.2" - device_info_plus_platform_interface: - dependency: transitive - description: - name: device_info_plus_platform_interface - sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 - url: "https://pub.dev" - source: hosted - version: "7.0.0" - expandable: - dependency: "direct main" - description: - name: expandable - sha256: "9604d612d4d1146dafa96c6d8eec9c2ff0994658d6d09fed720ab788c7f5afc2" - url: "https://pub.dev" - source: hosted - version: "5.0.1" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" - url: "https://pub.dev" - source: hosted - version: "1.3.2" - ffi: - dependency: transitive - description: - name: ffi - sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_driver: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 - url: "https://pub.dev" - source: hosted - version: "2.0.3" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_bluetooth: - dependency: transitive - description: - name: flutter_web_bluetooth - sha256: "1363831def5eed1e1064d1eca04e8ccb35446e8f758579c3c519e156b77926da" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - fuchsia_remote_debug_protocol: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - integration_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec - url: "https://pub.dev" - source: hosted - version: "10.0.8" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 - url: "https://pub.dev" - source: hosted - version: "3.0.9" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - lints: - dependency: transitive - description: - name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - logging: - dependency: transitive - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" - source: hosted - version: "1.16.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - permission_handler: - dependency: "direct main" - description: - name: permission_handler - sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 - url: "https://pub.dev" - source: hosted - version: "10.4.5" - permission_handler_android: - dependency: transitive - description: - name: permission_handler_android - sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" - url: "https://pub.dev" - source: hosted - version: "10.3.6" - permission_handler_apple: - dependency: transitive - description: - name: permission_handler_apple - sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" - url: "https://pub.dev" - source: hosted - version: "9.1.4" - permission_handler_platform_interface: - dependency: transitive - description: - name: permission_handler_platform_interface - sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" - url: "https://pub.dev" - source: hosted - version: "3.12.0" - permission_handler_windows: - dependency: transitive - description: - name: permission_handler_windows - sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 - url: "https://pub.dev" - source: hosted - version: "0.1.3" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 - url: "https://pub.dev" - source: hosted - version: "6.0.2" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - process: - dependency: transitive - description: - name: process - sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" - url: "https://pub.dev" - source: hosted - version: "5.0.3" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - sync_http: - dependency: transitive - description: - name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" - source: hosted - version: "0.3.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd - url: "https://pub.dev" - source: hosted - version: "0.7.4" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.dev" - source: hosted - version: "1.3.2" - universal_ble: - dependency: "direct main" - description: - path: ".." - relative: true - source: path - version: "0.17.0" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" - url: "https://pub.dev" - source: hosted - version: "14.3.1" - web: - dependency: transitive - description: - name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb - url: "https://pub.dev" - source: hosted - version: "1.1.0" - webdriver: - dependency: transitive - description: - name: webdriver - sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" - url: "https://pub.dev" - source: hosted - version: "3.0.4" - win32: - dependency: transitive - description: - name: win32 - sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 - url: "https://pub.dev" - source: hosted - version: "5.5.1" - win32_registry: - dependency: transitive - description: - name: win32_registry - sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb" - url: "https://pub.dev" - source: hosted - version: "1.1.3" - xml: - dependency: transitive - description: - name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.dev" - source: hosted - version: "6.5.0" -sdks: - dart: ">=3.7.0-0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" diff --git a/universal_ble/example/pubspec.yaml b/universal_ble/example/pubspec.yaml deleted file mode 100644 index 8bb7697..0000000 --- a/universal_ble/example/pubspec.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: universal_ble_example -description: Demonstrates how to use the universal_ble plugin. -version: 1.0.0+1 -publish_to: "none" - -environment: - sdk: ">=3.1.3 <4.0.0" - -dependencies: - flutter: - sdk: flutter - convert: ^3.1.1 - expandable: ^5.0.1 - cupertino_icons: ^1.0.2 - permission_handler: ^10.4.3 - device_info_plus: ^9.0.2 - universal_ble: - path: ../ - -dev_dependencies: - integration_test: - sdk: flutter - flutter_test: - sdk: flutter - flutter_lints: ^2.0.0 - -flutter: - uses-material-design: true diff --git a/universal_ble/example/web/favicon.png b/universal_ble/example/web/favicon.png deleted file mode 100644 index 8aaa46a..0000000 Binary files a/universal_ble/example/web/favicon.png and /dev/null differ diff --git a/universal_ble/example/web/icons/Icon-192.png b/universal_ble/example/web/icons/Icon-192.png deleted file mode 100644 index b749bfe..0000000 Binary files a/universal_ble/example/web/icons/Icon-192.png and /dev/null differ diff --git a/universal_ble/example/web/icons/Icon-512.png b/universal_ble/example/web/icons/Icon-512.png deleted file mode 100644 index 88cfd48..0000000 Binary files a/universal_ble/example/web/icons/Icon-512.png and /dev/null differ diff --git a/universal_ble/example/web/icons/Icon-maskable-192.png b/universal_ble/example/web/icons/Icon-maskable-192.png deleted file mode 100644 index eb9b4d7..0000000 Binary files a/universal_ble/example/web/icons/Icon-maskable-192.png and /dev/null differ diff --git a/universal_ble/example/web/icons/Icon-maskable-512.png b/universal_ble/example/web/icons/Icon-maskable-512.png deleted file mode 100644 index d69c566..0000000 Binary files a/universal_ble/example/web/icons/Icon-maskable-512.png and /dev/null differ diff --git a/universal_ble/example/web/index.html b/universal_ble/example/web/index.html deleted file mode 100644 index 26f5da2..0000000 --- a/universal_ble/example/web/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - example - - - - - - diff --git a/universal_ble/example/web/manifest.json b/universal_ble/example/web/manifest.json deleted file mode 100644 index 8bc88df..0000000 --- a/universal_ble/example/web/manifest.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "Universal BLE", - "short_name": "Universal BLE", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "Example app for Web", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} diff --git a/universal_ble/example/windows/.gitignore b/universal_ble/example/windows/.gitignore deleted file mode 100644 index d492d0d..0000000 --- a/universal_ble/example/windows/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -flutter/ephemeral/ - -# 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/ diff --git a/universal_ble/example/windows/CMakeLists.txt b/universal_ble/example/windows/CMakeLists.txt deleted file mode 100644 index 0937d82..0000000 --- a/universal_ble/example/windows/CMakeLists.txt +++ /dev/null @@ -1,104 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.14) -project(universal_ble_example LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "universal_ble_example") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(VERSION 3.14...3.25) - -# Define build configuration option. -get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - 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() -endif() -# Define settings for the Profile build mode. -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}") - -# Use Unicode for all projects. -add_definitions(-DUNICODE -D_UNICODE) - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -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() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - -# Enable the test target. -set(include_universal_ble_tests TRUE) - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# Support files are copied into place next to the executable, so that it can -# run in place. This is done instead of making a separate bundle (as on Linux) -# so that building and running from within Visual Studio will work. -set(BUILD_BUNDLE_DIR "$") -# Make the "install" step default, as it's required to run. -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}") - -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) - -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -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 the AOT library on non-Debug builds only. -install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) diff --git a/universal_ble/example/windows/flutter/CMakeLists.txt b/universal_ble/example/windows/flutter/CMakeLists.txt deleted file mode 100644 index 903f489..0000000 --- a/universal_ble/example/windows/flutter/CMakeLists.txt +++ /dev/null @@ -1,109 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.14) - -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) - -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) - -# === Wrapper === -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) - -# 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) - -# === Flutter tool backend === -# _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} -) diff --git a/universal_ble/example/windows/flutter/generated_plugin_registrant.cc b/universal_ble/example/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 3860860..0000000 --- a/universal_ble/example/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,17 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - PermissionHandlerWindowsPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); - UniversalBlePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("UniversalBlePluginCApi")); -} diff --git a/universal_ble/example/windows/flutter/generated_plugin_registrant.h b/universal_ble/example/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index dc139d8..0000000 --- a/universal_ble/example/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/universal_ble/example/windows/flutter/generated_plugins.cmake b/universal_ble/example/windows/flutter/generated_plugins.cmake deleted file mode 100644 index 3dcad9f..0000000 --- a/universal_ble/example/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - permission_handler_windows - universal_ble -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/universal_ble/example/windows/runner/CMakeLists.txt b/universal_ble/example/windows/runner/CMakeLists.txt deleted file mode 100644 index 394917c..0000000 --- a/universal_ble/example/windows/runner/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.14) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the build version. -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") - -# Disable Windows macros that collide with C++ standard library functions. -target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") - -# Add dependency libraries and include directories. Add any application-specific -# dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) -target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/universal_ble/example/windows/runner/Runner.rc b/universal_ble/example/windows/runner/Runner.rc deleted file mode 100644 index 23c0d5c..0000000 --- a/universal_ble/example/windows/runner/Runner.rc +++ /dev/null @@ -1,121 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) -#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD -#else -#define VERSION_AS_NUMBER 1,0,0,0 -#endif - -#if defined(FLUTTER_VERSION) -#define VERSION_AS_STRING FLUTTER_VERSION -#else -#define VERSION_AS_STRING "1.0.0" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "com.navideck" "\0" - VALUE "FileDescription", "universal_ble_example" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "universal_ble_example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2023 com.navideck. All rights reserved." "\0" - VALUE "OriginalFilename", "universal_ble_example.exe" "\0" - VALUE "ProductName", "universal_ble_example" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/universal_ble/example/windows/runner/flutter_window.cpp b/universal_ble/example/windows/runner/flutter_window.cpp deleted file mode 100644 index 955ee30..0000000 --- a/universal_ble/example/windows/runner/flutter_window.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "flutter_window.h" - -#include - -#include "flutter/generated_plugin_registrant.h" - -FlutterWindow::FlutterWindow(const flutter::DartProject& project) - : project_(project) {} - -FlutterWindow::~FlutterWindow() {} - -bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } - - RECT frame = GetClientArea(); - - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); - - // Flutter can complete the first frame before the "show window" callback is - // registered. The following call ensures a frame is pending to ensure the - // window is shown. It is a no-op if the first frame hasn't completed yet. - flutter_controller_->ForceRedraw(); - - return true; -} - -void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - flutter_controller_ = nullptr; - } - - Win32Window::OnDestroy(); -} - -LRESULT -FlutterWindow::MessageHandler(HWND hwnd, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opportunity to handle window messages. - if (flutter_controller_) { - std::optional result = - flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, - lparam); - if (result) { - return *result; - } - } - - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } - - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); -} diff --git a/universal_ble/example/windows/runner/flutter_window.h b/universal_ble/example/windows/runner/flutter_window.h deleted file mode 100644 index 6da0652..0000000 --- a/universal_ble/example/windows/runner/flutter_window.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RUNNER_FLUTTER_WINDOW_H_ -#define RUNNER_FLUTTER_WINDOW_H_ - -#include -#include - -#include - -#include "win32_window.h" - -// A window that does nothing but host a Flutter view. -class FlutterWindow : public Win32Window { - public: - // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject& project); - virtual ~FlutterWindow(); - - protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; - - private: - // The project to run. - flutter::DartProject project_; - - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; -}; - -#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/universal_ble/example/windows/runner/main.cpp b/universal_ble/example/windows/runner/main.cpp deleted file mode 100644 index f2b1e45..0000000 --- a/universal_ble/example/windows/runner/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#include "flutter_window.h" -#include "utils.h" - -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - flutter::DartProject project(L"data"); - - std::vector command_line_arguments = - GetCommandLineArguments(); - - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - - FlutterWindow window(project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.Create(L"universal_ble_example", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - ::MSG msg; - while (::GetMessage(&msg, nullptr, 0, 0)) { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - ::CoUninitialize(); - return EXIT_SUCCESS; -} diff --git a/universal_ble/example/windows/runner/resource.h b/universal_ble/example/windows/runner/resource.h deleted file mode 100644 index 66a65d1..0000000 --- a/universal_ble/example/windows/runner/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Runner.rc -// -#define IDI_APP_ICON 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/universal_ble/example/windows/runner/resources/app_icon.ico b/universal_ble/example/windows/runner/resources/app_icon.ico deleted file mode 100644 index c04e20c..0000000 Binary files a/universal_ble/example/windows/runner/resources/app_icon.ico and /dev/null differ diff --git a/universal_ble/example/windows/runner/runner.exe.manifest b/universal_ble/example/windows/runner/runner.exe.manifest deleted file mode 100644 index a42ea76..0000000 --- a/universal_ble/example/windows/runner/runner.exe.manifest +++ /dev/null @@ -1,20 +0,0 @@ - - - - - PerMonitorV2 - - - - - - - - - - - - - - - diff --git a/universal_ble/example/windows/runner/utils.cpp b/universal_ble/example/windows/runner/utils.cpp deleted file mode 100644 index b2b0873..0000000 --- a/universal_ble/example/windows/runner/utils.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include - -void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); - } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } -} - -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } - - std::vector command_line_arguments; - - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } - - ::LocalFree(argv); - - return command_line_arguments; -} - -std::string Utf8FromUtf16(const wchar_t* utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character - int input_length = (int)wcslen(utf16_string); - std::string utf8_string; - if (target_length <= 0 || target_length > utf8_string.max_size()) { - return utf8_string; - } - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; -} diff --git a/universal_ble/example/windows/runner/utils.h b/universal_ble/example/windows/runner/utils.h deleted file mode 100644 index 3879d54..0000000 --- a/universal_ble/example/windows/runner/utils.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RUNNER_UTILS_H_ -#define RUNNER_UTILS_H_ - -#include -#include - -// Creates a console for the process, and redirects stdout and stderr to -// it for both the runner and the Flutter library. -void CreateAndAttachConsole(); - -// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string -// encoded in UTF-8. Returns an empty std::string on failure. -std::string Utf8FromUtf16(const wchar_t* utf16_string); - -// Gets the command line arguments passed in as a std::vector, -// encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); - -#endif // RUNNER_UTILS_H_ diff --git a/universal_ble/example/windows/runner/win32_window.cpp b/universal_ble/example/windows/runner/win32_window.cpp deleted file mode 100644 index 60608d0..0000000 --- a/universal_ble/example/windows/runner/win32_window.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "win32_window.h" - -#include -#include - -#include "resource.h" - -namespace { - -/// Window attribute that enables dark mode window decorations. -/// -/// Redefined in case the developer's machine has a Windows SDK older than -/// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute -#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE -#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 -#endif - -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; - -/// Registry key for app theme preference. -/// -/// A value of 0 indicates apps should use dark mode. A non-zero or missing -/// value indicates apps should use light mode. -constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; - -// The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; - -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); - -// Scale helper to convert logical scaler values to physical using passed in -// scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} - -// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. -// This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { - return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - } - FreeLibrary(user32_module); -} - -} // namespace - -// Manages the Win32Window's window class registration. -class WindowClassRegistrar { - public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registrar instance. - static WindowClassRegistrar* GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); - } - return instance_; - } - - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t* GetWindowClass(); - - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); - - private: - WindowClassRegistrar() = default; - - static WindowClassRegistrar* instance_; - - bool class_registered_ = false; -}; - -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; - -const wchar_t* WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; -} - -void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; -} - -Win32Window::Win32Window() { - ++g_active_window_count; -} - -Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); -} - -bool Win32Window::Create(const std::wstring& title, - const Point& origin, - const Size& size) { - Destroy(); - - const wchar_t* window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); - - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; - - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); - - if (!window) { - return false; - } - - UpdateTheme(window); - - return OnCreate(); -} - -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} - -// static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } - - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -void Win32Window::Destroy() { - OnDestroy(); - - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); - - SetFocus(child_content_); -} - -RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; -} - -HWND Win32Window::GetHandle() { - return window_handle_; -} - -void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; -} - -bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; -} - -void Win32Window::OnDestroy() { - // No-op; provided for subclasses. -} - -void Win32Window::UpdateTheme(HWND const window) { - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - - if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); - } -} diff --git a/universal_ble/example/windows/runner/win32_window.h b/universal_ble/example/windows/runner/win32_window.h deleted file mode 100644 index e901dde..0000000 --- a/universal_ble/example/windows/runner/win32_window.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef RUNNER_WIN32_WINDOW_H_ -#define RUNNER_WIN32_WINDOW_H_ - -#include - -#include -#include -#include - -// A class abstraction for a high DPI-aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling -class Win32Window { - public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates a win32 window with |title| that is positioned and sized using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size this function will scale the inputted width and height as - // as appropriate for the default monitor. The window is invisible until - // |Show| is called. Returns true if the window was created successfully. - bool Create(const std::wstring& title, const Point& origin, const Size& size); - - // Show the current window. Returns true if the window was successfully shown. - bool Show(); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); - - protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); - - // Called when Destroy is called. - virtual void OnDestroy(); - - private: - friend class WindowClassRegistrar; - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - - // Update the window frame's theme to match the system theme. - static void UpdateTheme(HWND const window); - - bool quit_on_close_ = false; - - // window handle for top level window. - HWND window_handle_ = nullptr; - - // window handle for hosted content. - HWND child_content_ = nullptr; -}; - -#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/universal_ble/lib/src/ble_command_queue.dart b/universal_ble/lib/src/ble_command_queue.dart deleted file mode 100644 index 2d5449b..0000000 --- a/universal_ble/lib/src/ble_command_queue.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:universal_ble/src/queue.dart'; -import 'package:universal_ble/universal_ble.dart'; - -/// Set queue type and queue commands -class BleCommandQueue { - QueueType queueType; - Duration? timeout = const Duration(seconds: 10); - OnQueueUpdate? onQueueUpdate; - final Map _queueMap = {}; - static const String globalQueueId = 'global'; - - BleCommandQueue({this.queueType = QueueType.global}); - - Future queueCommand( - Future Function() command, { - bool withTimeout = true, - String? deviceId, - Duration? timeout, - }) { - Duration? duration = timeout ?? (withTimeout ? this.timeout : null); - return switch (queueType) { - QueueType.global => _queue().add(command, duration), - QueueType.perDevice => _queue(deviceId).add(command, duration), - QueueType.none => - duration != null ? command().timeout(duration) : command(), - }; - } - - Queue _queue([String? id = globalQueueId]) => - _queueMap[id] ?? _newQueue(id ?? globalQueueId); - - Queue _newQueue(String id) { - final queue = Queue(); - queue.onRemainingItemsUpdate = (int items) { - try { - onQueueUpdate?.call(id, items); - } catch (_) {} - }; - _queueMap[id] = queue; - return queue; - } -} diff --git a/universal_ble/lib/src/models/availability_state.dart b/universal_ble/lib/src/models/availability_state.dart deleted file mode 100644 index 0e0f8e6..0000000 --- a/universal_ble/lib/src/models/availability_state.dart +++ /dev/null @@ -1,12 +0,0 @@ -enum AvailabilityState { - unknown, - resetting, - unsupported, - unauthorized, - poweredOff, - poweredOn; - - const AvailabilityState(); - - factory AvailabilityState.parse(int index) => AvailabilityState.values[index]; -} diff --git a/universal_ble/lib/src/models/ble_capabilities.dart b/universal_ble/lib/src/models/ble_capabilities.dart deleted file mode 100644 index 9b37657..0000000 --- a/universal_ble/lib/src/models/ble_capabilities.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:flutter/foundation.dart'; - -class BleCapabilities { - /// Returns true if in-app pairing is possible either by API or by encrypted characteristic - /// using any kind of pairing method (Just Works, Numeric Comparison or Passkey Entry). - /// - /// All platforms return true except Web/Windows and Web/Linux which return false - /// because they only support "Numeric Comparison" and "Passkey Entry". - /// - /// For more fine-grained control it is recommended to use `triggersConfirmOnlyPairing` - /// in conjunction with the pairing method of your peripheral, - /// e.g. if (!BleCapabilities.triggersConfirmOnlyPairing && peripheralUsesConfirmOnlyPairing) throw "In-app pairing not supported"; - static final bool supportsAllPairingKinds = - triggersConfirmOnlyPairing || hasSystemPairingApi; - - /// Returns true if the platform triggers pairing for devices that use only confirmation pairing - /// (a.k.a. "Just Works" or legacy pairing) when trying to read or write to an encrypted characteristic. - /// - /// The "Numeric Comparison" and "Passkey Entry" pairing methods trigger pairing on all platforms. - /// - /// `Web/Linux` could also, under certain conditions, trigger "Just Works" pairing - /// but it very unreliable, therefore we return false. - static final triggersConfirmOnlyPairing = - defaultTargetPlatform != TargetPlatform.windows && - defaultTargetPlatform != TargetPlatform.linux; - - /// Returns true if pair()/unpair() are supported on the platform. - static bool hasSystemPairingApi = !kIsWeb && - (defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.windows || - defaultTargetPlatform == TargetPlatform.linux); - - static bool requiresRuntimePermission = - !_Platform.isWeb && !_Platform.isWindows && !_Platform.isLinux; - - static bool supportsBluetoothEnableApi = - !_Platform.isWeb && !_Platform.isCupertino; - - static bool supportsConnectedDevicesApi = !_Platform.isWeb; - - static bool supportsRequestMtuApi = !_Platform.isWeb; -} - -class _Platform { - static bool isWeb = kIsWeb; - static bool isIOS = !isWeb && defaultTargetPlatform == TargetPlatform.iOS; - static bool isMacos = !isWeb && defaultTargetPlatform == TargetPlatform.macOS; - static bool isWindows = - !isWeb && defaultTargetPlatform == TargetPlatform.windows; - static bool isLinux = !isWeb && defaultTargetPlatform == TargetPlatform.linux; - static bool get isCupertino => isIOS || isMacos; -} diff --git a/universal_ble/lib/src/models/ble_command.dart b/universal_ble/lib/src/models/ble_command.dart deleted file mode 100644 index 345d19c..0000000 --- a/universal_ble/lib/src/models/ble_command.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'dart:typed_data'; - -class BleCommand { - String service; - String characteristic; - Uint8List? writeValue; - - BleCommand({ - required this.service, - required this.characteristic, - this.writeValue, - }); -} diff --git a/universal_ble/lib/src/models/ble_connection_state.dart b/universal_ble/lib/src/models/ble_connection_state.dart deleted file mode 100644 index 2230299..0000000 --- a/universal_ble/lib/src/models/ble_connection_state.dart +++ /dev/null @@ -1,11 +0,0 @@ -enum BleConnectionState { - connected, - disconnected, - connecting, - disconnecting; - - const BleConnectionState(); - - factory BleConnectionState.parse(int index) => - BleConnectionState.values[index]; -} diff --git a/universal_ble/lib/src/models/ble_connection_update.dart b/universal_ble/lib/src/models/ble_connection_update.dart deleted file mode 100644 index f9727a7..0000000 --- a/universal_ble/lib/src/models/ble_connection_update.dart +++ /dev/null @@ -1,11 +0,0 @@ -class BleConnectionUpdate { - final String deviceId; - final bool isConnected; - final String? error; - - BleConnectionUpdate({ - required this.deviceId, - required this.isConnected, - this.error, - }); -} diff --git a/universal_ble/lib/src/models/ble_device.dart b/universal_ble/lib/src/models/ble_device.dart deleted file mode 100644 index b471861..0000000 --- a/universal_ble/lib/src/models/ble_device.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'dart:typed_data'; - -import 'package:universal_ble/universal_ble.dart'; - -class BleDevice { - String deviceId; - String? name; - String? rawName; - int? rssi; - bool? isPaired; - List services; - bool? isSystemDevice; - List manufacturerDataList; - - @Deprecated("Use `manufacturerDataList` instead") - Uint8List? get manufacturerData => manufacturerDataList.isEmpty - ? null - : manufacturerDataList.first.toUint8List(); - - /// Returns connection state of the device. - /// All platforms will return `Connected/Disconnected` states. - /// `Android` and `Apple` can also return `Connecting/Disconnecting` states. - Future get connectionState => - UniversalBle.getConnectionState(deviceId); - - /// On web, it returns true if the web browser supports receiving advertisements from this device. - /// The rest of the platforms will always return true. - bool get receivesAdvertisements => - UniversalBle.receivesAdvertisements(deviceId); - - BleDevice({ - required this.deviceId, - required String? name, - this.rssi, - this.isPaired, - this.services = const [], - this.isSystemDevice, - this.manufacturerDataList = const [], - }) { - rawName = name; - this.name = name?.replaceAll(RegExp(r'[^ -~]'), '').trim(); - } - - @override - String toString() { - return 'BleDevice: ' - 'deviceId: $deviceId, ' - 'name: $name, ' - 'rssi: $rssi, ' - 'isPaired: $isPaired, ' - 'services: $services, ' - 'isSystemDevice: $isSystemDevice, ' - 'manufacturerDataList: $manufacturerDataList'; - } -} diff --git a/universal_ble/lib/src/models/ble_property.dart b/universal_ble/lib/src/models/ble_property.dart deleted file mode 100644 index df94343..0000000 --- a/universal_ble/lib/src/models/ble_property.dart +++ /dev/null @@ -1,18 +0,0 @@ -enum BleInputProperty { - disabled, - notification, - indication; - - const BleInputProperty(); - - factory BleInputProperty.parse(int index) => BleInputProperty.values[index]; -} - -enum BleOutputProperty { - withResponse, - withoutResponse; - - const BleOutputProperty(); - - factory BleOutputProperty.parse(int index) => BleOutputProperty.values[index]; -} diff --git a/universal_ble/lib/src/models/ble_service.dart b/universal_ble/lib/src/models/ble_service.dart deleted file mode 100644 index f844820..0000000 --- a/universal_ble/lib/src/models/ble_service.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:universal_ble/universal_ble.dart'; - -class BleService { - late String uuid; - List characteristics; - - BleService(String uuid, this.characteristics) { - this.uuid = BleUuidParser.string(uuid); - } - - @override - String toString() { - return 'BleService{uuid: $uuid, characteristics: $characteristics}'; - } -} - -class BleCharacteristic { - late String uuid; - List properties; - - BleCharacteristic(String uuid, this.properties) { - this.uuid = BleUuidParser.string(uuid); - } - - @override - String toString() { - return 'BleCharacteristic{uuid: $uuid, properties: $properties}'; - } -} - -enum CharacteristicProperty { - broadcast, - read, - writeWithoutResponse, - write, - notify, - indicate, - authenticatedSignedWrites, - extendedProperties; - - const CharacteristicProperty(); - - factory CharacteristicProperty.parse(int index) => - CharacteristicProperty.values[index]; - - @override - String toString() => name; -} diff --git a/universal_ble/lib/src/models/ble_uuid_parser.dart b/universal_ble/lib/src/models/ble_uuid_parser.dart deleted file mode 100644 index be775f5..0000000 --- a/universal_ble/lib/src/models/ble_uuid_parser.dart +++ /dev/null @@ -1,69 +0,0 @@ -class BleUuidParser { - BleUuidParser._(); - - /// Parse a string to a valid 128-bit UUID. - /// Throws `FormatException` if the string does not hold a valid UUID format. - static String string(String uuid) { - uuid = uuid.trim(); - if (uuid.length < 4) { - throw const FormatException('Invalid UUID'); - } - - if (uuid.startsWith('0x')) { - uuid = uuid.substring(2); - } - - if (uuid.length <= 8) { - uuid = "${uuid.padLeft(8, '0')}-0000-1000-8000-00805f9b34fb"; - } - - if (!uuid.contains("-")) { - if (uuid.length != 32) throw const FormatException("Invalid UUID"); - - uuid = "${uuid.substring(0, 8)}-${uuid.substring(8, 12)}" - "-${uuid.substring(12, 16)}-${uuid.substring(16, 20)}-${uuid.substring(20, 32)}"; - } - - var groups = uuid.split('-'); - - if (groups.length != 5 || - groups[0].length != 8 || - groups[1].length != 4 || - groups[2].length != 4 || - groups[3].length != 4 || - groups[4].length != 12) { - throw const FormatException('Invalid UUID'); - } - - try { - int.parse(groups[0], radix: 16); - int.parse(groups[1], radix: 16); - int.parse(groups[2], radix: 16); - int.parse(groups[3], radix: 16); - int.parse(groups[4], radix: 16); - } catch (e) { - throw const FormatException('Invalid UUID'); - } - - return uuid.toLowerCase(); - } - - /// Parse an int number into a 128-bit UUID string. - /// e.g. `0x1800` to `00001800-0000-1000-8000-00805f9b34fb`. - static String number(int short) { - if (short <= 0xFF || short > 0xFFFF) { - throw const FormatException('Invalid UUID'); - } - return string(short.toRadixString(16).padLeft(4, '0')); - } - - /// Compare two UUIDs regardless of their format. - /// Throws `FormatException` if the UUID is invalid. - static bool compareStrings(String uuid1, String uuid2) => - string(uuid1) == string(uuid2); -} - -/// Parse a list of strings to a list of UUIDs. -extension StringListToUUID on List { - List toValidUUIDList() => map(BleUuidParser.string).toList(); -} diff --git a/universal_ble/lib/src/models/manufacturer_data.dart b/universal_ble/lib/src/models/manufacturer_data.dart deleted file mode 100644 index c6a64ba..0000000 --- a/universal_ble/lib/src/models/manufacturer_data.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:flutter/foundation.dart'; - -/// Represents the manufacturer data of a BLE device. -class ManufacturerData { - final int companyId; - final Uint8List payload; - ManufacturerData(this.companyId, this.payload); - - String get companyIdRadix16 => "0x0${companyId.toRadixString(16)}"; - - factory ManufacturerData.fromData(Uint8List data) { - if (data.length < 2) { - throw const FormatException("Invalid Manufacturer Data"); - } - return ManufacturerData( - (data[0] + (data[1] << 8)), - data.sublist(2), - ); - } - - Uint8List toUint8List() { - final byteData = ByteData(2); - byteData.setInt16(0, companyId, Endian.host); - return Uint8List.fromList( - byteData.buffer.asUint8List() + payload.toList(), - ); - } - - @override - int get hashCode => companyId.hashCode ^ payload.hashCode; - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other is! ManufacturerData) return false; - return companyId == other.companyId && listEquals(payload, other.payload); - } - - @override - String toString() { - return 'Manufacturer: $companyIdRadix16 - $payload'; - } -} diff --git a/universal_ble/lib/src/models/manufacturer_data_filter.dart b/universal_ble/lib/src/models/manufacturer_data_filter.dart deleted file mode 100644 index e1d68f0..0000000 --- a/universal_ble/lib/src/models/manufacturer_data_filter.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'dart:typed_data'; - -class ManufacturerDataFilter { - /// Must be of integer type, in hex or decimal form (e.g. 0x004c or 76). - int companyIdentifier; - - /// Matches as prefix the peripheral's advertised data. - Uint8List? payloadPrefix; - - /// For each bit in the mask, set it to 1 if it needs to match - /// the corresponding one in manufacturer data, or otherwise set it to 0. - /// The 'mask' must have the same length as the payload. - Uint8List? payloadMask; - - /// Filter manufacturer data by company identifier, payload prefix, or payload mask. - ManufacturerDataFilter({ - required this.companyIdentifier, - this.payloadPrefix, - this.payloadMask, - }); - - @override - String toString() { - return 'ManufacturerDataFilter(companyIdentifier: $companyIdentifier, payloadPrefix: $payloadPrefix, mask: $payloadMask)'; - } -} diff --git a/universal_ble/lib/src/models/model_exports.dart b/universal_ble/lib/src/models/model_exports.dart deleted file mode 100644 index 07e5354..0000000 --- a/universal_ble/lib/src/models/model_exports.dart +++ /dev/null @@ -1,14 +0,0 @@ -export 'package:universal_ble/src/models/ble_connection_update.dart'; -export 'package:universal_ble/src/models/manufacturer_data.dart'; -export 'package:universal_ble/src/models/platform_config.dart'; -export 'package:universal_ble/src/models/queue_type.dart'; -export 'package:universal_ble/src/models/ble_uuid_parser.dart'; -export 'package:universal_ble/src/models/scan_filter.dart'; -export 'package:universal_ble/src/models/manufacturer_data_filter.dart'; -export 'package:universal_ble/src/models/ble_property.dart'; -export 'package:universal_ble/src/models/ble_service.dart'; -export 'package:universal_ble/src/models/availability_state.dart'; -export 'package:universal_ble/src/models/ble_connection_state.dart'; -export 'package:universal_ble/src/models/ble_device.dart'; -export 'package:universal_ble/src/models/ble_command.dart'; -export 'package:universal_ble/src/models/ble_capabilities.dart'; diff --git a/universal_ble/lib/src/models/platform_config.dart b/universal_ble/lib/src/models/platform_config.dart deleted file mode 100644 index df2c823..0000000 --- a/universal_ble/lib/src/models/platform_config.dart +++ /dev/null @@ -1,23 +0,0 @@ -/// Platform specific config to scan devices -class PlatformConfig { - WebOptions? web; - - PlatformConfig({this.web}); -} - -/// Web options to scan devices -/// [optionalServices] is a list of service uuid's to ensure that you can access the specified services after connecting to the device, -/// by default services from scanFilter will be used -/// [optionalManufacturerData] is list of `CompanyIdentifier's` and used to add `ManufacturerData` in advertisement results of selected device from web dialog, -/// by default manufacturerData from scanFilter will be used -/// Checkout more details on [web](https://developer.mozilla.org/en-US/docs/Web/API/Bluetooth/requestDevice) -/// Note: you will only get advertisements if Experimental Flag is enabled in the browser -class WebOptions { - List optionalServices; - List optionalManufacturerData; - - WebOptions({ - this.optionalServices = const [], - this.optionalManufacturerData = const [], - }); -} diff --git a/universal_ble/lib/src/models/queue_type.dart b/universal_ble/lib/src/models/queue_type.dart deleted file mode 100644 index b516d1d..0000000 --- a/universal_ble/lib/src/models/queue_type.dart +++ /dev/null @@ -1,5 +0,0 @@ -enum QueueType { - none, - perDevice, - global, -} diff --git a/universal_ble/lib/src/models/scan_filter.dart b/universal_ble/lib/src/models/scan_filter.dart deleted file mode 100644 index 31455ef..0000000 --- a/universal_ble/lib/src/models/scan_filter.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:universal_ble/src/models/manufacturer_data_filter.dart'; - -class ScanFilter { - List withServices; - List withManufacturerData; - List withNamePrefix; - - ScanFilter({ - this.withServices = const [], - this.withManufacturerData = const [], - this.withNamePrefix = const [], - }); - - @override - String toString() { - return 'ScanFilter(withServices: $withServices, withManufacturerData: $withManufacturerData, withNamePrefix: $withNamePrefix)'; - } -} diff --git a/universal_ble/lib/src/queue.dart b/universal_ble/lib/src/queue.dart deleted file mode 100644 index 1203bce..0000000 --- a/universal_ble/lib/src/queue.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'dart:async'; - -/// Original Author: Ryan Knell (https://github.com/rknell/dart_queue) - -/// Queue to execute Futures in order. -/// It awaits each future before executing the next one. -class Queue { - final Set _activeItems = {}; - int _lastProcessId = 0; - bool _isCancelled = false; - final List<_QueuedFuture> _nextCycle = []; - Function(int)? onRemainingItemsUpdate; - - Future add(Future Function() closure, [Duration? timeout]) { - if (_isCancelled) throw Exception('Queue Cancelled'); - final completer = Completer(); - _nextCycle.add(_QueuedFuture(closure, completer, timeout)); - _updateRemainingItems(); - if (_activeItems.isEmpty) _queueUpNext(); - return completer.future; - } - - void dispose() { - for (final item in _nextCycle) { - item.completer.completeError(Exception('Queue Cancelled')); - } - _nextCycle.removeWhere((item) => item.completer.isCompleted); - _isCancelled = true; - } - - void _queueUpNext() { - if (_nextCycle.isNotEmpty && !_isCancelled && _activeItems.length <= 1) { - final processId = _lastProcessId; - _activeItems.add(processId); - final item = _nextCycle.first; - _lastProcessId++; - _nextCycle.remove(item); - item.onComplete = () async { - _activeItems.remove(processId); - _updateRemainingItems(); - _queueUpNext(); - }; - unawaited(item.execute()); - } - } - - void _updateRemainingItems() { - int remainingQueueItems = _nextCycle.length + _activeItems.length; - onRemainingItemsUpdate?.call(remainingQueueItems); - } -} - -class _QueuedFuture { - final Completer completer; - final Future Function() closure; - Function? onComplete; - final Duration? timeout; - - _QueuedFuture(this.closure, this.completer, this.timeout, {this.onComplete}); - - Future execute() async { - try { - T result; - if (timeout != null) { - result = await closure().timeout(timeout!); - } else { - result = await closure(); - } - if (result != null) { - completer.complete(result); - } else { - completer.complete(null); - } - await Future.microtask(() {}); - } catch (e, stack) { - completer.completeError(e, stack); - } finally { - if (onComplete != null) onComplete?.call(); - } - } -} diff --git a/universal_ble/lib/src/universal_ble.dart b/universal_ble/lib/src/universal_ble.dart deleted file mode 100644 index 874c6ba..0000000 --- a/universal_ble/lib/src/universal_ble.dart +++ /dev/null @@ -1,504 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/foundation.dart'; -import 'package:universal_ble/src/ble_command_queue.dart'; -import 'package:universal_ble/src/universal_ble_linux/universal_ble_linux.dart'; -import 'package:universal_ble/src/universal_ble_pigeon/universal_ble_pigeon_channel.dart'; -import 'package:universal_ble/src/universal_ble_web/universal_ble_web.dart'; -import 'package:universal_ble/src/universal_logger.dart'; -import 'package:universal_ble/universal_ble.dart'; - -class UniversalBle { - /// Get platform specific implementation. - static UniversalBlePlatform _platform = _defaultPlatform(); - static final BleCommandQueue _bleCommandQueue = BleCommandQueue(); - - /// Set custom platform specific implementation (e.g. for testing). - static void setInstance(UniversalBlePlatform instance) => - _platform = instance; - - /// Set global timeout for all commands. - /// Default timeout is 10 seconds. - /// Set to null to disable. - static set timeout(Duration? duration) { - _bleCommandQueue.timeout = duration; - } - - /// Set how commands will be executed. By default, all commands are executed in a global queue (`QueueType.global`), - /// with each command waiting for the previous one to finish. - /// - /// [QueueType.global] will execute commands of all devices in a single queue. - /// [QueueType.perDevice] will execute command of each device in separate queues. - /// [QueueType.none] will execute all commands in parallel. - static set queueType(QueueType queueType) { - _bleCommandQueue.queueType = queueType; - UniversalLogger.logInfo('Queue ${queueType.name}'); - } - - /// Get Bluetooth availability state. - /// To be notified of updates, set [onAvailabilityChange] listener. - static Future getBluetoothAvailabilityState() async { - return await _bleCommandQueue.queueCommand( - () => _platform.getBluetoothAvailabilityState(), - ); - } - - /// Start scan. - /// Scan results will arrive in [onScanResult] listener. - /// It might throw errors if Bluetooth is not available. - /// `webRequestOptions` is supported on Web only. - static Future startScan({ - ScanFilter? scanFilter, - PlatformConfig? platformConfig, - }) async { - return await _bleCommandQueue.queueCommand( - () => _platform.startScan( - scanFilter: scanFilter, - platformConfig: platformConfig, - ), - withTimeout: false, - ); - } - - /// Stop scan. - /// Set [onScanResult] listener to `null` if you don't need it anymore. - /// It might throw errors if Bluetooth is not available. - static Future stopScan() async { - return await _bleCommandQueue.queueCommand( - () => _platform.stopScan(), - withTimeout: false, - ); - } - - /// Connection stream of a device - static Stream connectionStream(String deviceId) => - _platform.connectionStream(deviceId); - - /// Connect to a device. - /// It is advised to stop scanning before connecting. - /// It throws error if device connection fails. - /// Default connection timeout is 60 sec. - /// Can throw `ConnectionException` or `PlatformException`. - static Future connect( - String deviceId, { - Duration? connectionTimeout, - }) async { - connectionTimeout ??= const Duration(seconds: 60); - StreamSubscription? connectionSubscription; - - try { - Completer completer = Completer(); - - connectionSubscription = connectionStream(deviceId).listen( - (BleConnectionUpdate event) { - connectionSubscription?.cancel(); - if (!completer.isCompleted) { - String? error = event.error; - if (error != null) { - completer.completeError(ConnectionException(error)); - } else { - completer.complete(event.isConnected); - } - } - }, - onError: (error) { - if (!completer.isCompleted) { - connectionSubscription?.cancel(); - completer.completeError(ConnectionException(error)); - } - }, - ); - - _platform - .connect(deviceId, connectionTimeout: connectionTimeout) - .catchError( - (error) { - if (!completer.isCompleted) { - connectionSubscription?.cancel(); - completer.completeError(ConnectionException(error)); - } - }, - ); - - if (!await completer.future.timeout(connectionTimeout)) { - throw ConnectionException("Failed to connect"); - } - } finally { - connectionSubscription?.cancel(); - } - } - - /// Disconnect from a device. - /// Get notified of connection state changes in [onConnectionChange] listener. - static Future disconnect(String deviceId) async { - return await _bleCommandQueue.queueCommand( - () => _platform.disconnect(deviceId), - deviceId: deviceId, - ); - } - - /// Discover services of a device. - static Future> discoverServices(String deviceId) async { - return await _bleCommandQueue.queueCommand( - () => _platform.discoverServices(deviceId), - deviceId: deviceId, - ); - } - - /// Set a characteristic notifiable. - /// Set `bleInputProperty` to [BleInputProperty.notification] or [BleInputProperty.indication]. - /// Updates will arrive in [onValueChange] listener. - /// To stop listening to a characteristic, set `bleInputProperty` to [BleInputProperty.disabled]. - static Future setNotifiable( - String deviceId, - String service, - String characteristic, - BleInputProperty bleInputProperty, - ) async { - return await _bleCommandQueue.queueCommand( - () => _platform.setNotifiable( - deviceId, - BleUuidParser.string(service), - BleUuidParser.string(characteristic), - bleInputProperty, - ), - deviceId: deviceId, - ); - } - - /// Read a characteristic value. - /// On iOS and MacOS this command will also trigger [onValueChange] listener. - static Future readValue( - String deviceId, - String service, - String characteristic, { - final Duration? timeout, - }) async { - return await _bleCommandQueue.queueCommand( - () => _platform.readValue( - deviceId, - BleUuidParser.string(service), - BleUuidParser.string(characteristic), - timeout: timeout ?? _bleCommandQueue.timeout, - ), - timeout: timeout, - deviceId: deviceId, - ); - } - - /// Write a characteristic value. - /// To write a characteristic value with response, set `bleOutputProperty` to [BleOutputProperty.withResponse]. - static Future writeValue( - String deviceId, - String service, - String characteristic, - Uint8List value, - BleOutputProperty bleOutputProperty, - ) async { - await _bleCommandQueue.queueCommand( - () => _platform.writeValue( - deviceId, - BleUuidParser.string(service), - BleUuidParser.string(characteristic), - value, - bleOutputProperty, - ), - deviceId: deviceId, - ); - } - - /// Request MTU value. - /// It will **attempt** to set the MTU (Maximum Transmission Unit) but it is not guaranteed to succeed due to platform limitations. - /// It will always return the current MTU. - static Future requestMtu(String deviceId, int expectedMtu) async { - return await _bleCommandQueue.queueCommand( - () => _platform.requestMtu(deviceId, expectedMtu), - deviceId: deviceId, - ); - } - - /// Check if a device is paired. - /// - /// For `Apple` and `Web`, you have to pass a "pairingCommand" with an encrypted read or write characteristic. - /// Returns true/false if it manages to execute the command. - /// Returns null when no `pairingCommand` is passed. - /// Note that it will trigger pairing if the device is not already paired. - static Future isPaired( - String deviceId, { - BleCommand? pairingCommand, - Duration? connectionTimeout, - }) async { - if (BleCapabilities.hasSystemPairingApi) { - return _bleCommandQueue.queueCommand( - () => _platform.isPaired(deviceId), - deviceId: deviceId, - ); - } - - if (pairingCommand == null) { - UniversalLogger.logWarning("PairingCommand required to get result"); - return null; - } - - try { - await _connectAndExecuteBleCommand( - deviceId, - pairingCommand, - connectionTimeout: connectionTimeout, - updateCallbackValue: false, - ); - - // Because pairingCommand will be never null, so we wont get Unknown result here - return true; - } catch (e) { - UniversalLogger.logError("ExecuteBleCommandFailed: $e"); - return false; - } - } - - /// Pair a device. - /// - /// It throws error if pairing fails. - /// - /// On `Apple` and `Web`, it only works on devices with encrypted characteristics. - /// It is advised to pass a pairingCommand with an encrypted read or write characteristic. - /// When not passing a pairingCommand, you should afterwards use [isPaired] with a pairingCommand - /// to verify the pairing state. - /// - /// On `Web/Windows` and `Web/Linux`, it does not work for devices that use `ConfirmOnly` pairing. - /// Can throw `PairingException`, `ConnectionException` or `PlatformException`. - static Future pair( - String deviceId, { - BleCommand? pairingCommand, - Duration? connectionTimeout, - }) async { - if (BleCapabilities.hasSystemPairingApi) { - bool paired = await _platform.pair(deviceId); - if (!paired) throw PairingException(); - } else { - if (pairingCommand == null) { - UniversalLogger.logWarning("PairingCommand required to get result"); - } - await _connectAndExecuteBleCommand( - deviceId, - pairingCommand, - connectionTimeout: connectionTimeout, - ); - } - } - - /// Unpair a device. - /// It might throw an error if device is not paired. - static Future unpair(String deviceId) async { - return await _bleCommandQueue.queueCommand( - () => _platform.unpair(deviceId), - deviceId: deviceId, - ); - } - - /// Get connected devices to the system (connected by any app). - /// Use [withServices] to filter devices by services. - /// On `Apple`, [withServices] is required to get any connected devices. If not passed, several [18XX] generic services will be set by default. - /// On `Android`, `Linux` and `Windows`, if [withServices] is used, then internally all services will be discovered for each device first (either by connecting or by using cached services). - /// Not supported on `Web`. - static Future> getSystemDevices({ - List? withServices, - }) async { - return await _bleCommandQueue.queueCommand( - () => _platform.getSystemDevices(withServices?.toValidUUIDList()), - ); - } - - /// Returns connection state of the device. - /// All platforms will return `Connected/Disconnected` states. - /// `Android` and `Apple` can also return `Connecting/Disconnecting` states. - static Future getConnectionState(String deviceId) async { - return await _bleCommandQueue.queueCommand( - () => _platform.getConnectionState(deviceId), - ); - } - - /// Enable Bluetooth. - /// It might throw errors if Bluetooth is not available. - /// Not supported on `Web` and `Apple`. - static Future enableBluetooth() async { - return await _bleCommandQueue.queueCommand( - () => _platform.enableBluetooth(), - ); - } - - /// Disable Bluetooth. - /// It might throw errors if Bluetooth is not available. - /// Not supported on `Web` and `Apple`. - static Future disableBluetooth() async { - return await _bleCommandQueue.queueCommand( - () => _platform.disableBluetooth(), - ); - } - - /// [receivesAdvertisements] returns true on web if the browser supports receiving advertisements from a certain `deviceId`. - /// The rest of the platforms will always return true. - /// If true, then you will be getting scanResult updates for this device. - /// - /// For this feature to work, you need to enable the `chrome://flags/#enable-experimental-web-platform-features` flag. - /// Not every browser supports this API yet. - /// Even if the browser supports it, sometimes it won't fire any advertisement events even though the device may be sending them. - static bool receivesAdvertisements(String deviceId) => - _platform.receivesAdvertisements(deviceId); - - /// Get Bluetooth state availability. - static set onAvailabilityChange(OnAvailabilityChange? onAvailabilityChange) { - _platform.onAvailabilityChange = onAvailabilityChange; - if (onAvailabilityChange != null) { - getBluetoothAvailabilityState().then((value) { - onAvailabilityChange(value); - }).onError((error, stackTrace) => null); - } - } - - static Future _connectAndExecuteBleCommand( - String deviceId, - BleCommand? bleCommand, { - Duration? connectionTimeout, - bool updateCallbackValue = false, - }) async { - // Try to connect first - if (await getConnectionState(deviceId) != BleConnectionState.connected) { - UniversalLogger.logInfo("Connecting to $deviceId"); - await connect( - deviceId, - connectionTimeout: connectionTimeout, - ); - } - - List services = await discoverServices(deviceId); - UniversalLogger.logInfo("Discovered services: ${services.length}"); - - if (bleCommand == null) { - // Just attempt pairing - await _attemptPairingReadingAll(deviceId, services); - return; - } - - await _executeBleCommand(deviceId, services, bleCommand); - if (updateCallbackValue) _platform.updatePairingState(deviceId, true); - } - - // Fire and forget, and do not rely on result - static _attemptPairingReadingAll( - String deviceId, - List services, - ) async { - bool containsReadCharacteristics = false; - try { - // If BleCommand not given, fallback to reading all characteristics - for (BleService service in services) { - for (BleCharacteristic characteristic in service.characteristics) { - if (characteristic.properties.contains(CharacteristicProperty.read)) { - containsReadCharacteristics = true; - await readValue( - deviceId, - service.uuid, - characteristic.uuid, - timeout: const Duration(seconds: 30), - ); - } - } - } - } catch (_) {} - - if (!containsReadCharacteristics) { - throw PairingException("No readable characteristic found"); - } - } - - static Future _executeBleCommand( - String deviceId, - List services, - BleCommand bleCommand, - ) async { - // First find BleCommand's characteristic - BleCharacteristic? characteristic; - for (BleService service in services) { - if (BleUuidParser.compareStrings(service.uuid, bleCommand.service)) { - for (BleCharacteristic char in service.characteristics) { - if (BleUuidParser.compareStrings( - char.uuid, bleCommand.characteristic)) { - characteristic = char; - break; - } - } - } - } - - if (characteristic == null) { - throw PairingException("BleCommand not found in discovered services"); - } - - // Check if BleCommand Supports Read or Write - BleOutputProperty? bleOutputProperty; - if (characteristic.properties.contains(CharacteristicProperty.write)) { - bleOutputProperty = BleOutputProperty.withResponse; - } else if (characteristic.properties - .contains(CharacteristicProperty.writeWithoutResponse)) { - bleOutputProperty = BleOutputProperty.withoutResponse; - } else if (!characteristic.properties - .contains(CharacteristicProperty.read)) { - throw PairingException( - "BleCommand does not support read or write operation", - ); - } - - Uint8List? value = bleCommand.writeValue; - - try { - if (value != null && bleOutputProperty != null) { - await writeValue( - deviceId, - bleCommand.service, - bleCommand.characteristic, - value, - bleOutputProperty, - ); - } else { - // Fallback to read if supported - await readValue( - deviceId, - bleCommand.service, - bleCommand.characteristic, - timeout: const Duration(seconds: 30), - ); - } - } catch (e) { - throw PairingException(e.toString()); - } - } - - /// Get updates of remaining items of a queue. - static set onQueueUpdate(OnQueueUpdate? onQueueUpdate) => - _bleCommandQueue.onQueueUpdate = onQueueUpdate; - - /// Get scan results. - static set onScanResult(OnScanResult? bleDevice) => - _platform.onScanResult = bleDevice; - - /// Get connection state changes. - static set onConnectionChange(OnConnectionChange? onConnectionChange) => - _platform.onConnectionChange = onConnectionChange; - - /// Get characteristic value updates, set `bleInputProperty` in [setNotifiable] to [BleInputProperty.notification] or [BleInputProperty.indication]. - static set onValueChange(OnValueChange? onValueChange) => - _platform.onValueChange = onValueChange; - - /// Get pair state changes. - static set onPairingStateChange(OnPairingStateChange pairingStateChange) => - _platform.onPairingStateChange = pairingStateChange; - - static UniversalBlePlatform _defaultPlatform() { - if (kIsWeb) return UniversalBleWeb.instance; - if (defaultTargetPlatform == TargetPlatform.linux) { - return UniversalBleLinux.instance; - } - return UniversalBlePigeonChannel.instance; - } -} diff --git a/universal_ble/lib/src/universal_ble_exceptions.dart b/universal_ble/lib/src/universal_ble_exceptions.dart deleted file mode 100644 index 15275b9..0000000 --- a/universal_ble/lib/src/universal_ble_exceptions.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:flutter/services.dart'; - -class ConnectionException implements Exception { - late String message; - - ConnectionException([dynamic error]) { - message = _errorParser(error); - } - - @override - String toString() => message; -} - -class PairingException implements Exception { - late String message; - - PairingException([dynamic error]) { - message = _errorParser(error); - } - - @override - String toString() => message; -} - -String _errorParser(dynamic error) { - if (error == null) { - return "Failed"; - } else if (error is PlatformException) { - return error.message ?? error.details ?? error.code; - } else if (error is String) { - return error; - } else { - return error.toString(); - } -} diff --git a/universal_ble/lib/src/universal_ble_filter_util.dart b/universal_ble/lib/src/universal_ble_filter_util.dart deleted file mode 100644 index e4d3345..0000000 --- a/universal_ble/lib/src/universal_ble_filter_util.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'dart:typed_data'; - -import 'package:universal_ble/universal_ble.dart'; - -// A default Filter on dart side -// Used on Linux only -class UniversalBleFilterUtil { - ScanFilter? scanFilter; - - bool matchesDevice(BleDevice device) { - final filter = scanFilter; - if (filter == null) return true; - - final hasNamePrefixFilter = filter.withNamePrefix.isNotEmpty; - final hasServiceFilter = filter.withServices.isNotEmpty; - final hasManufacturerDataFilter = filter.withManufacturerData.isNotEmpty; - - // If there is no filter at all, then allow device - if (!hasNamePrefixFilter && - !hasServiceFilter && - !hasManufacturerDataFilter) { - return true; - } - - // Else check one of the filter passes - return hasNamePrefixFilter && nameMatches(filter, device) || - hasServiceFilter && servicesMatch(filter, device) || - hasManufacturerDataFilter && manufacturerDataMatches(filter, device); - } - - bool nameMatches(ScanFilter scanFilter, BleDevice device) { - var namePrefixFilter = scanFilter.withNamePrefix; - if (namePrefixFilter.isEmpty) return true; - - String? name = device.name; - if (name == null || name.isEmpty) return false; - return namePrefixFilter.any(name.startsWith); - } - - bool servicesMatch(ScanFilter scanFilter, BleDevice device) { - var serviceFilters = scanFilter.withServices; - if (serviceFilters.isEmpty) return true; - - List serviceUuids = device.services; - if (serviceUuids.isEmpty) { - return false; - } - return serviceFilters.any(serviceUuids.contains); - } - - bool manufacturerDataMatches(ScanFilter scanFilter, BleDevice device) { - final manufacturerDataFilters = scanFilter.withManufacturerData; - if (manufacturerDataFilters.isEmpty) return true; - - List deviceDataList = device.manufacturerDataList; - if (deviceDataList.isEmpty) return false; - - return deviceDataList - .any((deviceData) => manufacturerDataFilters.any((filter) { - // Early return if company identifiers don't match - if (filter.companyIdentifier != deviceData.companyId) { - return false; - } - - final payloadPrefix = filter.payloadPrefix; - final payload = deviceData.payload; - - // Handle cases where payload prefix is null or empty - if (payloadPrefix == null || payloadPrefix.isEmpty) { - return true; - } - - // Validate payload lengths - if (payload.isEmpty || payloadPrefix.length > payload.length) { - return false; - } - - final filterMask = filter.payloadMask; - - // Choose comparison strategy based on filter mask - return filterMask != null && - filterMask.length == payloadPrefix.length - ? _compareWithMask(payloadPrefix, payload, filterMask) - : _compareWithoutMask(payloadPrefix, payload); - })); - } - - bool _compareWithMask(Uint8List prefix, Uint8List payload, Uint8List mask) { - for (int i = 0; i < prefix.length; i++) { - if ((prefix[i] & mask[i]) != (payload[i] & mask[i])) { - return false; - } - } - return true; - } - - bool _compareWithoutMask(Uint8List prefix, Uint8List payload) { - for (int i = 0; i < prefix.length; i++) { - if (prefix[i] != payload[i]) { - return false; - } - } - return true; - } -} diff --git a/universal_ble/lib/src/universal_ble_linux/universal_ble_linux.dart b/universal_ble/lib/src/universal_ble_linux/universal_ble_linux.dart deleted file mode 100644 index 4827c46..0000000 --- a/universal_ble/lib/src/universal_ble_linux/universal_ble_linux.dart +++ /dev/null @@ -1,613 +0,0 @@ -import 'dart:async'; - -import 'package:bluez/bluez.dart'; -import 'package:flutter/services.dart'; -import 'package:universal_ble/src/models/model_exports.dart'; -import 'package:universal_ble/src/universal_ble_filter_util.dart'; -import 'package:universal_ble/src/universal_ble_platform_interface.dart'; -import 'package:universal_ble/src/universal_logger.dart'; - -class UniversalBleLinux extends UniversalBlePlatform { - UniversalBleLinux._(); - static UniversalBleLinux? _instance; - static UniversalBleLinux get instance => _instance ??= UniversalBleLinux._(); - - bool isInitialized = false; - - final BlueZClient _client = BlueZClient(); - late final UniversalBleFilterUtil _bleFilter = UniversalBleFilterUtil(); - BlueZAdapter? _activeAdapter; - StreamSubscription? _deviceAdded; - StreamSubscription? _deviceRemoved; - Completer? _initializationCompleter; - final Map _devices = {}; - final Map _deviceUpdateStreamSubscriptions = {}; - final Map _deviceAdvertisementSubscriptions = {}; - - final Map _characteristicPropertiesSubscriptions = - {}; - - @override - Future getBluetoothAvailabilityState() async { - await _ensureInitialized(); - - BlueZAdapter? adapter = _activeAdapter; - if (adapter == null) { - return AvailabilityState.unsupported; - } - return adapter.powered - ? AvailabilityState.poweredOn - : AvailabilityState.poweredOff; - } - - @override - Future enableBluetooth() async { - await _ensureInitialized(); - if (_activeAdapter?.powered == true) return true; - try { - await _activeAdapter?.setPowered(true); - return _activeAdapter?.powered ?? false; - } catch (e) { - UniversalLogger.logError('Error enabling bluetooth: $e'); - return false; - } - } - - @override - Future disableBluetooth() async { - await _ensureInitialized(); - var adapter = _activeAdapter; - if (adapter == null) { - throw "Adapter not available"; - } - if (!adapter.powered) return true; - try { - await adapter.setPowered(false); - return !adapter.powered; - } catch (e) { - UniversalLogger.logError('Error disabling bluetooth: $e'); - return false; - } - } - - @override - Future startScan({ - ScanFilter? scanFilter, - PlatformConfig? platformConfig, - }) async { - await _ensureInitialized(); - var adapter = _activeAdapter; - if (adapter == null) { - throw "Adapter not available"; - } - - // Stop scan and clean all old advertisement listeners - await stopScan(); - - _bleFilter.scanFilter = scanFilter; - - // Setup listeners - _deviceAdded ??= _client.deviceAdded.listen(_onDeviceAdd); - _deviceRemoved ??= _client.deviceRemoved.listen(_onDeviceRemoved); - - await adapter.startDiscovery(); - - for (var device in _client.devices) { - _onDeviceAdd(device); - } - } - - @override - Future stopScan() async { - await _ensureInitialized(); - try { - // Dispose listeners - _deviceAdded?.cancel(); - _deviceRemoved?.cancel(); - _deviceAdded = null; - _deviceRemoved = null; - - // Stop Discovery - if (_activeAdapter?.discovering == true) { - await _activeAdapter?.stopDiscovery(); - } - - // Clean all advertisement listeners - _deviceAdvertisementSubscriptions.removeWhere((e, value) { - value.cancel(); - return true; - }); - } catch (e) { - UniversalLogger.logError("stopScan error: $e"); - } - } - - @override - Future getConnectionState(String deviceId) async { - BlueZDevice? device = _devices[deviceId] ?? - _client.devices.cast().firstWhere( - (device) => device?.address == deviceId, - orElse: () => null); - bool connected = device?.connected ?? false; - return connected - ? BleConnectionState.connected - : BleConnectionState.disconnected; - } - - @override - Future connect(String deviceId, {Duration? connectionTimeout}) async { - final device = _findDeviceById(deviceId); - if (device.connected) { - updateConnection(deviceId, true); - return; - } - await device.connect(); - } - - @override - Future disconnect(String deviceId) async { - final device = _findDeviceById(deviceId); - if (!device.connected) { - updateConnection(deviceId, false); - return; - } - await device.disconnect(); - } - - @override - Future> discoverServices(String deviceId) async { - final device = _findDeviceById(deviceId); - if (device.gattServices.isEmpty && !device.servicesResolved) { - await device.propertiesChanged.firstWhere((element) { - if (element.contains(BluezProperty.connected)) { - if (!device.connected) { - UniversalLogger.logInfo( - "DiscoverServicesFailed: Device disconnected", - ); - return true; - } - } - return element.contains(BluezProperty.servicesResolved); - }).timeout(const Duration(seconds: 10), onTimeout: () { - UniversalLogger.logInfo( - "DiscoverServicesFailed: Timeout", - ); - return []; - }); - } - - // Few ble devices requires delay to perform operations after discovering services - await Future.delayed(const Duration(seconds: 1)); - - if (device.gattServices.isEmpty && !device.servicesResolved) { - throw "Failed to resolve services"; - } - - List services = []; - for (final service in device.gattServices) { - final characteristics = service.characteristics.map((e) { - final properties = List.from(e.flags - .map((e) => e.toCharacteristicProperty()) - .where((element) => element != null) - .toList()); - return BleCharacteristic(e.uuid.toString(), properties); - }).toList(); - services.add(BleService(service.uuid.toString(), characteristics)); - } - return services; - } - - BlueZGattCharacteristic _getCharacteristic( - String deviceId, String service, String characteristic) { - final device = _findDeviceById(deviceId); - final s = device.gattServices - .cast() - .firstWhere((s) => s?.uuid.toString() == service, orElse: () => null); - final c = s?.characteristics.cast().firstWhere( - (c) => c?.uuid.toString() == characteristic, - orElse: () => null); - - if (c == null) { - throw Exception('Unknown characteristic:$characteristic'); - } - return c; - } - - @override - Future setNotifiable(String deviceId, String service, - String characteristic, BleInputProperty bleInputProperty) async { - final char = _getCharacteristic(deviceId, service, characteristic); - - String characteristicKey = "${deviceId}_${service}_$characteristic"; - - if (bleInputProperty != BleInputProperty.disabled) { - if (char.notifying) { - UniversalLogger.logInfo('$characteristic already notifying'); - return; - } - - await char.startNotify(); - - if (_characteristicPropertiesSubscriptions[characteristicKey] != null) { - _characteristicPropertiesSubscriptions[characteristicKey]?.cancel(); - } - - _characteristicPropertiesSubscriptions[characteristicKey] = - char.propertiesChanged.listen((List properties) { - for (String property in properties) { - switch (property) { - case BluezProperty.value: - updateCharacteristicValue( - deviceId, - characteristic, - Uint8List.fromList(char.value), - ); - break; - default: - UniversalLogger.logInfo( - "UnhandledCharValuePropertyChange: $property", - ); - } - } - }); - } else { - if (char.notifying) await char.stopNotify(); - _characteristicPropertiesSubscriptions - .remove(characteristicKey) - ?.cancel(); - } - } - - @override - Future readValue( - String deviceId, - String service, - String characteristic, { - final Duration? timeout, - }) async { - try { - final c = _getCharacteristic(deviceId, service, characteristic); - final data = await c.readValue(); - return Uint8List.fromList(data); - } on BlueZFailedException catch (e) { - throw PlatformException( - code: e.errorCode ?? "ReadFailed", - message: e.message, - ); - } - } - - @override - Future writeValue( - String deviceId, - String service, - String characteristic, - Uint8List value, - BleOutputProperty bleOutputProperty) async { - try { - final c = _getCharacteristic(deviceId, service, characteristic); - if (bleOutputProperty == BleOutputProperty.withResponse) { - await c.writeValue( - value, - type: BlueZGattCharacteristicWriteType.request, - ); - } else { - await c.writeValue( - value, - type: BlueZGattCharacteristicWriteType.command, - ); - } - } on BlueZFailedException catch (e) { - throw PlatformException( - code: e.errorCode ?? "WriteFailed", - message: e.message, - ); - } - } - - @override - Future requestMtu(String deviceId, int expectedMtu) async { - final device = _findDeviceById(deviceId); - if (!device.connected) throw Exception('Device not connected'); - for (BlueZGattService service in device.gattServices) { - for (BlueZGattCharacteristic characteristic in service.characteristics) { - int? mtu = characteristic.mtu; - // The value provided by Bluez includes an extra 3 bytes from the GATT header, which needs to be removed. - if (mtu != null) return mtu - 3; - } - } - throw Exception('MTU not available'); - } - - @override - Future pair(String deviceId) async { - BlueZDevice device = _findDeviceById(deviceId); - try { - if (device.paired) return true; - await device.pair(); - return true; - } catch (error) { - updatePairingState(deviceId, false); - return false; - } - } - - @override - Future unpair(String deviceId) async { - BlueZDevice device = _findDeviceById(deviceId); - if (device.paired) { - // await device.cancelPairing(); - await _activeAdapter?.removeDevice(device); - } - } - - @override - Future isPaired(String deviceId) async { - return _findDeviceById(deviceId).paired; - } - - @override - Future> getSystemDevices( - List? withServices, - ) async { - List devices = - _client.devices.where((device) => device.connected).toList(); - if (withServices != null && withServices.isNotEmpty) { - devices = devices.where((device) { - if (device.servicesResolved) { - return device.gattServices - .map((e) => e.uuid.toString()) - .any((service) => withServices.contains(service)); - } else { - UniversalLogger.logInfo( - 'Skipping: ${device.address}: Services not resolved yet.', - ); - return false; - } - }).toList(); - } - return devices - .map((device) => device.toBleDevice(isSystemDevice: true)) - .toList(); - } - - AvailabilityState get _availabilityState { - return _activeAdapter?.powered == true - ? AvailabilityState.poweredOn - : AvailabilityState.poweredOff; - } - - BlueZDevice _findDeviceById(String deviceId) { - final device = _devices[deviceId] ?? - _client.devices.cast().firstWhere( - (device) => device?.address == deviceId, - orElse: () => null); - if (device == null) { - throw Exception('Unknown deviceId:$deviceId'); - } - return device; - } - - Future _ensureInitialized() async { - if (isInitialized) return; - - if (_initializationCompleter != null) { - await _initializationCompleter?.future; - return; - } - - _initializationCompleter = Completer(); - try { - await _client.connect(); - await _waitForAdapter(_client); - - _activeAdapter ??= _client.adapters.first; - - UniversalLogger.logInfo( - 'BleAdapter: ${_activeAdapter?.name} - ${_activeAdapter?.address}', - ); - - _activeAdapter?.propertiesChanged.listen((List properties) { - // Handle pairing state change - for (final property in properties) { - switch (property) { - case BluezProperty.powered: - updateAvailability(_availabilityState); - break; - case BluezProperty.discoverable: - case BluezProperty.discovering: - // print("Adapter Discovering: ${_activeAdapter?.discovering}"); - break; - case BluezProperty.propertyClass: - default: - UniversalLogger.logInfo( - "UnhandledPropertyChanged: $property", - ); - } - } - }); - - updateAvailability(_availabilityState); - isInitialized = true; - _initializationCompleter?.complete(); - _initializationCompleter = null; - } catch (e) { - UniversalLogger.logError('Error initializing: $e'); - _initializationCompleter?.completeError(e); - await _client.close(); - rethrow; - } - } - - Future _waitForAdapter(BlueZClient client) async { - if (client.adapters.isNotEmpty) return; - - int attempts = 0; - while (attempts < 10 && client.adapters.isEmpty) { - await Future.delayed(const Duration(milliseconds: 100)); - attempts++; - } - - if (client.adapters.isEmpty) { - throw Exception('Bluetooth adapter unavailable'); - } - } - - void _onDeviceAdd(BlueZDevice device) { - BleDevice bleDevice = device.toBleDevice(); - if (!_bleFilter.matchesDevice(bleDevice)) { - return; - } - - // Update scan results only if rssi is available - if (device.rssi != 0) { - updateScanResult(bleDevice); - } - - // Setup Cache - _devices[device.address] = device; - - // Setup advertisements Listener - _deviceAdvertisementSubscriptions[device.address] ??= device - .propertiesChanged - .where((e) => - e.contains(BluezProperty.rssi) || - e.contains(BluezProperty.manufacturerData) || - e.contains(BluezProperty.uuids)) - .listen((_) { - if (_bleFilter.matchesDevice(bleDevice)) { - updateScanResult(device.toBleDevice()); - } - }); - - // Setup update listener - _deviceUpdateStreamSubscriptions[device.address] ??= - device.propertiesChanged.listen((properties) { - for (final property in properties) { - switch (property) { - // Connection/Pair updates - case BluezProperty.connected: - updateConnection(device.address, device.connected); - break; - case BluezProperty.paired: - updatePairingState(device.address, device.paired); - break; - // Ignored these properties updates - case BluezProperty.bonded: - case BluezProperty.legacyPairing: - case BluezProperty.servicesResolved: - case BluezProperty.uuids: - case BluezProperty.txPower: - case BluezProperty.address: - case BluezProperty.addressType: - case BluezProperty.rssi: - case BluezProperty.manufacturerData: - break; - default: - UniversalLogger.logInfo( - "UnhandledDevicePropertyChanged ${device.name} ${device.address}: $property", - ); - break; - } - } - }); - } - - void _onDeviceRemoved(BlueZDevice device) { - _devices.remove(device.address); - // Clean Update listeners - _deviceUpdateStreamSubscriptions.removeWhere((key, value) { - if (key == device.address) { - value.cancel(); - return true; - } - return false; - }); - // Clean Advertisement listeners - _deviceAdvertisementSubscriptions.removeWhere((key, value) { - if (key == device.address) { - value.cancel(); - return true; - } - return false; - }); - } -} - -class BluezProperty { - static const String rssi = 'RSSI'; - static const String connected = 'Connected'; - static const String txPower = 'TxPower'; - static const String bonded = 'Bonded'; - static const String manufacturerData = 'ManufacturerData'; - static const String legacyPairing = 'LegacyPairing'; - static const String servicesResolved = 'ServicesResolved'; - static const String paired = 'Paired'; - static const String address = 'Address'; - static const String addressType = 'AddressType'; - static const String modalias = 'Modalias'; - static const String uuids = 'UUIDs'; - static const String value = 'Value'; - static const String powered = 'Powered'; - static const String discoverable = 'Discoverable'; - static const String discovering = 'Discovering'; - static const String propertyClass = 'Class'; -} - -extension on BlueZGattCharacteristicFlag { - CharacteristicProperty? toCharacteristicProperty() { - return switch (this) { - BlueZGattCharacteristicFlag.broadcast => CharacteristicProperty.broadcast, - BlueZGattCharacteristicFlag.read => CharacteristicProperty.read, - BlueZGattCharacteristicFlag.writeWithoutResponse => - CharacteristicProperty.writeWithoutResponse, - BlueZGattCharacteristicFlag.write => CharacteristicProperty.write, - BlueZGattCharacteristicFlag.notify => CharacteristicProperty.notify, - BlueZGattCharacteristicFlag.indicate => CharacteristicProperty.indicate, - BlueZGattCharacteristicFlag.authenticatedSignedWrites => - CharacteristicProperty.authenticatedSignedWrites, - BlueZGattCharacteristicFlag.extendedProperties => - CharacteristicProperty.extendedProperties, - _ => null, - }; - } -} - -extension on BlueZFailedException { - /// Extract error code from message and parse into decimal - /// example: 'Operation failed with ATT error: 0x90' => 144 - String? get errorCode { - try { - RegExp regExp = RegExp(r'0x\w+'); - Match? match = regExp.firstMatch(message); - String? code = match?.group(0); - if (code == null) return null; - int? decimalValue = int.tryParse( - code.replaceFirst('0x', ''), - radix: 16, - ); - return decimalValue?.toString() ?? code; - } catch (e) { - return null; - } - } -} - -extension BlueZDeviceExtension on BlueZDevice { - List get manufacturerDataList => manufacturerData.entries - .map((MapEntry> data) => - ManufacturerData(data.key.id, Uint8List.fromList(data.value))) - .toList(); - - BleDevice toBleDevice({bool? isSystemDevice}) { - return BleDevice( - name: name, - deviceId: address, - isPaired: paired, - rssi: rssi, - isSystemDevice: isSystemDevice, - services: uuids.map((e) => e.toString()).toList(), - manufacturerDataList: manufacturerDataList, - ); - } -} diff --git a/universal_ble/lib/src/universal_ble_pigeon/universal_ble.g.dart b/universal_ble/lib/src/universal_ble_pigeon/universal_ble.g.dart deleted file mode 100644 index ae3484f..0000000 --- a/universal_ble/lib/src/universal_ble_pigeon/universal_ble.g.dart +++ /dev/null @@ -1,862 +0,0 @@ -// Autogenerated from Pigeon (v22.6.1), do not edit directly. -// See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers - -import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; - -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; -import 'package:flutter/services.dart'; - -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); -} - -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { - if (empty) { - return []; - } - if (error == null) { - return [result]; - } - return [error.code, error.message, error.details]; -} - -class UniversalBleScanResult { - UniversalBleScanResult({ - required this.deviceId, - this.name, - this.isPaired, - this.rssi, - this.manufacturerDataList, - this.services, - }); - - String deviceId; - - String? name; - - bool? isPaired; - - int? rssi; - - List? manufacturerDataList; - - List? services; - - Object encode() { - return [ - deviceId, - name, - isPaired, - rssi, - manufacturerDataList, - services, - ]; - } - - static UniversalBleScanResult decode(Object result) { - result as List; - return UniversalBleScanResult( - deviceId: result[0]! as String, - name: result[1] as String?, - isPaired: result[2] as bool?, - rssi: result[3] as int?, - manufacturerDataList: (result[4] as List?)?.cast(), - services: (result[5] as List?)?.cast(), - ); - } -} - -class UniversalBleService { - UniversalBleService({ - required this.uuid, - this.characteristics, - }); - - String uuid; - - List? characteristics; - - Object encode() { - return [ - uuid, - characteristics, - ]; - } - - static UniversalBleService decode(Object result) { - result as List; - return UniversalBleService( - uuid: result[0]! as String, - characteristics: (result[1] as List?)?.cast(), - ); - } -} - -class UniversalBleCharacteristic { - UniversalBleCharacteristic({ - required this.uuid, - required this.properties, - }); - - String uuid; - - List properties; - - Object encode() { - return [ - uuid, - properties, - ]; - } - - static UniversalBleCharacteristic decode(Object result) { - result as List; - return UniversalBleCharacteristic( - uuid: result[0]! as String, - properties: (result[1] as List?)!.cast(), - ); - } -} - -/// Scan Filters -class UniversalScanFilter { - UniversalScanFilter({ - required this.withServices, - required this.withNamePrefix, - required this.withManufacturerData, - }); - - List withServices; - - List withNamePrefix; - - List withManufacturerData; - - Object encode() { - return [ - withServices, - withNamePrefix, - withManufacturerData, - ]; - } - - static UniversalScanFilter decode(Object result) { - result as List; - return UniversalScanFilter( - withServices: (result[0] as List?)!.cast(), - withNamePrefix: (result[1] as List?)!.cast(), - withManufacturerData: (result[2] as List?)!.cast(), - ); - } -} - -class UniversalManufacturerDataFilter { - UniversalManufacturerDataFilter({ - required this.companyIdentifier, - this.data, - this.mask, - }); - - int companyIdentifier; - - Uint8List? data; - - Uint8List? mask; - - Object encode() { - return [ - companyIdentifier, - data, - mask, - ]; - } - - static UniversalManufacturerDataFilter decode(Object result) { - result as List; - return UniversalManufacturerDataFilter( - companyIdentifier: result[0]! as int, - data: result[1] as Uint8List?, - mask: result[2] as Uint8List?, - ); - } -} - -class UniversalManufacturerData { - UniversalManufacturerData({ - required this.companyIdentifier, - required this.data, - }); - - int companyIdentifier; - - Uint8List data; - - Object encode() { - return [ - companyIdentifier, - data, - ]; - } - - static UniversalManufacturerData decode(Object result) { - result as List; - return UniversalManufacturerData( - companyIdentifier: result[0]! as int, - data: result[1]! as Uint8List, - ); - } -} - - -class _PigeonCodec extends StandardMessageCodec { - const _PigeonCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is int) { - buffer.putUint8(4); - buffer.putInt64(value); - } else if (value is UniversalBleScanResult) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is UniversalBleService) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is UniversalBleCharacteristic) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else if (value is UniversalScanFilter) { - buffer.putUint8(132); - writeValue(buffer, value.encode()); - } else if (value is UniversalManufacturerDataFilter) { - buffer.putUint8(133); - writeValue(buffer, value.encode()); - } else if (value is UniversalManufacturerData) { - buffer.putUint8(134); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 129: - return UniversalBleScanResult.decode(readValue(buffer)!); - case 130: - return UniversalBleService.decode(readValue(buffer)!); - case 131: - return UniversalBleCharacteristic.decode(readValue(buffer)!); - case 132: - return UniversalScanFilter.decode(readValue(buffer)!); - case 133: - return UniversalManufacturerDataFilter.decode(readValue(buffer)!); - case 134: - return UniversalManufacturerData.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - -/// Flutter -> Native -class UniversalBlePlatformChannel { - /// Constructor for [UniversalBlePlatformChannel]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default - /// BinaryMessenger will be used which routes to the host platform. - UniversalBlePlatformChannel({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? pigeonVar_binaryMessenger; - - static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - - final String pigeonVar_messageChannelSuffix; - - Future getBluetoothAvailabilityState() async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as int?)!; - } - } - - Future enableBluetooth() async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future disableBluetooth() async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disableBluetooth$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future startScan(UniversalScanFilter? filter) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([filter]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future stopScan() async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send(null) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future connect(String deviceId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future disconnect(String deviceId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future setNotifiable(String deviceId, String service, String characteristic, int bleInputProperty) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId, service, characteristic, bleInputProperty]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future> discoverServices(String deviceId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as List?)!.cast(); - } - } - - Future readValue(String deviceId, String service, String characteristic) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId, service, characteristic]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as Uint8List?)!; - } - } - - Future requestMtu(String deviceId, int expectedMtu) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId, expectedMtu]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as int?)!; - } - } - - Future writeValue(String deviceId, String service, String characteristic, Uint8List value, int bleOutputProperty) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId, service, characteristic, value, bleOutputProperty]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future isPaired(String deviceId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future pair(String deviceId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future unPair(String deviceId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future> getSystemDevices(List withServices) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([withServices]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as List?)!.cast(); - } - } - - Future getConnectionState(String deviceId) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = - await pigeonVar_channel.send([deviceId]) as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as int?)!; - } - } -} - -/// Native -> Flutter -abstract class UniversalBleCallbackChannel { - static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - - void onAvailabilityChanged(int state); - - void onPairStateChange(String deviceId, bool isPaired, String? error); - - void onScanResult(UniversalBleScanResult result); - - void onValueChanged(String deviceId, String characteristicId, Uint8List value); - - void onConnectionChanged(String deviceId, bool connected, String? error); - - static void setUp(UniversalBleCallbackChannel? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (api == null) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null.'); - final List args = (message as List?)!; - final int? arg_state = (args[0] as int?); - assert(arg_state != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged was null, expected non-null int.'); - try { - api.onAvailabilityChanged(arg_state!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (api == null) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null.'); - final List args = (message as List?)!; - final String? arg_deviceId = (args[0] as String?); - assert(arg_deviceId != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null, expected non-null String.'); - final bool? arg_isPaired = (args[1] as bool?); - assert(arg_isPaired != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange was null, expected non-null bool.'); - final String? arg_error = (args[2] as String?); - try { - api.onPairStateChange(arg_deviceId!, arg_isPaired!, arg_error); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (api == null) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null.'); - final List args = (message as List?)!; - final UniversalBleScanResult? arg_result = (args[0] as UniversalBleScanResult?); - assert(arg_result != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult was null, expected non-null UniversalBleScanResult.'); - try { - api.onScanResult(arg_result!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (api == null) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null.'); - final List args = (message as List?)!; - final String? arg_deviceId = (args[0] as String?); - assert(arg_deviceId != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null String.'); - final String? arg_characteristicId = (args[1] as String?); - assert(arg_characteristicId != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null String.'); - final Uint8List? arg_value = (args[2] as Uint8List?); - assert(arg_value != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged was null, expected non-null Uint8List.'); - try { - api.onValueChanged(arg_deviceId!, arg_characteristicId!, arg_value!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - { - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (api == null) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null.'); - final List args = (message as List?)!; - final String? arg_deviceId = (args[0] as String?); - assert(arg_deviceId != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null, expected non-null String.'); - final bool? arg_connected = (args[1] as bool?); - assert(arg_connected != null, - 'Argument for dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged was null, expected non-null bool.'); - final String? arg_error = (args[2] as String?); - try { - api.onConnectionChanged(arg_deviceId!, arg_connected!, arg_error); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } -} diff --git a/universal_ble/lib/src/universal_ble_pigeon/universal_ble_pigeon_channel.dart b/universal_ble/lib/src/universal_ble_pigeon/universal_ble_pigeon_channel.dart deleted file mode 100644 index 9071a18..0000000 --- a/universal_ble/lib/src/universal_ble_pigeon/universal_ble_pigeon_channel.dart +++ /dev/null @@ -1,260 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; -import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart'; -import 'package:universal_ble/universal_ble.dart'; - -class UniversalBlePigeonChannel extends UniversalBlePlatform { - static UniversalBlePigeonChannel? _instance; - static UniversalBlePigeonChannel get instance => - _instance ??= UniversalBlePigeonChannel._(); - - UniversalBlePigeonChannel._() { - _setupListeners(); - } - - final _channel = UniversalBlePlatformChannel(); - - @override - Future getBluetoothAvailabilityState() async { - int state = await _channel.getBluetoothAvailabilityState(); - return AvailabilityState.parse(state); - } - - @override - Future enableBluetooth() { - if (!BleCapabilities.supportsBluetoothEnableApi) { - throw UnsupportedError("Not supported"); - } - return _channel.enableBluetooth(); - } - - @override - Future disableBluetooth() { - if (!BleCapabilities.supportsBluetoothEnableApi) { - throw UnsupportedError("Not supported"); - } - return _channel.disableBluetooth(); - } - - @override - Future startScan({ - ScanFilter? scanFilter, - PlatformConfig? platformConfig, - }) async { - await _ensureInitialized(); - await _channel.startScan( - scanFilter.toUniversalScanFilter(), - ); - } - - @override - Future stopScan() => _channel.stopScan(); - - @override - Future getConnectionState(String deviceId) async { - int state = await _channel.getConnectionState(deviceId); - return BleConnectionState.parse(state); - } - - @override - Future connect(String deviceId, {Duration? connectionTimeout}) => - _channel.connect(deviceId); - - @override - Future disconnect(String deviceId) => _channel.disconnect(deviceId); - - @override - Future> discoverServices(String deviceId) async { - List universalBleServices = - await _channel.discoverServices(deviceId); - return List.from(universalBleServices - .where((e) => e != null) - .map((e) => e!.toBleService()) - .toList()); - } - - @override - Future setNotifiable(String deviceId, String service, - String characteristic, BleInputProperty bleInputProperty) { - return _channel.setNotifiable( - deviceId, - service, - characteristic, - bleInputProperty.index, - ); - } - - @override - Future readValue( - String deviceId, - String service, - String characteristic, { - final Duration? timeout, - }) { - return _channel.readValue(deviceId, service, characteristic); - } - - @override - Future writeValue( - String deviceId, - String service, - String characteristic, - Uint8List value, - BleOutputProperty bleOutputProperty) { - return _channel.writeValue( - deviceId, - service, - characteristic, - value, - bleOutputProperty.index, - ); - } - - @override - Future requestMtu(String deviceId, int expectedMtu) => - _channel.requestMtu(deviceId, expectedMtu); - - @override - Future isPaired(String deviceId) => _channel.isPaired(deviceId); - - @override - Future pair(String deviceId) => _channel.pair(deviceId); - - @override - Future unpair(String deviceId) => _channel.unPair(deviceId); - - @override - Future> getSystemDevices( - List? withServices, - ) async { - var devices = await _channel.getSystemDevices(withServices ?? []); - return List.from( - devices.map((e) => e.toBleDevice(isSystemDevice: true)).toList(), - ); - } - - /// To set listeners - void _setupListeners() { - UniversalBleCallbackChannel.setUp(_UniversalBleCallbackHandler( - scanResult: updateScanResult, - availabilityChange: updateAvailability, - connectionChanged: updateConnection, - valueChanged: updateCharacteristicValue, - pairStateChange: updatePairingState, - )); - } - - Future _ensureInitialized() async { - // Check bluetooth availability on Apple - // so that it will ask permission only when required, and throw error on failed - if (defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.macOS) { - AvailabilityState state = await getBluetoothAvailabilityState(); - switch (state) { - case AvailabilityState.unauthorized: - throw PlatformException( - code: "Unauthorized", - message: "Not authorized to access Bluetooth", - ); - case AvailabilityState.unsupported: - throw PlatformException( - code: "Unsupported", - message: "Bluetooth is not supported", - ); - default: - // Ignore rest.. - } - } - } -} - -extension _BleServiceExtension on UniversalBleService { - BleService toBleService() { - List bleCharacteristics = []; - for (UniversalBleCharacteristic? characteristic in characteristics ?? []) { - if (characteristic == null) continue; - List? properties = List.from(characteristic.properties); - bleCharacteristics.add(BleCharacteristic( - characteristic.uuid, - List.from( - properties.map((e) => CharacteristicProperty.parse(e ?? 1)), - ), - )); - } - return BleService(uuid, bleCharacteristics); - } -} - -class _UniversalBleCallbackHandler extends UniversalBleCallbackChannel { - OnAvailabilityChange availabilityChange; - OnScanResult scanResult; - OnConnectionChange connectionChanged; - OnValueChange valueChanged; - OnPairingStateChange pairStateChange; - - _UniversalBleCallbackHandler({ - required this.availabilityChange, - required this.scanResult, - required this.connectionChanged, - required this.valueChanged, - required this.pairStateChange, - }); - - @override - void onAvailabilityChanged(int state) => - availabilityChange(AvailabilityState.parse(state)); - - @override - void onConnectionChanged(String deviceId, bool connected, String? error) => - connectionChanged(deviceId, connected, error); - - @override - void onScanResult(UniversalBleScanResult result) => - scanResult(result.toBleDevice()); - - @override - void onValueChanged( - String deviceId, String characteristicId, Uint8List value) => - valueChanged(deviceId, characteristicId, value); - - @override - void onPairStateChange(String deviceId, bool isPaired, String? error) => - pairStateChange(deviceId, isPaired); -} - -extension _UniversalBleScanResultExtension on UniversalBleScanResult { - BleDevice toBleDevice({bool? isSystemDevice}) { - return BleDevice( - name: name, - deviceId: deviceId, - rssi: rssi, - isPaired: isPaired, - isSystemDevice: isSystemDevice, - services: services?.map(BleUuidParser.string).toList() ?? [], - manufacturerDataList: manufacturerDataList - ?.map((e) => ManufacturerData(e.companyIdentifier, e.data)) - .toList() ?? - [], - ); - } -} - -extension _ScanFilterExtension on ScanFilter? { - UniversalScanFilter? toUniversalScanFilter() { - List? manufacturerDataFilters = this - ?.withManufacturerData - .map((e) => UniversalManufacturerDataFilter( - companyIdentifier: e.companyIdentifier, - data: e.payloadPrefix, - mask: e.payloadMask, - )) - .toList(); - - // Windows crashes if it's null, so we need to pass empty scan filter in this case - return UniversalScanFilter( - withServices: this?.withServices.toValidUUIDList() ?? [], - withNamePrefix: this?.withNamePrefix ?? [], - withManufacturerData: manufacturerDataFilters ?? [], - ); - } -} diff --git a/universal_ble/lib/src/universal_ble_platform_interface.dart b/universal_ble/lib/src/universal_ble_platform_interface.dart deleted file mode 100644 index 818352d..0000000 --- a/universal_ble/lib/src/universal_ble_platform_interface.dart +++ /dev/null @@ -1,141 +0,0 @@ -import 'dart:async'; -import 'dart:typed_data'; -import 'package:universal_ble/universal_ble.dart'; - -abstract class UniversalBlePlatform { - // Do not use these directly to push updates - OnScanResult? onScanResult; - OnConnectionChange? onConnectionChange; - OnValueChange? onValueChange; - OnAvailabilityChange? onAvailabilityChange; - OnPairingStateChange? onPairingStateChange; - final Map _pairStateMap = {}; - StreamController? _connectionStreamController; - - Future getBluetoothAvailabilityState(); - - Future enableBluetooth(); - - Future disableBluetooth(); - - Future startScan({ - ScanFilter? scanFilter, - PlatformConfig? platformConfig, - }); - - Future stopScan(); - - Future connect(String deviceId, {Duration? connectionTimeout}); - - Future disconnect(String deviceId); - - Future> discoverServices(String deviceId); - - Future setNotifiable(String deviceId, String service, - String characteristic, BleInputProperty bleInputProperty); - - Future readValue( - String deviceId, - String service, - String characteristic, { - final Duration? timeout, - }); - - Future writeValue( - String deviceId, - String service, - String characteristic, - Uint8List value, - BleOutputProperty bleOutputProperty); - - Future requestMtu(String deviceId, int expectedMtu); - - Future isPaired(String deviceId); - - Future pair(String deviceId); - - Future unpair(String deviceId); - - Future getConnectionState(String deviceId); - - Future> getSystemDevices( - List? withServices, - ); - - bool receivesAdvertisements(String deviceId) => true; - - Stream connectionStream(String deviceId) { - _setupConnectionStreamIfRequired(); - return _connectionStreamController!.stream; - } - - void updateScanResult(BleDevice bleDevice) { - try { - onScanResult?.call(bleDevice); - } catch (_) {} - } - - void updateConnection(String deviceId, bool isConnected, [String? error]) { - _connectionStreamController?.add(BleConnectionUpdate( - deviceId: deviceId, - isConnected: isConnected, - error: error, - )); - - try { - onConnectionChange?.call(deviceId, isConnected, error); - } catch (_) {} - } - - void updateCharacteristicValue( - String deviceId, String characteristicId, Uint8List value) { - try { - onValueChange?.call( - deviceId, BleUuidParser.string(characteristicId), value); - } catch (_) {} - } - - void updateAvailability(AvailabilityState state) { - try { - onAvailabilityChange?.call(state); - } catch (_) {} - } - - void updatePairingState(String deviceId, bool isPaired) { - if (_pairStateMap[deviceId] == isPaired) return; - _pairStateMap[deviceId] = isPaired; - - try { - onPairingStateChange?.call(deviceId, isPaired); - } catch (_) {} - } - - /// Creates an auto disposable streamController - void _setupConnectionStreamIfRequired() { - if (_connectionStreamController != null) return; - - _connectionStreamController = StreamController.broadcast(); - - // Auto dispose if no more subscribers - _connectionStreamController?.onCancel = () { - // logInfo('Disposing Connection Stream'); - _connectionStreamController?.close(); - _connectionStreamController = null; - }; - } -} - -// Callback types -typedef OnConnectionChange = void Function( - String deviceId, bool isConnected, String? error); - -typedef OnValueChange = void Function( - String deviceId, String characteristicId, Uint8List value); - -typedef OnScanResult = void Function(BleDevice scanResult); - -typedef OnAvailabilityChange = void Function(AvailabilityState state); - -typedef OnPairingStateChange = void Function(String deviceId, bool isPaired); - -typedef OnQueueUpdate = void Function(String id, int remainingQueueItems); diff --git a/universal_ble/lib/src/universal_ble_web/universal_ble_web.dart b/universal_ble/lib/src/universal_ble_web/universal_ble_web.dart deleted file mode 100644 index 65afb17..0000000 --- a/universal_ble/lib/src/universal_ble_web/universal_ble_web.dart +++ /dev/null @@ -1,481 +0,0 @@ -import 'dart:async'; -import 'dart:collection'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter_web_bluetooth/flutter_web_bluetooth.dart'; -import 'package:universal_ble/src/models/model_exports.dart'; -import 'package:universal_ble/src/universal_ble_platform_interface.dart'; -import 'package:universal_ble/src/universal_logger.dart'; - -class UniversalBleWeb extends UniversalBlePlatform { - static UniversalBleWeb? _instance; - static UniversalBleWeb get instance => _instance ??= UniversalBleWeb._(); - - UniversalBleWeb._() { - _setupListeners(); - } - - final Map _bluetoothDeviceList = {}; - final Map _deviceAdvertisementStreamList = {}; - final Map _connectedDeviceStreamList = {}; - final Map _characteristicStreamList = {}; - final Map> _serviceCache = {}; - - @override - Future getConnectionState(String deviceId) async { - BluetoothDevice? device = _getDeviceById(deviceId); - bool connected = await device?.connected.first ?? false; - return connected - ? BleConnectionState.connected - : BleConnectionState.disconnected; - } - - @override - Future connect( - String deviceId, { - Duration? connectionTimeout = const Duration(seconds: 10), - }) async { - var device = _getDeviceById(deviceId); - if (device == null) throw "$deviceId Not Found"; - await device.connect(timeout: connectionTimeout); - - // Subscribe to Connection Stream - if (_connectedDeviceStreamList[deviceId] != null) { - _connectedDeviceStreamList[deviceId]?.cancel(); - } - - _connectedDeviceStreamList[deviceId] = device.connected.listen((event) { - if (!event) _cleanConnection(deviceId); - updateConnection(deviceId, event); - }); - } - - @override - Future disconnect(String deviceId) async { - _cleanConnection(deviceId); - updateConnection(deviceId, false); - _getDeviceById(deviceId)?.disconnect(); - } - - @override - Future> discoverServices(String deviceId) async => - (await _getServices(deviceId)).map((e) => e._bleService).toList(); - - @override - Future getBluetoothAvailabilityState() async { - bool isSupported = FlutterWebBluetooth.instance.isBluetoothApiSupported; - if (!isSupported) { - return AvailabilityState.unsupported; - } - bool isAvailable = await FlutterWebBluetooth.instance.isAvailable.first; - if (isSupported && !isAvailable) { - return AvailabilityState.poweredOff; - } else if (isAvailable) { - return AvailabilityState.poweredOn; - } - return AvailabilityState.unknown; - } - - @override - Future startScan({ - ScanFilter? scanFilter, - PlatformConfig? platformConfig, - }) async { - FlutterWebBluetooth.instance.isAvailable; - BluetoothDevice device = await FlutterWebBluetooth.instance.requestDevice( - _getRequestOptionBuilder(scanFilter, platformConfig?.web), - ); - - // Update local device list - _bluetoothDeviceList[device.id] = device; - - // Update Scan Result - updateScanResult(device.toBleScanResult()); - - _watchDeviceAdvertisements(device); - } - - @override - bool receivesAdvertisements(String deviceId) { - // Advertisements do not work on Linux/Web even with the "Experimental Web Platform features" flag enabled. Verified with Chrome Version 128.0.6613.138 - if (kIsWeb && defaultTargetPlatform == TargetPlatform.linux) { - return false; - } - - return _getDeviceById(deviceId)?.hasWatchAdvertisements() ?? false; - } - - /// This will work only if `chrome://flags/#enable-experimental-web-platform-features` is enabled - Future _watchDeviceAdvertisements(BluetoothDevice device) async { - try { - if (!device.hasWatchAdvertisements()) return; - - if (_deviceAdvertisementStreamList[device.id] != null) { - _deviceAdvertisementStreamList[device.id]?.cancel(); - await device.unwatchAdvertisements(); - } - - _deviceAdvertisementStreamList[device.id] = - device.advertisements.listen((event) { - updateScanResult( - device.toBleScanResult( - rssi: event.rssi, - manufacturerDataMap: event.manufacturerData, - services: event.uuids.toSet().toList(), - ), - ); - }); - device.advertisementsUseMemory = true; - await device.watchAdvertisements(); - } catch (e) { - UniversalLogger.logError("WebWatchAdvertisementError: $e"); - } - } - - @override - Future stopScan() async { - _disposeAdvertisementWatcher(); - } - - @override - Future setNotifiable( - String deviceId, - String service, - String characteristic, - BleInputProperty bleInputProperty, - ) async { - final bleCharacteristic = await _getBleCharacteristic( - deviceId: deviceId, - serviceId: service, - characteristicId: characteristic, - ); - - if (bleCharacteristic == null) { - throw Exception( - 'Characteristic $characteristic for service $service not found', - ); - } - - String characteristicKey = "${deviceId}_${service}_$characteristic"; - - if (bleInputProperty != BleInputProperty.disabled) { - if (_characteristicStreamList[characteristicKey] != null) { - _characteristicStreamList[characteristicKey]?.cancel(); - } - await bleCharacteristic.startNotifications(); - _characteristicStreamList[characteristicKey] = - bleCharacteristic.value.listen((ByteData event) { - updateCharacteristicValue( - deviceId, - characteristic, - event.buffer.asUint8List(), - ); - }); - } else { - await bleCharacteristic.stopNotifications(); - _characteristicStreamList.remove(characteristicKey)?.cancel(); - } - } - - @override - Future writeValue( - String deviceId, - String service, - String characteristic, - Uint8List value, - BleOutputProperty bleOutputProperty, - ) async { - final bleCharacteristic = await _getBleCharacteristic( - deviceId: deviceId, - serviceId: service, - characteristicId: characteristic, - ); - - if (bleCharacteristic == null) { - throw Exception( - 'Characteristic $characteristic for service $service not found', - ); - } - - if (bleOutputProperty == BleOutputProperty.withResponse) { - await bleCharacteristic.writeValueWithResponse(Uint8List.fromList(value)); - } else { - await bleCharacteristic - .writeValueWithoutResponse(Uint8List.fromList(value)); - } - } - - @override - Future readValue( - String deviceId, - String service, - String characteristic, { - final Duration? timeout, - }) async { - var bleCharacteristic = await _getBleCharacteristic( - deviceId: deviceId, - serviceId: service, - characteristicId: characteristic, - ); - if (bleCharacteristic == null) { - throw Exception( - 'Characteristic $characteristic for service $service not found'); - } - var data = timeout != null - ? bleCharacteristic.readValue(timeout: timeout) - : bleCharacteristic.readValue(); - return (await data).buffer.asUint8List(); - } - - /// `Unimplemented` - @override - Future requestMtu(String deviceId, int expectedMtu) { - throw UnimplementedError(); - } - - @override - Future isPaired(String deviceId) { - throw UnimplementedError(); - } - - @override - Future pair(String deviceId) { - throw UnimplementedError(); - } - - @override - Future unpair(String deviceId) { - throw UnimplementedError(); - } - - @override - Future> getSystemDevices( - List? withServices, - ) { - throw UnimplementedError(); - } - - /// Helpers - void _setupListeners() { - FlutterWebBluetooth.instance.isAvailable.listen( - (bool isAvailable) { - AvailabilityState newState = AvailabilityState.unknown; - if (!FlutterWebBluetooth.instance.isBluetoothApiSupported) { - newState = AvailabilityState.unsupported; - } else if (FlutterWebBluetooth.instance.isBluetoothApiSupported && - !isAvailable) { - newState = AvailabilityState.poweredOff; - } else if (isAvailable) { - newState = AvailabilityState.poweredOn; - } - updateAvailability(newState); - }, - ); - } - - void _cleanConnection(String deviceId) { - _connectedDeviceStreamList.removeWhere((key, value) { - if (key == deviceId) value.cancel(); - return key == deviceId; - }); - _characteristicStreamList.removeWhere((key, value) { - if (key.contains(deviceId)) value.cancel(); - return key.contains(deviceId); - }); - _disposeAdvertisementWatcher(deviceId); - _serviceCache.remove(deviceId); - // _bluetoothDeviceList.removeWhere((element) => element.id == deviceId); - } - - Future _getBleCharacteristic({ - required String deviceId, - required String serviceId, - required String characteristicId, - }) async { - for (var service in await _getServices(deviceId)) { - if (BleUuidParser.compareStrings(service.uuid, serviceId)) { - return service.getCharacteristic(characteristicId); - } - } - return null; - } - - BluetoothDevice? _getDeviceById(String id) => _bluetoothDeviceList[id]; - - /// Get services and their characteristics. - /// Services and characteristics are cached. - /// Clears cache on disconnection. - Future> _getServices( - String deviceId, - ) async { - BluetoothDevice? device = _getDeviceById(deviceId); - if (device == null) return []; - var services = _serviceCache[deviceId] ?? []; - if (services.isNotEmpty) return services; - for (var service in await device.discoverServices()) { - services.add(await _UniversalWebBluetoothService.fromService(service)); - } - _serviceCache[deviceId] = services; - return services; - } - - void _disposeAdvertisementWatcher([String? deviceId]) { - _deviceAdvertisementStreamList.removeWhere((key, value) { - if (deviceId != null && key != deviceId) return false; - value.cancel(); - _getDeviceById(deviceId ?? key) - ?.unwatchAdvertisements() - .onError((_, __) {}); - return true; - }); - } - - @override - Future enableBluetooth() { - throw UnimplementedError(); - } - - @override - Future disableBluetooth() { - throw UnimplementedError(); - } - - RequestOptionsBuilder _getRequestOptionBuilder( - ScanFilter? scanFilter, - WebOptions? webOptions, - ) { - List filters = []; - List optionalManufacturerData = []; - List optionalServices = []; - - if (webOptions != null) { - optionalServices.addAll(webOptions.optionalServices.toValidUUIDList()); - optionalManufacturerData.addAll(webOptions.optionalManufacturerData); - } - - if (scanFilter != null) { - // Add services filter - for (var service in scanFilter.withServices.toValidUUIDList()) { - filters.add(RequestFilterBuilder(services: [service])); - if (webOptions == null || webOptions.optionalServices.isEmpty) { - optionalServices.add(service); - } - } - - // Add manufacturer data filter - for (var manufacturerData in scanFilter.withManufacturerData) { - filters.add( - RequestFilterBuilder( - manufacturerData: [ - ManufacturerDataFilterBuilder( - companyIdentifier: manufacturerData.companyIdentifier, - dataPrefix: manufacturerData.payloadPrefix, - mask: manufacturerData.payloadMask, - ), - ], - ), - ); - - // Add optionalManufacturerData from scanFilter if webOptions is not provided - if (webOptions == null || webOptions.optionalManufacturerData.isEmpty) { - optionalManufacturerData.add(manufacturerData.companyIdentifier); - } - } - - // Add name filter - for (var name in scanFilter.withNamePrefix) { - filters.add(RequestFilterBuilder(namePrefix: name)); - } - } - - if (optionalServices.isEmpty) { - UniversalLogger.logError( - "OptionalServices list is empty on web, you have to specify services in the ScanFilter in order to be able to access those after connecting", - ); - } - - if (filters.isEmpty) { - return RequestOptionsBuilder.acceptAllDevices( - optionalServices: optionalServices, - optionalManufacturerData: optionalManufacturerData, - ); - } else { - return RequestOptionsBuilder( - filters, - optionalServices: optionalServices, - optionalManufacturerData: optionalManufacturerData, - ); - } - } -} - -extension _BluetoothDeviceExtension on BluetoothDevice { - BleDevice toBleScanResult({ - int? rssi, - UnmodifiableMapView? manufacturerDataMap, - List services = const [], - }) { - return BleDevice( - name: name, - deviceId: id, - manufacturerDataList: manufacturerDataMap?.toManufacturerDataList() ?? [], - rssi: rssi, - services: services, - ); - } -} - -extension _UnmodifiableMapViewExtension on UnmodifiableMapView { - List? toManufacturerDataList() => entries - .map((MapEntry data) => - ManufacturerData(data.key, data.value.buffer.asUint8List())) - .toList(); -} - -class _UniversalWebBluetoothService { - late String uuid; - BluetoothService service; - List characteristics; - - _UniversalWebBluetoothService({ - required this.service, - required this.characteristics, - }) { - uuid = service.uuid; - } - - static Future<_UniversalWebBluetoothService> fromService( - BluetoothService service, - ) async { - return _UniversalWebBluetoothService( - service: service, - characteristics: await service.getCharacteristics(), - ); - } - - BluetoothCharacteristic? getCharacteristic(String characteristicId) { - for (var characteristic in characteristics) { - if (BleUuidParser.compareStrings(characteristic.uuid, characteristicId)) { - return characteristic; - } - } - return null; - } - - BleService get _bleService => BleService( - service.uuid, - characteristics.map((e) { - return BleCharacteristic(e.uuid, [ - if (e.properties.broadcast) CharacteristicProperty.broadcast, - if (e.properties.read) CharacteristicProperty.read, - if (e.properties.write) CharacteristicProperty.write, - if (e.properties.writeWithoutResponse) - CharacteristicProperty.writeWithoutResponse, - if (e.properties.notify) CharacteristicProperty.notify, - if (e.properties.indicate) CharacteristicProperty.indicate, - if (e.properties.authenticatedSignedWrites) - CharacteristicProperty.authenticatedSignedWrites, - ]); - }).toList(), - ); -} diff --git a/universal_ble/lib/src/universal_logger.dart b/universal_ble/lib/src/universal_logger.dart deleted file mode 100644 index 4b7af51..0000000 --- a/universal_ble/lib/src/universal_logger.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'dart:developer'; - -class UniversalLogger { - static void logInfo(message) { - log( - message.toString(), - name: 'UniversalBle:INFO', - ); - } - - static void logError(message) { - log( - '\x1B[31m$message\x1B[31m', - name: 'UniversalBle:ERROR', - ); - } - - static void logWarning(message) { - log( - '\x1B[33m$message\x1B[33m', - name: 'UniversalBle:WARN', - ); - } -} diff --git a/universal_ble/lib/universal_ble.dart b/universal_ble/lib/universal_ble.dart deleted file mode 100644 index 66d5652..0000000 --- a/universal_ble/lib/universal_ble.dart +++ /dev/null @@ -1,6 +0,0 @@ -library universal_ble; - -export 'package:universal_ble/src/universal_ble_exceptions.dart'; -export 'package:universal_ble/src/universal_ble_platform_interface.dart'; -export 'package:universal_ble/src/universal_ble.dart'; -export 'package:universal_ble/src/models/model_exports.dart'; diff --git a/universal_ble/pigeon/universal_ble.dart b/universal_ble/pigeon/universal_ble.dart deleted file mode 100644 index f6f8d8b..0000000 --- a/universal_ble/pigeon/universal_ble.dart +++ /dev/null @@ -1,171 +0,0 @@ -import 'package:pigeon/pigeon.dart'; - -// dart run pigeon --input pigeon/universal_ble.dart -@ConfigurePigeon( - PigeonOptions( - dartPackageName: 'universal_ble', - dartOut: 'lib/src/universal_ble_pigeon/universal_ble.g.dart', - dartOptions: DartOptions(), - kotlinOut: - 'android/src/main/kotlin/com/navideck/universal_ble/UniversalBle.g.kt', - swiftOut: 'darwin/Classes/UniversalBle.g.swift', - kotlinOptions: KotlinOptions(package: 'com.navideck.universal_ble'), - swiftOptions: SwiftOptions(), - cppOptions: CppOptions(namespace: 'universal_ble'), - cppHeaderOut: 'windows/src/generated/universal_ble.g.h', - cppSourceOut: 'windows/src/generated/universal_ble.g.cpp', - debugGenerators: true, - ), -) - -/// Flutter -> Native -@HostApi() -abstract class UniversalBlePlatformChannel { - @async - int getBluetoothAvailabilityState(); - - @async - bool enableBluetooth(); - - @async - bool disableBluetooth(); - - void startScan(UniversalScanFilter? filter); - - void stopScan(); - - void connect(String deviceId); - - void disconnect(String deviceId); - - @async - void setNotifiable( - String deviceId, - String service, - String characteristic, - int bleInputProperty, - ); - - @async - List discoverServices(String deviceId); - - @async - Uint8List readValue( - String deviceId, - String service, - String characteristic, - ); - - @async - int requestMtu(String deviceId, int expectedMtu); - - @async - void writeValue( - String deviceId, - String service, - String characteristic, - Uint8List value, - int bleOutputProperty, - ); - - @async - bool isPaired(String deviceId); - - @async - bool pair(String deviceId); - - void unPair(String deviceId); - - @async - List getSystemDevices( - List withServices, - ); - - int getConnectionState(String deviceId); -} - -/// Native -> Flutter -@FlutterApi() -abstract class UniversalBleCallbackChannel { - void onAvailabilityChanged(int state); - - void onPairStateChange(String deviceId, bool isPaired, String? error); - - void onScanResult(UniversalBleScanResult result); - - void onValueChanged( - String deviceId, - String characteristicId, - Uint8List value, - ); - - void onConnectionChanged( - String deviceId, - bool connected, - String? error, - ); -} - -class UniversalBleScanResult { - final String deviceId; - final String? name; - final bool? isPaired; - final int? rssi; - final List? manufacturerDataList; - final List? services; - - UniversalBleScanResult({ - required this.name, - required this.deviceId, - required this.isPaired, - required this.rssi, - required this.manufacturerDataList, - required this.services, - }); -} - -class UniversalBleService { - String uuid; - List? characteristics; - UniversalBleService(this.uuid, this.characteristics); -} - -class UniversalBleCharacteristic { - String uuid; - List properties; - UniversalBleCharacteristic(this.uuid, this.properties); -} - -/// Scan Filters -class UniversalScanFilter { - final List withServices; - final List withNamePrefix; - final List withManufacturerData; - - UniversalScanFilter( - this.withServices, - this.withNamePrefix, - this.withManufacturerData, - ); -} - -class UniversalManufacturerDataFilter { - int companyIdentifier; - Uint8List? data; - Uint8List? mask; - UniversalManufacturerDataFilter({ - required this.companyIdentifier, - this.data, - this.mask, - }); -} - -class UniversalManufacturerData { - final int companyIdentifier; - final Uint8List data; - - UniversalManufacturerData({ - required this.companyIdentifier, - required this.data, - }); -} diff --git a/universal_ble/pubspec.yaml b/universal_ble/pubspec.yaml deleted file mode 100644 index 7fca45a..0000000 --- a/universal_ble/pubspec.yaml +++ /dev/null @@ -1,48 +0,0 @@ -name: universal_ble -description: A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter -version: 0.18.0 -homepage: https://navideck.com -repository: https://github.com/Navideck/universal_ble -issue_tracker: https://github.com/Navideck/universal_ble/issues -funding: - - https://github.com/sponsors/Navideck - -platforms: - android: - ios: - linux: - macos: - web: - windows: - -environment: - sdk: ">=3.1.3 <4.0.0" - flutter: ">=3.3.0" - -dependencies: - flutter: - sdk: flutter - plugin_platform_interface: ^2.1.6 - flutter_web_bluetooth: ^1.0.0 - bluez: ^0.8.3 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^2.0.0 - pigeon: ^22.4.0 - -flutter: - plugin: - platforms: - android: - package: com.navideck.universal_ble - pluginClass: UniversalBlePlugin - ios: - pluginClass: UniversalBlePlugin - sharedDarwinSource: true - macos: - pluginClass: UniversalBlePlugin - sharedDarwinSource: true - windows: - pluginClass: UniversalBlePluginCApi diff --git a/universal_ble/test/ble_uuid_parser_test.dart b/universal_ble/test/ble_uuid_parser_test.dart deleted file mode 100644 index 2cdbb79..0000000 --- a/universal_ble/test/ble_uuid_parser_test.dart +++ /dev/null @@ -1,233 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:universal_ble/universal_ble.dart'; - -void main() { - group('Parsing string', () { - group('Succeeds', () { - test('128-bit UUID in lowercase', () { - expect( - BleUuidParser.string('0000180a-0000-1000-8000-00805f9b34fb'), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('128-bit UUID in uppercase', () { - expect( - BleUuidParser.string('0000180A-0000-1000-8000-00805F9B34FB'), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('16-bit UUID in lowercase', () { - expect( - BleUuidParser.string('180a'), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('16-bit UUID in uppercase', () { - expect( - BleUuidParser.string('180A'), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('32-bit UUID', () { - expect( - BleUuidParser.string('0000180a'), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('UUID without dashes', () { - expect( - BleUuidParser.string('0000180a00001000800000805f9b34fb'), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('Lowercase 16-bit string to 128-bit starting with 0x', () { - expect( - BleUuidParser.string('0x0180a'), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('Uppercase 16-bit string to 128-bit starting with 0x', () { - expect( - BleUuidParser.string('0x0180A'), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('128-bit UUID with trailing space', () { - expect( - BleUuidParser.string('0000180a-0000-1000-8000-00805f9b34fb '), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - }); - group('Fails', () { - test('Invalid UUID length is less than 4', () { - expect( - () => BleUuidParser.string('123'), - throwsFormatException, - ); - }); - - test('Invalid UUID without dashes and short length', () { - expect( - () => BleUuidParser.string('0000180a00001000800000805f9b34'), - throwsFormatException, - ); - }); - - test('Invalid UUID without dashes and long length', () { - expect( - () => BleUuidParser.string('0000180a00001000800000805f9b34fb34'), - throwsFormatException, - ); - }); - - test('Invalid UUID is missing a dash', () { - expect( - () => BleUuidParser.string('0000180a-0000-1000-800000805f9b34fb'), - throwsFormatException, - ); - }); - - test('Invalid UUID has too many dashes', () { - expect( - () => BleUuidParser.string('0000-180a-0000-1000-8000-0080-5f9b-34fb'), - throwsFormatException, - ); - }); - - test('Invalid UUID is too short for 128 bits', () { - expect( - () => BleUuidParser.string('01'), - throwsFormatException, - ); - - expect( - () => BleUuidParser.string('0000180a-0000-1000-8000-00805f9b34f'), - throwsFormatException, - ); - }); - - test('Invalid UUID is too long for 128 bits', () { - expect( - () => BleUuidParser.string('0000180a-0000-1000-8000-00805f9b34fba'), - throwsFormatException, - ); - }); - - test('Invalid UUID contains non-hex characters', () { - expect( - () => BleUuidParser.string('0000180g-0000-1000-8000-00805f9b34fba'), - throwsFormatException, - ); - }); - }); - }); - - group('Parsing number', () { - group('Succeeds', () { - test('16-bit UUID in lowercase', () { - expect( - BleUuidParser.number(0x180a), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('16-bit UUID in uppercase', () { - expect( - BleUuidParser.number(0x180A), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - - test('32-bit UUID', () { - expect( - BleUuidParser.number(0x0000180A), - equals('0000180a-0000-1000-8000-00805f9b34fb'), - ); - }); - }); - group('Fails', () { - test('Invalid UUID is 8 bits', () { - expect( - () => BleUuidParser.number(0x18), - throwsFormatException, - ); - }); - - test('Invalid UUID is more than 32 bits', () { - expect( - () => BleUuidParser.number(0x180A01), - throwsFormatException, - ); - }); - }); - }); - - group('CompareStrings', () { - group('Succeeds', () { - test('Identical UUIDs', () { - expect( - BleUuidParser.compareStrings('0000180a-0000-1000-8000-00805f9b34fb', - '0000180a-0000-1000-8000-00805f9b34fb'), - isTrue, - ); - }); - - test('UUIDs with different case', () { - expect( - BleUuidParser.compareStrings('180A', '180a'), - isTrue, - ); - }); - - test('16-bit and 128-bit UUIDs', () { - expect( - BleUuidParser.compareStrings( - '0000180a-0000-1000-8000-00805f9b34fb', '180a'), - isTrue, - ); - }); - - test('16-bit and 128-bit UUIDs without dashes', () { - expect( - BleUuidParser.compareStrings( - '0000180A00001000800000805F9B34FB', '180a'), - isTrue, - ); - }); - - test('32-bit and 128-bit UUIDs', () { - expect( - BleUuidParser.compareStrings( - '0000180A', '0000180a-0000-1000-8000-00805f9b34fb'), - isTrue, - ); - }); - }); - - group('Fails with', () { - test('Different UUIDs', () { - expect( - BleUuidParser.compareStrings('180A', '180B'), - isFalse, - ); - }); - - test('Different UUIDs with different formats', () { - expect( - BleUuidParser.compareStrings( - '0000180A', '0000180b-0000-1000-8000-00805f9b34fb'), - isFalse, - ); - }); - }); - }); -} diff --git a/universal_ble/test/manufacturer_data_filter_test.dart b/universal_ble/test/manufacturer_data_filter_test.dart deleted file mode 100644 index a5265dc..0000000 --- a/universal_ble/test/manufacturer_data_filter_test.dart +++ /dev/null @@ -1,178 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:universal_ble/src/universal_ble_filter_util.dart'; -import 'dart:typed_data'; - -import 'package:universal_ble/universal_ble.dart'; - -void main() { - group('ManufacturerData Matching Tests', () { - late UniversalBleFilterUtil filterUtil; - late ScanFilter scanFilter; - late BleDevice device; - - setUp(() { - filterUtil = UniversalBleFilterUtil(); - scanFilter = ScanFilter( - withNamePrefix: [], - withServices: [], - withManufacturerData: [], - ); - }); - - test('should match when no manufacturer filters are present', () { - device = BleDevice( - deviceId: '1', - name: 'Test Device', - manufacturerDataList: [], - services: [], - ); - - expect(filterUtil.manufacturerDataMatches(scanFilter, device), true); - }); - - test('should not match when device has no manufacturer data', () { - scanFilter = ScanFilter( - withNamePrefix: [], - withServices: [], - withManufacturerData: [ - ManufacturerDataFilter(companyIdentifier: 0x004C), - ], - ); - - device = BleDevice( - deviceId: '1', - name: 'Test Device', - manufacturerDataList: [], - services: [], - ); - - expect(filterUtil.manufacturerDataMatches(scanFilter, device), false); - }); - - test( - 'should match when company identifiers are equal and no payload prefix', - () { - scanFilter = ScanFilter( - withNamePrefix: [], - withServices: [], - withManufacturerData: [ - ManufacturerDataFilter(companyIdentifier: 0x004C), - ], - ); - - device = BleDevice( - deviceId: '1', - name: 'Test Device', - manufacturerDataList: [ - ManufacturerData(0x004C, Uint8List.fromList([])), - ], - services: [], - ); - - expect(filterUtil.manufacturerDataMatches(scanFilter, device), true); - }); - - group('Payload Prefix Tests', () { - test('should match when payload prefix matches start of payload', () { - scanFilter = ScanFilter( - withNamePrefix: [], - withServices: [], - withManufacturerData: [ - ManufacturerDataFilter( - companyIdentifier: 0x004C, - payloadPrefix: Uint8List.fromList([0x01, 0x02]), - ), - ], - ); - - device = BleDevice( - deviceId: '1', - name: 'Test Device', - manufacturerDataList: [ - ManufacturerData(0x004C, Uint8List.fromList([0x01, 0x02, 0x03])), - ], - services: [], - ); - - expect(filterUtil.manufacturerDataMatches(scanFilter, device), true); - }); - - test('should match with multiple manufacturer data entries', () { - scanFilter = ScanFilter( - withNamePrefix: [], - withServices: [], - withManufacturerData: [ - ManufacturerDataFilter( - companyIdentifier: 0x004D, - payloadPrefix: Uint8List.fromList([0x01, 0x02]), - ), - ], - ); - - device = BleDevice( - deviceId: '1', - name: 'Test Device', - manufacturerDataList: [ - ManufacturerData(0x004C, Uint8List.fromList([0x03, 0x04])), - ManufacturerData(0x004D, Uint8List.fromList([0x01, 0x02, 0x03])), - ], - services: [], - ); - - expect(filterUtil.manufacturerDataMatches(scanFilter, device), true); - }); - }); - - group('Payload Mask Tests', () { - test('should match when masked values are equal', () { - scanFilter = ScanFilter( - withNamePrefix: [], - withServices: [], - withManufacturerData: [ - ManufacturerDataFilter( - companyIdentifier: 0x004C, - payloadPrefix: Uint8List.fromList([0xFF, 0xFF]), - payloadMask: Uint8List.fromList([0xF0, 0xF0]), - ), - ], - ); - - device = BleDevice( - deviceId: '1', - name: 'Test Device', - manufacturerDataList: [ - ManufacturerData(0x004C, Uint8List.fromList([0xF5, 0xF8])), - ], - services: [], - ); - - expect(filterUtil.manufacturerDataMatches(scanFilter, device), true); - }); - - test('should not match when masked values are different', () { - scanFilter = ScanFilter( - withNamePrefix: [], - withServices: [], - withManufacturerData: [ - ManufacturerDataFilter( - companyIdentifier: 0x004C, - payloadPrefix: Uint8List.fromList([0xFF, 0xFF]), - payloadMask: Uint8List.fromList([0xF0, 0xF0]), - ), - ], - ); - - device = BleDevice( - deviceId: '1', - name: 'Test Device', - manufacturerDataList: [ - ManufacturerData(0x004C, Uint8List.fromList([0xE5, 0xF8])), - ], - services: [], - ); - - expect(filterUtil.manufacturerDataMatches(scanFilter, device), false); - }); - }); - }); -} diff --git a/universal_ble/test/scan_filter_test.dart b/universal_ble/test/scan_filter_test.dart deleted file mode 100644 index de27b07..0000000 --- a/universal_ble/test/scan_filter_test.dart +++ /dev/null @@ -1,198 +0,0 @@ -import 'dart:typed_data'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:universal_ble/src/universal_ble_filter_util.dart'; -import 'package:universal_ble/universal_ble.dart'; - -void main() { - final universalBleFilter = UniversalBleFilterUtil(); - var device1 = BleDevice( - deviceId: '1', - name: '1_device', - services: ['1_ser'], - manufacturerDataList: [ - ManufacturerData(0x01, Uint8List.fromList([1, 2, 3])), - ], - ); - var device2 = BleDevice( - deviceId: '2', - name: '2_device', - services: ['2_ser'], - manufacturerDataList: [ - ManufacturerData(0x02, Uint8List.fromList([1, 2, 3])) - ], - ); - var device3 = BleDevice( - deviceId: '3', - name: '3_device', - services: ['3_ser'], - manufacturerDataList: [ - ManufacturerData(0x03, Uint8List.fromList([1, 2, 3])) - ], - ); - - group("Test Individual Filter", () { - test('Test isNameMatchingFilters', () { - var scanFilter = ScanFilter( - withNamePrefix: ['1', '2'], - ); - expect( - universalBleFilter.nameMatches(scanFilter, device1), - isTrue, - ); - expect( - universalBleFilter.nameMatches(scanFilter, device2), - isTrue, - ); - expect( - universalBleFilter.nameMatches(scanFilter, device3), - isFalse, - ); - }); - - test('Test isServicesMatchingFilters', () { - var scanFilter = ScanFilter( - withServices: ['1_ser', 'random', '3_ser'], - ); - expect( - universalBleFilter.servicesMatch(scanFilter, device1), - isTrue, - ); - expect( - universalBleFilter.servicesMatch(scanFilter, device2), - isFalse, - ); - expect( - universalBleFilter.nameMatches(scanFilter, device3), - isTrue, - ); - }); - - test('Test isManufacturerDataMatchingFilters', () { - var scanFilter = ScanFilter(withManufacturerData: [ - ManufacturerDataFilter( - companyIdentifier: 0x01, - payloadPrefix: Uint8List.fromList([1, 2]), - ), - ManufacturerDataFilter( - companyIdentifier: 0x02, - ), - ManufacturerDataFilter( - companyIdentifier: 0x03, - payloadPrefix: Uint8List.fromList([3, 4]), - ) - ]); - expect( - universalBleFilter.manufacturerDataMatches( - scanFilter, - device1, - ), - isTrue, - ); - expect( - universalBleFilter.manufacturerDataMatches( - scanFilter, - device2, - ), - isTrue, - ); - expect( - universalBleFilter.manufacturerDataMatches( - scanFilter, - device3, - ), - isFalse, - ); - }); - }); - - group("Test Scan Filter", () { - test('Test filterDevice: Have filter for all', () { - universalBleFilter.scanFilter = ScanFilter( - withNamePrefix: ['1'], - withServices: ['3_ser'], - withManufacturerData: [ - ManufacturerDataFilter( - companyIdentifier: 0x02, - ) - ], - ); - expect( - universalBleFilter.matchesDevice(device1), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device2), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device3), - isTrue, - ); - }); - test('Test filterDevice: Filter for one', () { - universalBleFilter.scanFilter = ScanFilter( - withNamePrefix: ['1'], - ); - expect( - universalBleFilter.matchesDevice(device1), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device2), - isFalse, - ); - expect( - universalBleFilter.matchesDevice(device3), - isFalse, - ); - }); - test('Test filterDevice: Filter for two', () { - universalBleFilter.scanFilter = ScanFilter( - withNamePrefix: ['1', '2'], - ); - expect( - universalBleFilter.matchesDevice(device1), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device2), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device3), - isFalse, - ); - }); - test('Test filterDevice: Empty Filter', () { - universalBleFilter.scanFilter = ScanFilter(); - expect( - universalBleFilter.matchesDevice(device1), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device2), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device3), - isTrue, - ); - }); - test('Test filterDevice: Null Filter', () { - universalBleFilter.scanFilter = ScanFilter(); - expect( - universalBleFilter.matchesDevice(device1), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device2), - isTrue, - ); - expect( - universalBleFilter.matchesDevice(device3), - isTrue, - ); - }); - }); -} diff --git a/universal_ble/windows/.gitignore b/universal_ble/windows/.gitignore deleted file mode 100644 index b3eb2be..0000000 --- a/universal_ble/windows/.gitignore +++ /dev/null @@ -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/ diff --git a/universal_ble/windows/CMakeLists.txt b/universal_ble/windows/CMakeLists.txt deleted file mode 100644 index 3c2854e..0000000 --- a/universal_ble/windows/CMakeLists.txt +++ /dev/null @@ -1,80 +0,0 @@ -cmake_minimum_required(VERSION 3.21) -set(PROJECT_NAME "universal_ble") -project(${PROJECT_NAME} LANGUAGES CXX) -cmake_policy(VERSION 3.14...3.25) -include(FetchContent) -set(CPPWINRT_VERSION "2.0.220418.1") -set(PLUGIN_NAME "universal_ble_plugin") - -# ############### NuGet intall begin ################ -FetchContent_Declare(nuget - URL "https://dist.nuget.org/win-x86-commandline/v6.0.0/nuget.exe" - URL_HASH SHA256=04eb6c4fe4213907e2773e1be1bbbd730e9a655a3c9c58387ce8d4a714a5b9e1 - DOWNLOAD_NO_EXTRACT true -) - -find_program(NUGET nuget) - -if(NOT NUGET) - # message("Nuget.exe not found, trying to download or use cached version.") - FetchContent_MakeAvailable(nuget) - set(NUGET ${nuget_SOURCE_DIR}/nuget.exe) -endif() - -execute_process(COMMAND - ${NUGET} install "Microsoft.Windows.CppWinRT" -Version ${CPPWINRT_VERSION} -OutputDirectory packages - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - RESULT_VARIABLE ret) - -if(NOT ret EQUAL 0) - message(FATAL_ERROR "Failed to install nuget package Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}") -endif() - -# ############### NuGet install end ################ -list(APPEND PLUGIN_SOURCES - "src/universal_ble_plugin.cpp" - "src/universal_ble_plugin.h" - "src/helper/universal_enum.h" - "src/helper/universal_ble_base.h" - "src/helper/utils.cpp" - "src/helper/utils.h" - "src/ui_thread_handler.hpp" - "src/generated/universal_ble.g.cpp" - "src/generated/universal_ble.g.h" - "src/pin_entry.h" - "src/universal_ble_filter_util.cpp" - "src/universal_ble_filter_util.h" - "src/universal_ble_thread_safe.h" - "src/enum_parser.h" -) - -add_library(${PLUGIN_NAME} SHARED - "include/universal_ble/universal_ble_plugin_c_api.h" - "universal_ble_plugin_c_api.cpp" - ${PLUGIN_SOURCES} -) - -apply_standard_settings(${PLUGIN_NAME}) - -# ############### NuGet import begin ################ -set_target_properties(${PLUGIN_NAME} PROPERTIES VS_PROJECT_IMPORT - ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/build/native/Microsoft.Windows.CppWinRT.props -) - -target_link_libraries(${PLUGIN_NAME} PRIVATE - ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/build/native/Microsoft.Windows.CppWinRT.targets -) - -# ############### NuGet import end ################ -set_target_properties(${PLUGIN_NAME} PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) - -target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) - -set(universal_ble_bundled_libraries - "" - PARENT_SCOPE -) diff --git a/universal_ble/windows/include/universal_ble/universal_ble_plugin_c_api.h b/universal_ble/windows/include/universal_ble/universal_ble_plugin_c_api.h deleted file mode 100644 index 37dd653..0000000 --- a/universal_ble/windows/include/universal_ble/universal_ble_plugin_c_api.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_C_API_H_ -#define FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_C_API_H_ - -#include - -#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 UniversalBlePluginCApiRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar); - -#if defined(__cplusplus) -} // extern "C" -#endif - -#endif // FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_C_API_H_ diff --git a/universal_ble/windows/src/enum_parser.h b/universal_ble/windows/src/enum_parser.h deleted file mode 100644 index eb7899a..0000000 --- a/universal_ble/windows/src/enum_parser.h +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include - -namespace universal_ble -{ - inline std::string device_watcher_status_to_string(const DeviceWatcherStatus result) - { - switch (result) - { - case DeviceWatcherStatus::Created: return "Created"; - case DeviceWatcherStatus::Aborted: return "Aborted"; - case DeviceWatcherStatus::EnumerationCompleted: return "EnumerationCompleted"; - case DeviceWatcherStatus::Started: return "Started"; - case DeviceWatcherStatus::Stopped: return "Stopped"; - case DeviceWatcherStatus::Stopping: return "Stopping"; - } - return ""; - } - - inline std::optional gatt_communication_status_to_error(const GattCommunicationStatus result) - { - switch (result) - { - case GattCommunicationStatus::Success: return std::nullopt; - case GattCommunicationStatus::Unreachable: return "Unreachable"; - case GattCommunicationStatus::ProtocolError: return "ProtocolError"; - case GattCommunicationStatus::AccessDenied: return "AccessDenied"; - } - return std::nullopt; - } - - - - inline std::optional device_unpairing_result_to_string(const DeviceUnpairingResultStatus result) - { - switch (result) - { - case DeviceUnpairingResultStatus::Failed: return "Failed to unpair device"; - case DeviceUnpairingResultStatus::AccessDenied: return "Access denied"; - case DeviceUnpairingResultStatus::AlreadyUnpaired: return "Device is already unpaired"; - case DeviceUnpairingResultStatus::OperationAlreadyInProgress: return "OperationAlreadyInProgress"; - case DeviceUnpairingResultStatus::Unpaired: return std::nullopt; - - } - return std::nullopt; - } - - inline std::optional parse_pairing_fail_error(const DevicePairingResult& result) - { - switch (result.Status()) - { - case DevicePairingResultStatus::Paired: return std::nullopt; - case DevicePairingResultStatus::AlreadyPaired: return "AlreadyPaired"; - case DevicePairingResultStatus::ConnectionRejected: return "ConnectionRejected"; - case DevicePairingResultStatus::NotPaired: return "NotPaired"; - case DevicePairingResultStatus::NotReadyToPair: return "NotReadyToPair"; - case DevicePairingResultStatus::TooManyConnections: return "TooManyConnections"; - case DevicePairingResultStatus::HardwareFailure: return "HardwareFailure"; - case DevicePairingResultStatus::AuthenticationTimeout: return "AuthenticationTimeout"; - case DevicePairingResultStatus::AuthenticationNotAllowed: return "AuthenticationNotAllowed"; - case DevicePairingResultStatus::AuthenticationFailure: return "AuthenticationFailure"; - case DevicePairingResultStatus::NoSupportedProfiles: return "NoSupportedProfiles"; - case DevicePairingResultStatus::ProtectionLevelCouldNotBeMet: return "ProtectionLevelCouldNotBeMet"; - case DevicePairingResultStatus::AccessDenied: return "AccessDenied"; - case DevicePairingResultStatus::InvalidCeremonyData: return "InvalidCeremonyData"; - case DevicePairingResultStatus::PairingCanceled: return "PairingCanceled"; - case DevicePairingResultStatus::OperationAlreadyInProgress: return "OperationAlreadyInProgress"; - case DevicePairingResultStatus::RequiredHandlerNotRegistered: return "RequiredHandlerNotRegistered"; - case DevicePairingResultStatus::RejectedByHandler: return "RejectedByHandler"; - case DevicePairingResultStatus::RemoteDeviceHasAssociation: return "RemoteDeviceHasAssociation"; - default: return "Failed to pair"; - } - } - - - inline AvailabilityState get_availability_state_from_radio(const RadioState radio_state) - { - switch (radio_state) - { - case RadioState::On: return AvailabilityState::poweredOn; - case RadioState::Off: return AvailabilityState::poweredOff; - case RadioState::Disabled: return AvailabilityState::unsupported; - case RadioState::Unknown: return AvailabilityState::unknown; - } - return AvailabilityState::unknown; - } - - inline flutter::EncodableList properties_to_flutter_encodable (const GattCharacteristicProperties properties_value) - { - auto properties = flutter::EncodableList(); - if ((properties_value & GattCharacteristicProperties::Broadcast) != GattCharacteristicProperties::None) - { - properties.push_back(static_cast(CharacteristicProperty::broadcast)); - } - if ((properties_value & GattCharacteristicProperties::Read) != GattCharacteristicProperties::None) - { - properties.push_back(static_cast(CharacteristicProperty::read)); - } - if ((properties_value & GattCharacteristicProperties::Write) != GattCharacteristicProperties::None) - { - properties.push_back(static_cast(CharacteristicProperty::write)); - } - if ((properties_value & GattCharacteristicProperties::WriteWithoutResponse) != GattCharacteristicProperties::None) - { - properties.push_back(static_cast(CharacteristicProperty::writeWithoutResponse)); - } - if ((properties_value & GattCharacteristicProperties::Notify) != GattCharacteristicProperties::None) - { - properties.push_back(static_cast(CharacteristicProperty::notify)); - } - if ((properties_value & GattCharacteristicProperties::Indicate) != GattCharacteristicProperties::None) - { - properties.push_back(static_cast(CharacteristicProperty::indicate)); - } - if ((properties_value & GattCharacteristicProperties::AuthenticatedSignedWrites) != GattCharacteristicProperties::None) - { - properties.push_back(static_cast(CharacteristicProperty::authenticatedSignedWrites)); - } - if ((properties_value & GattCharacteristicProperties::ExtendedProperties) != GattCharacteristicProperties::None) - { - properties.push_back(static_cast(CharacteristicProperty::extendedProperties)); - } - return properties; - } - -} diff --git a/universal_ble/windows/src/generated/universal_ble.g.cpp b/universal_ble/windows/src/generated/universal_ble.g.cpp deleted file mode 100644 index 46ed503..0000000 --- a/universal_ble/windows/src/generated/universal_ble.g.cpp +++ /dev/null @@ -1,1190 +0,0 @@ -// Autogenerated from Pigeon (v22.6.1), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#undef _HAS_EXCEPTIONS - -#include "universal_ble.g.h" - -#include -#include -#include -#include - -#include -#include -#include - -namespace universal_ble { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; - -FlutterError CreateConnectionError(const std::string channel_name) { - return FlutterError( - "channel-error", - "Unable to establish connection on channel: '" + channel_name + "'.", - EncodableValue("")); -} - -// UniversalBleScanResult - -UniversalBleScanResult::UniversalBleScanResult(const std::string& device_id) - : device_id_(device_id) {} - -UniversalBleScanResult::UniversalBleScanResult( - const std::string& device_id, - const std::string* name, - const bool* is_paired, - const int64_t* rssi, - const EncodableList* manufacturer_data_list, - const EncodableList* services) - : device_id_(device_id), - name_(name ? std::optional(*name) : std::nullopt), - is_paired_(is_paired ? std::optional(*is_paired) : std::nullopt), - rssi_(rssi ? std::optional(*rssi) : std::nullopt), - manufacturer_data_list_(manufacturer_data_list ? std::optional(*manufacturer_data_list) : std::nullopt), - services_(services ? std::optional(*services) : std::nullopt) {} - -const std::string& UniversalBleScanResult::device_id() const { - return device_id_; -} - -void UniversalBleScanResult::set_device_id(std::string_view value_arg) { - device_id_ = value_arg; -} - - -const std::string* UniversalBleScanResult::name() const { - return name_ ? &(*name_) : nullptr; -} - -void UniversalBleScanResult::set_name(const std::string_view* value_arg) { - name_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void UniversalBleScanResult::set_name(std::string_view value_arg) { - name_ = value_arg; -} - - -const bool* UniversalBleScanResult::is_paired() const { - return is_paired_ ? &(*is_paired_) : nullptr; -} - -void UniversalBleScanResult::set_is_paired(const bool* value_arg) { - is_paired_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void UniversalBleScanResult::set_is_paired(bool value_arg) { - is_paired_ = value_arg; -} - - -const int64_t* UniversalBleScanResult::rssi() const { - return rssi_ ? &(*rssi_) : nullptr; -} - -void UniversalBleScanResult::set_rssi(const int64_t* value_arg) { - rssi_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void UniversalBleScanResult::set_rssi(int64_t value_arg) { - rssi_ = value_arg; -} - - -const EncodableList* UniversalBleScanResult::manufacturer_data_list() const { - return manufacturer_data_list_ ? &(*manufacturer_data_list_) : nullptr; -} - -void UniversalBleScanResult::set_manufacturer_data_list(const EncodableList* value_arg) { - manufacturer_data_list_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void UniversalBleScanResult::set_manufacturer_data_list(const EncodableList& value_arg) { - manufacturer_data_list_ = value_arg; -} - - -const EncodableList* UniversalBleScanResult::services() const { - return services_ ? &(*services_) : nullptr; -} - -void UniversalBleScanResult::set_services(const EncodableList* value_arg) { - services_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void UniversalBleScanResult::set_services(const EncodableList& value_arg) { - services_ = value_arg; -} - - -EncodableList UniversalBleScanResult::ToEncodableList() const { - EncodableList list; - list.reserve(6); - list.push_back(EncodableValue(device_id_)); - list.push_back(name_ ? EncodableValue(*name_) : EncodableValue()); - list.push_back(is_paired_ ? EncodableValue(*is_paired_) : EncodableValue()); - list.push_back(rssi_ ? EncodableValue(*rssi_) : EncodableValue()); - list.push_back(manufacturer_data_list_ ? EncodableValue(*manufacturer_data_list_) : EncodableValue()); - list.push_back(services_ ? EncodableValue(*services_) : EncodableValue()); - return list; -} - -UniversalBleScanResult UniversalBleScanResult::FromEncodableList(const EncodableList& list) { - UniversalBleScanResult decoded( - std::get(list[0])); - auto& encodable_name = list[1]; - if (!encodable_name.IsNull()) { - decoded.set_name(std::get(encodable_name)); - } - auto& encodable_is_paired = list[2]; - if (!encodable_is_paired.IsNull()) { - decoded.set_is_paired(std::get(encodable_is_paired)); - } - auto& encodable_rssi = list[3]; - if (!encodable_rssi.IsNull()) { - decoded.set_rssi(std::get(encodable_rssi)); - } - auto& encodable_manufacturer_data_list = list[4]; - if (!encodable_manufacturer_data_list.IsNull()) { - decoded.set_manufacturer_data_list(std::get(encodable_manufacturer_data_list)); - } - auto& encodable_services = list[5]; - if (!encodable_services.IsNull()) { - decoded.set_services(std::get(encodable_services)); - } - return decoded; -} - -// UniversalBleService - -UniversalBleService::UniversalBleService(const std::string& uuid) - : uuid_(uuid) {} - -UniversalBleService::UniversalBleService( - const std::string& uuid, - const EncodableList* characteristics) - : uuid_(uuid), - characteristics_(characteristics ? std::optional(*characteristics) : std::nullopt) {} - -const std::string& UniversalBleService::uuid() const { - return uuid_; -} - -void UniversalBleService::set_uuid(std::string_view value_arg) { - uuid_ = value_arg; -} - - -const EncodableList* UniversalBleService::characteristics() const { - return characteristics_ ? &(*characteristics_) : nullptr; -} - -void UniversalBleService::set_characteristics(const EncodableList* value_arg) { - characteristics_ = value_arg ? std::optional(*value_arg) : std::nullopt; -} - -void UniversalBleService::set_characteristics(const EncodableList& value_arg) { - characteristics_ = value_arg; -} - - -EncodableList UniversalBleService::ToEncodableList() const { - EncodableList list; - list.reserve(2); - list.push_back(EncodableValue(uuid_)); - list.push_back(characteristics_ ? EncodableValue(*characteristics_) : EncodableValue()); - return list; -} - -UniversalBleService UniversalBleService::FromEncodableList(const EncodableList& list) { - UniversalBleService decoded( - std::get(list[0])); - auto& encodable_characteristics = list[1]; - if (!encodable_characteristics.IsNull()) { - decoded.set_characteristics(std::get(encodable_characteristics)); - } - return decoded; -} - -// UniversalBleCharacteristic - -UniversalBleCharacteristic::UniversalBleCharacteristic( - const std::string& uuid, - const EncodableList& properties) - : uuid_(uuid), - properties_(properties) {} - -const std::string& UniversalBleCharacteristic::uuid() const { - return uuid_; -} - -void UniversalBleCharacteristic::set_uuid(std::string_view value_arg) { - uuid_ = value_arg; -} - - -const EncodableList& UniversalBleCharacteristic::properties() const { - return properties_; -} - -void UniversalBleCharacteristic::set_properties(const EncodableList& value_arg) { - properties_ = value_arg; -} - - -EncodableList UniversalBleCharacteristic::ToEncodableList() const { - EncodableList list; - list.reserve(2); - list.push_back(EncodableValue(uuid_)); - list.push_back(EncodableValue(properties_)); - return list; -} - -UniversalBleCharacteristic UniversalBleCharacteristic::FromEncodableList(const EncodableList& list) { - UniversalBleCharacteristic decoded( - std::get(list[0]), - std::get(list[1])); - return decoded; -} - -// UniversalScanFilter - -UniversalScanFilter::UniversalScanFilter( - const EncodableList& with_services, - const EncodableList& with_name_prefix, - const EncodableList& with_manufacturer_data) - : with_services_(with_services), - with_name_prefix_(with_name_prefix), - with_manufacturer_data_(with_manufacturer_data) {} - -const EncodableList& UniversalScanFilter::with_services() const { - return with_services_; -} - -void UniversalScanFilter::set_with_services(const EncodableList& value_arg) { - with_services_ = value_arg; -} - - -const EncodableList& UniversalScanFilter::with_name_prefix() const { - return with_name_prefix_; -} - -void UniversalScanFilter::set_with_name_prefix(const EncodableList& value_arg) { - with_name_prefix_ = value_arg; -} - - -const EncodableList& UniversalScanFilter::with_manufacturer_data() const { - return with_manufacturer_data_; -} - -void UniversalScanFilter::set_with_manufacturer_data(const EncodableList& value_arg) { - with_manufacturer_data_ = value_arg; -} - - -EncodableList UniversalScanFilter::ToEncodableList() const { - EncodableList list; - list.reserve(3); - list.push_back(EncodableValue(with_services_)); - list.push_back(EncodableValue(with_name_prefix_)); - list.push_back(EncodableValue(with_manufacturer_data_)); - return list; -} - -UniversalScanFilter UniversalScanFilter::FromEncodableList(const EncodableList& list) { - UniversalScanFilter decoded( - std::get(list[0]), - std::get(list[1]), - std::get(list[2])); - return decoded; -} - -// UniversalManufacturerDataFilter - -UniversalManufacturerDataFilter::UniversalManufacturerDataFilter(int64_t company_identifier) - : company_identifier_(company_identifier) {} - -UniversalManufacturerDataFilter::UniversalManufacturerDataFilter( - int64_t company_identifier, - const std::vector* data, - const std::vector* mask) - : company_identifier_(company_identifier), - data_(data ? std::optional>(*data) : std::nullopt), - mask_(mask ? std::optional>(*mask) : std::nullopt) {} - -int64_t UniversalManufacturerDataFilter::company_identifier() const { - return company_identifier_; -} - -void UniversalManufacturerDataFilter::set_company_identifier(int64_t value_arg) { - company_identifier_ = value_arg; -} - - -const std::vector* UniversalManufacturerDataFilter::data() const { - return data_ ? &(*data_) : nullptr; -} - -void UniversalManufacturerDataFilter::set_data(const std::vector* value_arg) { - data_ = value_arg ? std::optional>(*value_arg) : std::nullopt; -} - -void UniversalManufacturerDataFilter::set_data(const std::vector& value_arg) { - data_ = value_arg; -} - - -const std::vector* UniversalManufacturerDataFilter::mask() const { - return mask_ ? &(*mask_) : nullptr; -} - -void UniversalManufacturerDataFilter::set_mask(const std::vector* value_arg) { - mask_ = value_arg ? std::optional>(*value_arg) : std::nullopt; -} - -void UniversalManufacturerDataFilter::set_mask(const std::vector& value_arg) { - mask_ = value_arg; -} - - -EncodableList UniversalManufacturerDataFilter::ToEncodableList() const { - EncodableList list; - list.reserve(3); - list.push_back(EncodableValue(company_identifier_)); - list.push_back(data_ ? EncodableValue(*data_) : EncodableValue()); - list.push_back(mask_ ? EncodableValue(*mask_) : EncodableValue()); - return list; -} - -UniversalManufacturerDataFilter UniversalManufacturerDataFilter::FromEncodableList(const EncodableList& list) { - UniversalManufacturerDataFilter decoded( - std::get(list[0])); - auto& encodable_data = list[1]; - if (!encodable_data.IsNull()) { - decoded.set_data(std::get>(encodable_data)); - } - auto& encodable_mask = list[2]; - if (!encodable_mask.IsNull()) { - decoded.set_mask(std::get>(encodable_mask)); - } - return decoded; -} - -// UniversalManufacturerData - -UniversalManufacturerData::UniversalManufacturerData( - int64_t company_identifier, - const std::vector& data) - : company_identifier_(company_identifier), - data_(data) {} - -int64_t UniversalManufacturerData::company_identifier() const { - return company_identifier_; -} - -void UniversalManufacturerData::set_company_identifier(int64_t value_arg) { - company_identifier_ = value_arg; -} - - -const std::vector& UniversalManufacturerData::data() const { - return data_; -} - -void UniversalManufacturerData::set_data(const std::vector& value_arg) { - data_ = value_arg; -} - - -EncodableList UniversalManufacturerData::ToEncodableList() const { - EncodableList list; - list.reserve(2); - list.push_back(EncodableValue(company_identifier_)); - list.push_back(EncodableValue(data_)); - return list; -} - -UniversalManufacturerData UniversalManufacturerData::FromEncodableList(const EncodableList& list) { - UniversalManufacturerData decoded( - std::get(list[0]), - std::get>(list[1])); - return decoded; -} - - -PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} - -EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, - flutter::ByteStreamReader* stream) const { - switch (type) { - case 129: { - return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get(ReadValue(stream)))); - } - case 130: { - return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get(ReadValue(stream)))); - } - case 131: { - return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get(ReadValue(stream)))); - } - case 132: { - return CustomEncodableValue(UniversalScanFilter::FromEncodableList(std::get(ReadValue(stream)))); - } - case 133: { - return CustomEncodableValue(UniversalManufacturerDataFilter::FromEncodableList(std::get(ReadValue(stream)))); - } - case 134: { - return CustomEncodableValue(UniversalManufacturerData::FromEncodableList(std::get(ReadValue(stream)))); - } - default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } -} - -void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, - flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = std::get_if(&value)) { - if (custom_value->type() == typeid(UniversalBleScanResult)) { - stream->WriteByte(129); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); - return; - } - if (custom_value->type() == typeid(UniversalBleService)) { - stream->WriteByte(130); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); - return; - } - if (custom_value->type() == typeid(UniversalBleCharacteristic)) { - stream->WriteByte(131); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); - return; - } - if (custom_value->type() == typeid(UniversalScanFilter)) { - stream->WriteByte(132); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); - return; - } - if (custom_value->type() == typeid(UniversalManufacturerDataFilter)) { - stream->WriteByte(133); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); - return; - } - if (custom_value->type() == typeid(UniversalManufacturerData)) { - stream->WriteByte(134); - WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); - return; - } - } - flutter::StandardCodecSerializer::WriteValue(value, stream); -} - -/// The codec used by UniversalBlePlatformChannel. -const flutter::StandardMessageCodec& UniversalBlePlatformChannel::GetCodec() { - return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance()); -} - -// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binary_messenger`. -void UniversalBlePlatformChannel::SetUp( - flutter::BinaryMessenger* binary_messenger, - UniversalBlePlatformChannel* api) { - UniversalBlePlatformChannel::SetUp(binary_messenger, api, ""); -} - -void UniversalBlePlatformChannel::SetUp( - flutter::BinaryMessenger* binary_messenger, - UniversalBlePlatformChannel* api, - const std::string& message_channel_suffix) { - const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : ""; - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - api->GetBluetoothAvailabilityState([reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - api->EnableBluetooth([reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disableBluetooth" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - api->DisableBluetooth([reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_filter_arg = args.at(0); - const auto* filter_arg = encodable_filter_arg.IsNull() ? nullptr : &(std::any_cast(std::get(encodable_filter_arg))); - std::optional output = api->StartScan(filter_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - std::optional output = api->StopScan(); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - std::optional output = api->Connect(device_id_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - std::optional output = api->Disconnect(device_id_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - const auto& encodable_service_arg = args.at(1); - if (encodable_service_arg.IsNull()) { - reply(WrapError("service_arg unexpectedly null.")); - return; - } - const auto& service_arg = std::get(encodable_service_arg); - const auto& encodable_characteristic_arg = args.at(2); - if (encodable_characteristic_arg.IsNull()) { - reply(WrapError("characteristic_arg unexpectedly null.")); - return; - } - const auto& characteristic_arg = std::get(encodable_characteristic_arg); - const auto& encodable_ble_input_property_arg = args.at(3); - if (encodable_ble_input_property_arg.IsNull()) { - reply(WrapError("ble_input_property_arg unexpectedly null.")); - return; - } - const int64_t ble_input_property_arg = encodable_ble_input_property_arg.LongValue(); - api->SetNotifiable(device_id_arg, service_arg, characteristic_arg, ble_input_property_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - api->DiscoverServices(device_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - const auto& encodable_service_arg = args.at(1); - if (encodable_service_arg.IsNull()) { - reply(WrapError("service_arg unexpectedly null.")); - return; - } - const auto& service_arg = std::get(encodable_service_arg); - const auto& encodable_characteristic_arg = args.at(2); - if (encodable_characteristic_arg.IsNull()) { - reply(WrapError("characteristic_arg unexpectedly null.")); - return; - } - const auto& characteristic_arg = std::get(encodable_characteristic_arg); - api->ReadValue(device_id_arg, service_arg, characteristic_arg, [reply](ErrorOr>&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - const auto& encodable_expected_mtu_arg = args.at(1); - if (encodable_expected_mtu_arg.IsNull()) { - reply(WrapError("expected_mtu_arg unexpectedly null.")); - return; - } - const int64_t expected_mtu_arg = encodable_expected_mtu_arg.LongValue(); - api->RequestMtu(device_id_arg, expected_mtu_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - const auto& encodable_service_arg = args.at(1); - if (encodable_service_arg.IsNull()) { - reply(WrapError("service_arg unexpectedly null.")); - return; - } - const auto& service_arg = std::get(encodable_service_arg); - const auto& encodable_characteristic_arg = args.at(2); - if (encodable_characteristic_arg.IsNull()) { - reply(WrapError("characteristic_arg unexpectedly null.")); - return; - } - const auto& characteristic_arg = std::get(encodable_characteristic_arg); - const auto& encodable_value_arg = args.at(3); - if (encodable_value_arg.IsNull()) { - reply(WrapError("value_arg unexpectedly null.")); - return; - } - const auto& value_arg = std::get>(encodable_value_arg); - const auto& encodable_ble_output_property_arg = args.at(4); - if (encodable_ble_output_property_arg.IsNull()) { - reply(WrapError("ble_output_property_arg unexpectedly null.")); - return; - } - const int64_t ble_output_property_arg = encodable_ble_output_property_arg.LongValue(); - api->WriteValue(device_id_arg, service_arg, characteristic_arg, value_arg, ble_output_property_arg, [reply](std::optional&& output) { - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - api->IsPaired(device_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - api->Pair(device_id_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - std::optional output = api->UnPair(device_id_arg); - if (output.has_value()) { - reply(WrapError(output.value())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue()); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getSystemDevices" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_with_services_arg = args.at(0); - if (encodable_with_services_arg.IsNull()) { - reply(WrapError("with_services_arg unexpectedly null.")); - return; - } - const auto& with_services_arg = std::get(encodable_with_services_arg); - api->GetSystemDevices(with_services_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } - { - BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectionState" + prepended_suffix, &GetCodec()); - if (api != nullptr) { - channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_device_id_arg = args.at(0); - if (encodable_device_id_arg.IsNull()) { - reply(WrapError("device_id_arg unexpectedly null.")); - return; - } - const auto& device_id_arg = std::get(encodable_device_id_arg); - ErrorOr output = api->GetConnectionState(device_id_arg); - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(EncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); - } else { - channel.SetMessageHandler(nullptr); - } - } -} - -EncodableValue UniversalBlePlatformChannel::WrapError(std::string_view error_message) { - return EncodableValue(EncodableList{ - EncodableValue(std::string(error_message)), - EncodableValue("Error"), - EncodableValue() - }); -} - -EncodableValue UniversalBlePlatformChannel::WrapError(const FlutterError& error) { - return EncodableValue(EncodableList{ - EncodableValue(error.code()), - EncodableValue(error.message()), - error.details() - }); -} - -// Generated class from Pigeon that represents Flutter messages that can be called from C++. -UniversalBleCallbackChannel::UniversalBleCallbackChannel(flutter::BinaryMessenger* binary_messenger) - : binary_messenger_(binary_messenger), - message_channel_suffix_("") {} - -UniversalBleCallbackChannel::UniversalBleCallbackChannel( - flutter::BinaryMessenger* binary_messenger, - const std::string& message_channel_suffix) - : binary_messenger_(binary_messenger), - message_channel_suffix_(message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : "") {} - -const flutter::StandardMessageCodec& UniversalBleCallbackChannel::GetCodec() { - return flutter::StandardMessageCodec::GetInstance(&PigeonInternalCodecSerializer::GetInstance()); -} - -void UniversalBleCallbackChannel::OnAvailabilityChanged( - int64_t state_arg, - std::function&& on_success, - std::function&& on_error) { - const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged" + message_channel_suffix_; - BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); - EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ - EncodableValue(state_arg), - }); - channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* list_return_value = std::get_if(&encodable_return_value); - if (list_return_value) { - if (list_return_value->size() > 1) { - on_error(FlutterError(std::get(list_return_value->at(0)), std::get(list_return_value->at(1)), list_return_value->at(2))); - } else { - on_success(); - } - } else { - on_error(CreateConnectionError(channel_name)); - } - }); -} - -void UniversalBleCallbackChannel::OnPairStateChange( - const std::string& device_id_arg, - bool is_paired_arg, - const std::string* error_arg, - std::function&& on_success, - std::function&& on_error) { - const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange" + message_channel_suffix_; - BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); - EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ - EncodableValue(device_id_arg), - EncodableValue(is_paired_arg), - error_arg ? EncodableValue(*error_arg) : EncodableValue(), - }); - channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* list_return_value = std::get_if(&encodable_return_value); - if (list_return_value) { - if (list_return_value->size() > 1) { - on_error(FlutterError(std::get(list_return_value->at(0)), std::get(list_return_value->at(1)), list_return_value->at(2))); - } else { - on_success(); - } - } else { - on_error(CreateConnectionError(channel_name)); - } - }); -} - -void UniversalBleCallbackChannel::OnScanResult( - const UniversalBleScanResult& result_arg, - std::function&& on_success, - std::function&& on_error) { - const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult" + message_channel_suffix_; - BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); - EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ - CustomEncodableValue(result_arg), - }); - channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* list_return_value = std::get_if(&encodable_return_value); - if (list_return_value) { - if (list_return_value->size() > 1) { - on_error(FlutterError(std::get(list_return_value->at(0)), std::get(list_return_value->at(1)), list_return_value->at(2))); - } else { - on_success(); - } - } else { - on_error(CreateConnectionError(channel_name)); - } - }); -} - -void UniversalBleCallbackChannel::OnValueChanged( - const std::string& device_id_arg, - const std::string& characteristic_id_arg, - const std::vector& value_arg, - std::function&& on_success, - std::function&& on_error) { - const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged" + message_channel_suffix_; - BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); - EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ - EncodableValue(device_id_arg), - EncodableValue(characteristic_id_arg), - EncodableValue(value_arg), - }); - channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* list_return_value = std::get_if(&encodable_return_value); - if (list_return_value) { - if (list_return_value->size() > 1) { - on_error(FlutterError(std::get(list_return_value->at(0)), std::get(list_return_value->at(1)), list_return_value->at(2))); - } else { - on_success(); - } - } else { - on_error(CreateConnectionError(channel_name)); - } - }); -} - -void UniversalBleCallbackChannel::OnConnectionChanged( - const std::string& device_id_arg, - bool connected_arg, - const std::string* error_arg, - std::function&& on_success, - std::function&& on_error) { - const std::string channel_name = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged" + message_channel_suffix_; - BasicMessageChannel<> channel(binary_messenger_, channel_name, &GetCodec()); - EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ - EncodableValue(device_id_arg), - EncodableValue(connected_arg), - error_arg ? EncodableValue(*error_arg) : EncodableValue(), - }); - channel.Send(encoded_api_arguments, [channel_name, on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* list_return_value = std::get_if(&encodable_return_value); - if (list_return_value) { - if (list_return_value->size() > 1) { - on_error(FlutterError(std::get(list_return_value->at(0)), std::get(list_return_value->at(1)), list_return_value->at(2))); - } else { - on_success(); - } - } else { - on_error(CreateConnectionError(channel_name)); - } - }); -} - -} // namespace universal_ble diff --git a/universal_ble/windows/src/generated/universal_ble.g.h b/universal_ble/windows/src/generated/universal_ble.g.h deleted file mode 100644 index 2a22a7c..0000000 --- a/universal_ble/windows/src/generated/universal_ble.g.h +++ /dev/null @@ -1,403 +0,0 @@ -// Autogenerated from Pigeon (v22.6.1), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#ifndef PIGEON_UNIVERSAL_BLE_G_H_ -#define PIGEON_UNIVERSAL_BLE_G_H_ -#include -#include -#include -#include - -#include -#include -#include - -namespace universal_ble { - - -// Generated class from Pigeon. - -class FlutterError { - public: - explicit FlutterError(const std::string& code) - : code_(code) {} - explicit FlutterError(const std::string& code, const std::string& message) - : code_(code), message_(message) {} - explicit FlutterError(const std::string& code, const std::string& message, const flutter::EncodableValue& details) - : code_(code), message_(message), details_(details) {} - - const std::string& code() const { return code_; } - const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } - - private: - std::string code_; - std::string message_; - flutter::EncodableValue details_; -}; - -template class ErrorOr { - public: - ErrorOr(const T& rhs) : v_(rhs) {} - ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} - ErrorOr(const FlutterError& rhs) : v_(rhs) {} - ErrorOr(const FlutterError&& rhs) : v_(std::move(rhs)) {} - - bool has_error() const { return std::holds_alternative(v_); } - const T& value() const { return std::get(v_); }; - const FlutterError& error() const { return std::get(v_); }; - - private: - friend class UniversalBlePlatformChannel; - friend class UniversalBleCallbackChannel; - ErrorOr() = default; - T TakeValue() && { return std::get(std::move(v_)); } - - std::variant v_; -}; - - - -// Generated class from Pigeon that represents data sent in messages. -class UniversalBleScanResult { - public: - // Constructs an object setting all non-nullable fields. - explicit UniversalBleScanResult(const std::string& device_id); - - // Constructs an object setting all fields. - explicit UniversalBleScanResult( - const std::string& device_id, - const std::string* name, - const bool* is_paired, - const int64_t* rssi, - const flutter::EncodableList* manufacturer_data_list, - const flutter::EncodableList* services); - - const std::string& device_id() const; - void set_device_id(std::string_view value_arg); - - const std::string* name() const; - void set_name(const std::string_view* value_arg); - void set_name(std::string_view value_arg); - - const bool* is_paired() const; - void set_is_paired(const bool* value_arg); - void set_is_paired(bool value_arg); - - const int64_t* rssi() const; - void set_rssi(const int64_t* value_arg); - void set_rssi(int64_t value_arg); - - const flutter::EncodableList* manufacturer_data_list() const; - void set_manufacturer_data_list(const flutter::EncodableList* value_arg); - void set_manufacturer_data_list(const flutter::EncodableList& value_arg); - - const flutter::EncodableList* services() const; - void set_services(const flutter::EncodableList* value_arg); - void set_services(const flutter::EncodableList& value_arg); - - - private: - static UniversalBleScanResult FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class UniversalBlePlatformChannel; - friend class UniversalBleCallbackChannel; - friend class PigeonInternalCodecSerializer; - std::string device_id_; - std::optional name_; - std::optional is_paired_; - std::optional rssi_; - std::optional manufacturer_data_list_; - std::optional services_; - -}; - - -// Generated class from Pigeon that represents data sent in messages. -class UniversalBleService { - public: - // Constructs an object setting all non-nullable fields. - explicit UniversalBleService(const std::string& uuid); - - // Constructs an object setting all fields. - explicit UniversalBleService( - const std::string& uuid, - const flutter::EncodableList* characteristics); - - const std::string& uuid() const; - void set_uuid(std::string_view value_arg); - - const flutter::EncodableList* characteristics() const; - void set_characteristics(const flutter::EncodableList* value_arg); - void set_characteristics(const flutter::EncodableList& value_arg); - - - private: - static UniversalBleService FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class UniversalBlePlatformChannel; - friend class UniversalBleCallbackChannel; - friend class PigeonInternalCodecSerializer; - std::string uuid_; - std::optional characteristics_; - -}; - - -// Generated class from Pigeon that represents data sent in messages. -class UniversalBleCharacteristic { - public: - // Constructs an object setting all fields. - explicit UniversalBleCharacteristic( - const std::string& uuid, - const flutter::EncodableList& properties); - - const std::string& uuid() const; - void set_uuid(std::string_view value_arg); - - const flutter::EncodableList& properties() const; - void set_properties(const flutter::EncodableList& value_arg); - - - private: - static UniversalBleCharacteristic FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class UniversalBlePlatformChannel; - friend class UniversalBleCallbackChannel; - friend class PigeonInternalCodecSerializer; - std::string uuid_; - flutter::EncodableList properties_; - -}; - - -// Scan Filters -// -// Generated class from Pigeon that represents data sent in messages. -class UniversalScanFilter { - public: - // Constructs an object setting all fields. - explicit UniversalScanFilter( - const flutter::EncodableList& with_services, - const flutter::EncodableList& with_name_prefix, - const flutter::EncodableList& with_manufacturer_data); - - const flutter::EncodableList& with_services() const; - void set_with_services(const flutter::EncodableList& value_arg); - - const flutter::EncodableList& with_name_prefix() const; - void set_with_name_prefix(const flutter::EncodableList& value_arg); - - const flutter::EncodableList& with_manufacturer_data() const; - void set_with_manufacturer_data(const flutter::EncodableList& value_arg); - - - private: - static UniversalScanFilter FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class UniversalBlePlatformChannel; - friend class UniversalBleCallbackChannel; - friend class PigeonInternalCodecSerializer; - flutter::EncodableList with_services_; - flutter::EncodableList with_name_prefix_; - flutter::EncodableList with_manufacturer_data_; - -}; - - -// Generated class from Pigeon that represents data sent in messages. -class UniversalManufacturerDataFilter { - public: - // Constructs an object setting all non-nullable fields. - explicit UniversalManufacturerDataFilter(int64_t company_identifier); - - // Constructs an object setting all fields. - explicit UniversalManufacturerDataFilter( - int64_t company_identifier, - const std::vector* data, - const std::vector* mask); - - int64_t company_identifier() const; - void set_company_identifier(int64_t value_arg); - - const std::vector* data() const; - void set_data(const std::vector* value_arg); - void set_data(const std::vector& value_arg); - - const std::vector* mask() const; - void set_mask(const std::vector* value_arg); - void set_mask(const std::vector& value_arg); - - - private: - static UniversalManufacturerDataFilter FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class UniversalBlePlatformChannel; - friend class UniversalBleCallbackChannel; - friend class PigeonInternalCodecSerializer; - int64_t company_identifier_; - std::optional> data_; - std::optional> mask_; - -}; - - -// Generated class from Pigeon that represents data sent in messages. -class UniversalManufacturerData { - public: - // Constructs an object setting all fields. - explicit UniversalManufacturerData( - int64_t company_identifier, - const std::vector& data); - - int64_t company_identifier() const; - void set_company_identifier(int64_t value_arg); - - const std::vector& data() const; - void set_data(const std::vector& value_arg); - - - private: - static UniversalManufacturerData FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class UniversalBlePlatformChannel; - friend class UniversalBleCallbackChannel; - friend class PigeonInternalCodecSerializer; - int64_t company_identifier_; - std::vector data_; - -}; - - -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { - public: - PigeonInternalCodecSerializer(); - inline static PigeonInternalCodecSerializer& GetInstance() { - static PigeonInternalCodecSerializer sInstance; - return sInstance; - } - - void WriteValue( - const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - - protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, - flutter::ByteStreamReader* stream) const override; - -}; - -// Flutter -> Native -// -// Generated interface from Pigeon that represents a handler of messages from Flutter. -class UniversalBlePlatformChannel { - public: - UniversalBlePlatformChannel(const UniversalBlePlatformChannel&) = delete; - UniversalBlePlatformChannel& operator=(const UniversalBlePlatformChannel&) = delete; - virtual ~UniversalBlePlatformChannel() {} - virtual void GetBluetoothAvailabilityState(std::function reply)> result) = 0; - virtual void EnableBluetooth(std::function reply)> result) = 0; - virtual void DisableBluetooth(std::function reply)> result) = 0; - virtual std::optional StartScan(const UniversalScanFilter* filter) = 0; - virtual std::optional StopScan() = 0; - virtual std::optional Connect(const std::string& device_id) = 0; - virtual std::optional Disconnect(const std::string& device_id) = 0; - virtual void SetNotifiable( - const std::string& device_id, - const std::string& service, - const std::string& characteristic, - int64_t ble_input_property, - std::function reply)> result) = 0; - virtual void DiscoverServices( - const std::string& device_id, - std::function reply)> result) = 0; - virtual void ReadValue( - const std::string& device_id, - const std::string& service, - const std::string& characteristic, - std::function> reply)> result) = 0; - virtual void RequestMtu( - const std::string& device_id, - int64_t expected_mtu, - std::function reply)> result) = 0; - virtual void WriteValue( - const std::string& device_id, - const std::string& service, - const std::string& characteristic, - const std::vector& value, - int64_t ble_output_property, - std::function reply)> result) = 0; - virtual void IsPaired( - const std::string& device_id, - std::function reply)> result) = 0; - virtual void Pair( - const std::string& device_id, - std::function reply)> result) = 0; - virtual std::optional UnPair(const std::string& device_id) = 0; - virtual void GetSystemDevices( - const flutter::EncodableList& with_services, - std::function reply)> result) = 0; - virtual ErrorOr GetConnectionState(const std::string& device_id) = 0; - - // The codec used by UniversalBlePlatformChannel. - static const flutter::StandardMessageCodec& GetCodec(); - // Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binary_messenger`. - static void SetUp( - flutter::BinaryMessenger* binary_messenger, - UniversalBlePlatformChannel* api); - static void SetUp( - flutter::BinaryMessenger* binary_messenger, - UniversalBlePlatformChannel* api, - const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); - - protected: - UniversalBlePlatformChannel() = default; - -}; -// Native -> Flutter -// -// Generated class from Pigeon that represents Flutter messages that can be called from C++. -class UniversalBleCallbackChannel { - public: - UniversalBleCallbackChannel(flutter::BinaryMessenger* binary_messenger); - UniversalBleCallbackChannel( - flutter::BinaryMessenger* binary_messenger, - const std::string& message_channel_suffix); - static const flutter::StandardMessageCodec& GetCodec(); - void OnAvailabilityChanged( - int64_t state, - std::function&& on_success, - std::function&& on_error); - void OnPairStateChange( - const std::string& device_id, - bool is_paired, - const std::string* error, - std::function&& on_success, - std::function&& on_error); - void OnScanResult( - const UniversalBleScanResult& result, - std::function&& on_success, - std::function&& on_error); - void OnValueChanged( - const std::string& device_id, - const std::string& characteristic_id, - const std::vector& value, - std::function&& on_success, - std::function&& on_error); - void OnConnectionChanged( - const std::string& device_id, - bool connected, - const std::string* error, - std::function&& on_success, - std::function&& on_error); - - private: - flutter::BinaryMessenger* binary_messenger_; - std::string message_channel_suffix_; -}; - -} // namespace universal_ble -#endif // PIGEON_UNIVERSAL_BLE_G_H_ diff --git a/universal_ble/windows/src/helper/universal_ble_base.h b/universal_ble/windows/src/helper/universal_ble_base.h deleted file mode 100644 index 196761e..0000000 --- a/universal_ble/windows/src/helper/universal_ble_base.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace universal_ble -{ - using namespace winrt; - using namespace winrt::Windows; - using namespace winrt::Windows::Devices; - using namespace winrt::Windows::Foundation; - using namespace winrt::Windows::Foundation::Collections; - using namespace winrt::Windows::Storage::Streams; - using namespace winrt::Windows::Devices::Radios; - using namespace winrt::Windows::Devices::Bluetooth; - using namespace winrt::Windows::Devices::Bluetooth::Advertisement; - using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile; - using namespace Windows::Devices::Enumeration; -} \ No newline at end of file diff --git a/universal_ble/windows/src/helper/universal_enum.h b/universal_ble/windows/src/helper/universal_enum.h deleted file mode 100644 index 0d795a8..0000000 --- a/universal_ble/windows/src/helper/universal_enum.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -namespace universal_ble -{ - - enum class ConnectionState : int - { - connected = 0, - disconnected = 1, - }; - - enum class CharacteristicProperty : int - { - broadcast = 0, - read = 1, - writeWithoutResponse = 2, - write = 3, - notify = 4, - indicate = 5, - authenticatedSignedWrites = 6, - extendedProperties = 7, - }; - - enum class BleInputProperty : int - { - disabled = 0, - notification = 1, - indication = 2, - }; - - enum class BleOutputProperty : int - { - withResponse = 0, - withoutResponse = 1, - }; - - enum class AvailabilityState : int - { - unknown = 0, - resetting = 1, - unsupported = 2, - unauthorized = 3, - poweredOff = 4, - poweredOn = 5, - }; - - enum class AdvertisementSectionType : uint8_t - { - Flags = 0x01, - IncompleteService16BitUuids = 0x02, - CompleteService16BitUuids = 0x03, - IncompleteService32BitUuids = 0x04, - CompleteService32BitUuids = 0x05, - IncompleteService128BitUuids = 0x06, - CompleteService128BitUuids = 0x07, - ShortenedLocalName = 0x08, - CompleteLocalName = 0x09, - TxPowerLevel = 0x0A, - ClassOfDevice = 0x0D, - SimplePairingHashC192 = 0x0E, - SecurityManagerTKValues = 0x10, - SecurityManagerOutOfBandFlags = 0x11, - SlaveConnectionIntervalRange = 0x12, - ServiceSolicitation16BitUuids = 0x14, - ServiceSolicitation32BitUuids = 0x1F, - ServiceSolicitation128BitUuids = 0x15, - ServiceData16BitUuids = 0x16, - ServiceData32BitUuids = 0x20, - ServiceData128BitUuids = 0x21, - PublicTargetAddress = 0x17, - RandomTargetAddress = 0x18, - Appearance = 0x19, - AdvertisingInterval = 0x1A, - LEBluetoothDeviceAddress = 0x1B, - LERole = 0x1C, - SimplePairingHashC256 = 0x1D, - ThreeDimensionInformationData = 0x3D, - ManufacturerSpecificData = 0xFF, - }; - -} // namespace universal_ble \ No newline at end of file diff --git a/universal_ble/windows/src/helper/utils.cpp b/universal_ble/windows/src/helper/utils.cpp deleted file mode 100644 index a34f8e1..0000000 --- a/universal_ble/windows/src/helper/utils.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "Utils.h" - -#include -#include -#include -#include -#include -#include - -#if WDK_NTDDI_VERSION < NTDDI_WIN10_VB -#error "Windows SDK version before 10.0.19041.0 is not supported" -#elif WDK_NTDDI_VERSION == NTDDI_WIN10_VB -#define WINRT_IMPL_CoGetApartmentType WINRT_CoGetApartmentType -#endif - -#define MAC_ADDRESS_STR_LENGTH (size_t)17 -typedef LONG NTSTATUS, *PNTSTATUS; -#define STATUS_SUCCESS (0x00000000) -typedef NTSTATUS(WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); - -namespace universal_ble -{ - - std::string mac_address_to_str(uint64_t mac_address) - { - uint8_t* mac_ptr = (uint8_t*)&mac_address; - char mac_str[MAC_ADDRESS_STR_LENGTH + 1] = { 0 }; - snprintf(mac_str, MAC_ADDRESS_STR_LENGTH + 1, "%02x:%02x:%02x:%02x:%02x:%02x", mac_ptr[5], mac_ptr[4], mac_ptr[3], - mac_ptr[2], mac_ptr[1], mac_ptr[0]); - return std::string(mac_str); - } - - uint64_t str_to_mac_address(const std::string& mac_str) - { - uint64_t mac_address_number = 0; - uint8_t* mac_ptr = (uint8_t*)&mac_address_number; - sscanf_s(mac_str.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &mac_ptr[5], &mac_ptr[4], &mac_ptr[3], - &mac_ptr[2], &mac_ptr[1], &mac_ptr[0]); - return mac_address_number; - } - - guid uuid_to_guid(const std::string &uuid) - { - std::stringstream helper; - for (int i = 0; i < uuid.length(); i++) - { - if (uuid[i] != '-') - { - helper << uuid[i]; - } - } - std::string clean_uuid = helper.str(); - winrt::guid guid; - uint64_t* data4_ptr = (uint64_t*)guid.Data4; - - guid.Data1 = static_cast(std::strtoul(clean_uuid.substr(0, 8).c_str(), nullptr, 16)); - guid.Data2 = static_cast(std::strtoul(clean_uuid.substr(8, 4).c_str(), nullptr, 16)); - guid.Data3 = static_cast(std::strtoul(clean_uuid.substr(12, 4).c_str(), nullptr, 16)); - *data4_ptr = _byteswap_uint64(std::strtoull(clean_uuid.substr(16, 16).c_str(), nullptr, 16)); - - return guid; - } - - std::string guid_to_uuid(const guid &guid) - { - std::stringstream helper; - for (uint32_t i = 0; i < 4; i++) - { - helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t*)&guid.Data1)[3 - i]; - } - helper << '-'; - for (uint32_t i = 0; i < 2; i++) - { - helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t*)&guid.Data2)[1 - i]; - } - helper << '-'; - for (uint32_t i = 0; i < 2; i++) - { - helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t*)&guid.Data3)[1 - i]; - } - helper << '-'; - for (uint32_t i = 0; i < 2; i++) - { - helper << std::hex << std::setw(2) << std::setfill('0') << (int)guid.Data4[i]; - } - helper << '-'; - for (uint32_t i = 0; i < 6; i++) - { - helper << std::hex << std::setw(2) << std::setfill('0') << (int)guid.Data4[2 + i]; - } - return helper.str(); - } - - std::vector to_bytevc(const IBuffer& buffer) - { - auto reader = DataReader::FromBuffer(buffer); - auto result = std::vector(reader.UnconsumedBufferLength()); - reader.ReadBytes(result); - return result; - } - - IBuffer from_bytevc(std::vector bytes) - { - auto writer = DataWriter(); - writer.WriteBytes(bytes); - return writer.DetachBuffer(); - } - - std::string to_hexstring(const std::vector& bytes) - { - auto ss = std::stringstream(); - for (auto b : bytes) - ss << std::setw(2) << std::setfill('0') << std::hex << static_cast(b); - return ss.str(); - } - - std::string to_uuidstr(const guid guid) - { - char chars[36 + 1]; - sprintf_s(chars, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", - guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], - guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); - return std::string{ chars }; - } - - bool is_little_endian() - { - uint16_t number = 0x1; - char* numPtr = (char*)&number; - return (numPtr[0] == 1); - } - - bool is_windows11_or_greater() - { - const HMODULE h_mod = GetModuleHandleW(L"ntdll.dll"); - if (!h_mod) - { - std::cout << "Failed to get ntdll" << std::endl; - return false; - } - - const auto fx_ptr = reinterpret_cast(GetProcAddress(h_mod, "RtlGetVersion")); - if (fx_ptr == nullptr) - { - std::cout << "Failed to get RtlGetVersionPtr" << std::endl; - return false; - } - - RTL_OSVERSIONINFOW rove = {0}; - rove.dwOSVersionInfoSize = sizeof(rove); - if (STATUS_SUCCESS != fx_ptr(&rove)) - { - std::cout << "Failed to get RTL_OSVERSIONINFOW" << std::endl; - return false; - } - - // Windows 11 => MajorVersion = 10 and BuildNumber >= 22000 - return rove.dwMajorVersion == 10 && rove.dwBuildNumber >= 22000; - } - -} // namespace universal_ble diff --git a/universal_ble/windows/src/helper/utils.h b/universal_ble/windows/src/helper/utils.h deleted file mode 100644 index 49408bb..0000000 --- a/universal_ble/windows/src/helper/utils.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "winrt/Windows.Foundation.h" -#include "winrt/Windows.Storage.Streams.h" -#include "winrt/base.h" -#include "universal_ble_base.h" - -constexpr uint32_t TEN_SECONDS_IN_MSECS = 10000; - -namespace universal_ble -{ - - std::string mac_address_to_str(uint64_t mac_address); - uint64_t str_to_mac_address(const std::string& mac_str); - - guid uuid_to_guid(const std::string &uuid); - std::string guid_to_uuid(const guid &guid); - - std::vector to_bytevc(const IBuffer& buffer); - IBuffer from_bytevc(std::vector bytes); - std::string to_hexstring(const std::vector& bytes); - - std::string to_uuidstr(guid guid); - bool is_little_endian(); - bool is_windows11_or_greater(); - - /// To call async functions synchronously - template - static auto async_get(AsyncT const &async) - { - if (async.Status() == AsyncStatus::Started) - { - wait_for_completed(async, TEN_SECONDS_IN_MSECS); - } - try - { - return async.GetResults(); - } - catch (const hresult_error &err) - { - throw FlutterError("Failed", to_string(err.message())); - } - catch (...) - { - throw FlutterError("Failed", "Unknown error"); - } - } - -} // namespace universal_ble \ No newline at end of file diff --git a/universal_ble/windows/src/pin_entry.h b/universal_ble/windows/src/pin_entry.h deleted file mode 100644 index 4b86bc4..0000000 --- a/universal_ble/windows/src/pin_entry.h +++ /dev/null @@ -1,134 +0,0 @@ -#pragma once - -#include -#include - -namespace universal_ble -{ - typedef struct SizeAndPos_s - { - int x, y, width, height; - } SizeAndPos_t; - - const WORD ID_btnOK = 1; - const WORD ID_txtEdit = 4; - HWND txtEditHandle = NULL; - TCHAR textBoxText[16]; - - // Positions and dimensions of UI elements: X, Y, Width, Height - const SizeAndPos_t mainWindow = {150, 150, 450, 260}; - const SizeAndPos_t txtEdit = {50, 40, 320, 40}; - const SizeAndPos_t btnOK = {50, 100, 320, 40}; - - LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) - { - switch (msg) - { - case WM_CREATE: - { - txtEditHandle = CreateWindow( - TEXT("Edit"), TEXT(""), - WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER, - txtEdit.x, txtEdit.y, txtEdit.width, txtEdit.height, - hwnd, (HMENU)ID_txtEdit, NULL, NULL); - CreateWindow( - TEXT("Button"), TEXT("OK"), - WS_CHILD | WS_VISIBLE | BS_FLAT, - btnOK.x, btnOK.y, btnOK.width, btnOK.height, - hwnd, (HMENU)ID_btnOK, NULL, NULL); - break; - } - case WM_COMMAND: - if (LOWORD(wParam) == ID_btnOK) - { - GetWindowText(txtEditHandle, textBoxText, sizeof(textBoxText) / sizeof(TCHAR)); - DestroyWindow(hwnd); - } - break; - case WM_CLOSE: - DestroyWindow(hwnd); - break; - case WM_DESTROY: - PostQuitMessage(0); - break; - default: - return DefWindowProc(hwnd, msg, wParam, lParam); - } - - return 0; - } - - hstring askForPairingPin() - { - textBoxText[0] = '\0'; - HINSTANCE hInstance = GetModuleHandle(NULL); - MSG msg; - WNDCLASS mainWindowClass = {0}; - mainWindowClass.lpszClassName = TEXT("JRH.MainWindow"); - mainWindowClass.hInstance = hInstance; - mainWindowClass.hbrBackground = GetSysColorBrush(COLOR_BTNHIGHLIGHT); - mainWindowClass.lpfnWndProc = WndProc; - mainWindowClass.hCursor = LoadCursor(0, IDC_ARROW); - - // Register the window class - if (!RegisterClass(&mainWindowClass)) - { - std::cout << "PinPairDialog: Failed to register window class" << std::endl; - return L""; - } - - HWND hwnd = CreateWindow( - mainWindowClass.lpszClassName, - TEXT("PIN"), (WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX) | WS_VISIBLE, - mainWindow.x, mainWindow.y, mainWindow.width, mainWindow.height, - NULL, 0, hInstance, NULL); - - if (hwnd == NULL) - { - std::cout << "PinPairDialog: Failed to create window" << std::endl; - return L""; - } - - // After creating the window, make it topmost - SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - - ShowWindow(hwnd, SW_SHOW); - - // Create a font with the desired size - HFONT hFont = CreateFont( - 36, // Height of the font - 0, // Width of the font - 0, // Angle of escapement - 0, // Orientation angle - FW_NORMAL, // Font weight - FALSE, // Italic attribute option - FALSE, // Underline attribute option - FALSE, // Strikeout attribute option - DEFAULT_CHARSET, // Character set identifier - OUT_DEFAULT_PRECIS, // Output precision - CLIP_DEFAULT_PRECIS, // Clipping precision - DEFAULT_QUALITY, // Output quality - DEFAULT_PITCH | FF_SWISS, // Pitch and family - TEXT("Arial") // Font name - ); - - // Set the font to the edit control - SendMessage(txtEditHandle, WM_SETFONT, (WPARAM)hFont, TRUE); - - while (GetMessage(&msg, NULL, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if (msg.wParam != 0) - { - std::wcout << "PinPairDialog: Got invalid result" << std::endl; - } - - DeleteObject(hFont); - DestroyWindow(hwnd); - UnregisterClass(mainWindowClass.lpszClassName, hInstance); - return winrt::to_hstring(textBoxText); - } -} diff --git a/universal_ble/windows/src/ui_thread_handler.hpp b/universal_ble/windows/src/ui_thread_handler.hpp deleted file mode 100644 index 9f8a327..0000000 --- a/universal_ble/windows/src/ui_thread_handler.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include - -#include - -#include -#include -#include -#include - -class UniversalBleUiThreadHandler -{ -public: - explicit UniversalBleUiThreadHandler(flutter::PluginRegistrarWindows *registrar) - : registrar_(registrar) - { - windowProcId_ = registrar_->RegisterTopLevelWindowProcDelegate( - [this](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) - { - return HandleWindowMessage(hwnd, message, wparam, lparam); - }); - } - - ~UniversalBleUiThreadHandler() - { - registrar_->UnregisterTopLevelWindowProcDelegate(windowProcId_); - } - - UniversalBleUiThreadHandler(const UniversalBleUiThreadHandler &) = delete; - UniversalBleUiThreadHandler &operator=(const UniversalBleUiThreadHandler &) = delete; - - void Post(std::function &&func) - { - std::lock_guard lock(mutex_); - queuedFuncs_.emplace_back(std::move(func)); - Notify(); - } - -private: - static const UINT kWmCallQueuedFunctions = WM_APP + 0x1d7; - - void Notify() - { - if (hwnd_ != 0) - { - PostMessage(hwnd_, kWmCallQueuedFunctions, 0, reinterpret_cast(this)); - } - } - - std::optional HandleWindowMessage( - HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) - { - if (hwnd_ == 0) - { - hwnd_ = hwnd; - Notify(); // Make sure queued functions are processed - } - if (message == kWmCallQueuedFunctions && lparam == reinterpret_cast(this)) - { - std::list> queuedFuncs; - { - std::lock_guard lock(mutex_); - std::swap(queuedFuncs_, queuedFuncs); - } - for (auto &func : queuedFuncs) - { - func(); - } - } - return std::nullopt; - } - - flutter::PluginRegistrarWindows *registrar_; - int windowProcId_ = 0; - HWND hwnd_ = 0; - std::list> queuedFuncs_; - std::mutex mutex_; -}; \ No newline at end of file diff --git a/universal_ble/windows/src/universal_ble_filter_util.cpp b/universal_ble/windows/src/universal_ble_filter_util.cpp deleted file mode 100644 index 65bf064..0000000 --- a/universal_ble/windows/src/universal_ble_filter_util.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include "helper/utils.h" -#include "generated/universal_ble.g.h" -#include - -namespace universal_ble -{ - std::vector manufacturerScanFilter = std::vector(); - std::vector serviceFilterUUIDS = std::vector(); - std::vector namePrefixFilter = std::vector(); - - void setScanFilter(const UniversalScanFilter filter) - { - // Set ManufacturerData filter - const auto &manufacturerData = filter.with_manufacturer_data(); - for (const flutter::EncodableValue &data : manufacturerData) - { - UniversalManufacturerDataFilter manufacturerDataFilter = std::any_cast(std::get(data)); - manufacturerScanFilter.push_back(manufacturerDataFilter); - } - // Set Services Filter - if (!filter.with_services().empty()) - { - for (const auto &uuid : filter.with_services()) - { - serviceFilterUUIDS.push_back(uuid_to_guid(std::get(uuid))); - } - } - // Set Names Filter - if (!filter.with_name_prefix().empty()) - { - for (const auto &name : filter.with_name_prefix()) - { - namePrefixFilter.push_back(std::get(name)); - } - } - } - - void resetScanFilter() - { - manufacturerScanFilter.clear(); - serviceFilterUUIDS.clear(); - namePrefixFilter.clear(); - } - - bool isNameMatchingFilters(const std::string *name) - { - if (namePrefixFilter.empty()) - return true; - if (name == nullptr || name->empty()) - return false; - return std::any_of(namePrefixFilter.begin(), namePrefixFilter.end(), - [&name](const flutter::EncodableValue &prefix) - { - return name->find(std::get(prefix)) == 0; - }); - } - - bool isServicesMatchingFilters(const flutter::EncodableList *services) - { - if (serviceFilterUUIDS.empty()) - return true; - if (services == nullptr || services->empty()) - return false; - - std::unordered_set serviceGUIDs; - serviceGUIDs.reserve(services->size()); - for (const auto &service : *services) - { - if (const auto *str = std::get_if(&service)) - { - serviceGUIDs.insert(uuid_to_guid(*str)); - } - } - - // Check if any of the filter UUIDs are in the set of service GUIDs - return std::any_of(serviceFilterUUIDS.begin(), serviceFilterUUIDS.end(), - [&serviceGUIDs](const winrt::guid &filterUUID) - { - return serviceGUIDs.find(filterUUID) != serviceGUIDs.end(); - }); - } - - bool isManufacturerDataMatchingFilters(const flutter::EncodableList *manufacturerDataList) - { - if (manufacturerScanFilter.empty()) - return true; - if (manufacturerDataList == nullptr || manufacturerDataList->empty()) - return false; - - for (const auto &filter : manufacturerScanFilter) - { - const auto *data_filter = filter.data(); - const auto *mask = filter.mask(); - - for (const auto &value : *manufacturerDataList) - { - const auto &deviceManufacturerData = std::any_cast( - std::get(value)); - - if (deviceManufacturerData.company_identifier() != filter.company_identifier()) - continue; - - // If no data filter, all data matches - if (data_filter == nullptr) - return true; - - const auto &deviceData = deviceManufacturerData.data(); - if (deviceData.size() < data_filter->size()) - continue; - - bool isMatch = true; - for (size_t i = 0; i < data_filter->size(); ++i) - { - const bool hasMask = mask != nullptr && i < mask->size(); - const uint8_t maskByte = hasMask ? (*mask)[i] : 0xFF; - if ((maskByte & (*data_filter)[i]) != (maskByte & deviceData[i])) - { - isMatch = false; - break; - } - } - - if (isMatch) - return true; - } - } - - return false; - } - - bool filterDevice(UniversalBleScanResult scanResult) - { - bool hasNamePrefixFilter = !namePrefixFilter.empty(); - bool hasServiceFilter = !serviceFilterUUIDS.empty(); - bool hasManufacturerDataFilter = !manufacturerScanFilter.empty(); - - // If there is no filter at all, then allow device - if (!hasNamePrefixFilter && - !hasServiceFilter && - !hasManufacturerDataFilter) - { - return true; - } - - // Check each filter condition - return (hasNamePrefixFilter && isNameMatchingFilters(scanResult.name())) || - (hasServiceFilter && isServicesMatchingFilters(scanResult.services())) || - (hasManufacturerDataFilter && isManufacturerDataMatchingFilters(scanResult.manufacturer_data_list())); - } - -} // namespace universal_ble diff --git a/universal_ble/windows/src/universal_ble_filter_util.h b/universal_ble/windows/src/universal_ble_filter_util.h deleted file mode 100644 index 13496d8..0000000 --- a/universal_ble/windows/src/universal_ble_filter_util.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "helper/universal_ble_base.h" -#include "generated/universal_ble.g.h" - -namespace universal_ble -{ - void setScanFilter(const UniversalScanFilter filter); - void resetScanFilter(); - bool filterDevice(UniversalBleScanResult scanResult); -} // namespace universal_ble \ No newline at end of file diff --git a/universal_ble/windows/src/universal_ble_plugin.cpp b/universal_ble/windows/src/universal_ble_plugin.cpp deleted file mode 100644 index a5f0097..0000000 --- a/universal_ble/windows/src/universal_ble_plugin.cpp +++ /dev/null @@ -1,1249 +0,0 @@ -// ReSharper disable CppTooWideScopeInitStatement -// ReSharper disable CppTooWideScope -#include "universal_ble_plugin.h" -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "helper/utils.h" -#include "helper/universal_enum.h" -#include "generated/universal_ble.g.h" -#include "pin_entry.h" -#include "universal_ble_filter_util.h" -#include "enum_parser.h" - -namespace universal_ble -{ - using universal_ble::ErrorOr; - using universal_ble::UniversalBleCallbackChannel; - using universal_ble::UniversalBlePlatformChannel; - using universal_ble::UniversalBleScanResult; - - const auto is_connectable_key = L"System.Devices.Aep.Bluetooth.Le.IsConnectable"; - const auto is_connected_key = L"System.Devices.Aep.IsConnected"; - const auto is_paired_key = L"System.Devices.Aep.IsPaired"; - const auto is_present_key = L"System.Devices.Aep.IsPresent"; - const auto device_address_key = L"System.Devices.Aep.DeviceAddress"; - const auto signal_strength_key = L"System.Devices.Aep.SignalStrength"; - static std::unique_ptr callback_channel; - - void UniversalBlePlugin::RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar) - { - auto plugin = std::make_unique(registrar); - SetUp(registrar->messenger(), plugin.get()); - callback_channel = std::make_unique(registrar->messenger()); - registrar->AddPlugin(std::move(plugin)); - } - - UniversalBlePlugin::UniversalBlePlugin(flutter::PluginRegistrarWindows *registrar) - : ui_thread_handler_(registrar) - { - InitializeAsync(); - } - - UniversalBlePlugin::~UniversalBlePlugin() = default; - - // UniversalBlePlatformChannel implementation. - void UniversalBlePlugin::GetBluetoothAvailabilityState(std::function reply)> result) - { - if (!bluetooth_radio_) - { - if (!initialized_) - { - result(static_cast(AvailabilityState::unknown)); - } - else - { - result(static_cast(AvailabilityState::unsupported)); - } - } - else - { - result(static_cast(get_availability_state_from_radio(bluetooth_radio_.State()))); - } - }; - - void UniversalBlePlugin::EnableBluetooth(std::function reply)> result) - { - if (!bluetooth_radio_) - { - result(FlutterError("BluetoothNotAvailable", "Bluetooth is not available")); - return; - } - - if (bluetooth_radio_.State() == RadioState::On) - { - result(true); - return; - } - - bluetooth_radio_.SetStateAsync(RadioState::On).Completed( - [&, result](const IAsyncOperation& sender, const AsyncStatus args) - { - if (const auto radio_access_status = sender.GetResults(); radio_access_status == RadioAccessStatus::Allowed) - { - result(true); - } - else - { - result(FlutterError("Failed","Failed to enable bluetooth")); - } - }); - } - - void UniversalBlePlugin::DisableBluetooth(std::function reply)> result) - { - if (!bluetooth_radio_) - { - result(FlutterError("BluetoothNotAvailable", "Bluetooth is not available")); - return; - } - - if (bluetooth_radio_.State() == RadioState::Off) - { - result(true); - return; - } - - bluetooth_radio_.SetStateAsync(RadioState::Off).Completed( - [&, result](IAsyncOperation const& sender, AsyncStatus const args) - { - if (const auto radio_access_status = sender.GetResults(); radio_access_status == RadioAccessStatus::Allowed) - { - result(true); - } - else - { - result(FlutterError("Failed","Failed to disable bluetooth")); - } - }); - } - - std::optional UniversalBlePlugin::StartScan(const UniversalScanFilter *filter) - { - - if (!bluetooth_radio_ || bluetooth_radio_.State() != RadioState::On) - { - return FlutterError("BluetoothNotAvailable", "Bluetooth is not available"); - } - - try - { - SetupDeviceWatcher(); - scan_results_.clear(); - const DeviceWatcherStatus device_watcher_status = device_watcher_.Status(); - // std::cout << "DeviceWatcherState: " << DeviceWatcherStatusToString(deviceWatcherStatus) << std::endl; - // DeviceWatcher can only start if its in Created, Stopped, or Aborted state - if (device_watcher_status == DeviceWatcherStatus::Created || device_watcher_status == DeviceWatcherStatus::Stopped || device_watcher_status == DeviceWatcherStatus::Aborted) - { - device_watcher_.Start(); - } - else if (device_watcher_status == DeviceWatcherStatus::Stopping) - { - return FlutterError("AlreadyInProgress", "StoppingScan in progress"); - } - - // Setup LeWatcher and apply filters - if (!bluetooth_le_watcher_) - { - bluetooth_le_watcher_ = BluetoothLEAdvertisementWatcher(); - bluetooth_le_watcher_.ScanningMode(BluetoothLEScanningMode::Active); - resetScanFilter(); - - if (filter != nullptr) - { - // Native filter supports only 1 service - const bool uses_custom_filters = filter->with_services().size() > 1 || filter->with_manufacturer_data().size() > 0 || filter->with_name_prefix().size() > 0; - - if (uses_custom_filters) - { - std::cout << "Using Custom Scan Filter" << std::endl; - setScanFilter(*filter); - } - else - { - // Apply Services filter - if (!filter->with_services().empty()) - { - for (const auto &uuid : filter->with_services()) - { - bluetooth_le_watcher_.AdvertisementFilter().Advertisement().ServiceUuids().Append(uuid_to_guid(std::get(uuid))); - } - } - } - } - - bluetooth_le_watcher_received_token_ = bluetooth_le_watcher_.Received({this, &UniversalBlePlugin::BluetoothLeWatcherReceived}); - } - bluetooth_le_watcher_.Start(); - return std::nullopt; - } - catch (...) - { - std::cout << "Unknown error StartScan" << std::endl; - return FlutterError("Failed", "Unknown error"); - } - }; - - std::optional UniversalBlePlugin::StopScan() - { - if (bluetooth_radio_ && bluetooth_radio_.State() == RadioState::On) - { - try - { - if (bluetooth_le_watcher_) - { - bluetooth_le_watcher_.Received(bluetooth_le_watcher_received_token_); - bluetooth_le_watcher_.Stop(); - } - bluetooth_le_watcher_ = nullptr; - DisposeDeviceWatcher(); - scan_results_.clear(); - return std::nullopt; - } - catch (const hresult_error &err) - { - const int error_code = err.code(); - std::cout << "StopScanLog: " << to_string(err.message()) << " ErrorCode: " << std::to_string(error_code) << std::endl; - return FlutterError(std::to_string(error_code), to_string(err.message())); - } - catch (...) - { - return FlutterError("Failed", "Failed to Stop"); - } - } - else - { - return FlutterError("BluetoothNotAvailable", "Bluetooth is not available"); - } - }; - - ErrorOr UniversalBlePlugin::GetConnectionState(const std::string& device_id) - { - const auto it = connected_devices_.find(str_to_mac_address(device_id)); - if (it == connected_devices_.end()) - { - return static_cast(ConnectionState::disconnected); - } - - const auto device_agent = *it->second; - - if (device_agent.device.ConnectionStatus() == BluetoothConnectionStatus::Connected) - { - return static_cast(ConnectionState::connected); - } - else - { - return static_cast(ConnectionState::disconnected); - } - } - - std::optional UniversalBlePlugin::Connect(const std::string &device_id) - { - ConnectAsync(str_to_mac_address(device_id)); - return std::nullopt; - }; - - std::optional UniversalBlePlugin::Disconnect(const std::string &device_id) - { - auto device_address = str_to_mac_address(device_id); - CleanConnection(device_address); - // TODO: send disconnect event only after disconnect is complete - ui_thread_handler_.Post([device_address] - { callback_channel->OnConnectionChanged(mac_address_to_str(device_address), false, nullptr, SuccessCallback, ErrorCallback); }); - - return std::nullopt; - } - - void UniversalBlePlugin::DiscoverServices( - const std::string &device_id, - std::function reply)> result) - { - try - { - const auto it = connected_devices_.find(str_to_mac_address(device_id)); - if (it == connected_devices_.end()) - { - result(FlutterError("IllegalArgument", "Unknown devicesId:" + device_id)); - return; - } - auto device_agent = *it->second; - DiscoverServicesAsync(device_agent, result); - } - catch (const FlutterError &err) - { - return result(err); - } - catch (...) - { - std::cout << "DiscoverServicesLog: Unknown error" << std::endl; - return result(FlutterError("Failed", "Unknown error")); - } - } - - void UniversalBlePlugin::SetNotifiable( - const std::string &device_id, - const std::string &service, - const std::string &characteristic, - int64_t ble_input_property, - std::function reply)> result) - { - SetNotifiableAsync(device_id, service, characteristic, ble_input_property, result); - }; - - void UniversalBlePlugin::ReadValue( - const std::string& device_id, - const std::string& service, - const std::string& characteristic, - std::function> reply)> result) - { - try - { - const auto it = connected_devices_.find(str_to_mac_address(device_id)); - if (it == connected_devices_.end()) - { - result(FlutterError("IllegalArgument", "Unknown devicesId:" + device_id)); - return; - } - - auto bluetooth_agent = *it->second; - const GattCharacteristicObject& gatt_characteristic_holder = bluetooth_agent.FetchCharacteristic(service, characteristic); - const GattCharacteristic gatt_characteristic = gatt_characteristic_holder.obj; - - const auto properties = gatt_characteristic.CharacteristicProperties(); - if ((properties & GattCharacteristicProperties::Read) == GattCharacteristicProperties::None) - { - result(FlutterError("NotSupported", "Characteristic does not support read")); - return; - } - - gatt_characteristic.ReadValueAsync(BluetoothCacheMode::Uncached).Completed( - [&, result](IAsyncOperation const &sender, AsyncStatus const args) - { - const auto read_value_result = sender.GetResults(); - auto error = gatt_communication_status_to_error(read_value_result.Status()); - if (error.has_value()) - { - result(FlutterError("Failed", error.value())); - } - else - { - result(to_bytevc(read_value_result.Value())); - } - }); - } - catch (const FlutterError& err) - { - return result(err); - } - catch (...) - { - std::cout << "ReadValueLog: Unknown error" << std::endl; - return result(FlutterError("Failed","Unknown error")); - } - } - - void UniversalBlePlugin::WriteValue( - const std::string& device_id, - const std::string& service, - const std::string& characteristic, - const std::vector& value, - int64_t ble_output_property, - std::function reply)> result) - { - try - { - const auto it = connected_devices_.find(str_to_mac_address(device_id)); - if (it == connected_devices_.end()) - { - result(FlutterError("IllegalArgument", "Unknown devicesId:" + device_id)); - return; - } - auto bluetooth_agent = *it->second; - const GattCharacteristicObject& gatt_characteristic_holder = bluetooth_agent.FetchCharacteristic( - service, characteristic); - const GattCharacteristic gatt_characteristic = gatt_characteristic_holder.obj; - const auto properties = gatt_characteristic.CharacteristicProperties(); - - auto write_option = GattWriteOption::WriteWithResponse; - if (ble_output_property == static_cast(BleOutputProperty::withoutResponse)) - { - write_option = GattWriteOption::WriteWithoutResponse; - if ((properties & GattCharacteristicProperties::WriteWithoutResponse) == GattCharacteristicProperties::None) - { - result(FlutterError("NotSupported", "Characteristic does not support WriteWithoutResponse")); - return; - } - } - else - { - if ((properties & GattCharacteristicProperties::Write) == GattCharacteristicProperties::None) - { - result(FlutterError("NotSupported", "Characteristic does not support Write")); - return; - } - } - - gatt_characteristic.WriteValueAsync(from_bytevc(value), write_option).Completed( - [&, result](IAsyncOperation const &sender, AsyncStatus const args) - { - if (args == AsyncStatus::Error) - { - result(FlutterError("Failed", "Encountered an error.")); - return; - } - - const auto error = gatt_communication_status_to_error(sender.GetResults()); - if (error.has_value()) - { - result(FlutterError("Failed", error.value())); - } - else - { - result(std::nullopt); - } - }); - } - catch (const FlutterError& err) - { - result(err); - } - catch (...) - { - std::cout << "WriteValue: Unknown error" << std::endl; - result(FlutterError("Failed", "Unknown error")); - } - } - - void UniversalBlePlugin::RequestMtu( - const std::string &device_id, - int64_t expected_mtu, - std::function reply)> result) - { - try - { - const auto it = connected_devices_.find(str_to_mac_address(device_id)); - if (it == connected_devices_.end()) - { - result(FlutterError("IllegalArgument", "Unknown devicesId:" + device_id)); - return; - } - const auto bluetooth_agent = *it->second; - GattSession::FromDeviceIdAsync(bluetooth_agent.device.BluetoothDeviceId()).Completed( - [&, result](IAsyncOperation const& sender, AsyncStatus const args) - { - if (args == AsyncStatus::Error) - { - result(FlutterError("Failed", "Encountered an error.")); - return; - } - - result((int64_t)sender.GetResults().MaxPduSize()); - }); - } - catch (const FlutterError &err) - { - result(err); - } - } - - void UniversalBlePlugin::IsPaired( - const std::string &device_id, - std::function reply)> result) - { - IsPairedAsync(device_id, result); - } - - void UniversalBlePlugin::Pair( - const std::string& device_id, - std::function reply)> result) - { - try - { - if (is_windows11_or_greater()) - { - PairAsync(device_id, result); - } - else - { - CustomPairAsync(device_id, result); - } - } - catch (const FlutterError& err) - { - result(err); - } - } - - std::optional UniversalBlePlugin::UnPair(const std::string& device_id) - { - try - { - const auto device = async_get(BluetoothLEDevice::FromBluetoothAddressAsync(str_to_mac_address(device_id))); - if (device == nullptr) - { - return FlutterError("IllegalArgument", "Unknown devicesId:" + device_id); - } - const auto device_information = device.DeviceInformation(); - - if (!device_information.Pairing().IsPaired()) - { - return FlutterError("NotPaired", "Device is not paired"); - } - - const auto device_unpairing_result = async_get(device_information.Pairing().UnpairAsync()); - - const auto error = device_unpairing_result_to_string(device_unpairing_result.Status()); - - if (error.has_value()) - { - return FlutterError("Failed", error.value()); - } - return std::nullopt; - } - catch (const FlutterError& err) - { - return err; - } - } - - void UniversalBlePlugin::GetSystemDevices( - const flutter::EncodableList &with_services, - std::function reply)> result) - { - auto with_services_str = std::vector(); - for (const auto &item : with_services) - { - auto service_id = std::get(item); - with_services_str.push_back(service_id); - } - GetSystemDevicesAsync(with_services_str, result); - } - - /// Helper Methods - - fire_and_forget UniversalBlePlugin::InitializeAsync() - { - const auto radios = co_await Radio::GetRadiosAsync(); - for (auto &&radio : radios) - { - if (radio.Kind() == RadioKind::Bluetooth) - { - bluetooth_radio_ = radio; - radio_state_changed_revoker_ = bluetooth_radio_.StateChanged(auto_revoke, {this, &UniversalBlePlugin::RadioStateChanged}); - RadioStateChanged(bluetooth_radio_, nullptr); - break; - } - } - if (!bluetooth_radio_) - { - std::cout << "Bluetooth is not available" << std::endl; - ui_thread_handler_.Post([] - { callback_channel->OnAvailabilityChanged(static_cast(AvailabilityState::unsupported), SuccessCallback, ErrorCallback); }); - } - initialized_ = true; - } - - fire_and_forget UniversalBlePlugin::PairAsync( - const std::string& device_id, - const std::function reply)> result) - { - try - { - std::cout << "Trying to pair" << std::endl; - - const auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(str_to_mac_address(device_id)); - if (device == nullptr) - { - result(FlutterError("IllegalArgument", "Unknown devicesId:" + device_id)); - co_return; - } - - std::cout << "Got device" << std::endl; - - const auto device_information = device.DeviceInformation(); - if (device_information.Pairing().IsPaired()) - result(true); - else if (!device_information.Pairing().CanPair()) - result(FlutterError("NotPairable", "Device is not pairable")); - else - { - const auto pair_result = co_await device_information.Pairing().PairAsync(); - std::cout << "PairLog: Received pairing status" << std::endl; - bool is_paired = pair_result.Status() == DevicePairingResultStatus::Paired; - result(is_paired); - - const std::string* error_msg = nullptr; - const auto error_str = parse_pairing_fail_error(pair_result); - if (error_str.has_value()) - { - error_msg = &error_str.value(); - } - ui_thread_handler_.Post([device_id, is_paired, error_msg] - { callback_channel->OnPairStateChange(device_id, is_paired, error_msg, SuccessCallback, ErrorCallback); }); - } - } - catch (...) - { - result(false); - std::cout << "PairLog: Unknown error" << std::endl; - } - } - - fire_and_forget UniversalBlePlugin::CustomPairAsync( - const std::string& device_id, - const std::function reply)> result) - { - try - { - const auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(str_to_mac_address(device_id)); - if (device == nullptr) - { - result(FlutterError("IllegalArgument", "Unknown devicesId:" + device_id)); - co_return; - } - const auto device_information = device.DeviceInformation(); - if (device_information.Pairing().IsPaired()) - result(true); - else if (!device_information.Pairing().CanPair()) - result(FlutterError("NotPairable", "Device is not pairable")); - else - { - const auto custom_pairing = device_information.Pairing().Custom(); - const event_token token = custom_pairing.PairingRequested({this, &UniversalBlePlugin::PairingRequestedHandler}); - std::cout << "PairLog: Trying to pair" << std::endl; - const DevicePairingProtectionLevel protection_level = device_information.Pairing().ProtectionLevel(); - // DevicePairingKinds => None, ConfirmOnly, DisplayPin, ProvidePin, ConfirmPinMatch, ProvidePasswordCredential - const auto pair_result = co_await custom_pairing.PairAsync(DevicePairingKinds::ConfirmOnly | DevicePairingKinds::ProvidePin, protection_level); - std::cout << "PairLog: Got Pair Result" << std::endl; - const DevicePairingResultStatus status = pair_result.Status(); - custom_pairing.PairingRequested(token); - bool is_paired = status == DevicePairingResultStatus::Paired; - result(is_paired); - - const std::string* error_msg = nullptr; - const auto error_str = parse_pairing_fail_error(pair_result); - if (error_str.has_value()) - { - error_msg = &error_str.value(); - } - ui_thread_handler_.Post([device_id, is_paired, error_msg] - { callback_channel->OnPairStateChange(device_id, is_paired, error_msg, SuccessCallback, ErrorCallback); }); - } - } - catch (...) - { - result(false); - std::cout << "PairLog Error: Pairing Failed" << std::endl; - } - } - - // ReSharper disable once CppMemberFunctionMayBeStatic - void UniversalBlePlugin::PairingRequestedHandler(DeviceInformationCustomPairing sender, const DevicePairingRequestedEventArgs& event_args) - { - std::cout << "PairLog: Got PairingRequest" << std::endl; - const DevicePairingKinds kind = event_args.PairingKind(); - if (kind != DevicePairingKinds::ProvidePin) - { - event_args.Accept(); - return; - } - - std::cout << "PairLog: Trying to get pin from user" << std::endl; - const hstring pin = askForPairingPin(); - std::wcout << "PairLog: Got Pin: " << pin.c_str() << std::endl; - event_args.Accept(pin); - } - - // Send device to callback channel - // if device is already discovered in deviceWatcher then merge the scan result - void UniversalBlePlugin::PushUniversalScanResult(UniversalBleScanResult scan_result, const bool is_connectable) - { - const std::optional it = scan_results_.get(scan_result.device_id()); - if (it.has_value()) - { - const UniversalBleScanResult ¤t_scan_result = it.value(); - bool should_update = false; - - // Check if current scanResult name is longer than the received scanResult name - if (scan_result.name() != nullptr && !scan_result.name()->empty() && current_scan_result.name() != nullptr && !current_scan_result.name()->empty()) - { - if (current_scan_result.name()->size() > scan_result.name()->size()) - { - scan_result.set_name(*current_scan_result.name()); - } - } - - if ((scan_result.name() == nullptr || scan_result.name()->empty()) && (current_scan_result.name() != nullptr && !current_scan_result.name()->empty())) - { - scan_result.set_name(*current_scan_result.name()); - should_update = true; - } - - if (scan_result.is_paired() == nullptr && current_scan_result.is_paired() != nullptr) - { - scan_result.set_is_paired(current_scan_result.is_paired()); - should_update = true; - } - - if ((scan_result.manufacturer_data_list() == nullptr || scan_result.manufacturer_data_list()->empty()) && current_scan_result.manufacturer_data_list() != nullptr) - { - scan_result.set_manufacturer_data_list(current_scan_result.manufacturer_data_list()); - should_update = true; - } - - if (scan_result.services() == nullptr && current_scan_result.services() != nullptr) - { - scan_result.set_services(current_scan_result.services()); - should_update = true; - } - - // if nothing to update then return - if (!should_update) - { - return; - } - } - - // Update cache - scan_results_.insert_or_assign(scan_result.device_id(), scan_result); - - // Filter final result before sending to Flutter - if (is_connectable && filterDevice(scan_result)) - { - ui_thread_handler_.Post([scan_result] - { callback_channel->OnScanResult(scan_result, SuccessCallback, ErrorCallback); }); - } - } - - void UniversalBlePlugin::SetupDeviceWatcher() - { - if (device_watcher_ != nullptr) - return; - - device_watcher_ = DeviceInformation::CreateWatcher( - L"(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")", - { - device_address_key, - is_connected_key, - is_paired_key, - is_present_key, - is_connectable_key, - signal_strength_key, - }, - DeviceInformationKind::AssociationEndpoint); - - /// Device Added from DeviceWatcher - device_watcher_added_token_ = device_watcher_.Added([this](DeviceWatcher sender, const DeviceInformation& device_info) - { - const std::string device_id = to_string(device_info.Id()); - device_watcher_devices_.insert_or_assign(device_id, device_info); - OnDeviceInfoReceived(device_info); - // On Device Added - }); - - // Update only if device is already discovered in deviceWatcher.Added - device_watcher_updated_token_ = device_watcher_.Updated([this](DeviceWatcher sender, const DeviceInformationUpdate& device_info_update) - { - const std::string device_id = to_string(device_info_update.Id()); - const auto it = device_watcher_devices_.get(device_id); - if (it.has_value()) - { - const auto value = it.value(); - value.Update(device_info_update); - device_watcher_devices_.insert_or_assign(device_id, value); - OnDeviceInfoReceived(value); - } - // On Device Updated - }); - - device_watcher_removed_token_ = device_watcher_.Removed([this](DeviceWatcher sender, const DeviceInformationUpdate& args) - { - const std::string device_id = to_string(args.Id()); - device_watcher_devices_.remove(device_id); - // On Device Removed - }); - - device_watcher_enumeration_completed_token_ = device_watcher_.EnumerationCompleted([this](DeviceWatcher sender, IInspectable args) - { - std::cout << "DeviceWatcherEvent: EnumerationCompleted" << std::endl; - DisposeDeviceWatcher(); - // EnumerationCompleted - }); - - device_watcher_stopped_token_ = device_watcher_.Stopped([this](DeviceWatcher sender, IInspectable args) - { - // std::cout << "DeviceWatcherEvent: Stopped" << std::endl; - // disposeDeviceWatcher(); - // DeviceWatcher Stopped - }); - } - - void UniversalBlePlugin::DisposeDeviceWatcher() - { - if (device_watcher_ != nullptr) - { - device_watcher_.Added(device_watcher_added_token_); - device_watcher_.Updated(device_watcher_updated_token_); - device_watcher_.Removed(device_watcher_removed_token_); - device_watcher_.EnumerationCompleted(device_watcher_enumeration_completed_token_); - device_watcher_.Stopped(device_watcher_stopped_token_); - const auto status = device_watcher_.Status(); - // std::cout << "DisposingDeviceWatcher, CurrentState: " << DeviceWatcherStatusToString(status) << std::endl; - if (status == DeviceWatcherStatus::Started) - { - device_watcher_.Stop(); - } - device_watcher_ = nullptr; - device_watcher_devices_.clear(); - } - } - - void UniversalBlePlugin::OnDeviceInfoReceived(const DeviceInformation& device_info) - { - const auto properties = device_info.Properties(); - - // Avoid devices if not connectable or if deviceAddressKey is not present - if (!(properties.HasKey(is_connectable_key) && (properties.Lookup(is_connectable_key).as()).GetBoolean()) || !properties.HasKey(device_address_key)) - return; - - const auto bluetooth_address_property_value = properties.Lookup(device_address_key).as(); - const std::string device_address = to_string(bluetooth_address_property_value.GetString()); - - // Update device info if already discovered in advertisementWatcher - if (scan_results_.get(device_address).has_value()) - { - bool is_paired = device_info.Pairing().IsPaired(); - if (properties.HasKey(is_paired_key)) - { - const auto is_paired_property_value = properties.Lookup(is_paired_key).as(); - is_paired = is_paired_property_value.GetBoolean(); - } - - UniversalBleScanResult universal_scan_result(device_address); - universal_scan_result.set_is_paired(is_paired); - - if (!device_info.Name().empty()) - universal_scan_result.set_name(to_string(device_info.Name())); - - if (properties.HasKey(signal_strength_key)) - { - const auto rssi_property_value = properties.Lookup(signal_strength_key).as(); - const int16_t rssi = rssi_property_value.GetInt16(); - universal_scan_result.set_rssi(rssi); - } - - PushUniversalScanResult(universal_scan_result, true); - } - } - - /// Advertisement received from advertisementWatcher - void UniversalBlePlugin::BluetoothLeWatcherReceived(const BluetoothLEAdvertisementWatcher&, const BluetoothLEAdvertisementReceivedEventArgs& args) - { - try - { - auto device_id = mac_address_to_str(args.BluetoothAddress()); - auto universal_scan_result = UniversalBleScanResult(device_id); - std::string name = to_string(args.Advertisement().LocalName()); - - auto manufacturer_data_encodable_list = flutter::EncodableList(); - if (args.Advertisement() != nullptr) - { - for (BluetoothLEManufacturerData msd : args.Advertisement().ManufacturerData()) - { - auto universal_manufacturer_data = UniversalManufacturerData(static_cast(msd.CompanyId()), to_bytevc(msd.Data())); - manufacturer_data_encodable_list.push_back(flutter::CustomEncodableValue(universal_manufacturer_data)); - } - } - - auto data_section = args.Advertisement().DataSections(); - for (auto &&data : data_section) - { - auto data_bytes = to_bytevc(data.Data()); - // Use CompleteName from dataType if localName is empty - if (name.empty() && data.DataType() == static_cast(AdvertisementSectionType::CompleteLocalName)) - { - name = std::string(data_bytes.begin(), data_bytes.end()); - } - // Use ShortenedLocalName from dataType if localName is empty - else if (name.empty() && data.DataType() == static_cast(AdvertisementSectionType::ShortenedLocalName)) - { - name = std::string(data_bytes.begin(), data_bytes.end()); - } - } - - if (!name.empty()) - { - universal_scan_result.set_name(name); - } - - if (!manufacturer_data_encodable_list.empty()) - { - universal_scan_result.set_manufacturer_data_list(manufacturer_data_encodable_list); - } - - universal_scan_result.set_rssi(args.RawSignalStrengthInDBm()); - - // Add services - auto services = flutter::EncodableList(); - for (auto &&uuid : args.Advertisement().ServiceUuids()) - services.push_back(guid_to_uuid(uuid)); - universal_scan_result.set_services(services); - - // check if this device already discovered in deviceWatcher - auto it = device_watcher_devices_.get(device_id); - if (it.has_value()) - { - auto &device_info = it.value(); - auto properties = device_info.Properties(); - - // Update Paired Status - bool is_paired = device_info.Pairing().IsPaired(); - if (properties.HasKey(is_paired_key)) - is_paired = (properties.Lookup(is_paired_key).as()).GetBoolean(); - universal_scan_result.set_is_paired(is_paired); - - // Update Name - if (name.empty() && !device_info.Name().empty()) - universal_scan_result.set_name(to_string(device_info.Name())); - } - - // Filter Device - PushUniversalScanResult(universal_scan_result, args.IsConnectable()); - } - catch (...) - { - std::cout << "ScanResultErrorInParsing" << std::endl; - } - } - - void UniversalBlePlugin::RadioStateChanged(const Radio& sender, const IInspectable&) - { - const auto radio_state = !sender ? RadioState::Disabled : sender.State(); - if (old_radio_state_ == radio_state) - { - return; - } - old_radio_state_ = radio_state; - auto state = get_availability_state_from_radio(radio_state); - - ui_thread_handler_.Post([state] - { callback_channel->OnAvailabilityChanged(static_cast(state), SuccessCallback, ErrorCallback); }); - } - - - fire_and_forget UniversalBlePlugin::ConnectAsync(uint64_t bluetooth_address) - { - BluetoothLEDevice device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(bluetooth_address); - if (!device) - { - std::cout << "ConnectionLog: ConnectionFailed: Failed to get device" << std::endl; - ui_thread_handler_.Post([bluetooth_address] - { callback_channel->OnConnectionChanged(mac_address_to_str(bluetooth_address), false, new std::string("Failed to get device"), SuccessCallback, ErrorCallback); }); - - co_return; - } - std::cout << "ConnectionLog: Device found" << std::endl; - auto services_result = co_await device.GetGattServicesAsync((BluetoothCacheMode::Uncached)); - auto services_result_error = gatt_communication_status_to_error(services_result.Status()); - if (services_result_error.has_value()) - { - std::cout << "ConnectionFailed: Failed to get services: " << services_result_error.value() << std::endl; - ui_thread_handler_.Post([bluetooth_address, services_result_error] - { callback_channel->OnConnectionChanged(mac_address_to_str(bluetooth_address), false, &services_result_error.value(), SuccessCallback, ErrorCallback); }); - co_return; - } - - std::cout << "ConnectionLog: Services discovered" << std::endl; - std::unordered_map gatt_map; - auto gatt_services = services_result.Services(); - for (GattDeviceService &&service : gatt_services) - { - GattServiceObject gatt_service; - gatt_service.obj = service; - std::string service_uuid = guid_to_uuid(service.Uuid()); - auto characteristics_result = co_await service.GetCharacteristicsAsync(BluetoothCacheMode::Uncached); - auto characteristics_result_error = gatt_communication_status_to_error(characteristics_result.Status()); - - if (characteristics_result_error.has_value()) - { - std::cout << "Failed to get characteristics for service: " << service_uuid << ", With Status: " << characteristics_result_error.value() << std::endl; - continue; - // PostConnectionUpdate(bluetoothAddress, ConnectionState::disconnected); - // co_return; - } - auto gatt_characteristics = characteristics_result.Characteristics(); - for (GattCharacteristic &&characteristic : gatt_characteristics) - { - GattCharacteristicObject gatt_characteristic; - gatt_characteristic.obj = characteristic; - gatt_characteristic.subscription_token = std::nullopt; - std::string characteristic_uuid = guid_to_uuid(characteristic.Uuid()); - gatt_service.characteristics.insert_or_assign(characteristic_uuid, std::move(gatt_characteristic)); - } - gatt_map.insert_or_assign(service_uuid, std::move(gatt_service)); - } - - event_token connection_status_changed_token = device.ConnectionStatusChanged({this, &UniversalBlePlugin::BluetoothLeDeviceConnectionStatusChanged}); - auto device_agent = std::make_unique(device, connection_status_changed_token, gatt_map); - auto pair = std::make_pair(bluetooth_address, std::move(device_agent)); - connected_devices_.insert(std::move(pair)); - std::cout << "ConnectionLog: Connected" << std::endl; - ui_thread_handler_.Post([bluetooth_address] - { callback_channel->OnConnectionChanged(mac_address_to_str(bluetooth_address), true, nullptr, SuccessCallback, ErrorCallback); }); - } - - void UniversalBlePlugin::BluetoothLeDeviceConnectionStatusChanged(const BluetoothLEDevice& sender, const IInspectable& - ) - { - if (sender.ConnectionStatus() == BluetoothConnectionStatus::Disconnected) - { - CleanConnection(sender.BluetoothAddress()); - auto bluetooth_address = sender.BluetoothAddress(); - ui_thread_handler_.Post([bluetooth_address] - { callback_channel->OnConnectionChanged(mac_address_to_str(bluetooth_address), false, nullptr, SuccessCallback, ErrorCallback); }); - } - } - - void UniversalBlePlugin::CleanConnection(const uint64_t bluetooth_address) - { - const auto node = connected_devices_.extract(bluetooth_address); - if (!node.empty()) - { - const auto device_agent = std::move(node.mapped()); - device_agent->device.ConnectionStatusChanged(device_agent->connection_status_changed_token); - // Clean up all characteristics tokens - for (auto& [service_id, service] : device_agent->gatt_map) - { - for (auto& [char_id, characteristic] : service.characteristics) - { - if (characteristic.subscription_token.has_value()) - { - characteristic.obj.ValueChanged(characteristic.subscription_token.value()); - characteristic.subscription_token = std::nullopt; - } - } - } - device_agent->gatt_map.clear(); - } - } - - fire_and_forget UniversalBlePlugin::GetSystemDevicesAsync( - std::vector with_services, - std::function reply)> result) - { - try - { - auto selector = BluetoothLEDevice::GetDeviceSelectorFromConnectionStatus(BluetoothConnectionStatus::Connected); - DeviceInformationCollection devices = co_await DeviceInformation::FindAllAsync(selector); - auto results = flutter::EncodableList(); - for (auto &&device_info : devices) - { - try - { - BluetoothLEDevice device = co_await BluetoothLEDevice::FromIdAsync(device_info.Id()); - auto device_id = mac_address_to_str(device.BluetoothAddress()); - // Filter by services - if (!with_services.empty()) - { - auto service_result = co_await device.GetGattServicesAsync(BluetoothCacheMode::Cached); - if (service_result.Status() == GattCommunicationStatus::Success) - { - bool has_service = false; - for (auto service : service_result.Services()) - { - std::string service_uuid = to_uuidstr(service.Uuid()); - if (std::find(with_services.begin(), with_services.end(), service_uuid) != with_services.end()) - { - has_service = true; - break; - } - } - if (!has_service) - continue; - } - } - // Add to results, if pass all filters - auto universal_scan_result = UniversalBleScanResult(device_id); - universal_scan_result.set_name(to_string(device_info.Name())); - universal_scan_result.set_is_paired(device_info.Pairing().IsPaired()); - results.push_back(flutter::CustomEncodableValue(universal_scan_result)); - } - catch (...) - { - } - } - result(results); - } - catch (const hresult_error &err) - { - int error_code = err.code(); - std::cout << "GetConnectedDeviceLog: " << to_string(err.message()) << " ErrorCode: " << std::to_string(error_code) << std::endl; - result(FlutterError(std::to_string(error_code), to_string(err.message()))); - } - catch (...) - { - std::cout << "Unknown error GetSystemDevicesAsyncAsync" << std::endl; - result(FlutterError("Failed", "Unknown error")); - } - } - - void UniversalBlePlugin::DiscoverServicesAsync(BluetoothDeviceAgent &bluetooth_device_agent, const std::function reply)>& result) - { - try - { - auto universal_services = flutter::EncodableList(); - for (auto & [service_id, service] : bluetooth_device_agent.gatt_map) - { - flutter::EncodableList universal_characteristics; - for (auto [char_id, characteristic] : service.characteristics) - { - auto& c = characteristic.obj; - - const auto properties_value = c.CharacteristicProperties(); - auto properties = properties_to_flutter_encodable(properties_value); - - universal_characteristics.push_back( - flutter::CustomEncodableValue(UniversalBleCharacteristic(to_uuidstr(c.Uuid()), properties))); - } - - auto universal_ble_service = UniversalBleService(to_uuidstr(service.obj.Uuid())); - universal_ble_service.set_characteristics(universal_characteristics); - universal_services.push_back(flutter::CustomEncodableValue(universal_ble_service)); - } - result(universal_services); - } - catch (...) - { - result(FlutterError("Failed", "Unknown error")); - std::cout << "DiscoverServiceError: Unknown error" << '\n'; - } - } - - fire_and_forget UniversalBlePlugin::IsPairedAsync( - const std::string& device_id, - const std::function reply)> result) - { - try - { - const auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(str_to_mac_address(device_id)); - if (device == nullptr) - { - result(FlutterError("IllegalArgument", "Unknown devicesId:" + device_id)); - co_return; - } - const bool is_paired = device.DeviceInformation().Pairing().IsPaired(); - result(is_paired); - } - catch (...) - { - std::cout << "IsPairedAsync: Error " << std::endl; - result(FlutterError("Failed", "Unknown error")); - } - } - - fire_and_forget UniversalBlePlugin::SetNotifiableAsync(const std::string& device_id, - const std::string& service, - const std::string& characteristic, - const int64_t ble_input_property, - const std::function reply)> result) - { - try - { - const auto it = connected_devices_.find(str_to_mac_address(device_id)); - if (it == connected_devices_.end()) - { - result(FlutterError("IllegalArgument", "Unknown devicesId:" + device_id)); - co_return; - } - - auto& gatt_char = it->second->FetchCharacteristic(service, characteristic); - - const auto properties = gatt_char.obj.CharacteristicProperties(); - auto descriptor_value = GattClientCharacteristicConfigurationDescriptorValue::None; - if (ble_input_property == static_cast(BleInputProperty::notification)) - { - descriptor_value = GattClientCharacteristicConfigurationDescriptorValue::Notify; - if ((properties & GattCharacteristicProperties::Notify) == GattCharacteristicProperties::None) - { - result(FlutterError("NotSupported", "Characteristic does not support notify")); - co_return; - } - } - else if (ble_input_property == static_cast(BleInputProperty::indication)) - { - descriptor_value = GattClientCharacteristicConfigurationDescriptorValue::Indicate; - if ((properties & GattCharacteristicProperties::Indicate) == GattCharacteristicProperties::None) - { - result(FlutterError("NotSupported", "Characteristic does not support indicate")); - co_return; - } - } - - const auto gatt_characteristic = gatt_char.obj; - const auto uuid = to_uuidstr(gatt_characteristic.Uuid()); - - // Write to the descriptor. - const auto status = co_await gatt_characteristic.WriteClientCharacteristicConfigurationDescriptorAsync( - descriptor_value); - const auto error = gatt_communication_status_to_error(status); - if (error.has_value()) - { - result(FlutterError("Failed", error.value())); - co_return; - } - - // Register/UnRegister handler for the ValueChanged event. - if (descriptor_value == GattClientCharacteristicConfigurationDescriptorValue::None) - { - if (gatt_char.subscription_token.has_value()) - { - gatt_characteristic.ValueChanged(gatt_char.subscription_token.value()); - gatt_char.subscription_token = std::nullopt; - std::cout << "Unsubscribed " << to_uuidstr(gatt_characteristic.Uuid()) << std::endl; - } - } - else - { - // If a notification for the given characteristic is already in progress, swap the callbacks. - if (gatt_char.subscription_token.has_value()) - { - std::cout << "A notification for the given characteristic is already in progress. Swapping callbacks." << std::endl; - gatt_characteristic.ValueChanged(gatt_char.subscription_token.value()); - gatt_char.subscription_token = std::nullopt; - } - - gatt_char.subscription_token = std::make_optional(gatt_characteristic.ValueChanged({ - this, &UniversalBlePlugin::GattCharacteristicValueChanged - })); - } - - result(std::nullopt); - } - catch (const FlutterError& err) - { - result(err); - } - catch (...) - { - std::cout << "SetNotifiableLog: Unknown error" << std::endl; - result(FlutterError("Failed", "Unknown error")); - } - } - - void UniversalBlePlugin::GattCharacteristicValueChanged(const GattCharacteristic& sender, const GattValueChangedEventArgs& args) - { - auto uuid = to_uuidstr(sender.Uuid()); - auto bytes = to_bytevc(args.CharacteristicValue()); - ui_thread_handler_.Post([sender, uuid, bytes] - { callback_channel->OnValueChanged(mac_address_to_str(sender.Service().Device().BluetoothAddress()), uuid, bytes, SuccessCallback, ErrorCallback); }); - } - -} // namespace universal_ble \ No newline at end of file diff --git a/universal_ble/windows/src/universal_ble_plugin.h b/universal_ble/windows/src/universal_ble_plugin.h deleted file mode 100644 index abeffed..0000000 --- a/universal_ble/windows/src/universal_ble_plugin.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_H_ -#define FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_H_ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "helper/utils.h" -#include "helper/universal_enum.h" -#include "helper/universal_ble_base.h" -#include "generated/universal_ble.g.h" -#include "ui_thread_handler.hpp" -#include "universal_ble_thread_safe.h" - -namespace universal_ble -{ - struct GattCharacteristicObject - { - GattCharacteristic obj = nullptr; - std::optional subscription_token; - }; - - struct GattServiceObject - { - GattDeviceService obj = nullptr; - std::unordered_map characteristics; - }; - - struct BluetoothDeviceAgent - { - BluetoothLEDevice device; - event_token connection_status_changed_token; - std::unordered_map gatt_map; - - BluetoothDeviceAgent(const BluetoothLEDevice &device, const event_token connection_status_changed_token, - const std::unordered_map &gatt_map) - : device(device), - connection_status_changed_token(connection_status_changed_token), - gatt_map(gatt_map) - { - } - - ~BluetoothDeviceAgent() - { - device = nullptr; - } - - GattCharacteristicObject &FetchCharacteristic(const std::string &service_uuid, - const std::string &characteristic_uuid) - { - if (gatt_map.count(service_uuid) == 0) - { - throw FlutterError("IllegalArgument", "Service not found"); - } - if (gatt_map[service_uuid].characteristics.count(characteristic_uuid) == 0) - { - throw FlutterError("IllegalArgument", "Characteristic not found"); - } - return gatt_map[service_uuid].characteristics.at(characteristic_uuid); - } - }; - - class UniversalBlePlugin : public flutter::Plugin, public UniversalBlePlatformChannel - { - public: - static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); - - UniversalBlePlugin(flutter::PluginRegistrarWindows *registrar); - - ~UniversalBlePlugin(); - - // Disallow copy and assign. - UniversalBlePlugin(const UniversalBlePlugin&) = delete; - UniversalBlePlugin& operator=(const UniversalBlePlugin&) = delete; - - - private: - static void SuccessCallback() {} - static void ErrorCallback(const FlutterError &error) - { - // Ignore ChannelConnection Error, This might occur because of HotReload - if (error.code() != "channel-error") - { - std::cout << "ErrorCode: " << error.code() << " Message: " << error.message() << std::endl; - } - } - - flutter::PluginRegistrarWindows *registrar_; - bool initialized_ = false; - - UniversalBleUiThreadHandler ui_thread_handler_; - Radio bluetooth_radio_{nullptr}; - RadioState old_radio_state_ = RadioState::Unknown; - BluetoothLEAdvertisementWatcher bluetooth_le_watcher_{nullptr}; - DeviceWatcher device_watcher_{nullptr}; - - std::unordered_map> connected_devices_{}; - ThreadSafeMap device_watcher_devices_{}; - ThreadSafeMap scan_results_{}; - - event_token bluetooth_le_watcher_received_token_; - event_token device_watcher_added_token_; - event_token device_watcher_updated_token_; - event_token device_watcher_removed_token_; - event_token device_watcher_enumeration_completed_token_; - event_token device_watcher_stopped_token_; - event_revoker radio_state_changed_revoker_; - - - fire_and_forget InitializeAsync(); - fire_and_forget ConnectAsync(uint64_t bluetooth_address); - fire_and_forget SetNotifiableAsync( - const std::string& device_id, - const std::string& service, - const std::string& characteristic, - int64_t ble_input_property, - std::function reply)> result); - fire_and_forget PairAsync(const std::string& device_id, std::function reply)> result); - fire_and_forget CustomPairAsync(const std::string& device_id, std::function reply)> result); - static fire_and_forget GetSystemDevicesAsync( - std::vector with_services, - std::function reply)> result); - static fire_and_forget IsPairedAsync(const std::string& device_id, std::function reply)> result); - - static void DiscoverServicesAsync(BluetoothDeviceAgent& bluetooth_device_agent, const std::function reply)>&); - void PairingRequestedHandler(DeviceInformationCustomPairing sender, const DevicePairingRequestedEventArgs& event_args); - - void RadioStateChanged(const Radio& sender, const IInspectable&); - void SetupDeviceWatcher(); - void DisposeDeviceWatcher(); - void PushUniversalScanResult(UniversalBleScanResult scan_result, bool is_connectable); - void BluetoothLeWatcherReceived(const BluetoothLEAdvertisementWatcher& sender, const - BluetoothLEAdvertisementReceivedEventArgs& args); - void OnDeviceInfoReceived(const DeviceInformation& device_info); - void BluetoothLeDeviceConnectionStatusChanged(const BluetoothLEDevice& sender, const IInspectable& args); - void CleanConnection(uint64_t bluetooth_address); - - - void GattCharacteristicValueChanged(const GattCharacteristic& sender, const GattValueChangedEventArgs& args); - - // UniversalBlePlatformChannel implementation. - void GetBluetoothAvailabilityState(std::function reply)> result) override; - void EnableBluetooth(std::function reply)> result) override; - void DisableBluetooth(std::function reply)> result) override; - ErrorOr GetConnectionState(const std::string &device_id) override; - std::optional StartScan(const UniversalScanFilter *filter) override; - std::optional StopScan() override; - std::optional Connect(const std::string &device_id) override; - std::optional Disconnect(const std::string &device_id) override; - void DiscoverServices( - const std::string &device_id, - std::function reply)> result) override; - void SetNotifiable( - const std::string &device_id, - const std::string &service, - const std::string &characteristic, - int64_t ble_input_property, - std::function reply)> result) override; - void ReadValue( - const std::string &device_id, - const std::string &service, - const std::string &characteristic, - std::function> reply)> result) override; - void WriteValue( - const std::string &device_id, - const std::string &service, - const std::string &characteristic, - const std::vector &value, - int64_t ble_output_property, - std::function reply)> result) override; - void RequestMtu( - const std::string &device_id, - int64_t expected_mtu, - std::function reply)> result) override; - void IsPaired( - const std::string &device_id, - std::function reply)> result) override; - void Pair( - const std::string &device_id, - std::function reply)> result) override; - std::optional UnPair(const std::string &device_id) override; - void GetSystemDevices( - const flutter::EncodableList &with_services, - std::function reply)> result) override; - }; - -} // namespace universal_ble - -#endif // FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_H_ \ No newline at end of file diff --git a/universal_ble/windows/src/universal_ble_thread_safe.h b/universal_ble/windows/src/universal_ble_thread_safe.h deleted file mode 100644 index e38a0cf..0000000 --- a/universal_ble/windows/src/universal_ble_thread_safe.h +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace universal_ble -{ - // Thread Safe Map wrapper - // Use only if you don't care about value ownership and it's OK to work with copies of the data. - template - class ThreadSafeMap - { - private: - std::unordered_map data; - mutable std::shared_mutex mutex; - - public: - void insert_or_assign(const Key &key, const Value &value) - { - std::unique_lock lock(mutex); - data.insert_or_assign(key, value); - } - - bool remove(const Key &key) - { - std::unique_lock lock(mutex); - return data.erase(key) > 0; - } - - std::optional get(const Key &key) const - { - std::shared_lock lock(mutex); - auto it = data.find(key); - return (it != data.end()) ? std::optional(it->second) : std::nullopt; - } - - void clear() - { - std::unique_lock lock(mutex); - data.clear(); - } - - std::map get_snapshot() const - { - std::shared_lock lock(mutex); - return data; - } - }; - -} // namespace universal_ble diff --git a/universal_ble/windows/universal_ble_plugin_c_api.cpp b/universal_ble/windows/universal_ble_plugin_c_api.cpp deleted file mode 100644 index cb59edd..0000000 --- a/universal_ble/windows/universal_ble_plugin_c_api.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "include/universal_ble/universal_ble_plugin_c_api.h" - -#include - -#include "src/universal_ble_plugin.h" - -void UniversalBlePluginCApiRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar) -{ - universal_ble::UniversalBlePlugin::RegisterWithRegistrar( - flutter::PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar)); -}