The Internet of Things on AWS – Official Blog

Manage IoT device state anywhere using AWS IoT Device Shadow service and AWS IoT Greengrass

Introduction

Internet of Things (IoT) developers often need to implement a robust mechanism for managing IoT device state either locally or remotely. A typical example is a smart home radiator, an IoT device where you can use the built-in control panel to adjust the temperature (device state), or trigger temperature adjustment messages remotely from a software application running in the cloud.

You can quickly build this mechanism by using the AWS IoT Device Shadow service. The AWS IoT Device Shadow service can make a device’s state available to your business logic, even in the case of intermittent network connection.

In addition, to efficiently manage your device’s software lifecycle and accelerate your development efforts, you can use AWS IoT Greengrass along with its pre-built components. AWS IoT Greengrass is an open-source edge runtime and cloud service for building, deploying, and managing device software. One of the components of AWS IoT Greengrass is the shadow manager, which enables the local shadow service on your core device. The local shadow service allows components to use interprocess communication (IPC) to interact with local shadows. The shadow manager component manages the storage of local shadow documents, and also handles synchronization of local shadow states with the AWS IoT Device Shadow service.

In this blog post, I am using AWS IoT Device Shadow service and AWS IoT Greengrass together with a Raspberry Pi and Sense HAT hardware to simulate a smart home radiator. This demonstration uses a single digit number (0 – 9) to simulate the output power. This number is the device state that we want to manage from anywhere, local and remote. The user can change this number through a local hardware switch (the built-in joystick on the Sense HAT) as well as remotely from a cloud-based application.

The Raspberry Pi shows the number on the Sense HAT LED display, indicating the radiator output power. The user can push up on the joystick on the Sense HAT to increase the number (or push down to decrease it).

Raspberry Pi simulating home radiator
Figure 1. Raspberry Pi – simulating home radiator

Architecture overview
Figure 2. Architecture overview

By following this blog post, you can quickly start building and testing your IoT solutions for managing your device’s state anywhere.

Prerequisites

To follow through this blog post, you will need:

Hardware:

Software:

Walkthrough

Step 1: Install and configure the AWS IoT Greengrass core software on the Raspberry Pi.

In order to make your Raspberry Pi as an AWS IoT Greengrass core device, follow step 1 to step 3 in the AWS IoT Greengrass Getting started document. I created the device with the following configuration:

  • Core device name: PiWithSenseHat
  • Thing group: RaspberryPiGroup

Now you should be able to see this device in your AWS console.

AWS IoT Greengrass core device in console
Figure 3. AWS IoT Greengrass core device in console

Step 2: Deploy prebuilt AWS IoT Greengrass components to the device

The next step is to deploy prebuilt AWS IoT Greengrass components to the device. AWS IoT Greengrass provides and maintains a set of prebuilt components that can accelerate our development. In this demonstration, I am deploying the following components:

  • greengrass.Cli:
    Provides a local command-line interface that you can use on core devices to develop and debug components locally
  • greengrass.ShadowManager
    Enables the local shadow service on your core device and handles synchronization of local shadow states with the AWS IoT Device Shadow service
  • greengrass.LocalDebugConsole (optional)
    Provides a local dashboard that displays information about your AWS IoT Greengrass core devices and its components

Steps:

  1. Go to AWS IoT Greengrass console
  2. Navigate to Deployment in Greengrass devices, create a new deployment
  3. Deployment target could be either Thing group RaspberryPiGroup, or Core device
  4. Select these 3 components from Public components

Select the prebuilt components
Figure 4. Select the prebuilt components

  1. Configure aws.greengrass.ShadowManager component

In Configure components step, select aws.greengrass.ShadowManager, then click Configure component

Configure aws.greengrass.ShadowManager
Figure 5. Configure aws.greengrass.ShadowManager

  1. Set up component version and configuration json of aws.greengrass.ShadowManager

Configure aws.greengrass.ShadowManager details
Figure 6. Configure aws.greengrass.ShadowManager – details

  • Version: 2.3.1
  • Configuration to merge:  
{
  "synchronize": {
    "coreThing": {
      "classic": true,
      "namedShadows": [
        "NumberLEDNamedShadow"
      ]
    },
    "shadowDocuments": [],
    "direction": "betweenDeviceAndCloud"
  },
  "rateLimits": {
    "maxOutboundSyncUpdatesPerSecond": 100,
    "maxTotalLocalRequestsRate": 200,
    "maxLocalRequestsPerSecondPerThing": 20
  },
  "shadowDocumentSizeLimitBytes": 8192
}

The json configuration synchronizes a named shadow, called NumberLEDNamedShadow in this example, in both directions, betweenDeviceAndCloud option. In your real-world application, you could use multiple named shadows, and with 1 way or bi-directional synchronization. Check the details of the aws.greengrass.ShadowManager in its document.

  1. Complete the Create Deployment wizard to finish the deployment.

At the end of the Step 2, the Raspberry Pi is ready to synchronize a named shadow NumberLEDNamedShadow between device and cloud, by using AWS IoT Greengrass core software and the prebuilt component.

Step 3: Create AWS IoT Greengrass components for simulating smart home radiator with local control

Now create two AWS IoT Greengrass components for simulating a smart home radiator with local control. We can leverage interprocess communication (IPC) for the internal communication between the components. If you are not familiar with how to build custom AWS IoT Greengrass components, please follow step 4 in the Getting started document. In this blog, we create and test them locally.

  1. Component example.sensehat.joystick: Capture the events from the joystick and publish the events to an IPC topic “ipc/joystick” (It was defined as a variable in the recipe).
  2. Component example.sensehat.led: Subscribe the IPC topic “ipc/joystick”, update the local shadow and the Sense HAT LED display.

3.1 Create component com.example.sensehat.joystick

This component is publishing events of the built-in joystick to AWS IoT Greengrass core IPC. The event is like:

{
   "timemillis":1669202845134,
   "direction":"down",
   "action":"released"
}

You can find the component recipe and artifact from blog source code repo. Instead of hard coding the IPC topic in the source code, it is defined in the recipe as a variable.

3.2 Create component com.example.sensehat.led

Now create the second component named com.example.sensehat.led. You can find the component recipe and artifact in the source code repo. In the recipe it defines the access permission to IPC and shadow documents.

This component:

  • Maintains a number as device state, and displays it on LED
  • Subscribes to joystick event topic via IPC
  • Based on the received joystick event, increase/decrease the number
  • Periodically checks the shadow. If there is a new number in the shadow document, update the device with that number.

Workflow of com.example.sensehat.led component
Figure 7. Workflow of com.example.sensehat.led component

Demo: Manage the device state in action

Now the Raspberry Pi as simulator is ready for use.

It responds to 2 types of events:

  • New joystick event: Control the device locally
  • New cloud shadow document: Control the device remotely

Logic to control the device either locally or remotely
Figure 8: Logic to control the device either locally or remotely

To see the device shadow in action:

  1. Go to AWS IoT Greengrass console
  2. Navigate to Things, select PiWithSenseHat
  3. In Device Shadows, you can find the NumberLEDNamedShadow. Note that you do not need to manually create this shadow. When device reports back the shadow for the first time, it will create it for you if it is missing.

locate the device shadow in AWS console
Figure 9. locate the device shadow in AWS console

Demo 1: Update the device locally by using joystick

  1. Use the joystick to increase/decrease the number locally (The initial number was 6. I firstly deceased it to 0, then increased it to 2).
  2. Observe the device shadow document is updated in real time in AWS console. The change is sync to the cloud shadow in the real time.
    • status is changed to “device updated by local”
    • number is changed to the new value from local

Using joystick to update the number
Figure 10: Using joystick to update the number, and report the new value to cloud in real time

Demo 2: Update the device remotely by updating device shadow document in cloud

  1. In the beginning of this demo, the device LED was displaying 0, and device shadow document was
    {
      "state": {
        "desired": {
          "number": 0
        },
        "reported": {
          "status": "device is updated by local",
          "number": 0
        }
      }
    }
    
  2. In AWS IoT Core console, Edit the shadow document with the following Json (you can skip the “reported” section), then click Update

    {
      "state": {
        "desired": {
          "number":9
        }
      }
    }
    
  1. Observe the Raspberry Pi LED updates the number. The change is pushed from cloud to local device. Now the device is displaying number 9:
    • status is changed to “device updated by shadow”
    • number is changed from 0 to 9.

Update the device remotely by updating device shadow document in cloud
Figure 11. Update the device remotely by updating device shadow document in cloud

As the display number can be updated either by local joystick or remotely from AWS console, the latest update takes precedence. Therefore when the update is done locally, it is important to set the “desired” value back to remote shadow in cloud, so the remote shadow knows the new “desired” value and will not update it in the next shadow sync cycle. See more at the document device-shadow-empty-fields.

Cleaning up

  • Delete/disable IAM user which you used for installing AWS IoT Greengrass core software in Raspberry Pi
  • Under AWS IoT console, navigate to Greengrass devices
    • In Core Device select the device PiWithSenseHat and Hit delete on top right.
    • In Thing groups delete RaspberryPiGroup
  • Remove these two custom components from Raspberry Pi
    • Run the following commands in the terminal on Raspberry Pi
      • sudo /greengrass/v2/bin/greengrass-cli --ggcRootPath /greengrass/v2 deployment create --remove "com.example.sensehat.led"
      • sudo /greengrass/v2/bin/greengrass-cli --ggcRootPath /greengrass/v2 deployment create --remove "com.example.sensehat.joystick"
    • Uninstall AWS IoT Greengrass core software from Raspberry Pi
      • Follow the steps in this document to uninstall the AWS IoT Greengrass core software from your Raspberry Pi.

Conclusion

In this post, you learned how to use AWS IoT Device Shadow service and AWS IoT Greengrass to build a robust solution for managing IoT device state, whether it’s done locally or remotely. You can now focus on your own business logic, and let these two AWS services to do the heavy lifting for managing device state anywhere. Currently these two custom components are created and deployed locally in the device. The next step could be making them available in AWS IoT Greengrass, so you can deploy them to more devices. In order to that, you can follow step 5 and step 6 in AWS IoT Greengrass document.

About the author

Feng Lu

Feng Lu is a Senior Solutions Architect in AWS with 18 years professional experience. He is passionate about helping organizations to craft scalable, flexible, and resilient architectures that address their business problems. Currently his focus is on connecting the physical world and cloud with IoT technologies, and uniting computing/AI capacity to make our physical environment smarter and better.