Arduino MKR1000 How to send Message to Azure IoT Hub
Asked Answered
R

0

7

I am trying to setup a basic example of sending a message from the Arduino MKR1000 to the Azure IOT Event Hub but can't seem to get any of the online examples to work and I am new to Arduino.

Any pointers for a simple working example?

I tried this example and changing slightly to POST a message rather than receive but no luck. I can connect to the Wifi with no issues, its just when posting the HTTP request it errors with "HTTP Error 411. The request must be chunked or have a content length". It also doesn't seem like the most clean approach but I just wan't to get something basic up and running for now to play with :)

Code Example:

#include <SPI.h>
#include <WiFi101.h>

#include "arduino_secrets.h"

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

const int MKR1000_LED = 6 ;


///*** Azure IoT Hub Config ***///
//see: http://mohanp.com/  for details on getting this right if you are not sure.

char hostname[] = "*****.azure-devices.net";    // host name address for your Azure IoT Hub
char feeduri[] = "/devices/MKR1000/messages/events?api-version=2018-06-30"; //feed URI
char authSAS[] = "SharedAccessSignature sr=******.azure-devices.net%2Fdevices%2FMKR1000&sig=*****&se=******";

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

unsigned long lastConnectionTime = 0;
const unsigned long pollingInterval = 5L * 1000L; // 5 sec polling delay, in milliseconds

int status = WL_IDLE_STATUS;

WiFiSSLClient client;

void setup() {
  Serial.println("setup...");
  pinMode(MKR1000_LED, OUTPUT);

  //check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    // don't continue:
    while (true);
  }

  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Wifi connected...");
}

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(""))
  {
    Serial.println(response);
    //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("{TEST MESSAGE!}");
  }
}

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

  // 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(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("Content-Type: application/json");
    client.println("Content-Length: " + data.length());
    client.println("\r\n\r\n" + data);



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

Edit: I have seen that there is a full Azure IOT library with a simple HTTP example, but this also doesn't run (it gets passed the wifi connection and failing with call to azure) but this example project is fairly large and I was hoping for a simple example to build upon!

https://github.com/Azure/azure-iot-arduino

Restaurant answered 19/3, 2019 at 1:40 Comment(11)
is there any specific reason why you are not using the IoT Device SDK and instead constructing the connection yourself?Make
Are you referring to the Azure specific library as per my link? I have taken the code mainly from an example online so I am trying to get something working initially. If you have a clearer approach though please shareRestaurant
Also: "I have seen that there is a full Azure IOT library with a simple HTTP example, but this also doesn't run (it gets passed the wifi connection and failing with call to azure) but this example project is fairly large and I was hoping for a simple example to build upon!"Restaurant
You absolutely sure data.length() returns something in the client.println near the end there? Print it out to serial console. Transfer-Encoding: chunked should work as well (instead of Content-Length).Digression
I will double check when back near the Arduino, but i presume it should as I have passed in a static string. I will also try changing the header to use transfer-encodingRestaurant
No joy:22:39:23.631 -> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""w3.org/TR/html4/strict.dtd"> 22:39:23.631 -> <HTML><HEAD><TITLE>Bad Request</TITLE> 22:39:23.631 -> <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD> 22:39:23.631 -> <BODY><h2>Bad Request - Invalid Header</h2> 22:39:23.631 -> <hr><p>HTTP Error 400. The request has an invalid header name.</p> 22:39:23.631 -> </BODY></HTML>Restaurant
I also confirmed the length did return an integer greater than zeroRestaurant
I had similar issue till yesterday but now it suddenly started working as if there has been update to Iot service. I noticed one thing that your content-type is "application/json" but actual message is not in key/value format like "{ "messagestring" : "test message" } .. I used NodeMCU esp32 module to test thisInimical
In addition to Rahul: if you're not sending a (correct) json file, you could replace Content-Type with: Content-Type: application/x-www-form-urlencoded; charset=UTF-8. I also suggest not to send a newline command on the last print (not a newline after the data)There
You have a ready-to-use example here: github.com/firedog1024/mkr1000-iotc. Note that it uses Azure IoT Device Provisioning Service for provisioning so you will need to setup a DPS instance alongside your IoT Hub.Tatianna
@Make is likely referring to the various SDK's by Microsoft: github.com/Azure/azure-iot-sdks There is one for embedded C, which is probably what you need.Humblebee

© 2022 - 2024 — McMap. All rights reserved.