![]() |
Morse Micro IoT SDK
2.9.7
|
AWS IoT example to demonstrate connecting to AWS Shadow service and demonstrate a simple light bulb example.
This example application demonstrates how to use AWS IoT Core services to connect to an AWS endpoint and use the shadow service to mirror the state of a light bulb shadow state maintained by AWS.
The following steps need to be done to run this application:
AllowAll AllowAll policy is selectedCongratulations! Your device should now be created.
Download the certificates and key files and proceed to the next step. Specifically you will need the Device Certificate, Device Private Key amd the Amazon RSA Root Certificate.
openssh to create the device certificate and keys and upload them using AWS CLI.https://docs.aws.amazon.com/iot/latest/developerguide/jit-provisioning.html This method loads all devices with a common provisioning certificate, which then gets replaced with a unique device certificate when the device first connects to the AWS endpoint.AmazonRootCA.pem, certificate.pem.crt, and private.pem.key with the files downloaded from AWS in the previous step. Rename the downloaded files to match the target file names. Note: Amazon provides you with 2 root CA files to download, please use the file named AmazonRootCA1.pem.config.hjson file.aws.thingname with the name of the thing you created in the previous section.aws.endpoint with the server name in the URL. Ensure you remove the https:// and everything after amazonaws.com config.hjson file to the device. powerOn variable."<your_thing_name>" with the name of the thing you created.powerOn parameter printed on the console output should change.AWS Shadow service allows us to cache the state of an IoT device on the cloud. This allows the IoT device to go to sleep and wake up once in a while to update its state on the cloud and act on pending state change requests on the cloud. For example a temperature sensor could periodically measure and update the temperature using the AWS Shadow service and go to sleep for minutes or even hours at a time while AWS Shadow caches this data and makes it available persistently to anyone who may be interested in the temperature even though the sensor is asleep and no longer reachable on the network.
Likewise, for a light bulb, AWS Shadow remembers the state of the light bulb even though the light bulb itself may have been unplugged and so not connected to the network. In fact the AWS Shadow can accept state change requests on behalf of the light bulb when it is unplugged and then convey the desired state to the light bulb when it connects again.
This is how it works:
"$aws/things/<your_thing_name>/shadow/update" "$aws/things/<your_thing_name>/shadow/update/delta" as "$aws/things/<your_thing_name>/shadow/update" "$aws/things/<your_thing_name>/shadow/update/accepted" "$aws/things/<your_thing_name>/shadow/update/rejected" For more information see: https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html
Now that we have seen AWS Shadow being used to connect to and control our IoT device, how can we put this to practice with a real world application?
Amazon shows us how we can use Alexa to post messages to AWS IoT devices with an example smart hotel application: https://aws.amazon.com/blogs/iot/implement-a-connected-building-with-alexa-and-aws-iot/
In this example they show us how to create an Alexa skill that can post JSON messages to our IoT device using AWS Shadow. You can use the tutorial above to customize this application for your specific smart device needs.
In the example above we used the AWS IoT console to create certificates and publish/subscribe to MQTT messages. While this may be convenient for development and testing, it is hardly a practical approach for real world applications. Luckily, we have options - Amazon provides us with the AWS CLI (Command Line Interface), which lets us do everything above using a command line interface such as creating certificates, registering devices, publishing and subscribing to MQTT messages. This allows us to automate and script production and registration of devices and even implement M2M communications using the MQTT publish/subscribe API. A full reference of the available commands is at: https://docs.aws.amazon.com/cli/latest/index.html
This application supports Over The Air updates. OTA updates can be used to update the existing application on the IoT device with newer versions of itself. For OTA updates to work, there must be a bootloader installed and an existing version of the application that is able to connect to the AWS IoT infrastructure.
ENABLE_OTA_APP to 1.To perform an OTA update, first ensure there is a version of this application running on the device with the right credentials and certificates to connect to the service. In addition to certificates and keys described in step 3 of the Getting Started section above, we will also need a code signing certificate to be installed on the device. This certificate can be generated using a tool like openssl as described below:
mm-ekh08-u575 and mm-mm6108-ekh05 platforms - you will get an error on all other platforms if you attempt an OTA update. To add OTA support to your platform, you will need to:openocd, then first load the application and then load the bootloader. Do this every time you load the application using openocd as the application contains a stub bootloader that will overwrite the real bootloader..filesystem section to your linker definition file that is big enough to accommodate the OTA download image plus any other data you may store in the file-system. Also ensure you have a valid implementation of mmhal_get_littlefs_config() that returns your file-system configuration.The steps below are from the following document: https://docs.aws.amazon.com/freertos/latest/userguide/ota-code-sign-cert-win.html
cert_config.txt with the following text: me@my.nosp@m.emai.nosp@m.l.com with your organization email and replace the my in my_dn and my_exts with your organization name as appropriate.ECDSA code-signing private key: ECDSA code-signing certificate: otasigning.pem.crt file to the credentials folder and follow the Programming the config store from a host PC instructions to load the config.hjson file to the device. Ensure you have generated the other certificates, keys and provisioning information as described in Getting Started section above.otasigning.pem.crt file to the credentials folder and follow the Programming the config store from a host PC instructions to load the config.hjson file to the device. Ensure you have generated the other certificates, keys and provisioning information as described in Getting Started section above.signature.txt file into the signature fieldhttps://docs.aws.amazon.com/freertos/latest/userguide/code-sign-policy.html MQTT for file transfer protocol.signature.txt file that you generated while signing into the signature box.aws.ota_cert as the path name of the code signing certificate on the device. (This incidentally is the name of the config store key that contains the certificate)IAM role with permissions to do OTA updates and click Next.otasigning.pem.crt as the certificate body.otasigning.key as the certificate private key.aws.ota_cert as the path name of the code signing certificate on the device.IAM role with permissions to do OTA updates and click Next.Congratulations! The update has been deployed. If the application is currently running on the device, it should immediately see the update and start downloading it. In a minute or two the device should reboot and the new update will be applied. AWS will indicate successful update on the console once the updated firmware boots and connects to AWS.
ota_config.h and modifying this configuration may decrease update time. See ota_config.h for more information on each option and what they are used for. DISABLE_OTA_LOGGING flag from the Makefile and platformio.ini files for this example. Also, ensure you increment the version numbers in version.h prior to every OTA update or you will get warnings that the new version is not higher than the old version, the update will still complete though.For more information, see: https://docs.aws.amazon.com/freertos/latest/userguide/ota-console-workflow.html
The steps above describe how to provision one device at a time for AWS IoT. This however is not practical when we have to provision thousands of devices in the field. Thankfully AWS provides a mechanism called Fleet Provisioning that allows us to automate this process.
For more information on Fleet Provisioning see: https://docs.aws.amazon.com/whitepapers/latest/device-manufacturing-provisioning/provisioning-identity-in-aws-iot-core-for-device-connections.html
There are multiple mechanisms of implementing Fleet Provisioning - we have implemented the Fleet Provisioning by claim mechanism. In this mechanism a batch of devices (say 1000) will be loaded with a shared claim certificate and keys. The device will make first contact with the AWS endpoint using this shared certificate and key just as it would with regular device certificates and keys. The device then generates a new set of keys and sends the certificate to AWS for signing. AWS signs the certificate and assigns the device a new thing name based on the provisioning template - the provisioning template may specify the thing name is an amalgam of the device serial number (in our case the MAC address) and some prefix. The device saves the signed certificate, generated keys and thing name and uses them for all connections henceforth.
Use the steps below to implement fleet provisioning. Alternatively, if you prefer to use the AWS command line, then all the steps below are described here for the command line: https://www.freertos.org/iot-fleet-provisioning/demo.html#setting-up
Ensure you have the required permissions and roles to implement fleet provisioning. Your AWS administrator can setup the roles using the following commands on the AWS command line:
FleetProvisioningRole role AWSIoTThingsRegistration policy to the role AllowAll policy as described in Create a Thing_fp_demo_things_ and click Create thing typetemplates/fleet_provisioning_policy.json): _FleetProvisioningTemplate_ with the name of the template you specified in Create provisioning template. Set the aws.provisioningtemplate key to the provisioning template name you specified here._FleetProvisioningTemplate_ IAM role_ is unchecked.templates/fleet_provisioning_template.json): _AllowAll_ matches the name of the AllowAll policy you created in the prerequisites. Ensure _fp_demo_things_ matches the thing type you created in Create a thing typeaws.provisioningtemplate key to the provisioning template name you set in Create provisioning template.Wi-Fi credentials and country code.aws.thingname and atomically replace the claim credentials with the newly generated credentials.aws.thingname key. However, be aware that claim certificates are intended to be used temporarily and may expire or be revoked. So this method of re-provisioning may fail if the claim certificate is no longer valid.create-from-csr and provisioning-templates resources. In our case the AllowAll policy allows everything including these claim permissions. To re-provision, the application simply deletes the aws.thingname key to trigger the provisioning process. This method has the advantage of requiring less resources by not needing to keep a copy of the claim certificate and key which saves around 3KB of storage in persistent store. Definition in file aws_iot.c.
#include <string.h>#include "mmhal.h"#include "mmosal.h"#include "mmconfig.h"#include "mm_app_loadconfig.h"#include "mmipal.h"#include "mqtt_agent_task.h"#include "sntp_client.h"#include "core_json.h"#include "mm_app_common.h"#include "aws_iot_config.h"
Go to the source code of this file.
Macros | |
| #define | NTP_MIN_TIMEOUT 3000 |
| Minimum NTP timeout per attempt. More... | |
| #define | NTP_MIN_BACKOFF 60000 |
| We need to back-off at least 60 seconds or most NTP Servers will tell us to go away. More... | |
| #define | NTP_MIN_BACKOFF_JITTER 3000 |
| Minimum back-off jitter per attempt. More... | |
| #define | NTP_MAX_BACKOFF_JITTER 60000 |
| Maximum back-off jitter per attempt. More... | |
| #define | SHADOW_PUBLISH_JSON |
| Format string representing a Shadow document with a "reported" state. More... | |
Functions | |
| void | app_init (void) |
| Main entry point to the application. More... | |
| #define NTP_MAX_BACKOFF_JITTER 60000 |
| #define NTP_MIN_BACKOFF 60000 |
| #define NTP_MIN_BACKOFF_JITTER 3000 |
| #define NTP_MIN_TIMEOUT 3000 |
| #define SHADOW_PUBLISH_JSON |
Format string representing a Shadow document with a "reported" state.
The real json document will look like this:
Note the client token, which is optional. The token is used to identify the response to an update. The client token must be unique at any given time, but may be reused once the update is completed. For this demo, a timestamp is used for a client token.