Thursday, February 12, 2015

Windows IoT on Galileo – Accessing Azure storage services



Now Galileo is capable of accessing azure storage services after several tries and tweaks. As you know Windows developer Program for IoT released the Casablanca C++ REST SDK for accessing cloud services from Galileo but this is not sufficient to access azure services and we need to port or develop another layer on top of it to access specific Azure services. I searched and fortunately found a C++ library that can specifically made to access Azure storage services and again that is using the Casablanca C++ REST SDK. Wow!!!. But this happiness was not withstood for long time after building it and running it simply on Galileo. Let’s get hands dirty!!!

Prerequisites

  • Supported for both Intel Galileo Gen1 and Gen2.
  • Latest OS update released on 21-Nov-2014 (common .wim for Gen1 and Gen2) for    lightning (improved performance on I2C, SPI, and UART etc..) 
  • Visual studio 2013 with Windows IoT SDK (Visit: windowsondevices.com for more details) and Microsoft IoT C++ SDK and its dependent NuGet Package is required.
  • NuGet package for C++ REST SDK (Casablanca) Version ≥ 2.0.1 (tested with version    2.0.1 and 2.2.0)
  • Source code for C++ REST SDK. Go through the instructions given in the below link.




Building the Casablanca C++ REST SDK
·         Refer the topic “Build Casablanca” and “Place the lib on the Galileo” on this link http://ms-iot.github.io/content/Casablanca.htm


Building the Azure Storage Client library for C++
  • Go to Azure Storage Client Library for C++ 0.3.0-preview  link and download the source code by clone or Download zip option. Unzip it and you can find the azure-storage-cpp-0.3.0-preview.
  • Open the Micosoft.WindowsAzure.Storage.v.120.sln file.
  • Go to Project » Properties » Configuration Properties » C/C++ » Code Generation 
    • Set Enable Enhanced Instruction Set = No Enhanced Instructions (/arch:IA32) for both Debug and Release
  • Install the C++ REST SDK Nuget as shown below through the package manager console.
    • Install-Package cpprestsdk  –version 2.2.0
  • Build the solution.
  • Navigate to \\mygalileo\c$\test in file explorer (create the “test” folder if necessary).
  • Copy the wastorage.dll file (generated during the build step and placed at  \ azure-storage-cpp-0.3.0-preview \ Micosoft.WindowsAzure.Storage \v120\Win32\Debug), into the “test” folder from the previous step.

Building the Galileo Wiring Application
  • Create a “Galileo Wiring App” solution, let’s named as GalileoAzureStorage. You can download it from the below codeplex link. https://azurestorageclientgalileo.codeplex.com
  • Add the source code for accessing the table shown in the prerequisites to the setup() function of Main.cpp. Install the C++ REST SDK and Azure Storage client library NuGet packages as shown on the prerequisites in addition to the basic Microsoft IoT C++ SDK and its dependencies.
    • Install-Package cpprestsdk  –version 2.2.0
    • Install-Package wastorage   -Version 0.3.0-preview –Pre
  • Build the application, now your GalileoAzureStorage.exe is ready.

Executing the application
·         Copy both the cpprest120d_2_2.dll and wastorage.dll to Galileo as mentioned in previous topics.
·         Run the program through remote windows debugger and now the problem starts. The program doesn’t work as expected and you can see the following error message in the output window.
Fig: Error Entry not found


The error shows that the APIs linked during the build is not found in the runtime. Which means the DLL contains the corresponding API is missing or couldn’t able to forward to the corresponding DLL in the OS.

Troubleshooting
I have reported this issue to Microsoft through connect last month and IoT team has proposed some suggestion to resolve the issues and now it is published on the windowsondevices.com as forwarder and Stubs. Thanks for Microsoft support to achieve this. 

Linking Azure Storage client with Mincore.lib
  • Build the Azure storage client library by linking with mincore.lib instead of using the default library.
  • Go to Micosoft.WindowsAzure.Storage.v.120 Project >> Properties >> Linker >> Input.
  •  Remove the default entries (legacy libraries) in additional Dependencies and add mincore.lib and xmllite.lib (This is required for this project.)
Fig : Default Libraries
  •  Make sure that you have de selected the inherit option as shown in the below image.

Fig ) Adding Mincore.lib
  • Add the list of libraries you have to exclude, in the “ Ignore Specific Default Libraries”
Fig) excluding the default libs.
  • Build and Copy the wastorage.dll to \\mygalileo\C$\test folder. and run the application but still you will get the same “Entry Not Found” error.

Find the Missing APIs and its dependencies
  •  Refer the Diagnosing a failing application topic on the Forwarder and stubs link.
  •  Replace the Node.exe with GalileoAzureStorage.exe in the command given in the above link.
  •  Run the application again from “Remote Windows Debugger”.
  •  Now the detailed APIs and its corresponding DLLs are listed in your output window while loading the application and finally found the Missing APIs Name.
  •  Following two APIs Entry Points are missing.
o    UnregisterClassW
o   MessageBoxW

·         Windows on Galileo is derived from Windows Phone 8.1. This mobile edition of Windows uses the Windows 8.1 API Set. You can find the list of APIs supported in mincore library in this link.

Forwarder and stubs
If the missing APIs are listed in the Windows 8.1 API Set, you can choose forwarder option. Refer the “Forwarder” topic in the Forwarder and stubs link. Our case, the above listed APIs are not listed in the Windows 8.1 API Set. These two APIs are belongs to User32.dll but unfortunately the Galileo Windows version of User32.dll doesn’t contain the two APIs. So you have to develop a stub User32.dll for the APIs and link it while loading the application.

Building User32.dll
Fortunately you already have the User32 stub project created by Microsoft IoT team and now you can download the project, add the stub and build your own user32.dll as explained in the “Forwarder and Stub repository” topic in the Forwarder and stubs link. You can also contribute back to the Github. I have summited my pull request after this changes.
·         Add the missing API names in the sources.def file in the User32 project as shown below.

Fig: sources.def of User32 Project
  • Add the stubs for these API in stubs.cpp.

Fig: Missing APIs stubs in Stubs.cpp

  •  Build it and copy the User32.dll to \\mygalileo\c$\test
  • Make sure the cpprest120d_2_2.dll and wastorage.dll are in the same location as mentioned in the previous step.
  •  Run the GalileoAzureStorage.exe from “remote windows debugger”. Now the program loaded successfully without loading issues but unfortunately we have another issue happened during application execution. Come on! Let’s not give up.

Exception due to server “Authentication Failed”
After captured the azure storage exception it shows that the server failed to authenticate for the request due to incorrect authentication header as shown below.
Fig: Authentication Failed

But the strange behaviour is, the same application (binaries along with the DLLs) run without any issue on windows 8.1 PC. Good news is, At least I have an option to trace the authentication header difference between PC and Galileo.
Of course, this approach worked well. I have captured the authentication header of PC and Galileo as shown below. If you compare it you can find the difference in the x-ms-date member of the Authentication headers between PC and Galileo.
Fig: Correct date and time format in PC for x-ms-date

Fig: Wrong date and time format in Galileo for x-ms-date
If you trace the code, The x-ms-date member is filled by the function called shared_key_authentication_handler::sign_request() of “azure-storage-cpp-0.3.0-preview\azure-storage-cpp-0.3.0-preview\Microsoft.WindowsAzure.Storage\src authentication.cpp” file.
Again don’t give up. Let’s trace further to find the root cause of this issue. if you see the source code of the above function there is some other utility function is called inside to get the date and time to fill the x-ms-date member of the authentication header.
Fig: Getting time from Date time utility

Workaround in C++ REST SDK
If you trace it further, This “datetime” utility function is a part of the C++ REST SDK. You can find the function datetime::to_string(date_format format) in casablanca\casablanca\Release\src\utilities\ asyncrt_utils.cpp. This function using the GetDateFormatEx() WIN32 API to retrieve the RFC_1123 date format. Unfortunately this API not returns the required time format in Galileo but in Windows 8.1 PC is it working as expected. So here I made a workaround for this issue. Comment the existing code related to GetDateFormatEx() and replace it with our own code as shown below.

Fig) workaround to get the RFC_1123 date format
·        
  •  Rebuild the C++ REST SDK and copy the cpprest120d_2_2.dll to \\mygalileo\c$\test\ folder.
  • Run again the GalileoAzureStorage.exe from “remote windows debugger”. SUCCESS !!!!.
  • You can’t see the table entries in Azure portal, instead there are some third party tools are available to play with the tables. I used Azure storage explorer 6 downloaded from codeplex.
  • GalileoAzureStorage.exe will perform create table , add data, retrieve data and delete table.

Conclusion
GalileoAzureStorage project available on codeplex.Now pushing sensor data to cloud is a cakewalk from Windows on Galieo. Enjoy real IoT-ing on Galileo.

2 comments:

Unknown said...

Vinoth,

I finally found some time to try this out. It worked exactly as you described. Your explanations of the problems and their solutions saved me a lot of time, and your detective work on the Authentication date problem was truly impressive. Thanks!

I've just started logging some sensor data to Azure based on the sample code from your "sensors to server" article. So far, so good.

If you are still using your Galileo with Azure, what has your experience been with stability: does the Galileo keep posting to Azure without any downtime or errors?

Thanks,

Dan.

Vinoth said...

Hello Dan,
Thanks for reading this article. I testes the Azure storage services for few hours from Galileo.I didn't noticed any issue. But i tested the Azure Service Bus (event hubs) for 24 hours from Galileo. i didn't noticed any issue.
Regards,
Vinoth