This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Windows 10, Thingy 52 BLE

I'm attempting to write a plugin/dll to pull data from the Nordic Thingy52. I can scan all devices that are paired with windows 10, and load up the services, etc.

I can also read from descriptors that have explicit Read permissions. However, when I attempt to set a characteristic (such as motion data) to notify, or write to a service configuration characteristic, It instantly disconnects.

I loaded up the Thingy Firmware as a debug build from the github repo, and logged the data thingy_log.txt

It appears to reboot 20+ times. Int he Jlink RTT Viewer I would sometimes see drv_ext_gpio.c line 466 error (in Keil it's a blank line) (correction: line 446)

err_code = drv_sx1509_data_modify((1UL << pin_number), 0);
RETURN_IF_ERROR_EXT_GPIO_CLOSE(err_code);

Is there a sequence to connecting to the Thingy that's done in android/iOS apps that I'm missing here?

Edit: I am Currently connecting by getting the Config service, then getting motion, sound, and UI services (I don't need the rest) from the DeviceInfo on windows.

I am then attempting to write characteristic values for motion config, etc. But nothing stays connected. Do I need to be doing some sort of MTU request?

Parents
  • Hello. I had the same problem. If my device is paired - fail connection (unreachable). In last windows version (Windows 10 Fall Creators Update (1709, build 16229.19)) you can communicate with unpaired devices. I updated windows platform in my PC app, and was able to connect and subscribe to notifications after deleted from paired list in windows settings.

    // search for unpaired devices var findAllDevicesTask = DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelectorFromPairingState(false)).AsTask(); Task.WaitAll(findAllDevicesTask); var devices = findAllDevicesTask.Result;

    // connect BluetoothLEDevice bluetoothLeDevice = null; var deviceTask = BluetoothLEDevice.FromIdAsync(di.Id).AsTask(); Task.WaitAll(deviceTask);

  • Old thread but very relevant today!

    I'm having exactly this issue. Has anyone figured out how to connect to a PAIRED BLE device on Windows??? Any help appreciated. See below.

    The following code snippet works if the Bluetooth LE device is NOT paired. After pairing the same device, the call to WriteClientCharacteristicConfigurationDescriptorAsync() fails with UNREACHABLE. No PIN code required for pairing.

    The code will become part of a library with Java JNI bindings, so needs to be in C++. That's why I'm using the WinRT stuff. I'm using VS 2017 target SDK 10.0.18362.0 running on Windows 10 1903.

    #include "pch.h"
    
    #include <combaseapi.h>
    
    using namespace winrt;
    using namespace Windows::Foundation;
    using namespace winrt::Windows::Foundation;
    using namespace Windows::Storage::Streams;
    using namespace Windows::Devices::Bluetooth;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::Devices::Bluetooth::Advertisement;
    using namespace Windows::Devices::Bluetooth::GenericAttributeProfile;
    
    #define NU_SERVICE			"{6E400001-B5A3-F393-E0A9-E50E24DCCA9E}"
    #define TX_CHARACTERISTIC	"{6E400002-B5A3-F393-E0A9-E50E24DCCA9E}"
    #define RX_CHARACTERISTIC	"{6E400003-B5A3-F393-E0A9-E50E24DCCA9E}"
    
    std::wstring guidToString(GUID uuid) {
    	std::wstring guid;
    	WCHAR* wszUuid = NULL;
    	if(::UuidToString(&uuid, (RPC_WSTR*) &wszUuid) == RPC_S_OK) {
    		guid = wszUuid;
    		::RpcStringFree((RPC_WSTR*) &wszUuid);
    	}
    	return guid;
    }
    
    void str2ba(const char *straddr, unsigned long long *btaddr) {
    	int i;
    	unsigned int aaddr[6];
    	unsigned long long tmpaddr = 0;
    
    	if (sscanf_s(straddr, "%02x:%02x:%02x:%02x:%02x:%02x", &aaddr[0], &aaddr[1], &aaddr[2], &aaddr[3], &aaddr[4], &aaddr[5]) != 6) {
    		return;
    	}
    	*btaddr = 0;
    	for (i = 0; i < 6; i++) {
    		tmpaddr = (unsigned long long) (aaddr[i] & 0xff);
    		*btaddr = ((*btaddr) << 8) + tmpaddr;
    	}
    }
    
    IAsyncAction OpenDevice(unsigned long long deviceAddress) {
    	auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(deviceAddress);
    
    	std::wcout << std::hex <<
    		"Device Information: " << std::endl <<
    		"\tName     :" << device.Name().c_str() << std::endl <<
    		"\tAddress  :" << device.BluetoothAddress() << std::endl <<
    		"\tStatus   :" << (device.ConnectionStatus() == BluetoothConnectionStatus::Connected ? "Connected" : "Disconnected") << std::endl <<
    		"\tDeviceId :" << device.DeviceId().c_str()  << std::endl <<
    		std::endl;
    
    	GUID nusGUID, txcGUID, rxcGUID;
    	CLSIDFromString(TEXT(NU_SERVICE), &nusGUID);
    	CLSIDFromString(TEXT(TX_CHARACTERISTIC), &txcGUID);
    	CLSIDFromString(TEXT(RX_CHARACTERISTIC), &rxcGUID);
    
    	auto services = co_await device.GetGattServicesAsync();//BluetoothCacheMode::Cached);
    	for(GenericAttributeProfile::GattDeviceService const & s : services.Services()) {
    		std::wcout << std::hex << "\t\tService - Guid: [" << guidToString(s.Uuid()) << "]" << std::endl;
    
    		auto characteristics = co_await s.GetCharacteristicsAsync();
    		for(GenericAttributeProfile::GattCharacteristic const & c : characteristics.Characteristics()) {
    			std::wcout << std::hex << "\t\tCharacteristic - Guid: [" << guidToString(c.Uuid()) << "]" << std::endl;
    
    			if(c.CharacteristicProperties() == GattCharacteristicProperties::Notify) {
    				printf("Notify supported\n");
    
    				GattCommunicationStatus status = co_await c.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue::Notify);
    				switch (status) {
    				case GattCommunicationStatus::AccessDenied:
    					printf("access denied\n");
    					break;
    				case GattCommunicationStatus::ProtocolError:
    					printf("protocol error\n");
    					break;
    				case GattCommunicationStatus::Unreachable:
    					printf("unreachable\n");
    					break;
    				case GattCommunicationStatus::Success:
    					c.ValueChanged([](GattCharacteristic const& charateristic, GattValueChangedEventArgs const& args) {
    						std::wcout << std::hex <<
    							"\t\tNotified GattCharacteristic - Guid: [" << guidToString(charateristic.Uuid()) << "]" << std::endl;
    					});
    
    					//
    					// Code to write to BT device ommitted.... Sleep 5 secs then exit.
    					//
    					Sleep(5000);
    				}
    			}
    		}
    	}
    
    	device.Close();
    }
    
    int main() {
    	init_apartment();
    
    	// Connect to a specific Bluetooth device.
    	unsigned long long deviceAddress;
    	str2ba("db:e7:df:00:52:32", &deviceAddress);
    	printf("device = %lld\n", deviceAddress);
    
    	try {
    		OpenDevice(deviceAddress).get();
    	} catch (const std::exception& e) {
    		std::cout << e.what() << std::endl;
    		return FALSE;
    	}
    	return TRUE;
    }

Reply
  • Old thread but very relevant today!

    I'm having exactly this issue. Has anyone figured out how to connect to a PAIRED BLE device on Windows??? Any help appreciated. See below.

    The following code snippet works if the Bluetooth LE device is NOT paired. After pairing the same device, the call to WriteClientCharacteristicConfigurationDescriptorAsync() fails with UNREACHABLE. No PIN code required for pairing.

    The code will become part of a library with Java JNI bindings, so needs to be in C++. That's why I'm using the WinRT stuff. I'm using VS 2017 target SDK 10.0.18362.0 running on Windows 10 1903.

    #include "pch.h"
    
    #include <combaseapi.h>
    
    using namespace winrt;
    using namespace Windows::Foundation;
    using namespace winrt::Windows::Foundation;
    using namespace Windows::Storage::Streams;
    using namespace Windows::Devices::Bluetooth;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::Devices::Bluetooth::Advertisement;
    using namespace Windows::Devices::Bluetooth::GenericAttributeProfile;
    
    #define NU_SERVICE			"{6E400001-B5A3-F393-E0A9-E50E24DCCA9E}"
    #define TX_CHARACTERISTIC	"{6E400002-B5A3-F393-E0A9-E50E24DCCA9E}"
    #define RX_CHARACTERISTIC	"{6E400003-B5A3-F393-E0A9-E50E24DCCA9E}"
    
    std::wstring guidToString(GUID uuid) {
    	std::wstring guid;
    	WCHAR* wszUuid = NULL;
    	if(::UuidToString(&uuid, (RPC_WSTR*) &wszUuid) == RPC_S_OK) {
    		guid = wszUuid;
    		::RpcStringFree((RPC_WSTR*) &wszUuid);
    	}
    	return guid;
    }
    
    void str2ba(const char *straddr, unsigned long long *btaddr) {
    	int i;
    	unsigned int aaddr[6];
    	unsigned long long tmpaddr = 0;
    
    	if (sscanf_s(straddr, "%02x:%02x:%02x:%02x:%02x:%02x", &aaddr[0], &aaddr[1], &aaddr[2], &aaddr[3], &aaddr[4], &aaddr[5]) != 6) {
    		return;
    	}
    	*btaddr = 0;
    	for (i = 0; i < 6; i++) {
    		tmpaddr = (unsigned long long) (aaddr[i] & 0xff);
    		*btaddr = ((*btaddr) << 8) + tmpaddr;
    	}
    }
    
    IAsyncAction OpenDevice(unsigned long long deviceAddress) {
    	auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(deviceAddress);
    
    	std::wcout << std::hex <<
    		"Device Information: " << std::endl <<
    		"\tName     :" << device.Name().c_str() << std::endl <<
    		"\tAddress  :" << device.BluetoothAddress() << std::endl <<
    		"\tStatus   :" << (device.ConnectionStatus() == BluetoothConnectionStatus::Connected ? "Connected" : "Disconnected") << std::endl <<
    		"\tDeviceId :" << device.DeviceId().c_str()  << std::endl <<
    		std::endl;
    
    	GUID nusGUID, txcGUID, rxcGUID;
    	CLSIDFromString(TEXT(NU_SERVICE), &nusGUID);
    	CLSIDFromString(TEXT(TX_CHARACTERISTIC), &txcGUID);
    	CLSIDFromString(TEXT(RX_CHARACTERISTIC), &rxcGUID);
    
    	auto services = co_await device.GetGattServicesAsync();//BluetoothCacheMode::Cached);
    	for(GenericAttributeProfile::GattDeviceService const & s : services.Services()) {
    		std::wcout << std::hex << "\t\tService - Guid: [" << guidToString(s.Uuid()) << "]" << std::endl;
    
    		auto characteristics = co_await s.GetCharacteristicsAsync();
    		for(GenericAttributeProfile::GattCharacteristic const & c : characteristics.Characteristics()) {
    			std::wcout << std::hex << "\t\tCharacteristic - Guid: [" << guidToString(c.Uuid()) << "]" << std::endl;
    
    			if(c.CharacteristicProperties() == GattCharacteristicProperties::Notify) {
    				printf("Notify supported\n");
    
    				GattCommunicationStatus status = co_await c.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue::Notify);
    				switch (status) {
    				case GattCommunicationStatus::AccessDenied:
    					printf("access denied\n");
    					break;
    				case GattCommunicationStatus::ProtocolError:
    					printf("protocol error\n");
    					break;
    				case GattCommunicationStatus::Unreachable:
    					printf("unreachable\n");
    					break;
    				case GattCommunicationStatus::Success:
    					c.ValueChanged([](GattCharacteristic const& charateristic, GattValueChangedEventArgs const& args) {
    						std::wcout << std::hex <<
    							"\t\tNotified GattCharacteristic - Guid: [" << guidToString(charateristic.Uuid()) << "]" << std::endl;
    					});
    
    					//
    					// Code to write to BT device ommitted.... Sleep 5 secs then exit.
    					//
    					Sleep(5000);
    				}
    			}
    		}
    	}
    
    	device.Close();
    }
    
    int main() {
    	init_apartment();
    
    	// Connect to a specific Bluetooth device.
    	unsigned long long deviceAddress;
    	str2ba("db:e7:df:00:52:32", &deviceAddress);
    	printf("device = %lld\n", deviceAddress);
    
    	try {
    		OpenDevice(deviceAddress).get();
    	} catch (const std::exception& e) {
    		std::cout << e.what() << std::endl;
    		return FALSE;
    	}
    	return TRUE;
    }

Children
No Data
Related