Skip to content
This repository was archived by the owner on Jul 22, 2022. It is now read-only.

Update AzureIoT Library with support for more boards #1

Merged
merged 19 commits into from
Apr 5, 2016
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,75 @@
# AzureIoT - Azure IoT library for Arduino
# AzureIoT - Azure IoT Hub library for Arduino

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think the library should be renamed to "AzureIoTHub" as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've agreed to rename this repo to AzureIoTHub.

This library is a port of the [Microsoft Azure IoT device SDK for C](https://github.com/Azure/azure-iot-sdks/blob/master/c/readme.md) to Arduino. It allows you to use your Arduino/Genuino with the [Azure IoT Hub](https://azure.microsoft.com/en-us/services/iot-hub/).
This library is a port of the [Microsoft Azure IoT device SDK for C](https://github.com/Azure/azure-iot-sdks/blob/master/c/readme.md) to Arduino. It allows you to use several Arduino compatible boards with Azure IoT Hub.

For the Arduino/Genuino [MKR1000](https://www.arduino.cc/en/Main/ArduinoMKR1000) or [Zero](https://www.arduino.cc/en/Main/ArduinoBoardZero) and [WiFi Shield 101](https://www.arduino.cc/en/Main/ArduinoWiFiShield101) only.
Currently supported hardware:
- Atmel SAMD Based boards
- Arduino/Genuino [MKR1000](https://www.arduino.cc/en/Main/ArduinoMKR1000) (pending release)
- Adafruit [Feather M0](https://www.adafruit.com/products/3010)
- [Zero](https://www.arduino.cc/en/Main/ArduinoBoardZero) and [WiFi Shield 101](https://www.arduino.cc/en/Main/ArduinoWiFiShield101)
- ESP8266 based boards with [esp8266/arduino](https://github.com/esp8266/arduino)
- SparkFun [Thing](https://www.sparkfun.com/products/13711)
- Adafruit [Feather Huzzah](https://www.adafruit.com/products/2821)

[![Microsoft Azure Certified][Microsoft-Azure-Certified-Badge]][azure-certifiedforiot]

## Getting started
## Prerequisites

See the [Microsoft Azure IoT device SDK for C - Arduino WiFi Shield 101 and MKR1000 Setup Guide](https://github.com/Azure/azure-iot-sdks/blob/master/c/doc/run_sample_on_arduino_wifi101.md).
You should have the following ready before beginning with any board:
- [Setup your IoT hub](https://github.com/Azure/azure-iot-sdks/blob/master/doc/setup_iothub.md)
- [Provision your device and get its credentials](https://github.com/Azure/azure-iot-sdks/blob/master/doc/manage_iot_hub.md)
- [Arduino IDE 1.6.8](https://www.arduino.cc/en/Main/Software) (currently this is available only as the hourly build)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDE 1.6.8 has been released :) (as of yesterday).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!!! Will update readme.

- Install the AzureIoT library
* Currently this must be installed from source control by cloning the repo into your arduino libraries folder. An example is below:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have the IDE library manager as the recommended way to get the library.

For users wanting to use from Github, I would recommend cloning to <SKETCHBOOK>/libraries/ instead. The default <SKETCHBOOK> path is:

  • Windows: My Documents\Arduino\
  • OS X: ~/Documents/Arduino/libraries
  • Linux: ~/sketchbook

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, this was temporary as we had folks using it before it was merged, I will update this to reflect the library manager.


```
cd C:\Program Files (x86)\Arduino\libraries
git clone <the URI for this repository>
```
Then reference the section appropriate for your hardware below.

## ESP8266
##### Sparkfun Thing, Adafruit Feather Huzzah, or generic ESP8266 board

1. Install esp8266 board support into your Arduino IDE.
* Start Arduino and open Preferences window.
* Enter `http://arduino.esp8266.com/stable/package_esp8266com_index.json` into Additional Board Manager URLs field. You can add multiple URLs, separating them with commas.
* Open Boards Manager from Tools > Board menu and install esp8266 platform 2.1.0 or later
* Select your ESP8266 board from Tools > Board menu after installation

2. Copy and reference the sample provided in library directory
```
\examples\esp8266\simplesample_http\simplesample_http.ino
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about changing this for use the Arduino IDE examples menu? File -> Examples -> AzureIoT (same applies to other boards below)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had no idea that feature was there! Very cool, will fix.

```
3. Update Wifi SSID/Password in simplesample_http.ino
* Ensure you are using a wifi network that does not require additional manual steps after connection, such as opening a web browser.
4. Update IoT Hub Connection string in simplesample_http.c


## Adafruit Feather M0
1. Install Feather M0 board support into your Arduino IDE.
* Start Arduino and open Preferences window.
* Enter `https://adafruit.github.io/arduino-board-index/package_adafruit_index.json` into Additional Board Manager URLs field. You can add multiple URLs, separating them with commas.
* Open Boards Manager from Tools > Board menu and install Adafruit SAMD Boards 1.0.7 or later.
* Select your Adafruit Feather M0 from Tools > Board menu after installation

2. Copy and reference the sample folder provided in library directory
```
\examples\samd\simplesample_http\simplesample_http.ino
```
3. Update Wifi SSID/Password in simplesample_http.ino
* Ensure you are using a wifi network that does not require additional manual steps after connection, such as opening a web browser.
4. Update IoT Hub Connection string in simplesample_http.c

## MKR1000 or Zero + Wifi101
##### These boards have had limited testing in this release.
1. Copy and reference the sample folder provided in library directory
```
\examples\samd\simplesample_http\simplesample_http.ino
```
2. Update Wifi SSID/Password in simplesample_http.ino
* Ensure you are using a wifi network that does not require additional manual steps after connection, such as opening a web browser.
3. Update IoT Hub Connection string in simplesample_http.c

## License

Expand Down
226 changes: 226 additions & 0 deletions examples/esp8266/simplesample_http/simplesample_http.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdlib.h>

#include <stdio.h>
#include <stdint.h>
#include <pgmspace.h>

/* This sample uses the _LL APIs of iothub_client for example purposes.
That does not mean that HTTP only works with the _LL APIs.
Simply changing the using the convenience layer (functions not having _LL)
and removing calls to _DoWork will yield the same results. */

#ifdef ARDUINO
#include "AzureIoT.h"
#else
#include "serializer.h"
#include "iothub_client_ll.h"
#include "iothubtransporthttp.h"
#include "threadapi.h"
#endif

#ifdef MBED_BUILD_TIMESTAMP
#include "certs.h"
#endif // MBED_BUILD_TIMESTAMP

static const char* connectionString = "HostName=[host].azure-devices.net;DeviceId=[device];SharedAccessKey=[key]";

// Define the Model
BEGIN_NAMESPACE(WeatherStation);

DECLARE_MODEL(ContosoAnemometer,
WITH_DATA(ascii_char_ptr, DeviceId),
WITH_DATA(int, WindSpeed),
WITH_ACTION(TurnFanOn),
WITH_ACTION(TurnFanOff),
WITH_ACTION(SetAirResistance, int, Position)
);

END_NAMESPACE(WeatherStation);

DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES)

EXECUTE_COMMAND_RESULT TurnFanOn(ContosoAnemometer* device)
{
(void)device;
LogInfo("Turning fan on.\r\n");
return EXECUTE_COMMAND_SUCCESS;
}

EXECUTE_COMMAND_RESULT TurnFanOff(ContosoAnemometer* device)
{
(void)device;
LogInfo("Turning fan off.\r\n");
return EXECUTE_COMMAND_SUCCESS;
}

EXECUTE_COMMAND_RESULT SetAirResistance(ContosoAnemometer* device, int Position)
{
(void)device;
LogInfo("Setting Air Resistance Position to %d.\r\n", Position);
return EXECUTE_COMMAND_SUCCESS;
}

void sendCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
{
int messageTrackingId = (intptr_t)userContextCallback;

LogInfo("Message Id: %d Received.\r\n", messageTrackingId);

LogInfo("Result Call Back Called! Result is: %s \r\n", ENUM_TO_STRING(IOTHUB_CLIENT_CONFIRMATION_RESULT, result));
}

static void sendMessage(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const unsigned char* buffer, size_t size)
{
static unsigned int messageTrackingId;
IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(buffer, size);
if (messageHandle == NULL)
{
printf(PSTR("unable to create a new IoTHubMessage\r\n"));
}
else
{
if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, sendCallback, (void*)(uintptr_t)messageTrackingId) != IOTHUB_CLIENT_OK)
{
printf(PSTR("failed to hand over the message to IoTHubClient"));
}
else
{
printf(PSTR("IoTHubClient accepted the message for delivery\r\n"));
}
IoTHubMessage_Destroy(messageHandle);
}
free((void*)buffer);
messageTrackingId++;
}

/*this function "links" IoTHub to the serialization library*/
static IOTHUBMESSAGE_DISPOSITION_RESULT IoTHubMessage(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
IOTHUBMESSAGE_DISPOSITION_RESULT result;
const unsigned char* buffer;
size_t size;
if (IoTHubMessage_GetByteArray(message, &buffer, &size) != IOTHUB_MESSAGE_OK)
{
printf(PSTR("unable to IoTHubMessage_GetByteArray\r\n"));
result = EXECUTE_COMMAND_ERROR;
}
else
{
/*buffer is not zero terminated*/
char* temp = malloc(size + 1);
if (temp == NULL)
{
printf(PSTR("failed to malloc\r\n"));
result = EXECUTE_COMMAND_ERROR;
}
else
{
memcpy(temp, buffer, size);
temp[size] = '\0';
EXECUTE_COMMAND_RESULT executeCommandResult = EXECUTE_COMMAND(userContextCallback, temp);
result =
(executeCommandResult == EXECUTE_COMMAND_ERROR) ? IOTHUBMESSAGE_ABANDONED :
(executeCommandResult == EXECUTE_COMMAND_SUCCESS) ? IOTHUBMESSAGE_ACCEPTED :
IOTHUBMESSAGE_REJECTED;
free(temp);
}
}
return result;
}

void simplesample_http_run(void)
{
if (serializer_init(NULL) != SERIALIZER_OK)
{
LogInfo("Failed on serializer_init\r\n");
}
else
{
IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, HTTP_Protocol);
srand((unsigned int)time(NULL));
int avgWindSpeed = 10.0;

if (iotHubClientHandle == NULL)
{
LogInfo("Failed on IoTHubClient_LL_Create\r\n");
}
else
{
unsigned int minimumPollingTime = 9; /*because it can poll "after 9 seconds" polls will happen effectively at ~10 seconds*/
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "MinimumPollingTime", &minimumPollingTime) != IOTHUB_CLIENT_OK)
{
printf(PSTR("failure to set option \"MinimumPollingTime\"\r\n"));
}

#ifdef MBED_BUILD_TIMESTAMP
// For mbed add the certificate information
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
{
LogInfo("failure to set option \"TrustedCerts\"\r\n");
}
#endif // MBED_BUILD_TIMESTAMP

ContosoAnemometer* myWeather = CREATE_MODEL_INSTANCE(WeatherStation, ContosoAnemometer);
if (myWeather == NULL)
{
LogInfo("Failed on CREATE_MODEL_INSTANCE\r\n");
}
else
{
if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, IoTHubMessage, myWeather) != IOTHUB_CLIENT_OK)
{
printf(PSTR("unable to IoTHubClient_SetMessageCallback\r\n"));
}
else
{
myWeather->DeviceId = "myFirstDevice";
myWeather->WindSpeed = avgWindSpeed + (rand() % 4 + 2);
{
unsigned char* destination;
size_t destinationSize;
if (SERIALIZE(&destination, &destinationSize, myWeather->DeviceId, myWeather->WindSpeed) != IOT_AGENT_OK)
{
LogInfo("Failed to serialize\r\n");
}
else
{
IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(destination, destinationSize);
if (messageHandle == NULL)
{
printf(PSTR("unable to create a new IoTHubMessage\r\n"));
}
else
{
if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, sendCallback, (void*)1) != IOTHUB_CLIENT_OK)
{
printf(PSTR("failed to hand over the message to IoTHubClient"));
}
else
{
printf(PSTR("IoTHubClient accepted the message for delivery\r\n"));
}

IoTHubMessage_Destroy(messageHandle);
}
free(destination);
}
}

/* wait for commands */
while (1)
{
IoTHubClient_LL_DoWork(iotHubClientHandle);
ThreadAPI_Sleep(100);
}
}

DESTROY_MODEL_INSTANCE(myWeather);
}
IoTHubClient_LL_Destroy(iotHubClientHandle);
}
serializer_deinit();
}
}
64 changes: 64 additions & 0 deletions examples/esp8266/simplesample_http/simplesample_http.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Please use an Arduino IDE 1.6.8 (once released) or an hourly build from 1/21/2016 or later from
// https://www.arduino.cc/en/Main/Software
// Prior builds may experience pre-processor function prototype failures.

#include <ESP8266WiFi.h>
#include <time.h>
#include "simplesample_http.h"

char ssid[] = "ssid"; // your network SSID (name)
char pass[] = "password"; // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;

void setup() {
initSerial();
initWifi();
initTime();
}

void loop() {
// Run the SimpleSample from the Azure IoT Hub SDK
// You must set the connection string in simplesample_http.c
simplesample_http_run();
}

void initSerial() {
// Start serial and initialize stdout
Serial.begin(115200);
Serial.setDebugOutput(true);
}

void initWifi() {
// Attempt to connect to Wifi network:
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);

// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("Connected to wifi");
}

void initTime() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about moving this into the NTPClient class? Then it the same for SAMD, and doesn't need to be repeated in all sketches.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one turned out to be a little more complicated. HTTPAPI is actually too late to set time properly as the SDK uses it quite a bit before the first HTTP call, and there aren't actually other hooks early enough. I'm also not sure it is a good idea to hide configuration of time from the user by putting it in the library as people may want to configure it themselves, or use time() prior to initializing the library. I think we will pull time config into the sketch for all boards so it is clear to users time configuration is a prerequisite.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

time_t epochTime;

configTime(0, 0, "pool.ntp.org", "time.nist.gov");

while (true) {
epochTime = time(NULL);

if (epochTime == 0) {
Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry.");
delay(2000);
} else {
Serial.print("Fetched NTP epoch time is: ");
Serial.println(epochTime);
break;
}
}
}
File renamed without changes.
11 changes: 5 additions & 6 deletions src/sdk/certs.h → ...amd/simplesample_http/simplesample_http.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef CERTS_H
#define CERTS_H
#ifndef SIMPLESAMPLEHTTP_H
#define SIMPLESAMPLEHTTP_H

#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif

extern const char certificates[];
void simplesample_http_run(void);

#ifdef __cplusplus
}
#endif

#endif /* CERTS_H */
#endif /* SIMPLESAMPLEHTTP_H */
Loading