Sergiy Baydachnyy

Blog about technologies

Posts Tagged ‘Universal Applications

UWP: Working with Bluetooth (part 5: Bluetooth RFCOMM)

with one comment

Windows 10 API supports not just Bluetooth Low Energy devices, but allows you to utilize RFCOMM protocol as the most widespread since Bluetooth invention. Even if your module doesn’t support BLE, you always can use RFCOMM. As in the case of BLE Windows 10 allows you to publish RFCOMM services or work with other services as a client.

I decided to implement client only, and for a server I used a cheap Bluetooth module HC-06. It’s possible to buy the module for couple dollars and you can find lots of videos and examples about how to connect it to Arduino board. But you can use any available Bluetooth module. Just in case you can find a schema below:

clip_image002

My module wasn’t on a plate with a voltage regulator. So, I decided to add a voltage divider for TX->RX connection, because Arduino generate 5 volts there rather than 3.3 volts. If you have a module like on the schema above (with the regulator), you still can use the divider, and it will not break your circuit.

To communicate with the module from Arduino, you can simply use the serial port. So, I connected TX and RX pins on Arduino to RX and TX pins on the module. Additionally, I connected 3.3V and GRN on Arduino to VCC and GRN on the module.

I setup my module to use 115200 speed and changed the name of the module to rfcommhc06. You can do it connection the module to your computer using USB to Serial adapter and execute some AT commands (AT+NAMErfcommhc06 and AT+BAUD8).

Finally, I could implement a very simple code for Arduino:

void setup()
{
   Serial.begin(115200);
   pinMode(13,OUTPUT);
}
byte blue;
void loop()
{
   if(Serial.available())
   {
      blue=Serial.read();
      Serial.write(blue);
      if (blue==3)
      {
         digitalWrite(13,HIGH);
      }
      else if(blue==2)
      {
         digitalWrite(13,LOW);
      }
      Serial.write(blue);
   }
}

This code read data from serial port using infinity loop and one there is 3, it sends high voltage to pin number 13. In the case if 2 is in the stream, it sends low voltage to pin 13. Because pin 13 are connected with a LED on Arduino Uno boards, the led will switch status between on and off depends on input data. At the end of each iteration, I send all incoming data back.

If you finish your circuit and deploy the code successfully, it’s time to start developing a client for Windows 10.

The first part of our code will look similar to BLE example. We have to start watcher and declare handlers for Added and Removed events:

DeviceWatcher deviceWatcher;
DataWriter tx;
DataReader rx;
StreamSocket stream;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
   deviceWatcher = DeviceInformation.CreateWatcher(
      "System.ItemNameDisplay:~~\"rfcommhc\"",
      null,
      DeviceInformationKind.AssociationEndpoint);
   deviceWatcher.Added += DeviceWatcher_Added;
   deviceWatcher.Removed += DeviceWatcher_Removed;
   deviceWatcher.Start();
   base.OnNavigatedTo(e);
}

The DeviceWatcher_Added method will looks different compare to BLE example.

private async void DeviceWatcher_Added(DeviceWatcher sender,
   DeviceInformation args)
{
   var device = await BluetoothDevice.FromIdAsync(args.Id);
   var services = await device.GetRfcommServicesAsync();
   if (services.Services.Count>0)
   {
      var service = services.Services[0];
      stream = new StreamSocket();
      await stream.ConnectAsync(service.ConnectionHostName,
      service.ConnectionServiceName);
      rx = new DataReader(stream.InputStream);
      tx = new DataWriter(stream.OutputStream);
      await this.Dispatcher.RunAsync(
         Windows.UI.Core.CoreDispatcherPriority.Normal,
         () => { switchLed.IsEnabled = true; });
      deviceWatcher.Stop();
   }
}

First, we use the BluetoothDevice class rather than BluetoothLEDevice. Once we have a reference to the device, the GetRfcommServiceAsync method helps us to get list of all available services. Our Arduino code is very primitive and we have just one service. Once we have a reference to the service, we can use the StreamSocket class to establish a connection to the Bluetooth module and get references to input and output streams.

Finally, we can use DataReader and DataWriter classes to start working with the module like with a virtual serial port:

private async void ToggleSwitch_Toggled(object sender, RoutedEventArgs e)
{
   byte data = 2;
   if (switchLed.IsOn)
   {
      data = 3;
   }
   tx.WriteByte(data);
   await tx.StoreAsync();
   uint buf;
   buf = await rx.LoadAsync(1);
   var symbol = rx.ReadByte();
   Debug.WriteLine(data);
}

If you want to develop something more for Arduino and Windows 10, I would recommend to use Remote Wiring project (https://github.com/ms-iot/remote-wiring) that can help you control Arduino board using your own UWP application.

Written by Sergiy Baydachnyy

05/19/2017 at 10:58 PM

UWP: Working with Bluetooth (part 3: Advertisement)

leave a comment »

Bluetooth Low Energy can be used to implement beacons. Usually beacons are not designed for pairing and simply broadcast data making them available for everybody. You can use beacons in a mall to notify shoppers about some deals, or in quests, notifying players about some treasures in the area, or even for people with disabilities notifying them about surrounding environment. Today, almost all mobile devices support Bluetooth Low Energy and advertisement feature there and you even can find some SDKs for Android and iOS that implement own data payload specifications (Eddystone and iBeacon) based on Bluetooth Low Energy Advertisement. Thanks to the specifications you can understand what kind of data is broadcasting and use them in your applications even if a beacon was implemented by somebody else.

In the case of Universal Windows Platform you have access to a special namespace Windows.Devices.Bluetooth.Advertisement that can help you receive and send data using BLE Advertisement. Using this namespace you can implement classes that will use existing payload specifications or simply broadcast data in your own way.

To implement advertisement example, I am not going to use any microcontroller. Instead, I would recommend to use just Windows 10 computers. In general, any Windows 10 computer can send and receive advertisement, but in some cases, it’s not true and some Bluetooth radio adapters don’t support broadcasting advertisement data.

To understand if your adapter supports broadcasting, you can simply execute the following line of code:

BluetoothAdapter adapter = await BluetoothAdapter.GetDefaultAsync();

And just check adapter’s property using Debugger:

clip_image002

You can see that there is a property IsAdvertisementOffloadSupported that shows if your adapter can broadcast advertisement. In my case this property is true.

Ok, let’s start with code that broadcast some data:

BluetoothLEAdvertisementPublisher publisher;
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    var manufacturerData =
        new BluetoothLEManufacturerData();
    var writer = new DataWriter();
    writer.WriteString("Buy our socks for a dollar");
    manufacturerData.CompanyId = 0xFFFE;
    manufacturerData.Data = writer.DetachBuffer();
    publisher =
        new BluetoothLEAdvertisementPublisher();
    publisher.Advertisement.ManufacturerData.Add(manufacturerData);
    publisher.StatusChanged += Publisher_StatusChanged;
    publisher.Start();
    base.OnNavigatedTo(e);
    }
private void Publisher_StatusChanged(BluetoothLEAdvertisementPublisher sender,
    BluetoothLEAdvertisementPublisherStatusChangedEventArgs args)
{
    Debug.WriteLine(args.Status.ToString());
}

In our case we made all preparation work using the BluetoothLEManufacturerData class. We used this class just in order to simplify our work, because we are not going to broadcast anything special, but in the most cases you will use the DataSections property rather than the ManufacturerData property. Exactly DataSections contains all payloads and filling ManufacturerData you automatically add a section to DataSections collection. But working with the BluetoothLEAdvertisementDataSection class to fill DataSections is a little bit more complicated, because you need to know different data types from BLE specification, form a header that will include special flags and size of the buffer and so on. In the case of the BluetoothLEManufacturerData class you can write your data directly and all what you need is just provide a company id. Using this link (https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers), you can find some hardcoded company ids for companies like Apple and Microsoft. Therefore, I selected the first available ID from the end. Additionally, I implemented the StatusChanged event handler to make sure that my application starts broadcasting data.

Therefore, we have a publisher that broadcasts a text message. Now, we can create a watcher that will receive our advertisement. Let’s look at the following code:

private BluetoothLEAdvertisementWatcher watcher;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    watcher = new BluetoothLEAdvertisementWatcher();
    watcher.SignalStrengthFilter.InRangeThresholdInDBm = -70;
    var manufacturerData =
        new BluetoothLEManufacturerData();
    manufacturerData.CompanyId = 0xFFFE;
    watcher.AdvertisementFilter.Advertisement.ManufacturerData.Add(
        manufacturerData);
    watcher.Stopped += Watcher_Stopped;
    watcher.Received += Watcher_Received;
    watcher.Start();
    base.OnNavigatedTo(e);
}
private void Watcher_Stopped(BluetoothLEAdvertisementWatcher sender,
    BluetoothLEAdvertisementWatcherStoppedEventArgs args)
{ }
private void Watcher_Received(BluetoothLEAdvertisementWatcher sender,
    BluetoothLEAdvertisementReceivedEventArgs args)
{
    Debug.WriteLine(args.Advertisement.LocalName);
    Debug.Write(args.RawSignalStrengthInDBm);
    if ((args.Advertisement.ManufacturerData.Count>0))
    {
        DataReader data =
            DataReader.FromBuffer(args.Advertisement.ManufacturerData[0].Data);
        Debug.Write(data.ReadString(
            args.Advertisement.ManufacturerData[0].Data.Length));
    }
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    watcher.Stop();
    base.OnNavigatedFrom(e);
}

In fact, it’s not a complex task to create a watcher, but implementing your own application, you should not always watch all advertisements around. It’s better to watch exactly beacons that were designed for your application. That’s why the BluetoothLEAdvertisementWatcher class allows us to setup filters. In our case we have two filters: signal strength and company id. It can help us understand that we are too close to the beacon and that it’s exactly our service.

Working with beacons we have to note several things:

  • In most cases you will work with the DataSections property. So, if you want to develop something cool, you have to learn Bluetooth LE Advertisement specification. Additionally, you may need to implement Eddystone and iBeacon specifications;
  • You can see that beacon broadcasts the same data all time and if you run our application in the Debug mode, you will be able to see that the application prints advertisement message all time. So, it’s important to check if you already received the message to avoid duplicate actions;
  • Above we implemented just foreground applications, but it’s not wisely. Probably, our application will not stay open all time even in the case of watcher. In the case of publisher, there is no sense to implement interface at all. That’s why it’s important to know how to work with Bluetooth in background. We will discuss background approach later;

Written by Sergiy Baydachnyy

05/08/2017 at 10:27 PM

UWP: Working with Bluetooth devices (part 2: pairing)

leave a comment »

Implementing the previous example, I didn’t pair my device with my Windows 10 PC, but in the most cases you cannot omit pairing. Exactly thanks to pairing you can establish trust communications with a Bluetooth device that will allow your application get access to characteristics, lock the device to your computer and many other things. Windows 10 allows you to pair any device (not just Bluetooth) using Settings window:

clip_image002

But you can pair your devices directly from your application. In order to do it you can use the same DeviceInformation class that we used to track available devices.

Let’s modify our code. We will check the status and if the device is not paired we will pair it. You can use the following code in order to pair the device and navigate the application to the next page:

private async void deviceListView_ItemClick(object sender, ItemClickEventArgs e)
{
    var item = e.ClickedItem as DeviceInformation;
    if (item.Pairing.CanPair)
    {
        var result = await item.Pairing.PairAsync();
        if ((result.Status == DevicePairingResultStatus.Paired) ||
            (result.Status == DevicePairingResultStatus.AlreadyPaired))
        {
            this.Frame.Navigate(typeof(DevicePage), item);
        }
    }
    else if (item.Pairing.IsPaired == true)
    {
        this.Frame.Navigate(typeof(DevicePage), item);
    }
}

You can see that we used Pairing property to get a reference to an object of DeviceInformationPairing type. Using it we can check if the device is already paired, and pair the device if needed.

Pay attention that Windows is caching all paired devices. So, once your device is paired, you will be able to see it in the list, even if the device is not present physically. It’s a problem and it’s better to check if the device is still available.

Of course, pairing process may require some actions from user side. For example, STEVAL-IDB007V1 evaluation board requires to inter a pin (123456 by default) to complete the pairing process. So, the PairAsync method will show all needed dialogs:

clip_image004

Once the device is paired, the application will display the next page with data. If you navigate your application back, you will be able to see that the device is already paired:

clip_image006

UWP API supports one more way for pairing: custom pairing mechanism. Using this way, you can create your own dialogs that will requires all needed pins or any additional information. In our case we can suppress the default pin dialog and hardcode the default pin in code. The following code demonstrates this feature:

private async void deviceListView_ItemClick(object sender, ItemClickEventArgs e)
{
    var item = e.ClickedItem as DeviceInformation;
    if (item.Pairing.CanPair)
    {
        //var result = await item.Pairing.PairAsync();
        var customPairing = item.Pairing.Custom;
        customPairing.PairingRequested += CustomPairing_PairingRequested;
        var result =
            await customPairing.PairAsync(DevicePairingKinds.ProvidePin);
        customPairing.PairingRequested -= CustomPairing_PairingRequested;
        if ((result.Status == DevicePairingResultStatus.Paired) ||
            (result.Status == DevicePairingResultStatus.AlreadyPaired))
        {
            this.Frame.Navigate(typeof(DevicePage), item);
        }
    }
    else if (item.Pairing.IsPaired == true)
    {
        this.Frame.Navigate(typeof(DevicePage), item);
    }
}
private void CustomPairing_PairingRequested(
    DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)
{
    args.Accept("123456");
}

You can see that we used Custom property in order to invoke custom pairing process. Using this property and PairAsync method there we can activate pairing process. It will generate a special event PairingRequested where we can provide all needed information. In our case we simply use Accept method with the pin as a parameter.

Of course, Microsoft try to avoid any security issues with pairing. So, even in the case of custom pairing users will be able to see a notification window:

clip_image008

One more benefit due to pairing is ability to use a watcher to list services. In the previous example we used a snapshot of all services, but in the real life this process may take some time or some services may be available later. Using a watcher, you can control the process showing progress and all recognized services dynamically. Below you can find modified code that uses DeviceWatcher class to list all services for a selected device:

public async void StartReceivingData()
{
    leDevice = await BluetoothLEDevice.FromIdAsync(device.Id);
    string selector = "(System.DeviceInterface.Bluetooth.DeviceAddress:=\"" +
        leDevice.BluetoothAddress.ToString("X") + "\")";
    watcher = DeviceInformation.CreateWatcher(selector);
    watcher.Added += Watcher_Added;
    watcher.Removed += Watcher_Removed;
    watcher.Start();
    timer.Interval = new TimeSpan(0, 0, 1);
    timer.Tick += Timer_Tick;
    timer.Start();
}
private async void Watcher_Removed(DeviceWatcher sender,
    DeviceInformationUpdate args)
{ }
private async void Watcher_Added(DeviceWatcher sender, DeviceInformation args)
{
    var service = await GattDeviceService.FromIdAsync(args.Id);
    if (service!=null)
    {
        switch (service.Uuid.ToString())
        {
        case SensorUUIDs.UUID_ENV_SERV:
            InitializeTemperatureSensor(service);
            InitializePressureSensor(service);
        break;
        case SensorUUIDs.UUID_ACC_SERV:
            InitializeAccelerationSensor(service);
        break;
        }
    }
}

You can see that code is not very complex, but you can extend your UI now showing progress.

Written by Sergiy Baydachnyy

04/28/2017 at 11:08 PM

UWP: Working with Bluetooth devices (part 1)

with 4 comments

Code: Chapter26_BluetoothData on https://github.com/sbaidachni/Win10BookSamples

Universal Windows Platform supports really great Bluetooth API that allows us to build applications that are connected to various kinds of wiring devices. Your application can support Bluetooth LE (Low Energy, 4.x version) or even previous versions of the protocol, and I am going to cover how to use all of them, but let’s start with Bluetooth LE.

Bluetooth Low Energy

In order to build couple samples, I would recommend to use any BLE development board. The board should contain several sensors and a preinstalled example. In my case I have an evaluation board from STMicroelectronics (STEVAL-IDB007V1) based on BlueNRG-1 Bluetooth chip. This board contains a 3D digital accelerometer, a gyroscope (preinstalled example doesn’t return data from gyroscope by design) and a pressure sensor with an embedded temperature sensor. All these things we will be able to use in our application.

clip_image002

In fact, you can use any BLE device like a smart bulb that you can buy in Home Depot, but prior to buy anything you need to make sure that there is a document that describes all services and characteristics. Of course, using UWP API you will be able to read all available characteristics, but in the case of “no name” devices it’s really hard to understand how to interpret incoming data.

Universal Windows Platform contains five namespaces with Bluetooth keyword including Windows.Devices.Bluetooth. Exactly this namespace contains the BluetoothLEDevice class that will help us to get information about all available services and characteristics. But prior to start creating any instance of this class we need to implement interface that will allow a user to select our device from the list. Of course, we can list all device in code and connect to any of them without any interaction with the user, but it’s always better to get confirmation from the user.

Therefore, I am going to implement UI that will use some criteria to list all available devices and allows users to select one from the list. We can do it using the Windows.Devices.Enumeration namespace. In general, the namespace doesn’t contain any Bluetooth related classes. Instead, there are several universal classes that allow us to list anything that is connected to our computer/phone. This namespace even supports DevicePicker and DevicePickerFilter classes that can simplify our work thanks to embedded dialogs. But using these classes is a trivial task:

DevicePicker picker = new DevicePicker(); picker.Filter.SupportedDeviceSelectors.Add
    BluetoothLEDevice.GetDeviceSelectorFromPairingState(false));
picker.Filter.SupportedDeviceSelectors.Add(
    BluetoothLEDevice.GetDeviceSelectorFromPairingState(true));
picker.Show(new Rect(x, y, width, height));

Code below will show the following dialog that display all paired and non-paired Bluetooth Low Energy devices:

clip_image004

The dialog support DeviceSelected event that helps us to understand which device is selected. Alternatively, you can use PickSingleDeviceAsync method to avoid any event handlers. You can see that DevicePicker can display any devices. So, in order to display just BLE devices we need to setup a filter using Advanced Query Syntax string. ADS can be a little bit complex to setup. That’s why we used the BluetoothLEDevice class to get access to some predefined strings. Using the GetDeviceSelectorFromPairingState method we can return all BLE devices that are paired or non-paired. Adding both strings to the filter, we can select all available BLE devices.

In my examples, I am not going to use embedded dialogs. Instead of using them, I decided to build my own interface. In order to implement it, I need to create a page that will display a list of all devices in my own way. Using the DeviceInformation class I can find all BLE devices using the FindAllAsync method, but this approach is not the best one, because, I have to assume that users can activate new Bluetooth devices “on fly”. So, we have to look at all changes all time rather than use a snapshot and we cannot use just the FindAllAsync method in the DeviceInformation class. Instead, we will create a watcher that will notify us about any changes in the list of available devices. In order to do that, we can use the DeviceWatcher class that is available in the Windows.Devices.Enumeration namespace. Let’s look at the following code:

DeviceWatcher deviceWatcher;
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    deviceWatcher = DeviceInformation.CreateWatcher(
        "System.ItemNameDisplay:~~\"BlueNRG\"",
        new string[] {
            "System.Devices.Aep.DeviceAddress",
            "System.Devices.Aep.IsConnected" },
        DeviceInformationKind.AssociationEndpoint);
    deviceWatcher.Added += DeviceWatcher_Added;
    deviceWatcher.Removed += DeviceWatcher_Removed;
    deviceWatcher.Start();
    base.OnNavigatedTo(e);
}

You can see that in order to create the watcher, we used the CreateWatcher static method that you can find in the DeviceInformation class. This method accepts several parameters. Using the first one we can provide a filter that can help us list just needed devices. It’s the same Advanced Query Syntax string that we used before, but in this case, we created it from scratch rather than using a predefined one. It’s a good idea to show different approaches and I used a filter that helps me find exactly devices that contain BlueNRG string in their names. To implement this filter I used the System.ItemNameDisplay property. Because all my dev kit is available as BlueNRG by default, my application will show just my device. Of course, we should not hardcode any names and it’s better to use less restrictive filter like we did in the first block of codeIf you want to find more information about possible ADS properties you can visit this page.

The second parameter is a set of properties that should be available for a device. In this case we requested DeviceAddress and IsConnected properties, but I used it just for the demo. I assume that you will not able to find many different devices with BlueNRG name around, so, you can simply remove this parameter.

Finally, we have to pass the DeviceInformationKind flag. In our case it should be AssociationEndpoint that is true for all Bluetooth LE devices that advertise their interface.

Once we create the watcher, we need to assign event handlers to Added and Removed events and start the watcher. Pay attention that if you forget to assign Removed event handler, the watcher will not work. I am not sure “why”, but once I assigned an empty event handler, the watcher started without any problem. Here is my code:

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    deviceWatcher.Stop();
    base.OnNavigatedFrom(e);
}
private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
    //throw new NotImplementedException();
}
private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
    var device = await BluetoothLEDevice.FromIdAsync(args.Id);
    var services=await device.GetGattServicesAsync();
    foreach(var service in services.Services)
    {
        Debug.WriteLine($"Service: {service.Uuid}");
        var characteristics=await service.GetCharacteristicsAsync();
        foreach (var character in characteristics.Characteristics)
        {
            Debug.WriteLine($"Characteristic: {character.Uuid}");
        }
    }
}

Now, you can run the code above and it will start looking for a BlueNRG device and once it’s available, it will print all supported services and characteristics to the Output window. I got the following data for my device:

Service: 00001801-0000-1000-8000-00805f9b34fb
Characteristic: 00002a05-0000-1000-8000-00805f9b34fb
Service: 00001800-0000-1000-8000-00805f9b34fb
Characteristic: 00002a00-0000-1000-8000-00805f9b34fb
Characteristic: 00002a01-0000-1000-8000-00805f9b34fb
Characteristic: 00002a04-0000-1000-8000-00805f9b34fb
Service: 02366e80-cf3a-11e1-9ab4-0002a5d5c51b
Characteristic: e23e78a0-cf4a-11e1-8ffc-0002a5d5c51b
Characteristic: 340a1b80-cf4b-11e1-ac36-0002a5d5c51b
Service: 42821a40-e477-11e2-82d0-0002a5d5c51b
Characteristic: a32e5520-e477-11e2-a9e3-0002a5d5c51b
Characteristic: cd20c480-e48b-11e2-840b-0002a5d5c51b

You can see that the device supports four services and each of them contains from one to three characteristics. In order to understand what is it, we need to visit STMicroelectronics web-site (st.com) and find a document that describes all these things. The document called UM2071: BlueNRG-1 development kit. If you type this name in the Search box and open the Resource tab, you will be able to find it. This document contains much information, but we need just a table with characteristics (Figure 20):

clip_image006

Looking at this table we can note service UUIDs for Acceleration, Temperature and Pressure. It’s exactly that I am going to display in my application. Potentially we can check Free Fall, but I have just one board, and I will try to avoid any scary experiments.

Pay attention that Bluetooth LE standard contains some standard profiles that can help you recognize some standard services. Profiles, it’s something that operating system uses to connect any Bluetooth mouse or stream video/audio between different devices (not BLE, but the idea is the same). In some case you will need to rely on standard profiles, but in some cases, you can create your own. Looking at the table below you can see that our development board implements standard attribute and generic access profiles. Thanks to them Windows can read some information about the device like device name. But all other services implement custom profiles. It’s ok if your device is not going to support any standard feature and it can be a problem for you if you want to connect some low-cost Bluetooth devices to your application. I found that lots of devices from “no name” companies implement own custom profile and if you want to connect your phone or tablet to these devices you have to download an application. But once you want to create your own application, it’s really hard to find how the device works.

Ok. Now we know where to find information about supported services and characteristics, but we still didn’t finish our main page. So, let’s do it.

In order to store information about all available devices I will use a collection that will store references to DeviceInformation objects:

ObservableCollection<DeviceInformation> deviceList =
    new ObservableCollection<DeviceInformation>();

The collection should be observable because we are going to bind it to our interface and it should track any changes dynamically.

Now, we can modify our event handlers:

private async void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
    var toRemove = (from a in deviceList where a.Id == args.Id select a).FirstOrDefault();
    if (toRemove != null)
        await this.Dispatcher.RunAsync(
            Windows.UI.Core.CoreDispatcherPriority.Normal,
            () => { deviceList.Remove(toRemove); });
}
private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
    await this.Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        () => { deviceList.Add(args); });
}

You can see that we use the handlers to track changes in the list. Pay attention that both handlers are running in non-UI thread. So, we have to invoke dispatcher to modify our collection.

Finally, we can build UI. It will be primary a ListView that will display Id, Name and Pairing properties:

<ListView Grid.Row="2" Name="deviceListView" ItemsSource="{Binding}" IsItemClickEnabled="True" ItemClick="deviceListView_ItemClick" HorizontalAlignment="Center">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid Margin="10">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100"></ColumnDefinition> 
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <Image Source="Assets/stlogo.png" Margin="10" Grid.RowSpan="3"></Image>
                <TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding Id}"></TextBlock>
                <TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding Name}"></TextBlock>
                <StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal">
                    <TextBlock Text="Can be paired: "></TextBlock>
                    <TextBlock Text="{Binding Pairing, Converter={StaticResource pairingConv}, Mode=OneWay}"></TextBlock>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

To run this code, you need to add an empty event handler for ItemClick. We will implement it later. Additionally, you can use OnNavigatedTo to set DataContext property and activate binding:

this.DataContext = deviceList;

Running this code, we will see the following window:

clip_image008

Pay attention that our device is still not paired, but in order to start reading data from it we should not pair it. This feature is available since Windows 10 Creators Update. All previous UWP versions requires pairing prior start reading any data.

Ok. Now we can implement ItemClick event handler and once a user selects the device, we may navigate our application to the second page:

private void deviceListView_ItemClick(object sender, ItemClickEventArgs e)
{
    this.Frame.Navigate(typeof(DevicePage), e.ClickedItem);
}

In order to simplify work with all sensors I created a base class that implements all needed features to read values from characteristics:

public class SensorBase:IDisposable
{
    protected GattDeviceService deviceService;
    protected string sensorDataUuid;
    protected byte[] data;
    protected bool isNotificationSupported = false;
    private GattCharacteristic dataCharacteristic;
    public SensorBase(GattDeviceService dataService, string sensorDataUuid)
    {
        this.deviceService = dataService;
        this.sensorDataUuid = sensorDataUuid;
    }
    public virtual async Task EnableNotifications()
    {
        isNotificationSupported = true;
        dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync(
            new Guid(sensorDataUuid))).Characteristics[0];
        dataCharacteristic.ValueChanged += dataCharacteristic_ValueChanged;
        GattCommunicationStatus status =
            await dataCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
                GattClientCharacteristicConfigurationDescriptorValue.Notify);
    }
    public virtual async Task DisableNotifications()
    {
        isNotificationSupported = false;
        dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync(
            new Guid(sensorDataUuid))).Characteristics[0];
        dataCharacteristic.ValueChanged -= dataCharacteristic_ValueChanged;
        GattCommunicationStatus status =
            await dataCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
            GattClientCharacteristicConfigurationDescriptorValue.None);
    }
    protected async Task<byte[]> ReadValue()
    {
        if (!isNotificationSupported)
        {
            if (dataCharacteristic == null)
                dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync(
                    new Guid(sensorDataUuid))).Characteristics[0];
            GattReadResult readResult =
                await dataCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached);
            data = new byte[readResult.Value.Length]; 
            DataReader.FromBuffer(readResult.Value).ReadBytes(data); 
        }
        return data;
    }
    private void dataCharacteristic_ValueChanged(GattCharacteristic sender,
        GattValueChangedEventArgs args)
    {
        data = new byte[args.CharacteristicValue.Length];
        DataReader.FromBuffer(args.CharacteristicValue).ReadBytes(data);
    }
    public async void Dispose()
    {
        await DisableNotifications();
    }
}

In general, the most important method in this class is ReadValue, but BLE supports notification mechanism. From the GATT table, we can see that our board supports at least one sensor that allows us use notifications to receive updated data. This is accelerometer sensor. Of course, I could read data from accelerometer using just ReadValueAsync method, but I wanted to show how to use notifications. It’s not always true that your device will send updated data several time per second and in this case notifications allows to save some time, avoiding not needed queries. You can see that in order to enable notification for a characteristic we simply have to add a special descriptor using WriteClientCharacteristicConfigurationDescriptorAsync method. Once the descriptor is assigned, we will be able to receive messages with new values for the characteristic.

Using our base class, it’s not a problem to create three more classes that describe our sensors. Here is an example for the temperature sensor:

public class TemperatureSensor: SensorBase
{
    public TemperatureSensor(GattDeviceService dataService) :
        base(dataService, SensorUUIDs.UUID_ENV_TEMP) { }
    public async Task<double> GetTemperature()
    {
        byte[] data = await ReadValue();
        return ((double)BitConverter.ToInt16(data,0))/10;
    }
}

Pay attention that by default our sensors don’t use notification mechanism. So, if you want to enable notification for accelerometer, it’s needed to call EnableNotification method.

protected async void InitializeAccelerationSensor(GattDeviceService service)
{
    accSensor = new AccelerationSensor(service);
    await accSensor.EnableNotifications();
}

Finally, we can create a view model and bind it to our interface. I am not going to discuss all aspects of the view model, but want to concentrate your attention around couple methods. The first one is a method that initializes everything:

public async void StartReceivingData()
{
    leDevice = await BluetoothLEDevice.FromIdAsync(device.Id);
    string selector = "(System.DeviceInterface.Bluetooth.DeviceAddress:=\"" +
         leDevice.BluetoothAddress.ToString("X") + "\")";
    var services = await leDevice.GetGattServicesAsync();
    foreach (var service in services.Services)
    { 
        switch (service.Uuid.ToString())
        {
        case SensorUUIDs.UUID_ENV_SERV:
            InitializeTemperatureSensor(service); 
            InitializePressureSensor(service); 
            break;
        case SensorUUIDs.UUID_ACC_SERV:
            InitializeAccelerationSensor(service);
            break;
        }
    }
    timer.Interval = new TimeSpan(0, 0, 1);
    timer.Tick += Timer_Tick;
    timer.Start();
}

You can see that we simple list all available services and once we found needed service we initialize appropriate sensor. This code should work even if you select a wrong device from the list of all BLE devices. The user interface will simply display nothing. Because two of our characteristics don’t support notifications we will simply use a timer to update the UI once per second.

The second method is exactly Tick implementation. It simply read data from all available sensors (characteristics) and uses INotifyPropertyChanged to update bindings:

public async void UpdateAllData()
{
    if (tempSensor != null)
    {
        temperature = String.Format(
            $"{(await tempSensor.GetTemperature())} Celsius");
        if (PropertyChanged!=null)
            PropertyChanged(this,
                new PropertyChangedEventArgs("Temperature"));
    } 
    if (presSensor != null)
    {
        pressure = String.Format(
            $"{(await presSensor.GetPressure()).ToString()} milliBar");
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("Pressure"));
    }
    if (accSensor != null)
    {
        var data = await accSensor.GetAcceleration();
        angleX = data[0];
        angleY = data[1];
        angleZ = data[2];
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("AngleX"));
            PropertyChanged(this, new PropertyChangedEventArgs("AngleY"));
            PropertyChanged(this, new PropertyChangedEventArgs("AngleZ"));
        }
    }
}

Running our code, we will be able to see two tabs. On the first tab (Acceleration), you will be able to see data from the accelerometer:

clip_image010

The second tab provides information about temperature and pressure:

clip_image012

Now, you know how to connect your application to any BLE device and get data from there. At the same time, we didn’t pair out device. Let’s see, how to use Bluetooth API to implement pairing and get some benefits from there.

Written by Sergiy Baydachnyy

04/28/2017 at 4:10 AM

State triggers and Blend

leave a comment »

At last, Windows 10 is released and today developers have access to Visual Studio 2015 and Windows 10 SDK. I have already published some posts about Universal Windows Platform and Visual Studio 2015, and I promise lots of topics about it over next months; but today I want to drag your attention to Microsoft Blend 2015 tool which is included to Visual Studio installation.

Looks like Microsoft continues to invest in Blend and the latest release contains lots of new features. Today I want to talk about visual states editor new features.

In order to see the new features just create a new project in Blend and select MainPage.xaml in Solution Explorer. Once you do this, Objects and Timeline window will show structure of the page. Usually, when we create visual states we work with main container such as Grid. So, in order to create several visual states it’s better to select the root Grid element in Object and Timeline and States windows to start editing visual states.

Blend allows you to edit visual states without coding at all. With the help of the States window you can create as many states as needed, and once you select a state, Blend switches editor to Record mode (Ctrl+R). In this mode you can change properties of any user controls and all these changes will be included to the selected state automatically. So, I propose to create just one state using Add State button in States window and select the main grid to change some properties. For example, you can change Opacity and Visibility using Properties window.

clip_image002

If you open XAML document you can find the following code there:

<VisualState x:Name="Normal"> <VisualState.Setters> <Setter Target="grid.(UIElement.Opacity)" Value="0.5"/> <Setter Target="grid.(UIElement.Visibility)" Value="Collapsed"/> </VisualState.Setters> </VisualState>

So, you can see that Blend editor is fully integrated with the new approach that Universal Windows Platform implements thanks to Setter elements.

If you want to use the old approach or animate your properties from one state to another, you can continue to use the timeline and Blend will use animation instead of setters.

One more feature of Universal Windows Platform is state triggers, which allow you to move interface from one state to another without coding at all. UWP supports just AdaptiveTrigger but you can create your own triggers. Let’s see, how to use triggers in Blend.

I propose to add a class to the project which will have just one property but this class should be inherited from StateTriggerBase:

class MyTrigger: StateTriggerBase { public int State { get; set; } }

Of course, this class doesn’t have any sense because it does not have any logic inside but it’s enough to show it in Blend. Just recompile the application because Blend will look at assemblies.

Let’s try to apply the created trigger to one of the states using the States window. Pay attention that this window contains new button called edit adaptive triggers:

clip_image003

Just click the button for any state and Blend will show a dialog, which allows to select available triggers for the project:

clip_image005

Just select our trigger and Blend will allow you to initialize all public properties there (we have just one):

clip_image007

Enter any value there and click OK. Blend will generate the following code:

<VisualState.StateTriggers> <Code:MyTrigger State="10"/> </VisualState.StateTriggers>

Therefore, if you want to create a real adaptive interface and need to create lots of states and use many triggers, Microsoft Blend is the best tool for that.

Written by Sergiy Baydachnyy

09/07/2015 at 9:20 PM

UWP: New features of Launcher class

leave a comment »

In this post I want to discuss how to establish communications between Universal Windows Platform applications. It was a problem since Windows 8 because each application is running in its own sandbox without access to data of other applications. Of course, Windows 8.x supports several ways to invoke external applications and pass data to them. For example you could use share charm or use Launcher class. But all these methods have some disadvantages. Let’s look at Launcher class.

In Windows 8.x Launcher class allows to launch external applications based on Uri. The most common protocol for Uri is http and you can use it to launch browser but applications can register their own protocols for own needs. For example, in Windows 10 to invoke Settings window you can use ms-settings protocol and create Uri for Launcher class based on it:

await Launcher.LaunchUriAsync(new Uri("ms-settings:"));

You can see that in order to launch external application you should call LaunchUriAsync method which doesn’t allow to pass anything except Uri. If you need to pass some parameters to external application, you could use the same approach as for http protocol: get parameters in Uri. But if you need to pass file as a parameter you cannot make it using LaunchUriAsync. Frankly speaking, Launcher class supports LaunchFileAsync method but that method supports StorageFile as a parameter. So, you can not pass several files and you can not combine both methods (launch application using Uri and pass file at the same time). Even in order to pass file to a(??) third-party application it is required to register extensions of accepted files. Additionally, LaunchUriAsync and LaunchFileAsync don’t allow to control which application should be launched. If several applications register the same extension, user needs to select an application from the list. Finally, there was no way to understand if an application is launched and how to get some result back.

Let’s summarize all disadvantages, which Launcher class has in Windows 8.x:

· Allows to pass Uri or file using two different methods without a way to combine them;

· Doesn’t allow to pass several files;

· System might ask user to select an application from the list;

· There is no way to know if an external application is launched;

· There is no way to get response from an external application;

But in Universal Windows Platform, Microsoft made huge investment to Launcher class and today developers can avoid all mentioned disadvantages. Let’s see which changes were implemented there.

Look at the following code:

LauncherOptions options = new LauncherOptions() { TargetApplicationPackageFamilyName = "Microsoft.MicrosoftEdge_8wekyb3d8bbwe" }; await Launcher.LaunchUriAsync(new Uri("http://www.microsoft.com"), options);

When running this code we asked Launcher to launch an application which has defined application package name. This approach is very useful for corporate systems when you developed for customers more than one application. Using LauncherOptions you can guarantee that system will run exactly the application you need from your bunch of applications. Of course, you need to know the application family name but you can easily to find it using the Store:

clip_image002

Additionally, you can use FindUriSchemeHandlersAsync method of Launcher class to get information about all packages which accept the selected schema:

var res = await Launcher.FindUriSchemeHandlersAsync("http");

This method returns an array which contains all needed information including package name:

clip_image003

Of course, if package doesn’t exist in the system, LaunchUriAsync method will return false and you can ask users to install an additional application.

Launcher class contains one more method, QueryUriSupportAsync, which allows to get information if selected Uri is supported in the system:

var res = await Launcher.QueryUriSupportAsync(new Uri("http://www.microsoft.com"), LaunchQuerySupportType.Uri);

This method doesn’t return any information about external applications but allows to check if you can run an application using a passed Uri. And what is more important, this method allows to check result using package family name and even to understand if external application can return a response.

I would like to note that you can use the same bunch of methods for open files using external applications: LaunchFileAsync, FindFileHandlersAsync, QueryFileSupportAsync. Of course, these methods don’t resolve the problem with multiply files but UWP brings an opportunity to use LaunchUriAsync method for passing several files (references) as parameters. Let’s see how to implement it.

The idea is in using of SharedStorageAccessManager class. Thanks to this class you can share files between applications using tokens.

var token=SharedStorageAccessManager.AddFile(myfile);

Because token is a string, you can use it as a parameter in Uri. So, you should not pass any IStorageFile objects or anything special – just the same Uri. And it is possible to create as many tokens as needed.

External application can redeem tokens and get access to IStorageFile objects:

string myFileToken = queryStrings.GetFirstValueByName("GpxFile"); if (!string.IsNullOrEmpty(myFileToken)) { StorageFile file=await SharedStorageAccessManager.RedeemTokenForFileAsync(myFileToken)); }

Once the token is redeemed nobody can redeem the token once again. But the token may live for 14 days. So, if the application discovers a problem with launching of an external application, there is a way to delete token from the list using RemoveFile method.

Of course, in case of file token it’s easy to include tokens to Uri but you can pass any serializable objects what you want. In order to do it you can use ValueSet class , which is a dictionary of serializable objects. Developers can use it to pass tokens as well but it’s possible to pass anything:

ValueSet v = new ValueSet(); v.Add("token1", token); var f = await Launcher.LaunchUriAsync(myUri, options, v);

Finally, Launcher class allows to launch Uri for results. Imagine an application for making a payment. You can use this application as external method to make payments inside your own application but you need to get information from external one if payment is processed and, probably, some information to check if payment is received. In Windows 10 you can implement it using LaunchUriForResultsAsync method. This method has the same parameter list like LaunchUriAsync but it returns LaunchUriResult object instead of bool and you can use this object to see status and get results if launch was succeeded.

var result = await Windows.System.Launcher.LaunchUriForResultsAsync(myUri, options, inputData); if (result.Status == LaunchUriStatus.Success) { ValueSet theValues = result.Result; //do something here }

Therefore, all Windows 8.x problems with Launcher class are gone and today you have a great way to make communications between different applications.

Written by Sergiy Baydachnyy

09/03/2015 at 9:22 PM

UWP: Clipboard

leave a comment »

Starting with Windows 10 you can implement clipboard operations not just for desktop but also for all Windows 10 devices.

I already published the post about Drag and Drop functionality where we used DataPackage class in order to prepare data for sending to external applications and DataPackageView class to get data which was dragged from external source. In case of Clipboard we need to use the same approach but instead of event handlers we should implement content menus with standard commands there.

Let’s see how to implement Paste functionality. I am going to use the same application which I used in Drag and Drop post because we can use the same code. I am going to allow Paste feature for images, so I will show images in ListView and I need to implement a simple MenuFlyout:

<ListView Margin="50" Name="listView" RightTapped="listView_RightTapped" IsRightTapEnabled="True"> <ListView.Resources> <MenuFlyout x:Name="menuFlyout"> <MenuFlyout.Items> <MenuFlyoutItem Name="pasteItem" Text="Paste" Click="MenuFlyoutItem_Click"></MenuFlyoutItem> </MenuFlyout.Items> </MenuFlyout> </ListView.Resources> <ListView.ItemTemplate> <DataTemplate> <Grid> <Image Source="{Binding Source}" Width="200" Margin="10"></Image> </Grid> </DataTemplate> </ListView.ItemTemplate> </ListView>

You can see that I declared MenuFlyout like a resource of ListView. MenuFlyout class doesn’t allow to show menu automatically. So, I allowed right click for my ListView and implemented RightTapped event handler in the following way:

private async void listView_RightTapped(object sender, RightTappedRoutedEventArgs e) { var format = Clipboard.GetContent().Contains("FileDrop"); pasteItem.IsEnabled = format; menuFlyout.ShowAt(listView, e.GetPosition(null)); }

In order to implement a better UX I check if any files are available and enable or disable menu item.

Finally, if user selects Paste menu item I use Clipboard class in order to get all available files and prepare them to show in ListView:

private async void MenuFlyoutItem_Click(object sender, RoutedEventArgs e) { var files = await Clipboard.GetContent().GetStorageItemsAsync(); List<BitmapItem> items = new List<BitmapItem>(); foreach (StorageFile file in files) { try { BitmapImage bi = new BitmapImage(); bi.SetSource(await file.OpenAsync(FileAccessMode.Read)); items.Add(new BitmapItem() { Source = bi }); } catch { } } listView.ItemsSource = items; }

You can see that we used the same code like in the Drag and Drop post. We changed just the first line of code – we used Clipboard class to get DataPackageView.

Therefore you can see that Drag and Drop and clipboard features are better to implement together because you can use the same approach and these features are now universal.

Written by Sergiy Baydachnyy

09/03/2015 at 9:16 PM

UWP: How to implement Drag and Drop functionality

leave a comment »

One more new feature, which is available for Windows 10 developers, is Drag and Drop support. Starting with Windows 10 you can implement Drag and Drop functionality between UI parts of your application or use external sources/targets including Win 32 applications.

Let’s start with Drag operation. In order to show how Drag operation works, I simply added an image from the application package to the main page.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Image Source="Assets\drone.jpg" Name="image" CanDrag="True" DragStarting="Image_DragStarting" Margin="100" VerticalAlignment="Top" HorizontalAlignment="Left"></Image> </Grid>

You can see two important attributes there that activate Drag operation: CanDrag and DragStarting. CanDrag attribute is just a flag which enables the feature for all UIElement controls but DragStaring attribute contains name for event handler. Thanks to this event handler you can define any content to drag. In my case I implemented the following handler:

private async void Image_DragStarting(UIElement sender, DragStartingEventArgs args) { List<IStorageItem> files = new List<IStorageItem>(); StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/drone.jpg")); files.Add(file); args.DragUI.SetContentFromDataPackage(); args.Data.RequestedOperation = DataPackageOperation.Copy; args.Data.SetStorageItems(files); }

In this event handler I used StorageFile class in order to pass my image like a file and thanks to Data property of DragStartingEventArgs parameter I packaged the file to the object of DataPackage class. DataPackage class is very popular among different features in Universal Windows Platform and usually you need to pass it to the operation system and OS allows to select the target application. But in case of Drag functionality user selects the target directly. So, we just need to prepare the DataPackage and that’s all.

Additionally I used two important properties there: DragUI and RequestedOperation. Thanks to the RequestedOperation I can assign the right operation and user should not be able to select anything from system menu – just drag and drop. Thanks to DragUI I can apply the content which will be shown during Drag operation. If you don’t use DragUI property, user will see the same image with the same width and height like in your application. It’s not very cozy to drag a huge image especially if you don’t use RequestedOperation – the system menu will be behind the image. That’s why you can assign any other content using DragUI or use SetContentFromDataPackage method in order to ask API to prepare appropriate icon for you based on content in DataPackage.

Just run the application and drag and drop the image to the file explorer – image will be copied to the selected folder.

Let’s see how to implement an opposite task – Drop functionality. I want to accept several images. So, I am going to use ListView in order to show my items.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" AllowDrop="True" Drop="Grid_Drop" DragEnter="Grid_DragEnter"> <ListView Margin="50" Name="listView"> <ListView.ItemTemplate> <DataTemplate> <Grid> <Image Source="{Binding Source}" Width="200" Margin="10"></Image> </Grid> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid>

You can see that I am using AllowDrop to activate the Drop functionality, DragEnter – to setup allowed operations (Copy) and Drop – to get content from DataPackage and show it using ListView.

In order to create items source for images I created BitmapItem class:

class BitmapItem { public ImageSource Source { get; set; } }

In the next step I implemented DragEnter event handler in order to notify the system about supported operations.

private void Grid_DragEnter(object sender, DragEventArgs e) { e.AcceptedOperation = DataPackageOperation.Copy; }

Finally, I am using DataPackageView in order to get reference to the content. DataPackageView can contain anything but I want to work with files only, so I call GetStorageItemsAsync in order to get references to files there and use BitmapImage to prepare the image files for Image objects.

private async void Grid_Drop(object sender, DragEventArgs e) { var files=await e.DataView.GetStorageItemsAsync(); List<BitmapItem> items = new List<BitmapItem>(); foreach(StorageFile file in files) { try { BitmapImage bi = new BitmapImage(); bi.SetSource(await file.OpenAsync(FileAccessMode.Read)); items.Add(new BitmapItem() { Source = bi }); } catch { } } listView.ItemsSource = items; }

I am too lazy, so I decided to avoid any checking – I simply use empty catch block if user passed non-image file(s).

That’s all. You can see that it’s easy to implement Drag and Drop functionality and you can make experiments with different content types there or implement the same functionality inside the same application (drag and drop content from one part of application to another).

Written by Sergiy Baydachnyy

08/25/2015 at 10:33 PM

Live Visual Tree in Visual Studio

leave a comment »

In this post I am going to talk about a cool tool in Visual Studio – Live Visual Tree. This tool is available for Store and WPF applications including Store applications for Windows 8.x.

Live Visual Tree allows to observe XAML visual tree in runtime, review properties of elements there and even change properties in runtime in order to check how changes will affect interface without restarting application itself. There are lots of scenarios when you need to use a tool like this and I have already adopted this tool for the following tasks:

· If you have a huge number of visual states in your interface it’s really hard to understand while a state is not fired. Thanks to Live Visual Tree you can check properties of all controls and see what happens applying changes to these properties – check if a state is applied and how the result looks like;

· Visual designer in Visual Studio works fine but if you have lots of bindings you can use Live Visual Tree to change something in runtime and see how it affects the design of the running application with active bindings and data there;

· Live Visual Tree allows to visualize layout in order to show alignments and space for UI elements. It allows to find some mistakes which you cannot find in design mode due to absence of real data;

· Checking count of elements in each container you can find potential problem with performance;

· Live Visual Tree allows to check XAML tree not just for your applications – you can easily attach debugger to any running “XAML application” and see XAML visual tree there and apply any changes in the same way;

In order to open the Live Visual Tree window for your application you need to run your application in the Debug Mode and you can find the Live Visual Tree using Debug->Windows menu item. The second window, which is associated with the Live Visual Tree, is Live Property Explorer. Using the Live Visual Tree you can navigate between XAML elements and using Live Property Explorer you can check, change and create properties there.

clip_image002

You can see that Live Visual Tree provides information about number of XAML elements inside each container. Pay special attention that you can see elements from XAML visual tree only. So, Live Visual Tree contains visible elements only, and if interface changes from one state to another you can see that Live Visual Tree is changing in runtime.

Live Property Explorer shows default values for properties, values which were inherited from other controls and local values of control properties itself. Of course, you can modify local values only. If a value has been assigned to a property previously you can modify it but you can add any other available properties and assign values to them as well.

In Live Visual Tree window you can find two useful buttons. The first one allows to select any element in the running application in order to find it in the XAML tree. It’s very useful when you want to locate a place of a button and other controls that have tap event handler. The second one allows to visualize layout. Once you select any element you will be able to see layout there.

As I mentioned earlier you can attach Visual Studio to any existing “XAML window”. For example, you can run the settings window and select Attach to Process in Debug menu of Visual Studio 2015. In the Attach to Process dialog select SystemSettings process and you will be able to see the structure of the window. You even can change current settings and check layout of the window.

clip_image004

So, Live Visual Tree is a very powerful tool which can help to make your application better.

Written by Sergiy Baydachnyy

08/11/2015 at 9:41 PM

Win2D: How to use graphics without knowledge in DirectX

with one comment

Direct2D is a very good technology but using of it requires some knowledge in DirectX. Yes, DirectX is cool but lots of developers who build business applications have never used DirectX in their entire life. That’s why many of them ask about Direct2D features like about a separate Windows Runtime API, which is ready for non-game developers. Win2D is such an API.

Win2D is a Windows Runtime API which is available for C++ and C# developers and brings GPU optimized 2D graphic to Windows 8.x/Windows 10 XAML applications.

The best way to start working with Win2D is to visit Win2D Team Blog where you can find links to the documentation, sample code, source code (Win2D is an open source project) etc. But if you want to understand the full power of Win2D it is better to start develop something using this API. So, let’s look at some useful classes there and learn how to start developing with Win2D.

Since Win2D is an open source project and is not a part of Universal Windows Platform by default, you need to use NuGet package manager to add the latest version of Win2D libraries (use Win2D.uwp).

clip_image002

NuGet will add a reference to Microsoft.Graphics.Canvas assembly what contains all Win2D classes. So, it’s easy to open this assembly and find all namespaces and classes at the same place.

clip_image003

Just open Microsoft.Graphics.Canvas.UI.Xaml namespace and find all XAML controls there. You can see that there are two classes based on UserControl: CanvasAnimatedControl and CanvasControl. Additionally, there is CanvasSwapChainPanel class which is derived from Grid class. Let’s see these classes in more details.

First of all you need to add Microsoft.Graphics.Canvas.UI.Xaml namespace to your XAML file:

xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"

Right after that you can use the controls there and we will start with the simplest one, CanvasControl.

<canvas:CanvasControl Draw="CanvasControl_Draw"></canvas:CanvasControl>

CanvasControl is a place for drawing but we need some places to implement drawing algorithms. That’s why CanvasControl has two important events: Draw and CreateResources. Let’s start with Draw event and look at the code below:

int i = 0; private void CanvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { i++; CanvasTextFormat format = new CanvasTextFormat() { FontSize = 96, FontWeight = FontWeights.Bold }; args.DrawingSession.DrawText($"Hello {i}", 200, 100, Colors.Green, format); }

In this event handler we used DrawText method to print text. You can find lots of different methods inside CanvasDrawingSession class and it’s easy to use. Pay special attention that I injected integer variable to the output string. Thanks to this variable we can see when our event handler works. Just run the application and try to work with the window for some time. You will see that Draw event fires when it’s needed for Windows to redraw the window. So, if you change window size your counter will increase but if you don’t touch widow at all the counter will remain the same.

clip_image005

That’s why CanvasControl works fine for “static” content.

The second important event for CanvasControl is CreateResources event. Let’s look at our code again and you can see that the application creates CanvasTextFormat object each time when Draw event handler is invoked. Of course, this object is not very complex but in case of real scenarios developers need to make lots of objects first before they can start drawing and additionally developers should guarantee that all objects will be created before event handler is invoked. There are two ways to initialize all needed objects: assign Draw event handler dynamically (right after initialization methods) or use CreateResources event handler. The second method is more straightforward and implements some stuff for asynchronous programming.

Let’s modify our XAML page:

<canvas:CanvasControl Draw="CanvasControl_Draw" CreateResources="CanvasControl_CreateResources"></canvas:CanvasControl>

And here is code:

CanvasLinearGradientBrush brush; CanvasTextFormat format; private void CanvasControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { brush = new CanvasLinearGradientBrush(sender, Colors.Red, Colors.Green); brush.StartPoint = new Vector2(50, 50); brush.EndPoint = new Vector2(300, 300); format = new CanvasTextFormat() { FontSize = 96, FontWeight = FontWeights.Bold }; } int i = 0; private void CanvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { i++; args.DrawingSession.DrawText($"Hello {i}", 50, 50, brush, format); }

You can see that I used CanvasControl_CreateResources method to make a brush for my text.

clip_image007

Using CreateResource event handler you can guarantee that Draw event will not be fired up to the event handler is completed.

In the previous example we used synchronous event handler for CreateResource method but even for simple image loading action you need to call asynchronous APIs. Of course advanced C# developers will add async keyword before the event handler signature but this approach doesn’t work for CreateResources event handler. Instead of async keyword you should use the following approach:

CanvasImageBrush brush; CanvasTextFormat format; private void CanvasControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResources(sender).AsAsyncAction()); } async Task CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender) { brush = new CanvasImageBrush(sender); brush.Image= await CanvasBitmap.LoadAsync(sender, "Assets/drone.jpg"); format = new CanvasTextFormat() { FontSize = 96, FontWeight = FontWeights.Bold }; } int i = 0; private void CanvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { i++; args.DrawingSession.DrawText($"Hello {i}", 50, 50, brush, format); }

You can see that we used parameter of event handler to call TrackAsyncAction method and this method can get async method as a parameter.

Ok. Thanks to CanvasControl we can draw “static” content and it’s fine for many scenarios. For example, you can use this control to apply effects to images, you can create graphs or high performance text rendering application. But you cannot use CanvasControl for developing simple 2D games or similar applications which should present “dynamic” content. In order to make it, Win2D provides another control: CanvasAnimatedControl.

We can use almost the same code, slightly modifying it:

<canvas:CanvasAnimatedControl Draw="CanvasAnimatedControl_Draw" CreateResources="CanvasAnimatedControl_CreateResources"></canvas:CanvasAnimatedControl> CanvasImageBrush brush; CanvasTextFormat format; async Task CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender) { brush = new CanvasImageBrush(sender); brush.Image= await CanvasBitmap.LoadAsync(sender, "Assets/drone.jpg"); format = new CanvasTextFormat() { FontSize = 96, FontWeight = FontWeights.Bold }; } int i = 0; private void CanvasAnimatedControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args) { i++; args.DrawingSession.DrawText($"Hello {i}", 50, 50, brush, format); } private void CanvasAnimatedControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResources(sender).AsAsyncAction()); }

You can see the same text but counter will increase very fast (every 16.6 ms or 60 steps per second). So, CanvasAnimatedControl is better to create a large number of dynamic objects that are flying, firing, jumping etc. Of course, it’s not enough to have just Draw method because in real games you need to guarantee timing and have the same speed on all devices. So, a game loop is more complex than a simple Draw method. But developers of Win2D know about it and you can find some more events and useful properties in CanvasAnimatedControl class.

Let’s review those properties and events slightly modifying the previous Draw even handler:

private void CanvasAnimatedControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args) { i++; args.DrawingSession.DrawText($"Hello {i}", 50, 50, brush, format); sender.Paused = true; }

You can see that we used Paused property to make pause in our game loop. And if you don’t touch the application you can see that the counter is frozen but once you resize the window the counter will grow fast. It happens because in the pause mode draw method is called once Windows needs to redraw the window. So, it’s better to use Draw event handler only for drawing. If you need to change any data in the game loop then it is better to use Update event. Update event handler will be called before Draw method and in case of pause Update event handler will be frozen.

private void CanvasAnimatedControl_Update(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedUpdateEventArgs args) { i++; }

In general, Draw+Update event handlers should be called every 16.6 ms but if you have a slow device and running timeframe is greater, Update call may be passed. So, you can see several Draw calls before Update call. It allows saving same speed of the game but you can see some drawing problems. If it happens not very often it’s not very critical but in some cases you can decrease the elapsed time for each step (for example, 30 frames per second). You can easily do it using TargetElapsedTime property.

Additionally, you can use events like GameLoopStarting and GameLoopStopped. These events fire before and after the game loop and can be used for scene initialization and for destroying all objects from memory respectively.

Pay special attention that all event handlers fire in separate gaming loop. So, any actions there will not block interface thread. But developers should think how to pass the data to the gaming thread from the interface one. The best way is calling RunOnGameLoopThreadAsync method from the interface thread:

await myCanvas.RunOnGameLoopThreadAsync(()=> {/*call something here*/});

The last control in Microsoft.Graphics.Canvas.UI.Xaml namespace is CanvasSwapChainPanel. If you know something about game development you should have heard about the swap chains. The main idea is have two or more buffers (pages) for your game. The first page you use for presenting an updated scene on the screen while updating the second one behind the scene. You should not use CanvasSwapChainPanel class or CanvasSwapChain with CanvasAnimatedControl because the last one uses swap chains internally. But if you want to implement your own CanvasAnimatedControl or a similar control you can use both classes.

var swapChain = new CanvasSwapChain(device, width, height, dpi); swapChainPanel.SwapChain = swapChain; //draw swapChain.Present();

Ok, right now we have some knowledge how to draw something and what are the differences between controls there. So, it’s time to talk about other useful classes and I am going to start with image effects.

Image effect is the most growing category in Win2D and just several days ago they added 10 more effects but we are still waiting for some classes, which help to create our own custom effects. In any case Win2D API already contains more than 50 effects, so, you definitely can find some useful filters there. Here is an example how to apply two effects to the same image:

GrayscaleEffect effect; GaussianBlurEffect blurEffect; async Task CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender) { effect = new GrayscaleEffect(); var bitmap=await CanvasBitmap.LoadAsync(sender, "Assets/drone.jpg"); effect.Source = bitmap; blurEffect = new GaussianBlurEffect(); blurEffect.BlurAmount = 5; blurEffect.Source = effect; } private void myCanvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { args.DrawingSession.DrawImage(blurEffect); } private void myCanvas_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResources(sender).AsAsyncAction()); }

In this example I used blur and grayscale filters. Since I don’t have any other logic I used CreateResources event handler.

clip_image009

If you use the same effect for the same image you can simply apply this effect in advance and reuse it later. But in many cases you need to build more complex objects which should contain not just effect but some drawing etc. In this case you can use CanvasCommandList class in order to prepare and preserve your object for future use. I just slightly modified the previous example:

GrayscaleEffect effect; GaussianBlurEffect blurEffect; CanvasCommandList cl; async Task CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender) { cl = new CanvasCommandList(sender); using (CanvasDrawingSession clds = cl.CreateDrawingSession()) { effect = new GrayscaleEffect(); var bitmap = await CanvasBitmap.LoadAsync(sender, "Assets/drone.jpg"); effect.Source = bitmap; blurEffect = new GaussianBlurEffect(); blurEffect.BlurAmount = 5; blurEffect.Source = effect; clds.DrawImage(blurEffect); } } private void myCanvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { args.DrawingSession.DrawImage(cl); } private void myCanvas_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResources(sender).AsAsyncAction()); }

In this example we created our own CanvasDrawingSession and used it to draw all needed objects and to apply filters there. Right after that we destroyed CanvasDrawingSession and preserved CanvasCommandList for future use (making global reference on it). Thanks to this approach you can create all complex objects in advance and later draw them as images.

When I told about image effects I didn’t mention geometry and text but you can apply effects to these entities as well. In order to do in you need to use CanvasRenderTarget class for converting vector data to pixels:

private void myCanvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { var myBitmap = new CanvasRenderTarget(sender, 300, 300); using (var ds = myBitmap.CreateDrawingSession()) { ds.DrawText("Hello", 0, 0, Colors.Green, new CanvasTextFormat() {FontSize=96, FontWeight=FontWeights.Bold }); } var blur = new GaussianBlurEffect { BlurAmount = 10, Source = myBitmap }; args.DrawingSession.DrawImage(blur); }

Running this code you will see the following window:

clip_image011

I think this is enough for the first look at Win2D. I missed lots of classes that help to work outside XAML or allow working with images pixel by pixel but I hope that it’s easy to understand using documentation because Win2D is easy.

Written by Sergiy Baydachnyy

08/04/2015 at 1:40 AM