Navideck / universal_ble

A cross-platform Android/iOS/macOS/Windows/Linux/Web Bluetooth Low Energy (BLE) plugin for Flutter
https://pub.dev/packages/universal_ble
Other
19 stars 2 forks source link

Implement ScanFilter #17

Closed rohitsangwan01 closed 2 months ago

rohitsangwan01 commented 2 months ago

User description

Implemented and Tested on


Type

enhancement, bug_fix


Description


Changes walkthrough

Relevant files
Enhancement
9 files
universal_ble.g.cpp
Implement Scan Filtering by Services on Windows                   

windows/src/generated/universal_ble.g.cpp
  • Added support for filtering scan results by services.
  • Implemented UniversalScanFilter class with with_services attribute.
  • Enhanced UniversalBleScanResult to include services in its encodable
    list.
  • +61/-4   
    universal_ble_plugin.cpp
    Apply Scan Filters in BLE Scanning                                             

    windows/src/universal_ble_plugin.cpp
  • Added ApplyScanFilter method to apply scan filters.
  • Modified StartScan to accept UniversalScanFilter as a parameter.
  • +31/-2   
    mock_universal_ble.dart
    Update Mock Universal BLE to Support Scan Filters               

    example/lib/data/mock_universal_ble.dart - Updated `startScan` method to accept `scanFilter` parameter.
    +4/-1     
    ble_scan_result.dart
    Add Services Attribute to BLE Scan Result Model                   

    lib/src/models/ble_scan_result.dart - Added `services` attribute to `BleScanResult` class.
    +2/-0     
    scan_filter.dart
    Introduce Scan Filter Model                                                           

    lib/src/models/scan_filter.dart - Introduced `ScanFilter` class with `withServices` attribute.
    +4/-0     
    universal_ble.dart
    Enhance Universal BLE Start Scan with Filter Support         

    lib/src/universal_ble.dart - Enhanced `startScan` to support `ScanFilter`.
    +6/-1     
    universal_ble_web.dart
    Apply Scan Filters for Web Platform                                           

    lib/src/universal_ble_web/universal_ble_web.dart - Updated `startScan` to apply scan filters for web platform.
    +24/-2   
    UniversalBlePlugin.kt
    Apply Scan Filters on Android Platform                                     

    android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt - Updated `startScan` to apply scan filters on Android.
    +21/-3   
    UniversalBlePlugin.swift
    Apply Scan Filters on iOS and macOS                                           

    darwin/Classes/UniversalBlePlugin.swift - Updated `startScan` to apply scan filters on iOS and macOS.
    +17/-3   

    โœจ PR-Agent usage: Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    codiumai-pr-agent[bot] commented 2 months ago

    PR Description updated to latest commit (https://github.com/Navideck/universal_ble/commit/8e9b567fad7b8c58946dcf5f3fdb290df67cf60c)

    codiumai-pr-agent[bot] commented 2 months ago

    PR Review

    (Review updated until commit https://github.com/Navideck/universal_ble/commit/eca821efd65a33274b7ad0fc13eee5213aab6ffb)

    โฑ๏ธ Estimated effort to review [1-5] 4, because the PR introduces a significant feature across multiple platforms, affecting the core functionality of BLE scanning with filters. It involves changes in the native code for Android, iOS/macOS, and Windows, as well as Dart code adjustments. Reviewing this PR requires a thorough understanding of BLE concepts, cross-platform development nuances, and the ability to assess the impact on existing functionalities.
    ๐Ÿงช Relevant tests No
    ๐Ÿ” Possible issues Possible Bug: The implementation of `validFullUUID` in `UniversalBleHelper.swift` and `UniversalBleHelper.kt` might not correctly handle UUIDs that are already in full form. It assumes all UUIDs are short forms and forcibly appends them to a base UUID, which could lead to incorrect UUIDs being used for scanning.
    Performance Concern: The method `startScan` in both Android and iOS/macOS platforms now involves additional processing to apply scan filters. This could introduce a delay in starting the scan, especially if the list of services to filter is large. It's crucial to assess the impact on the scanning start time and ensure it remains within acceptable limits.
    ๐Ÿ”’ Security concerns No
    Code feedback:
    relevant filedarwin/Classes/UniversalBleHelper.swift
    suggestion       Consider validating if the provided UUID is already in full form before appending it to the base UUID. This will prevent potential issues with incorrect UUIDs being used for scanning. [important]
    relevant linevar validFullUUID: String {

    relevant fileandroid/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt
    suggestion       Similar to the Swift implementation, ensure that the UUID conversion function checks if the UUID is already in full form to avoid incorrect UUID processing. [important]
    relevant linefun String.validFullUUID(): String {

    relevant filelib/src/universal_ble_web/universal_ble_web.dart
    suggestion       Implement a mechanism to measure the delay introduced by applying scan filters in the `startScan` method. If the delay is significant, consider optimizing the filter application process or providing feedback to the user about the scanning initiation. [medium]
    relevant lineFuture startScan({

    relevant filewindows/src/universal_ble_plugin.h
    suggestion       Ensure that the `ApplyScanFilter` method efficiently processes the list of services to filter without significantly impacting the performance of the BLE scan start operation. Consider benchmarking the method with a large number of services. [medium]
    relevant linevoid ApplyScanFilter(const UniversalScanFilter *filter, BluetoothLEAdvertisementWatcher &bluetoothWatcher);


    โœจ Review tool usage guide:
    **Overview:** The `review` tool scans the PR code changes, and generates a PR review. The tool can be triggered [automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) every time a new PR is opened, or can be invoked manually by commenting on any PR. When commenting, to edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L19) related to the review tool (`pr_reviewer` section), use the following template: ``` /review --pr_reviewer.some_config1=... --pr_reviewer.some_config2=... ``` With a [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#working-with-github-app), use the following template: ``` [pr_reviewer] some_config1=... some_config2=... ```
    Utilizing extra instructions
    The `review` tool can be configured with extra instructions, which can be used to guide the model to a feedback tailored to the needs of your project. Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter. Specify the relevant sub-tool, and the relevant aspects of the PR that you want to emphasize. Examples for extra instructions: ``` [pr_reviewer] # /review # extra_instructions=""" In the 'possible issues' section, emphasize the following: - Does the code logic cover relevant edge cases? - Is the code logic clear and easy to understand? - Is the code logic efficient? ... """ ``` Use triple quotes to write multi-line instructions. Use bullet points to make the instructions more readable.
    How to enable\disable automation
    - When you first install PR-Agent app, the [default mode](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) for the `review` tool is: ``` pr_commands = ["/review", ...] ``` meaning the `review` tool will run automatically on every PR, with the default configuration. Edit this field to enable/disable the tool, or to change the used configurations
    Auto-labels
    The `review` tool can auto-generate two specific types of labels for a PR: - a `possible security issue` label, that detects possible [security issues](https://github.com/Codium-ai/pr-agent/blob/tr/user_description/pr_agent/settings/pr_reviewer_prompts.toml#L136) (`enable_review_labels_security` flag) - a `Review effort [1-5]: x` label, where x is the estimated effort to review the PR (`enable_review_labels_effort` flag)
    Extra sub-tools
    The `review` tool provides a collection of possible feedbacks about a PR. It is recommended to review the [possible options](https://github.com/Codium-ai/pr-agent/blob/main/docs/REVIEW.md#enabledisable-features), and choose the ones relevant for your use case. Some of the feature that are disabled by default are quite useful, and should be considered for enabling. For example: `require_score_review`, `require_soc2_ticket`, and more.
    Auto-approve PRs
    By invoking: ``` /review auto_approve ``` The tool will automatically approve the PR, and add a comment with the approval. To ensure safety, the auto-approval feature is disabled by default. To enable auto-approval, you need to actively set in a pre-defined configuration file the following: ``` [pr_reviewer] enable_auto_approval = true ``` (this specific flag cannot be set with a command line argument, only in the configuration file, committed to the repository) You can also enable auto-approval only if the PR meets certain requirements, such as that the `estimated_review_effort` is equal or below a certain threshold, by adjusting the flag: ``` [pr_reviewer] maximal_review_effort = 5 ```
    More PR-Agent commands
    > To invoke the PR-Agent, add a comment using one of the following commands: > - **/review**: Request a review of your Pull Request. > - **/describe**: Update the PR title and description based on the contents of the PR. > - **/improve [--extended]**: Suggest code improvements. Extended mode provides a higher quality feedback. > - **/ask \**: Ask a question about the PR. > - **/update_changelog**: Update the changelog based on the PR's contents. > - **/add_docs** ๐Ÿ’Ž: Generate docstring for new components introduced in the PR. > - **/generate_labels** ๐Ÿ’Ž: Generate labels for the PR based on the PR's contents. > - **/analyze** ๐Ÿ’Ž: Automatically analyzes the PR, and presents changes walkthrough for each component. >See the [tools guide](https://github.com/Codium-ai/pr-agent/blob/main/docs/TOOLS_GUIDE.md) for more details. >To list the possible configuration parameters, add a **/config** comment.
    See the [review usage](https://github.com/Codium-ai/pr-agent/blob/main/docs/REVIEW.md) page for a comprehensive guide on using this tool.
    codiumai-pr-agent[bot] commented 2 months ago

    PR Code Suggestions

    CategorySuggestions                                                                                                                                                       
    Performance
    Improve efficiency by using move semantics for services in UniversalBleScanResult constructor. ___ **The UniversalBleScanResult constructor initializes services_ with a copy of the
    EncodableList pointed to by services. This is potentially inefficient if services points
    to a large EncodableList. Consider using move semantics if services is no longer needed
    after this point, or ensure that the cost of copying is acceptable in this context.** [windows/src/generated/universal_ble.g.cpp [50]](https://github.com/Navideck/universal_ble/pull/17/files#diff-92e69b3dc0c97a5367d2a46ee4a042924534973f5adbc808f2ba303168895f45R50-R50) ```diff -services_(services ? std::optional(*services) : std::nullopt) {} +services_(services ? std::optional(std::move(*services)) : std::nullopt) {} ```
    Optimize validFullUUID method by checking full UUID length first. ___ **The validFullUUID extension method for String can be optimized by directly checking for
    the full UUID length first, as it's the most common case, before handling shorter UUIDs.** [darwin/Classes/UniversalBleHelper.swift [144-156]](https://github.com/Navideck/universal_ble/pull/17/files#diff-64579e5454d2beef64b5056e1f9eea6e9f92006164a448fcd4207c126df2af48R144-R156) ```diff var validFullUUID: String { let uuidLength = self.count - if uuidLength == 4 || uuidLength == 8 { + if uuidLength == 36 { + return self + } else if uuidLength == 4 || uuidLength == 8 { let baseUuid = "00000000-0000-1000-8000-00805F9B34FB" let start = baseUuid.startIndex let range = baseUuid.index(start, offsetBy: 4-uuidLength)..
    Maintainability
    Simplify set_services method by removing the pointer overload. ___ **The method UniversalBleScanResult::set_services is overloaded with both a pointer and a
    reference to EncodableList. This can be confusing and error-prone. Consider using a single
    method that takes a reference, as it simplifies the interface and makes the ownership
    semantics clearer.** [windows/src/generated/universal_ble.g.cpp [130-135]](https://github.com/Navideck/universal_ble/pull/17/files#diff-92e69b3dc0c97a5367d2a46ee4a042924534973f5adbc808f2ba303168895f45R130-R135) ```diff -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; } ```
    Possible issue
    Add error handling for UUID conversion in ApplyScanFilter. ___ **The method UniversalBlePlugin::ApplyScanFilter directly modifies the
    BluetoothLEAdvertisementWatcher without checking if the uuid_to_guid conversion was
    successful. This could potentially add invalid UUIDs to the watcher. Consider adding error
    handling for the UUID conversion process.** [windows/src/universal_ble_plugin.cpp [132]](https://github.com/Navideck/universal_ble/pull/17/files#diff-c744a38517e9dcb9177126ffd1392b9decc2b53e55772d4270f4387a4f4c9357R132-R132) ```diff -bluetoothWatcher.AdvertisementFilter().Advertisement().ServiceUuids().Append(uuid_to_guid(uuid_str)); +auto guid = uuid_to_guid(uuid_str); +if (guid.has_value()) { + bluetoothWatcher.AdvertisementFilter().Advertisement().ServiceUuids().Append(guid.value()); +} else { + // Handle error: Invalid UUID string +} ```
    Ensure scanFilter is not null and not empty before applying in toRequestOptionsBuilder. ___ **The method WebRequestOptionsBuilder.toRequestOptionsBuilder introduces a new parameter
    scanFilter but does not handle the case when scanFilter is null. This could lead to
    unexpected behavior. Consider adding a null check for scanFilter before applying it.** [lib/src/models/web_request_options_builder.dart [37-38]](https://github.com/Navideck/universal_ble/pull/17/files#diff-8542fcd57539fbecbb68a21440dc79742e2090883121abafcd128082f6123819R37-R38) ```diff -if (scanFilter != null) _applyScanFilter(scanFilter); +if (scanFilter != null && scanFilter.withServices.isNotEmpty) { + _applyScanFilter(scanFilter); +} ```
    Add null safety checks in UniversalScanFilter.decode method. ___ **The UniversalScanFilter.decode method does not handle the case where the decoded list
    might be null, which could lead to a runtime error. Consider adding null safety checks or
    ensuring that the input to decode cannot be null.** [lib/src/universal_ble_pigeon/universal_ble.g.dart [146-147]](https://github.com/Navideck/universal_ble/pull/17/files#diff-23aeae5146301c4596bf4b4f71fb72e39877ee48c7135bec3fc9ae81b2d81b3eR146-R147) ```diff return UniversalScanFilter( - withServices: (result[0] as List?)!.cast(), + withServices: (result[0] as List?)?.cast() ?? [], ); ```
    Improve null safety by using non-nullable types for services. ___ **Ensure null safety by using non-nullable types for services in UniversalBleScanResult if
    the service list is always expected.** [android/src/main/kotlin/com/navideck/universal_ble/UniversalBle.g.kt [57]](https://github.com/Navideck/universal_ble/pull/17/files#diff-d6e68c26f4000d9fc6e49ecc16fe5da3071f5852ba7354c7dd6fee39ecfb931eR57-R57) ```diff -val services: List? = null +val services: List = emptyList() ```
    Add null check for Bluetooth scanner before starting scan. ___ **Consider checking for bluetoothManager.adapter.bluetoothLeScanner being null before
    calling startScan to avoid potential NullPointerException. You can throw a custom error or
    handle the null case gracefully.** [android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt [115-119]](https://github.com/Navideck/universal_ble/pull/17/files#diff-9bf8297311d93083e68b98b07fd87ec8038bf693833cef20b676ac88a4aa837eR115-R119) ```diff -bluetoothManager.adapter.bluetoothLeScanner?.startScan( - filter?.toScanFilters() ?: emptyList(), - settings, - scanCallback +bluetoothManager.adapter.bluetoothLeScanner?.let { + it.startScan( + filter?.toScanFilters() ?: emptyList(), + settings, + scanCallback + ) +} ?: throw FlutterError( + "BluetoothScannerUnavailable", + "Bluetooth scanner is not available", + null ) ```
    Enhancement
    Simplify initialization of RequestOptionsBuilder with null-aware operations. ___ **Consider initializing RequestOptionsBuilder requestFilterBuilder with a null-aware
    operation to simplify the code.** [lib/src/universal_ble_web/universal_ble_web.dart [115-122]](https://github.com/Navideck/universal_ble/pull/17/files#diff-dc72e700f7c098e3f4e71b5d1f38c8514d3007af606d0fd15b1e5f0ecbd580cdR115-R122) ```diff -RequestOptionsBuilder requestFilterBuilder; -if (webRequestOptions != null) { - requestFilterBuilder = webRequestOptions.toRequestOptionsBuilder( - scanFilter: scanFilter, - ); -} else { - requestFilterBuilder = scanFilter?.toRequestOptionsBuilder() ?? - RequestOptionsBuilder.acceptAllDevices(); -} +RequestOptionsBuilder requestFilterBuilder = webRequestOptions?.toRequestOptionsBuilder(scanFilter: scanFilter) ?? scanFilter?.toRequestOptionsBuilder() ?? RequestOptionsBuilder.acceptAllDevices(); ```
    Add validation for UUID format in validFullUUID function. ___ **The validFullUUID function does not handle UUIDs of incorrect lengths other than 4 or 8.
    Consider adding validation for the UUID format to ensure it's either a valid short UUID (4
    or 8 characters) or a valid full UUID (36 characters).** [android/src/main/kotlin/com/navideck/universal_ble/UniversalBleHelper.kt [67-73]](https://github.com/Navideck/universal_ble/pull/17/files#diff-07528325c9af8065d3fe07cc2436350a5db4dde75378b96e4801cdc7675b128aR67-R73) ```diff fun String.validFullUUID(): String { return when (this.count()) { 4 -> "0000$this-0000-1000-8000-00805F9B34FB" 8 -> "$this-0000-1000-8000-00805F9B34FB" - else -> this + 36 -> this + else -> throw IllegalArgumentException("Invalid UUID format: $this") } } ```
    Best practice
    Use final for immutable fields and improve UUID validation. ___ **Use final instead of late for immutable fields and validate the UUID format more robustly.** [lib/src/models/uuid.dart [4-5]](https://github.com/Navideck/universal_ble/pull/17/files#diff-d8d15ee961d7d80f761d0d83f468cd7eb843f2f35e5c66b98c51a603964cdde1R4-R5) ```diff -late String value; -late BlueZUUID _blueZUUID; +final String value; +final BlueZUUID _blueZUUID; ```
    Ensure immutability of ScanFilter instances by making withServices final. ___ **Make `withServices` a final field to ensure immutability of `ScanFilter` instances.** [lib/src/models/scan_filter.dart [2]](https://github.com/Navideck/universal_ble/pull/17/files#diff-3855acfe8c6c77715a45e6abbf2757d06d7bb8eb65c325745f7f40d8765d79a7R2-R2) ```diff -List withServices; +final List withServices; ```
    Use completion handler for error handling in startScan. ___ **Instead of throwing a FlutterError directly in the startScan method, consider using a
    completion handler to return errors to the Flutter side. This approach is more consistent
    with asynchronous error handling in Flutter plugins.** [darwin/Classes/UniversalBlePlugin.swift [59-73]](https://github.com/Navideck/universal_ble/pull/17/files#diff-87832239a271a17152d0bd5fd33a705cd1398bda21bfdfff19934f405c09965fR59-R73) ```diff -func startScan(filter: UniversalScanFilter?) throws { +func startScan(filter: UniversalScanFilter?, completion: @escaping (FlutterError?) -> Void) { ... - throw FlutterError(code: "IllegalArgument", message: "Invalid service UUID:\(service)", details: nil) + completion(FlutterError(code: "IllegalArgument", message: "Invalid service UUID:\(service)", details: nil)) ... } ```
    Bug
    Add null check to avoid potential null pointer exceptions. ___ **Check for null before calling toValidUUIDList() to avoid potential null pointer
    exceptions.** [lib/src/universal_ble_linux/universal_ble_linux.dart [65]](https://github.com/Navideck/universal_ble/pull/17/files#diff-bd61ea0530e3e409336cd7d8a6d93c00911618355a9bf99fd1cf3d92cb6a02d9R65-R65) ```diff -uuids: scanFilter?.withServices.toValidUUIDList(), +uuids: scanFilter?.withServices?.toValidUUIDList(), ```
    Add null check for filter in ApplyScanFilter. ___ **When applying a scan filter in ApplyScanFilter, ensure to handle the case where filter is
    nullptr to avoid dereferencing a null pointer. This can be done by checking if filter is
    not null before proceeding with applying the filter.** [windows/src/universal_ble_plugin.h [126]](https://github.com/Navideck/universal_ble/pull/17/files#diff-5e53d816e18b3a55d63090396aac40ab0c2159f0bf24d5ae5687d003c22c809fR126-R126) ```diff -void ApplyScanFilter(const UniversalScanFilter *filter, BluetoothLEAdvertisementWatcher &bluetoothWatcher); +void ApplyScanFilter(const UniversalScanFilter *filter, BluetoothLEAdvertisementWatcher &bluetoothWatcher) { + if (filter == nullptr) { + // Handle the case where filter is null, e.g., apply no filter or use default settings. + return; + } + // Existing implementation +} ```

    โœจ Improve tool usage guide:
    **Overview:** The `improve` tool scans the PR code changes, and automatically generates suggestions for improving the PR code. The tool can be triggered [automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) every time a new PR is opened, or can be invoked manually by commenting on a PR. When commenting, to edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L69) related to the improve tool (`pr_code_suggestions` section), use the following template: ``` /improve --pr_code_suggestions.some_config1=... --pr_code_suggestions.some_config2=... ``` With a [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#working-with-github-app), use the following template: ``` [pr_code_suggestions] some_config1=... some_config2=... ```
    Enabling\disabling automation
    When you first install the app, the [default mode](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools) for the improve tool is: ``` pr_commands = ["/improve --pr_code_suggestions.summarize=true", ...] ``` meaning the `improve` tool will run automatically on every PR, with summarization enabled. Delete this line to disable the tool from running automatically.
    Utilizing extra instructions
    Extra instructions are very important for the `improve` tool, since they enable to guide the model to suggestions that are more relevant to the specific needs of the project. Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter. Specify relevant aspects that you want the model to focus on. Examples for extra instructions: ``` [pr_code_suggestions] # /improve # extra_instructions=""" Emphasize the following aspects: - Does the code logic cover relevant edge cases? - Is the code logic clear and easy to understand? - Is the code logic efficient? ... """ ``` Use triple quotes to write multi-line instructions. Use bullet points to make the instructions more readable.
    A note on code suggestions quality
    - While the current AI for code is getting better and better (GPT-4), it's not flawless. Not all the suggestions will be perfect, and a user should not accept all of them automatically. - Suggestions are not meant to be simplistic. Instead, they aim to give deep feedback and raise questions, ideas and thoughts to the user, who can then use his judgment, experience, and understanding of the code base. - Recommended to use the 'extra_instructions' field to guide the model to suggestions that are more relevant to the specific needs of the project, or use the [custom suggestions :gem:](https://github.com/Codium-ai/pr-agent/blob/main/docs/CUSTOM_SUGGESTIONS.md) tool - With large PRs, best quality will be obtained by using 'improve --extended' mode.
    More PR-Agent commands
    > To invoke the PR-Agent, add a comment using one of the following commands: > - **/review**: Request a review of your Pull Request. > - **/describe**: Update the PR title and description based on the contents of the PR. > - **/improve [--extended]**: Suggest code improvements. Extended mode provides a higher quality feedback. > - **/ask \**: Ask a question about the PR. > - **/update_changelog**: Update the changelog based on the PR's contents. > - **/add_docs** ๐Ÿ’Ž: Generate docstring for new components introduced in the PR. > - **/generate_labels** ๐Ÿ’Ž: Generate labels for the PR based on the PR's contents. > - **/analyze** ๐Ÿ’Ž: Automatically analyzes the PR, and presents changes walkthrough for each component. >See the [tools guide](https://github.com/Codium-ai/pr-agent/blob/main/docs/TOOLS_GUIDE.md) for more details. >To list the possible configuration parameters, add a **/config** comment.
    See the [improve usage](https://github.com/Codium-ai/pr-agent/blob/main/docs/IMPROVE.md) page for a more comprehensive guide on using this tool.
    fotiDim commented 2 months ago

    /review

    codiumai-pr-agent[bot] commented 2 months ago

    Persistent review updated to latest commit https://github.com/Navideck/universal_ble/commit/eca821efd65a33274b7ad0fc13eee5213aab6ffb