<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Canadian Developer Connection</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/cdndevs/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/cdndevs/feed.xml</link>
    <description>The latest developer news and events in Canada!</description>
    <lastBuildDate>Wed, 13 Sep 2017 21:29:57 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>How to cook Azure Mobile Apps (node.js): “50 records” limit and lazy loading</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/how-to-cook-azure-mobile-apps-node-js-50-records-limit-and-lazy-loading</link>
      <pubDate>Wed, 13 Sep 2017 21:29:55 GMT</pubDate>
      <dc:creator><![CDATA[Sergiy Baydachnyy]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=27485</guid>
      <description><![CDATA[Code is available here: https://github.com/sbaidachni/XamarinMobileAppsDemo

In the previous posts...]]></description>
      <content:encoded><![CDATA[<p align="justify"><i>Code is available here: <a href="https://github.com/sbaidachni/XamarinMobileAppsDemo">https://github.com/sbaidachni/XamarinMobileAppsDemo</a></i></p>

<p align="justify">In the previous posts we discussed how to create and setup node.js Azure Mobile Apps backend and how to start using .NET Standard libraries with Xamarin applications. Now, I am waiting for my next flight, and it’s time to build a basic interface using Xamarin.Forms.</p>

<p align="justify">I am going to work with records from the SalesLT.Product table. So, I need to make sure that my backend contains the <b>MS_TableSchema</b> application setting with the SalesLT value there, and my Product.json file contains <b>autoIncrement</b> property in <b>true</b> due to integer primary key there. </p>

<p align="justify">But there is one more problem: as we discussed in the first post, Azure Mobile Apps (node.js) service requires <b>id</b> name for the primary key rather than <b>ProductID</b>. In general, it’s not easy to change any column name, and even in our simplest case, we cannot do it using just <b>sp_rename</b>. You will be able to see that the database contains lots of dependencies to <b>ProductID</b>. So, I would recommend to create a new view rather than redesign the whole database. We will be able to work with the view like with the table, and we will be able to define new names for our columns. </p>
<font style="font-size: 12pt"></font><font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><font style="font-size: 7pt">CREATE</font></span><font style="font-size: 7pt"><span> </span><span>VIEW</span><span> [SalesLT]</span><span>.</span></font><span><font style="font-size: 7pt">[vProductList]</font></span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><font style="font-size: 7pt">WITH</font></span><font style="font-size: 7pt"><span> </span></font><span><font style="font-size: 7pt">SCHEMABINDING</font></span><span></span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><font style="font-size: 7pt">AS</font></span><span></span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><font style="font-size: 7pt">SELECT</font></span><span></span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><b><span><span><font style="font-size: 7pt">&nbsp;&nbsp;&nbsp; </font></span><font style="font-size: 7pt">p</font></span></b><font style="font-size: 7pt"><b><span>.</span></b><b><span>[ProductID] </span></b><b><span>as</span></b><b><span> id</span></b></font><b><span><font style="font-size: 7pt">,</font></span></b><b><span></span></b></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><span><font style="font-size: 7pt">&nbsp;&nbsp;&nbsp; </font></span><font style="font-size: 7pt">p</font></span><font style="font-size: 7pt"><span>.</span><span>[Name]</span></font><span><font style="font-size: 7pt">,</font></span><span></span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><font style="font-size: 7pt"></font></span><span>. . . . .</span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><span><font style="font-size: 7pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span><font style="font-size: 7pt">p</font></span><font style="font-size: 7pt"><span>.</span><span>version</span></font><span><font style="font-size: 7pt">,</font></span><span></span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><span><font style="font-size: 7pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span><font style="font-size: 7pt">p</font></span><font style="font-size: 7pt"><span>.</span><span>createdAt</span></font><span><font style="font-size: 7pt">,</font></span><span></span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><font style="font-size: 7pt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.</span><span>updatedAt</span></font><span><font style="font-size: 7pt">,</font></span><span></span></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span><font style="font-size: 7pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p</font></span><font style="font-size: 7pt"><span>.</span></font><span><font style="font-size: 7pt">deleted</font></span></p>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><span></span><span style="line-height: 7pt"><font style="font-size: 7pt">FROM</font></span><font style="font-size: 7pt"><span style="line-height: 7pt"> [SalesLT]</span><span style="line-height: 7pt">.</span></font><span style="line-height: 7pt"><font style="font-size: 7pt">[Product] p</font></span></p>
<font style="font-size: 12pt"></font>

<p align="justify">Prior to create the view, you have to make sure that <b>SalesLT.Product</b> already contains <b>version</b>,<b>createdAt</b>, <b>updatedAt</b> and <b>deleted</b> columns. You can simply create Product.json and Product.js in your backend environment to force the framework to create these columns for you and after that you can rename Product.js and Product.json to vProductList. Once you finish, you will be able to use Easy Tables functionality and review your data in the portal:</p>

<p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/09/clip_image00210.jpg"><img width="244" height="67" title="clip_image002" style="margin: 0px" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/2017/09/clip_image002_thumb10.jpg" border="0"></a></p>

<p align="justify">Of course, if you create any additional column in the view, you will fail because views don’t allow you to alter associated tables.</p>

<p align="justify">Let’s go back to our Xamarin application and implement something simple.</p>

<p align="justify">I will not implement a really perfect MVVM approach, but we will need to create some classes in any case. First of all, we need to create a class that will represent our table. It’s exactly a model and we will implement all needed properties there. You can manage name-column relationships using attributes, but if you use identical to your db names in your class, you have to do almost nothing. So, you can find my class below:</p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><a href="https://github.com/sbaidachni/XamarinMobileAppsDemo/blob/master/Xamarin_MobileApps_STD/Models/vProductList.cs">vProductList.cs</a></p>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"></p>
<font style="font-size: 12pt"></font>

<p align="justify"><br></p><p align="justify">You can see that I used vProductList as a class name and Id, Name, ProductNumber, Color and Size are my columns from the table.</p>

<p align="justify">Now, we need to implement a view-model class that will prepare all data to show UI. I am going to use an <b>ObservableCollection</b> to store our items to make sure that our UI will be updated automatically in the case of new items there. I am using the singleton approach to make sure that we have just one view-model in time and I will implement the Product class that will satisfy our needs better, compare to our vProductList. Of course, the Product class doesn’t have any specific things now, but later we will be able to add some UI-related features to it.</p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><a href="https://github.com/sbaidachni/XamarinMobileAppsDemo/blob/master/Xamarin_MobileApps_STD/ViewModels/MainPageViewModel.cs">MainPageViewModel.cs</a></p>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"></p>
<font style="font-size: 12pt"></font>

<p align="justify"><br></p><p align="justify">You can see that we use <b>MobileServiceClient</b> class to get a reference to our service, and once we need some data, I am using <b>ToListAsync</b> to download everything. At the same time you can find that I am using a strange property RecordCounts. It’s still not clear why I need it, but later we will be able to see why it’s important if you want to show all data from your table.</p>

<p align="justify">Let’s implement our UI:</p>

<p align="justify"><a href="https://github.com/sbaidachni/XamarinMobileAppsDemo/blob/master/Xamarin_MobileApps_STD/MainPage.xaml">MainPage.xaml</a></p>
<font style="font-size: 12pt"></font>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal">You can see that there is a ListView that just displays Id and Name fields from the table. Additionally, there is a label that shows number of records that we just downloaded.</p>

<p align="justify">Below you can find associated with the UI code:</p>

<p class="MsoNormal" style="margin: 0mm 0mm 0pt;line-height: normal"><a href="https://github.com/sbaidachni/XamarinMobileAppsDemo/blob/master/Xamarin_MobileApps_STD/MainPage.xaml.cs">MainPage.xaml.cs</a></p>
<font style="font-size: 12pt"></font>

<p align="justify"><br></p><p align="justify">We are just getting a reference to our view-model and download data once our UI is appearing.</p>

<p align="justify">Let’s start our application and you will be able to see that the UI displays just 50 records:</p>

<p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/09/clip_image00414.jpg"><img width="244" height="158" title="clip_image004" style="margin: 0px" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/2017/09/clip_image004_thumb12.jpg" border="0"></a></p>

<p align="justify">It’s happened because node.js implementation doesn’t allow you to get all records. By default, you can get just 50 records, but there is the <b>pageSize</b> parameter that you can provide in your app.js file. </p>

<p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/09/clip_image00613.jpg"><img width="244" height="66" title="clip_image006" style="margin: 0px 5px" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/2017/09/clip_image006_thumb10.jpg" border="0"></a></p>

<p align="justify">In any case, if you change the parameter, you will be able to download fixed number of records only. That’s why we need to implement something on the client side to display everything.</p>

<p align="justify">In order to do it we can use <b>ItemAppearing</b> event handler for our <b>ListView</b>. The <b>ItemAppearing</b> event fires for every item before it will be displayed. We cannot guarantee exactly when, be it will fire in advance. So, we can use this event to download more and more records, implementing some sort of lazy loading approach. Just look at the following code:</p>
<font style="font-size: 12pt"></font><font style="font-size: 12pt"></font>

<p>protected async void ListView_ItemsAppearing(object sender, ItemVisibilityEventArgs e)</p>

<p>{</p>

<p>var itemTypeObject = e.Item as Product;</p>

<p>if (model.Items.Last() == itemTypeObject)</p>

<p>{</p>

<p>await model.LoadDataAsync();</p>

<p>}</p>

<p>}</p>
<font style="font-size: 12pt"></font>

<p align="justify">You can see that if <b>ItemAppearing</b> fires for the last element in the list, we will be able to download more. The most important thing there that if <b>ListView</b> implements <b>RecycleElement</b> caching strategy, we will download more elements just if a user scrolls the list far enough. </p>

<p align="justify">If you run the application, you will be able to see that there 100 or 150 records in the list (depends on your monitor and other parameters), but once you start scrolling down, the list will download more and more items (by 50 records in our case).</p>

<p align="justify">So, now you know how to deal with big table and aware about “50 records” limit. Next time we will discuss how to implement continues integration with GitHub.</p>]]></content:encoded>
    </item>
    <item>
      <title>How to cook Azure Mobile Apps (node.js): Xamarin and .NET Standard</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/how-to-cook-azure-mobile-apps-node-js-xamarin-and-net-standard</link>
      <pubDate>Wed, 30 Aug 2017 05:07:33 GMT</pubDate>
      <dc:creator><![CDATA[Sergiy Baydachnyy]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=27417</guid>
      <description><![CDATA[In the previous post we discussed how to setup Mobile Apps in node.js, and it’s time to start...]]></description>
      <content:encoded><![CDATA[<p align="justify">In the previous post we discussed how to setup Mobile Apps in node.js, and it’s time to start developing a simple client application. I will use Xamarin and C# programming language, because Xamarin is the coolest technology right now that allows me to develop applications for all modern devices. </p> <p align="justify">My application is not very complex, so, I will use Xamarin forms to develop it just once for all platforms not digging to any platform specific features. </p> <p align="justify">You can create your application on Mac or Windows using Visual Studio for Mac or Visual Studio 2017 (2015). In my case I am sitting at Kelowna airport with my Windows computer, so, I will use Visual Studio 2017 Update 3. </p> <p align="justify">Pay attention that Visual Studio allows you to create Xamarin Forms application using Shared Project or PCL templates. It’s strange, but Shared Project is the default option, and I would like to recommend changing it to PCL. Later, you will be able to use .NET Standard rather than PCL just moving your code to a .NET Standard library project.</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image00217.jpg"><img title="clip_image002" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image002_thumb15.jpg" width="244" height="136"></a></p> <p align="justify">Visual Studio creates 4 projects in one solution and three of these projects contain platform-specific code for supported platforms (iOS, Android and UWP), but the last one is exactly Xamarin.Forms based portable class library. Almost all time we will work with this library, but on the first step we need to add a reference to Mobile Apps SDK for each of our projects. Therefore, I would recommend to select <b>Manage NuGet Packages</b> for the solution rather than for a particular project and find <b>Microsoft.Azure.Mobile.Client</b> library:</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image00422.jpg"><img title="clip_image004" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image004_thumb16.jpg" width="244" height="104"></a></p> <p align="justify">The process is not complicated, but there is a surprise: we will not be able to install the latest version of the library exactly to Xamarin.Forms project:</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image00614.jpg"><img title="clip_image006" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image006_thumb13.jpg" width="244" height="29"></a></p> <p align="justify">The latest version supports .NET Standard (at least 1.4) and we can easy add it to our Android, iOS or UWP applications (because Xamarin added support for it some time ago), but you cannot add it to your PCL (Xamarin.Forms part). Of course, you can say that I could avoid this problem using <b>Shared Project</b> approach. Yes, I could do it as well as I could create lots of “spaghetti” #if #else code and got a problem with IntelliSense and so on, but I want to stay with “a separate library” approach and there are several ways to fix the problem:</p> <p align="justify">· I will start with some suicidal ways like: you can use REST API directly. It’s really great way to increase your income if anybody pays you for number of code lines, but in my case, it’s not true;</p> <p align="justify">· Some guys like to recommend using the previous version of the library. Talking about “previous” they tell about 3.0.1 that was published couple versions ago. I am not sure what there is changed since 3.0.1, but I believe that they didn’t publish new couple versions “just because”. That’s why I would not recommend using this approach as well;</p> <p align="justify">· Finally, you can migrate your library to .NET Standard; </p> <p align="justify">Let’s stay with the last approach and see, how we can make the migration. </p> <p align="justify">It’s funny, but you could do the migration process just clicking a button. Using Visual Studio 2017 Update 3 I could not find any button. If you visit PCL project settings, you still will be able to select a profile for PCL and you will see a message about .NET Standard benefits, but the button is disappeared. Probably, it was a reason to do that. At the same time, I am sure that yesterday I could see the button in Visual Studio for Mac.</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image00812.jpg"><img title="clip_image008" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image008" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image008_thumb11.jpg" width="244" height="209"></a></p> <p align="justify">Because we don’t have any button, we need to create one more project based on .NET Standard library template manually:</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image01011.jpg"><img title="clip_image010" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image010" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image010_thumb10.jpg" width="244" height="139"></a></p> <p align="justify">Opening project settings you can select any .NET Standard version for the project. Just pay attention that Visual Studio 2017 Update 3 will not install .NET Standard 2.0 automatically and you will need to install it manually from Microsoft web site, but Update 4 installer should include 2.0 version.</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image0127.jpg"><img title="clip_image012" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image012" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image012_thumb7.jpg" width="244" height="145"></a></p> <p align="justify">But don’t be in a hurry because .NET Standard 2.0 is just released, and it will be supported by Xamarin in <b>next major update</b> only. In fact, the problem even is not Xamarin, but in UWP platform that works based .NET Standard 1.4. You can find this information looking at the following page: https://docs.microsoft.com/en-us/dotnet/standard/net-standard</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image0145.jpg"><img title="clip_image014" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image014" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image014_thumb5.jpg" width="244" height="136"></a></p> <p align="justify">Microsoft is going to support .NET Framework 2.0 for UWP projects since Fall Creators Update, but it doesn’t mean that you will be able to target .NET Standard 2.0 and earlier UWP releases at the same time. </p> <p align="justify">Therefore, if you want to avoid any previews, alfas and insider releases at this time, you need to stay with .NET Standard 1.4, at least for next couple months. </p> <p align="justify">Once the project is created, we can move all our files from Xamarin.Forms PCL project to .NET Standard library project and remove initial Class1.cs. Thanks to Galaxy you can use Drag and Drop to copy all your files and folders. So, if you already have lots of files in the PCL, it should not be challenging.</p> <p align="justify">Now, it’s time to remove your PCL, and you can rename your .NET Standard library using “old” PCL name. It will not help you to avoid problems with dependencies for your iOS, Android and UWP projects, and you should target your .net standard library from each of them. </p> <p align="justify">The last thing that we need to do is adding reference to <b>Microsoft.Azure.Mobile.Client</b> and <b>Xamarin.Forms</b> libraries. The first package will not generate any problems this time, but I cannot say the same about the second one. Xamarin.Forms 2.3.4 still is not .NET Standard library. </p> <p align="justify">Of course, the next release (2.3.5) already supports .NET Standard, but it’s still in preview. At the same time, if you want to test new features, you can check “Include prereleases” box in NuGet package manager and use a prerelease for 2.3.5 or even 2.4.0. </p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image0164.jpg"><img title="clip_image016" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image016" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image016_thumb4.jpg" width="189" height="244"></a></p> <p align="justify">Both releases support .NET Standard, but the second one supports even .NET Standard 2.0. But if you want to use .NET Standard 2.0 for all projects, including UWP, you will need to install Visual Studio 2017 Update 4 Preview, the latest Windows 10 Insider Preview and the latest UWP SDK insider preview. I can use both options on my computer, but today we are working with components that are in production right now. So, we need to think about how to use the current Xamarin.Forms release.</p> <p align="justify">It’s not the biggest problem because .NET Standard supports type forwarding and other stuff to target old libraries and we can use Xamarin.Forms, but we need to make some modifications in our project file: just open your .csproj for editing and add <b>&lt;PackageTargetFallback&gt;portable-net45+win8+wpa81+wp8&lt;/PackageTargetFallback&gt; </b>right after <b>TargetFramework</b>:</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image0185.jpg"><img title="clip_image018" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image018" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image018_thumb5.jpg" width="244" height="36"></a></p> <p align="justify">It will tell the compiler that if it cannot add a reference due to a problem with the target platform, it’s OK and it should be ignored.</p> <p align="justify">That’s all. Now, we can recompile our solution and even start initial projects using real devices or emulators.</p> <p align="justify">Of course, once a new version of Xamarin.Forms is released, we will be able to use it as a .NET Standard library, but the previous approach will work fine for any other PCL assembly. Counting that there are huge number of existing PCLs, it’s important to know how to use them.</p> <p align="justify">One more thing. If you still targeting Silverlight (WP) using Xamarin, you may need to add a special library to enable compatibility for it:</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image0202.jpg"><img title="clip_image020" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="clip_image020" src="https://msdnshared.blob.core.windows.net/media/2017/08/clip_image020_thumb2.jpg" width="244" height="58"></a></p> <p align="justify">Next time we are going to start using our Mobile Apps and we will discuss lazy loading and 50 records limit.</p>]]></content:encoded>
    </item>
    <item>
      <title>How to cook Mobile Apps (node.js): table schemas, primary keys and existing tables</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/how-to-cook-mobile-apps-node-js-table-schemas-primary-keys-and-existing-tables</link>
      <pubDate>Tue, 22 Aug 2017 06:29:35 GMT</pubDate>
      <dc:creator><![CDATA[Sergiy Baydachnyy]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=27255</guid>
      <description><![CDATA[In this post I am going to discuss how to start developing a Xamarin client application that should...]]></description>
      <content:encoded><![CDATA[<p align="justify">In this post I am going to discuss how to start developing a Xamarin client application that should be connected to an existing database. As a backend I am going to use Azure Mobile Apps, because the service can minimize our work on server side and provides lots of useful features. But to get all benefits from the service, you need to know some tricks that it’s not easy to find in standard tutorials. </p> <p align="justify">Today, I am going to discuss, how to use Mobile Apps in the case if you already have a database. Yes, Mobile App allows you to create a database from scratch using a graphical interface, but usually it’s not the case. I participated in lots of projects last year, and we always had a database in advance or designed it a few days before any client application. I know, it can hurt some client developers, but in many cases Xamarin app is not the centerpiece of your project.&nbsp; <p align="justify">Before to create any database, I want to note couple things.&nbsp; <p align="justify">First, you can develop your code for Mobile Apps in JavaScript or in C#. I like C# and don’t like JavaScript, but in the case of JavaScript/node.js implementation, you should do/know almost nothing to implement your backend. In the case of C#, you will need to generate lots of code, know Entity Framework details, and Azure Portal will provide limited number of features. In fact, C# and node.js implementations are fully different and if I don’t need to create a complex enterprise application I will always select node.js. If you want to use C# rather than JavaScript, this post will not be useful for you at all.  <p align="justify">Second, Microsoft still supports an old implementation of the mobile backend called Azure Mobile Service. It’s not available in the new Azure portal, but there are still lots of content about it. I found that some developers continue to use Mobile Service term and it generates some messy. Try to use Mobile App everywhere. It’s the latest implementation under Azure App Service umbrella.  <p align="justify">Ok. Let’s try to create a new database using SQL Azure. In order to have some tables and data, I would recommend selecting AdventureWorkLT database. It’s possible to do from the Azure portal. So, you can simple select New-&gt;Databases-&gt;SQL Database, and&nbsp; you will be able to select the database from the “select source” field in the wizard:  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image411.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb326.png" width="137" height="244"></a> </p> <p align="justify">Once you create your database, add a firewall rule to connect it from your SQL Management Studio or Visual Studio, you can note two things there:  <ol> <li> <p align="justify">There are several schemas rather than just <strong>dbo</strong> one. It’s very important, because dbo is the default schema in Mobile Apps, and if we want to get some data from SalesLT.Product table, we have to deal with SalesLT schema;</p></li></ol> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image412.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb327.png" width="237" height="244"></a> </p> <ol start="2"> <li> <p align="justify">You can note that all tables contain primary keys of the <strong>int</strong> data type. In the case of the Product table we have ProductID as the key. It’s a very important note because some people likes to tell that you have to use guid as a data type for keys. I don’t think so, but we even should not discuss this question since we ALREADY HAVE a database that was designed by Microsoft as an example. I just want to connect my Xamarin app to it.</p></li></ol> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image413.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb328.png" width="224" height="244"></a> </p> <p align="justify">That’s all with the database and now we can create an instance of Mobile App:  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image414.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb329.png" width="346" height="172"></a> </p> <p align="justify">It’s a trivial task and you should not select any specific parameters on this step.  <p align="justify">Once you have your database and an instance of Mobile App, you can connect it together. To do it, you need to open Data Connections tab from the Mobile App dashboard and add a new connection:  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image415.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb330.png" width="244" height="194"></a> </p> <p align="justify">Azure portal is clever enough to list your database. So, you should not provide any connection strings manually. You can see that a default name for the connection string is <strong>MS_TableConnectionString</strong>. DON’T TOUCH IT! Exactly this name is hardcoded in many places.&nbsp; <p align="justify">In fact, using Add data connection tab, you are creating a new connection string that is available from the Application Settings tab. Therefore, Data Connections tab is just an easier way to create MS_TableConnectionString parameter, but you can use Application Settings as well and we are going to use this tab for some additional parameters:  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image416.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb331.png" width="429" height="63"></a> </p> <p align="justify">Now, it’s time to select a programming language. In the case of C#, you can close the portal and just create all code in Visual Studio, but in our case, we want to use the portal and node.js. So, we have to initialize our empty hosting space with the right environment. It’s possible to do if you select Easy Tables tab:  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image417.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb332.png" width="244" height="188"></a> </p> <p align="justify">Just click Initialize App and all needed components will be installed to your hosting space. Now, Easy Tables tab allows you to create new tables in the existing database and you can note that it doesn’t display our existing tables. Let’s try to understand, how to show our SalesLT.Product table in the list. To do it, I will just create a new table and check what is happening with my hosting space:  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image418.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb333.png" width="247" height="328"></a> </p> <p align="justify">To create a new table, you can provide a table name and some security parameters for different operations with the table.&nbsp; <p align="justify">Now, you can use Mobile App dashboard to open App Service Editor to review all available code in your hosting space:  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image419.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb334.png" width="467" height="152"></a> </p> <p align="justify">You can see that for our faketable we have two files faketable.js and faketable.json. The first file imports azure-mobile-apps module and creates a table object, and the second one contains some parameters for the table:  <p>{ <br>"softDelete" : true, <br>"autoIncrement": false, <br>"insert": { <br>"access": "anonymous" <br>}, <br>"update": { <br>"access": "authenticated" <br>}, <br>"delete": { <br>"access": "anonymous" <br>}, <br>"read": { <br>"access": "anonymous" <br>}, <br>"undelete": { <br>"access": "anonymous" <br>}} <p align="justify">Both files contain important information for our research. Now, we can see that there is a module that contains implementation for the backend, and if we check the module, we can find it on github: <a href="https://github.com/Azure/azure-mobile-apps-node">https://github.com/Azure/azure-mobile-apps-node</a>. So, node.js implementation for Azure Mobile Apps IS IN OPEN-SOURCE. It’s great because we can find some answers there. The second file allows us to tune the backend behavior a little bit providing some parameters per table.&nbsp; <p align="justify">In fact, in order to connect a table to our service from our database, we need to create these two files. Let’s make the experiment and create product.json and product.js files with the same content as faketable.js and faketable.json. Of course, if you go back to Easy Table, you will not be able to see any Product table due to some problems. In order to understand all these problems let’s look at faketable structure:  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image420.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb335.png" width="482" height="176"></a> </p> <p align="justify">You can see that the backend created five columns for the table and the table was created in the dbo schema. So, to make our table available we have to manage several things:  <ul> <li> <p align="justify">Table schema</p> <li> <p align="justify">Additional columns</p> <li> <p align="justify">Primary key that is GUID rather than int</p></li></ul> <p align="justify">In the case of columns createdAt, updatedAt, version and deleted you should nor care too much. Once we fix all other problems, the framework will add all columns automatically and we will not loose our existing data. Of course, if you suddenly have some columns with the same names, you are in trouble, but it’s a very rare case.  <p align="justify">Let’s fix the table schema. In our case we have SalesLT rather than dbo. To understand how to change the table schema for all tables, I would recommend to open node.js implementation on github: <a href="https://github.com/Azure/azure-mobile-apps-node">https://github.com/Azure/azure-mobile-apps-node</a>. You can open <strong>environment.js</strong> in <strong>src/configuration/from</strong> subfolder and check all available parameters there. One of the parameters is <strong>MS_TableSchema</strong> that you can provide from the Application Settings tab on Azure portal.&nbsp; <p align="justify">* @param {string} MS_TableSchema Default schema name for sql tables. Can override in table config  <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image421.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb336.png" width="569" height="108"></a> </p> <p align="justify">Therefore, we can specify SalesLT schema for the project.&nbsp; <p align="justify">Now, you should be able to see Product table in the list, but it will not work due to the problem with the key. By default the key is <strong>GUID</strong>, but in our case it’s <strong>int</strong> and we are not going to change it because it will lead to huge amount of problems. In fact, Mobile Apps allow us to use <strong>int</strong>, but we need to configure it. In order to understand where to make all needed changes, I would recommend to check <strong>/src/data/mssql/statements/createTable.js</strong> on github. There is some code:  <div align="justify"><pre><pre style="font-size: 12px;font-family: consolas,'Courier New',courier,monospace;width: 100%;margin: 0em;background-color: #fbfbfb">pkType = tableConfig.autoIncrement ? 'INT' :</pre></pre></div>
<div align="justify"><pre>&nbsp;</pre></div>
<p align="justify">It’s just the beginning of the line, but you can see that this line is setting up the primary key type. It’s clear that it will be int if <strong>autoIncrement</strong> property from Product.json is true. 
<p align="justify">Therefore, we fixed almost all problems, but we still have one left: the primary key MUST have “<strong>id</strong>” name. If you open src/data/mssql/statements/insert.js on github, you can find something like this: 
<div align="justify"><pre><pre style="font-size: 12px;font-family: consolas,'Courier New',courier,monospace;width: 100%;margin: 0em;background-color: #fbfbfb">sql += util.format('SELECT * FROM %s WHERE [<span style="color: #0000ff">id</span>] = SCOPE_IDENTITY()', tableName);</pre></pre></div>
<div align="justify"><pre>&nbsp;</pre></div>
<p align="justify">You can see that id is hardcoded inside the query. I really don’t know why it was implemented in this way, but it’s something that you cannot modify it in any config file. Of course, it’s possible to assign own commands, but I am not sure if you want to implement own data provider. Additionally, it’s possible to modify existing code and redeploy it, but it’s not easy as well. The fastest way to fix the problem, it’s renaming our ProductId to id: 
<div align="justify"><pre><pre style="font-size: 12px;font-family: consolas,'Courier New',courier,monospace;width: 100%;margin: 0em;background-color: #fbfbfb">EXEC sp_rename 'SalesLT.Product.ProductID', '<span style="color: #0000ff">id</span>', 'COLUMN';  </pre></pre></div>
<div align="justify"><pre>&nbsp;</pre></div>
<p align="justify">It’s not the best way, because you have to check all your stored procedures, modules and other client applications. So, it will not work in enterprise.&nbsp; <p align="justify">Now you can use Easy Tables to see all data, and all additional columns will be created. 
<p align="justify">That’s all for today and next time we will discuss how to develop a basic Xamarin application, but there are still some things to research, which you can do yourselves: find a way to work with app.js in order to use more parameters (including schema); try to understand if it’s possible to modify table schema per table (schema parameter in table config file); how to modify the code to use any primary key name.]]></content:encoded>
    </item>
    <item>
      <title>UWP: Working with Bluetooth devices (part 2: pairing)</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/uwp-working-with-bluetooth-devices-part-2-pairing</link>
      <pubDate>Mon, 08 May 2017 19:30:59 GMT</pubDate>
      <dc:creator><![CDATA[Sergiy Baydachnyy]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=27075</guid>
      <description><![CDATA[Implementing the previous example, I didn’t pair my device with my Windows 10 PC, but in the most...]]></description>
      <content:encoded><![CDATA[<p>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:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/05/clip_image0026.jpg"><img title="clip_image002" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/2017/05/clip_image002_thumb4.jpg" width="244" height="176"></a><b></b></p> <p>But you can pair your devices directly from your application. In order to do it you can use the same <b>DeviceInformation</b> class that we used to track available devices.</p> <p>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:</p> <p style="background-color: #cccccc"><font face="Courier New">private async void deviceListView_ItemClick(object sender, ItemClickEventArgs e)<br>{<br>&nbsp;&nbsp;&nbsp; var item = e.ClickedItem as DeviceInformation;<br>&nbsp;&nbsp;&nbsp; if (item.Pairing.CanPair)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var result = await item.Pairing.PairAsync();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((result.Status == DevicePairingResultStatus.Paired) || <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (result.Status == DevicePairingResultStatus.AlreadyPaired))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Frame.Navigate(typeof(DevicePage), item);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else if (item.Pairing.IsPaired == true)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Frame.Navigate(typeof(DevicePage), item);<br>&nbsp;&nbsp;&nbsp; }<br>}</font></p> <p>You can see that we used <b>Pairing</b> property to get a reference to an object of <b>DeviceInformationPairing</b> type. Using it we can check if the device is already paired, and pair the device if needed.</p> <p>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. </p> <p>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 <b>PairAsync</b> method will show all needed dialogs:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/05/clip_image0041.jpg"><img title="clip_image004" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/2017/05/clip_image004_thumb1.jpg" width="244" height="112"></a></p> <p>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:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/05/clip_image0061.jpg"><img title="clip_image006" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/2017/05/clip_image006_thumb1.jpg" width="244" height="173"></a></p> <p>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: </p> <p style="background-color: #cccccc"><font face="Courier New">private async void deviceListView_ItemClick(object sender, ItemClickEventArgs e)<br>{<br>&nbsp;&nbsp;&nbsp; var item = e.ClickedItem as DeviceInformation;<br>&nbsp;&nbsp;&nbsp; if (item.Pairing.CanPair)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //var result = await item.Pairing.PairAsync();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var customPairing = item.Pairing.Custom;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; customPairing.PairingRequested += CustomPairing_PairingRequested;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var result = <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; await customPairing.PairAsync(DevicePairingKinds.ProvidePin);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; customPairing.PairingRequested -= CustomPairing_PairingRequested;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((result.Status == DevicePairingResultStatus.Paired) || <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (result.Status == DevicePairingResultStatus.AlreadyPaired))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Frame.Navigate(typeof(DevicePage), item);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else if (item.Pairing.IsPaired == true)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Frame.Navigate(typeof(DevicePage), item);<br>&nbsp;&nbsp;&nbsp; }<br>}<br>private void CustomPairing_PairingRequested(<br>&nbsp;&nbsp;&nbsp; DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)<br>{<br>&nbsp;&nbsp;&nbsp; args.Accept("123456");<br>}</font></p> <p>You can see that we used Custom property in order to invoke custom pairing process. Using this property and <b>PairAsync</b> method there we can activate pairing process. It will generate a special event <b>PairingRequested</b> where we can provide all needed information. In our case we simply use <b>Accept</b> method with the pin as a parameter.</p> <p>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:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/05/clip_image0081.jpg"><img title="clip_image008" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px 5px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image008" src="https://msdnshared.blob.core.windows.net/media/2017/05/clip_image008_thumb1.jpg" width="244" height="64"></a></p> <p>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:</p> <p style="background-color: #cccccc"><font face="Courier New">public async void StartReceivingData()<br>{<br>&nbsp;&nbsp;&nbsp; leDevice = await BluetoothLEDevice.FromIdAsync(device.Id);<br>&nbsp;&nbsp;&nbsp; string selector = "(System.DeviceInterface.Bluetooth.DeviceAddress:=\"" + <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leDevice.BluetoothAddress.ToString("X") + "\")";<br>&nbsp;&nbsp;&nbsp; watcher = DeviceInformation.CreateWatcher(selector);<br>&nbsp;&nbsp;&nbsp; watcher.Added += Watcher_Added;<br>&nbsp;&nbsp;&nbsp; watcher.Removed += Watcher_Removed;<br>&nbsp;&nbsp;&nbsp; watcher.Start();<br>&nbsp;&nbsp;&nbsp; timer.Interval = new TimeSpan(0, 0, 1);<br>&nbsp;&nbsp;&nbsp; timer.Tick += Timer_Tick;<br>&nbsp;&nbsp;&nbsp; timer.Start();<br>}<br>private async void Watcher_Removed(DeviceWatcher sender, <br>&nbsp;&nbsp;&nbsp; DeviceInformationUpdate args)<br>{ }<br>private async void Watcher_Added(DeviceWatcher sender, DeviceInformation args)<br>{<br>&nbsp;&nbsp;&nbsp; var service = await GattDeviceService.FromIdAsync(args.Id);<br>&nbsp;&nbsp;&nbsp; if (service!=null)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (service.Uuid.ToString())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case SensorUUIDs.UUID_ENV_SERV:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializeTemperatureSensor(service);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializePressureSensor(service);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case SensorUUIDs.UUID_ACC_SERV:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializeAccelerationSensor(service);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}</font></p> <p>You can see that code is not very complex, but you can extend your UI now showing progress.</p>]]></content:encoded>
    </item>
    <item>
      <title>UWP: Working with Bluetooth devices (part 1)</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/uwp-working-with-bluetooth-devices-part-1</link>
      <pubDate>Fri, 28 Apr 2017 20:16:22 GMT</pubDate>
      <dc:creator><![CDATA[Sergiy Baydachnyy]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=26995</guid>
      <description><![CDATA[Code: Chapter26_BluetoothData on https://github.com/sbaidachni/Win10BookSamples Universal Windows...]]></description>
      <content:encoded><![CDATA[<p><i>Code: Chapter26_BluetoothData on <a href="https://github.com/sbaidachni/Win10BookSamples">https://github.com/sbaidachni/Win10BookSamples</a></i></p> <p>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.</p> <h4>Bluetooth Low Energy</h4> <p>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. </p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image00228.jpg"><img title="clip_image002" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image002_thumb26.jpg" width="244" height="163"></a></p> <p>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. </p> <p>Universal Windows Platform contains five namespaces with Bluetooth keyword including <b>Windows.Devices.Bluetooth</b>. Exactly this namespace contains the <b>BluetoothLEDevice</b> 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. </p> <p>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 <b>Windows.Devices.Enumeration </b>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 <b>DevicePicker</b> and <b>DevicePickerFilter</b> classes that can simplify our work thanks to embedded dialogs. But using these classes is a trivial task:</p> <p style="background-color: #cccccc"><font face="Courier New">DevicePicker picker = new DevicePicker(); picker.Filter.SupportedDeviceSelectors.Add <br>&nbsp;&nbsp;&nbsp; BluetoothLEDevice.GetDeviceSelectorFromPairingState(false)); <br>picker.Filter.SupportedDeviceSelectors.Add( <br>&nbsp;&nbsp;&nbsp; BluetoothLEDevice.GetDeviceSelectorFromPairingState(true)); <br>picker.Show(new Rect(x, y, width, height));</font></p> <p>Code below will show the following dialog that display all paired and non-paired Bluetooth Low Energy devices:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image00414.jpg"><img title="clip_image004" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image004_thumb15.jpg" width="234" height="244"></a></p> <p>The dialog support <b>DeviceSelected</b> event that helps us to understand which device is selected. Alternatively, you can use <b>PickSingleDeviceAsync</b> method to avoid any event handlers. You can see that <b>DevicePicker</b> 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 <b>BluetoothLEDevice</b> class to get access to some predefined strings. Using the <b>GetDeviceSelectorFromPairingState</b> 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.</p> <p>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 <b>DeviceInformation</b> class I can find all BLE devices using the <b>FindAllAsync</b> 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 <b>FindAllAsync</b> method in the <b>DeviceInformation</b> 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 <b>DeviceWatcher</b> class that is available in the <b>Windows.Devices.Enumeration</b> namespace. Let’s look at the following code:</p> <p style="background-color: #cccccc"><font face="Courier New">DeviceWatcher deviceWatcher; <br>protected async override void OnNavigatedTo(NavigationEventArgs e) <br>{ <br>&nbsp;&nbsp;&nbsp; deviceWatcher = DeviceInformation.CreateWatcher( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "System.ItemNameDisplay:~~\"BlueNRG\"", <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new string[] { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "System.Devices.Aep.DeviceAddress", <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "System.Devices.Aep.IsConnected" }, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeviceInformationKind.AssociationEndpoint); <br>&nbsp;&nbsp;&nbsp; deviceWatcher.Added += DeviceWatcher_Added; <br>&nbsp;&nbsp;&nbsp; deviceWatcher.Removed += DeviceWatcher_Removed; <br>&nbsp;&nbsp;&nbsp; deviceWatcher.Start(); <br>&nbsp;&nbsp;&nbsp; base.OnNavigatedTo(e); <br>} <br></font></p> <p>You can see that in order to create the watcher, we used the <b>CreateWatcher</b> static method that you can find in the <b>DeviceInformation</b> 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 <b>System.ItemNameDisplay </b>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 <a href="https://msdn.microsoft.com/windows/uwp/devices-sensors/device-information-properties">this page</a>. </p> <p>The second parameter is a set of properties that should be available for a device. In this case we requested <b>DeviceAddress</b> and <b>IsConnected</b> 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.</p> <p>Finally, we have to pass the <b>DeviceInformationKind</b> flag. In our case it should be <b>AssociationEndpoint</b> that is true for all Bluetooth LE devices that advertise their interface. </p> <p>Once we create the watcher, we need to assign event handlers to <b>Added</b> and <b>Removed</b> events and start the watcher. Pay attention that if you forget to assign <b>Removed</b> 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:</p> <p style="background-color: #cccccc"><font face="Courier New">protected override void OnNavigatedFrom(NavigationEventArgs e) <br>{ <br>&nbsp;&nbsp;&nbsp; deviceWatcher.Stop(); <br>&nbsp;&nbsp;&nbsp; base.OnNavigatedFrom(e); <br>} <br>private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args) <br>{ <br>&nbsp;&nbsp;&nbsp; //throw new NotImplementedException(); <br>} <br>private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args) <br>{ <br>&nbsp;&nbsp;&nbsp; var device = await BluetoothLEDevice.FromIdAsync(args.Id); <br>&nbsp;&nbsp;&nbsp; var services=await device.GetGattServicesAsync(); <br>&nbsp;&nbsp;&nbsp; foreach(var service in services.Services) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug.WriteLine($"Service: {service.Uuid}"); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var characteristics=await service.GetCharacteristicsAsync(); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var character in characteristics.Characteristics) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug.WriteLine($"Characteristic: {character.Uuid}"); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; } <br>}</font></p> <p>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:</p> <p style="background-color: #cccccc"><font face="Courier New">Service: 00001801-0000-1000-8000-00805f9b34fb <br>Characteristic: 00002a05-0000-1000-8000-00805f9b34fb <br>Service: 00001800-0000-1000-8000-00805f9b34fb <br>Characteristic: 00002a00-0000-1000-8000-00805f9b34fb <br>Characteristic: 00002a01-0000-1000-8000-00805f9b34fb <br>Characteristic: 00002a04-0000-1000-8000-00805f9b34fb <br>Service: 02366e80-cf3a-11e1-9ab4-0002a5d5c51b <br>Characteristic: e23e78a0-cf4a-11e1-8ffc-0002a5d5c51b <br>Characteristic: 340a1b80-cf4b-11e1-ac36-0002a5d5c51b <br>Service: 42821a40-e477-11e2-82d0-0002a5d5c51b <br>Characteristic: a32e5520-e477-11e2-a9e3-0002a5d5c51b <br>Characteristic: cd20c480-e48b-11e2-840b-0002a5d5c51b</font></p> <p>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 <b>UM2071</b><b>: BlueNRG-1 development kit.</b> 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):</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image00611.jpg"><img title="clip_image006" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image006_thumb10.jpg" width="244" height="192"></a></p> <p>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. </p> <p>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<b> attribute</b> and <b>generic access</b> 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.</p> <p>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.</p> <p>In order to store information about all available devices I will use a collection that will store references to <b>DeviceInformation</b> objects:</p> <p style="background-color: #cccccc"><font face="Courier New">ObservableCollection&lt;DeviceInformation&gt; deviceList = <br>&nbsp;&nbsp;&nbsp; new ObservableCollection&lt;DeviceInformation&gt;();</font></p> <p>The collection should be observable because we are going to bind it to our interface and it should track any changes dynamically.</p> <p>Now, we can modify our event handlers:</p> <p style="background-color: #cccccc"><font face="Courier New">private async void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args) <br>{ <br>&nbsp;&nbsp;&nbsp; var toRemove = (from a in deviceList where a.Id == args.Id select a).FirstOrDefault(); <br>&nbsp;&nbsp;&nbsp; if (toRemove != null) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; await this.Dispatcher.RunAsync( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Windows.UI.Core.CoreDispatcherPriority.Normal, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; () =&gt; { deviceList.Remove(toRemove); }); <br>} <br>private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args) <br>{ <br>&nbsp;&nbsp;&nbsp; await this.Dispatcher.RunAsync( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Windows.UI.Core.CoreDispatcherPriority.Normal, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; () =&gt; { deviceList.Add(args); }); <br>}</font></p> <p>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. </p> <p>Finally, we can build UI. It will be primary a <b>ListView</b> that will display Id, Name and Pairing properties:</p> <p style="background-color: #cccccc"><font face="Courier New">&lt;ListView Grid.Row="2" Name="deviceListView" ItemsSource="{Binding}" IsItemClickEnabled="True" ItemClick="deviceListView_ItemClick" HorizontalAlignment="Center"&gt; <br>&nbsp;&nbsp;&nbsp; &lt;ListView.ItemTemplate&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;DataTemplate&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Grid Margin="10"&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Grid.ColumnDefinitions&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ColumnDefinition Width="100"&gt;&lt;/ColumnDefinition&gt;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ColumnDefinition Width="Auto"&gt;&lt;/ColumnDefinition&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Grid.ColumnDefinitions&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Grid.RowDefinitions&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RowDefinition&gt;&lt;/RowDefinition&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RowDefinition&gt;&lt;/RowDefinition&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RowDefinition&gt;&lt;/RowDefinition&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Grid.RowDefinitions&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Image Source="Assets/stlogo.png" Margin="10" Grid.RowSpan="3"&gt;&lt;/Image&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding Id}"&gt;&lt;/TextBlock&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding Name}"&gt;&lt;/TextBlock&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal"&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock Text="Can be paired: "&gt;&lt;/TextBlock&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock Text="{Binding Pairing, Converter={StaticResource pairingConv}, Mode=OneWay}"&gt;&lt;/TextBlock&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/StackPanel&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Grid&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/DataTemplate&gt; <br>&nbsp;&nbsp;&nbsp; &lt;/ListView.ItemTemplate&gt; <br>&lt;/ListView&gt;</font></p> <p>To run this code, you need to add an empty event handler for <b>ItemClick</b>. We will implement it later. Additionally, you can use <b>OnNavigatedTo</b> to set <b>DataContext</b> property and activate binding:</p> <p style="background-color: #cccccc"><font face="Courier New">this.DataContext = deviceList;</font></p> <p>Running this code, we will see the following window:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image0089.jpg"><img title="clip_image008" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image008" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image008_thumb8.jpg" width="244" height="116"></a></p> <p>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.</p> <p>Ok. Now we can implement <b>ItemClick</b> event handler and once a user selects the device, we may navigate our application to the second page:</p> <p style="background-color: #cccccc"><font face="Courier New">private void deviceListView_ItemClick(object sender, ItemClickEventArgs e) <br>{ <br>&nbsp;&nbsp;&nbsp; this.Frame.Navigate(typeof(DevicePage), e.ClickedItem); <br>}</font></p> <p>In order to simplify work with all sensors I created a base class that implements all needed features to read values from characteristics:</p> <p style="background-color: #cccccc"><font face="Courier New">public class SensorBase:IDisposable <br>{ <br>&nbsp;&nbsp;&nbsp; protected GattDeviceService deviceService; <br>&nbsp;&nbsp;&nbsp; protected string sensorDataUuid; <br>&nbsp;&nbsp;&nbsp; protected byte[] data; <br>&nbsp;&nbsp;&nbsp; protected bool isNotificationSupported = false; <br>&nbsp;&nbsp;&nbsp; private GattCharacteristic dataCharacteristic; <br>&nbsp;&nbsp;&nbsp; public SensorBase(GattDeviceService dataService, string sensorDataUuid) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.deviceService = dataService; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.sensorDataUuid = sensorDataUuid; <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; public virtual async Task EnableNotifications() <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isNotificationSupported = true; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Guid(sensorDataUuid))).Characteristics[0]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataCharacteristic.ValueChanged += dataCharacteristic_ValueChanged; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GattCommunicationStatus status = <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; await dataCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GattClientCharacteristicConfigurationDescriptorValue.Notify); <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; public virtual async Task DisableNotifications() <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isNotificationSupported = false; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Guid(sensorDataUuid))).Characteristics[0]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataCharacteristic.ValueChanged -= dataCharacteristic_ValueChanged; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GattCommunicationStatus status = <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; await dataCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GattClientCharacteristicConfigurationDescriptorValue.None); <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; protected async Task&lt;byte[]&gt; ReadValue() <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!isNotificationSupported) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (dataCharacteristic == null) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Guid(sensorDataUuid))).Characteristics[0]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GattReadResult readResult = <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; await dataCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data = new byte[readResult.Value.Length];&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataReader.FromBuffer(readResult.Value).ReadBytes(data);&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return data; <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; private void dataCharacteristic_ValueChanged(GattCharacteristic sender, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GattValueChangedEventArgs args) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data = new byte[args.CharacteristicValue.Length]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataReader.FromBuffer(args.CharacteristicValue).ReadBytes(data); <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; public async void Dispose() <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; await DisableNotifications(); <br>&nbsp;&nbsp;&nbsp; } <br>}</font></p> <p>In general, the most important method in this class is <b>ReadValue</b>, 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 <b>WriteClientCharacteristicConfigurationDescriptorAsync</b> method. Once the descriptor is assigned, we will be able to receive messages with new values for the characteristic.</p> <p>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:</p> <p style="background-color: #cccccc"><font face="Courier New">public class TemperatureSensor: SensorBase <br>{ <br>&nbsp;&nbsp;&nbsp; public TemperatureSensor(GattDeviceService dataService) : <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base(dataService, SensorUUIDs.UUID_ENV_TEMP) { } <br>&nbsp;&nbsp;&nbsp; public async Task&lt;double&gt; GetTemperature() <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] data = await ReadValue(); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((double)BitConverter.ToInt16(data,0))/10; <br>&nbsp;&nbsp;&nbsp; } <br>}</font></p> <p>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 <b>EnableNotification</b> method.</p> <p style="background-color: #cccccc"><font face="Courier New">protected async void InitializeAccelerationSensor(GattDeviceService service) <br>{ <br>&nbsp;&nbsp;&nbsp; accSensor = new AccelerationSensor(service); <br>&nbsp;&nbsp;&nbsp; await accSensor.EnableNotifications(); <br>}</font></p> <p>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:</p> <p style="background-color: #cccccc"><font face="Courier New">public async void StartReceivingData() <br>{ <br>&nbsp;&nbsp;&nbsp; leDevice = await BluetoothLEDevice.FromIdAsync(device.Id); <br>&nbsp;&nbsp;&nbsp; string selector = "(System.DeviceInterface.Bluetooth.DeviceAddress:=\"" + <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leDevice.BluetoothAddress.ToString("X") + "\")"; <br>&nbsp;&nbsp;&nbsp; var services = await leDevice.GetGattServicesAsync(); <br>&nbsp;&nbsp;&nbsp; foreach (var service in services.Services) <br>&nbsp;&nbsp;&nbsp; {&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (service.Uuid.ToString()) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case SensorUUIDs.UUID_ENV_SERV: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializeTemperatureSensor(service);&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializePressureSensor(service);&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case SensorUUIDs.UUID_ACC_SERV: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializeAccelerationSensor(service); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; timer.Interval = new TimeSpan(0, 0, 1); <br>&nbsp;&nbsp;&nbsp; timer.Tick += Timer_Tick; <br>&nbsp;&nbsp;&nbsp; timer.Start(); <br>}</font></p> <p>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. </p> <p>The second method is exactly Tick implementation. It simply read data from all available sensors (characteristics) and uses <b>INotifyPropertyChanged</b> to update bindings:</p> <p style="background-color: #cccccc"><font face="Courier New">public async void UpdateAllData() <br>{ <br>&nbsp;&nbsp;&nbsp; if (tempSensor != null) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temperature = String.Format( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $"{(await tempSensor.GetTemperature())} Celsius"); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (PropertyChanged!=null) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PropertyChanged(this, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new PropertyChangedEventArgs("Temperature")); <br>&nbsp;&nbsp;&nbsp; }&nbsp; <br>&nbsp;&nbsp;&nbsp; if (presSensor != null) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pressure = String.Format( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $"{(await presSensor.GetPressure()).ToString()} milliBar"); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (PropertyChanged != null) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PropertyChanged(this, new PropertyChangedEventArgs("Pressure")); <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; if (accSensor != null) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var data = await accSensor.GetAcceleration(); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angleX = data[0]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angleY = data[1]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; angleZ = data[2]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (PropertyChanged != null) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PropertyChanged(this, new PropertyChangedEventArgs("AngleX")); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PropertyChanged(this, new PropertyChangedEventArgs("AngleY")); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PropertyChanged(this, new PropertyChangedEventArgs("AngleZ")); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; } <br>}</font></p> <p>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:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image0106.jpg"><img title="clip_image010" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image010" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image010_thumb6.jpg" width="244" height="191"></a></p> <p>The second tab provides information about temperature and pressure:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image0125.jpg"><img title="clip_image012" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;margin: 0px 5px;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image012" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image012_thumb5.jpg" width="244" height="191"></a></p> <p>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.</p>]]></content:encoded>
    </item>
    <item>
      <title>Developing for Surface Dial</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/developing-for-surface-dial</link>
      <pubDate>Tue, 25 Apr 2017 23:59:49 GMT</pubDate>
      <dc:creator><![CDATA[Sergiy Baydachnyy]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=26885</guid>
      <description><![CDATA[Code: Chapter47_RotateImage on https://github.com/sbaidachni/Win10BookSamples Today, I want to...]]></description>
      <content:encoded><![CDATA[<p><i>Code: Chapter47_RotateImage on <a href="https://github.com/sbaidachni/Win10BookSamples">https://github.com/sbaidachni/Win10BookSamples</a></i></p> <p>Today, I want to discuss one more sensor – Surface Dial. It’s a new Bluetooth device from Microsoft that has own API that you can use in your UWP applications. Due to this API, I decided to show how to work with this device in a separate post rather than extend my post about Bluetooth (see next one in couple days).</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image00222.jpg"><img title="clip_image002" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;margin-left: auto;padding-right: 0px;border-top-width: 0px;margin-right: auto" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image002_thumb20.jpg" width="244" height="139"></a></p> <p>Surface Dial is a device that you can buy separately, and it can work with any computer on Windows 10 Creators Update and later. Once you connect the device to your computer, you will be able to use Wheel settings window to setup default tools and even associate your Surface Dial with an application, assigning application shortcuts to Surface Dial tools.</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image00413.jpg"><img title="clip_image004" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;margin-left: auto;padding-right: 0px;border-top-width: 0px;margin-right: auto" border="0" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image004_thumb14.jpg" width="244" height="176"></a></p> <p>In general, Surface Dial supports three ways to interact: rotation, click, tap and hold. Of course, it’s possible to understand rotation direction and other parameters like angle. In the case of <b>tap and hold</b> this action is reserved for the Dial and allows users to display Surface Dial menu. Counting all available actions (click, rotation left and rotation right), you can assign up to three application shortcuts to each custom tool. Therefore, we can say that it’s possible to integrate the device with any application that supports shortcuts.</p> <p>There are several standard tools like Volume, Scroll, Zoom and so on. Some of these tools like Volume can have sense anywhere, but some of them like Scroll have sense just for subset of applications. In any case, you can configure up to six custom and standard tools in total and start using them without any development effort. But we are developers and below I will describe how to create own custom tools dynamically that users will be able to invoke in your application’s context.</p> <p>Let’s look at the API. Almost all needed classes are located in <b>Windows.UI.Input</b> namespace and you should not install any additional packages, because Surface Dial API is a part of UWP platform in Windows 10. In our example, we will primary use three classes from the namespace: <b>RadialController</b>, <b>RadialControllerConfiguration</b> and <b>RadialControllerMenuItem</b>. The first class describes the controller itself and allows us to get access to all menu items and events. The second class allows us to activate/deactivate some features that are related to the controller. Finally, the <b>RadialControllerMenuItem</b> class helps us to create additional menu items/tools.</p> <p>It’s not wisely to setup the controller in the context of the whole application. Each page in your application may have own features and custom tools and it’s better to setup the controller in the context of each page. Therefore, in the case of multi-page applications you need to create a separate class that will help you to setup the controller in <b>OnNavigatedTo</b> method. In our case we will have just one page and it’s possible to setup the controller in the constructor right after InitializeComponent call.</p> <p>Let’s look at the code below:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">controller = RadialController.CreateForCurrentView();<br>customItem = RadialControllerMenuItem.CreateFromKnownIcon(<br>&nbsp;&nbsp;&nbsp; "Rotate", RadialControllerMenuKnownIcon.Ruler);<br>controller.Menu.Items.Add(customItem);<br>controller.RotationChanged += Controller_RotationChanged;</span></p> <p>This code allows us to get a reference to the controller and create a new menu item with Rotate name and using a standard icon Ruler. Of course, I could use my own icon using <b>CreateFromIcon</b> method or even glyph using <b>CreateFromFontGlyph</b>, but you can experiment with these methods yourselves. Additionally, we assign our own event handler to <b>RotationChanged</b> event. Thanks to this event handler we are going to rotate an image in our application:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">private void Controller_RotationChanged(RadialController sender,<br>&nbsp;&nbsp;&nbsp; RadialControllerRotationChangedEventArgs args)<br>{<br>&nbsp;&nbsp;&nbsp; rotateTransform.Angle += args.RotationDeltaInDegrees;<br>}</span></p> <p>XAML for our page is below:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">&lt;Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"&gt;<br>&nbsp;&nbsp;&nbsp; &lt;Image Source="Assets/mushroom.jpg" Margin="100" RenderTransformOrigin="0.5,0.5"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Image.RenderTransform&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RotateTransform<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x:Name="rotateTransform"&gt;&lt;/RotateTransform&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Image.RenderTransform&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/Image&gt;<br>&lt;/Grid&gt;</span></p> <p>Of course, there are some tricks that you have to know even implementing this simple code:</p> <ul> <li><b>RotationChanged</b> or button events will work only for your custom tools. It means that your image will not be rotated until a user select our Rotate tool. Therefore, it’s safe to assign handlers and it will not override default behavior for standard tools;  <li>In our case we have just one custom menu item, but in the case of two menu items <b>RotationChanged</b> will fire for both. That’s why it’s important to use <b>Invoke</b> event that you can find in each menu item. Using this event, you can setup some flags to store information about selected menu item and implement your code based on the context; </li></ul> <p>One more important thing that you have to count is maximum number of menu items (six). Potentially you can get some problems if a user filled all slots. At the same time your application may not support all standard tools. So, it’s better to leave just needed tools in your application. It’s possible thanks to the <b>RadialControllerConfiguration</b> class.</p> <p style="background-color: #cccccc"><span style="font-family: courier new">config = RadialControllerConfiguration.GetForCurrentView();<br>config.SetDefaultMenuItems(new[] {<br>&nbsp;&nbsp;&nbsp; RadialControllerSystemMenuItemKind.Volume,<br>&nbsp;&nbsp;&nbsp; RadialControllerSystemMenuItemKind.Scroll });</span></p> <p>You can see that we left just two menu items, and we have enough room for our custom tools. If you want to remove all of them, you can pass empty array as the parameter.</p> <p>It’s time to start our application. If you start the application, you will be able to see the following menu once you tap and hold the controller:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image00610.jpg"><img title="clip_image006" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;margin-left: auto;padding-right: 0px;border-top-width: 0px;margin-right: auto" border="0" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image006_thumb9.jpg" width="240" height="244"></a></p> <p>There are two standard menu items and our custom one. If you select the custom one and rotate the controller, it will rotate our image. But the application has some problems. The first one is in that the controller generates <b>RotationChanged</b> event if you rotate it for 10 degrees or more. So, our rotation effect is not smooth. We can change this behavior using <b>RotationResolutionInDegrees</b> property:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">controller.RotationResolutionInDegrees = 1;</span></p> <p>But once we change the property, we will have another problem: the controller will produce permanent buzz. It will happen due to haptic feedback. If the controller generates the feedback not too often, it works fine, but once the controller starts to generate feedback continuously, you will want to disable it. It’s possible to do using the following line:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">controller.UseAutomaticHapticFeedback = false;</span></p> <p>So, we have added two more line to our code and now the application works better. But for the final user it’s still not clear how our tool work, and the rotation itself didn’t display any additional parameters like the current angle. So, it’s wisely to display own user control once a user selects your custom tool. In our case we can build a user control that will display the current angle using digits and graphical representation.</p> <p>I decided to use Win2D in order to build own control. It’s easy to do and our XAML contains just couple elements:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">&lt;Grid&gt;<br>&nbsp;&nbsp;&nbsp; &lt;canvas:CanvasControl Name="canvasControl" Draw="canvasControl_Draw" /&gt;<br>&lt;/Grid&gt;</span></p> <p>C# code is not very complex as well. It just declares a dependency property and a method that draws our UI:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">public static readonly DependencyProperty AngleProperty = DependencyProperty.Register(<br>&nbsp;&nbsp;&nbsp; "Angle",<br>&nbsp;&nbsp;&nbsp; typeof(float),<br>&nbsp;&nbsp;&nbsp; typeof(RotationControl),<br>&nbsp;&nbsp;&nbsp; new PropertyMetadata(null)<br>);<br>public float Angle<br>{<br>&nbsp;&nbsp;&nbsp; get<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (float)GetValue(AngleProperty);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; set<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetValue(AngleProperty, value);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; canvasControl.Invalidate();<br>&nbsp;&nbsp;&nbsp; }<br>}<br>private void canvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,<br>Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)<br>{<br>&nbsp;&nbsp;&nbsp; int stroke = 3;<br>&nbsp;&nbsp;&nbsp; float width = (float)this.ActualWidth;<br>&nbsp;&nbsp;&nbsp; float height = (float)this.ActualHeight;<br>&nbsp;&nbsp;&nbsp; float radius=Math.Min(width, height)/2-2*stroke;<br>&nbsp;&nbsp;&nbsp; float centerX = width / 2;<br>&nbsp;&nbsp;&nbsp; float centerY = height / 2;<br>&nbsp;&nbsp;&nbsp; float lineEndX = radius * (float)Math.Cos(Math.PI * Angle / 180) + centerX;<br>&nbsp;&nbsp;&nbsp; float lineEndY = radius * (float)Math.Sin(Math.PI * Angle / 180) + centerY;<br>&nbsp;&nbsp;&nbsp; args.DrawingSession.DrawCircle(centerX, centerY, radius, Colors.Red,stroke);<br>&nbsp;&nbsp;&nbsp; args.DrawingSession.DrawLine(centerX, centerY,lineEndX , lineEndY,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Colors.Green, stroke);<br>&nbsp;&nbsp;&nbsp; args.DrawingSession.DrawText(Angle.ToString(), centerX, centerY, Colors.Black);<br>}</span></p> <p>We use <b>Invalidate</b> method of Win2D surface to redraw our surface once we change the angle and the surface itself contain a circle, a line and text. You can design better UI, but I wanted to simplify my code.</p> <p>Now, I can modify my XAML in Main.xaml:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">&lt;Image Source="Assets/mushroom.jpg" Margin="100" RenderTransformOrigin="0.5,0.5"&gt;<br>&nbsp;&nbsp;&nbsp; &lt;Image.RenderTransform&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RotateTransform Angle="{Binding Angle, ElementName=rotationControl}"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x:Name="rotateTransform"&gt;&lt;/RotateTransform&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/Image.RenderTransform&gt;<br>&lt;/Image&gt;<br>&lt;controls:RotationControl Visibility="Collapsed" x:Name="rotationControl" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="100" Height="100" Margin="20"&gt;&lt;/controls:RotationControl&gt;</span></p> <p>You can see that there is an element binding to avoid unsynchronized behavior between the image and our control. Additionally, our control is collapsed by default. We have to display it just in the case if our custom tool is selected. To understand it, we can use <b>ControlLost</b> and <b>ControlAquired</b> events:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">controller.ControlLost += Controller_ControlLost;<br>controller.ControlAcquired += Controller_ControlAcquired;<br>private void Controller_ControlAcquired(RadialController sender, RadialControllerControlAcquiredEventArgs args)<br>{<br>&nbsp;&nbsp;&nbsp; rotationControl.Visibility = Visibility.Visible;<br>}<br>private void Controller_ControlLost(RadialController sender, object args)<br>{<br>&nbsp;&nbsp;&nbsp; rotationControl.Visibility = Visibility.Collapsed;<br>}</span></p> <p>Finally, we need to modify RotationChanged method:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">private void Controller_RotationChanged(RadialController sender, RadialControllerRotationChangedEventArgs args)<br>{<br>&nbsp;&nbsp;&nbsp; rotationControl.Angle += (float)args.RotationDeltaInDegrees;<br>}</span></p> <p>If you run the application and select our custom tool, you will be able to see our user control:</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image0088.jpg"><img title="clip_image008" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;margin: 0px auto;padding-right: 0px;border-top-width: 0px" border="0" alt="clip_image008" src="https://msdnshared.blob.core.windows.net/media/2017/04/clip_image008_thumb7.jpg" width="326" height="260"></a></p> <p>That’s not all. Now, I want to modify the code counting that we don’t need any standard tools. But if we have just our tool, probably, it’s wisely to suppress standard menu at all. API allows me to fully suppress the standard menu and work with <b>ButtonHolding</b> event if the menu is suppressed. In order to do that we can add just four lines of code:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">controller.Menu.SelectMenuItem(customItem);<br>config.ActiveControllerWhenMenuIsSuppressed = controller;<br>config.IsMenuSuppressed = true;<br>controller.ButtonHolding += Controller_ButtonHolding;</span></p> <p>The first line activates exactly our custom menu item. Next two lines allow us to suppress the menu. It’s important to use the <b>ActiveControllerWhenMenuIsSuppressed</b> property and if you don’t assign it nothing will work. Finally, we need to handle <b>ButtonHolding</b> event to activate and deactivate our control. You can find <b>ButtonHolding</b> event handler below:</p> <p style="background-color: #cccccc"><span style="font-family: courier new">private void Controller_ButtonHolding(RadialController sender,<br>RadialControllerButtonHoldingEventArgs args)<br>{<br>&nbsp;&nbsp;&nbsp; if (rotationControl.Visibility == Visibility.Visible)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; controller.RotationChanged -= Controller_RotationChanged;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rotationControl.Visibility = Visibility.Collapsed;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; controller.RotationChanged += Controller_RotationChanged;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rotationControl.Visibility = Visibility.Visible;<br>&nbsp;&nbsp;&nbsp; }<br>}</span></p> <p>Running this code, you will be able to see that we fully suppressed the default menu and used our own control as an alternative menu instead. It’s really great! In fact, you can do anything with the controller in the context of the application, but that’s not all.</p> <p>Some devices like Surface Studio allows users to work with the controller directly on screen. In this case, you can handle three events: <b>ScreenContactStarted</b>, <b>ScreenContactEnded</b> and <b>ScreenContactContinued</b>. Thanks to these events you will be able to know a position of the controller and a virtual rectangle that contains the controller. Using this information, it’s possible to execute tools applying actions to the position of the controller. For example, we can rotate our image not around its center but around the center of the controller. But the most beautiful effects can be created exactly around your own custom menu. In our case, the menu can be expanded to include the controller inside the area, and as for me, it’s the most important guideline that you have to follow: if you have a custom menu always handle screen contact events and adjust your menu based on location of the controller on the screen. In our case it will require some additional work, but it’s not a problem to write ten more lines of code (add width and height properties to the control, change text location and handle the events placing the control using Margin property).</p>]]></content:encoded>
    </item>
    <item>
      <title>Detecting emotion with Machine Learning</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/detecting-emotion-with-machine-learning</link>
      <pubDate>Tue, 28 Jun 2016 11:30:00 GMT</pubDate>
      <dc:creator><![CDATA[Mickey MacDonald]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=26735</guid>
      <description><![CDATA[Machine Learning is a very hot topic these days. Getting started can be fast and easy. In this video...]]></description>
      <content:encoded><![CDATA[Machine Learning is a very hot topic these days. Getting started can be fast and easy. In this video post, I walk through the steps to build a simple Universal Windows Application (UWP) that connects to the Microsoft Cognitive Services and the Emotion API.

<iframe src="https://channel9.msdn.com/Events/canada/MSFTHacks/Microsoft-Cognitive-Services-An-Emotional-Demo/player?wt.mc_id=DX_841030" width="640" height="360" frameborder="0" allowfullscreen="allowfullscreen"></iframe>

The Microsoft Cognitive Services are a set of APIs that enable your apps to leverage powerful algorithms using just a few lines of code. They work across lots of various devices and platforms such as iOS, Android, and Windows, keep improving and are easy to set up.

&nbsp;

In the demo we use the Emotion API to take a facial expression of an image, we capture as input. The API returns the confidence across a set of emotions for each face in the image, as well as a bounding box for each of the faces found in the image or stream. The emotions detected are anger, contempt, disgust, fear, happiness, neutral, sadness, and surprise. These emotions are understood to be cross-culturally and universally communicated with particular facial expressions.

The demo above is based around UWP and uses C# as the programming language. If you are looking for a NodeJS and JavaScript solution, I suggest this excellent video by Rami Sayar <a href="https://channel9.msdn.com/Events/canada/MSFTHacks/Am-I-happy-Overview-of-Cognitive-Services--the-Emotion-API" target="_blank">https://channel9.msdn.com/Events/canada/MSFTHacks/Am-I-happy-Overview-of-Cognitive-Services--the-Emotion-API</a>

<strong>Some links of interest:</strong>

Microsoft Cognitive Services Website: <a title="https://www.microsoft.com/cognitive-services" href="https://www.microsoft.com/cognitive-services">https://www.microsoft.com/cognitive-services</a>

Emotion API  Documentation: <a title="https://dev.projectoxford.ai/docs/services/5639d931ca73072154c1ce89/operations/563b31ea778daf121cc3a5fa" href="https://dev.projectoxford.ai/docs/services/5639d931ca73072154c1ce89/operations/563b31ea778daf121cc3a5fa">https://dev.projectoxford.ai/docs/services/5639d931ca73072154c1ce89/operations/563b31ea778daf121cc3a5fa</a>

Cognitive Services Application Gallery: <a title="https://www.microsoft.com/cognitive-services/en-us/applications" href="https://www.microsoft.com/cognitive-services/en-us/applications">https://www.microsoft.com/cognitive-services/en-us/applications</a>

<strong>Happy Coding!</strong>]]></content:encoded>
    </item>
    <item>
      <title>Bizspark Startup Chats: Ep 1: Support System for Startups in Canada</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/bizspark-startup-chats-ep-1-support-system-for-startups-in-canada</link>
      <pubDate>Thu, 23 Jun 2016 07:30:12 GMT</pubDate>
      <dc:creator><![CDATA[Adarsha Datta]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=26695</guid>
      <description><![CDATA[Welcome to BizSpark Startup Chats!







This is a new series to discuss anything and...]]></description>
      <content:encoded><![CDATA[<em>Welcome to BizSpark Startup Chats!</em>
<script src="https://4056.xg4ken.com/media/getpx.php?cid=193af514-7859-4934-9855-1f5ca53ec607" type="text/javascript"></script>
<div class="mainHolder">
<div class="mainContent text">
<div class="entry">
<div class="entry-content">
<div id="entry-body">

<em>This is a new series to discuss anything and everything with startups. Through this platform we will invite some of the biggest influencers and startups in the ecosystem to share their insights and experience for the benefit of everyone in the startup space. </em>

<iframe src="https://channel9.msdn.com/Series/BizSpark-Startup-Chats/Ep1-BizSpark-Startup-Chats-Overview-of-startup-support-in-the-Canadian-startup-ecosystem/player" width="960" height="540" frameborder="0" allowfullscreen="allowfullscreen"></iframe>

For our inaugural episode we have invited Nathan Monk, Sr. Strategist at MaRS Discovery District, who shares his vast experiences in working in the startup community in Canada.  During this episode we talk in depth about the kind of support systems that exist for startups in their various stages of development.  With government support, private sector participants (like Microsoft), startup alumni, and many other startup ecosystem participants we discuss how these various entities play a critical role in supporting Canada's startup community now and in the future.  Nathan provides very useful insights through his experience in the ecosystem relevant to all startups in all stages.

Here are some links to the funding programs and startup community resources that Nathan was referring too.

https://www.oce-ontario.org/programs
https://www.cmf-fmc.ca/
https://www.marsdd.com/mars-library/commercialization-programs-funding/
https://www.thec100.org/
https://www.marsdd.com/funding/investment-accelerator-fund/

</div>
As mentioned, this is the inaugural episode. We hope that this will be useful for you - so please let us know if this was insightful and what else you would like to see on this platform either through the comments below or <a href="https://twitter.com/AdarshaDatta" target="_blank">@AdarshaDatta</a>

</div>
</div>
</div>
</div>]]></content:encoded>
    </item>
    <item>
      <title>Be ready for Maker Faire: The final report</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/be-ready-for-maker-faire-the-final-report</link>
      <pubDate>Wed, 22 Jun 2016 04:30:32 GMT</pubDate>
      <dc:creator><![CDATA[Sergiy Baydachnyy]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=26675</guid>
      <description><![CDATA[For the second time I got a chance to participate in Vancouver Mini Maker Faire. You can find my...]]></description>
      <content:encoded><![CDATA[<p align="justify">For the second time I got a chance to participate in Vancouver Mini Maker Faire. You can find my previous report <a href="https://blogs.msdn.microsoft.com/cdndevs/2015/06/12/microsoft-canada-at-vancouver-mini-maker-faire/">here</a>.</p>
<p align="justify">This year we decided to avoid any entertainment activities and build our demos around the most interesting technologies for makers. So, people could find the following demos visiting our booth:</p>
<p align="justify">· Lots of robots from our good friends – EZ-Robot;</p>
<p align="justify">· Home automation demo that shows Windows 10 IoT Core abilities to manage lots of smart devices;</p>
<p align="justify">· Azure IoT Services in action;</p>
<p align="justify">· Bluetooth Low Energy support in Windows 10;</p>
<p align="justify">Let’s discuss each of these demos in details.</p>
<p align="justify">Everybody like robots! That’s why <a href="https://www.ez-robot.com/default.aspx">EZ-Robot</a> booth was the most popular place among children and their parents. EZ-Robot is founded in Calgary and allows you to learn robotics using lots of hardware and software tools. You can start with <a href="https://www.ez-robot.com/Shop/AccessoriesDetails.aspx?prevCat=9&amp;productNumber=40">EZ-B controller</a> and build your own robot using any motors and sensors or you can buy a ready-to-use <a href="https://www.ez-robot.com/Shop">robot kit</a>. Once you assemble your robot, you can use innovative <a href="https://www.ez-robot.com/EZ-Builder/">EZ-Builder tool</a> in order to develop software even without coding at all. Advanced developers can find lots of SDKs, including SDK for <a href="https://www.ez-robot.com/EZ-Builder/UniversalBot">Windows 10 Universal applications</a>. Don’t miss our interview with EZ-Robot and cool demos at the end:</p>
<p align="justify"> <iframe src="https://channel9.msdn.com/Series/Internet-of-Things-micro-boards-for-beginners/Improve-your-robotics-skills-with-EZ-Robot/player" width="480" height="270" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p align="justify">In the second demo we showed, how to use Windows 10 IoT Core on Raspberry Pi 2 in order to build a home automation system. Windows 10 supports AllJoyn as well as AllJoyn API that you can use in order to create Windows 10 applications. But, if we are talking about home automation, you can find lots of ZigBee and Z-Wave but not AllJoyn devices. But it’s not a problem at all. You can simply use <a href="https://developer.microsoft.com/en-us/windows/iot/win10/alljoyndsb">our bridges for AllJoyn</a> and use the same API in order to work with any device in your home. So, if you are looking for a hub for your smart home, you can easy use Win 10 IoT Core, Rapberry, C# and Visual Studio in order to create anything.</p>
<p align="justify">  <iframe src="https://channel9.msdn.com/Series/Internet-of-Things-micro-boards-for-beginners/Be-ready-for-MakerFaire-AllJoyn-demo/player" width="480" height="270" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p align="justify">In the next demo we showed several Azure IoT services. In order to avoid questions “why Raspberry” and “why C# and Windows 10” I installed four different micro boards: Raspberry (Linux/NodeJS), Raspberry (Windows/C#), ESP8266 (Arduino) and CC3200 Launchpad (TI RTOS/C). Thanks to <a href="https://github.com/Azure/azure-iot-sdks">Azure IoT SDK</a>, you can use C, C#, Python, JavaScript and Java in order to connect anything to Azure. I used three services: IoT Hub for device management and messaging, Stream Analytics for real-time analytics and Power BI for real-time dashboard. In my next articles I am going to share more details.</p>
<p align="justify">  <iframe src="https://channel9.msdn.com/Series/Internet-of-Things-micro-boards-for-beginners/Be-ready-for-MakerFaire-Azure-IoT-demo/player" width="480" height="270" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p align="justify">Finally, in order to show Windows 10 connectivity features, I decided to build an application that shows how to work with Bluetooth Low Energy devices. I selected the <a href="https://www.ti.com/ww/en/wireless_connectivity/sensortag2015/?INTC=SensorTag&amp;HQS=sensortag">sensor tag device</a> from Texas Instruments but you can use anything. Later, I am going to publish the project to github but it’s really easy.</p>
<p align="justify">  <iframe src="https://channel9.msdn.com/Series/Internet-of-Things-micro-boards-for-beginners/Be-ready-for-MakerFaire-Bluetooth-Low-Energy-demo/player" width="480" height="270" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p align="justify">Here are couple images from the event:</p>
<a href="https://msdnshared.blob.core.windows.net/media/2016/06/clip_image00221.jpg"><img style="padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-width: 0px" title="clip_image002" src="https://msdnshared.blob.core.windows.net/media/2016/06/clip_image002_thumb19.jpg" alt="clip_image002" width="244" height="139" border="0" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/clip_image00410.jpg"><img style="padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-width: 0px" title="clip_image004" src="https://msdnshared.blob.core.windows.net/media/2016/06/clip_image004_thumb7.jpg" alt="clip_image004" width="244" height="139" border="0" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2016/06/clip_image0069.jpg"><img style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" title="clip_image006" src="https://msdnshared.blob.core.windows.net/media/2016/06/clip_image006_thumb7.jpg" alt="clip_image006" width="244" height="139" border="0" /></a>]]></content:encoded>
    </item>
    <item>
      <title>Step by Step Machine Learning: A Classification model to help the Humane Society</title>
      <link>https://docs.microsoft.com/archive/blogs/cdndevs/step-by-step-machine-learning-a-classification-model-to-help-the-humane-society</link>
      <pubDate>Mon, 13 Jun 2016 13:24:26 GMT</pubDate>
      <dc:creator><![CDATA[Susan Ibach]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/cdndevs/?p=26615</guid>
      <description><![CDATA[This tutorial will walk you through a classification machine learning experiment to predict one of...]]></description>
      <content:encoded><![CDATA[<p><strong><em><a href="https://msdnshared.blob.core.windows.net/media/2016/06/WP_20160426_13_41_43_Pro.jpg"><img title="WP_20160426_13_41_43_Pro" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: left;padding-top: 0px;padding-left: 0px;margin: 0px 10px 10px 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="WP_20160426_13_41_43_Pro" src="https://msdnshared.blob.core.windows.net/media/2016/06/WP_20160426_13_41_43_Pro_thumb.jpg" width="300" align="left" height="171"></a>This tutorial will walk you through a classification machine learning experiment to predict one of several possible outcomes for an animal brought to the humane society.</em></strong></p> <p>If you missed the previous tutorials you can find them here</p> <ul> <li><a href="https://blogs.msdn.microsoft.com/cdndevs/2016/05/13/would-you-have-survived-the-titanic-try-this-step-by-step-machine-learning-experiment-to-find-out/" target="_blank">Predicting survivors on the titanic</a> (two-class prediction) </li> <li><a href="https://blogs.msdn.microsoft.com/cdndevs/2016/05/31/getting-started-with-machine-learningwisconsin-breast-cancer-dataset/" target="_blank">Analyzing breast cancer data</a> (two-class prediction)</li></ul> <p>For a more comprehensive introduction to data science and Azure Machine Learning Studio check out <a href="https://mva.microsoft.com/en-US/training-courses/data-science-and-machine-learning-essentials-14100">Data Science and Machine Learning Essentials on MVA</a></p> <p>In this post I will show you how to</p> <ol> <li><strong>Create your machine learning workspace</strong></li> <li><strong>Create a basic classification experiment</strong></li> <li><strong>Work the data to improve accuracy</strong></li> <li><strong>Deploy the trained model as a predictive web service and call it from Python code</strong></li></ol> <p>I recently adopted two cats from the humane society. That’s Oola, our acrobatic ninja cat, curled up on the higher bed and Cluseau, the lovable but somewhat clueless addition to the family, giving himself a bath on the lower level. As I was considering interesting new datasets to explore, I stumbled across a data set from the SPCA (Society for Prevention of Cruelty to Animals) on Kaggle. They wanted to predict the outcome of animals who arrived at the shelter.</p> <p>This data set helps illustrate two very important principles of machine learning:</p> <h2>Defining the business problem and benefits </h2> <p>Whenever you start an experiment you should have a problem in mind that you want to solve. What’s the goal of the SPCA? To find homes for as many animals as possible. If you are running the SPCA and you can predict that an animal is going to be difficult to place in a home through machine learning, you might be able to take actions to increase the animal’s chance of adoption. In my home town, the humane society has animals on display at local pet stores. I am sure some pet stores get more traffic and have higher adoptions rates, so perhaps you could give priority to animals who are less likely to find a home. As I created this tutorial, I also discovered that animals that were not neutered or spayed had a lower chance of adoption. So using funds to neuter or spay animals at the center should also incresae the adoption rate. Learnings from the experiment can be directly used to improve the adoption rate of animals at the center.</p> <h2>Data preparation</h2> <p>Executing your machine learning experiment is only a part of machine learning. The biggest chunk of work when doing machine learning, is becoming familiar with the data, collecting the data, and getting the data in a suitable format for machine learning. The original data set from the SPCA is not optimized for machine learning and needs some work!&nbsp; I’ll talk more about this in the video “work the data to improve accuracy” which you will find in section 3 of this post.</p> <h1>On with the tutorial!</h1> <p>Okay enough talk, let’s get on with the tutorial.</p> <h2>1. Create a machine learning workspace</h2> <p>First things first you are going to need a Machine Learning Workspace to execute any experiment</p><iframe height="540" src="https://channel9.msdn.com/Events/canada/MSFTHacks/Creating-a-Machine-Learning-Workspace/player" frameborder="0" width="960" allowfullscreen></iframe> <h2>2. Create a basic classification experiment</h2> <p>If you have followed the tutorial for the two-class experiments, you will notice the steps here are very similar! The biggest difference is in the evaluation report. The results for a classification experiment are quite different from a two-class experiment.&nbsp; </p><iframe height="540" src="https://channel9.msdn.com/Events/canada/MSFTHacks/Creating-a-Basic-Classification-Experiment/player" frameborder="0" width="960" allowfullscreen></iframe> <h2>3. Work the data to improve accuracy</h2> <p>When you get unsatisfactory results from your model, it’s time to go back to your data. MAchine Learning is an iterative process. You will find yourself constantly going back, tweaking the data, trying a new experiment hoping to get better results. In this video I will share a few examples of ways you could work with the data in the SPCA dataset to improve your results.</p><iframe height="540" src="https://channel9.msdn.com/Events/canada/MSFTHacks/How-To-Get-Better-Accuracy/player" frameborder="0" width="960" allowfullscreen></iframe> <p>I could have spent even more time improving this data set for my experiment. I didn’t even get to analyzing the data set for dogs! Think about the factors families consider when they adopt a dog: size, temperament, purebred vs mixed breed, allergy friendly (i.e. how much do they shed fur.). A lot of this information can be determined if we find out information about the breeds. Obviously it would be a fair bit of work to extract the breed for each dog and fetch information from another data source that tells us the temperament, size, and allergy friendly level of each breed. We would also need to make sure each of those values was categorized in a way that was helpful. Should we break down size of dog to small/medium/large? or should we break size into average expected height in inches? Should we simply identify which breeds are considered allergy friendly, such as poodles? </p> <p>Machine learning is an iterative process, if we aren’t happy with the results, sure you can change the algorithm you use to train the model, and you can tweak the parameters of the algorithm, that can improve your accuracy. But don’t forget to go back and re-evaluate the data itself! Is there additional data you can fetch, or derive? Are the columns that are not formatted in an optimal way for machine learning?</p> <h2>4. Deploy the trained model as a web service</h2> <p>Of course a trained model is only useful if you have a way to use it! In this short video I show you how to deploy the trained model as a predictive web service and call it from a simple Python application.</p> <p><iframe height="540" src="https://channel9.msdn.com/Events/canada/MSFTHacks/Deploying-your-trained-model-as-a-web-service/player" frameborder="0" width="960" allowfullscreen></iframe></p>]]></content:encoded>
    </item>
  </channel>
</rss>