

# Building demos with the AWS IoT Device Client
<a name="iot-tutorials-dc-intro"></a>

The tutorials in this learning path walk you through the steps to develop demonstration software by using the AWS IoT Device Client. The AWS IoT Device Client provides software that runs on your IoT device to test and demonstrate aspects of an IoT solution that's built on AWS IoT.

The goal of these tutorials is to facilitate exploration and experimentation so you can feel confident that AWS IoT supports your solution before you develop your device software.

**What you'll learn in these tutorials:**
+ How to prepare a Raspberry Pi for use as an IoT device with AWS IoT
+ How to demonstrate AWS IoT features by using the AWS IoT Device Client on your device

In this learning path, you'll install the AWS IoT Device Client on your own Raspberry Pi and create the AWS IoT resources in the cloud to demonstrate IoT solution ideas. While the tutorials in this learning path demonstrate features by using a Raspberry Pi, they explain the goals and procedures to help you adapt them to other devices.

## Prerequisites to building demos with the AWS IoT Device Client
<a name="iot-dc-tutorial-overview"></a>

This section describes what you'll need to have before you start the tutorials in this learning path.

**To complete the tutorials in this learning path, you'll need:**
+ 

**An AWS account**  
You can use your existing AWS account, if you have one, but you might need to add additional roles or permissions to use the AWS IoT features these tutorials use.

  If you need to create a new AWS account, see [Set up AWS account](setting-up.md).
+ 

**A Raspberry Pi or compatible IoT device**  
The tutorials use a [Raspberry Pi](https://www.raspberrypi.org/) because it comes in different form factors, it's ubiquitous, and it's a relatively inexpensive demonstration device. The tutorials have been tested on the [Raspberry Pi 3 Model B\$1](https://www.raspberrypi.com/products/raspberry-pi-3-model-b-plus/), the [Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/), and on an Amazon EC2 instance running Ubuntu Server 20.04 LTS (HVM). To use the AWS CLI and run the commands, We recommend that you use the latest version of the Raspberry Pi OS ([Raspberry Pi OS (64-bit)](https://www.raspberrypi.com/software/operating-systems/) or the OS Lite). Earlier versions of the OS might work, but we haven't tested it.
**Note**  
The tutorials explain the goals of each step to help you adapt them to IoT hardware that we haven't tried them on; however, they do not specifically describe how to adapt them to other devices.
+ 

**Familiarity with the IoT device's operating system**  
The steps in these tutorials assume that you are familiar with using basic Linux commands and operations from the command line interface supported by a Raspberry Pi. If you're not familiar with these operations, you might want to give yourself more time to complete the tutorials.

  To complete these tutorials, you should already understand how to:
  + Safely perform basic device operations such as assembling and connecting components, connecting the device to required power sources, and installing and removing memory cards.
  + Upload and download system software and files to the device. If your device doesn't use a removable storage device, such as a microSD card, you'll need to know how to connect to your device and upload and download system software and files to the device.
  + Connect your device to the networks that you plan to use it on.
  + Connect to your device from another computer using an SSH terminal or similar program.
  + Use a command line interface to create, copy, move, rename, and set the permissions of files and directories on the device.
  + Install new programs on the device.
  + Transfer files to and from your device using tools such as FTP or SCP.
+ 

**A development and testing environment for your IoT solution**  
The tutorials describe the software and hardware required; however, the tutorials assume that you'll be able to perform operations that might not be described explicitly. Examples of such hardware and operations include:
  + 

**A local host computer to download and store files on**  
For the Raspberry Pi, this is usually a personal computer or laptop that can read and write to microSD memory cards. The local host computer must:
    + Be connected to the Internet.
    + Have the [AWS CLI](https://aws.amazon.com//cli/) installed and configured.
    + Have a web browser that supports the AWS console.
  + 

**A way to connect your local host computer to your device to communicate with it, to enter commands, and to transfer files**  
On the Raspberry Pi, this is often done using SSH and SCP from the local host computer.
  + 

**A monitor and keyboard to connect to your IoT device**  
These can be helpful, but are not required to complete the tutorials.
  + 

**A way for your local host computer and your IoT devices to connect to the internet**  
This could be a cabled or a wireless network connection to a router or gateway that's connected to the internet. The local host must also be able to connect to the Raspberry Pi. This might require them to be on the same local area network. The tutorials can't show you how to set this up for your particular device or device configuration, but they show how you can test this connectivity.
  + 

**Access to your local area network's router to view the connected devices**  
To complete the tutorials in this learning path, you'll need to be able to find the IP address of your IoT device.

    On a local area network, this can be done by accessing the admin interface of the network router your devices connect to. If you can assign a fixed IP address for your device in the router, you can simplify reconnection after each time the device restarts.

    If you have a keyboard and a monitor attached to the device, **ifconfig** can display the device's IP address.

    If none of these are an option, you'll need to find a way to identify the device's IP address after each time it restarts. 

After you have all your materials, continue to [Tutorial: Preparing your devices for the AWS IoT Device Client](iot-dc-prepare-device.md). 

**Topics**
+ [

## Prerequisites to building demos with the AWS IoT Device Client
](#iot-dc-tutorial-overview)
+ [

# Tutorial: Preparing your devices for the AWS IoT Device Client
](iot-dc-prepare-device.md)
+ [

# Tutorial: Installing and configuring the AWS IoT Device Client
](iot-dc-install-dc.md)
+ [

# Tutorial: Demonstrate MQTT message communication with the AWS IoT Device Client
](iot-dc-testconn.md)
+ [

# Tutorial: Demonstrate remote actions (jobs) with the AWS IoT Device Client
](iot-dc-runjobs.md)
+ [

# Tutorial: Cleaning up after running the AWS IoT Device Client tutorials
](iot-dc-cleanup.md)

# Tutorial: Preparing your devices for the AWS IoT Device Client
<a name="iot-dc-prepare-device"></a>

This tutorial walks you through the initialization of your Raspberry Pi to prepare it for the subsequent tutorials in this learning path.

The goal of this tutorial is to install the current version of the device’s operating system and make sure that you can communicate with your device in the context of your development environment.

**Prerequisites**  
Before you start this tutorial, make sure that you have the items listed in [Prerequisites to building demos with the AWS IoT Device Client](iot-tutorials-dc-intro.md#iot-dc-tutorial-overview) available and ready to use.

This tutorial takes about 90 minutes to complete.

**In this tutorial, you'll:**
+ Install and update the operating system of your device.
+ Install and verify any additional software needed to run the tutorials.
+ Test your device's connectivity and install the required certificates.

After you complete this tutorial, the next tutorial prepares your device for the demos that use the AWS IoT Device Client.

**Topics**
+ [

# Install and update the operating system of the device
](iot-dc-prepare-device-sys.md)
+ [

# Install and verify required software on your device
](iot-dc-prepare-device-sw.md)
+ [

# Test your device and save the Amazon CA cert
](iot-dc-prepare-device-test.md)

# Install and update the operating system of the device
<a name="iot-dc-prepare-device-sys"></a>

The procedures in this section describe how to initialize the microSD card that the Raspberry Pi uses for its system drive. The Raspberry Pi's microSD card contains its operating system (OS) software as well as space for its application file storage. If you're not using a Raspberry Pi, follow the device's instructions to install and update the device's operating system software.

After you complete this section, you should be able to start your IoT device and connect to it from the terminal program on your local host computer.

**Required equipment:**
+ Your local development and testing environment
+ A Raspberry Pi that or your IoT device, that can connect to the internet
+ A microSD memory card with at least 8 GB capacity or sufficient storage for the OS and required software.
**Note**  
When selecting a microSD card for these exercises, choose one that is as large as necessary but, as small as possible.  
A small SD card will be faster to back up and update. On the Raspberry Pi, you won't need more than an 8-GB microSD card for these tutorials. If you need more space for your specific application, the smaller image files you save in these tutorials can resize the file system on a larger card to use all the supported space of the card you choose.

**Optional equipment:**
+ A USB keyboard connected to the Raspberry Pi
+ An HDMI monitor and cable to connect the monitor to the Raspberry Pi

**Topics**
+ [

## Load the device's operating system onto microSD card
](#iot-dc-prepare-device-sys-step1)
+ [

## Start your IoT device with the new operating system
](#iot-dc-prepare-device-sys-step2)
+ [

## Connect your local host computer to your device
](#iot-dc-prepare-device-sys-step3)

## Load the device's operating system onto microSD card
<a name="iot-dc-prepare-device-sys-step1"></a>

This procedure uses the local host computer to load the device's operating system onto a microSD card.

**Note**  
If your device doesn't use a removable storage medium for its operating system, install the operating system using the procedure for that device and continue to [Start your IoT device with the new operating system](#iot-dc-prepare-device-sys-step2).

**To install the operating system on your Raspberry Pi**

1. On your local host computer, download and unzip the Raspberry Pi operating system image that you want to use. The latest versions are available from [ https://www.raspberrypi.com/software/operating-systems/](https://www.raspberrypi.com/software/operating-systems/) 

**Choosing a version of Raspberry Pi OS**  
This tutorial uses the **Raspberry Pi OS Lite** version because it’s the smallest version that supports these the tutorials in this learning path. This version of the Raspberry Pi OS has only a command line interface and doesn't have a graphical user interface. A version of the latest Raspberry Pi OS with a graphical user interface will also work with these tutorials; however, the procedures described in this learning path use only the command line interface to perform operations on the Raspberry Pi.

1. Insert your microSD card into the local host computer.

1. Using an SD card imaging tool, write the unzipped OS image file to the microSD card.

1. After writing the Raspberry Pi OS image to the microSD card:

   1. Open the BOOT partition on the microSD card in a command line window or file explorer window. 

   1. In the BOOT partition of the microSD card, in the root directory, create an empty file named `ssh` with no file extension and no content. This tells the Raspberry Pi to enable SSH communications the first time it starts.

1. Eject the microSD card and safely remove it from the local host computer.

Your microSD card is ready to [Start your IoT device with the new operating system](#iot-dc-prepare-device-sys-step2).

## Start your IoT device with the new operating system
<a name="iot-dc-prepare-device-sys-step2"></a>

This procedure installs the microSD card and starts your Raspberry Pi for the first time using the downloaded operating system.

**To start your IoT device with the new operation system**

1. With the power disconnected from the device, insert the microSD card from the previous step, [Load the device's operating system onto microSD card](#iot-dc-prepare-device-sys-step1), into the Raspberry Pi.

1. Connect the device to a wired network.

1. These tutorials will interact with your Raspberry Pi from your local host computer using an SSH terminal.

   If you also want to interact with the device directly, you can:

   1. Connect an HDMI monitor to it to watch the Raspberry Pi’s console messages before you can connect the terminal window on your local host computer to your Raspberry Pi.

   1. Connect a USB keyboard to it if you want to interact directly with the Raspberry Pi.

1. Connect the power to the Raspberry Pi and wait about a minute for it to initialize.

   If you have a monitor connected to your Raspberry Pi, you can watch the start-up process on it.

1. 

   Find out your device’s IP address:
   + If you connected an HDMI monitor to the Raspberry Pi, the IP address appears in the messages displayed on the monitor 
   + If you have access to the router your Raspberry Pi is connects to, you can see its address in the router’s admin interface.

After you have your Raspberry Pi's IP address, you're ready to [Connect your local host computer to your device](#iot-dc-prepare-device-sys-step3).

## Connect your local host computer to your device
<a name="iot-dc-prepare-device-sys-step3"></a>

This procedure uses the terminal program on your local host computer to connect to your Raspberry Pi and change its default password.

**To connect your local host computer to your device**

1. 

   On your local host computer, open the SSH terminal program:
   + Windows: `PuTTY`
   + Linux/macOS: `Terminal`
**Note**  
PuTTY isn't installed automatically on Windows. If it's not on your computer, you might need to download and install it.

1. Connect the terminal program to your Raspberry Pi’s IP address and log in using its default credentials.

   ```
   username: pi
   password: raspberry
   ```

1. After you log in to your Raspberry Pi, change the password for the `pi` user.

   ```
   passwd
   ```

   Follow the prompts to change the password.

   ```
   Changing password for pi.
   Current password: raspberry
   New password: YourNewPassword
   Retype new password: YourNewPassword
   passwd: password updated successfully
   ```

After you have the Raspberry Pi's command line prompt in the terminal window and changed the password, you're ready to continue to [Install and verify required software on your device](iot-dc-prepare-device-sw.md).

# Install and verify required software on your device
<a name="iot-dc-prepare-device-sw"></a>

The procedures in this section continue from [the previous section](iot-dc-prepare-device-sys.md) to bring your Raspberry Pi's operating system up to date and install the software on the Raspberry Pi that will be used in the next section to build and install the AWS IoT Device Client.

After you complete this section, your Raspberry Pi will have an up-to-date operating system, the software required by the tutorials in this learning path, and it will be configured for your location.

**Required equipment:**
+ Your local development and testing environment from [the previous section](iot-dc-prepare-device-sys.md)
+ The Raspberry Pi that you used in [the previous section](iot-dc-prepare-device-sys.md)
+ The microSD memory card from [the previous section](iot-dc-prepare-device-sys.md)

**Note**  
The Raspberry Pi Model 3\$1 and Raspberry Pi Model 4 can perform all the commands described in this learning path. If your IoT device can't compile software or run the AWS Command Line Interface, you might need to install the required compilers on your local host computer to build the software and then transfer it to your IoT device. For more information about how to install and build software for your device, see the documentation for your device's software.

**Topics**
+ [

## Update operating system software
](#iot-dc-prepare-device-sw-step1)
+ [

## Install the required applications and libraries
](#iot-dc-prepare-device-sw-step2)
+ [

## (Optional) Save the microSD card image
](#iot-dc-prepare-device-sw-step3)

## Update operating system software
<a name="iot-dc-prepare-device-sw-step1"></a>

This procedure updates the operating system software.

**To update the operating system software on the Raspberry Pi**

Perform these steps in the terminal window of your local host computer.

1. Enter these commands to update the system software on your Raspberry Pi.

   ```
   sudo apt-get -y update
   sudo apt-get -y upgrade
   sudo apt-get -y autoremove
   ```

1. Update the Raspberry Pi's locale and time zone settings (optional).

   Enter this command to update the device's locale and time zone settings.

   ```
   sudo raspi-config
   ```

   1. To set the device's locale:

      1. In the **Raspberry Pi Software Configuration Tool (raspi-config)** screen, choose option **5**.

         **`5 Localisation Options Configure language and regional settings`**

         Use the Tab key to move to **<Select>,** and then press the space bar.

      1. In the localization options menu, choose option **L1**.

         **`L1 Locale Configure language and regional settings`**

         Use the Tab key to move to **<Select>,** and then press the space bar.

      1. In the list of locale options, choose the locales that you want to install on your Raspberry Pi by using the arrow keys to scroll and the space bar to mark those that you want. 

         In the United States, **`en_US.UTF-8`** is a good one to choose.

      1. After selecting the locales for your device, use the Tab key to choose **<OK>**, and then press the space bar to display the **Configuring locales** confirmation page.

   1. To set the device’s time zone:

      1. In the **raspi-config** screen, choose option **5**.

         **`5 Localisation Options Configure language and regional settings`**

         Use the Tab key to move to **<Select>,** and then press the space bar.

      1. In the localization options menu, use the arrow key to choose option **L2**:

         **`L2 time zone Configure time zone`**

         Use the Tab key to move to **<Select>,** and then press the space bar.

      1. In the **Configuring tzdata** menu, choose your geographical area from the list. 

         Use the Tab key to move to **<OK>**, and then press the space bar.

      1. In the list of cities, use the arrow keys to choose a city in your time zone.

         To set the time zone, use the Tab key to move to **<OK>**, and then press the space bar.

   1. When you’ve finished updating the settings, use the Tab key to move to **<Finish>**, and then press the space bar to close the **raspi-config** app.

1. Enter this command to restart your Raspberry Pi.

   ```
   sudo shutdown -r 0
   ```

1. Wait for your Raspberry Pi to restart.

1. After your Raspberry Pi has restarted, reconnect the terminal window on your local host computer to your Raspberry Pi.

Your Raspberry Pi system software is now configured and you're ready to continue to [Install the required applications and libraries](#iot-dc-prepare-device-sw-step2).

## Install the required applications and libraries
<a name="iot-dc-prepare-device-sw-step2"></a>

This procedure installs the application software and libraries that the subsequent tutorials use.

If you are using a Raspberry Pi, or if you can compile the required software on your IoT device, perform these steps in the terminal window on your local host computer. If you must compile software for your IoT device on your local host computer, review the software documentation for your IoT device for information about how to do these steps on your device.

**To install the application software and libraries on your Raspberry Pi**

1. Enter this command to install the application software and libraries.

   ```
   sudo apt-get -y install build-essential libssl-dev cmake unzip git python3-pip
   ```

1. Enter these commands to confirm that the correct version of the software was installed.

   ```
   gcc --version
   cmake --version
   openssl version
   git --version
   ```

1. 

   Confirm that these versions of the application software are installed:
   + `gcc`: 9.3.0 or later
   + `cmake`: 3.10.x or later
   + `OpenSSL`: 1.1.1 or later
   + `git`: 2.20.1 or later

If your Raspberry Pi has acceptable versions of the required application software, you're ready to continue to [(Optional) Save the microSD card image](#iot-dc-prepare-device-sw-step3).

## (Optional) Save the microSD card image
<a name="iot-dc-prepare-device-sw-step3"></a>

Throughout the tutorials in this learning path, you'll encounter these procedures to save a copy of the Raspberry Pi's microSD card image to a file on your local host computer. While encouraged, they are not required tasks. By saving the microSD card image where suggested, you can skip the procedures that precede the save point in this learning path, which can save time if you find the need to retry something. The consequence of not saving the microSD card image periodically is that you might have to restart the tutorials in the learning path from the beginning if your microSD card is damaged or if you accidentally configure an app or its settings incorrectly.

At this point, your Raspberry Pi's microSD card has an updated OS and the basic application software loaded. You can save the time it took you to complete the preceding steps by saving the contents of the microSD card to a file now. Having the current image of your device's microSD card image lets you start from this point to continue or retry a tutorial or procedure without the need to install and update the software from scratch.

**To save the microSD card image to a file**

1. Enter this command to shut down the Raspberry Pi.

   ```
   sudo shutdown -h 0
   ```

1. After the Raspberry Pi shuts down completely, remove its power.

1. Remove the microSD card from the Raspberry Pi.

1. On your local host computer: 

   1. Insert the microSD card.

   1. Using your SD card imaging tool, save the microSD card’s image to a file.

   1. After the microSD card’s image has been saved, eject the card from the local host computer.

1. With the power disconnected from the Raspberry Pi, insert the microSD card into the Raspberry Pi.

1. Apply power to the Raspberry Pi.

1. After waiting about a minute, on the local host computer, reconnect the terminal window on your local host computer that was connected to your Raspberry Pi., and then log in to the Raspberry Pi.

# Test your device and save the Amazon CA cert
<a name="iot-dc-prepare-device-test"></a>

The procedures in this section continue from [the previous section](iot-dc-prepare-device-sw.md) to install the AWS Command Line Interface and the Certificate Authority certificate used to authenticate your connections with AWS IoT Core.

After you complete this section, you'll know that your Raspberry Pi has the necessary system software to install the AWS IoT Device Client and that it has a working connection to the internet.

**Required equipment:**
+ Your local development and testing environment from [the previous section](iot-dc-prepare-device-sw.md)
+ The Raspberry Pi that you used in [the previous section](iot-dc-prepare-device-sw.md)
+ The microSD memory card from [the previous section](iot-dc-prepare-device-sw.md)

**Topics**
+ [

## Install the AWS Command Line Interface
](#iot-dc-prepare-device-test-step1)
+ [

## Configure your AWS account credentials
](#iot-dc-prepare-device-test-step2)
+ [

## Download the Amazon Root CA certificate
](#iot-dc-prepare-device-test-step3)
+ [

## (Optional) Save the microSD card image
](#iot-dc-prepare-device-test-step4)

## Install the AWS Command Line Interface
<a name="iot-dc-prepare-device-test-step1"></a>

This procedure installs the AWS CLI onto your Raspberry Pi.

If you are using a Raspberry Pi or if you can compile software on your IoT device, perform these steps in the terminal window on your local host computer. If you must compile software for your IoT device on your local host computer, review the software documentation for your IoT device for information about the libraries it requires.

**To install the AWS CLI on your Raspberry Pi**

1. Run these commands to download and install the AWS CLI.

   ```
   export PATH=$PATH:~/.local/bin # configures the path to include the directory with the AWS CLI
   git clone https://github.com/aws/aws-cli.git # download the AWS CLI code from GitHub
   cd aws-cli && git checkout v2 # go to the directory with the repo and checkout version 2
   pip3 install -r requirements.txt # install the prerequisite software
   ```

1. Run this command to install the AWS CLI. This command can take up to 15 minutes to complete.

   ```
   pip3 install . # install the AWS CLI 
   ```

1. Run this command to confirm that the correct version of the AWS CLI was installed.

   ```
   aws --version
   ```

   The version of the AWS CLI should be 2.2 or later.

If the AWS CLI displayed its current version, you're ready to continue to [Configure your AWS account credentials](#iot-dc-prepare-device-test-step2).

## Configure your AWS account credentials
<a name="iot-dc-prepare-device-test-step2"></a>

In this procedure, you'll obtain AWS account credentials and add them for use on your Raspberry Pi.

**To add your AWS account credentials to your device**

1. Obtain an **Access Key ID** and **Secret Access Key** from your AWS account to authenticate the AWS CLI on your device. 

   If you’re new to AWS IAM, [ https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/ ](https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/) describes the process to run in the AWS console to create AWS IAM credentials to use on your device. 

1. In the terminal window on your local host computer that's connected to your Raspberry Pi. and with the **Access Key ID** and **Secret Access Key** credentials for your device:

   1. Run the AWS configure app with this command:

      ```
      aws configure
      ```

   1. Enter your credentials and configuration information when prompted:

      ```
      AWS Access Key ID: your Access Key ID
      AWS Secret Access Key: your Secret Access Key
      Default region name: your AWS Region code
      Default output format: json
      ```

1. Run this command to test your device's access to your AWS account and AWS IoT Core endpoint.

   ```
   aws iot describe-endpoint --endpoint-type iot:Data-ATS
   ```

   It should return your AWS account-specific AWS IoT data endpoint, such as this example:

   ```
   {
       "endpointAddress": "a3EXAMPLEffp-ats.iot.us-west-2.amazonaws.com"
   }
   ```

If you see your AWS account-specific AWS IoT data endpoint, your Raspberry Pi has the connectivity and permissions to continue to [Download the Amazon Root CA certificate](#iot-dc-prepare-device-test-step3). 

**Important**  
Your AWS account credentials are now stored on the microSD card in your Raspberry Pi. While this makes future interactions with AWS easy for you and the software you’ll create in these tutorials, they will also be saved and duplicated in any microSD card images you make after this step by default.  
To protect the security of your AWS account credentials, before you save any more microSD card images, consider erasing the credentials by running `aws configure` again and entering random characters for the **Access Key ID** and **Secret Access Key** to prevent your AWS account credentials from compromised.  
If you find that you have saved your AWS account credentials inadvertently, you can deactivate them in the AWS IAM console. 

## Download the Amazon Root CA certificate
<a name="iot-dc-prepare-device-test-step3"></a>

This procedure downloads and saves a copy of a certificate of the Amazon Root Certificate Authority (CA). Downloading this certificate saves it for use in the subsequent tutorials and it also tests your device's connectivity with AWS services.

**To download and save the Amazon Root CA certificate**

1. Run this command to create a directory for the certificate.

   ```
   mkdir ~/certs
   ```

1. Run this command to download the Amazon Root CA certificate.

   ```
   curl -o ~/certs/AmazonRootCA1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem
   ```

1. Run these commands to set the access to the certificate directory and its file.

   ```
   chmod 745 ~
   chmod 700 ~/certs
   chmod 644 ~/certs/AmazonRootCA1.pem
   ```

1. Run this command to see the CA certificate file in the new directory.

   ```
   ls -l ~/certs
   ```

   You should see an entry like this. The date and time will be different; however, the file size and all other info should be the same as shown here.

   ```
   -rw-r--r-- 1 pi pi 1188 Oct 28 13:02 AmazonRootCA1.pem
   ```

   If the file size is not `1188`, check the **curl** command parameters. You might have downloaded an incorrect file.

## (Optional) Save the microSD card image
<a name="iot-dc-prepare-device-test-step4"></a>

At this point, your Raspberry Pi's microSD card has an updated OS and the basic application software loaded. 

**To save the microSD card image to a file**

1. In the terminal window on your local host computer, clear your AWS credentials.

   1. Run the AWS configure app with this command:

      ```
      aws configure
      ```

   1. Replace your credentials when prompted. You can leave **Default region name** and **Default output format** as they are by pressing **Enter**.

      ```
      AWS Access Key ID [****************YT2H]: XYXYXYXYX
      AWS Secret Access Key [****************9plH]: XYXYXYXYX
      Default region name [us-west-2]: 
      Default output format [json]:
      ```

1. Enter this command to shut down the Raspberry Pi.

   ```
   sudo shutdown -h 0
   ```

1. After the Raspberry Pi shuts down completely, remove its power connector.

1. Remove the microSD card from your device.

1. On your local host computer: 

   1. Insert the microSD card.

   1. Using your SD card imaging tool, save the microSD card’s image to a file.

   1. After the microSD card’s image has been saved, eject the card from the local host computer.

1. With the power disconnected from the Raspberry Pi, insert the microSD card into the Raspberry Pi.

1. Apply power to the device.

1. After about a minute, on the local host computer, restart the terminal window session and log in to the device.

   **Don't reenter your AWS account credentials yet.**

After you have restarted and logged in to your Raspberry Pi, you're ready to continue to [Tutorial: Installing and configuring the AWS IoT Device Client](iot-dc-install-dc.md).

# Tutorial: Installing and configuring the AWS IoT Device Client
<a name="iot-dc-install-dc"></a>

This tutorial walks you through the installation and configuration of the AWS IoT Device Client and the creation of AWS IoT resources that you'll use in this and other demos.

**To start this tutorial:**
+ Have your local host computer and Raspberry Pi from [the previous tutorial](iot-dc-prepare-device.md) ready.

This tutorial can take up to 90 minutes to complete.

**When you're finished with this topic:**
+ Your IoT device will be ready to use in other AWS IoT Device Client demos.
+ You'll have provisioned your IoT device in AWS IoT Core.
+ You'll have downloaded and installed the AWS IoT Device Client on your device.
+ You'll have saved an image of your device's microSD card that can be used in subsequent tutorials.

**Required equipment:**
+ Your local development and testing environment from [the previous section](iot-dc-prepare-device-test.md)
+ The Raspberry Pi that you used in [the previous section](iot-dc-prepare-device-test.md)
+ The microSD memory card from the Raspberry Pi that you used in [the previous section](iot-dc-prepare-device-test.md)

**Topics**
+ [

# Download and save the AWS IoT Device Client
](iot-dc-install-download.md)
+ [

# Provision your Raspberry Pi in AWS IoT
](iot-dc-install-provision.md)
+ [

# Configure the AWS IoT Device Client to test connectivity
](iot-dc-install-configure.md)

# Download and save the AWS IoT Device Client
<a name="iot-dc-install-download"></a>

The procedures in this section download the AWS IoT Device Client, compile it, and install it on your Raspberry Pi. After you test the installation, you can save the image of the Raspberry Pi's microSD card to use later when you want to try the tutorials again.

**Topics**
+ [

## Download and build the AWS IoT Device Client
](#iot-dc-install-dc-download)
+ [

## Create the directories used by the tutorials
](#iot-dc-install-dc-files)
+ [

## (Optional) Save the microSD card image
](#iot-dc-install-dc-save)

## Download and build the AWS IoT Device Client
<a name="iot-dc-install-dc-download"></a>

This procedure installs the AWS IoT Device Client on your Raspberry Pi.

Perform these commands in the terminal window on your local host computer that is connected to your Raspberry Pi.

**To install the AWS IoT Device Client on your Raspberry Pi**

1. Enter these commands to download and build the AWS IoT Device Client on your Raspberry Pi.

   ```
   cd ~
   git clone https://github.com/awslabs/aws-iot-device-client aws-iot-device-client
   mkdir ~/aws-iot-device-client/build && cd ~/aws-iot-device-client/build
   cmake ../
   ```

1. Run this command to build the AWS IoT Device Client. This command can take up to 15 minutes to complete.

   ```
   cmake --build . --target aws-iot-device-client
   ```

   The warning messages displayed as the AWS IoT Device Client compiles can be ignored.

   These tutorials have been tested with the AWS IoT Device Client built on **gcc**, version (Raspbian 10.2.1-6\$1rpi1) 10.2.1 20210110 on the Oct 30th 2021 version of Raspberry Pi OS (bullseye) on **gcc**, version (Raspbian 8.3.0-6\$1rpi1) 8.3.0 on the May 7th 2021 version of the Raspberry Pi OS (buster).

1. After the AWS IoT Device Client finishes building, test it by running this command.

   ```
   ./aws-iot-device-client --help
   ```

If you see the command line help for the AWS IoT Device Client, the AWS IoT Device Client has been built successfully and is ready for you to use.

## Create the directories used by the tutorials
<a name="iot-dc-install-dc-files"></a>

This procedure creates the directories on the Raspberry Pi that will be used to store the files used by the tutorials in this learning path.

**To create the directories used by the tutorials in this learning path:**

1. Run these commands to create the required directories.

   ```
   mkdir ~/dc-configs
   mkdir ~/policies
   mkdir ~/messages
   mkdir ~/certs/testconn
   mkdir ~/certs/pubsub
   mkdir ~/certs/jobs
   ```

1. Run these commands to set the permissions on the new directories.

   ```
   chmod 745 ~
   chmod 700 ~/certs/testconn
   chmod 700 ~/certs/pubsub
   chmod 700 ~/certs/jobs
   ```

After you create these directories and set their permission, continue to [(Optional) Save the microSD card image](#iot-dc-install-dc-save).

## (Optional) Save the microSD card image
<a name="iot-dc-install-dc-save"></a>

At this point, your Raspberry Pi's microSD card has an updated OS, the basic application software, and the AWS IoT Device Client. 

If you want to come back to try these exercises and tutorials again, you can skip the preceding procedures by writing the microSD card image that you save with this procedure to a new microSD card and continue the tutorials from [Provision your Raspberry Pi in AWS IoT](iot-dc-install-provision.md).

**To save the microSD card image to a file:**

In the terminal window on your local host computer that's connected to your Raspberry Pi:

1. Confirm that your AWS account credentials have not been stored.

   1. Run the AWS configure app with this command:

      ```
      aws configure
      ```

   1. If your credentials have been stored (if they are displayed in the prompt), then enter the **XYXYXYXYX** string when prompted as shown here. Leave **Default region name** and **Default output format** blank.

      ```
      AWS Access Key ID [****************YXYX]: XYXYXYXYX
      AWS Secret Access Key [****************YXYX]: XYXYXYXYX
      Default region name: 
      Default output format:
      ```

1. Enter this command to shutdown the Raspberry Pi.

   ```
   sudo shutdown -h 0
   ```

1. After the Raspberry Pi shuts down completely, remove its power connector.

1. Remove the microSD card from your device.

1. On your local host computer: 

   1. Insert the microSD card.

   1. Using your SD card imaging tool, save the microSD card’s image to a file.

   1. After the microSD card’s image has been saved, eject the card from the local host computer.

You can continue with this microSD card in [Provision your Raspberry Pi in AWS IoT](iot-dc-install-provision.md).

# Provision your Raspberry Pi in AWS IoT
<a name="iot-dc-install-provision"></a>

The procedures in this section start with the saved microSD image that has the AWS CLI and AWS IoT Device Client installed and create the AWS IoT resources and device certificates that provision your Raspberry Pi in AWS IoT.

## Install the microSD card in your Raspberry Pi
<a name="iot-dc-install-dc-restore"></a>

This procedure installs the microSD card with the necessary software loaded and configured into the Raspberry Pi and configures your AWS account so that you can continue with the tutorials in this learning path.

Use a microSD card from [(Optional) Save the microSD card image](iot-dc-install-download.md#iot-dc-install-dc-save) that has the necessary software for the exercises and tutorials in this learning path.

**To install the microSD card in your Raspberry Pi**

1. With the power disconnected from the Raspberry Pi, insert the microSD card into the Raspberry Pi.

1. Apply power to the Raspberry Pi.

1. After about a minute, on the local host computer, restart the terminal window session and log in to the Raspberry Pi.

1. On your local host computer, in the terminal window, and with the **Access Key ID** and **Secret Access Key** credentials for your Raspberry Pi:

   1. Run the AWS configure app with this command:

      ```
      aws configure
      ```

   1. Enter your AWS account credentials and configuration information when prompted:

      ```
      AWS Access Key ID [****************YXYX]: your Access Key ID
      AWS Secret Access Key [****************YXYX]: your Secret Access Key
      Default region name [us-west-2]: your AWS Region code
      Default output format [json]: json
      ```

After you have restored your AWS account credentials, you're ready to continue to [Provision your device in AWS IoT Core](#iot-dc-install-dc-provision).

## Provision your device in AWS IoT Core
<a name="iot-dc-install-dc-provision"></a>

The procedures in this section create the AWS IoT resources that provision your Raspberry Pi in AWS IoT. As you create these resources, you'll be asked to record various pieces of information. This information is used by the AWS IoT Device Client configuration in the next procedure.

For your Raspberry Pi to work with AWS IoT, it must be provisioned. Provisioning is the process of creating and configuring the AWS IoT resources that are necessary to support your Raspberry Pi as an IoT device.

With your Raspberry Pi powered up and restarted, connect the terminal window on your local host computer to the Raspberry Pi and complete these procedures.

**Topics**
+ [

### Create and download device certificate files
](#iot-dc-install-dc-provision-certs)
+ [

### Create AWS IoT resources
](#iot-dc-install-dc-provision-resources)

### Create and download device certificate files
<a name="iot-dc-install-dc-provision-certs"></a>

This procedure creates the device certificate files for this demo.

**To create and download the device certificate files for your Raspberry Pi**

1. In the terminal window on your local host computer, enter these commands to create the device certificate files for your device.

   ```
   mkdir ~/certs/testconn
   aws iot create-keys-and-certificate \
   --set-as-active \
   --certificate-pem-outfile "~/certs/testconn/device.pem.crt" \
   --public-key-outfile "~/certs/testconn/public.pem.key" \
   --private-key-outfile "~/certs/testconn/private.pem.key"
   ```

   The command returns a response like the following. Record the `certificateArn` value for later use.

   ```
   {
       "certificateArn": "arn:aws:iot:us-west-2:57EXAMPLE833:cert/76e7e4edb3e52f52334be2f387a06145b2aa4c7fcd810f3aea2d92abc227d269",
       "certificateId": "76e7e4edb3e52f5233EXAMPLE7a06145b2aa4c7fcd810f3aea2d92abc227d269",
       "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIDWTCCAkGgAwIBAgI_SHORTENED_FOR_EXAMPLE_Lgn4jfgtS\n-----END CERTIFICATE-----\n",
       "keyPair": {
           "PublicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BA_SHORTENED_FOR_EXAMPLE_ImwIDAQAB\n-----END PUBLIC KEY-----\n",
           "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQE_SHORTENED_FOR_EXAMPLE_T9RoDiukY\n-----END RSA PRIVATE KEY-----\n"
       }
   }
   ```

1. Enter the following commands to set the permissions on the certificate directory and its files.

   ```
   chmod 745 ~
   chmod 700 ~/certs/testconn
   chmod 644 ~/certs/testconn/*
   chmod 600 ~/certs/testconn/private.pem.key
   ```

1. Run this command to review the permissions on your certificate directories and files.

   ```
   ls -l ~/certs/testconn
   ```

   The output of the command should be the same as what you see here, except the file dates and times will be different.

   ```
   -rw-r--r-- 1 pi pi 1220 Oct 28 13:02 device.pem.crt
   -rw------- 1 pi pi 1675 Oct 28 13:02 private.pem.key
   -rw-r--r-- 1 pi pi  451 Oct 28 13:02 public.pem.key
   ```

At this point, you have the device certificate files installed on your Raspberry Pi and you can continue to [Create AWS IoT resources](#iot-dc-install-dc-provision-resources).

### Create AWS IoT resources
<a name="iot-dc-install-dc-provision-resources"></a>

This procedure provisions your device in AWS IoT by creating the resources that your device needs to access AWS IoT features and services.

**To provision your device in AWS IoT**

1. In the terminal window on your local host computer, enter the following command to get the address of the device data endpoint for your AWS account.

   ```
   aws iot describe-endpoint --endpoint-type IoT:Data-ATS
   ```

   The command from the previous steps returns a response like the following. Record the `endpointAddress` value for later use.

   ```
   {
       "endpointAddress": "a3qjEXAMPLEffp-ats.iot.us-west-2.amazonaws.com"
   }
   ```

1. Enter this command to create an AWS IoT thing resource for your Raspberry Pi.

   ```
   aws iot create-thing --thing-name "DevCliTestThing"
   ```

   If your AWS IoT thing resource was created, the command returns a response like this.

   ```
   {
       "thingName": "DevCliTestThing",
       "thingArn": "arn:aws:iot:us-west-2:57EXAMPLE833:thing/DevCliTestThing",
       "thingId": "8ea78707-32c3-4f8a-9232-14bEXAMPLEfd"
   }
   ```

1. In the terminal window:

   1. Open a text editor, such as `nano`.

   1. Copy this JSON policy document and paste it into your open text editor.  
****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Publish",
                      "iot:Subscribe",
                      "iot:Receive",
                      "iot:Connect"
                  ],
                  "Resource": [
                      "*"
                  ]
              }
          ]
      }
      ```
**Note**  
This policy document generously grants every resource permission to connect, receive, publish, and subscribe. Normally policies grant only permission to specific resources to perform specific actions. However, for the initial device connectivity test, this overly general and permissive policy is used to minimize the chance of an access problem during this test. In the subsequent tutorials, more narrowly scoped policy documents will be use to demonstrate better practices in policy design.

   1. Save the file in your text editor as **\$1/policies/dev\$1cli\$1test\$1thing\$1policy.json**. 

1. Run this command to use the policy document from the previous steps to create an AWS IoT policy.

   ```
   aws iot create-policy \
   --policy-name "DevCliTestThingPolicy" \
   --policy-document "file://~/policies/dev_cli_test_thing_policy.json"
   ```

   If the policy is created, the command returns a response like this.

   ```
   {
       "policyName": "DevCliTestThingPolicy",
       "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/DevCliTestThingPolicy",
       "policyDocument": "{\n    \"Version\": \"2012-10-17\",		 	 	 \n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"iot:Publish\",\n                \"iot:Subscribe\",\n                \"iot:Receive\",\n                \"iot:Connect\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        }\n    ]\n}\n",
       "policyVersionId": "1"
   }
   ```

1. Run this command to attach the policy to the device certificate. Replace `certificateArn` with the `certificateArn` value you saved earlier.

   ```
   aws iot attach-policy \
   --policy-name "DevCliTestThingPolicy" \
   --target "certificateArn"
   ```

   If successful, this command returns nothing.

1. Run this command to attach the device certificate to the AWS IoT thing resource. Replace `certificateArn` with the `certificateArn` value you saved earlier.

   ```
   aws iot attach-thing-principal \
   --thing-name "DevCliTestThing" \
   --principal "certificateArn"
   ```

   If successful, this command returns nothing.

After you successfully provisioned your device in AWS IoT, you're ready to continue to [Configure the AWS IoT Device Client to test connectivity](iot-dc-install-configure.md).

# Configure the AWS IoT Device Client to test connectivity
<a name="iot-dc-install-configure"></a>

The procedures in this section configure the AWS IoT Device Client to publish an MQTT message from your Raspberry Pi.

**Topics**
+ [

## Create the config file
](#iot-dc-install-dc-configure-step1)
+ [

## Open MQTT test client
](#iot-dc-install-dc-configure-step2)
+ [

## Run AWS IoT Device Client
](#iot-dc-install-dc-configure-step3)

## Create the config file
<a name="iot-dc-install-dc-configure-step1"></a>

This procedure creates the config file to test the AWS IoT Device Client.

**To create the config file to test the AWS IoT Device Client**
+ In the terminal window on your local host computer that's connected to your Raspberry Pi:

  1. Enter these commands to create a directory for the config files and set the permission on the directory:

     ```
     mkdir ~/dc-configs
     chmod 745 ~/dc-configs
     ```

  1. Open a text editor, such as `nano`.

  1. Copy this JSON document and paste it into your open text editor.

     ```
     {
       "endpoint": "a3qEXAMPLEaffp-ats.iot.us-west-2.amazonaws.com",
       "cert": "~/certs/testconn/device.pem.crt",
       "key": "~/certs/testconn/private.pem.key",
       "root-ca": "~/certs/AmazonRootCA1.pem",
       "thing-name": "DevCliTestThing",
       "logging": {
         "enable-sdk-logging": true,
         "level": "DEBUG",
         "type": "STDOUT",
         "file": ""
       },
       "jobs": {
         "enabled": false,
         "handler-directory": ""
       },
       "tunneling": {
         "enabled": false
       },
       "device-defender": {
         "enabled": false,
         "interval": 300
       },
       "fleet-provisioning": {
         "enabled": false,
         "template-name": "",
         "template-parameters": "",
         "csr-file": "",
         "device-key": ""
       },
       "samples": {
         "pub-sub": {
           "enabled": true,
           "publish-topic": "test/dc/pubtopic",
           "publish-file": "",
           "subscribe-topic": "test/dc/subtopic",
           "subscribe-file": ""
         }
       },
       "config-shadow": {
         "enabled": false
       },
       "sample-shadow": {
         "enabled": false,
         "shadow-name": "",
         "shadow-input-file": "",
         "shadow-output-file": ""
       }
     }
     ```

  1. Replace the *endpoint* value with device data endpoint for your AWS account that you found in [Provision your device in AWS IoT Core](iot-dc-install-provision.md#iot-dc-install-dc-provision).

  1. Save the file in your text editor as **\$1/dc-configs/dc-testconn-config.json**.

  1. Run this command to set the permissions on the new config file.

     ```
     chmod 644 ~/dc-configs/dc-testconn-config.json
     ```

After you save the file, you're ready to continue to [Open MQTT test client](#iot-dc-install-dc-configure-step2).

## Open MQTT test client
<a name="iot-dc-install-dc-configure-step2"></a>

This procedure prepares the **MQTT test client** in the AWS IoT console to subscribe to the MQTT message that the AWS IoT Device Client publishes when it runs.

**To prepare the **MQTT test client** to subscribe to all MQTT messages**

1. On your local host computer, in the [AWS IoT console](https://console.aws.amazon.com//iot/home#/test), choose **MQTT test client**.

1. In the **Subscribe to a topic** tab, in **Topic filter**, enter **\$1** (a single pound sign), and choose **Subscribe** to subscribe to every MQTT topic.

1. Below the **Subscriptions** label, confirm that you see **\$1** (a single pound sign).

Leave the window with the **MQTT test client** open as you continue to [Run AWS IoT Device Client](#iot-dc-install-dc-configure-step3).

## Run AWS IoT Device Client
<a name="iot-dc-install-dc-configure-step3"></a>

This procedure runs the AWS IoT Device Client so that it publishes a single MQTT message that the **MQTT test client** receives and displays.

**To send an MQTT message from the AWS IoT Device Client**

1. Make sure that both the terminal window that's connected to your Raspberry Pi and the window with the **MQTT test client** are visible while you perform this procedure.

1. In the terminal window, enter these commands to run the AWS IoT Device Client using the config file created in [Create the config file](#iot-dc-install-dc-configure-step1).

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-testconn-config.json
   ```

   In the terminal window, the AWS IoT Device Client displays information messages and any errors that occur when it runs.

   If no errors are displayed in the terminal window, review the **MQTT test client**.

1. In the **MQTT test client**, in the Subscriptions window, see the *Hello World\$1* message sent to the `test/dc/pubtopic` message topic.

1. If the AWS IoT Device Client displays no errors and you see *Hello World\$1* sent to the `test/dc/pubtopic` message in the **MQTT test client**, you've demonstrated a successful connection.

1. In the terminal window, enter **^C** (Ctrl-C) to stop the AWS IoT Device Client.

After you've demonstrated that the AWS IoT Device Client is running correctly on your Raspberry Pi and can communicate with AWS IoT, you can continue to the [Tutorial: Demonstrate MQTT message communication with the AWS IoT Device Client](iot-dc-testconn.md).

# Tutorial: Demonstrate MQTT message communication with the AWS IoT Device Client
<a name="iot-dc-testconn"></a>

This tutorial demonstrates how the AWS IoT Device Client can subscribe to and publish MQTT messages, which are commonly used in IoT solutions.

**To start this tutorial:**
+ Have your local host computer and Raspberry Pi configured as used in [the previous section](iot-dc-install-dc.md).

  If you saved the microSD card image after installing the AWS IoT Device Client, you can use a microSD card with that image with your Raspberry Pi.
+ If you have run this demo before, review [Step 2: Cleaning up your AWS account after building demos with the AWS IoT Device Client](iot-dc-cleanup.md#iot-dc-cleanup-cloud) to delete all AWS IoT resources that you created in earlier runs to avoid duplicate resource errors.

This tutorial takes about 45 minutes to complete.

**When you're finished with this topic:**
+ You'll have demonstrated different ways that your IoT device can subscribe to MQTT messages from AWS IoT and publish MQTT messages to AWS IoT.

**Required equipment:**
+ Your local development and testing environment from [the previous section](iot-dc-install-dc.md)
+ The Raspberry Pi that you used in [the previous section](iot-dc-install-dc.md)
+ The microSD memory card from the Raspberry Pi that you used in [the previous section](iot-dc-install-dc.md)

**Topics**
+ [

# Prepare the Raspberry Pi to demonstrate MQTT message communication
](iot-dc-testconn-provision.md)
+ [

# Demonstrate publishing messages with the AWS IoT Device Client
](iot-dc-testconn-publish.md)
+ [

# Demonstrate subscribing to messages with the AWS IoT Device Client
](iot-dc-testconn-subscribe.md)

# Prepare the Raspberry Pi to demonstrate MQTT message communication
<a name="iot-dc-testconn-provision"></a>

This procedure creates the resources in AWS IoT and in the Raspberry Pi to demonstrate MQTT message communication using the AWS IoT Device Client.

**Topics**
+ [

## Create the certificate files to demonstrate MQTT communication
](#iot-dc-testconn-provision-certs)
+ [

## Provision your device to demonstrate MQTT communication
](#iot-dc-testconn-provision-aws)
+ [

## Configure the AWS IoT Device Client config file and MQTT test client to demonstrate MQTT communication
](#iot-dc-testconn-provision-dc-config)

## Create the certificate files to demonstrate MQTT communication
<a name="iot-dc-testconn-provision-certs"></a>

This procedure creates the device certificate files for this demo.

**To create and download the device certificate files for your Raspberry Pi**



1. In the terminal window on your local host computer, enter the following command to create the device certificate files for your device.

   ```
   mkdir ~/certs/pubsub
   aws iot create-keys-and-certificate \
   --set-as-active \
   --certificate-pem-outfile "~/certs/pubsub/device.pem.crt" \
   --public-key-outfile "~/certs/pubsub/public.pem.key" \
   --private-key-outfile "~/certs/pubsub/private.pem.key"
   ```

   The command returns a response like the following. Save the `certificateArn` value for later use.

   ```
   {
   "certificateArn": "arn:aws:iot:us-west-2:57EXAMPLE833:cert/76e7e4edb3e52f52334be2f387a06145b2aa4c7fcd810f3aea2d92abc227d269",
   "certificateId": "76e7e4edb3e52f5233EXAMPLE7a06145b2aa4c7fcd810f3aea2d92abc227d269",
   "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIDWTCCAkGgAwIBAgI_SHORTENED_FOR_EXAMPLE_Lgn4jfgtS\n-----END CERTIFICATE-----\n",
   "keyPair": {
       "PublicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BA_SHORTENED_FOR_EXAMPLE_ImwIDAQAB\n-----END PUBLIC KEY-----\n",
       "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQE_SHORTENED_FOR_EXAMPLE_T9RoDiukY\n-----END RSA PRIVATE KEY-----\n"
   }
   }
   ```

1. Enter the following commands to set the permissions on the certificate directory and its files.

   ```
   chmod 700 ~/certs/pubsub
   chmod 644 ~/certs/pubsub/*
   chmod 600 ~/certs/pubsub/private.pem.key
   ```

1. Run this command to review the permissions on your certificate directories and files.

   ```
   ls -l ~/certs/pubsub
   ```

   The output of the command should be the same as what you see here, except the file dates and times will be different.

   ```
   -rw-r--r-- 1 pi pi 1220 Oct 28 13:02 device.pem.crt
   -rw------- 1 pi pi 1675 Oct 28 13:02 private.pem.key
   -rw-r--r-- 1 pi pi  451 Oct 28 13:02 public.pem.key
   ```

1. Enter these commands to create the directories for the log files.

   ```
   mkdir ~/.aws-iot-device-client
   mkdir ~/.aws-iot-device-client/log
   chmod 745 ~/.aws-iot-device-client/log
   echo " " > ~/.aws-iot-device-client/log/aws-iot-device-client.log
   echo " " > ~/.aws-iot-device-client/log/pubsub_rx_msgs.log
   chmod 600 ~/.aws-iot-device-client/log/*
   ```

## Provision your device to demonstrate MQTT communication
<a name="iot-dc-testconn-provision-aws"></a>

This section creates the AWS IoT resources that provision your Raspberry Pi in AWS IoT. 

**To provision your device in AWS IoT:**

1. In the terminal window on your local host computer, enter the following command to get the address of the device data endpoint for your AWS account.

   ```
   aws iot describe-endpoint --endpoint-type IoT:Data-ATS
   ```

   The endpoint value hasn’t changed since the time you ran this command for the previous tutorial. Running the command again here is done to make it easy to find and paste the data endpoint value into the config file used in this tutorial.

   The command from the previous steps returns a response like the following. Record the `endpointAddress` value for later use.

   ```
   {
   "endpointAddress": "a3qjEXAMPLEffp-ats.iot.us-west-2.amazonaws.com"
   }
   ```

1. Enter this command to create a new AWS IoT thing resource for your Raspberry Pi.

   ```
   aws iot create-thing --thing-name "PubSubTestThing"
   ```

   Because an AWS IoT thing resource is a *virtual* representation of your device in the cloud, we can create multiple thing resources in AWS IoT to use for different purposes. They can all be used by the same physical IoT device to represent different aspects of the device.

   These tutorials will only use one thing resource at a time to represent the Raspberry Pi. This way, in these tutorials, they represent the different demos so that after you create the AWS IoT resources for a demo, you can go back and repeat the demo using the resources you created specifically for each.

   If your AWS IoT thing resource was created, the command returns a response like this.

   ```
   {
   "thingName": "PubSubTestThing",
   "thingArn": "arn:aws:iot:us-west-2:57EXAMPLE833:thing/PubSubTestThing",
   "thingId": "8ea78707-32c3-4f8a-9232-14bEXAMPLEfd"
   }
   ```

1. In the terminal window:

   1. Open a text editor, such as `nano`.

   1. Copy this JSON document and paste it into your open text editor.  
****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Connect"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:client/PubSubTestThing"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Publish"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/test/dc/pubtopic"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Subscribe"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topicfilter/test/dc/subtopic"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Receive"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/test/dc/subtopic"
                  ]
              }
          ]
      }
      ```

   1. In the editor, in each `Resource` section of the policy document, replace *us-west-2:57EXAMPLE833* with your AWS Region, a colon character (:), and your 12-digit AWS account number.

   1. Save the file in your text editor as **\$1/policies/pubsub\$1test\$1thing\$1policy.json**. 

1. Run this command to use the policy document from the previous steps to create an AWS IoT policy.

   ```
   aws iot create-policy \
   --policy-name "PubSubTestThingPolicy" \
   --policy-document "file://~/policies/pubsub_test_thing_policy.json"
   ```

   If the policy is created, the command returns a response like this.

   ```
   {
                                       "policyName": "PubSubTestThingPolicy",
                                       "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/PubSubTestThingPolicy",
                                       "policyDocument": "{\n\"Version\": \"2012-10-17\",		 	 	 \n\"Statement\": [\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Connect\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:client/PubSubTestThing\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Publish\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/pubtopic\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Subscribe\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/subtopic\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Receive\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/*\"\n]\n}\n]\n}\n",
                                       "policyVersionId": "1"
                                       }
   ```

1. Run this command to attach the policy to the device certificate. Replace `certificateArn` with the `certificateArn` value you saved earlier in this section.

   ```
   aws iot attach-policy \
   --policy-name "PubSubTestThingPolicy" \
   --target "certificateArn"
   ```

   If successful, this command returns nothing.

1. Run this command to attach the device certificate to the AWS IoT thing resource. Replace `certificateArn` with the `certificateArn` value you saved earlier in this section.

   ```
   aws iot attach-thing-principal \
   --thing-name "PubSubTestThing" \
   --principal "certificateArn"
   ```

   If successful, this command returns nothing.

After you successfully provision your device in AWS IoT, you're ready to continue to [Configure the AWS IoT Device Client config file and MQTT test client to demonstrate MQTT communication](#iot-dc-testconn-provision-dc-config).

## Configure the AWS IoT Device Client config file and MQTT test client to demonstrate MQTT communication
<a name="iot-dc-testconn-provision-dc-config"></a>

This procedure creates a config file to test the AWS IoT Device Client.

**To create the config file to test the AWS IoT Device Client**

1. In the terminal window on your local host computer that's connected to your Raspberry Pi:

   1. Open a text editor, such as `nano`.

   1. Copy this JSON document and paste it into your open text editor.

      ```
      {
        "endpoint": "a3qEXAMPLEaffp-ats.iot.us-west-2.amazonaws.com",
        "cert": "~/certs/pubsub/device.pem.crt",
        "key": "~/certs/pubsub/private.pem.key",
        "root-ca": "~/certs/AmazonRootCA1.pem",
        "thing-name": "PubSubTestThing",
        "logging": {
          "enable-sdk-logging": true,
          "level": "DEBUG",
          "type": "STDOUT",
          "file": ""
        },
        "jobs": {
          "enabled": false,
          "handler-directory": ""
        },
        "tunneling": {
          "enabled": false
        },
        "device-defender": {
          "enabled": false,
          "interval": 300
        },
        "fleet-provisioning": {
          "enabled": false,
          "template-name": "",
          "template-parameters": "",
          "csr-file": "",
          "device-key": ""
        },
        "samples": {
          "pub-sub": {
            "enabled": true,
            "publish-topic": "test/dc/pubtopic",
            "publish-file": "",
            "subscribe-topic": "test/dc/subtopic",
            "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
          }
        },
        "config-shadow": {
          "enabled": false
        },
        "sample-shadow": {
          "enabled": false,
          "shadow-name": "",
          "shadow-input-file": "",
          "shadow-output-file": ""
        }
      }
      ```

   1. Replace the *endpoint* value with device data endpoint for your AWS account that you found in [Provision your device in AWS IoT Core](iot-dc-install-provision.md#iot-dc-install-dc-provision).

   1. Save the file in your text editor as **\$1/dc-configs/dc-pubsub-config.json**.

   1. Run this command to set the permissions on the new config file.

      ```
      chmod 644 ~/dc-configs/dc-pubsub-config.json
      ```

1. To prepare the **MQTT test client** to subscribe to all MQTT messages:

   1. On your local host computer, in the [AWS IoT console](https://console.aws.amazon.com//iot/home#/test), choose **MQTT test client**.

   1. In the **Subscribe to a topic** tab, in **Topic filter**, enter **\$1** (a single pound sign), and choose **Subscribe**.

   1. Below the **Subscriptions** label, confirm that you see **\$1** (a single pound sign).

   Leave the window with the **MQTT test client** open while you continue this tutorial.

After you save the file and configure the **MQTT test client**, you're ready to continue to [Demonstrate publishing messages with the AWS IoT Device Client](iot-dc-testconn-publish.md).

# Demonstrate publishing messages with the AWS IoT Device Client
<a name="iot-dc-testconn-publish"></a>

The procedures in this section demonstrate how the AWS IoT Device Client can send default and custom MQTT messages.

These policy statements in the policy that you created in the previous step for these exercises give the Raspberry Pi permission to perform these actions:
+ 

**`iot:Connect`**  
Gives the client named `PubSubTestThing`, your Raspberry Pi running the AWS IoT Device Client, to connect.

  ```
      {
        "Effect": "Allow",
        "Action": [
          "iot:Connect"
        ],
        "Resource": [
          "arn:aws:iot:us-west-2:57EXAMPLE833:client/PubSubTestThing"
        ]
      }
  ```
+ 

**`iot:Publish`**  
Gives the Raspberry Pi permission to publish messages with an MQTT topic of `test/dc/pubtopic`.

  ```
      {
        "Effect": "Allow",
        "Action": [
          "iot:Publish"
        ],
        "Resource": [
          "arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/pubtopic"
        ]
      }
  ```

  The `iot:Publish` action gives permission to publish to the MQTT topics listed in the Resource array. The *content* of those messages is not controlled by the policy statement.

## Publish the default message using the AWS IoT Device Client
<a name="iot-dc-testconn-publish-default"></a>

This procedure runs the AWS IoT Device Client so that it publishes a single default MQTT message that the **MQTT test client** receives and displays.

**To send the default MQTT message from the AWS IoT Device Client**

1. Make sure that both the terminal window on your local host computer that's connected to your Raspberry Pi and the window with the **MQTT test client** are visible while you perform this procedure.

1. In the terminal window, enter these commands to run the AWS IoT Device Client using the config file created in [Create the config file](iot-dc-install-configure.md#iot-dc-install-dc-configure-step1).

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-config.json
   ```

   In the terminal window, the AWS IoT Device Client displays information messages and any errors that occur when it runs.

   If no errors are displayed in the terminal window, review the **MQTT test client**.

1. In the **MQTT test client**, in the **Subscriptions** window, see the *Hello World\$1* message sent to the `test/dc/pubtopic` message topic.

1. If the AWS IoT Device Client displays no errors and you see *Hello World\$1* sent to the `test/dc/pubtopic` message in the **MQTT test client**, you've demonstrated a successful connection.

1. In the terminal window, enter **^C** (Ctrl-C) to stop the AWS IoT Device Client.

After you've demonstrated that the AWS IoT Device Client published the default MQTT message, you can continue to the [Publish a custom message using the AWS IoT Device Client](#iot-dc-testconn-publish-custom).

## Publish a custom message using the AWS IoT Device Client
<a name="iot-dc-testconn-publish-custom"></a>

The procedures in this section create a custom MQTT message and then runs the AWS IoT Device Client so that it publishes the custom MQTT message one time for the **MQTT test client** to receive and display.

### Create a custom MQTT message for the AWS IoT Device Client
<a name="iot-dc-testconn-publish-custom-create"></a>

Perform these steps in the terminal window on the local host computer that's connected to your Raspberry Pi.

**To create a custom message for the AWS IoT Device Client to publish**

1. In the terminal window, open a text editor, such as `nano`.

1. Into the text editor, copy and paste the following JSON document. This will be the MQTT message payload that the AWS IoT Device Client publishes.

   ```
   {
     "temperature": 28,
     "humidity": 80,
     "barometer": 1013,
     "wind": {
       "velocity": 22,
       "bearing": 255
     }
   }
   ```

1. Save the contents of the text editor as **\$1/messages/sample-ws-message.json**. 

1. Enter the following command to set the permissions of the message file that you just created.

   ```
   chmod 600 ~/messages/*
   ```

**To create a config file for the AWS IoT Device Client to use to send the custom message**

1. In the terminal window, in a text editor such as `nano`, open the existing AWS IoT Device Client config file: **\$1/dc-configs/dc-pubsub-config.json**. 

1. Edit the `samples` object to look like this. No other part of this file needs to be changed.

   ```
     "samples": {
       "pub-sub": {
         "enabled": true,
         "publish-topic": "test/dc/pubtopic",
         "publish-file": "~/messages/sample-ws-message.json",
         "subscribe-topic": "test/dc/subtopic",
         "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
   ```

1. Save the contents of the text editor as **\$1/dc-configs/dc-pubsub-custom-config.json**. 

1. Run this command to set the permissions on the new config file.

   ```
   chmod 644 ~/dc-configs/dc-pubsub-custom-config.json
   ```

### Publish the custom MQTT message by using the AWS IoT Device Client
<a name="iot-dc-testconn-publish-custom-publish"></a>

This change affects only the *contents* of the MQTT message payload, so the current policy will continue to work. However, if the *MQTT topic* (as defined by the `publish-topic` value in `~/dc-configs/dc-pubsub-custom-config.json`) was changed, the `iot::Publish` policy statement would also need to be modified to allow the Raspberry Pi to publish to the new MQTT topic.

**To send the MQTT message from the AWS IoT Device Client**

1. Make sure that both the terminal window and the window with the **MQTT test client** are visible while you perform this procedure. Also, make sure that your **MQTT test client** is still subscribed to the **\$1** topic filter. If it isn't, subscribe to the **\$1** topic filter again.

1. In the terminal window, enter these commands to run the AWS IoT Device Client using the config file created in [Create the config file](iot-dc-install-configure.md#iot-dc-install-dc-configure-step1).

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-custom-config.json
   ```

   In the terminal window, the AWS IoT Device Client displays information messages and any errors that occur when it runs.

   If no errors are displayed in the terminal window, review the MQTT test client.

1. In the **MQTT test client**, in the **Subscriptions** window, see the custom message payload sent to the `test/dc/pubtopic` message topic.

1. If the AWS IoT Device Client displays no errors and you see the custom message payload that you published to the `test/dc/pubtopic` message in the **MQTT test client**, you've published a custom message successfully.

1. In the terminal window, enter **^C** (Ctrl-C) to stop the AWS IoT Device Client.

After you've demonstrated that the AWS IoT Device Client published a custom message payload, you can continue to [Demonstrate subscribing to messages with the AWS IoT Device Client](iot-dc-testconn-subscribe.md).

# Demonstrate subscribing to messages with the AWS IoT Device Client
<a name="iot-dc-testconn-subscribe"></a>

In this section, you'll demonstrate two types of message subscriptions:
+ Single topic subscription
+ Wild-card topic subscription

These policy statements in the policy created for these exercises give the Raspberry Pi permission to perform these actions:
+ 

**`iot:Receive`**  
Gives the AWS IoT Device Client permission to receive MQTT topics that match those named in the `Resource` object.

  ```
      {
        "Effect": "Allow",
        "Action": [
          "iot:Receive"
        ],
        "Resource": [
          "arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/subtopic"
        ]
      }
  ```
+ 

**`iot:Subscribe`**  
Gives the AWS IoT Device Client permission to subscribe to MQTT topic filters that match those named in the `Resource` object.

  ```
      {
        "Effect": "Allow",
        "Action": [
          "iot:Subscribe"
        ],
        "Resource": [
          "arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/subtopic"
        ]
      }
  ```

## Subscribe to a single MQTT message topic
<a name="iot-dc-testconn-subscribe-simple-topic"></a>

This procedure demonstrates how the AWS IoT Device Client can subscribe to and log MQTT messages.

In the terminal window on your local host computer that's connected to your Raspberry Pi, list the contents of **\$1/dc-configs/dc-pubsub-custom-config.json** or open the file in a text editor to review its contents. Locate the `samples` object, which should look like this.

```
  "samples": {
    "pub-sub": {
      "enabled": true,
      "publish-topic": "test/dc/pubtopic",
      "publish-file": "~/messages/sample-ws-message.json",
      "subscribe-topic": "test/dc/subtopic",
      "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
```

Notice the `subscribe-topic` value is the MQTT topic to which the AWS IoT Device Client will subscribe when it runs. The AWS IoT Device Client writes the message payloads that it receives from this subscription to the file named in the `subscribe-file` value.

**To subscribe to a MQTT message topic from the AWS IoT Device Client**

1. Make sure that both the terminal window and the window with the MQTT test client are visible while you perform this procedure. Also, make sure that your **MQTT test client** is still subscribed to the **\$1** topic filter. If it isn't, subscribe to the **\$1** topic filter again.

1. In the terminal window, enter these commands to run the AWS IoT Device Client using the config file created in [Create the config file](iot-dc-install-configure.md#iot-dc-install-dc-configure-step1).

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-custom-config.json
   ```

   In the terminal window, the AWS IoT Device Client displays information messages and any errors that occur when it runs.

   If no errors are displayed in the terminal window, continue in the AWS IoT console.

1. In the AWS IoT console, in the **MQTT test client**, choose the **Publish to a topic** tab.

1. In **Topic name**, enter **test/dc/subtopic**

1. In **Message payload**, review the message contents.

1. Choose **Publish** to publish the MQTT message.

1. In the terminal window, watch for the *message received * entry from the AWS IoT Device Client that looks like this.

   ```
   2021-11-10T16:02:20.890Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 45 bytes
   ```

1. After you see the *message received * entry that shows the message was received, enter **^C** (Ctrl-C) to stop the AWS IoT Device Client.

1. Enter this command to view the end of the message log file and see the message you published from the **MQTT test client**.

   ```
   tail ~/.aws-iot-device-client/log/pubsub_rx_msgs.log
   ```

By viewing the message in the log file, you've demonstrated that the AWS IoT Device Client received the message that you published from the MQTT test client.

## Subscribe to multiple MQTT message topic using wildcard characters
<a name="iot-dc-testconn-subscribe-wild-topic"></a>

These procedures demonstrate how the AWS IoT Device Client can subscribe to and log MQTT messages using wildcard characters. To do this, you'll:

1. Update the topic filter that the AWS IoT Device Client uses to subscribe to MQTT topics.

1. Update the policy used by the device to allow the new subscriptions.

1. Run the AWS IoT Device Client and publish messages from the MQTT test console.

**To create a config file to subscribe to multiple MQTT message topics by using a wildcard MQTT topic filter**

1. In the terminal window on your local host computer that's connected to your Raspberry Pi, open **\$1/dc-configs/dc-pubsub-custom-config.json** for editing and locate the `samples` object.

1. In the text editor, locate the `samples` object and update the `subscribe-topic` value to look like this. 

   ```
     "samples": {
       "pub-sub": {
         "enabled": true,
         "publish-topic": "test/dc/pubtopic",
         "publish-file": "~/messages/sample-ws-message.json",
         "subscribe-topic": "test/dc/#",
         "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
   ```

   The new `subscribe-topic` value is an [MQTT topic filter](topics.md#topicfilters) with an MQTT wild card character at the end. This describes a subscription to all MQTT topics that start with `test/dc/`. The AWS IoT Device Client writes the message payloads that it receives from this subscription to the file named in `subscribe-file`.

1. Save the modified config file as **\$1/dc-configs/dc-pubsub-wild-config.json**, and exit the editor.

**To modify the policy used by your Raspberry Pi to allow subscribing to and receiving multiple MQTT message topics**

1. In the terminal window on your local host computer that's connected to your Raspberry Pi, in your favorite text editor, open **\$1/policies/pubsub\$1test\$1thing\$1policy.json** for editing, and then locate the `iot::Subscribe` and `iot::Receive` policy statements in the file.

1. In the `iot::Subscribe` policy statement, update the string in the Resource object to replace `subtopic` with `*`, so that it looks like this.

   ```
       {
         "Effect": "Allow",
         "Action": [
           "iot:Subscribe"
         ],
         "Resource": [
           "arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/*"
         ]
       }
   ```
**Note**  
The [MQTT topic filter wild card characters](topics.md#topicfilters) are the `+` (plus sign) and the `#` (pound sign). A subscription request with a `#` at the end subscribes to all topics that start with the string that precedes the `#` character (for example, `test/dc/` in this case).   
The resource value in the policy statement that authorizes this subscription, however, must use a `*` (an asterisk) in place of the `#` (a pound sign) in the topic filter ARN. This is because the policy processor uses a different wild card character than MQTT uses.  
For more information about using wild card characters for topics and topic filters in policies, see [Using wildcard characters in MQTT and AWS IoT Core policies](pub-sub-policy.md#pub-sub-policy-cert).

1. In the `iot::Receive` policy statement, update the string in the Resource object to replace `subtopic` with `*`, so that it looks like this.

   ```
       {
         "Effect": "Allow",
         "Action": [
           "iot:Receive"
         ],
         "Resource": [
           "arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/*"
         ]
       }
   ```

1. Save the updated policy document as **\$1/policies/pubsub\$1wild\$1test\$1thing\$1policy.json**, and exit the editor.

1. Enter this command to update the policy for this tutorial to use the new resource definitions.

   ```
   aws iot create-policy-version \
   --set-as-default \
   --policy-name "PubSubTestThingPolicy" \
   --policy-document "file://~/policies/pubsub_wild_test_thing_policy.json"
   ```

   If the command succeeds, it returns a response like this. Notice that `policyVersionId` is now `2`, indicating this is the second version of this policy. 

   If you successfully updated the policy, you can continue to the next procedure.

   ```
   {
       "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/PubSubTestThingPolicy",
       "policyDocument": "{\n  \"Version\": \"2012-10-17\",		 	 	 \n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iot:Connect\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iot:us-west-2:57EXAMPLE833:client/PubSubTestThing\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iot:Publish\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/pubtopic\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iot:Subscribe\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iot:Receive\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/*\"\n      ]\n    }\n  ]\n}\n",
       "policyVersionId": "2",
       "isDefaultVersion": true
   }
   ```

   If you get an error that there are too many policy versions to save a new one, enter this command to list the current versions of the policy. Review the list that this command returns to find a policy version that you can delete.

   ```
   aws iot list-policy-versions --policy-name "PubSubTestThingPolicy"
   ```

   Enter this command to delete a version that you no longer need. Note that you can't delete the default policy version. The default policy version is the one with a `isDefaultVersion` value of `true`.

   ```
   aws iot delete-policy-version \
   --policy-name "PubSubTestThingPolicy" \
   --policy-version-id policyId
   ```

   After deleting a policy version, retry this step.

With the updated config file and policy, you're ready to demonstrate wild card subscriptions with the AWS IoT Device Client.

**To demonstrate how the AWS IoT Device Client subscribes to and receives multiple MQTT message topics**

1. In the **MQTT test client**, check the subscriptions. If the **MQTT test client** is subscribed to the to the in the **\$1** topic filter, continue to the next step. If not, in the **MQTT test client**, in **Subscribe to a topic** tab, in **Topic filter**, enter **\$1** (a pound sign character), and then choose **Subscribe** to subscribe to it.

1. In the terminal window on your local host computer that's connected to your Raspberry Pi, enter these commands to start the AWS IoT Device Client.

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-wild-config.json
   ```

1. While watching the AWS IoT Device Client output in the terminal window on the local host computer, return to the **MQTT test client**. In the **Publish to a topic** tab, in **Topic name**, enter **test/dc/subtopic** , and then choose **Publish**. 

1. In the terminal window, confirm that the message was received by looking for a message such as:

   ```
   2021-11-10T16:34:20.101Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 76 bytes
   ```

1. While watching the AWS IoT Device Client output in the terminal window of the local host computer, return to the **MQTT test client**. In the **Publish to a topic** tab, in **Topic name**, enter **test/dc/subtopic2** , and then choose **Publish**. 

1. In the terminal window, confirm that the message was received by looking for a message such as:

   ```
   2021-11-10T16:34:32.078Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 77 bytes
   ```

1. After you see the messages that confirm both messages were received, enter **^C** (Ctrl-C) to stop the AWS IoT Device Client.

1. Enter this command to view the end of the message log file and see the message you published from the **MQTT test client**.

   ```
   tail -n 20 ~/.aws-iot-device-client/log/pubsub_rx_msgs.log
   ```
**Note**  
The log file contains only message payloads. The message topics are not recorded in the received message log file.  
You might also see the message published by the AWS IoT Device Client in the received log. This is because the wild card topic filter includes that message topic and, sometimes, the subscription request can be processed by message broker before the published message is sent to subscribers.

The entries in the log file demonstrate that the messages were received. You can repeat this procedure using other topic names. All messages that have a topic name that begins with `test/dc/` should be received and logged. Messages with topic names that begin with any other text are ignored.

After demonstrating how the AWS IoT Device Client can publish and subscribe to MQTT messages, continue to [Tutorial: Demonstrate remote actions (jobs) with the AWS IoT Device Client](iot-dc-runjobs.md).

# Tutorial: Demonstrate remote actions (jobs) with the AWS IoT Device Client
<a name="iot-dc-runjobs"></a>

In these tutorials, you'll configure and deploy jobs to your Raspberry Pi to demonstrate how you can send remote operations to your IoT devices.

**To start this tutorial:**
+ Have your local host computer an Raspberry Pi configured as used in [the previous section](iot-dc-testconn.md). 
+ If you haven't completed the tutorial in the previous section, you can try this tutorial by using the Raspberry Pi with a microSD card that has the image you saved after you installed the AWS IoT Device Client in [(Optional) Save the microSD card image](iot-dc-install-download.md#iot-dc-install-dc-save).
+ If you have run this demo before, review [Step 2: Cleaning up your AWS account after building demos with the AWS IoT Device Client](iot-dc-cleanup.md#iot-dc-cleanup-cloud) to delete all AWS IoT resources that you created in earlier runs to avoid duplicate resource errors.

This tutorial takes about 45 minutes to complete.

**When you're finished with this topic:**
+ You'll have demonstrated different ways that your IoT device can use the AWS IoT Core to run remote operations that are managed by AWS IoT .

**Required equipment:**
+ Your local development and testing environment that you tested in [a previous section](iot-dc-install-dc.md)
+ The Raspberry Pi that you tested in [a previous section](iot-dc-install-dc.md)
+ The microSD memory card from the Raspberry Pi that you tested in [a previous section](iot-dc-install-dc.md)

**Topics**
+ [

# Prepare the Raspberry Pi to run jobs
](iot-dc-runjobs-prepare.md)
+ [

# Create and run the job in AWS IoT with AWS IoT Device Client
](iot-dc-runjobs-prepare-define.md)

# Prepare the Raspberry Pi to run jobs
<a name="iot-dc-runjobs-prepare"></a>

The procedures in this section describe how to prepare your Raspberry Pi to run jobs by using the AWS IoT Device Client.

**Note**  
These procedures are device specific. If you want to perform the procedures in this section with more than one device at the same time, each device will need its own policy and unique, device-specific certificate and thing name. To give each device its unique resources, perform this procedure one time for each device while changing the device-specific elements as described in the procedures.

**Topics**
+ [

## Provision your Raspberry Pi to demonstrate jobs
](#iot-dc-runjobs-prepare-provision)
+ [

## Configure the AWS IoT Device Client to run the jobs agent
](#iot-dc-runjobs-prepare-config)

## Provision your Raspberry Pi to demonstrate jobs
<a name="iot-dc-runjobs-prepare-provision"></a>

The procedures in this section provision your Raspberry Pi in AWS IoT by creating AWS IoT resources and device certificates for it. 

**Topics**
+ [

### Create and download device certificate files to demonstrate AWS IoT jobs
](#iot-dc-runjobs-prepare-cert)
+ [

### Create AWS IoT resources to demonstrate AWS IoT jobs
](#iot-dc-runjobs-prepare-iot)

### Create and download device certificate files to demonstrate AWS IoT jobs
<a name="iot-dc-runjobs-prepare-cert"></a>

This procedure creates the device certificate files for this demo.

If you are preparing more than one device, this procedure must be performed on each device.

**To create and download the device certificate files for your Raspberry Pi:**

In the terminal window on your local host computer that's connected to your Raspberry Pi, enter these commands.

1. Enter the following command to create the device certificate files for your device.

   ```
   aws iot create-keys-and-certificate \
   --set-as-active \
   --certificate-pem-outfile "~/certs/jobs/device.pem.crt" \
   --public-key-outfile "~/certs/jobs/public.pem.key" \
   --private-key-outfile "~/certs/jobs/private.pem.key"
   ```

   The command returns a response like the following. Save the `certificateArn` value for later use.

   ```
   {
   "certificateArn": "arn:aws:iot:us-west-2:57EXAMPLE833:cert/76e7e4edb3e52f52334be2f387a06145b2aa4c7fcd810f3aea2d92abc227d269",
   "certificateId": "76e7e4edb3e52f5233EXAMPLE7a06145b2aa4c7fcd810f3aea2d92abc227d269",
   "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIDWTCCAkGgAwIBAgI_SHORTENED_FOR_EXAMPLE_Lgn4jfgtS\n-----END CERTIFICATE-----\n",
   "keyPair": {
       "PublicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BA_SHORTENED_FOR_EXAMPLE_ImwIDAQAB\n-----END PUBLIC KEY-----\n",
       "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQE_SHORTENED_FOR_EXAMPLE_T9RoDiukY\n-----END RSA PRIVATE KEY-----\n"
   }
   }
   ```

1. Enter the following commands to set the permissions on the certificate directory and its files.

   ```
   chmod 700 ~/certs/jobs
   chmod 644 ~/certs/jobs/*
   chmod 600 ~/certs/jobs/private.pem.key
   ```

1. Run this command to review the permissions on your certificate directories and files.

   ```
   ls -l ~/certs/jobs
   ```

   The output of the command should be the same as what you see here, except the file dates and times will be different.

   ```
   -rw-r--r-- 1 pi pi 1220 Oct 28 13:02 device.pem.crt
   -rw------- 1 pi pi 1675 Oct 28 13:02 private.pem.key
   -rw-r--r-- 1 pi pi  451 Oct 28 13:02 public.pem.key
   ```

After you have downloaded the device certificate files to your Raspberry Pi, you're ready to continue to [Provision your Raspberry Pi to demonstrate jobs](#iot-dc-runjobs-prepare-provision).

### Create AWS IoT resources to demonstrate AWS IoT jobs
<a name="iot-dc-runjobs-prepare-iot"></a>

Create the AWS IoT resources for this device.

If you are preparing more than one device, this procedure must be performed for each device.



**To provision your device in AWS IoT:**

In the terminal window on your local host computer that's connected to your Raspberry Pi:

1. Enter the following command to get the address of the device data endpoint for your AWS account.

   ```
   aws iot describe-endpoint --endpoint-type IoT:Data-ATS
   ```

   The endpoint value hasn’t changed since the last time you ran this command. Running the command again here makes it easy to find and paste the data endpoint value into the config file used in this tutorial.

   The **describe-endpoint** command returns a response like the following. Record the `endpointAddress` value for later use.

   ```
   {
   "endpointAddress": "a3qjEXAMPLEffp-ats.iot.us-west-2.amazonaws.com"
   }
   ```

1. Replace *uniqueThingName* with a unique name for your device. If you want to perform this tutorial with multiple devices, give each device its own name. For example, **TestDevice01**, **TestDevice02**, and so on.

   Enter this command to create a new AWS IoT thing resource for your Raspberry Pi.

   ```
   aws iot create-thing --thing-name "uniqueThingName"
   ```

   Because an AWS IoT thing resource is a *virtual* representation of your device in the cloud, we can create multiple thing resources in AWS IoT to use for different purposes. They can all be used by the same physical IoT device to represent different aspects of the device.
**Note**  
When you want to secure the policy for multiple devices, you can use `${iot:Thing.ThingName}` instead of the static thing name, `uniqueThingName`.

   These tutorials will only use one thing resource at a time per device. This way, in these tutorials, they represent the different demos so that after you create the AWS IoT resources for a demo, you can go back and repeat the demos using the resources you created specifically for each.

   If your AWS IoT thing resource was created, the command returns a response like this. Record the `thingArn` value for use later when you create the job to run on this device.

   ```
   {
   "thingName": "uniqueThingName",
   "thingArn": "arn:aws:iot:us-west-2:57EXAMPLE833:thing/uniqueThingName",
   "thingId": "8ea78707-32c3-4f8a-9232-14bEXAMPLEfd"
   }
   ```

1. In the terminal window:

   1. Open a text editor, such as `nano`.

   1. Copy this JSON document and paste it into your open text editor.  
****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Connect"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:client/uniqueThingName"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Publish"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/test/dc/pubtopic",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/events/job/*",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/events/jobExecution/*",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/things/uniqueThingName/jobs/*"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Subscribe"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topicfilter/test/dc/subtopic",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/events/jobExecution/*",
                      "arn:aws:iot:us-west-2:123456789012:topicfilter/$aws/things/uniqueThingName/jobs/*"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Receive"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/test/dc/subtopic",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/things/uniqueThingName/jobs/*"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:DescribeJobExecution",
                      "iot:GetPendingJobExecutions",
                      "iot:StartNextPendingJobExecution",
                      "iot:UpdateJobExecution"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/things/uniqueThingName"
                  ]
              }
          ]
      }
      ```

   1. In the editor, in the `Resource` section of every policy statement, replace *us-west-2:57EXAMPLE833* with your AWS Region, a colon character (:), and your 12-digit AWS account number.

   1. In the editor, in every policy statement, replace *uniqueThingName* with the thing name you gave this thing resource.

   1. Save the file in your text editor as **\$1/policies/jobs\$1test\$1thing\$1policy.json**.

      If you are running this procedure for multiple devices, save the file to this file name on each device.

1. Replace *uniqueThingName* with the thing name for the device, and then run this command to create an AWS IoT policy that is tailored for that device.

   ```
   aws iot create-policy \
   --policy-name "JobTestPolicyForuniqueThingName" \
   --policy-document "file://~/policies/jobs_test_thing_policy.json"
   ```

   If the policy is created, the command returns a response like this.  
****  

   ```
   {
       "policyName": "JobTestPolicyForuniqueThingName",
       "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/JobTestPolicyForuniqueThingName",
       "policyDocument": "{\n\"Version\": \"2012-10-17\",\n\"Statement\": [\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Connect\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:client/PubSubTestThing\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Publish\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/pubtopic\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Subscribe\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/subtopic\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Receive\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/*\"\n]\n}\n]\n}\n",
       "policyVersionId": "1"
   }
   ```

1. Replace *uniqueThingName* with the thing name for the device and `certificateArn` with the `certificateArn` value you saved earlier in this section for this device, and then run this command to attach the policy to the device certificate. 

   ```
   aws iot attach-policy \
   --policy-name "JobTestPolicyForuniqueThingName" \
   --target "certificateArn"
   ```

   If successful, this command returns nothing.

1.  Replace *uniqueThingName* with the thing name for the device, replace `certificateArn` with the `certificateArn` value that you saved earlier in this section, and then run this command to attach the device certificate to the AWS IoT thing resource.

   ```
   aws iot attach-thing-principal \
   --thing-name "uniqueThingName" \
   --principal "certificateArn"
   ```

   If successful, this command returns nothing.

After you successfully provisioned your Raspberry Pi, you're ready to repeat this section for another Raspberry Pi in your test or, if all devices have been provisioned, continue to [Configure the AWS IoT Device Client to run the jobs agent](#iot-dc-runjobs-prepare-config).

## Configure the AWS IoT Device Client to run the jobs agent
<a name="iot-dc-runjobs-prepare-config"></a>

This procedure creates a config file for the AWS IoT Device Client to run the jobs agent:.

Note: if you are preparing more than one device, this procedure must be performed on each device.

**To create the config file to test the AWS IoT Device Client:**

1. In the terminal window on your local host computer that's connected to your Raspberry Pi:

   1. Open a text editor, such as `nano`.

   1. Copy this JSON document and paste it into your open text editor.

      ```
      {
        "endpoint": "a3qEXAMPLEaffp-ats.iot.us-west-2.amazonaws.com",
        "cert": "~/certs/jobs/device.pem.crt",
        "key": "~/certs/jobs/private.pem.key",
        "root-ca": "~/certs/AmazonRootCA1.pem",
        "thing-name": "uniqueThingName",
        "logging": {
          "enable-sdk-logging": true,
          "level": "DEBUG",
          "type": "STDOUT",
          "file": ""
        },
        "jobs": {
          "enabled": true,
          "handler-directory": ""
        },
        "tunneling": {
          "enabled": false
        },
        "device-defender": {
          "enabled": false,
          "interval": 300
        },
        "fleet-provisioning": {
          "enabled": false,
          "template-name": "",
          "template-parameters": "",
          "csr-file": "",
          "device-key": ""
        },
        "samples": {
          "pub-sub": {
            "enabled": false,
            "publish-topic": "",
            "publish-file": "",
            "subscribe-topic": "",
            "subscribe-file": ""
          }
        },
        "config-shadow": {
          "enabled": false
        },
        "sample-shadow": {
          "enabled": false,
          "shadow-name": "",
          "shadow-input-file": "",
          "shadow-output-file": ""
        }
      }
      ```

   1. Replace the *endpoint* value with device data endpoint value for your AWS account that you found in [Provision your device in AWS IoT Core](iot-dc-install-provision.md#iot-dc-install-dc-provision).

   1. Replace *uniqueThingName* with the thing name that you used for this device.

   1. Save the file in your text editor as **\$1/dc-configs/dc-jobs-config.json**.

1. Run this command to set the file permissions of the new config file.

   ```
   chmod 644 ~/dc-configs/dc-jobs-config.json
   ```

You won't use the **MQTT test client** for this test. While the device will exchange jobs-related MQTT messages with AWS IoT, job progress messages are only exchanged with the device running the job. Because job progress messages are only exchanged with the device running the job, you can't subscribe to them from another device, such as the AWS IoT console.

After you save the config file, you're ready to continue to [Create and run the job in AWS IoT with AWS IoT Device Client](iot-dc-runjobs-prepare-define.md).

# Create and run the job in AWS IoT with AWS IoT Device Client
<a name="iot-dc-runjobs-prepare-define"></a>

The procedures in this section create a job document and an AWS IoT job resource. After you create the job resource, AWS IoT sends the job document to the specified job targets on which a jobs agent applies the job document to the device or client.

**Topics**
+ [

## Create and store the job document for the IoT job
](#iot-dc-runjobs-prepare-define-jobdoc)
+ [

## Run a job in AWS IoT for one IoT device
](#iot-dc-runjobs-prepare-define-job)

## Create and store the job document for the IoT job
<a name="iot-dc-runjobs-prepare-define-jobdoc"></a>

This procedure creates a simple job document to include in an AWS IoT job resource. This job document displays "Hello world\$1" on the job target.

**To create and store a job document:**

1. Select the Amazon S3 bucket into which you'll save your job document. If you don't have an existing Amazon S3 bucket to use for this, you'll need to create one. For information about how to create Amazon S3 buckets, see the topics in [Getting started with Amazon S3](https://docs.aws.amazon.com//AmazonS3/latest/userguide/GetStartedWithS3.html).

1. Create and save the job document for this job

   1. On your local host computer, open a text editor.

   1. Copy and paste this text into the editor.

      ```
      {
          "operation": "echo",
          "args": ["Hello world!"]
      }
      ```

   1. On the local host computer, save the contents of the editor to a file named **hello-world-job.json**.

   1. Confirm the file was saved correctly. Some text editors automatically append `.txt` to the file name when they save a text file. If your editor appended `.txt` to the file name, correct the file name before proceeding.

1. Replace the *path\$1to\$1file* with the path to **hello-world-job.json**, if it's not in your current directory, replace *s3\$1bucket\$1name* with the Amazon S3 bucket path to the bucket you selected, and then run this command to put your job document into the Amazon S3 bucket.

   ```
   aws s3api put-object \
   --key hello-world-job.json \
   --body path_to_file/hello-world-job.json --bucket s3_bucket_name
   ```

   The job document URL that identifies the job document that you stored in Amazon S3 is determined by replacing the *s3\$1bucket\$1name* and *AWS\$1region* in the following URL. Record the resulting URL to use later as the *job\$1document\$1path*

   ```
   https://s3_bucket_name.s3.AWS_Region.amazonaws.com/hello-world-job.json
   ```
**Note**  
AWS security prevents you from being able to open this URL outside of your AWS account, for example by using a browser. The URL is used by the AWS IoT jobs engine, which has access to the file, by default. In a production environment, you'll need to make sure that your AWS IoT services have permission to access to the job documents stored in Amazon S3.

After you have saved the job document's URL, continue to [Run a job in AWS IoT for one IoT device](#iot-dc-runjobs-prepare-define-job).

## Run a job in AWS IoT for one IoT device
<a name="iot-dc-runjobs-prepare-define-job"></a>

The procedures in this section start the AWS IoT Device Client on your Raspberry Pi to run the jobs agent on the device to wait for jobs to run. It also creates a job resource in AWS IoT, which will send the job to and run on your IoT device.

**Note**  
This procedure runs a job on only a single device.

**To start the jobs agent on your Raspberry Pi:**

1. In the terminal window on your local host computer that's connected to your Raspberry Pi, run this command to start the AWS IoT Device Client.

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-jobs-config.json
   ```

1. In the terminal window, confirm that the AWS IoT Device Client and displays these messages

   ```
   2021-11-15T18:45:56.708Z [INFO]  {Main.cpp}: Jobs is enabled
                         .
                         .
                         .
   2021-11-15T18:45:56.708Z [INFO]  {Main.cpp}: Client base has been notified that Jobs has started
   2021-11-15T18:45:56.708Z [INFO]  {JobsFeature.cpp}: Running Jobs!
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to startNextPendingJobExecution accepted and rejected
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to nextJobChanged events
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to updateJobExecutionStatusAccepted for jobId +
   2021-11-15T18:45:56.738Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToUpdateJobExecutionAccepted with code {0}
   2021-11-15T18:45:56.739Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to updateJobExecutionStatusRejected for jobId +
   2021-11-15T18:45:56.753Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToNextJobChanged with code {0}
   2021-11-15T18:45:56.760Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToStartNextJobRejected with code {0}
   2021-11-15T18:45:56.776Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToStartNextJobAccepted with code {0}
   2021-11-15T18:45:56.776Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToUpdateJobExecutionRejected with code {0}
   2021-11-15T18:45:56.777Z [DEBUG] {JobsFeature.cpp}: Publishing startNextPendingJobExecutionRequest
   2021-11-15T18:45:56.785Z [DEBUG] {JobsFeature.cpp}: Ack received for StartNextPendingJobPub with code {0}
   2021-11-15T18:45:56.785Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

1. In the terminal window, after you see this message, continue to the next procedure and create the job resource. Note that it might not be the last entry in the list.

   ```
   2021-11-15T18:45:56.785Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

**To create an AWS IoT job resource**

1. On your local host computer:

   1. Replace *job\$1document\$1url* with the job document URL from [Create and store the job document for the IoT job](#iot-dc-runjobs-prepare-define-jobdoc).

   1. Replace *thing\$1arn* with the ARN of the thing resource you created for your device and then run this command.

      ```
      aws iot create-job \
      --job-id hello-world-job-1 \
      --document-source "job_document_url" \
      --targets "thing_arn" \
      --target-selection SNAPSHOT
      ```

      If successful, the command returns a result like this one.

      ```
      {
        "jobArn": "arn:aws:iot:us-west-2:57EXAMPLE833:job/hello-world-job-1",
        "jobId": "hello-world-job-1"
      }
      ```

1. In the terminal window, you should see output from the AWS IoT Device Client like this.

   ```
   2021-11-15T18:02:26.688Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Job ids differ
   2021-11-15T18:10:24.890Z [INFO]  {JobsFeature.cpp}: Executing job: hello-world-job-1
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Attempting to update job execution status!
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Not including stdout with the status details
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Not including stderr with the status details
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Assuming executable is in PATH
   2021-11-15T18:10:24.890Z [INFO]  {JobsFeature.cpp}: About to execute: echo Hello world!
   2021-11-15T18:10:24.890Z [DEBUG] {Retry.cpp}: Retryable function starting, it will retry until success
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Created EphermalPromise for ClientToken 3TEWba9Xj6 in the updateJobExecution promises map
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Child process now running
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Child process about to call execvp
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Parent process now running, child PID is 16737
   2021-11-15T18:10:24.891Z [DEBUG] {16737}: Hello world!
   2021-11-15T18:10:24.891Z [DEBUG] {JobEngine.cpp}: JobEngine finished waiting for child process, returning 0
   2021-11-15T18:10:24.891Z [INFO]  {JobsFeature.cpp}: Job exited with status: 0
   2021-11-15T18:10:24.891Z [INFO]  {JobsFeature.cpp}: Job executed successfully!
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Attempting to update job execution status!
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Not including stdout with the status details
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Not including stderr with the status details
   2021-11-15T18:10:24.892Z [DEBUG] {Retry.cpp}: Retryable function starting, it will retry until success
   2021-11-15T18:10:24.892Z [DEBUG] {JobsFeature.cpp}: Created EphermalPromise for ClientToken GmQ0HTzWGg in the updateJobExecution promises map
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Ack received for PublishUpdateJobExecutionStatus with code {0}
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Removing ClientToken 3TEWba9Xj6 from the updateJobExecution promises map
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Success response after UpdateJobExecution for job hello-world-job-1
   2021-11-15T18:10:24.917Z [DEBUG] {JobsFeature.cpp}: Ack received for PublishUpdateJobExecutionStatus with code {0}
   2021-11-15T18:10:24.918Z [DEBUG] {JobsFeature.cpp}: Removing ClientToken GmQ0HTzWGg from the updateJobExecution promises map
   2021-11-15T18:10:24.918Z [DEBUG] {JobsFeature.cpp}: Success response after UpdateJobExecution for job hello-world-job-1
   2021-11-15T18:10:25.861Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

1. While the AWS IoT Device Client is running and waiting for a job, you can submit another job by changing the `job-id` value and re-running the **create-job** from Step 1.

When you’re done running jobs, in the terminal window, enter ^C (control-C) to stop the AWS IoT Device Client.

# Tutorial: Cleaning up after running the AWS IoT Device Client tutorials
<a name="iot-dc-cleanup"></a>

The procedures in this tutorial walk you through removing the files and resources you created while completing the tutorials in this learning path.

**Topics**
+ [

## Step 1: Cleaning up your devices after building demos with the AWS IoT Device Client
](#iot-dc-cleanup-devices)
+ [

## Step 2: Cleaning up your AWS account after building demos with the AWS IoT Device Client
](#iot-dc-cleanup-cloud)

## Step 1: Cleaning up your devices after building demos with the AWS IoT Device Client
<a name="iot-dc-cleanup-devices"></a>

This tutorial describes two options for how to clean up the microSD card after you built the demos in this learning path. Choose the option that provides the level of security that you need.

Note that cleaning the device's microSD card does not remove any AWS IoT resources that you created. To clean up the AWS IoT resources after you clean the device's microSD card, you should review the tutorial on [Step 2: Cleaning up your AWS account after building demos with the AWS IoT Device Client](#iot-dc-cleanup-cloud).

### Option 1: Cleaning up by rewriting the microSD card
<a name="iot-dc-cleanup-devices-flash"></a>

The easiest and most thorough way to clean the microSD card after completing the tutorials in this learning path is to overwrite the microSD card with a saved image file that you created while preparing your device the first time.

This procedure uses the local host computer to write a saved microSD card image to a microSD card.

**Note**  
If your device doesn't use a removable storage medium for its operating system, refer to the procedure for that device.

**To write a new image to the microSD card**

1. On your local host computer, locate the saved microSD card image that you want to write to your microSD card. 

1. Insert your microSD card into the local host computer.

1. Using an SD card imaging tool, write selected image file to the microSD card.

1. After writing the Raspberry Pi OS image to the microSD card, eject the microSD card and safely remove it from the local host computer.

Your microSD card is ready to use.

### Option 2: Cleaning up by deleting user directories
<a name="iot-dc-cleanup-devices-dirs"></a>

To clean the microSD card after completing the tutorials without rewriting the microSD card image, you can delete the user directories individually. This is not as thorough as rewriting the microSD card from a saved image because it does not remove any system files that might have been installed.

If removing the user directories is sufficiently thorough for you needs, you can follow this procedure.

**To delete this learning path's user directories from your device**

1. Run these commands to delete the user directories, subdirectories, and all their files that were created in this learning path, in the terminal window connected to your device.
**Note**  
After you delete these directories and files, you won't be able to run the demos without completing the tutorials again.

   ```
   rm -Rf ~/dc-configs
   rm -Rf ~/policies
   rm -Rf ~/messages
   rm -Rf ~/certs
   rm -Rf ~/.aws-iot-device-client
   ```

1. Run these commands to delete the application source directories and files, in the terminal window connected to your device.
**Note**  
These commands don't uninstall any programs. They only remove the source files used to build and install them. After you delete these files, the AWS CLI and the AWS IoT Device Client might not work.

   ```
   rm -Rf ~/aws-cli
   rm -Rf ~/aws
   rm -Rf ~/aws-iot-device-client
   ```

## Step 2: Cleaning up your AWS account after building demos with the AWS IoT Device Client
<a name="iot-dc-cleanup-cloud"></a>

These procedures help you identify and remove the AWS resources that you created while completing the tutorials in this learning path.

### Clean up AWS IoT resources
<a name="iot-dc-cleanup-cloud-iot"></a>

This procedure helps you identify and remove the AWS IoT resources that you created while completing the tutorials in this learning path.


**AWS IoT resources created in this learning path**  

| Tutorial | Thing resource | Policy resource | 
| --- | --- | --- | 
|  [Tutorial: Installing and configuring the AWS IoT Device Client](iot-dc-install-dc.md)  |  **DevCliTestThing**  | DevCliTestThingPolicy | 
|  [Tutorial: Demonstrate MQTT message communication with the AWS IoT Device Client](iot-dc-testconn.md)  |  **PubSubTestThing**  | PubSubTestThingPolicy | 
|  [Tutorial: Demonstrate remote actions (jobs) with the AWS IoT Device Client](iot-dc-runjobs.md)  | user defined (there could be more than one) |  *user defined* (there could be more than one)  | 

**To delete the AWS IoT resources, follow this procedure for each thing resource that you created**

1. Replace `thing_name` with the name of the thing resource you want to delete, and then run this command to list the certificates attached to the thing resource, from the local host computer.

   ```
   aws iot list-thing-principals --thing-name thing_name
   ```

   This command returns a response like this one that lists the certificates that are attached to `thing_name`. In most cases, there will only be one certificate in the list.

   ```
   {
       "principals": [
           "arn:aws:iot:us-west-2:57EXAMPLE833:cert/23853eea3cf0edc7f8a69c74abeafa27b2b52823cab5b3e156295e94b26ae8ac"
       ]
   }
   ```

1. For each certificate listed by the previous command:

   1. Replace `certificate_ID` with the certificate ID from the previous command. The certificate ID is the alphanumeric characters that follow `cert/` in the ARN returned by the previous command. Then run this command to inactivate the certificate.

      ```
      aws iot update-certificate --new-status INACTIVE --certificate-id certificate_ID
      ```

      If successful, this command doesn't return anything.

   1. Replace `certificate_ARN` with the certificate ARN from the list of certificates returned earlier, and then run this command to list the policies attached to this certificate.

      ```
      aws iot list-attached-policies --target certificate_ARN
      ```

      This command returns a response like this one that lists the policies attached to the certificate. In most cases, there will only be one policy in the list.

      ```
      {
          "policies": [
              {
                  "policyName": "DevCliTestThingPolicy",
                  "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/DevCliTestThingPolicy"
              }
          ]
      }
      ```

   1. For each policy attached to the certificate:

      1. Replace `policy_name` with the `policyName` value from the previous command, replace `certificate_ARN` with the certificate's ARN, and then run this command to detach the policy from the certificate.

         ```
         aws iot detach-policy --policy-name policy_name --target certificate_ARN
         ```

         If successful, this command doesn't return anything.

      1. Replace `policy_name` with the `policyName` value, and then run this command to see if the policy is attached to any more certificates.

         ```
         aws iot list-targets-for-policy --policy-name policy_name
         ```

         If the command returns an empty list like this, the policy is not attached to any certificates and you continue to list the policy versions. If there are still certificates attached to the policy, continue with the **detach-thing-principal** step.

         ```
         {
             "targets": []
         }
         ```

      1. Replace `policy_name` with the `policyName` value, and then run this command to check for policy versions. To delete the policy, it must have only one version.

         ```
         aws iot list-policy-versions --policy-name policy_name
         ```

         If the policy has only one version, like this example, you can skip to the **delete-policy** step and delete the policy now.

         ```
         {
             "policyVersions": [
                 {
                     "versionId": "1",
                     "isDefaultVersion": true,
                     "createDate": "2021-11-18T01:02:46.778000+00:00"
                 }
             ]
         }
         ```

         If the policy has more than one version, like this example, the policy versions with an `isDefaultVersion` value of `false` must be deleted before the policy can be deleted.

         ```
         {
             "policyVersions": [
                 {
                     "versionId": "2",
                     "isDefaultVersion": true,
                     "createDate": "2021-11-18T01:52:04.423000+00:00"
                 },
                 {
                     "versionId": "1",
                     "isDefaultVersion": false,
                     "createDate": "2021-11-18T01:30:18.083000+00:00"
                 }
             ]
         }
         ```

         If you need to delete a policy version, replace `policy_name` with the `policyName` value, replace `version_ID` with the `versionId` value from the previous command, and then run this command to delete a policy version.

         ```
         aws iot delete-policy-version --policy-name policy_name --policy-version-id version_ID
         ```

         If successful, this command doesn't return anything.

         After you delete a policy version, repeat this step until the policy has only one policy version.

      1. Replace `policy_name` with the `policyName` value, and then run this command to delete the policy.

         ```
         aws iot delete-policy --policy-name policy_name
         ```

   1. Replace `thing_name` with the thing's name, replace `certificate_ARN` with the certificate's ARN, and then run this command to detach the certificate from the thing resource.

      ```
      aws iot detach-thing-principal --thing-name thing_name --principal certificate_ARN
      ```

      If successful, this command doesn't return anything.

   1. Replace `certificate_ID` with the certificate ID from the previous command. The certificate ID is the alphanumeric characters that follow `cert/` in the ARN returned by the previous command. Then run this command to delete the certificate resource.

      ```
      aws iot delete-certificate --certificate-id certificate_ID
      ```

      If successful, this command doesn't return anything.

1. Replace `thing_name` with the thing's name, and then run this command to delete the thing.

   ```
   aws iot delete-thing --thing-name thing_name
   ```

   If successful, this command doesn't return anything. 

### Clean up AWS resources
<a name="iot-dc-cleanup-cloud-aws"></a>

This procedure helps you identify and remove other AWS resources that you created while completing the tutorials in this learning path.


**Other AWS resources created in this learning path**  

| Tutorial | Resource type | Resource name or ID | 
| --- | --- | --- | 
|  [Tutorial: Demonstrate remote actions (jobs) with the AWS IoT Device Client](iot-dc-runjobs.md)  | Amazon S3 object | hello-world-job.json | 
|  [Tutorial: Demonstrate remote actions (jobs) with the AWS IoT Device Client](iot-dc-runjobs.md)  |  AWS IoT job resources  | user defined | 

**To delete the AWS resources created in this learning path**

1. To delete the jobs created in this learning path

   1. Run this command to list the jobs in your AWS account.

      ```
      aws iot list-jobs
      ```

      The command returns a list of the AWS IoT jobs in your AWS account and AWS Region that looks like this.

      ```
      {
          "jobs": [
              {
                  "jobArn": "arn:aws:iot:us-west-2:57EXAMPLE833:job/hello-world-job-2",
                  "jobId": "hello-world-job-2",
                  "targetSelection": "SNAPSHOT",
                  "status": "COMPLETED",
                  "createdAt": "2021-11-16T23:40:36.825000+00:00",
                  "lastUpdatedAt": "2021-11-16T23:40:41.375000+00:00",
                  "completedAt": "2021-11-16T23:40:41.375000+00:00"
              },
              {
                  "jobArn": "arn:aws:iot:us-west-2:57EXAMPLE833:job/hello-world-job-1",
                  "jobId": "hello-world-job-1",
                  "targetSelection": "SNAPSHOT",
                  "status": "COMPLETED",
                  "createdAt": "2021-11-16T23:35:26.381000+00:00",
                  "lastUpdatedAt": "2021-11-16T23:35:29.239000+00:00",
                  "completedAt": "2021-11-16T23:35:29.239000+00:00"
              }
          ]
      }
      ```

   1. For each job that you recognize from the list as a job you created in this learning path, replace `jobId` with the `jobId` value of the job to delete, and then run this command to delete an AWS IoT job.

      ```
      aws iot delete-job --job-id jobId
      ```

      If the command is successful, it returns nothing.

1. To delete the job documents you stored in an Amazon S3 bucket in this learning path.

   1. Replace `bucket` with the name of the bucket you used, and then run this command to list the objects in the Amazon S3 bucket that you used.

      ```
      aws s3api list-objects --bucket bucket
      ```

      The command returns a list of the Amazon S3 objects in bucket that looks like this.

      ```
      {
          "Contents": [
              {
                  "Key": "hello-world-job.json",
                  "LastModified": "2021-11-18T03:02:12+00:00",
                  "ETag": "\"868c8bc3f56b5787964764d4b18ed5ef\"",
                  "Size": 54,
                  "StorageClass": "STANDARD",
                  "Owner": {
                      "DisplayName": "EXAMPLE",
                      "ID": "e9e3d6ec1EXAMPLEf5bfb5e6bd0a2b6ed03884d1ed392a82ad011c144736a4ee"
                  }
              },
              {
                  "Key": "iot_job_firmware_update.json",
                  "LastModified": "2021-04-13T21:57:07+00:00",
                  "ETag": "\"7c68c591949391791ecf625253658c61\"",
                  "Size": 66,
                  "StorageClass": "STANDARD",
                  "Owner": {
                      "DisplayName": "EXAMPLE",
                      "ID": "e9e3d6ec1EXAMPLEf5bfb5e6bd0a2b6ed03884d1ed392a82ad011c144736a4ee"
                  }
              },
              {
                  "Key": "order66.json",
                  "LastModified": "2021-04-13T21:57:07+00:00",
                  "ETag": "\"bca60d5380b88e1a70cc27d321caba72\"",
                  "Size": 29,
                  "StorageClass": "STANDARD",
                  "Owner": {
                      "DisplayName": "EXAMPLE",
                      "ID": "e9e3d6ec1EXAMPLEf5bfb5e6bd0a2b6ed03884d1ed392a82ad011c144736a4ee"
                  }
              }
          ]
      }
      ```

   1. For each object that you recognize from the list as an object you created in this learning path, replace `bucket` with the bucket name and `key` with key value of the object to delete, and then run this command to delete an Amazon S3 object.

      ```
       aws s3api delete-object --bucket bucket --key key
      ```

      If the command is successful, it returns nothing.

After you delete all the AWS resources and objects that you created while completing this learning path, you can start over and repeat the tutorials.