0 Comments

ShellLoginApp

Since the release of Xamarin Forms 4.5, Shell now supports modal navigation. Since one of my highest ranking blog posts is how to create a login page with Xamarin Forms. I thought it was time to revisit the topic and look at how to implement a login page using the Shell.

So what is so special about a login page? Well, to state the obvious, the user should only be able to exit it after entering a correct login. Further, the user should not be able to leave the login page, i.e. navigate back to a previous page. And finally once successfully authenticated, the user should not find the login page when navigating back.

So let's see how we can capture the user on a page and then ensure that this page is no longer on the navigation stack while using Shell. So let's get going with the UI flow of a possible login experience. Our app has the following screen flow:

PageFlow

All of our pages have to be registered with the Shell. Note that the first ContentPage in the Shell.xaml file is the one getting displayed after start-up. So our Shell is structured accordingly:

<!-- Loading/Start Page -->
<ShellItem Route="loading">
    <ShellContent ContentTemplate="{DataTemplate local:LoadingPage}" />
</ShellItem>

<!-- Login and Registration Page -->
<ShellContent Route="login"
              ContentTemplate="{DataTemplate local:LoginPage}">
</ShellContent>

<!-- Main Page -->
<!-- We will get to this later -->

Our loading screen mainly simulates checking if the user has valid credentials. If the app was not a total fake on the business logic side. It might be using a Token-based flow; this is where one would check if the app still has a valid token and can go directly to the main screen or the user has to log in.

LoadingPage

Beautiful load animation, right? 😉 And here is the slim logic in the View Model :

// Called by the views OnAppearing method
public async void Init()
{
    var isAuthenticated = await this.identityService.VerifyRegistration();
    if (isAuthenticated)
    {
        await this.routingService.NavigateTo("///main");
    }
    else
    {
        await this.routingService.NavigateTo("///login");
    }
}

Note we only tell the Shell to navigate to the login screen. When using Shell, you define the kind of navigation on the target page. So for the login page, we would set it like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             ...
             Shell.PresentationMode="ModalAnimated"
             ...>
    ...
</ContentPage>

And whenever you navigate modally, it is always a good idea to override the back button navigation in the code behind of the target page as follows:

protected override bool OnBackButtonPressed()
{
    return true;
}

Why? Well because otherwise all your Android users could just simply press the Android back button and weasel their way out of your carefully crafted login process. Now let's add a registration page. Here we define the standard push navigation:

?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             ...
             Shell.PresentationMode="Animated"
             ...>
    <Shell.BackButtonBehavior>
        <BackButtonBehavior Command="{Binding ExecuteBack}"
                            TextOverride="Back" />
    </Shell.BackButtonBehavior>
    ...
</ContentPage>

Before we can navigate to the registration page, we have to register the page with the Shell. We can do this in the code behind of the AppShell.xaml.cs file:

Routing.RegisterRoute("registration", typeof(RegistrationPage));

Now we can navigate from the login page to the registration page by as follows:

Shell.Current.GoToAsync("//login/registration");

The code above implements the default navigation behaviour, i.e. a back button on the top left or by using the back button on Android. So as soon as the user has logged in, we display the main page of the app. Which is again defined in the AppShell.xaml as follows:

<!-- Main Page -->
<FlyoutItem Route="main"
            FlyoutDisplayOptions="AsMultipleItems" IsTabStop="False">
    <ShellContent Route="home"
                  IsTabStop="False"
                  ContentTemplate="{DataTemplate local:MainPage}"
                  Title="Home" />
</FlyoutItem>

Since it is not part of the login page, the Shell automatically removes the login page form the navigation stack.

So now that we are in the app. Sometimes you will want to present the user with the option to logout. Shell gives us an easy way to define a flyout menu. In Non-Shell apps, this is usually done with the MasterDetailPage. So a nice place to add our logout is as a new entry in the flyout right? Instead of defining a flyout item, it will be better to use a menu item. In general think of flyout items as areas of your app and menu items as actions in the menu. The logout is less an area and more an action. So for our logout, we define a menu item like this:

<MenuItem Text="Logout"
          Command="{Binding ExecuteLogout}" />

The Command and Binding context get defined in the code behind, i.e. the App.xaml.cs:

public AppShell()
{
    InitializeComponent();
	// ... routes and stuff
    BindingContext = this;
}

public ICommand ExecuteLogout => new Command(async () => await GoToAsync("main/login"));

Depending on the requirements of your app, you might want to force the user to log in at different times. This could be during start-up, resume or on a rainy Tuesday. Whatever the requirement, you can simply invoke the navigation similar to above, and the user will be navigated to the login screen. Once successfully logged in, the user is returned to the page on which the login page was opened.

Conclusion

With the new modal navigation mode of Shell, the implementation of a Login screen can be done quite nicely and with a lot less worrying about the state of the navigation stack. One of the main differences between using a NavigationPage compared to the Shell is how you configure the different parts within the AppShell.xaml. The Xamarin team has mentioned that more goodness should come to Shell, so be sure to stay tuned and watch out for news on the Xamarin Blog regarding new updates and features.

You can find the entire sample on GitHub. And check out David Ortinau's sample which inspired this post.

HTH

0 Comments

Icons of Xamarin & Automapper in a mobile phone

You might have already heard of AutoMapper, the library that helps you to copy Properties form Object to another written by Jimmy Bogard. Whenever you are creating a larger Xamarin Forms application, you usually end up with different models representing similar data but for different areas of your app. For example, you will get a minimalist Data Transfer Object (DTO) from your backend, which you might copy into another app-internal model or directly to the View Model representing the data displayed on your view. And this is where AutoMapper will help you out and prevent you from writing all that copy code.

I must confess - while it always felt a bit like overkill at the beginning. At the end of the project, I was still happy to have made the decision at the beginning. So let's see how we get started.

Getting Setup

The setup is quite straight forward actually add the NuGet package of AutoMapper to your Xamarin Forms project. That is until you start compiling for iOS, then it will all blow up due to some reflection issue. Since iOS is compiled Ahead Of Time (AOT), you can't do any runtime operations such as reflections. Now AutoMapper does not use reflection when running on iOS. Still, due to some weird compilation thingy issue - I haven't understood the point in detail - the compiler ends up trying to add reflection which will not work on iOS. So to make things run under iOS, we have to add the following line to our iOS csproj file:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ItemGroup>
    ...
    <PackageReference Include="System.Reflection.Emit" Version="4.7.0">
      <ExcludeAssets>all</ExcludeAssets>
      <IncludeAssets>none</IncludeAssets>
    </PackageReference>
  </ItemGroup>
  ...
</Project>

Then there is still the Linker under iOS that tries to remove the System.Convert assembly. Which is required by AutoMapper. But luckily we can help the linker out here by adding an XML file:

<linker>
  <assembly fullname="mscorlib">
    <type fullname="System.Convert" preserve="All" />
  </assembly>
</linker>

And setting the build property to LinkDescription:

Showing Visual Studio Properties Pane

Configuration and usage

Okay so everything is set up now we still have to tell AutoMapper what which objects we would like to copy from A to B and back again. In the small app I prepared for this blogpost we will copy the note DTO object to it's View Model counterpart. So to get a configured AutoMapper instance, we would write something like this during the start-up of the app:

public static IMapper CreateMapper()
{
    var mapperConfiguration = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Note, NoteViewModel>();
        cfg.CreateMap<NoteViewModel, Note>();
    });

    return mapperConfiguration.CreateMapper();
}jjjjjjj

Now we could convert the DTO to a View Model by invoking the AutoMapper instance as follows:

var viewModel = _mapper.Map<MainViewModel>(note);

But what I often end up doing is populating the View Model after creation or when the Page/View it is being used in is getting created. For example, an Init method on the View Model might be invoked during the OnAppearing of the View. Then we could call a service in the View Model which would return a DTO of that object. In this scenario, we will want to tell AutoMapper to map the DTO directly on the View Model itself:

public async void Init()
{
    var note = (await _noteService.GetNotes()).First();
    _mapper.Map(note, this);
}

If you had a List of View Models, i.e. a CollectionView or ListView, we would use LINQ in combination with AutoMapper to quickly convert from DTO to View Model:

Notes = (await _noteService.GetNotes())
            .Select(_mapper.Map<MainViewModel>)
            .ToList();

Having AutoMapper in place you whenever a new DTO has to be presented in your app, you would add a new configuration and then be able to use the mapping. So the more mapping you require, the quicker using AutoMapper will pay itself off.

But there is one more thing I really like when using AutoMapper in my projects, and that is testing.

Testing your mappings

"Testing? Are you serious?" - well yes, I actually am. You can check your configuration with a simple test case:

[Fact]
public void AppBoostrapper_ValidateMapping_AssertCorrectness()
{
    var mapper = AppBootstrapper.CreateMapper();
    mapper.ConfigurationProvider.AssertConfigurationIsValid();
}

This test will tell you if AutoMapper has all the information necessary to copy your data from one object to the other. So if we start adding Commands to the View Model, the mapping will fail with the information that it can not map the command into our DTO. And we obviously do not want to send an ICommand data field back to the server, so we ignore it:

cfg.CreateMap<Note, NoteViewModel>()
    .ForMember(n => n.ExecuteReset, opt => opt.Ignore())
    .ForMember(n => n.ExecuteStore, opt => opt.Ignore());
cfg.CreateMap<NoteViewModel, Note>();

But what when we add a data field WriterMood to the DTO and forget to add it to the View Model? Correct, the test will fail and inform us that we have forgotten to add the field.

Screenshot of failed AutoMapper config test

And that test has saved me from so many forgotten data fields - ahem what I meant to say it saved a friend of mine... 😅

Looking back

I will surely use AutoMapper in my future Xamarin Forms project that have their share of DTOs, internal Models and View Models since it is not only convenient to copy the properties. But it also saves me from forgetting to add properties to objects.

Be sure to check out the official documentation of AutoMapper since this post barely scratches the surface on what you can configure with AutoMapper.

As always, you can find a complete little sample application on GitHub.

HTH

0 Comments

00_TitleImage

Ever had to develop an app where the position of something was of interest. An address of a user, store, restaurant or some other point of interest? The straight forward version might be to provide the user with a simple form.

Address entry form

While the form is easy to implement and reliable, it can be cumbersome. Plus what if you want to navigate to the location? Or why not use the position of the device? Tap on a map to get the address? Well, all of these things can be achieved quite easily with a few helpful libraries provided by the Xamarin team.

Geocoding like a pro

Whenever you need to convert between coordinates and addresses, Geocoding is your best friend. You can show up with either an address or position, and you will get back the opposite:

var location = (await Geocoding.GetLocationsAsync($"{street}, {city}, {country}")).FirstOrDefault();

if (location == null) return;

Position = new Position(location.Latitude, location.Longitude);

So if we had a form where the user can enter the address and we wanted to navigate to that position, we could convert the address to geo coordinates and then, using Xamarin Essentials, open the maps app on the platform and navigate to that position.

var location = new Location(Position.Latitude, Position.Longitude);
var options = new MapLaunchOptions { NavigationMode = NavigationMode.Driving };
await Xamarin.Essentials.Map.OpenAsync(location, options);

Quite impressive for a bunch of entries and a few lines of code right?

Getting an address with one tap

But typing in addresses can be cumbersome. Why not just select the position on the map and get the address from that position? Xamarin Forms has supported the maps control for quite some time. Once you have added the NuGet package, it will allow you to present the native map platform, i.e. Google Maps on Android.

<?xml version="1.0" encoding="utf-8" ?>
             ...
             xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
             ... >

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <maps:Map x:Name="MapControl" />
        ...
    </Grid>

</ContentPage>


Note there are some setup steps required depending on the platform you intend to target. So be sure to check out the official docs from Microsoft on those details. Here we will continue to focus on the fun stuff

The map has an event MapClicked which fires when the user taps on the map with the geo-position.

Observable.FromEventPattern<MapClickedEventArgs>(
    mc => MapControl.MapClicked += mc, 
    mc => MapControl.MapClicked -= mc)
    .Subscribe(ev => ViewModel.ExecuteSetAddress.Execute(ev.EventArgs.Position));

If you are not familiar with Rx.Net, here is the equivalent code with an event handler:

protected override void OnAppearing()
{
   // ...

    MapControl.MapClicked += HandleMapClicked;
}

private void HandleMapClicked(object sender, MapClickedEventArgs e)
{
    var postion = e.Position;
    // ...
}

To give the user some feedback, we could even present the taped position with a pin:

private Unit SetPin(Position position)
{
    Pin pin = new Pin
    {
        Label = "The Place",
        Address = $"{ViewModel.Street}, {ViewModel.City}, {ViewModel.Country}",
        Type = PinType.Place,
        Position = position
    };

    var latDegrees = MapControl.VisibleRegion?.LatitudeDegrees ?? 0.01;
    var longDegrees = MapControl.VisibleRegion?.LongitudeDegrees ?? 0.01;
    MapControl.MoveToRegion(new MapSpan(position, latDegrees, longDegrees));
    MapControl?.Pins?.Clear();
    MapControl?.Pins?.Add(pin);
    return Unit.Default;
}

This code will always place the pin at the new location. If the user taps the pin, it will display the information provided to the pin.

Side note: Managing to present that info is quite a challenge given this code, 9 out of 10 times I only managed to place the pin at a new position. But perhaps that's just me

Using the geocoder, we can now get the address for those coordinates:

private async Task SetAddress(Position p)
{
    var addrs = (await Geocoding.GetPlacemarksAsync(new Location(p.Latitude, p.Longitude))).FirstOrDefault();
    Street = $"{addrs.Thoroughfare} {addrs.SubThoroughfare}";
    City = $"{addrs.PostalCode} {addrs.Locality}";
    Country = addrs.CountryName;
    // ...
}

But now you have it, going from Coordinates to an address and back the other way. Easy right? Well, there is still one more thing; the default coordinates of the map point to Rome. And I get it. Rome has a lot to offer, but if your user is not currently in Rome, it might be quite a bit of pinching and swiping until the map will be useful. So long story short, why not use the user's position?

Marco? Polo!

Getting the users position is a piece of cake again, thanks to Xamarin Essentials. That is once you have required all the permissions as described in the link. With just a few lines we can get the address and set the position:

try
{
    var location = await Geolocation.GetLastKnownLocationAsync()
	var position = new Position(location.Latitude, location.Longitude);
	Position = position;
	// ... set address and stuff
}
// many exception handlers according to docs here


The user will get prompted the first time this code runs if they want to share their position. Just as a side note if you do not want to smother the user right of the batt with permission dialogues, you might want to put some thought into when this code should first be run.

So when the view appears, we can try to get the users position and tell the map control what part of the world to display:

Geolocation.GetLastKnownLocationAsync()
            .ToObservable()
            .Catch(Observable.Return(new Location()))
            .SubscribeOn(RxApp.MainThreadScheduler)
            .Subscribe(async location => { 
                var position = new Position(location.Latitude, location.Longitude);
                Position = position;
                await SetAddress(position);
            });

I hope you could see that it does not take much to go from tiresome form to a "fun" maps control.

GifRecordingSmall

And all by using standard libraries offered to you by Microsoft. You can find the complete sample on GitHub.

HTH

0 Comments

TitleImage

A while back, I used the F# type providers to create a conversion table. That post gave me the idea if it were possible to write an app that gets its data from a website. Perhaps you have also received the request for an app. Nothing expensive and actually all the data that should be displayed is already present on the web, i.e. this website right over here. So the question is: Could such an app be created without having to write a single line of backend code?

In this blog post, I will try to create an app for one of my favourite Xamarin conferences - the Xamarin Expert Day. So let's see if we can create our Fabulous Xamarin Expert Day App.

Getting the data

Type providers are a delightful feature of F#. During compilation type providers generate the data models represented in a data source. I have written a blogpost before on the topic of parsing HTML. This time we will use another toolset that comes with the F# Data NuGet package.

Since we want to get the information about the Xamarin Experts Day conference, we can try parsing the website directly. So we could use the following line to do this:

HtmlDocument.Load "https://expertday.forxamarin.com/"

Unfortunately, we live in the modern ages of JavaScript. I don't want to go on a tangent here, but just state the fact that the Xamarin Experts Day website seems to be loading the information about the talks and the tracks after the initial HTML has been loaded. Luckily when loading the page in a browser, we get an HTML version which contains all of the information we are looking for. So instead of loading the data directly from the website, we can load the data from a file. Budget projects have their limitations... 🙃

HtmlDocument.Parse("ExpertXamarin.html")

When we look at the HTML of the website (in the browser) we can see that the speakers are listed under the following HTML structure:

<li data-speakerid="df2bc5ca-5a6b-48a9-87ac-71c817d7b240" class="sz-speaker sz-speaker--compact ">
<div class="sz-speaker__photo">
  <a href="#" onclick="return ...');">
    <img src="...894db1.jpg">
  </a>
</div>
<h3 class="sz-speaker__name">
  <a href="#" onclick="return ...');">Mark Allibone</a>
</h3>
<h4 class="sz-speaker__tagline">Lead Mobile Developer Rey Automation, Microsoft MVP</h4>
</li>

So we know that we can get the image, name, tagline and id of every speaker. So let's create a record to store that information:

type Speaker = {Id:string; Name:string; Photo:string; Tagline:string}


Creating the record is not strictly necessary. But it does make working with the data a bit easier later on. Another plus is that we could capsule the type provider code in a .Net Standard library and then share it with non F# .Net code. No, you can't access type provider data types directly from C# and while some features in C# get inspired by F#. From what I have heard, I would not hold my breath, hoping to see type providers in C# anytime soon...

With the record in place, all that is left to be done is extracting the data from the HTML. Good thing that F# Data comes along with the HTML CSS selector. The HTML CSS selector allows filtering after ids, classes and tag types. So if we wanted to get the speakers name, we can filter the component and then extract the value as follows:

// .. other parsing methods
let private getName (htmlNode:HtmlNode) =
    htmlNode.CssSelect("h3.sz-speaker__name > a") |> Seq.map (fun h -> h.DirectInnerText()) |> Seq.head

let getSpeakers (html:string) =
    HtmlDocument.Parse(html)
        .CssSelect("li.sz-speaker")
        |> Seq.map (fun s -> {Id = (getId s); Name = (getName s); Photo = (getPhoto s); Tagline = (getTagline s)})

Similarly, the rest of the data can be accessed to fill the other fields in our record. Same goes for the tracks, again we would first create a record where we store the name, time, room and speaker id of every track. We will be able to link a track to a speaker with the id:

type Track = {Room:string; Time:string; Title:string; SpeakerId:string option}

let getTracks (html:string) =
    HtmlDocument.Parse(html)
        .CssSelect("div.sz-session__card")
        |> Seq.map(fun s -> {Room = (getRoom s); Time = (getTime s); Title = (getTitle s); SpeakerId = (getSpeakerId s) })

Now that we have all the data in place, it is time to get cracking on the app.

Fabulous Xamarin Experts App

Before we start writing our UI code, there is still that shortcut we took above with loading the information out of a file. While this works great when using a script in the mobile world, this means we have to pack that HTML doc into the app. There are two approaches: either put it into the Assets folder on Android and in the Resources folder (you can also use XCAssets...) on iOS or make an Embedded Resource in the .Net Standard library. While the first option would be what Apple and Google intended you to use when adding docs, you want to ship with your app. You will have to jump through some hoops to access the document. So let's again save some time and just pack the file as an Embedded Resource in our .Net Standard project. Embedded Resources are packed into your apps binary. This results in an awkward fashion of accessing the data. While described in the official docs here, this is how it is implemented in the Xamarin Experts Day Conference App (we need a shorter name...):

let loadFile filename =
    let assembly = IntrospectionExtensions.GetTypeInfo(typedefof<Model>).Assembly;
    let stream = assembly.GetManifestResourceStream(filename);
    use streamReader = new StreamReader(stream)
    streamReader.ReadToEnd()

With that out of the way. Let's create a list of all the talks with the title, time and room. When selecting a track, we will display the Information of the presentation along with the speaker info.

So the list we can put together like this:

let showTrackCell track =
    View.ViewCell( view =
        View.StackLayout(children = [
            View.Label (text = track.Title, 
                        fontSize = FontSize 22.)
            View.Label (text = track.Time + " in " + track.Room, 
                        fontSize = FontSize 14.,
                        fontAttributes = FontAttributes.Italic)
            ]))

let view (model: Model) dispatch =

    View.ContentPage(
        content = match model.SelectedTrack with 
                    | Some track -> showTrackInfo track model dispatch
                    | None -> View.ListView(
                                    rowHeight = 80,
                                    hasUnevenRows = true,
                                    margin = Thickness(8.,0.,0.,0.),
                                    items = (model.Tracks |> List.map showTrackCell),
                                    selectionMode = ListViewSelectionMode.Single,
                                    itemSelected = (fun args -> dispatch (TrackSelected args))
                                    )
        )

And the "detail view" would be done like this:

let showTrackInfo track (model:Model) dispatch =
    let speaker = match track.SpeakerId with
                  | Some speakerId -> model.Speakers |> Seq.tryPick(fun s -> if s.Id = speakerId then Some s else None)
                  | None -> None

    let addSpeakerInfo (speaker:Speaker) =
        View.StackLayout(margin = Thickness(0.,32.,0.,0.), children = [
                View.Label (text = "Speaker", fontSize = FontSize 22. )
                View.Image (source = (Image.Path speaker.Photo))
                View.Label (text = "Presenter: " + speaker.Name)
                View.Label (text = "Tagline: " + speaker.Tagline)
            ])
        
    let speakerViewElements = match (speaker |> Option.map addSpeakerInfo) with
                              | Some speakerInfo -> speakerInfo
                              | None -> View.Label(text = "Brought to you by the Organizers");

    View.Grid (margin = Thickness(8.,8.,8.,16.),
                rowdefs = [Star; Auto],
                children = [
                    View.StackLayout(children = [
                        View.Label (text = track.Title, fontSize = FontSize 22.)
                        View.Label (text = "In: " + track.Room, fontSize = FontSize 14.)
                        View.Label (text = "At: " + track.Time, fontSize = FontSize 14., margin = Thickness(0.,-4.,0.,0.))
                        speakerViewElements
                        ])
                    (View.Button (text = "Back", command = (fun () -> dispatch (TrackSelected None)))).Row(1)
                ])

You might have noticed that the talk description is missing. The website has a JavaScript function retrieve that additional information. I think it would be possible to replicate the JavaScript call to the backend and then parse through the answer

JSON/HTML answer. But INSERT-LAME-STATEMENT-WHY-I-AM-NOT-LAZY-HERE.

The app still feels a bit ruff I think I might have to follow up in another blog post and make it pretty 😎

Conclusion

In this little experiment, we set out to see if it would be possible to write a mobile app that displays the same information as already present on a website. And while there were some bumps in the road - I am looking at you JavaScript. It was indeed possible to write an app for the Xamarin Experts Day that runs on Android and iOS.

Though I really should get started on my next post and make the app pretty 😇

You can check out the entire app on GitHub.

This post is part of theF# advent calendar. Be sure to check out the other posts.

HTH

0 Comments

So a while back I posted about a little pet project I am working on along the lines of how hard can it be. To see the big picture, you can read the overview here. The first step is writing an Internet of Things (IoT) client app that runs on a device and sends sensor readings to the cloud. In the cloud, the Azure IoT Hub manages the client and also receives the data from the client.

PCB board

As the name implies, IoT devices connect to the internet. So not so different than your client app you might think at first. But when you start thinking about how IoT devices are deployed and run in the wild, there quite a few differences setting them apart. For one, the devices are usually not operated by a person. It's not a bring your own device (BYOD) scenario, the creator of the IoT device is generally in control of the software running on the device. Being in control also means that the device gets set up by the manufacturer and connects to the backend without or little human interaction. Since the device is out in the open and connected to the internet. It is generally a good idea if not mandatory to have a plan to update the device should a security breach such as Heartbleed ever occur. Though generally speaking the problems are often a lot more homegrown as this post from Troy Hunt nicely summarises. Another aspect that often arises with IoT solutions is the volume of data that has to be processed. While you can process data on the edge (on-site) - usually the desire is here to aggregate the data at a central point and act upon the live data or analyse the data in hindsight to find insights. It is often the data processing scenarios that bring the most significant business value and therefore are an essential part of the solution one tries to create with IoT solutions. Providing the developers with the challenge of creating a system that accomplishes to scale to meet the high data volumes running through the system. In short it is a different world than your traditional Xamarin, WPF, WinForms or Web client app.

The backend plays a significant role in IoT device scenarios. Therefore it comes at no surprise that you will find a lot of companies wanting to help you with your IoT endeavours. One of the solutions is the Azure IoT Hub which was created with the IoT challenges in mind. It provides many great features such as scalability to receive data from many million devices simultaneously, different messaging patterns to accommodate always connected vs IoT devices that may only have a connection now and then again. You can not only receive data from your devices with Azure IoT Hub but also send information to the device. It furthermore provides the means to inform your IoT devices that a new software/firmware update is available. And since it is running in the cloud, scalability is baked into the product.

For setting up the IoT Hub, I recommend you follow these instructions.

You can create one free IoT Hub instance per account, which is the one I will be using for this blog post.

With the IoT Hub setup, let's set up our local environment. You can manage your IoT Hub all from within PowerShell - oh yes feel that power of the shell (trying to improve my godfather jokes here...) all you will have to do is install the Azure CLI. Then install the IoT extension. If you did not have the tools already installed, be sure to first login to Azure on PowerShell with the following command:

az login

After being logged in and having the extensions you can do all sorts of stuff right from within PowerShell. For instance, we can create a new device like this:

az iot hub device-identity create --hub-name IoTEndpoint --device-id test-device-01

Note that the --hub-name must equal the name you gave your IoT Hub on Azure. You are free to choose a different name to register your device after --device-id. Once you have a device registered. You can send messages as the registered device:

az iot device send-d2c-message -n IoTEndpoint -d test-device-01 --data 'Hello IoTHub'

No error means success but, another handy command is seeing which messages the IoT Hub is receiving:

az iot hub monitor-events -n IoTEndpoint

If you now open a second PowerShell to send a message as a registered device, you will see IoT Hub receiving the message.

Showing received message

With all the tools installed and having a device registered, we are ready to implement our client. There are more commands which you can use with Azure CLI, you can find the full list of commands here.

Implementing an IoT Client

The Azure IoT Hub provides an SDK which clients can use to communicate. The SDK is available for .Net, Node.js, Python, C and Java. However can't or don't want to use the SDK you can manually connect to the IoT Hub over HTTP, MQTT or AMQP.

For my first endeavour, I used the Azure IoT Dev Kit. It is a fantastic value for money - perhaps you even have received one as a gift at an event you attended? The dev kit comes with many sensors, and an RGB LED, display, AUX, a USB- and WiFi-connection. That being said if you do not own a device, you can still get started with the SDK for .Net. The SDK runs on .Net Standard. So you can write a .Net Core client which using the NuGet package.

So we could implement a .Net Core Console app to implement our solution. Note since the library can be installed in a .Net Standard project you could extract all the IoT logic code into a .Net Standard library. Being lazy aka keeping the solution of this blog simple I will implement all of the code directly in the .Net Core project. The first thing we will want to do with our app is to connect to the backend. There are different ways how we can achieve this with the IoT hub. For getting started, we will take the easiest route, which is usually not what you want to deploy to production - i.e. using a connection string with an API key as an authentication mechanism:

var device = DeviceClient.CreateFromConnectionString("HostName=IoTEndpoint.azure-devices.net;DeviceId=test-device-01;SharedAccessKey=THIS-IS-WHERE-THE-SHARED-KEY-WOULD-BE-DISPLAYED");

You can retrieve this connection string from within the Azure Portal under your IoT Hub, IoT devices, in my case test-device-01 and then select either the Primary or Secondary Connection String.

Once connected, we can start to send sensor readings serialized to JSON:

var json = JsonConvert.SerializeObject(measurement);
var message = new Message(Encoding.UTF8.GetBytes(json));

await device.SendEventAsync(message);

Since .Net Standard runs on nearly every OS you can think of, you could extract the code above to run on a Raspberry Pie or Android or INSERT-YOUR-TARGET-HERE using actual sensors. And since the SDK is also available for other languages such as C version, we can use it for writing apps for the Azure Dev Kit.

Can I have the rest of the client code? Yes - if you stick around until the end you will find a link to the full source code of the client on GitHub.

Azure IoT Dev Kit Client

I have to recommend following the official docs by Microsoft on how to set up the Azure IoT Dev Kit with Visual Studio Code, which will show you how to initially set up the device and connect it to the IoT Hub. Word of advice make sure you follow all the steps of the documentation and do not leave out any parts such as installing the USB driver on your Windows machine. Talking out of experience from a friend here of course

Microsoft offers quite a few samples for the Dev Kit. The samples can be loaded directly onto the device using Visual Studio Code. I took some inspiration for the .Net Core Client above from the remote monitoring tutorial - I skipped the Azure stuff since I will want to process the data differently. Only changes I made to the C code was the changing the unit of the atmospheric pressure (atm) to hPa. Oh and of course removing the conversion from Celsius to Fahrenheit- my brain will not compute the imperial system

Note that a lot of IoT devices do not come with an operating system installed due to the restricted resources available on the device. These restrictions are often the reason why many programs are written in C. If you are a .Net developer like myself, you will probably miss a lot of conveniences. Then again you might find some consolidation in the knowledge that your code will be very efficient

Another device that I am looking forward to checking out soon is the Meadow by Wilderness Labs. The great thing about the Meadow is that you can write your IoT client code with C# for the device. Good news is they are open for pre-orders, but you might have to wait in line until all of the Kickstarter campaign supporters have received theirs.

Once you have installed the app on the dev kit and connected it to WiFi, you will be able to see the messages arrive on the IoT Hub dashboard.

Graph showing the messages being received by the Azure IoT Hub.

And by using the CLI tools command from before we can start a listener that will receive every message sent to the Azure IoT Hub:

ReceivingDeviceMessages

You will be able to see the raw JSON coming in on the IoT hub.

Conclusion

Setting up the first IoT device can be a bit of a daunting task since there are a few moving parts. First getting to know the client or even just knowing how to implement a client in .Net Core, then the Azure IoT Hub part. For me, it was good to notice that it is okay to start small and gradually learn the possibilities provided by Azure IoT Hub. But there is still so much more packed into the Azure IoT Hub. For instance updating a device, device twins or communicating from the cloud to a device - if you are interested in a detailed list, be sure to check out the official page here.

In the next blog post of the series, we will look at how to process the data in the cloud. And how to forward it to clients. Where we will visualise the data for the user. So stay tuned and check out all of the client code on GitHub.

HTH