The SimpleIOT Arduino library is an easy way to connect and send/receive data to the cloud via the SimpleIOT framework.
SimpleIOT abstracts out IoT device connectivity and hides the underlying details so you can focus on your application's unique features.
In the SimpleIOT world, an installation supports the following concepts:
- Team: A single installation of SimpleIOT in the cloud. This is mainly relevant to using the Command-Line-Interface (CLI) tool.
- Project: Each back-end supports one or more Projects.
- Model: A Model describes a device's capabilities. For example, what data it likes to exchange with the cloud, whether an end-node or a gateway device, what features it supports (i.e., storage, encryption, or AI/ML.), and how it communicates with the cloud.
- DataType: A DataType is a single named value that can be exchanged between a device and the cloud. A Model typically has one or more DataTypes associated with it.
- Device: A Device represents a single instance of a Model. Each device has a unique identification via its serial_number.
- Data: A Data element is an instance of a DataType associated with a single Device. For example, if a Model defines a DataType named
pressure
, each unique Device will have its own instance ofpressure
. You can get/set values associated with each Device instance by name.
Data elements are bi-directional so that updates go from the devices to the cloud or from the cloud back to the device. It is up to the firmware to handle what to do with values received from the cloud.
To install the SDK, if using the Arduino IDE, go into the Library Manager and add the library named simpleiot-arduino
. If using arduino-cli you can add support as follows:
% arduino-cli lib install simpleiot-arduino
To install the latest version from this GitHub repo, you can use:
% arduino-cli lib install --git-url https://github.com/awslabs/simpleiot-arduino.git
The SimpleIOT library relies on the following libraries:
To use the library, you'll need to include the wifi settings, secret credentials, and header files:
#include "iot-secrets.h" // NOTE: this contains the certs for the remote service
#include "wifi-settings.h" // and the local wifi-settings
#include <SimpleIOT.h> // SimpleIOT SDK header
The iot-secrets.h
files need to contain the following settings. These will generate automatically when you create a SimpleIOT Device instance via the CLI.
- SIMPLEIOT_IOT_ENDPOINT: The endpoint of the IOT service.
- SIMPLE_IOT_ROOT_CA: The root CA certificate for the AWS IOT service. These can be found here.
- SIMPLE_IOT_DEVICE_CERT: The IOT Thing device certificate. The certificate can be manually generated and downloaded via the AWS IOT Console or the
iot device add
command in the SimpleIOT CLI. - SIMPLE_IOT_DEVICE_PRIVATE_KEY: The IOT Thing device private key. The key can be manually generated and downloaded via the AWS IOT Console or the
iot device add
command in the SimpleIOT CLI.
Consult iot-secrets-template.h
for what these fields should contain.
If the code is auto-generated by the CLI, these values are automatically substituted in the code generated by the iot firmware generate
CLI command. If you create the device via the CLI, a copy of these certificate files can be found in the ~/.simpleiot
directory under the team > project > model > device directory.
The wifi-settings.h
file contains your embedded WiFi SSID name and password for the device. These are:
- WIFI_SSID: SSID of your WiFi access point.
- WIFI_PASSWORD: WiFi password for your access point.
If the code is auto-generated by the CLI, these values can be automatically filled out in the generated code only if they are passed to the iot firmware generate
command. This can be done via the CLI --wifi_ssid
and --wifi_password
parameters or by setting the IOT_WIFI_SSID
and IOT_WIFI_PASSWORD
environment variables.
Consult wifi-settings-template.h
for what these fields should contain.
You must define a single global instance of the SimpleIOT class outside the setup
and loop
functions:
SimpleIOT* iot = NULL;
To use the firmware for a specific device, we recommend also defining the following #define values:
#define IOT_PROJECT "{project_name}" // Project name defined by CLI
#define IOT_MODEL "{model_name}" // Model name defined by CLI
#define IOT_SERIAL "{serial_number}" // Serial number defined by CLI
#define IOT_FW_VERSION "{firmware_version}" // Firmware version in the #.#.# semantic version
For example:
#define IOT_PROJECT "SensorDemo"
#define IOT_MODEL "SensorDemoDevice"
#define IOT_SERIAL "SD-0001"
#define IOT_FW_VERSION "1.0.0"
You can now initialize the library in your setup()
function by calling the create
and config
methods.
iot = SimpleIOT::create(WIFI_SSID, WIFI_PASSWORD, SIMPLEIOT_IOT_ENDPOINT,
SIMPLE_IOT_ROOT_CA, SIMPLE_IOT_DEVICE_CERT, SIMPLE_IOT_DEVICE_PRIVATE_KEY);
iot->config(IOT_PROJECT, IOT_MODEL, IOT_SERIAL, IOT_FW_VERSION, onConnectionReady, onDataFromCloud);
The create
method creates an instance of the SimpleIOT class. The values passed are:
- WiFi SSID
- WiFI Password
- AWS IOT Endpoint
- Text of the Root CA certificate
- Text of the AWS IOT Device Certificate
- Text of the AWS IOT Device Private Key
The config
method can then be used to pass runtime parameters to the SDK. Parameters are:
- Project name
- Model name
- Device (unique) serial number
- Firmware version in semver MAJOR.MINOR.REV (i.e. 1.2.16) format.
onConnectionReady
is a callback invoked when the connection with AWS IOT has been established.onDataFromCloud
is a callback handler invoked when data from the cloud is received.
The onConnectionReady
function can be defined as follows:
void onConnectionReady(SimpleIOT *iot, int status, String message) {
...
}
The function will be called when the WiFi connection and a TLS secure connection has been established to the cloud. It is recommended that no data be sent to the cloud until this method has been called. If any error is encountered, the status
value will be non-zero, and the message
will attempt to provide a reason for the failure.
The onDataFromCloud
function can be defined as follows:
void onDataFromCloud(SimpleIOT *iot, String name, String value, SimpleIOTType type)
{
...
}
This function is called when a value has changed from the cloud side. The data passed will be the name
and value
that changed. You can adjust this value remotely using the SimpleIOT CLI via the following command:
iot device set --name {name} --value {value}
This value can also be updated via the SimpleIOT REST API.
At the bottom of every Arduino loop
function, a call to SimpleIOT::loop
should be made to allow the underlying MQTT networking to send data to the server.
For example:
iot->loop();
Sending a sensor value to the cloud is usually done inside the Arduino loop()
function each time sensor data has been received.
The data can be any of the following:
- String
- Integer
- Float/Double
- Boolean
These are sent to the cloud via the set
method. For example:
float pressure_value = 23.3;
...
iot->set("pressure", pressure_value);
The key value must be the same as the DataType associated with this model device. If it is an invalid name, the value is ignored. No error will be returned to the end device. However, you can monitor and verify that the value was correctly received in the AWS CloudWatch console.
Different value-types can be sent in the form:
int set(const char* name, const char* value);
int set(const char* name, int value);
int set(const char* name, float value);
int set(const char* name, double value);
int set(const char* name, bool value);
Under the hood, all values are coerced into string form and sent to the cloud using the MQTT protocol.
If your device has a GPS sensor, you can tag individual readings with location data. The data on the cloud side is routed to the Amazon Location Service. Amazon Location allows you to map data points, create custom tracking maps, and perform various other location-based services.
To send GPS data, you can use the set
method version and pass latitude and longitude data:
iot->set("humidity", humidity, last_lat, last_lng);
All value setters support passing lat/long data:
int set(const char* name, const char* value, float latitude, float longitude);
int set(const char* name, int value, float latitude, float longitude);
int set(const char* name, float value, float latitude, float longitude);
int set(const char* name, double value, float latitude, float longitude);
int set(const char* name, bool value, float latitude, float longitude);
The data sent to the cloud, once received, is routed to several destinations:
If the DataType was designated as "show on twin" (the default), it will be rebroadcast via MQTT. This can be monitored:
- Via the CLI
iot device monitor
command. - By subscribing to the MQTT
simpleiot_v1/app/monitor/{project}/{model}/{serial}/#
topic.
The data itself is also saved to:
- The Data table in the Postgres database. Only the latest value is saved here.
- In the DynamoDB table for the installation. All values are kept and time-stamped here.
- Sent to the Amazonn Timestream serverless time-based database. The values can be further monitored and analyzed in a dashboard via Amazon Managed Grafana.
The examples provided are designed to work with the AWS IOT EduKit device. This is an inexpensive development device based on an Espressif ESP-32 processor. A complete SimpleIOT Starter Bundle with an EduKit device and several peripheral sensors can be purchased from the manufacturer M5Stack.
To use the library with the M5Kit, you can set up your Arduino environment as follows. More information on the M5Stack Arduino SDK, including device schematics, can be found here.
NOTE: M5Stack carries two types of ESP32 devices. The first Core device has physical buttons, but the Core2 device (including AWS IOTKit) has slightly different hardware, including a touch-screen. First-generation Core device libraries can be found here whereas Core2 libraries are here.
The two examples provided are:
-
HelloWorld: Basic Arduino sketch that sends the values of the built-in EduKit touch-screen buttons to the cloud. The color of the globe can be modified from the cloud using the SimpleIOT CLI.
-
SensorDemo: A more advanced sketch that reads data from an environmental sensor (pressure, humidity, temperature), a rotary knob, and a GPS receiver. The use of these sensors requires the installation of the following third-party libraries:
-
ArduinoJson
-
MQTT
-
FastLED
-
TinyGPSPlus-ESP32
-
M5Core2
-
UNIT_ENV
-
UNIT_ENCODER
-
A step-by-step workshop using this configuration is available at SimpleIOT.net. In addition, the arduino-cli toolchain can be installed via the SimpleIOT CLI using:
% iot toolchain install
This will automatically install arduino-cli
as well as all the above libraries.
See CONTRIBUTING for more information.
This project is licensed under the Apache-2.0 License.