Xamarin WiFi SmartConfig integrating ESP8266 and ESP32

SmartConfig is a really interesting feature available in low-cost ESP board.

If you ever played around with Arduino and its various brother and modules for wifi communication, you should have faced one common issue. Setting up the WiFi connection.

In a real world application you can’t just hardcode the wifi password in every single appliance of your customer.
They expect you to provide them with a clever tool or app that allows them to configure their new IOT thing just by pressing a button.

This actually possible thanks to this SmartConfig feature on ESP boards. Basically the WiFi start sniffing the air looking for a special UDP package, which has been tailored to contain alla the necessary information to connect to a WiFi in range.

SmartConfig comes with a two libraries for iOS and Android that can be integrated in your apps to make the SmartConfig magic. You can find on both store a thousand apps to make the SmartConfig magic.

Bad guys like us love make thing cross platform with Xamarin

I was so disappointed when I figured out that there was no Xamarin Library for Smart Config. Fortunately Xamarin has a powerful system to wrap up external libraries and make them available to your Droid and iOS projects, and I spent a few hours making them up for you.

You find Smart Config for Xamarin.iOS, Xamarin.Droid and Xamarin.Forms here on Nuget

or just cut and paste and put it on PM

Install-Package EspTouchSmartConfigXamarin -Version 1.0.3

and for the ones like me who loves terminal

dotnet add package EspTouchSmartConfigXamarin --version 1.0.3

How to use SmartConfig in your Xamarin.Forms project

First of all you should install the package from nuget in all your project (Forms, iOS, Droid). There is no EspTouch Library for Windows Phone from the ESP team, so WP developers you should have a look around or implement your own SmartConfig you can start from Texas Instruments Spec.

You need then to make available to forms the real implementation of the SmartConfig Library using Dependency Service.
This is quite straight forward as we already provided a interface that wraps the original methods of the Library.

 
     public interface ISmartConfigTask
     {

         ISmartConfigResult executeForResult ();
 
         List executeForResults (int expectTaskResultCount);
 
         void SetSmartConfigTask (string ssid, string bssid, string passphrase);
 
         void SetSmartConfigTask (string ssid, string bssid, string passphrase, bool isHidden);
 
         void SetSmartConfigTask (string ssid, string bssid, string passphrase, bool isHidden, int timeoutMillis);
     }

The logic behind launch a process that start sending UDP packages on the active WiFi and looks for a package back from the device, when the package is back an ISmartConfigResult is created with all the information from the device. The most important information is the device’s IP in the network, so that you can call some endpoint in your device and expect a JSON response or so.

Last you need to instantiate a new Task in Forms, wait for answer(s) and make your stuff. Let’s the whole process.

Xamarin.iOS

Install the package from Nuget

Install-Package EspTouchSmartConfigXamarin -Version 1.0.3

Create a new class SmartConfig_iOS that is the real implementation of ISmartConfig. If you have not added the Nuget package to the PCL project than you’ll get an error, which will be fixed as soon as you’ll install it.

 using System;
 using EspTouchMultiPlatformLIbrary;
 using Xamarin.Forms;
 
 [assembly: Dependency(typeof(yournamespace.iOS.SmartConfig_iOS))]
 namespace yournamespace.iOS
 {
     public class SmartConfig_iOS : ISmartConfigHelper
     {
         public SmartConfig_iOS()
         {
         }
 
         public ISmartConfigTask CreatePlatformTask()
         {
             return new SmartConfigTask_iOS();
         }
     }
 }

Xamarin.Droid

Install the package from Nuget

Install-Package EspTouchSmartConfigXamarin -Version 1.0.3

Create a new class SmartConfig_Droid that is the real implementation of ISmartConfig. If you have not added the Nuget package to the PCL project than you’ll get an error, which will be fixed as soon as you’ll install it.

 using System;
 using EspTouchMultiPlatformLIbrary;
 using Xamarin.Forms;
 
 [assembly: Dependency(typeof(yournamespace.Droid.SmartConfig_Droid))]
 namespace yournamespace.Droid
 {
     public class SmartConfig_Droid : ISmartConfigHelper
     {
         public SmartConfig_Droid()
         {
         }
 
         public ISmartConfigTask CreatePlatformTask()
         {
             return new SmartConfigTask_Droid();
         }
     }
 }

Xamarin.Forms

Install the package from Nuget

Install-Package EspTouchSmartConfigXamarin -Version 1.0.3

The most work is here in Xamarin.Forms, as we should expect from a cross platform solution. This is the unique advantage of Xamarin. 99% of your code is portable.

First create an helper class for the DepencyService, this will fix any previous error in iOS and Droid projects.

 using System;
 using EspTouchMultiPlatformLIbrary;
 
 namespace yournamespace
 {
     public interface ISmartConfigHelper
     {
         ISmartConfigTask CreatePlatformTask();
     }
 }

In your ViewModel or in your Code Behind or wherever your app need to configure the device you should call the Smart Config Task in this way:

ISmartConfigTask smartconfig = DependencyService.Get<ISmartConfigHelper>().CreatePlatformTask();
 
smartconfig.SetSmartConfigTask(Ssid, Bssid, Passphrase, false60000);

await Task.Run(() =>
{
    var result = smartconfig.executeForResult();
    if (result.isSuc())
    {
        SetupRequired = false;
        DeviceIp = result.getInetAddress();
    }
});

It is a really simple example, you first have to get the SmartConfigTask object from the Dependency Service and you set a few parameters:

Ssid = your network ssid (the one you want to configure)
Bssid = your network bssid (the one you want to configure)
Passphrase = your network passphrase (the one you want to configure)
isHidden = true or false if the Ssid is hidden
Timeout = how long you’ll wait for answer. 60 sec might seems too much, but sometimes are necessary.

Secondly, you need to wrap the call to “executeForResult()” in a Task, if you don’t do that this task will run on main thread and the whole app will starve waiting for its completion.

Conclusions

SmartConfig is a powerful feature of ESP boards, but for the ones who are already using the ESP32 that integrates BLE, than it would be nicer to use Bluetooth to send configuration info to your board. I will soon publish an article on this!! Stay connected and follow me on twitter to keep up to date!

The Library are open source, you can contribute to the porting of the original library on GitHub

https://github.com/lucafabbri/EspTouchBinding-Xamarin-iOS-Droid

Comment below, I usually make a lot of typos, I apologize!

Annunci

Xamarin.Forms Horizontal Listview Explained

The greatest advantage of using Xamarin Forms is obviously the Binding system and the viewmodels. Especially, collections of data fits perfectly with ListViews allowing views prototyping and decoupling of views and models.

Quite often you need to show List of elements in a row, perhaps with a scrolling pane. For instance, you are trying to show an horizontal list of images or buttons which are not predetermined, but changes on user inputs or remote response.

If you are getting started with Xamarin.Forms documentation really not provide any info about Horizontal ListViews and you think they can’t be done, so you start browsing the Forum and Stackoverflow, which quite often redirect you to download a component, to write Platform specific code. Things mess up quite soon.

Fortunately, your search is over. You can make Horizontal ListViews with Bindings without doing much more than write few Xaml rows of code. Let’s go understand the logic.

Horizontal ListViews in Xaml basics

First, you have to know that each element in Xaml derive from base class that has Rotation property.

  • Rotation property is used to get and set the current Rotation of the element.

First step to create an Horizontal ListView is Rotate 270 degrees (for left to right) or 90 degrees (for right to left) and the inner View element should compensate this rotation as follows:

<ListView Rotation="270" ItemsSource="{Binding Items}">
 
  
   
    <ContentView Rotation="90">
     
    
   
  
 

If you try this code you can see that dimensions are all messed up. The problem here is that listview sizes are calculated before rotation. If your list view is wider than taller you’ll probably see it floating vertically on other elements of the page. This is not the required behavior.

Let’s see how to fix layout.

Fixing Horizontal ListView Layout

The trick here is all about wrapping the ListView in a container and constraint the ListView to match conteiner bounds.

The element in Xamarin.Forms to do this is the Relative Layout.

First, we wrap the ListView in a RelativeLayout element and set the Layout Height to the desired height:

<RelativeLayout HeightRequest="60">
 <ListView Rotation="270" ItemsSource="{Binding Items}" RowHeight="60">
   ....
 

In this example we will show square images, so we’ll also set RowHeight in ListView equal to RelativeLayout Height. Note that as the ListView is rotated the ListView.RowHeight property describe how wide the element is, while RelativeLayout.HeightRequest property describe how tall the element is. Just not get confused with rotation and names.

Second, we need to tell the ListView to bind to RelativeLayout bounds. This is possible setting the RelativeLayout constraints in the child element.

 <ListView Rotation="270" ItemsSource="{Binding Items}" RowHeight="60"
 RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=-30}"
 RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=-0.5, Constant=30}"
 RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=60}"
 RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}">
   ....
 

With XConstraint and YConstraint we adjust ListView X,Y anchors, then we set its Width (don’t forget it’s rotated so it correspond to how tall is shown) to a constant equal to parent height and we set its Height (again its shown width) to its parent width.

If you run this code now you should see the ListView much better. But probably you won’t see any element as they are now shifted out of the visible pane.

Last, indeed, we need to translate the content view on the X axis and make sure that images will fit the available viewport. Hereafter the whole code:

 <ListView Rotation="270" ItemsSource="{Binding Items}" RowHeight="60" SeparatorVisibility="None"
 RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=-30}"
 RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=-0.5, Constant=30}"
 RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=60}"
 RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}">
  
   
    
     <ContentView Rotation="90" Padding="1" TranslationX="60">
      <Image Source="{Binding Source}" HeightRequest="58" WidthRequest="58" Aspect="AspectFill">
     
    
   
  
 

Here you are! Your Horizontal ListView for Xamarin.Forms in XAML is ready

You can now play with Rotation, Width and Height to obtained the desired effect. Just don’t forget that ListView Width and Height refers to element Width and Height and do not take in consideration that you have Rotate the element.

If you have downloaded strange components get rid of them, notwithstanding if you have written a fantastic code and you want to share just put a comment below. We are keen to know about other solutions for the Best Horizontal ListView in Xamarin.Forms.