Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binding does not respect list of service ids in DiscoverServices, and instead tells windows to discover all (slow).) #19

Open
pursual opened this issue Sep 1, 2020 · 7 comments
Labels
help wanted Extra attention is needed

Comments

@pursual
Copy link

pursual commented Sep 1, 2020

This function simply requests all services from windows, and then filters the list, instead of requesting specific services from windows. For some devices with many services, this is slower than necessary.

bool BLEManager::DiscoverServices(const std::string& uuid,
                                  const std::vector<winrt::guid>& serviceUUIDs)
{
    CHECK_DEVICE();
    IFDEVICE(device, uuid)
    {
        auto completed = bind2(this, &BLEManager::OnServicesDiscovered, uuid, serviceUUIDs);
        device.GetGattServicesAsync(BluetoothCacheMode::Uncached).Completed(completed);
        return true;
    }
}
@geovie
Copy link
Contributor

geovie commented Sep 1, 2020

AFAIK the only available method is GetGattServicesForUuidAsync which would only request a single service.

So to implement this we'd have two cases:

  • if the serviceUUIDs array is empty (which means no filter): use GetGattServicesAsync as we use now
  • if the serviceUUIDs array not empty: issue a GetGattServicesForUuidAsync call for each uuid in the array and combine the results

If anyone wants to implement this I can provide further guidance.

@geovie geovie added the help wanted Extra attention is needed label Sep 1, 2020
@pursual
Copy link
Author

pursual commented Sep 2, 2020

It's looking more and more like I am going to need to do this. The same deficiency is in noble_uwp. I could knock this out in JS, but I am going to be bumbling around in C. Ill give it a shot. Any web links on debugging node c modules, and tracking multiple async events are appreciated.

@pursual
Copy link
Author

pursual commented Sep 2, 2020

I am assuming we want to hit peripheral_winrt/getService instead of going directly to the device? getService is a callback pattern. Assuming we want to get each service in series, maybe I could do a recursive callback situation?

@pursual
Copy link
Author

pursual commented Sep 2, 2020

I get a ton of build errors before making any changes. Can I get some help on how to set my build system to ignore these things? I am assuming I am using tools that are too new or something like that?

C:\Users\Benefit Denial\Documents\GitHub\noble-winrtorig\src\radio_watcher.h(37,21): error C2039: 'function': is not a member of 'std' (compiling source file ..\src\radio_watcher.cc) [C:\Users\Benefit Denial\Documents\GitH
ub\noble-winrtorig\build\noble_winrt.vcxproj]
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\cppwinrt\winrt\Windows.Devices.Radios.h(246): message : see declaration of 'std' (compiling source file ..\src\radio_watcher.cc) [C:\Users\Benefit Denial\Document
s\GitHub\noble-winrtorig\build\noble_winrt.vcxproj]
C:\Users\Benefit Denial\Documents\GitHub\noble-winrtorig\src\radio_watcher.h(37,29): error C2061: syntax error: identifier 'function' (compiling source file ..\src\radio_watcher.cc) [C:\Users\Benefit Denial\Documents\GitHu
b\noble-winrtorig\build\noble_winrt.vcxproj]
C:\Users\Benefit Denial\Documents\GitHub\noble-winrtorig\src\radio_watcher.h(59,10): error C2039: 'function': is not a member of 'std' (compiling source file ..\src\radio_watcher.cc) [C:\Users\Benefit Denial\Documents\GitH
ub\noble-winrtorig\build\noble_winrt.vcxproj]
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\cppwinrt\winrt\Windows.Devices.Radios.h(246): message : see declaration of 'std' (compiling source file ..\src\radio_watcher.cc) [C:\Users\Benefit Denial\Document
s\GitHub\noble-winrtorig\build\noble_winrt.vcxproj]
C:\Users\Benefit Denial\Documents\GitHub\noble-winrtorig\src\radio_watcher.h(59,18): error C7568: argument list missing after assumed function template 'function' (compiling source file ..\src\radio_watcher.cc) [C:\Users\B
enefit Denial\Documents\GitHub\noble-winrtorig\build\noble_winrt.vcxproj]
C:\Users\Benefit Denial\Documents\GitHub\noble-winrtorig\src\radio_watcher.h(59,39): error C2062: type 'unknown-type' unexpected (compiling source file ..\src\radio_watcher.cc) [C:\Users\Benefit Denial\Documents\GitHub\nob
le-winrtorig\build\noble_winrt.vcxproj]
C:\Users\Benefit Denial\Documents\GitHub\noble-winrtorig\src\radio_watcher.h(59,56): error C2238: unexpected token(s) preceding ';' (compiling source file ..\src\radio_watcher.cc) [C:\Users\Benefit Denial\Documents\GitHub\
noble-winrtorig\build\noble_winrt.vcxproj]
C:\Users\Benefit Denial\Documents\GitHub\noble-winrtorig\src\radio_watcher.cc(18,17): error C2039: 'bind': is not a member of 'std' [C:\Users\Benefit Denial\Documents\GitHub\noble-winrtorig\build\noble_winrt.vcxproj]       

@pursual
Copy link
Author

pursual commented Sep 2, 2020

Nevermind....adding #include <functional> to radio_watcher.cc fixed it.

@pursual
Copy link
Author

pursual commented Sep 2, 2020

This is as far as I have been able to get. It works with one service uuid, but for more than one it just gets all. noble-winrt doesnt seem to have any foundation for emitting an error instead of a list of discovered serviceids.

bool BLEManager::DiscoverServices(const std::string& uuid,
                                  const std::vector<winrt::guid>& serviceUUIDs)
{
    CHECK_DEVICE();
    IFDEVICE(device, uuid)
    {
        if (serviceUUIDs.empty() || serviceUUIDs.size() > 1) { 
            auto completed = bind2(this, &BLEManager::OnServicesDiscovered, uuid, serviceUUIDs);
            device.GetGattServicesAsync(BluetoothCacheMode::Uncached).Completed(completed);
            return true;
        } 
         
        if (serviceUUIDs.size() == 1) { 
            auto& id = serviceUUIDs.at(0);
            peripheral.GetService(id, [=](std::optional<GattDeviceService> service) {
                if (service)
                {
                    std::vector<std::string> serviceUuids;
                    serviceUuids.push_back(toStr(id));
                    mEmit.ServicesDiscovered(uuid, serviceUuids);
                }
                else
                {
                    LOGE("GetService error");
                    //need to emit an error here. 
                }
            });
        }
    }
}

@pursual
Copy link
Author

pursual commented Sep 9, 2020

It also appears that device.GetGattServicesAsync does not populate the internal cache of services upon completion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants