Giter VIP home page Giter VIP logo

aws-iot-device-sdk-arduino-yun's Introduction

AWS IoT Arduino Yún SDK

What is AWS IoT Arduino Yún SDK

The AWS-IoT-Arduino-Yún-SDK allows developers to connect their Arduino Yún compatible Board to AWS IoT. By connecting the device to the AWS IoT, users can securely work with the message broker, rules and the Thing Shadow provided by AWS IoT and with other AWS services like AWS Lambda, Amazon Kinesis, Amazon S3, etc.


Overview

This document provides step by step instructions to install the Arduino Yún SDK and connect your device to the AWS IoT.
The AWS-IoT-Arduino-Yún-SDK consists of two parts, which take use of the resources of the two chips on Arduino Yún, one for native Arduino IDE API access and the other for functionality and connections to the AWS IoT built on top of a modified Eclipse Paho paho-mqtt python package.

MQTT connection

The AWS-IoT-Arduino-Yún-SDK provides APIs to let users publish messages to AWS IoT and subscribe to MQTT topics to receive messages transmitted by other devices or coming from the broker. This allows to interact with the standard MQTT PubSub functionality of AWS IoT. More information on MQTT protocol is available here.

Thing shadow

The AWS-IoT-Arduino-Yún-SDK also provides APIs to provide access to thing shadows in AWS IoT. Using this SDK, users will be able to sync the data/status of their devices as JSON files to the cloud and respond to change of status requested by other applications. More information on Thing Shadow is available here.


Installation

Download AWS-IoT-Arduino-Yún-SDK

Click here to download AWS-IoT-Arduino-Yún-SDK zip package and extract it to AWS-IoT-Arduino-Yun-SDK on your computer.

Set up your Arduino Yún Board

Please follow the instructions from official website: Arduino Yún Guide.

Installation on Mac OS/Linux

Before proceeding to the following steps, please make sure that you have expect installed on your computer and correctly installed the Arduino IDE.
To install expect:
For Ubuntu, simply run sudo apt-get install expect.
For Mac, expect is installed as default.
For Arduino IDE installation on Linux, please visit here.

  1. Setup the Arduino Yún board and connect it to WiFi. Obtain its IP address and password.
  2. Make sure your computer is connected to the same network (local IP address range).
  3. Download the AWS IoT CA file from here.
  4. Put your AWS IoT CA file, private key and certificate into AWS-IoT-Arduino-Yun-SDK/AWS-IoT-Python-Runtime/certs. If you are using MQTT over Websocket, you can put only your AWS IoT CA file into the directory. You should have a correctly configured AWS Identity and Access Management (IAM) role with a proper policy, and a pair of AWS Access Key and AWS Secret Access Key ID, which will be used in step 6. For more information about IAM, please visit AWS IAM home page.
  5. Open a terminal, cd to AWS-IoT-Arduino-Yun-SDK. Do chmod 755 AWSIoTArduinoYunInstallAll.sh and execute it as ./AWSIoTArduinoYunInstallAll.sh <Board IP> <UserName> <Board Password>. By default for Arduino Yún Board, your user name will be root and your password will be arduino.
    This script will upload the python runtime codebase and credentials to openWRT running on the more powerful microcontroller on you Arduino Yún board.
    This script will also download and install libraries for openWRT to implement the necessary scripting environment as well as communication protocols.

Step 5 can take 1-5 minutes for the device to download and install the required packages (distribute, python-openssl).

NOTE: Do NOT close the terminal before the script finishes, otherwise you have to start over with step 5. Make sure you are in your local terminal before repeating step 5.

  1. Optional, only for Websocket. Open a terminal, cd to AWS-IoT-Arduino-Yun-SDK. Do chmod 755 AWSIoTArduinoYunWebsocketCredentialConfig.sh and execute it as ./AWSIoTArduinoYunWebsocketCredentialConfig.sh <Board iP> <UserName> <Board Password> <AWS_ACCESS_KEY_ID_STRING> <AWS_SECRET_ACCESS_KEY_STRING>.
    This script will add the given key ID and secret key onto the OpenWRT as envrionment variables $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY.

    NOTE1: You can always use this script to update your IAM credentials used on the board. The script will handle the update of the environment variables for you.

    NOTE2: Please follow the instructions on the screen after the script completes to power-cycle your board to enable all the environment changes on OpenWRT.

  2. Copy and paste AWS-IoT-Arduino-Yun-SDK/AWS-IoT-Arduino-Yun-Library folder into Arduino libraries that was installed with your Arduino SDK installation. For Mac OS default, it should be under Documents/Arduino/libraries.

  3. Restart the Arduino IDE if it was running during the installation. You should be able to see the AWS IoT examples in the Examples folder in your IDE.

There are the other two scripts: AWSIoTArduinoYunScp.sh and AWSIoTArduinoYunSetupEnvironment.sh, which are utilized in AWSIoTArduinoYunInstallAll.sh. You can always use AWSIoTArduinoYunScp.sh to upload your new credentials to your board. When you are in the directory AWS-IoT-Arduino-Yun-SDK/, the command should be something like this:

./AWSIoTArduinoYunScp.sh <Board IP> <UserName> <Board Password> <File> <Destination>


Installation on Windows

Before proceeding to the following steps, please make sure that you have Putty and WinSCP installed on your PC. If you prefer to use other tools for SSH-ing into your Arduino Yún board and transferring files, you will have to adjust the steps below according to your tools.
Putty can be downloaded from here.
WinSCP can be downloaded from here.

  1. Setup the Arduino Yún Cloud board and connect it to WiFi. Obtain its IP address and password.

  2. Make sure your PC is connected to the same network (local IP address range).

  3. Download the AWS IoT CA file from here.

  4. Put your AWS IoT CA file, private key and certificate into AWS-IoT-Arduino-Yun-SDK/AWS-IoT-Python-Runtime/certs. If you are using MQTT over Websocket, you can put only your AWS IoT CA file into the directory. You should have a correctly configured AWS Identity and Access Management (IAM) role with a proper policy, and a pair of AWS Access Key and AWS Secret Access Key ID, which will be used in step 7. For more information about IAM, please visit AWS IAM home page.

  5. Start WinSCP and upload AWS-IoT-Python-Runtime/ folder to /root on the board.

  6. Use Putty to ssh into OpenWRT on your board and execute the following commands to install the necessary libraries:

     opkg update
     opkg install distribute
     opkg install python-openssl
    

It can take 1-5 minutes for the device to download and install the required packages.

  1. Optional, only for Websocket. Use Putty to ssh into OpenWRT on your board and modify /etc/profile to include your IAM credentials as envrionment variables:

     ...
     export AWS_ACCESS_KEY_ID=<AWS_ACCES_KEY_ID_STRING>
     export AWS_SECRET_ACCESS_KEY=<AWS_SECRET_ACCESS_KEY_STRING>
     ...
    

After that, run source /etc/profile and power-cycle the board to enable the changes.

  1. Copy and paste AWS-IoT-Arduino-Yun-SDK/AWS-IoT-Arduino-Yun-Library folder into Arduino libraries that was installed with your Arduino SDK installation. For Windows default, it should be under Documents/Arduino/libraries.
  2. Restart the Arduino IDE if it was running during the installation. You should be able to see the AWS IoT examples in the Examples folder in your IDE.

API documentation

Class Name:

aws_iot_mqtt_client

API:

IoT_Error_t setup(char* client_id, bool clean_session, MQTTv_t MQTT_version, bool useWebsocket)

Description
Start the Python runtime and set up connection for aws_iot_mqtt_client object. Must be called before any of aws_iot_mqtt_client API is called.

Syntax

object.setup("myClientID"); // setup a client with client_id set to "myClientID"
object.setup("myClientID", true, MQTTv31, true); // setup a client with client_id set to "myClientID", with clean_session set to true, using MQTT 3.1, over Websocket

Parameters
client_id - The client id for this connection.
clean_session - Clear the previous connection with this id or not. Default value is true.
MQTT_version - Version of MQTT protocol for this connection, either MQTTv31 (MQTT version 3.1) or MQTTv311 (MQTT version 3.1.1). Default value is MQTTv311.
useWebsocket - Enable the use of Websocket or not. Default value is false. IAM credentials must be included in the environment variables on OpenWRT to make a successful MQTT connection over Websocket.

Returns
NONE_ERROR if the setup on openWRT side and connection settings are correct.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if input string exceeds the internal buffer size.
SET_UP_ERROR if the setup failed.
SERIAL1_COMMUNICATION_ERROR if there is an error in serial1 communication between the two chips.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t config(char* host, int port, char* cafile_path, char* keyfile_path, char* certfile_path)

Description
Configure host, port and certs location used to connect to AWS IoT. If the input strings for host, cafile_path, keyfile_path and certfile_path are set to NULL, the default value will be used to connect. Must be called to load user settings right after aws_iot_mqtt_client::setup and before connect.

Syntax

object.config("example.awsamazon.com", 1234, "./cafile", "./keyfile", "./certfile");

Parameters
host - The endpoint to connect to. Must be a NULL-terminated string.
port - The port number to connect to.
cafile_path - The path of CA file on OpenWRT. Must be a NULL-terminated string.
keyfile_path - The path of private key file on OpenWRT. Must be a NULL-terminated string.
certfile_path - The path of certificate file on OpenWRT. Must be a NULL-terminated string.

Returns
NONE_ERROR if the configuration is successful.
NO_SET_UP_ERROR if no setup is called before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
CONFIG_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t configWss(char* host, int port, char* cafile_path)

Description
Configure host, port and rootCA location used to connect to AWS IoT over Websocket. If the input strings for host and cafile_path are set to NULL, the default value will be used to connect. Must be called to load user settings right after aws_iot_mqtt_client::setup and before connect. The client must be configured in setup to use Websocket.

Syntax

object.configWss("example.awsamazon.com", 1234, "./cafile");

Parameters
host - The endpoint to connect to. Must be a NULL-terminated string.
port - The port number to connect to.
cafile_path - The path of CA file on OpenWRT. Must be a NULL-terminated string.

Returns
NONE_ERROR if the configuration is successful.
NO_SET_UP_ERROR if no setup is called before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
CONFIG_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t connect(int keepalive_interval)

Description
Connect to AWS IoT, using user-specific keepalive setting.

Syntax

object.connect(); // connect to AWS IoT with default keepalive set to 60 seconds
object.connect(55); // connect to AWS IoT with keepalive set to 55 seconds

Parameters
keepalive_interval - amount of time for MQTT ping request interval, in seconds. Default is set to 60 seconds.

Returns
NONE_ERROR if the connect is successful.
NO_SET_UP_ERROR if no setup is called before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
CONNECT_SSL_ERROR if the TLS handshake failed.
CONNECT_ERROR if the connection failed.
CONNECT_TIMEOUT if the connection gets timeout.
CONNECT_CREDENTIAL_NOT_FOUND if the specified credentials are not found on OpenWRT.
WEBSOCKET_CREDENTIAL_NOT_FOUND if the IAM credentials do not exist as environment variables on OpenWRT.
CONNECT_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t publish(char* topic, char* payload, int payload_len, int qos, bool retain)

Description
Publish a new message to the desired topic with qos and retain flag settings using MQTT protocol

Syntax

object.publish("myTopic", "myMessage", strlen("myMessage"), 0, false); // publish "myMessage" to topic "myTopic" in QoS 0 with retain flag set to false

Parameters
topic - Topic name to publish to. Must be a NULL-terminated string.
payload - Payload to publish.
payload_len - Length of payload.
qos - Qualiy of service, could be 0 or 1.
retain - retain flag.

Returns
NONE_ERROR if the publish is successful.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if topic/payload exceeds the internal buffer size.
NO_SET_UP_ERROR if no setup is called before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
PUBLISH_ERROR if the publish failed.
PUBLISH_TIMEOUT if the publish gets timeout.
PUBLISH_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t subscribe(char* topic, int qos, message_callback cb)

Description
Subscribe to the desired topic and register a callback for new messages from this topic.

Syntax

object.subscribe("myTopic", 0, myCallbackFunc); // subscribe to topic "myTopic" in QoS 0 and register its callback function as myCallbackFunc

Parameters
topic - The topic to subscribe to. Must be a NULL-terminated string.
qos - Quality of service, could be 0 or 1.
cb - Function pointer to user-specific callback function to call when a new message comes in for the subscribed topic. The callback function should have a parameter list of (char*, int) to store the incoming message content and the length of the message.

Returns
NONE_ERROR if the subscribe is successful.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if topic/payload exceeds the internal buffer size.
OUT_OF_SKETCH_SUBSCRIBE_MEMORY if the number of current subscribe exceeds the configured number in aws_iot_config_SDK.h.
NO_SET_UP_ERROR if no setup is called before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
SUBSCRIBE_ERROR if the subscribe failed.
SUBSCRIBE_TIMEOUT if the subscribe gets timeout.
SUBSCRIBE_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t unsubscribe(char* topic)

Description
Unsubscribe to the desired topic.

Syntax

object.unsubscribe("myTopic");

Parameters
topic - The topic to unsubscribe to. Must be a NULL-terminated string.

Returns
NONE_ERROR if the unsubscribe is successful.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if topic exceeds the internal buffer size.
NO_SET_UP_ERROR if no setup is called before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
UNSUBSCRIBE_ERROR if the unsubscribe failed.
UNSUBSCRIBE_TIMEOUT if the unsubscribe gets timeout.
UNSUBSCRIBE_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t yield()

Description
Called in the loop to check if there is a new message from all subscribed topics, as well as thing shadow topics. Registered callback functions will be called according to the sequence of messages if there is any. Specifically, unnecessary shadow thing topics (accepted/rejected) will be unsubscribed according to the incoming new messages to free subscribe slots. Users should call this function frequently to receive new messsages and free subscribe slots for new subscribes, especially for shadow thing requests.

Syntax

object.yield();

Parameters
None

Returns
NONE_ERROR if the yield is successful, whether there is a new message or not.
OVERFLOW_ERROR if the new message exceeds the internal buffer size.
YIELD_ERROR if the yield failed.

IoT_Error_t disconnect()

Description
Disconnect from AWS IoT.

Syntax

object.disconnect();

Parameters
None

Returns
NONE_ERROR if disconnect is successful.
NO_SET_UP_ERROR if no setup is called before this call.
DISCONNECT_ERROR if the disconnect failed.
DISCONNECT_TIMEOUT if the disconnect gets timeout.
DISCONNECT_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t shadow_init(char* thingName)

Description
Initialize thing shadow configuration and a shadow instance with thingName. Should be called before any of the thing shadow API call for thingName shadow operations.

Syntax

object.shadow_init("NewThingName"); // Init thing shadow configuration and set thing name to "NewThingName"

Parameters
thingName - Thing name for the shadow instance to be created. Must be a NULL-terminated string.

Returns
NONE_ERROR if thing shadow is successfully initialized.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if thing name exceeds the internal buffer size.
SHADOW_INIT_ERROR if thing shadow initialization failed.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t shadow_update(char* thingName, char* payload, int payload_len, message_callback cb, int timeout)

Description
Update the thing shadow data in the cloud by publishing a new JSON file onto the corresponding thing shadow topic and subscribing accepted/rejected thing shadow topics to get feedback of whether it is a successful/failed request. Timeout can be set in seconds as the maximum waiting time for feedback. Once the request gets timeout, a timeout message will be received. The registered callback function will be called whenever there is an accepted/rejected/timeout feedback. Subscription to accepted/rejected topics will be processed in a persistent manner and will not be unsubscribed once this API is called for this shadow.

Syntax

object.shadow_update("UserThingName", JSON_FILE, strlen(JSON_FILE), UserCallbackFunction, 5); // update the data of "UserThingName" thing shadow in the cloud to JSON_FILE, with a timeout of 5 seconds and UserCallbackFunction as the callback function

Parameters
thingName - The name of the thing shadow in the cloud. Must be a NULL-terminated string.
payload - The data that needs to be updated into the cloud, in JSON file format.
payload_len - Length of payload
cb - Function pointer to user-specific callback function to call when a new message comes in for the subscribed topic. The callback function should have a parameter list of (char*, int) to store the incoming message content and the length of the message.
timeout - The maximum time to wait for feedback.

Returns
NONE_ERROR if the shadow update request succeeds.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if thing name/payload exceeds the internal buffer size.
OUT_OF_SKETCH_SUBSCRIBE_MEMORY if the number of current subscribe exceeds the configured number in aws_iot_config_SDK.h.
NO_SHADOW_INIT_ERROR if the shadow with thingName is initialized before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
SUBSCRIBE_ERROR if the subscribe (accepted/rejected) failed.
SUBSCRIBE_TIMEOUT if the subscribe gets timeout.
PUBLISH_ERROR if the publish (payload) failed.
PUBLISH_TIMEOUT if the publish (payload) gets timeout.
SHADOW_UPDATE_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t shadow_get(char* thingName, message_callback cb, int timeout)

Description
Obtain the thing shadow data in the cloud by publishing an empty JSON file onto the corresponding thing shadow topic and subscribing accepted/rejected thing shadow topics to get feedback of whether it is a successful/failed request. Timeout can be set in seconds as the maximum waiting time for feedback. Once the request gets timeout, a timeout message will be received. The registered callback function will be called whenever there is an accepted/rejected/timeout feedback. Subscription to accepted/rejected topics will be processed in a persistent manner and will not be unsubscribed once this API is called for this shadow. Thing shadow data will be available as a JSON file in the callback.

Syntax

object.shadow_get("UserThingName", UserCallbackFunction, 5); // get the data of the thing shadow "UserThingName", with a timeout of 5 seconds and UserCallbackFunction as the callback function

Parameters
thingName - The name of the thing shadow in the cloud. Must be a NULL-terminated string.
cb - Function pointer to user-specific callback function to call when a new message comes in for the subscribed topic. The callback function should have a parameter list of (char*, int) to store the incoming message content and the length of the message.
timeout - The maximum time to wait for feedback.

Returns
NONE_ERROR if the shadow get request succeeds.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if thing name exceeds the internal buffer size.
OUT_OF_SKETCH_SUBSCRIBE_MEMORY if the number of current subscribe exceeds the configured number in aws_iot_config_SDK.h.
NO_SHADOW_INIT_ERROR if the shadow with thingName is initialized before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
SUBSCRIBE_ERROR if the subscribe (accepted/rejected) failed.
SUBSCRIBE_TIMEOUT if the subscribe gets timeout.
PUBLISH_ERROR if the publish (payload) failed.
PUBLISH_TIMEOUT if the publish (payload) gets timeout.
SHADOW_GET_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t shadow_delete(char* thingName, message_callback cb, int timeout)

Description
Delete the thing shadow data in the cloud by publishing an empty JSON file onto the corresponding thing shadow topic and subscribing accepted/rejected thing shadow topics to get feedback of whether it is a successful/failed request. Timeout can be set in seconds as the maximum waiting time for feedback. Once the request gets timeout, a timeout message will be received. The registered callback function will be called whenever there is an accepted/rejected/timeout feedback. After the feedback comes in, it will automatically unsubscribe accepted/rejected shadow topics.

Syntax

object.shadow_delete("UserThingName", UserCallbackFunction, 5); // delete the data of the thing shadow "UserThingName", with a timeout of 5 seconds and UserCallbackFunction as the callback function

Parameters
thingName - The name of the thing shadow in the cloud. Must be a NULL-terminated string.
cb - Function pointer to user-specific callback function to call when a new message comes in for the subscribed topic. The callback function should have a parameter list of (char*, int) to store the incoming message content and the length of the message.
timeout - The maximum time to wait for feedback.

Returns
NONE_ERROR if the shadow delete request succeeds.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if thing name exceeds the internal buffer size.
OUT_OF_SKETCH_SUBSCRIBE_MEMORY if the number of current subscribe exceeds the configured number in aws_iot_config_SDK.h.
NO_SHADOW_INIT_ERROR if the shadow with thingName is initialized before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
SUBSCRIBE_ERROR if the subscribe (accepted/rejected) failed.
SUBSCRIBE_TIMEOUT if the subscribe gets timeout.
PUBLISH_ERROR if the publish (payload) failed.
PUBLISH_TIMEOUT if the publish (payload) gets timeout.
SHADOW_DELETE_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t shadow_register_delta_func(char* thingName, message_callback cb)

Description
Subscribe to the delta topic of the corresponding thing shadow with the given name and register a callback. Whenever there is a difference between the desired and reported state data, the registered callback will be called and the feedback/message will be available in the callback.

Syntax

object.shadow_register_delta_func("UserThingName", UserCallBackFunction); // register UserCallbackFunction as the  delta callback function for the thing shadow "UserThingName"

Parameters
thingName - The name of the thing shadow in the cloud. Must be a NULL-terminated string.
cb - Function pointer to user-specific callback function to call when a new message comes in for the subscribed topic. The callback function should have a parameter list of (char*, int) to store the incoming message content and the length of the message.

Return
NONE_ERROR if the shadow delta topic is successfully subscribed and the callback function is successfully registered.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if thing name exceeds the internal buffer size.
OUT_OF_SKETCH_SUBSCRIBE_MEMORY if the number of current subscribe exceeds the configured number in aws_iot_config_SDK.h.
NO_SHADOW_INIT_ERROR if the shadow with thingName is initialized before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
SUBSCRIBE_ERROR if the subscribe (accepted/rejected) failed.
SUBSCRIBE_TIMEOUT if the subscribe gets timeout.
SHADOW_REGISTER_DELTA_CALLBACK_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.

IoT_Error_t shadow_unregister_delta_func(char* thingName)

Description
Unsubscribe to the delta topic of the corresponding thing shadow with the given name and unregister the callback. There will be no message coming after this API call if another difference occurs between the desired and reported state data for this thing shadow.

Syntax

object.shadow_unregister_delta_func("UserThingName"); // unregister the delta topic of the thing shadow "UserThingName"

Parameters
thingName - The name of the thing shadow in the cloud. Must be a NULL-terminated string.

Returns
NONE_ERROR if the shadow delta topic is successfully unsubscribed and the callback function is successfully unregistered.
NULL_VALUE_ERROR if input parameters have NULL value.
OVERFLOW_ERROR if thing name exceeds the internal buffer size.
NO_SHADOW_INIT_ERROR if the shadow with thingName is initialized before this call.
WRONG_PARAMETER_ERROR if there is an error for the Python Runtime to get enought input parameters for this command.
UNSUBSCRIBE_ERROR if the subscribe (accepted/rejected) failed.
UNSUBSCRIBE_TIMEOUT if the subscribe gets timeout.
SHADOW_UNREGISTER_DELTA_CALLBACK_GENERIC_ERROR if there is an error in executing the command in Python Runtime.
GENERIC_ERROR if an unknown error happens.


Using the SDK

Make sure you have properly installed the AWS-IoT-Arduino-Yún-SDK and setup the board.

Make sure to start the sketch after openWRT is ready and gets connected to WiFi. It takes about 80-90 seconds for Arduino Yún board to start the openWRT and get connected to WiFi for each power cycle.

Make sure you have properly configured SDK settings in aws_iot_config.h inside each sketch directory:

//===============================================================
#define AWS_IOT_MQTT_HOST "data.iot.us-east-1.amazonaws.com" 	// your endpoint
#define AWS_IOT_MQTT_PORT 8883									// your port, use 443 for MQTT over Websocket
#define AWS_IOT_CLIENT_ID	"My_ClientID"						// your client ID
#define AWS_IOT_MY_THING_NAME "My_Board"						// your thing name
#define AWS_IOT_ROOT_CA_FILENAME "aws-iot-rootCA.crt"           // your root-CA filename
#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem"                 // your certificate filename
#define AWS_IOT_PRIVATE_KEY_FILENAME "privkey.pem"              // your private key filename
//===============================================================

These settings can be downloaded from the AWS IoT console after you created a device and licked on "Connect a device".

Make sure you have included the AWS-IoT-Arduino-Yún-SDK library:

#include <aws_iot_mqtt.h>

Make sure you have included your configuration header file:

#include "aws_iot_config.h"

Make sure you have enough memory for subscribe, messages and sketch runtime. Internal buffer size is defined in SDK library source directory libraries/AWS-IoT-Arduino-Yun-Library/aws_iot_config_SDK.h. The following are default settings:

#define MAX_BUF_SIZE 256										// maximum number of bytes to publish/receive
#define MAX_SUB 15 												// maximum number of subscribe
#define CMD_TIME_OUT 200										// maximum time to wait for feedback from AR9331, 200 = 10 sec

Make sure you setup the client, configure it using your configuration and connect it to AWS IoT first. Remember to use certs path macros for configuration:

aws_iot_mqtt_client myClient;
myClient.setup(AWS_IOT_CLIENT_ID);
// myClient.setup(AWS_IOT_CLIENT_ID, true, MQTTv31, true); // Use Websocket
myClient.config(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, AWS_IOT_ROOT_CA_PATH, AWS_IOT_PRIVATE_KEY_PATH, AWS_IOT_CERTIFICATE_PATH);
// myClient.configWss(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, AWS_IOT_ROOT_CA_PATH); // Use Websocket
myClient.connnect();

Remember to check incoming messages in a loop:

void loop() { 
  ...  
  myClient.yield();
  ...
}

When you are using thing shadow API for a specific device shadow name, make sure you initialize the shadow with your device shadow name first:

myClient.shadow_init(AWS_IOT_MY_THING_NAME); // For shadow of this device
myClient.shadow_init("AnotherDevice"); // For another shadow

When you are using thing shadow API, always make sure MAX_SUB is big enough for a thing shadow request in the loop:

...
myClient.shadow_get("myThingName", myCallback, 5); // need 2 in MAX_SUB
...
void loop() {
	...
	myClient.shadow_get("myThingName", myCallback, 5); // need 4 in MAX_SUB
	myClient.yield(); // unsubscribe thing shadow topics when necessary
	...
}

When you are using thing shadow API, make sure you set the timeout to a proper value and frequently call yield to free subscribe resources. Long timeout with low rate of yielding and high rate of shadow request will result in exhaustion of subscribe resources:

void loop() {
	...
	myClient.shadow_get("myThingName", myCallback, 5); // 5 sec timeout is fine for a request per 5 sec
	
	// myClient.shadow_get("myThingName", myCallback, 50);
	// 50 sec timeout is too long. When missing feedback happens frequently, with a rate of 1 request per 5 sec, subscribed topics will soon accumulate and exceed MAX_SUB before any of the previously-subscribed topic gets timeout and unsubscribed
	
	myClient.yield();
	
	delay(5000); // 5 sec delay
	...
}

Enjoy the Internet of Things!


Example

BasicPubSub

This example demonstrates a simple MQTT publish/subscribe using AWS IoT from Arduino Yún board. It first subscribes to a topic once and registers a callback to print out new messages to Serial monitor and then publishes to the topic in a loop. Whenever it receives a new message, it will be printed out to Serial monitor indicating the callback function has been called.

  • Hardware Required
    Arduino Yún
    Computer connected with Arduino Yún using USB serial

  • Software Required
    None

  • Circuit Required
    None

  • Attention
    Please make sure to start the example sketch after the board is fully set up and openWRT is up and connected to WiFi. See here.

  • Code
    Create an instance of aws_iot_mqtt_client.

      aws_iot_mqtt_client myClient;
    

    In setup(), open the Serial. Set the instance up and connect it to the AWS IoT.

      Serial.begin(115200);
      ...
      if((rc = myClient.setup(AWS_IOT_CLIENT_ID)) == 0) {
      	// Load user configuration
      	if((rc = myClient.config(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, AWS_IOT_ROOT_CA_PATH, AWS_IOT_PRIVATE_KEY_PATH, AWS_IOT_CERTIFICATE_PATH)) == 0) {
    			// Use default connect: 60 sec for keepalive
    			if((rc = myClient.connect()) == 0) {
      			success_connect = true;
      			...
      		}
      		else {...}
      	}
      	else {...}
      }
      else {...}
      ...
    

    In setup(), subscribe to the desired topic and wait for some delay time.

    	if((rc = myClient.subscribe("topic1", 1, msg_callback)) != 0) {
      	Serial.println("Subscribe failed!");
      	Serial.println(rc);
      }
      delay(2000);
    

    In loop(), publish to this topic and call yield function to receive the message every 5 seconds.

      sprintf(msg, "new message %d", cnt);
      if((rc = myClient.publish("topic1", msg, strlen(msg), 1, false)) != 0) {
      	Serial.println("Publish failed!");
      	Serial.println(rc);
      }
      if((rc = myClient.yield()) != 0) {
      	Serial.println("Yield failed!");
      	Serial.println(rc);
      }
      ...
      delay(5000);
    

    The full sketch can be found in AWS-IoT-Arduino-Yun-Library/examples/BasicPubSub.

ThingShadowEcho sample app

This example demonstrates Arduino Yún board as a device communicating with AWS IoT, syncing data into the thing shadow in the cloud and receiving commands from an app. Whenever there is a new command from the app side to change the desired state of the device, the board will receive this request and apply the change by publishing it as the reported state. By registering a delta callback function, users will be able to see this incoming message and notice the syncing of the state.

  • Hardware Required
    Arduino Yún
    Computer connected with Arduino Yún using USB serial

  • Software Required
    App-side code that updates the state of the corresponding thing shadow in the cloud
    Note: You can also use AWS IoT console to update the shadow data.

  • Circuit Required
    None

  • Attention
    Please make sure to start the example sketch after the board is fully set up and openWRT is up and connected to WiFi. See here.

  • Code
    Create an instance of aws_iot_mqtt_client.

      aws_iot_mqtt_client myClient;
    

    Create logging function for execution tracking.

      bool print_log(char* src, int len) {
      	...
      }
    

    In setup(), open the Serial. Set the instance up and connect it to the AWS IoT. Init the shadow and register a delta callback function. All steps are tracked using logging function.

      if(print_log("setup", myClient.setup(AWS_IOT_CLIENT_ID))) {
      	if(print_log("config", myClient.config(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, AWS_IOT_ROOT_CA_PATH, AWS_IOT_PRIVATE_KEY_PATH, AWS_IOT_CERTIFICATE_PATH))) {
      		if(print_log("connect", myClient.connect())) {
      			success_connect = true;
      			print_log("shadow init", myClient.shadow_init(AWS_IOT_MY_THING_NAME));
      			print_log("register thing shadow delta function", myClient.shadow_register_delta_func(AWS_IOT_MY_THING_NAME, msg_callback_delta));
    			}
      	}
      }
    

    In loop(), yield to check and receive new incoming messages every 1 second.

      if(myClient.yield()) {
      	Serial.println("Yield failed.");
      }
      delay(1000);
    

    For delta callback function, simply parse out the desired state and put it as the reported state in the JSON file that needs to be updated.

      void msg_callback_delta(char* src, int len) {
      	String data = String(src);
      	int st = data.indexOf("\"state\":") + strlen("\"state\":");
      	int ed = data.indexOf(",\"metadata\":");
      	String delta = data.substring(st, ed);
      	String payload = "{\"state\":{\"reported\":";
      	payload += delta;
      	payload += "}}";
      	payload.toCharArray(JSON_buf, 100);
      	print_log("update thing shadow", myClient.shadow_update(AWS_IOT_MY_THING_NAME, JSON_buf, strlen(JSON_buf), NULL, 5));
      }
    

    Once an update of the desired state for this device is received, a delta message will be received and displayed in the Serial monitor. The device will update this data into the cloud.

    The full sketch can be found in AWS-IoT-Arduino-Yun-Library/examples/ThingShadowEcho.

Simple Thermostat Simulator

This example demonstrates Arduino Yún as a device accepting instructions and syncing reported state in shadow in AWS IoT, which simulates a thermostat to control the temperature of a room. With the provided example App script, users will be able to get real-time temperature data coming from the board and be able to remotely set the desired temperature. This example also demonstrates how to retrieve shadow JSON data received on Arduino Yún Board.
Eclipse Paho paho-mqtt python package is used in App scripts for MQTT connections. Users can modify it to use other MQTT library according to their needs.

  • Hardware Required
    Arduino Yún
    Computer connected with Arduino Yún using USB serial and running example App scripts

  • Software Required
    Tkinter for App GUI
    Eclipse Paho paho-mqtt python package for MQTT connectivity
    Example App script, which is included in the ExampleAppScripts/ThermostatSimulatorApp/
    Note: You can also use AWS IoT console to update the shadow data.

  • Circuit Required
    None

  • Attention
    Please make sure to start the example sketch after the board is fully set up and openWRT is up and connected to WiFi. See here.

  • Getting started
    Before proceeding to the following steps, please make sure you have your board set up, with all codebase and credentials properly installed. Please make sure you attach the correct policy to your certificate.

    1. Modify your configuration file to match your own credentials and host address.
    2. Start the sketch when the board boots up. It should pass the initialization steps and then start to update shadow data. It should have a similar display in the serial monitor as follows:

    3. On the App side, please make sure you have [Tkinter](http://tkinter.unpythonic.net/wiki/How_to_install_Tkinter) and [Eclipse Paho paho-mqtt python package](https://pypi.python.org/pypi/paho-mqtt) pre-installed on your computer. 4. Copy and paste your credentials (certificate, private key and rootCA) into `ThermostatSimulatorApp/certs/`. Please make sure to keep the file names as they are downloaded and make sure the CA file name ends with `CA.crt`. 5. In the directory `ThermostatSimulatorApp/`, start the App script by executing `python ThermostatSimulatorApp.py -h `. You should be able to see a GUI prompt up with default reported temperature:

    6. Try to input a desired temperature and click SET. If it succeeds, you should be able to see the desired temperature on the panel and a log printed out in the console space. The board will start continuously syncing temperature settings:

    *Note:* The temperature is configured to be lower than 100 F and higher than -100 F. Error message will be printed out if there is a malformed setting:

  • Code
    Create an instance of aws_iot_mqtt_client.

      aws_iot_mqtt_client myClient;
    

    Create logging function for execution tracking.

      bool print_log(char* src, int len) {
      	...
      }
    

    In setup(), open the Serial. Set the instance up and connect it to the AWS IoT. Init the shadow and register a delta callback function. All steps are tracked using logging function.

      if(print_log("setup", myClient.setup(AWS_IOT_CLIENT_ID))) {
        if(print_log("config", myClient.config(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, AWS_IOT_ROOT_CA_PATH, AWS_IOT_PRIVATE_KEY_PATH, AWS_IOT_CERTIFICATE_PATH))) {
          if(print_log("connect", myClient.connect())) {
            success_connect = true;
            print_log("shadow init", myClient.shadow_init(AWS_IOT_MY_THING_NAME));
            print_log("register thing shadow delta function", myClient.shadow_register_delta_func(AWS_IOT_MY_THING_NAME, msg_callback_delta));
          }
        }
      }
    

    In loop(), simulate the behavior of a thermostat. Check to see the difference between the desired and the reported temperature. If the desired temperature is higher, increase the reported temperature by 0.1 degree per 1 second (per loop). If the desired one is lower, decrease the reported temperature by 0.1 degree per 1 second (per loop). Increase/Decrease action will happen until the reported reaches the desired. Update the reported temperature and then yield to check if there is any new delta message.

      void loop() {
        if(success_connect) {
          if(desiredTemp - reportedTemp > 0.001) {reportedTemp += 0.1;}
          else if(reportedTemp - desiredTemp > 0.001) {reportedTemp -= 0.1;}
          dtostrf(reportedTemp, 4, 1, float_buf);
          float_buf[4] = '\0';
          sprintf(JSON_buf, "{\"state\":{\"reported\":{\"Temp\":%s}}}", float_buf);
          print_log("shadow update", myClient.shadow_update(AWS_IOT_MY_THING_NAME, JSON_buf, strlen(JSON_buf), NULL, 5));
          if(myClient.yield()) {
            Serial.println("Yield failed.");
          }
          delay(1000); // check for incoming delta per 1000 ms
        }
      }
    

    For delta callback function, parse out the desired state and the desired temperature data in it. Update the desired temperature record on board so that the board knows what to do, heating or cooling.

      void msg_callback_delta(char* src, int len) {
        String data = String(src);
        int st = data.indexOf("\"state\":") + strlen("\"state\":");
        int ed = data.indexOf(",\"metadata\":");
        String delta = data.substring(st, ed);
        st = delta.indexOf("\"Temp\":") + strlen("\"Temp\":");
        ed = delta.indexOf("}");
        String delta_data = delta.substring(st, ed);
        desiredTemp = delta_data.toFloat();
      }
    

    Each time the board receives a new desired temperature different from its reported temperature. Changes will happen, synced into shadow and captured by the example App. Users will be able to see the whole process of temperature updating from the App side.

    The full sketch can be found in AWS-IoT-Arduino-Yun-Library/examples/ThermostatSimulatorDevice.

Error code

The following error codes are defined in AWS-IoT-Arduino-Yun-Library/aws_iot_error.h:

typedef enum {
	NONE_ERROR = 0,
	GENERIC_ERROR = -1,
	NULL_VALUE_ERROR = -2,
	OVERFLOW_ERROR = -3,
	OUT_OF_SKETCH_SUBSCRIBE_MEMORY = -4,
	SERIAL1_COMMUNICATION_ERROR = -5,
	SET_UP_ERROR = -6,
	NO_SET_UP_ERROR = -7,
	WRONG_PARAMETER_ERROR = -8,
	CONFIG_GENERIC_ERROR = -9,
	CONNECT_SSL_ERROR = -10,
	CONNECT_ERROR = -11,
	CONNECT_TIMEOUT = -12,
	CONNECT_CREDENTIAL_NOT_FOUND = -13,
	CONNECT_GENERIC_ERROR = -14,
	PUBLISH_ERROR = -15,
	PUBLISH_TIMEOUT = -16,
	PUBLISH_GENERIC_ERROR = -17,
	SUBSCRIBE_ERROR = -18,
	SUBSCRIBE_TIMEOUT = -19,
	SUBSCRIBE_GENERIC_ERROR = -20,
	UNSUBSCRIBE_ERROR = -21,
	UNSUBSCRIBE_TIMEOUT = -22,
	UNSUBSCRIBE_GENERIC_ERROR = -23,
	DISCONNECT_ERROR = -24,
	DISCONNECT_TIMEOUT = -25,
	DISCONNECT_GENERIC_ERROR = -26,
	SHADOW_INIT_ERROR = -27,
	NO_SHADOW_INIT_ERROR = -28,
	SHADOW_GET_GENERIC_ERROR = -29,
	SHADOW_UPDATE_GENERIC_ERROR = -30,
	SHADOW_UPDATE_INVALID_JSON_ERROR = -31,
	SHADOW_DELETE_GENERIC_ERROR = -32,
	SHADOW_REGISTER_DELTA_CALLBACK_GENERIC_ERROR = -33,
	SHADOW_UNREGISTER_DELTA_CALLBACK_GENERIC_ERROR = -34,
	YIELD_ERROR = -35,
	WEBSOCKET_CREDENTIAL_NOT_FOUND = -36
} IoT_Error_t;

Support

If you have technical questions about AWS IoT Device SDK, please use AWS IoT forum.
For any other questions on AWS IoT, please contact AWS Support.

aws-iot-device-sdk-arduino-yun's People

Contributors

christophsaalfeld avatar hyandell avatar liuszeng avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.