Friday, 13 May 2016

Publishing

Bluetooth is for wireless communication of devices.


Bluetooth LE, 'Low Energy', also 'Bluetooth Smart', is a core technology for the IoT, Internet of Things: It is the way how little 'intelligent' 'Things' ('peripherals') can do their 'thing' and communicate it to the rest of the world.


To announce themselves, they can publish little messages called 'Advertisements'. A sensor might sit in the roof and call out every 100 milliseconds "I'm here. I'm here. I'm here. You can get the temperature from me. I'm here. I'm here. You can get the temperature from me.", and because it is 'low energy', it can do that for a long time.


What if we want to publish BLE advertisements using Windows?
It is possible to publish Bluetooth LE advertisements with the class Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementPublisher. Sample code from Microsoft is here.


This is how the sample code does it:


publisher = new BluetoothLEAdvertisementPublisher();
...
var manufacturerData = new BluetoothLEManufacturerData();
manufacturerData.CompanyId = 0xFFFE;
var writer = new DataWriter();
UInt16 uuidData = 0x1234;
writer.WriteUInt16(uuidData);
manufacturerData.Data = writer.DetachBuffer();
publisher.Advertisement.ManufacturerData.Add(manufacturerData);
...
publisher.StatusChanged += OnPublisherStatusChanged;


publisher.Start();


This will only work if the app requests 'Bluetooth' capabilities in its appManifest:
In Visual Studio:
Package.appmanifest -> Capabilities -> Ensure 'Bluetooth' is checked.

In a text editor:
Open Package.appmanifest in a text or xml editor:

  <Capabilities>
    ...
    <DeviceCapability Name="bluetooth" />
    ...
  </Capabilities>



Notes here:
  • Without manufacturer data, the publisher won't get started. Start() will throw a COMException with the message :
    "The data is invalid. Publisher can only be started with a non-empty payload."
  • The StatusChanged event comes back with a status and an error, which are both enums. Status can be:
    Success, RadioNotAvailable, ResourceInUse, DeviceNotConnected, OtherError, DisabledByPolicy, NotSupported, DisabledByUser.
    Error can be:
    Created, Waiting, Started, Stopping, Stopped, Aborted.


E.g., after Start()ing a publisher without a Bluetooth LE device installed in the computer, the status was 'RadioNotAvailable'.


When the App had not requested the 'Bluetooth' capability in the Package.appmanifest file, the status was 'OtherError'.


After fixing these errors, it all worked, and other BLE devices could see my advertised publisher. However, these other devices see my publisher as 'Unnamed', 'no name', or 'unknown'. My publisher does not advertise a name. This is where the sample ends, it does not show how to publish a name.


A 'Local Name' is normally advertised in the DataSections of the advertisement, so we could try to add a DataSection:


var dataSection = new BluetoothLEAdvertisementDataSection();
byte dataType = BluetoothLEAdvertisementDataTypes.CompleteLocalName;
dataSection.DataType = (byte)dataType;
writer = new DataWriter();
writer.WriteString("MyName");
dataSection.Data = writer.DetachBuffer();


However, if doing so, then publisher.Start() also throws a COMException:
"The data is invalid.\r\n\r\nInvalid advertisement payload detected."


Which is not surprising because this is documented for the BluetoothAdvertisementPublisher class.


According to this, nearly all interesting advertisement datasection types are "system-reserved and are not allowed".


This includes the Shortened Local Name (Data type 0x08), Complete Local Name (Data type 0x09), Class Of Device (Data type 0x0D), and all complete and incomplete lists of service UUIds (Data types 0x02-0x07).


So, no way for us to say "I'm here. I'm here. I'm here. You can get a Http Proxy from me."


No way to advertise a name when I publish a BluetoothLEAdvertisement. No way to publish a service or a characteristic.


Moreover, there is nothing here in the API to tell me if someone who sees my published advertisements wants to connect or pair with me.


But there are more people wanting this, so, watch this space.

Tuesday, 10 May 2016

To Start: Which Versions this is about...

To comment on the Bluetooth LE API, it would be useful to specify versions, but that is hard:
Since Windows 10, Microsoft are promising to keep you out of the version hassle, and update to new versions automatically. Consequently, they don't make it exactly easy to find version numbers.

I am remote debugging on a laptop with Windows 10 installed. The Computer Properties say
'Windows 10 Pro'.
Settings -> System -> About says:
Edition: Windows 10 Pro
Version: 1511
OS Build: 10586.218
The development environment is Visual Studio 2015 Update 2 on Windows 7, using a Remote Debugger. Visual Studio  creates the project for an UWP app or dll with the default settings for the target system:
.Net Core target version: 10.0.10586, minimal: 10.0.10240
Part of the Bluetooth LE API is, for example, the Windows.Devices.Bluetooth.Advertisement namespace, and at the time of writing this, it is documented on MSDN here.
The individual class documentations for this namespace state:
"Device family: Universal, introduced version 10.0.10240.0"
However, it is not easy to find out the actual current version of .Net Core on the computer.
It is not installed under C:\Windows\Microsoft\.Net\Framework and Framework64. Apparently, .Net Core is part of the system, and the best guess is that it has the version of the system itself (10.0.10586).

Sunday, 8 May 2016

The Joys and Sorrows of Bluetooth LE (BLE) with Windows

This is a summary of  how to use Bluetooth LE, also known as Bluetooth Smart or Bluetooth 4.* (4.0, 4.2) in Windows software development.


It contains explanation and critique of the Bluetooth LE API and lots of open questions to the Bluetooth LE development team at Microsoft (who will probably never read this, but anyway...)


The focus is on C# and the Bluetooth LE C# API available since Windows 10.0.10240.0 for Universal Windows (UWP) apps.


I will describe the journey to get BLE to work on a remote Windows 10 computer in 2016, will give some code examples of how to use the API, what worked and what didn't.


Bluetooth LE has been available since Windows 8 in the C++ Bluetooth LE API, but in Windows 10, a  C# API has been added to the .Net Core library and gives developers of Windows Store apps access to Bluetooth LE capabilities under the Windows.Devices.Bluetooth.* namespaces.