Building Web Based Temperature/Humidity Monitor App With Raspberry PI 3 and Azure IoT Hub

2. April 2017 07:39

ASP.NET MVC Azure Cloud IoT Projects Raspberry Pi Web Windows 

I was planning to build a web based temperature/humidity monitoring app with Raspberry PI 3 and Windows 10 IoT Core. I have playing around with Raspbian for a while now and this time I wanted to try something different. I have been using Python to write application for Raspberry PI, Windows IoT Core with C# will be something new for me and therefore, this time I choose to go with Windows 10 IoT Core.

Here is the list of things to get started:

  • Raspberry PI 3 with Windows 10 IoT Core
  • Adafruit BME280 Temperature Humidity Pressure sensor\
  • Jumper wires
  • Power Bank
  • Visual Studio 2015/2017
  • IoT Dashboard
  • Azure account

Setting up the PI with Windows 10 IoT Core is a very straight forward process. You can read about it more here. I recommend to connect the device to your Wi-Fi network. This will give you a benefit to move your device around. The problem for the first time users will be that the device will not auto-connect to the Wi-Fi network. To solve this problem, you need to use a wired LAN connection from the network or from the local computer. Once plugged in you will be able to see the device in the IoT dashboard from where you can go to Device Portal and connect to the Wi-Fi network. After the connection is successful, you can then remove the LAN cable. To follow the exact steps, head over to this documentation. This is how your device will get displayed in the IoT dashboard.

Getting things ready in Azure

You can set up things in the cloud from the Azure Portal as well as from the IoT Dashboard itself. From dashboard you can create and provisioned a new IoT Hub and register the device in that Hub. Here is how you can do that. First sign-in to your Azure account by clicking the Sign-In option in the left hand side bar. After the sign-in is successful, you will be prompted with the below screen where you can provision a new IoT Hub and add your current device in the hub.

I am skipping the step for setting the IoT Hub from the Azure Portal as there is a good documentation available at Azure Docs. Pushing data to the IoT Hub with the SDK is easy but you can't make use of the IoT Hub alone to read that data and do your work. Therefore, you also need to set up a Queue to read that data. As of now, you cannot create a Queue from the new Azure Portal instead you have to head towards the old portal at manage.windowsazure.com and create a queue from there. To create a queue, click the New>App Services>Service Bus>Queue>Quick Create. Fill in the details to create a new queue.

Make sure that the region you are selecting here for the queue, it should be the same as your IoT Hub region. If you select a different region than that of your IoT Hub, you will not be able to associate this queue with the hub endpoint.

In the Azure Portal, to associate this queue with the IoT Hub endpoint, click the Endpoints and then click Add to add the queue to the endpoint.

Setting up the circuit

Now as you have the device and the OS ready, you can now build the circuit. The BME280 sensor can be used with both I2C and SPI. For the project, I am using I2C. Below is the Fritzing diagram for your reference. You can download the Fritzing sketch file on Github repo.

Creating Device Application

I am using Visual Studio 2017 Enterprise Edition to build the device application and the web monitor application which I will be hosting in the cloud. For creating the device application, start with selection the Windows Universal project templates and then select Blank App (Universal) template.

There is a project template available for Visual Studio which will let you build applications for Raspberry PI. The problem with that project type is that you will not be able to make use of the libraries or the SDK available for .NET yet. You can still build applications with this project type but you have to make use of REST API and using REST API is not as straight-forward as SDKs.

After the project creation is successful, you need to add below dependencies which will let you connect to IoT Hub and have a device to cloud communication. Below are the NuGet packages you need to install.

This package will enable you to have a device to cloud communication.

Install-Package BuildAzure.IoT.Adafruit.BME280

This package is the wrapper for the BME280 sensor.

Install-Package Microsoft.Azure.Devices.Client

Add the below namespaces in the Main.xaml.cs file.

using Newtonsoft.Json;
using Microsoft.Azure.Devices.Client;
using BuildAzure.IoT.Adafruit.BME280;

Declare the variables.

private DeviceClient _deviceClient;
private BME280Sensor _sensor;
private string iotHubUri = "piiothub.azure-devices.net";
private string deviceKey = "Tj60asOk5ffVAT6a6SvZKMOqo8DYKSwWV7eQ2pLf0/k=";

The iothuburi is the URL for the IoT Hub created in the Azure portal or from the IoT dashboard. You can get the device key from the Device Explorer section in the IoT Hub. You can see how to get the Key from the Device Explorer from the below screen shot. I am using the Primary Key as a devicekey in my code.

In the constructor, initialize the DeviceClient and BME280Sensor objects. I have commented out the InitializeComponent(), but if you want you can keep it as it is.

public MainPage()
{
    //this.InitializeComponent();
    deviceClient = DeviceClient.Create(iotHubUri, new DeviceAuthenticationWithRegistrySymmetricKey("raspberrypi", deviceKey), TransportType.Mqtt);
    _sensor = new BME280Sensor();
    DeviceToCloudMessage();
}

Now add a function named DeviceToCloudMessage which will connect to the IoT Hub using the device key, read the sensor data, serialize the data in JSON format and send it to the IoT Hub. Add this at the very bottom of the constructor.

private async void DeviceToCloudMessage()
{
    await _sensor.Initialize();
    float temperature = 0.00f;
    float humidity = 0.00f;
    while (true)
    {
        temperature = await _sensor.ReadTemperature();
        humidity = await _sensor.ReadHumidity();
        var sensorData = new
        {
            date = String.Format("{0}, {1}, {2}",
                                 DateTime.Now.ToLocalTime().TimeOfDay.Hours,
                                 DateTime.Now.ToLocalTime().TimeOfDay.Minutes,
                                 DateTime.Now.ToLocalTime().TimeOfDay.Seconds),
            temp = Math.Round(temperature, 2),
            humid = Math.Round(humidity, 2)
        };
        var messageString = JsonConvert.SerializeObject(sensorData);
        var message = new Message(Encoding.ASCII.GetBytes(messageString));
        await deviceClient.SendEventAsync(message);
        //Debug.WriteLine("{0} > Sending message: {1}", DateTime.Now, messageString);
        Task.Delay(5000).Wait();
    }
}

The date property in the sensorData type is being set in this specific way because we want to see the graph continuously moving. I can also read Pressure from the sensor but as I am not interested in showing this data, I am skipping it out. If you want you can use it but you also have to change the web app to show this reading. Before I can send this data to the IoT Hub, I am serializing the sensorData object and use ASCII encoding to get the byte[] and pass it to the Message class constructor. The last step is to send the message to the hub by using the DeviceClient class SendEventAsync method. In the last line I am adding a delay of 5 seconds between each reading. You can increase the time and see how the chart renders. I recommend not to go below this time delay as this might give you some false readings from the sensor.

I took this code from the documentation here and tweaked it to have the real data from the sensor connected to the device. Press Ctrl+Shift+B to build the solution. Navigate to Project and then click <project> Properties. Under Debug section, set the Start Options as shown below. Notice that the Platform is set to ARM and Configuration is Active (Debug). When you are done with debugging the code and ready to deploy the code to the device you need to change it to Release.

Unlike Raspbian, where we ssh or RDP into the device and compile or build the code, Windows 10 IoT works in a different way. You need to remote deploy the application from Visual Studio. Also, if you have enabled the remote debugging on the device, you also have to add the port number to the Remote Machine value and set the Authentication Mode to None.

NOTE: When you make changes to device application, you also need to change/increment the version of the application in the Package.appxmanifest file. If you miss this step then the application deployment will fail.

To deploy the app to the device, click the Build menu and select Deploy <Project Name>. If you are deploying the application for the first time, it will take some time to get deployed. After the deployment is successful, you will see the application under the App section. At this moment, the application is stopped. To start the application in the, click the Play button in the list to start the application. The App Type show the type of application or you can say the mode it is running on. When I created the application, I selected the UWP application and therefore, it will always run in the Foreground type. The reason I choose this application type (UWP) is because I can then use the SDK to communicate with the IoT Hub. If you want to create a Background application type then you can download this Visual Studio Extension for 2017 and this for Visual Studio 2015 which will let you build the background application. Keep in mind that you cannot use any SDK library with this project type. All you have now is the power of REST API which is not very easy to use.

Setting the Web App

You can build any kind of app to visualize the data, but because the SDK support for .NET is good I am going to set up a simple MVC application using .NET Framework. As of now, you cannot use Azure SDK with .NET Core application and also it looks like the team does not have any plans to shift their focus for releasing the SDK for .NET Core anytime soon.

Start with installing NuGet packages. First with the package that will let you read the data from the Queue.

Install-Package WindowsAzure.ServiceBus

Because this is a real-time application you also need to install SignalR

Install-Package Microsoft.AspNet.SignalR

After these packages are installed, You need a way to visualize the temperature and humidity received from the queue. To do this you can use any jquery chart plugin or any other library of your choice. I will be using Google Charts in my app, Line Charts to be precise. Installation is straight forward for the charts and you can play around with different options to tweak the look and feel of the chart. I am going to add the chart code in the Index.cshtml file. Below is the complete code for the chart to render.

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
<script>
    var data = [];
    var chart;
    google.charts.load('current', { packages: ['corechart', 'line'] });
    google.charts.setOnLoadCallback(loadChart);
    var hub = $.connection.ioTHub;
    $.connection.hub.start();
    hub.client.iotHubNotification = function (d) {
        console.log(d);
        var pi = JSON.parse(d);
        var time = pi.date.split(',');
        var temp = pi.temp;
        var humid = pi.humid;
        data.addRows([[[parseInt(time[0]), parseInt(time[1]), parseInt(time[2])], temp, humid]]);
        var options = {
            height: 250,
            hAxis: {
                title: 'Time'
            },
            vAxis: {
                title: 'Temperature / Humidity',
                gridlines: { count: 22 }
            }
        };
        chart.draw(data, options);
    };
    function loadChart() {
        data = new google.visualization.DataTable();
        data.addColumn('timeofday', 'Time');
        data.addColumn('number', 'Temperature');
        data.addColumn('number', 'Humidity');
        var options = {
            height: 250,
            hAxis: {
                title: 'Time'
            },
            vAxis: {
                title: 'Temperarture / Humidity',
                gridlines: { count: 22 }
            }
        };
        chart = new google.visualization.LineChart(document.getElementById('chart_div'));
        chart.draw(data, options);
    }
</script>

I make use of the sample code from the examples at Google Charts and used it along with some minor tweaks to suite my needs. loadChart() function is called for the first time when the page is loaded and then I have a SignalR hub which updates the chart with the same option sets that I have in the loadChart() function. I add 3 data columns to display the data in the chart. There are few things that I would like to talk about in the above code. First is the timeofday is displayed on a X-Axis because time is continuous and I want to update the chart with time. Second, the gridlines property of the vAxis let you set how many horizontal rows you want to see in the graph. I have increased it to quite a significant number because I want to see the graph in more detail. You can play around with these settings and see what looks better for you. Third, the response I receive in the hub is in string format and therefore, I have parsed that string to JSON in order to read it and set to the rows. Also note that I have leave the console.log in the above code so that when you run the web app you can see the raw data in the console.

In the HomeController.cs, first I will set the connection string to the queue which I have associated with the IoT Hub endpoint in Azure and set the queue name along with the IHubContext for SignalR communication.

private string connectionString = "Endpoint=sb://iothubqueue-ns.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=88kJcD1mvJnO1jtiiY+AcUtIoinW//V/lF2WicOJ50s=";
private string queueName = "iothubqueue";
private IHubContext _hubContext;

In the constructor, initialize the IHubContext object.

_hubContext = GlobalHost.ConnectionManager.GetHubContext<IoTHub>();

Here is the code for the IoTHub class:

using Microsoft.AspNet.SignalR;
namespace IoTHubTempWebApp.Hubs
{
    public class IoTHub : Hub
    {
        public void IoTHubNotification(string value)
        {
            Clients.All.iotHubNotification(value);
        }
    }
}

And the code for Startup class (Startup.cs)

using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(IoTHubTempWebApp.Startup))]
namespace IoTHubTempWebApp
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

In the Index ActionResult, I will start a task which will read the messages from the queue and then SignalR will broadcast it to the client side which in turn update the chart with the latest data or temperature/humidity readings.

public ActionResult Index()
{
    Task task = Task.Run(() =>
    {
        QueueClient client = QueueClient.CreateFromConnectionString(connectionString, queueName, ReceiveMode.ReceiveAndDelete);
        client.OnMessage(message =>
        {
            Stream stream = message.GetBody<Stream>();
            StreamReader reader = new StreamReader(stream, Encoding.ASCII);
            string s = reader.ReadToEnd();
            _hubContext.Clients.All.ioTHubNotification(s);
        });
    });
    task.Wait();
    return View();
}

First I create a QueueClient object with the connection string and queue name along with the ReceiveMode. I have set ReceiveMode to ReceiveAndDelete as I want to delete the data from the queue once it has been read. Though you have an option to have the data in the queue for the maximum of 7 days in Azure. The QueueClient has an OnMessage event which process a message in an event-driven message pump, which means that as soon as the something is being added to the queue, this event is fired. I get the message body in the form of Stream, read the message to the end and pass the message to SignalR hub which in turn updates my chart in real-time. Here is the final output I have now.

If you look closely, you will notice that the temperature line is not as smooth as you thought it would be. This is because every time when Raspberry PI read the data from the sensor there is a slight change in the temperature only with a few decimal places. If you don't like this then you can change the gridlines property of the vAxis in the chart. Also you can try changing the time delay on the device to see if that impacts the lines on the chart. try changing both time delay in the device application and the gridlines in the web application to see how the chart renders.

The complete source code is available on Github.

 No Rating

Controlling 16x2 LCD With Raspberry PI 2 Using Adafruit Library

20. July 2015 12:41

Projects Raspberry Pi 

As an enthusiast, I started working with embedded with Netduino. It was fun but at the same time Netduino was not offering that much things that I can do now. For a person like me who has no knowledge of electronics and C/C++, this was a gift. Now here I am using Raspberry PI's latest version and I have everything I ever wanted on a single piece of hardware.

To get started with Python and Raspberry PI, I looked into the "Hello World" sort of LED blinking example. Using the LCD is the second thing I would like to test and so here it is. Before you start, here are the things you will need.

1. 1 x Raspberry PI 2

2. LCD with 16x2 display - HD44780

3. 8 x Male-Female jumper wires

4. 5 x Male-Male jumper wires

Here is the simple wiring to connect LCD with your Raspberry PI 2

As you can see from the wiring diagram, the LCD will take up around 6 GPIO pins on your Raspberry PI. If you have some modules plugged in or you are planning to then there are chances that you will fall short of the GPIO pins. To save GPIO pins on your board, you can use MCP23008 or MCP23017 . To keep it simple, I am not using any port expanders for now.

Now comes the code, I have a very little knowledge of Python at the moment. So I am going to stick with what I have read and tested. For controlling the LCD, I am going to use Adafruit's LCD library which you can get it from Github here. I am going to use Adafruit_CharLCD.py to control my LCD. The thing to keep in mind is that you cannot use this library out of the box. You have to make a change to set the correct GPIO pins in the __init__ function. Open the file using the below command.

$ sudo nano Adafruit_CharLCD.py

If you are using the same wiring as I am, then change the __init__ function like this

def __init__init(self, pin_rs=26, pin_e=19, pins_db=[13, 6, 5, 11], GPIO=None):

Save the changes and we are good to go. To check if the wiring and the code changes are done properly, execute the below command in the same directory.

$ sudo ./Adafruit_CharLCD_IPclock_example.py

Let's try displaying some custom messages to the display with this simple program.

from Adafruit_CharLCD import Adafruit_CharLCD

lcd = Adafruit_CharLCD()
lcd.message("Raspberry PI 2\nLCD Demo")

Here is one more. The program will ask you to enter the string to display.

from Adafruit_CharLCD import Adafruit_CharLCD

lcd = Adafruit_CharLCD()

#Getting input from user
msg = raw_input("Enter message to display\n")

#Display it on the LCD
lcd.message(str(msg))

The reason I am using Adafruit library to control the display is because it has other useful functions to control LCD. Here is the list of functions that you can try.

clear() - Clears the LCD and remove text from the memory.

display()/noDisplay() - Toggle the text visibility on the LCD. Text remains in the memory.

cursor()/noCursor - Toggle cursor visibility.

blink()/noBlink() - Toggle cursor blink.

home() - Take the cursor to the 0,0 position i.e. first column of first row.

setCursor(col, row) - Set the cursor to the specific position. Use lcd.begin(col, rows) to set the number of columns and rows your display has.

I hope this will be useful to the people who are just getting started with Raspberry Pi. You can also download the complete source code from Github here.

 No Rating

Turn Your Google Drive Folder In An Online Album Viewer

4. May 2014 15:09

API ASP.NET MVC C# Projects Web 

Working with Google Drive API is fun. The documentation is good and will let you get started with the API pretty quickly. I have my whole complete family album on OneDrive, but the API is still a bit hard to use as compared to Google Drive API or maybe it is just for me. But while playing around with Drive API I ended up creating a small razor based web page application which will allow you to show your folder as an online web album. I have the source code at Github.

To get started register your application on the Google Developer Console. Here is a complete guide on how to use the Google APIs.

Copy the API keys and save it on the notepad. The basic usage example on the Google Drive API reference page uses a file called client_secrets.json which actually holds the API key. You can find this file in the bin folder.

{
  "installed": {
    "client_id": "524339914714.apps.googleusercontent.com",
    "client_secret": "_Lq8D_Ai-T2IbhU8m2zXlQa"
  } 
}

You also have to enable the Drive API before you start using it.

I created a wrapper around the Google Drive API so I can use it in my other projects. Here is the complete code of my GoogleDrive class.

using System;
using System.Collections.Generic;
using System.Web;
using Google;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Download;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Logging;
using Google.Apis.Services;
using System.Threading.Tasks;
using System.Threading;
//using Google.Apis.Upload;

public class GoogleDrive
{
    DriveService service = null;
    public GoogleDrive()
    {
        Run().Wait();
    }


    private File GetFileByID(string fileID, DriveService service)
    {
        File file = service.Files.Get(fileID).Execute();
        if (file.ExplicitlyTrashed == null)
            return file;
        return null;
    }

    public string GetFolderID(string FolderName)
    {
        FilesResource.ListRequest request = service.Files.List();
        request.Q = "title = '" + FolderName + "'";
        FileList files = request.Execute();
        return files.Items[0].Id;
    }
    public List<File> ListFolderContent(string FolderID)
    {
        ChildrenResource.ListRequest request = service.Children.List(FolderID);
        List<File> files = new List<File>();
        //request.Q = "mimeType = 'image/jpeg'";

        request.Q = "'" + FolderID + "' in parents";

        do
        {
            try
            {
                ChildList children = request.Execute();

                foreach (ChildReference child in children.Items)
                {
                    files.Add(GetFileByID(child.Id, service));
                }

                request.PageToken = children.NextPageToken;

            }
            catch (Exception e)
            {
                request.PageToken = null;
            }
        } while (!String.IsNullOrEmpty(request.PageToken));
        return files;
    }

    public List<File> ListRootFileFolders()
    {
        List<File> result = new List<File>();
        FilesResource.ListRequest request = service.Files.List();
        do
        {
            try
            {
                FileList files = request.Execute();

                result.AddRange(files.Items);
                request.PageToken = files.NextPageToken;
            }
            catch (Exception e)
            {
                request.PageToken = null;
            }
        } while (!String.IsNullOrEmpty(request.PageToken));
        return result;
    }

    public byte[] DownloadFile(string fileID)
    {
        File file = service.Files.Get(fileID).Execute();
        var bytes = service.HttpClient.GetByteArrayAsync(file.DownloadUrl);
        return  bytes.Result;
    }


    private async Task Run()
    {
        try
        {
            GoogleWebAuthorizationBroker.Folder = "Files";
            UserCredential credential;
            using (var stream = new System.IO.FileStream("client_secrets.json",
                System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets, DriveConstants.Scopes, "user", CancellationToken.None);
            }

            var drvService = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Drive API Sample",

            });

            if (drvService != null)
            {
                service = drvService;
            }
        }
        catch { }
    }
}

The Storage class uses Biggy for the document storage. You have to manually add the names of the folder (considered as albums) on settings page. This will get added/appended in settings.json file in the Data folder which is in the web root of DriveGallery. Here is my settings file.

{"AlbumName":"Atlassian"}
{"AlbumName":"DivX"}
{"AlbumName":"Envato"}
{"AlbumName":"Disqus"}

Settings page from where I can add the names of folders/albums. No view and delete options as of now, but I will soon add it.

The added albums will be listed on the main/default page. The user will then have to click the name of the album to view the contents which should only images. At the moment there is no check which prevents it to show other files rather than only image files.

Google Drive is slow when it comes to handle high amount of data. Google Drive storage is not like Azure or Amazon storage. It’s different and will not get you large results in appropriate time. If you want to use Drive Gallery make sure that you don’t use more than 25-50 images in a folder. Querying 25-50 files in a single go will be long but not more than if you have more than 50. Better option is to break your folder in parts like volume I & II or Part 1 or 2.

I will try to make it look more attractive but for the moment it solves the purpose for me. Click on the View button to view the album. The View page accepts a query string name, which has the name of the folder/album. Google Drive API does not understand the name of the folder, so I have to get the folder id from the name. I will use the GetFolderID method of the GoogleDrive class which gives me the folder id. The received folder id is then passed to ListFolderContent method which will list all the files in the folder.

Please note that, for the moment there is no check to retrieve only images from the folder. GoogleDrive.cs class is a generic version of the class I am using in my other projects. You just need to be sure that you have only images in the folder and not any other file.

Click the View button to view the full size image in the browser else click the Download button to download it directly. Basically Drive API does not have any property which holds the value of the URL to view the image online. So I tweaked the thumbnail URL in the ViewURL property so I can view the images online without having to download it.

public class Albums
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string AlbumName { get; set; }
    public string DownloadURL { get; set; }
    public string ViewURL
    {
        get
        {
            return ThumbnailLink.Replace("=s220", "=s4000");
        }
    }
    public string ThumbnailLink { get; set; }
}

Taking the ThumbnailLink property and replace the =s220 to =s4000 does the trick.

Note: The URLs are not permanent, it will change when the request expires.

Properties of the Album class:

  • Id: File/Image id.
  • Tilte: Title of the image/file.
  • AlbumName: Name of the album/folder.
  • DownloadURL: Download URL of the image/file. Original Drive API property name: DownloadUrl.
  • ViewURL: URL which allows user to view the image in the browser.
  • ThumbnailLink: URL of the thumbnail image. Original Drive API property name: ThumbnailLink.

The duration of the operation depends on the amount of images you have in your folder. The lesser the number of images the fast the query will get executed. Here just for fun I have used Biggy JSON store to save the content details of the folder. If you want to remove it from your implementation, please do so. You may have to change some functions in order to get all other things working fine.

You can download the complete source code from Github. I am still working on it to make it more flexible and good looking. As I am not a designer and I seriously lack when it comes to web designs. Thanks to Twitter bootstrap to make it look a bit good.

Currently rated 5.0 by 1 person

Using Skydrive REST API

28. April 2013 21:52

API Cloud Microsoft Projects Utils 

I have created a wrapper class to simplify my work with REST API. I assume that you will be using a web application. First step is to create an application at dev.live.com. Once the application is created you will have the ClientID, Client Secret and Redirect domain. We will be using a ClientID and Redirect domain. Remember that the Redirect domain value cannot have localhost. You must provide a correct domain name as after successful authentication you, the user will be redirected to the domain along with the access token.

In the response you will get the access token which will be available to you for the next 3600 seconds. The access token will be in the returning URL of your domain. In my case it is http://midnightprogrammer.net/#access_token=EwBIA…. I will then retrieve the access token and pass it to my wrapper which will do the work for me.

Time to look and understand the code a bit. I have been using SkyDrive a lot for backup and sharing files and I also access SkyDrive from a web application I have built. But the code is pretty messy and needs revision. So I created a wrapper around the API.

First I need to authenticate the user with his/her live credentials with correct scopes. If scopes are wrong you will not be able to perform actions to the SkyDrive. To learn more about scopes read here. As I am working with SkyDrive I am using 2 scopes wl.signin and wl.skydrive_update. wl.skydrive_update is necessary if you want to have write access to SkyDrive. The SkyDriveAPI wrapper class has the Authenticate method which will redirect you to authentication screen of live service. Once you enter your credentials you will then be redirected to the domain (the domain you provided while you created the application) along with the access token. Here is the sample code:

public void Authenticate()
{
    string authorizeUri = AuthUri;
    authorizeUri = authorizeUri + String.Format("?client_id={0}&", _ClientId);
    authorizeUri = authorizeUri + String.Format("scope={0}&", "wl.signin,wl.skydrive_update");
    authorizeUri = authorizeUri + String.Format("response_type={0}&", "token");
    authorizeUri = authorizeUri + String.Format("redirect_uri={0}", HttpUtility.UrlEncode(_SiteURL));
    this.AuthURI = authorizeUri;
}

This is an insight of the wrapper class. In the actual scenario you will never be using it this way:

SkyDrive drive = new SkyDrive(ClientID, Site URL);
drive.Authenticate();
Response.Redirect(drive.AuthURI);

In the constructor of the SkyDrive class, the first parameter will be your ClientID and the second one will be the Site URL or the redirect domain. After this the SkyDrive class object drive (whatever the name you give) will call the Authenticate method to generate the URL with all the required parameters and store the URL in the public variable called AuthURI, which I used to redirect the user to authenticate using his credentials.

Now Once the user is authenticated you will be provided with the access token in the URL. It depends on you how you are going to fetch it. Once you fetch the access token you then need to keep it safe. To make sure that the access token remains with your API calls, save it like this:

drive.AccessToken = "EwBIA.....";

Once you have the access token, you are all good to make your first call to SkyDrive. For the simplicity, I am making a request to call get the basic user information.

User usr = drive.GetUserInfo();

Moreover you can also list all the folders in your SkyDriver with this simple call.

Folder driveFolders = new Folder();
foreach (var folder in driveFolders)
{
    Response.Write(folder.Value + " " + folder.Key +"<br/>");
}

The above code returns a Dictionary which contains the name of the folder and id of the folder. You’ll need the folder id in order to list down all the files in the folder. To list down all the files in a folder use the below code.

FolderContent content = drive.ListFolderContent("folder.77e33dba68367a16.77E33GBA68467A16!2189");
for (int i = 0; i < content.Files.Count; i++)
{
    Response.Write(content.Files[i].name);
}

It is not just the name of the files you get but you get the complete properties of the file. So you can play around with that too.

Coming to the most searched feature of SkyDriver REST API is to how to upload a file using REST API. The MSDN states that you can upload the files to SkyDriver by making HTTP POST or HTTP PUT requests. Here is how I am doing it inside my wrapper class.

public bool UploadFile(string FolderID, string FilePath)
{
    bool Uploaded = false;
    try
    {
        byte[] fileBytes = System.IO.File.ReadAllBytes(FilePath);
        string UploadURI = BaseURI + FolderID + "/files/" + Path.GetFileName(FilePath) + "?access_token=" + AccessToken;
 
        var request = (HttpWebRequest)HttpWebRequest.Create(UploadURI);
        request.Method = "PUT";
        request.ContentLength = fileBytes.Length;
 
        using (var dataStream = request.GetRequestStream())
        {
            dataStream.Write(fileBytes, 0, fileBytes.Length);
        }
 
        string status = (((HttpWebResponse)request.GetResponse()).StatusDescription);
 
        if (status.ToLower() == "created")
        {
            Uploaded = true;
        }
 
        return Uploaded;
    }
    catch (Exception)
    {
        return false;
    }
}

I am using a PUT method to upload files to SkyDrive. At this moment I have not implemented the POST method. But in near future I will. If you are using my wrapper class then the just use a single line of code to upload a file to a particular folder.

bool uploaded = drive.UploadFile("folder.77e33dba68367a16.77E33DUA68567A16!104", "D:\\walls\\flowers_442.jpg");

Calling the UploadFile method will upload a file to the folder. The first parameter in the above method is the folder id where you want to upload the folder and the second one is the local file path.

I am currently working and trying to understand the REST API and its features. I will include other functions as more and more I learn about them.

The SkyDrive API Wrapper is hosted on GitHub. Fork it, change it, customize it as you wish. And if you have or found something good, then please do let me know.

I want to give the credit to Christophe Geers for his post which gives me an insight of the API.

 No Rating

BingMap.JS - Jquery Plugin For Bing Maps

10. March 2012 16:39

API Jquery Microsoft Projects 

Bing maps are out there for a long time now and is getting mature pretty fast. I have used Bing maps myself in few of my projects and I remember as a first time user I have a hard time configuring it according to my project requirement. To get myself out of the overhead I searched the web for a jquery plugin, but I can't find a single jquery plugin for Bing Maps instead I found few for Google Maps. I do have some knowledge of jquery and Bing map API, so I decided to write a jquery plugin for Bing map in my free time that will handle all necessary configurations and all the hard work for me and more importantly save my time.

How I get started and how it ended up

Initially I started writing a plugin to just set up the default configuration like setting the map with different modes, zoom level and other necessary configurations, but I ended up doing something more. Besides just the normal configurations of the map I was also able to incorporate Bing map API to search and pinpoint the address on the map. Now if you have an address and you want that to be located on the map then you just have to write in the address in the address parameter and do the other necessary configuration like if you want to show the pushpin on the map or not, or you can set the description on the balloon tip when the user hover the mouse on the pushpin. You can also change the view modes and can also set the zoom level. Plenty of stuff in the plugin and I will add more to make it more flexible and more productive. The API thing in the plugin was just the test from my side, I never thought of using the API in the plugin when I started writing it. But I am happy that I ended up making something useful for myself and I am sure enough that it will help other fellow developers out there also.

Where to get the plugin?

I have a dedicated a page for the Bing Map plugin here. There are still few changes to be made on the page so that it can have more information. In the next phase I am planning to have a demo page and provide more information on plugin.

Make sure to read about the plugin and the configurations before you get started with the plugin at Bing map plugin home page.

If you are using NuGet then you can fire up the below command to install it into the Scripts folder.

If you have doubts and have suggestions for the plugin then please do drop me a comment or e-mail.

 No Rating

«12»