MKR1000 Azure IoT Hub Interface Using HTTP

MKR1000 Azure IoT Hub Controlled Blink

After getting my hands on the pre-release version of the MKR1000 as part of the Worlds Largest Arduino Maker Challenge yesterday, I was trying to get it running with the Azure IoT Hub. This guide lays out some of the things that I learned that might help out others out there trying to get their projects running with Azure IoT.

This guide doesn’t use AMQP or MQTT. This uses the simple HTTP interfaces available for Azure IoT Hub.  This assumes that you have already signed up for the Azure IoT Hub and created it. This guide will walk you through the following steps to get you going.

  1. Getting the Arduino Environment ready for MKR1000
  2. Setting up the WiFi101 library
  3. Understanding the HTTP REST API for the Azure IoT Hub
  4. Getting the SAS token from the Device Explorer for Azure IoT Hub
  5. Setting up the SSL for Azure IoT Hub on the MKR1000 WiFi
  6. Walk through of the Arduino Sketch that you will run on the MKR1000
  7. Testing by Sending Messages to Azure IoT Hub with Device Explorer

Update 2/29/2016: Part 2 of this Azure IoT Hub interface using HTTP to complete/reject/abandon a received message is here. Be sure to read that as well after this.

Getting the Arduino Environment Ready for MKR1000

1. Install/upgrade to the latest version of the Arduino IDE.

2. Install the SAMD board using the Boards Manager.. That’s SAMD not SAM

SAMD Board Install
SAMD Board Install

You should now be able to run the blink sketch (on board LED is on Pin 6 and not on Pin13) and verify that the simplest sketch is working on the MKR1000.

Setting up the WiFi101 library

MKR1000 sketches need the WiFi101 library. Particularly version 0.8. As of this writing, the default Arduino IDE installation didn’t have the latest library. You can verify it by going to Sketch > Include Libraries > Manage Libraries and search for Wifi101.. if you see version 0.8.0 and above installed you are fine. Otherwise try to get the library updated. If you don’t see the “Update” button on the Libraries Manager, you might have to do it manually by:

  1. Deleting the WiFi101 folder from the Arduino libraries folder. On windows its at C:\Users\yourusername\Documents\Arduino\libraries
  2. Download the latest WiFi101 library zip file from Github
  3. Install using Sketch > Include Libraries > Add .Zip Library menu
Update WiFI101 library
Update WiFI101 library
Understanding the HTTP REST API for the Azure IoT Hub

Microsoft Azure IoT Hub is accessible through HTTP, AMQP or MQTT. The HTTP REST API’s makes it easier for connecting and polling for messages on the Azure IoT Hub using just Http clients. The following two REST http endpoints would allow us to perform basic tasks from the devices.

Purpose
HTTP Verb
URI
Receive or Poll for a Message
GET
https://{IoTHubName}.azure-devices.net/devices/{deviceId}/messages/devicebound?api-version={api-version}
Send a message
POST
https://{IoTHubName}.azure-devices.net/devices/{deviceId}/messages/events?api-version={api-version}

The highlighted fields are described below. They are needed for the Sketch configuration.

Field
description
IoTHubName
This is your  IoT hub Host name. Can get it from the Azure Portal
Example: yourTestIotHub.azure-devices.net
deviceId
Name of the device that you created using Device Explorer (see below)
api-version
As of this writing (on Feb 19, 2016) its “2016-02-03”

There are 3 more endpoints available for dealing with the messages (Complete, Reject, Abondon). You can read about them here.

Microsoft Azure IoT uses Shared Access Signatures (SAS) to secure the Azure endpoints. These are expiring signatures that can be used to securely access the Azure IoT device queues without the need for passwords. These have to be passed in the HTTP headers when making the request.

Though this signature needs to be created on fly with a very short expiration, when you install the Device Explorer utility you will be able to create the shared access key with a longer expiration. You will then be able to use this static key in your sketch with out having to generate them in the code.

Getting the SAS token from the Device Explorer for Azure IoT Hub

Device Explorer is a small utility that makes it easy to manage devices connecting to your IoT hub.  You can add/remove devices, create SAS token, send/receive messages for specific device identities.

The Device explorer GUI runs only on Windows.  You can install it from here.

For other OS, you can install the IoThub explorer tool using npm.

I am using the Windows Version. For configuring the Device Explorer, you need to obtain the IoT Hub Connection string and use it in the configuration tab of the device explorer. After that you will be able to access the “Management” tab to view and create the devices. This is where you can select a particular device and create the SAS token for it as well. Refer to the how to use guide here.

I created a device named “MyMKR1000” and created the SAS Token with the TTL set to 5 days. I might have to update the sketch later once the SAS token expires. You need to copy only the part that starts with the second SharedAccessSignature. For example the SAS key in the screenshot that i will use in the MKR1000 sketch is:
SharedAccessSignature sr=UPPHub.azure-devices.net%2fdevices%2fMyMKR1000&sig=JeQBhIBmFQrHBTmwainLMSmDc35rZ2hoGPbEmM9QEDQ%3d&se=1455974333

(In the screen shot I am using 0 just so that the share access key expire by the time this post goes online.)

Azure IoT Hub Device SAS Token
Azure IoT Hub Device SAS Token

 

Setting up the SSL for Azure IoT Hub on the MKR1000 WiFi

Now that the SAS token is available, we almost have everything we need to configure the sketch. The last thing we need is the SSL certificate configured.

Azure IoT Hub (and for that matter most of the IoT Services) uses SSL to secure the communication. On the Arduino MKR1000 board, when the sketch runs, it needs to establish an SSL communication with the Azure IoT hub first before it can proceed further. The MKR1000’s WiFi chip doesn’t have that much memory. It cannot possible store a large number of SSL certificates like your computer does. So we need to first upload the SSL certificate to the WiFi chip. Not a big deal.

  1. Get the latest version of WiFi101 Firmware updater from here. Extract the contents of the zip file to a folder. You should see “winc1500-uploader-gui” in that folder. You can also use the console application found there.
  2. On the Arduino IDE, choose the FirmwareUpdater sketch from File > Examples > WiFi101 > FirmwareUpdater
  3. With the MKR1000 connected run this sketch. Your MKR1000 will now be ready to accept the new WiFi Firmware.
  4. Run the “winc1500-uploader-gui” application
  5. On the Ip or Domain name field provide the name of your IoTHub host name.  Click download to get the SSL certificate.
  6. Select the COM port that MKR1000 is connected to.
  7. Press upload certificates to send the certificate to the WiFi module. Once the certificates are uploaded you are all set for MKR1000 Azure IoT Hub interfacing.
MKR1000 Certificate Uploader
MKR1000 Certificate Uploader
MKR1000 Arduino Sketch

Following are the basic configuration that need to be set on the sketch for WiFi connection and Azure IoT Hub Connection.

///*** WiFi Network Config ***///
char ssid[] = "YourWiFiNetworkSSID"; //  your network SSID (name)
char pass[] = "YourWiFiNetworkPasswd";    // your network password (use for WPA, or use as key for WEP)

///*** Azure IoT Hub Config ***///
char hostname[] = "YourIoTHubName.azure-devices.net";    // host name address for your Azure IoT Hub
char feeduri[] = "/devices/YourDeviceName/messages/devicebound?api-version=2016-02-03"; //feed URI 
char authSAS[] = "YourSharedAccessKey"; 

///*** Azure IoT Hub Config ***///

The main part of the sketch that deals with making HTTP requests to Azure IoT hub is the following. The sketch uses the WiFiSSLClient to establish a SSL handshake to the hostname via port 443. Once Connection is established, it makes a GET request to the devicebound URI to receive messages. When establishing the GET request, the “Authorization” header is also added which contains the value for the SAS token.

// this method makes an HTTPS connection to the Azure IOT Hub Server:
void azureHttpRequest() {

  // close any connection before send a new request.
  // This will free the socket on the WiFi shield
  client.stop();

  // if there's a successful connection:
  if (client.connect(hostname, 443)) {
    //make the GET request to the Azure IOT device feed uri
    client.print("GET ");  //Do a GET
    client.print(feeduri);  // On the feedURI
    client.println(" HTTP/1.1"); 
    client.print("Host: "); 
    client.println(hostname);  //with hostname header
    client.print("Authorization: ");
    client.println(authSAS);  //Authorization SAS token obtained from Azure IoT device explorer
    client.println("Connection: close");
    client.println();

    // note the time that the connection was made:
    lastConnectionTime = millis();
  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
  }
}

On the main loop, the response, if available, is read. If the response contains the 204 response code, it means there was no new message. Else there is a message and I just blink the LED on pin #6. I have configured a polling interval and the code loops through to repeatedly check for messages. We can do more with the response, but for this post i just kept it simple.

void loop() 
{
  String response = "";
  char c;
  ///read response if WiFi Client is available
  while (client.available()) {
    c = client.read();
    response.concat(c);
  }

  if (!response.equals(""))
  {
    //if there are no messages in the IoT Hub Device queue, Azure will return 204 status code. 
    if (response.startsWith("HTTP/1.1 204"))
    {
      //turn off onboard LED
      digitalWrite(MKR1000_LED, LOW);
    }
    else
    {
      //turn on onboard LED
      digitalWrite(MKR1000_LED, HIGH);
    }
  }

  // polling..if pollingInterval has passed
  if (millis() - lastConnectionTime > pollingInterval) {
    digitalWrite(MKR1000_LED, LOW);
    azureHttpRequest();
  }
}

 

The complete sketch is available in Github at MKR1000Azure.

Sending Messages to Azure IoT Hub

After uploading the sketch to MKR1000, I used the Device Explorer to send some messages to the IoT Hub.

Send Message To Device
Send Message To Device

I could see the MKR1000 receiving the messages from Azure IoT hub and activating the LED.

MKR1000 Azure IoT Hub Controlled Blink
MKR1000 Azure IoT Hub Controlled Blink

(Note: The MKR1000 is hiding in its box due to the request from Arduino not to take pictures of the MKR1000)

Now that a simple GET is possible, sending messages and dealing with other uses cases around Azure IoT Hub interface should be easier.

Update 2/29/2016: Part 2 of this Azure IoT Hub interface using HTTP to complete/reject/abandon a received message is here. Be sure to read that as well after this to ensure received messages are properly de-queued in Azure IoT Hub.

Hopefully this guide is useful for the community. Like it says on the MKR1000 box, “Open-Source is Love”.

23 thoughts on “MKR1000 Azure IoT Hub Interface Using HTTP”

  1. Hello,

    Thanks for the example! I am having a problem with Serial.println() on the mkr1000.

    Have you been able to monitor the serial port?

    1. Yes. I was able to use serial.println and use the serial monitor. Try to run the simple blink sketch and use the serial.begin and serial.println to verify.

      1. The below returns nothing to serial monitor. This is in the setup mothed.

        Serial.begin(9600);
        delay(100);
        while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
        }
        Serial.println(” Serial Print line here.”);

          1. I signed up with the link they sent. But still get eh following error.

            An Error Has Occurred: The topic or board you are looking for appears to be either missing or off limits to you.

    1. I am putting together part 2 of this post.. Meanwhile this might help you keep going..call the azureHTTPPost with your content:

      //Post URI
      char azurePOST_Uri[]= “/devices/MyMKR1000/messages/events?api-version=2016-02-03”;// feed POST Uri

      void azureHttpPOST(String content) {

      // close any connection before send a new request.
      // This will free the socket on the WiFi shield
      client.stop();

      // if there’s a successful connection:
      if (client.connect(hostname, 443)) {
      //make the GET request to the Azure IOT device feed uri
      client.print(“POST “); //Do a GET
      client.print(azurePOST_Uri); // On the feedURI
      client.println(” HTTP/1.1″);
      client.print(“Host: “);
      client.println(hostname); //with hostname header
      client.print(“Authorization: “);
      client.println(authSAS); //Authorization SAS token obtained from Azure IoT device explorer
      client.println(“Connection: close”);
      client.println(“Content-Type: text/plain”);
      client.print(“Content-Length: “);
      client.println(content.length());
      client.println();
      client.println(content);
      client.println();

      // note the time that the connection was made:
      lastConnectionTime = millis();
      }
      else {
      // if you couldn’t make a connection:
      Serial.println(“connection failed”);
      }
      }

  2. Hi,

    Thank you for the detailed example. Do you recall how long it took you to update the SSL certificate? I am stuck at “Synchronizing with programmer”

    1. Actually, I tried another MKR1000 and it was also stuck at the same spot. However, once I switch to an UNO+WiFi Shield. it uploaded instantly. Did something similar happen to you.

      Note: The two MKR1000 are Genuino, I don’t think that makes any difference but just FYI

    2. It got updated immediately. Didn’t have any issues. Did you make sure that your wifi101 firmare is up to date? There is an example sketch under wifi101 library. CheckWifi101FirmwareVersion.ino

      1. arghhh, i tried loading the check firmware sketch, which brings me to another problem. I cannot get the Serial Functionality to work on the MKR1000. Did you have any problems?

        1. I didn’t have any issues with the serial functionality. I am using a Windows 7 with Arduino version 1.6.7 with the latest boards updated. Have you followed the instructions in the Arduino forum for getting started?
          https://forum.arduino.cc/index.php?topic=380369.0

          Just in case you don’t have access to the MKR1000 topic on Arduino Forum (seems like some have delays in getting access) here is the copy of the instructions.

          Install guide for MKR1000
          ————————–

          1. We recommend to download the hourly build IDE at:
          https://www.arduino.cc/en/Main/Software
          it’s not mandatory but we recommend it as it includes a lot of fixes (in particular a nasty bug that prevents some library from being updated on Windows)

          2. From the Arduino Boards Manager install or update “SAMD cores” at version 1.6.4

          3. Add to the “Additional board manager URL” under IDE -> preferences the followin link:

          http://downloads.arduino.cc/packages/package_mkr1000_index.json

          4. From the Board Manager install “hackster.io – MKR1000 build”.
          We are going to update this core independently from the upstream “SAMD” core as needed.

          5. Install the WiFi101 library version 0.8.0 from the Library Manager. This is the library to use to use the wifi module.

  3. I am trying to POST data. I tried the code you listed and I always get

    Response: HTTP/1.1 400 Bad Request
    Content-Length: 25
    Content-Type: application/json; charset=utf-8
    Server: Microsoft-HTTPAPI/2.0
    iothub-errorcode: InvalidErrorCode
    Date: Mon, 28 Mar 2016 03:48:18 GMT

    {“Message”:”Bad Request”}

    Any idea what would cause a bad request? I don’t know what to make of iothub invalidErrorCode. I am pretty sure host and authorization are correct – i get different errors when they are wrong.

  4. Mine is hanging at “Updating Certificates”. I tried using the hackster.io board config, but it’s not working. The process goes great until it hangs halfway. Any advice?

  5. Can u please give an example for post a data from device to cloud… It highly helpful.. If we replace post instead of get in the above example the code doesn’t work properly… Pls do help

Leave a Reply

Your email address will not be published. Required fields are marked *