Using shadows in devices
This section describes device communications with shadows using MQTT messages, the preferred method for devices to communicate with the AWS IoT Device Shadow service.
Shadow communications emulate a request/response model using the publish/subscribe
communication model of MQTT. Every shadow action consists of a request topic, a
successful response topic (accepted
), and an error response topic
(rejected
).
If you want apps and services to be able to determine whether a device is connected, see Detecting a device is connected.
Important
Because MQTT uses a publish/subscribe communication model, you should subscribe to the response topics before you publish a request topic. If you don't, you might not receive the response to the request that you publish.
If you use an AWS IoT Device SDK to call the Device Shadow service APIs, this is handled for you.
The examples in this section use an abbreviated form of the topic where the
ShadowTopicPrefix
can refer to either a named or an
unnamed shadow, as described in this table.
Shadows can be named or unnamed (classic). The topics used by each differ only in the topic prefix. This table shows the topic prefix used by each shadow type.
ShadowTopicPrefix value |
Shadow type |
---|---|
$aws/things/ |
Unnamed (classic) shadow |
$aws/things/ |
Named shadow |
Important
Make sure that your app's or service's use of the shadows is consistent and supported by the corresponding implementations in your devices. For example, consider how shadows are created, updated, and deleted. Also consider how updates are handled in the device and the apps or services that access the device through a shadow. Your design should be clear about how the device's state is updated and reported and how your apps and services interact with the device and its shadows.
To create a complete topic, select the
for the type of shadow
to which you want to refer, replace ShadowTopicPrefix
,
and thingName
if applicable, with their
corresponding values, and then append that with the topic stub as shown in the following
table. Remember that topics are case sensitive.shadowName
See Shadow topics for more information about the reserved topics for shadows.
Initializing the device on first connection to AWS IoT
After a device registers with AWS IoT, it should subscribe to these MQTT messages for the shadows that it supports.
Topic | Meaning | Action a device should take when this topic is received |
---|---|---|
|
The |
The actions necessary to accommodate the deleted shadow, such as stop publishing updates. |
|
The |
Respond to the error message in the message body. |
|
The |
The actions necessary to process the state document in the message body. |
|
The |
Respond to the error message in the message body. |
|
The |
Confirm the updated data in the message body matches the device state. |
|
The |
Respond to the error message in the message body. |
|
The shadow document was updated by a request to AWS IoT, and the message body contains the changes requested. |
Update the device's state to match the desired state in the message body. |
|
An update to the shadow was recently completed, and the message body contains the current shadow document. |
Confirm the updated state in the message body matches the device's state. |
After subscribing to the messages in the preceding table for each shadow, the
device should test to see if the shadows that it supports have already been created
by publishing a /get
topic to each shadow. If a
/get/accepted
message is received, the message body contains the
shadow document, which the device can use to initialize its state. If a
/get/rejected
message is received, the shadow should be created by
publishing an /update
message with the current device state.
For example, suppose you have a thing My_IoT_Thing
which doesn't have
any classic or named shadows. If you now publish a /get
request on the
reserved topic $aws/things/My_IoT_Thing/shadow/get
, it returns an error
on the $aws/things/My_IoT_Thing/shadow/get/rejected
topic because the
thing doesn't have any shadows. To resolve this error, first publish an
/update
message by using the
$aws/things/My_IoT_Thing/shadow/update
topic with the current
device state such as the following payload.
{ "state": { "reported": { "welcome": "aws-iot", "color": "yellow" } } }
A classic shadow is now created for the thing and the message is published to the
$aws/things/My_IoT_Thing/shadow/update/accepted
topic. If you publish to
the topic $aws/things/My_IoT_Thing/shadow/get
, it returns a response
to the $aws/things/My_IoT_Thing/shadow/get/accepted
topic with the device
state.
For named shadows, you must first create the named shadow or publish an update
with the shadow name before using the get request. For example, to create a named
shadow namedShadow1
, first publish the device state information to the
topic $aws/things/My_IoT_Thing/shadow/name/namedShadow1/update
. To retrieve
the state information, use the /get
request for the named shadow,
$aws/things/My_IoT_Thing/shadow/name/namedShadow1/get
.
Processing messages while the device is connected to AWS IoT
While a device is connected to AWS IoT, it can receive /update/delta messages and should keep the device state matched to the changes in its shadows by:
-
Reading all /update/delta messages received and synchronizing the device state to match.
-
Publishing an /update message with a
reported
message body that has the device’s current state, whenever the device's state changes.
While a device is connected, it should publish these messages when indicated.
Indication | Topic | Payload |
---|---|---|
The device's state has changed. |
|
A shadow document with the |
The device might not be synchronized with the shadow. |
|
(empty) |
An action on the device indicates that a shadow will no longer be supported by the device, such as when the device is being removed or replaced. |
|
(empty) |
Processing messages when the device reconnects to AWS IoT
When a device with one or more shadows connects to AWS IoT, it should synchronize its state with that of all the shadows that it supports by:
-
Reading all /update/delta messages received and synchronizing the device state to match.
-
Publishing an /update message with a
reported
message body that has the device’s current state.