-
Notifications
You must be signed in to change notification settings - Fork 93
Update AzureIoT Library with support for more boards #1
Changes from 6 commits
5b57a49
93675c3
c48c29a
69c5783
5db97d6
1ed5b4c
2c208ac
db42b07
162884c
eba5b0e
a88cea8
1a7cfe1
5296198
9b964ce
7b001af
614ae72
b10ee9d
a332a6c
e0136d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 | ||
|
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IDE 1.6.8 has been released :) (as of yesterday). There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
||
|
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(); | ||
} | ||
} |
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() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about moving this into the There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
} | ||
} | ||
} |
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 */ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
.