Amazon Things Graph
Amazon Things Graph
User Guide
AWS IoT Things Graph User Guide
Amazon's trademarks and trade dress may not be used in connection with any product or service that is not
Amazon's, in any manner that is likely to cause confusion among customers, or in any manner that disparages or
discredits Amazon. All other trademarks not owned by Amazon are the property of their respective owners, who may
or may not be affiliated with, connected to, or sponsored by Amazon.
AWS IoT Things Graph User Guide
Table of Contents
What Is AWS IoT Things Graph? ........................................................................................................... 1
Model, Flow, and Mapping .......................................................................................................... 1
How AWS IoT Things Graph Works ............................................................................................... 2
Step 1: Build a Flow ........................................................................................................... 2
Step 2: Create the Flow Configuration .................................................................................. 3
Step 3: Deploy ................................................................................................................... 5
How Do I Get Started? ................................................................................................................ 5
How a Flow Works ..................................................................................................................... 6
How a Flow Configuration Works ................................................................................................. 6
Contents of a Flow Configuration ......................................................................................... 7
How to Create a Flow Configuration ..................................................................................... 8
Namespaces .............................................................................................................................. 8
Getting Started .................................................................................................................................. 9
Getting Started with AWS IoT Things Graph in the Cloud ................................................................ 9
Prepare for Cloud Deployments ........................................................................................... 9
Cloud Flow Examples ........................................................................................................ 10
Getting Started with AWS IoT Things Graph in AWS IoT Greengrass ................................................ 20
Setting Up Your Environment for AWS IoT Greengrass Deployments ....................................... 21
AWS IoT Greengrass Flow Examples .................................................................................... 22
Using the Example Mock Devices ............................................................................................... 52
What the Mock Devices Do ................................................................................................ 52
Motion Sensor ................................................................................................................. 53
Camera ........................................................................................................................... 54
Screen ............................................................................................................................. 54
Adapting the Mock Devices ................................................................................................ 55
Modeling Entities ............................................................................................................................. 57
Modeling by Device Communication Protocol ............................................................................... 57
MQTT ............................................................................................................................. 57
Modbus ........................................................................................................................... 59
MQTT Device Modeling 101 ....................................................................................................... 62
Creating Your Abstract Device Model .................................................................................. 63
Creating Your Device's Capability (Motion Sensor) ................................................................. 64
Creating Your Device's Capability (Camera) .......................................................................... 65
Creating Your Device Definitions ........................................................................................ 66
Modbus Device Modeling 101 .................................................................................................... 68
Creating Your Abstract Device Model .................................................................................. 69
Creating the Definition for Your Device ............................................................................... 72
Service Modeling 101 ............................................................................................................... 73
Modeling an AWS Service .................................................................................................. 74
Modeling an AWS Lambda Function ................................................................................... 77
Creating and Uploading Entities ................................................................................................. 80
Step 1. Define the Entities ................................................................................................. 80
Step 2. Upload the Entity Definitions .................................................................................. 82
Step 3. Associate Devices with Things ................................................................................. 86
Versioning and Entity Modeling ................................................................................................. 88
Uploading Entities ............................................................................................................ 88
Synchronizing with the Public Namespace ........................................................................... 88
Viewing Models and Things in the AWS IoT Things Graph Console .................................................. 88
Models List ...................................................................................................................... 89
Model Details ................................................................................................................... 89
Model Definition .............................................................................................................. 89
Associating Things with Devices ......................................................................................... 90
Creating and Deploying Flows ............................................................................................................ 91
Creating and Deploying Flows (AWS IoT Greengrass) ..................................................................... 91
iii
AWS IoT Things Graph User Guide
iv
AWS IoT Things Graph User Guide
General Deployment Issues with AWS IoT Things Graph .............................................................. 193
Modbus Flow Deployment Issues with AWS IoT Things Graph ....................................................... 194
AWS IoT Things Graph Data Model Reference .................................................................................... 195
What Is the AWS IoT Things Graph Data Model? ......................................................................... 195
GraphQL Syntax ............................................................................................................. 196
AWS IoT Things Graph Data Model and GraphQL ........................................................................ 198
Type ............................................................................................................................. 198
Query ............................................................................................................................ 198
Using Directives .............................................................................................................. 199
Creating a Device with GraphQL ....................................................................................... 201
AWS IoT Things Graph Data Model Core Constructs .................................................................... 202
Built-in Data Types ......................................................................................................... 202
URN ID Scheme .............................................................................................................. 203
Properties ...................................................................................................................... 205
Enum Types ................................................................................................................... 207
Expressions ................................................................................................................... 207
IoT Domain Constructs ............................................................................................................ 209
State ............................................................................................................................. 210
Mapping ........................................................................................................................ 211
Event ............................................................................................................................ 215
Action ........................................................................................................................... 215
Capability ...................................................................................................................... 216
Device Model ................................................................................................................. 216
Device ........................................................................................................................... 217
Service .......................................................................................................................... 219
Workflow ....................................................................................................................... 221
System .......................................................................................................................... 225
Trigger .......................................................................................................................... 226
Deployments .................................................................................................................. 228
Tagging Your AWS IoT Things Graph Resources .................................................................................. 230
Tag Basics .............................................................................................................................. 230
Tag Restrictions and Limitations ....................................................................................... 230
Using Tags with IAM Policies .................................................................................................... 231
AWS CloudFormation Support for AWS IoT Things Graph .................................................................... 233
Create Resources .................................................................................................................... 233
Glossary ........................................................................................................................................ 234
............................................................................................................................................... ccxxxvii
v
AWS IoT Things Graph User Guide
Model, Flow, and Mapping
For example, a home security application can contain cameras, door and window sensors, and motion
sensors from a variety of manufacturers that might not conform to the same IoT standards. As a result,
these cameras and sensors aren't necessarily designed to communicate with each other. The application
builder has to expend significant development effort to translate messages and actions from one device
to another. This drives up software development costs and increases the time to market.
Additionally, the device vendor used might be different for each installation. Each time the device vendor
changes, the development effort needs to be repeated. Customers prefer to have a large catalog of
supported devices so that they can pick the most cost-effective alternative.
Lastly, in many sites, the flow may use web services and run in the cloud. In other sites, the automation
flows need to be deployed on the edge gateways (such as AWS IoT Greengrass). Designing flows that can
run either in the cloud or on edge gateways is difficult. AWS IoT Things Graph manages the interactions
between the devices, ensuring that the necessary transformations take place.
AWS IoT Things Graph can communicate with the different devices and web services and orchestrate
interactions between them through the use of reusable abstractions known as models. Models define the
supported actions and events generated by the devices. They also describe how to invoke those actions
and read the generated events. With AWS IoT Things Graph, application builders need to specify only
the sequence of interactions in their application using models and the corresponding devices and web
services. AWS IoT Things Graph uses the models to identify the protocols, addressing schemes, and data
formats that the different devices use. It does all the necessary translating of messages between the
devices and web services. This enables the flow to execute in the expected order.
AWS IoT Things Graph offers a visual drag-and-drop flow design interface that drastically reduces the
application development time. Application builders can define interactions graphically, and build their
applications using just a few actions. The visual interface includes models that implement conditional
operations such as if-then-else and logical operators such as AND/OR. This enables you to easily
create multistep automation flows. Also, AWS IoT Things Graph enables you to replace devices in the
system with newer versions as they become available, without doing additional work to integrate them
into your application.
Prebuilt Models
The AWS IoT Things Graph console contains prebuilt models for commonly used devices, such as cameras
and motion sensors, and web services, such as Amazon Rekognition and AWS Lambda. Application
builders can also use AWS IoT Things Graph to create their own models for their devices. After you build
an application, you can deploy your it to the AWS Cloud to orchestrate interactions between web services
and devices connected to the AWS IoT cloud. You can also deploy it to an AWS IoT Greengrass-enabled
device to orchestrate interactions between locally connected devices and web services.
1
AWS IoT Things Graph User Guide
How AWS IoT Things Graph Works
Device and service models are representations of the agents that interact in a flow. Device and service
models generically define the attributes, inputs, and outputs of the devices and services that interact
with each other in flows. AWS IoT Things Graph enables you to define device and service interactions
without considering the low-level implementations of devices produced by different manufacturers.
Flow
A flow (or workflow) consists of device models and services. Flows define how the devices and services
interact with each other after a triggering event occurs. A flow lists these interactions as a sequence of
steps. Each step contains an action on a device or web service and the related inputs to and outputs from
that action. The flow defines the logical interactions and orders of execution between the devices and
services.
Mapping
A mapping provides information that enables AWS IoT Things Graph to convert the output message
of one device into the expected format for the next device in the flow. Mappings bridge differences
between the devices and enable them to work together. Mappings enable you to build IoT applications
that use a variety of devices from different manufacturers.
The model library contains models that AWS IoT Things Graph has made publicly available (public
models), and the models that you created (private models). Private models are visible only to you. Define
interactions by connecting the model outputs with appropriate inputs of other models. Choose Publish
to save your flow and publish it to the list of flows that can be deployed.
2
AWS IoT Things Graph User Guide
Step 2: Create the Flow Configuration
• For cloud deployments, specify the flow action ARN. This is the ARN of the IAM role that AWS IoT
Things Graph will use when the flow executes in the cloud.
• For AWS IoT Greengrass deployments, specify the AWS IoT Greengrass group where the application
will run. Also specify the Amazon Simple Storage Service (Amazon S3) bucket to store the application
configuration so that AWS IoT Greengrass can retrieve it when it starts.
Cloud
3
AWS IoT Things Graph User Guide
Step 2: Create the Flow Configuration
Map Things
When you create your flow configuration, select things from your registry that correspond with each
device model in your flow.
4
AWS IoT Things Graph User Guide
Step 3: Deploy
Step 3: Deploy
After you configure your deployment, deploy the application to the cloud or to AWS IoT Greengrass-
enabled devices.
AWS IoT Things Graph packages up the flow and its dependencies and pushes them either to the cloud
or to the AWS IoT Greengrass-enabled device. AWS IoT Things Graph then manages interactions between
locally connected devices.
You define flows by chaining together models and web services. Then you deploy the flow.
For more information about how a flow works, see How a Flow Works. For examples that demonstrate
how this works, see Getting Started with AWS IoT Things Graph.
5
AWS IoT Things Graph User Guide
How a Flow Works
The following diagram shows how an AWS IoT Things Graph flow works when device and flow definitions
are deployed and a flow is ready to run. This is a hypothetical automated door entry workflow for a
building's security system, and is an example of a business process represented as a graph.
In the diagram, the badge reader is defined by Model A, the validation web service by Model B, the
turnstile by Model C, and the camera by Model D. When a valid badge is scanned, the badge reader
triggers an event that causes the next step to execute. This step is a validation web service. The step calls
the validation API in the service. In this way, AWS IoT Things Graph coordinates all of the steps in the
graph.
The nodes in the graph represent things (devices or web services), and the edges represent connections
between pairs of nodes.
Each thing is described by a model (a device definition). The models define each thing as a set of inputs,
outputs, and attributes. Models also expose interfaces for the rest of the application to use. Each step
(node) in a workflow (flow) represents an action for a device, service, or built-in control flow action to
take. A connection between two nodes represents a logical interaction or an order of execution between
two nodes. A flow is one or more steps chained together, and represents business processes.
The following diagram shows the elements of a flow configuration and how they relate to each other.
6
AWS IoT Things Graph User Guide
Contents of a Flow Configuration
Flow
A flow (or workflow) consists of device models and services. Flows define how the devices and services
interact with each other after a triggering event occurs. A flow lists these interactions as a sequence of
steps. Each step contains an action on a device or web service and the related inputs to and outputs from
that action. The flow defines the logical interactions and orders of execution between the devices and
services.
Triggers
Triggers are the events that start flows. Triggers define the conditions (such as an interval of time
passing, a sensor detecting motion, or a change in temperature) that cause a flow to start. You define
7
AWS IoT Things Graph User Guide
How to Create a Flow Configuration
triggers for each flow when you create a flow configuration, so different triggers can start a given flow in
different deployments.
Things
Things are the physical devices used in the flows. When you create a flow configuration, you associate
specific things with the device models used in the flows. For example, if your flow contains a thermostat
device model, your flow configuration will contain a thermostat from your AWS IoT things registry that is
associated with the thermostat device model.
For detailed instructions on how to create and deploy flow configurations using both the AWS CLI and
the AWS IoT Things Graph console, see Creating and Deploying Flows.
Namespaces
A namespace is the repository for entities (for example, models) created using the AWS IoT Things Graph
Data Modeling (TDM) language. These entities are associated with a specific account. The namespace is
part of the URN for each entity.
When you upload TDM entities for the first time, AWS IoT Things Graph creates a namespace for you.
The namespace consists of your AWS Region, your account ID, and a fixed suffix default. The pattern is
REGION/ACCOUNT ID/default. For example, a TDM entity created in the us-west-2 region looks like
this: us-west-2/012345678910/default.
You can extend the path under default to organize your entities. For example, you could place
your device definitions under default/devices and your property definitions under default/
properties.
Currently AWS IoT Things Graph supports only one namespace per account. TDM entities that are stored
in a namespace are Properties, States, Events, Actions, Capabilities, Mappings, Devices, and Services.
There are two kinds of namespaces: public and private. The namespace associated with your account is
private. You create and upload your own entity models inside this namespace. The public namespace is
maintained by AWS and contains the entity definitions that all accounts can access. Private namespaces
track the public namespace, and you can synchronize your private namespace with a specific version of
the public namespace.
8
AWS IoT Things Graph User Guide
Getting Started with AWS IoT Things Graph in the Cloud
Getting Started
This section contains example AWS IoT Things Graph entity models, workflows (flows), and deployment
configurations to get you started with end-to-end development using AWS IoT Things Graph.
When you work with AWS IoT Things Graph, you must deploy the service and all associated AWS and
AWS IoT services (such as AWS IoT Device Management, Amazon Simple Storage Service (Amazon S3)
buckets, and AWS Lambda functions) in the same AWS Region.
Topics
• Getting Started with AWS IoT Things Graph in the Cloud (p. 9)
• Getting Started with AWS IoT Things Graph in AWS IoT Greengrass (p. 20)
• Using the Example Mock Devices (p. 52)
Topics
• Prepare for Cloud Deployments (p. 9)
• Cloud Flow Examples (p. 10)
The role you create should have policies that allow AWS IoT Things Graph to perform all of the actions
in your workflow. Workflows that contain devices or device models that publish and subscribe to MQTT
messages need permission for Iot:Connect, Iot:DescribeEndpoint, and Iot:Publish. The
getting started examples in this section also need permission for Lambda. If you are using any other web
service in your workflows, add the appropriate policies. For sample AWS IoT policies that assign MQTT
publish and subscribe permissions, see Publish/Subscribe Policy Examples.
When you deploy AWS IoT Things Graph flows to the cloud, you need to specify the IAM role that AWS
IoT Things Graph assumes when it executes the flow in the cloud. If your flow uses other services, then
your role must also have the appropriate permissions for those services.
For information about securing AWS resources, see IAM Best Practices. For information about best
practices for attaching policies to IAM roles, see Grant Least Privilege and Get Started Using Permissions
With AWS Managed Policies.
9
AWS IoT Things Graph User Guide
Cloud Flow Examples
This must have a trust relationship with AWS IoT Things Graph. The following instructions describe how
to create this role.
1. In the IAM console (https://console.aws.amazon.com/iam/), choose Roles, and then choose Create
Role.
2. On the Choose the service that will use this role page, choose IoT Things Graph, and then choose
Next: Permissions.
3. On the Attach permissions policies page, choose policies that contain permissions that your flows
require. All flows require read-write permissions to AWS IoT, and the example flows in this section
require read permission to AWS Lambda. Choose Next: Tags.
4. On the Add tags (optional) page, add optional tags that help you categorize your role. Choose Next:
Review.
5. On the Create role page, enter a name for your role. Choose Create role.
After you create this role, copy the role ARN so that you can use it when you create cloud flow
configurations.
Topics
• Creating a Flow in the Cloud with Devices (p. 10)
• Creating a Flow with Devices by Using the AWS CLI (p. 18)
The flow in this example is triggered when the motion sensor detects motion. The motion sensor sends a
message to the camera, which takes a picture and sends it to the screen for display.
Find the code for the mock devices in the CloudMockDevices.zip file. You can run these scripts on any
Linux environment, such as a Raspberry Pi or an Amazon EC2 instance, on which Python 2.7 is installed.
Prerequisites
To create this example, you need the following AWS resources:
• An AWS account
• An IAM role that is configured according to the instructions in Prepare for Cloud Deployments
Create Things
Open the AWS IoT console and create three things: one thing for your motion sensor, and two things for
the camera and screen that are attached to your Raspberry Pi.
10
AWS IoT Things Graph User Guide
Cloud Flow Examples
For instructions on how to create things in the registry, see Register a Device in the Registry. Be sure to
create and activate certificates for each thing.
For more information about AWS IoT concepts, see What is AWS IoT?
If you haven't created and activated certificates for your things, follow the steps in Register a Device
in the Registry. Make sure to attach a policy to each certificate.
1. Open the AWS IoT Things Graph console, and then choose Create flow.
2. Create a flow.
In the Flow configuration pane that appears, name your flow (such as SecurityFlow). Choose
Create flow.
3. Add the device models to the flow.
Search for the MotionSensor device model. Select the device model and drag it into the flow
designer. Do the same for the Camera and Screen device models.
11
AWS IoT Things Graph User Guide
Cloud Flow Examples
In the flow designer, select the edge of the MotionSensor device model and connect it to the
Camera device model. Also connect the Camera device model to the Screen device model.
In the trigger editor that appears in the right pane, for Condition, choose StateChanged. For Action,
choose ThingsGraph.startFlow.
6. Update the camera device action.
Choose Publish at the upper right of the page. This creates the flow and adds it to the list of flows
that can be deployed.
12
AWS IoT Things Graph User Guide
Cloud Flow Examples
On the Things page, choose the motion sensor thing that you created earlier. Then choose Associate
with device.
2. On the Select device model page, choose HCSR501MotionSensor. Choose Associate. This step
associates the HCSR501MotionSensor motion sensor thing in your registry with the motion sensor
device model in your flow. The HCSR501MotionSensor device implements the capability of the
motion sensor device model.
13
AWS IoT Things Graph User Guide
Cloud Flow Examples
3. After you return to the Select device model page, refresh the page to verify that the motion sensor
thing is associated with the HCSR501MotionSensor device. Repeat the previous two steps for the
RaspberryPiCamera and RaspberryPiScreen devices.
Select the menu icon at the upper left of the page, and then choose Flows to return to the
Flows page. Select the box next to the flow that you just created, and then choose Create flow
configuration.
A flow configuration contains the details that are specific to a single deployment. On the Describe
flow configuration page, select your flow and enter a flow configuration name. The flow
configuration name can't contain spaces.
On the Configure target page, enter the ARN of the role that you created in Prepare for Cloud
Deployments. Choose Next.
14
AWS IoT Things Graph User Guide
Cloud Flow Examples
The Map Things page provides an interface for selecting the specific things to include in your
deployment. The menus under each device model in your deployment contain all of the things that
you associated with the device model. Because you're getting started, the menus for each device on
this page will include only one thing (the thing that you've associated with each device model).
On the Map Things page, from the menu under the motionSensor device model, select the motion
sensor thing that you created earlier. Select the camera and screen things for the Camera and
Screen device models. Choose Next.
5. View the trigger.
On the Set up triggers page, the GraphQL that defines the motion event trigger appears in the
editor. This GraphQL specifies the event that triggers the flow. When the motion sensor detects a
person moving, the ThingsGraph.startFlow function initiates the flow. You don't need to edit
this code.
Choose Review.
15
AWS IoT Things Graph User Guide
Cloud Flow Examples
On the Review and create page, review the information you entered for your flow configuration.
Then choose Create.
When the Flow configuration created message appears, choose Deploy now.
Refresh the Deployments page to verify that the flow has deployed. After a successful deployment,
the Deployments page displays Deployed in target in the Status column.
To find this endpoint, open the AWS IoT console (https://console.aws.amazon.com/iot/), and then
choose Settings. You can also find the endpoint by using the aws iot describe-endpoint AWS CLI
command.
16
AWS IoT Things Graph User Guide
Cloud Flow Examples
If you're using an Amazon Trust Services (ATS) root CA, use the following AWS CLI command to find your
custom endpoint. For more information about certificates and ATS endpoints, see X.509 Certificates and
AWS IoT.
Follow these steps to run all three Python scripts and observe the mock devices interacting in the flow.
1. Open three terminal sessions on your Linux environment. In one terminal, navigate to the ms
directory. To run the ms.py script, run the following command.
python cloudms.py -e custom endpoint -r root CA file path -c certificate file path -
k private key file path -n motion sensor thing name
After the script starts running, it displays the following output every 10 seconds. This indicates that
the mock motion sensor has detected motion.
2. In the second terminal, navigate to the camera directory. Run the camera.py script by using the
following command.
python cloudcamera.py -e custom endpoint -r root CA file path -c certificate file path
-k private key file path -n camera thing name
After the script starts running, it displays the following output every 10 seconds. This indicates that
the motion sensor trigger has prompted the mock camera to capture an image and publish it to the
/capture/finished MQTT topic.
3. In the third terminal, navigate to the screen directory. Run the screen.py script by using the
following command.
python cloudscreen.py -e custom endpoint -r root CA file path -c certificate file path
-k private key file path -n screen thing name
After the script starts running, it displays the following output every 10 seconds. This indicates that
the mock screen has received the image from the mock camera.
17
AWS IoT Things Graph User Guide
Cloud Flow Examples
1. The following AWS IoT Things Graph Data Model (TDM) code contains the definition of the flow used
in this example.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID.
{
query SecurityFlow($camera: string!, $screen: string!) @workflowType(id:
\"urn:tdm:REGION/ACCOUNT ID/default:Workflow:SecurityFlow\") {
variables {
cameraResult @property(id: \"urn:tdm:aws/examples:property:CameraStateProperty\")
}
steps {
step(name: \"Camera\", outEvent: [\"cameraStepDone\"]) {
DeviceActivity(deviceModel: \"urn:tdm:aws/examples:deviceModel:Camera\", out:
\"cameraResult\", deviceId: \"${camera}\") {
capture
}
}
step(name: \"Screen\", inEvent: [\"cameraStepDone\"]) {
DeviceActivity(deviceModel: \"urn:tdm:aws/examples:deviceModel:Screen\",
deviceId: \"${screen}\") {
display(imageUrl: \"${cameraResult.lastClickedImage}\")
}
}
}
}
}
2. Enter the following command to create the flow. This command assumes that you're working in a
Linux or Unix environment. For other environments, use the equivalent of the cat utility.
18
AWS IoT Things Graph User Guide
Cloud Flow Examples
3. The following TDM code contains the definition of the system used in this example. The console
creates this system for you.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID.
{
type SecurityFlow @systemType(id: \"urn:tdm:REGION/ACCOUNT ID/
default:System:SecurityFlow\", description: \"Home Security System\") {
motionSensor: Device @thing(id: \"urn:tdm:aws/examples:deviceModel:MotionSensor\")
camera: Device @thing(id: \"urn:tdm:aws/examples:deviceModel:Camera\")
screen: Device @thing(id: \"urn:tdm:aws/examples:deviceModel:Screen\")
SecurityFlow: Flow @workflow(id: \"urn:tdm:REGION/ACCOUNT ID/
default:Workflow:SecurityFlow\")
}
}
5. Enter the following commands to associate the things you created in your registry with the device
models used in the flow.
Replace the MotionSensorName, CameraName, and ScreenName placeholders with the names of
the things you created earlier.
6. The following TDM code contains the definition of the flow configuration used in this example.
The TDM definition is inside the definition object. For more information, see Creating Flow
Configurations.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID. Replace the MotionSensorName, ScreenName, and CameraName placeholders with
the names of the things you created earlier.
{
query Room215 @deployment(id: \"urn:tdm:REGION/ACCOUNT ID/default:Deployment:Room215\",
systemId: \"urn:tdm:REGION/ACCOUNT ID/default:System:SecurityFlow\") {
motionSensor(deviceId: \"MotionSensorName\")
screen(deviceId: \"ScreenName\")
camera(deviceId: \"CameraName\")
triggers {MotionEventTrigger(description: \"a trigger\") {
condition(expr: \"devices[name == 'motionSensor'].events[name ==
'StateChanged'].lastEvent\")
action(expr: \"ThingsGraph.startFlow('SecurityFlow', bindings[name ==
'camera'].deviceId, bindings[name == 'screen'].deviceId)\")
19
AWS IoT Things Graph User Guide
Getting Started with AWS IoT
Things Graph in AWS IoT Greengrass
}
}
}
}
Replace ROLE ARN with the IAM role ARN that you created in Prepare for Cloud Deployments.
When the operation completes, the AWS CLI returns the following deployment summary as a JSON
object. Use the id value in the summary block as the TDM URN of the flow configuration.
{
"summary": {
"status": "PENDING_DEPLOYMENT",
"greengrassGroupName": "",
"target": "CLOUD",
"arn": "arn:aws:iotthingsgraph:REGION:ACCOUNT ID:default#Deployment#Room215",
"updatedAt": 1555021747.176,
"id": "urn:tdm:REGION/ACCOUNT ID/default:Deployment:Room215",
"createdAt": 1555021747.176
}
}
8. Enter the following command to deploy the flow configuration to your AWS IoT Greengrass group.
Use the TDM URN value returned in the previous step as the value of the id parameter.
9. To verify the deployment, follow the steps in Run the Flow with Mock Devices (p. 16).
Topics
• Setting Up Your Environment for AWS IoT Greengrass Deployments (p. 21)
• AWS IoT Greengrass Flow Examples (p. 22)
20
AWS IoT Things Graph User Guide
Setting Up Your Environment for
AWS IoT Greengrass Deployments
Before you get started, make sure that you have an AWS account.
To perform the tasks related to setting up your AWS IoT Greengrass core, you need a Mac, Windows, or
Linux or Unix system. The setup instructions in Getting Started with AWS IoT Greengrass recommend
that you start with a Raspberry Pi.
Follow the instructions in Deploy Cloud Configurations to an AWS IoT Greengrass Core Device to
start AWS IoT Greengrass.
3. Create a directory named thingsgraph at the root directory of your AWS IoT Greengrass core
device. AWS IoT Things Graph installs files in this location. This directory must have read, write, and
execute permissions for ggc_user. If your AWS IoT Greengrass core is using a Unix-like operating
system, set these permissions by entering the following commands at a command prompt.
For example, a flow that needs to read and write to an Amazon S3 bucket needs to have the
AmazonS3FullAccess policy attached to it.
5. When AWS IoT Things Graph installs a flow to your AWS IoT Greengrass core, it first uploads a file
that contains all of the flow's dependencies to an Amazon S3 bucket. It then installs the flow and its
dependencies from the bucket. This means that the AWS IoT Greengrass service needs permission to
access this bucket.
In the IAM console (https://console.aws.amazon.com/iam/), choose Roles. Select the role named
Greengrass_ServiceRole, and attach the AmazonS3FullAccess policy to give it access to your S3
bucket.
Install Java
To run AWS IoT Things Graph, your AWS IoT Greengrass core device needs to have Java 8 installed.
21
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
If you're using a Linux environment, follow these steps to install the correct version of Java. See the Java
website for instructions on installing Java 8 on Windows and Mac environments.
Topics
• Creating a Flow in an AWS IoT Greengrass Group with Devices (p. 22)
• Creating a Flow with Lambda Functions (p. 32)
• Creating a Flow with Devices and a Service (p. 37)
• Creating a Flow with Devices by Using the AWS CLI (p. 44)
• Creating a Flow with Lambda Functions by Using the AWS CLI (p. 46)
• Creating a Flow with Devices and a Service by Using the CLI (p. 49)
The flow in this example is triggered when the motion sensor detects motion. The motion sensor sends a
message to the camera, which takes a picture and sends it to the screen for display.
If you don't want to buy the devices used in this example, you can run three Python scripts that mimic
the functions of the devices. This topic shows you how to run the flow with both the real and mock
devices.
Find the code for the mock devices in the MockDevices.zip file. You can run these scripts on any Linux
environment, such as a Raspberry Pi or an Amazon EC2 instance, on which Python 2.7 is installed.
Prerequisites
To create this example, you need the following AWS resources:
• An AWS account
• An Amazon S3 bucket
To create this example with real devices, you need the following hardware resources:
22
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
Now you've configured your Raspberry Pi to communicate with the motion sensor, camera, and screen.
If you're creating this example with real devices, install AWS IoT Greengrass on the same Raspberry Pi to
which you attached your motion sensor, camera, and screen.
If you're using mock devices, install AWS IoT Greengrass on the same Linux environment where you run
the Python scripts.
Perform the steps in Setting Up Your Environment on the appropriate device or computer. Make sure
that you've created an IAM role for AWS IoT Greengrass (step 4 in the Create an AWS IoT Greengrass
Group procedure in that topic). Attach the AmazonS3FullAccess policy to give it access to your S3
bucket.
Note
The AWS IoT Greengrass group and Amazon S3 bucket that you use in this example must be
created in the same AWS Region. The AWS IoT Things Graph entities that you create must also
be in the same Region as these resources.
Create Things
Open the AWS IoT console and create three things: one thing for your motion sensor, and two things for
the camera and screen that are attached to your Raspberry Pi.
For instructions on how to create things in the registry, see Register a Device in the Registry. Be sure to
create and activate certificates for each thing.
In the AWS IoT console, on the Greengrass tab, select your group, choose Devices, and then add the
three new things to your AWS IoT Greengrass group.
For more information about AWS IoT concepts, see What is AWS IoT?
If you're creating this example with real devices, skip ahead to Create and Deploy the Flow (p. 27).
23
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
1. To download and decompress the AWS IoT Greengrass Core SDK, follow the steps in Create and
Package a Lambda Function. (Choose the Unix-like system tab on the step for decompressing the
greengrass-core-python-sdk-1.3.0.tar.g file.)
You don't need to create the greengrassHelloWorld AWS Lambda function. Stop when you've
extracted the python_sdk_1_3_0.zip file.
2. Download and extract the MockDevices.zip file. The extracted directory contains three files named
ms.py, camera.py, and screen.py.
3. Create folders named ms, camera, and screen.
4. Copy the ms.py file into the ms directory, the camera.py file into the camera directory, and the
screen.py file into the screen directory.
5. Copy the greengrasssdk directory (in sdk\python_sdk_1_3_0) into each of the mock device
directories that you created.
6. Copy the certificate and private key for each of the three things that you created into the
appropriate directory on your Linux environment. Also copy the root certificate authority (CA) for
AWS IoT into each directory. For example, the motion sensor certificate and private key should be in
the ms directory, with the root CA for AWS IoT and the ms.py file.
If you haven't created and activated certificates for your things, follow the steps in Register a Device
in the Registry. Make sure to attach a policy to each certificate.
1. Open the AWS IoT Things Graph console, and then choose Create flow.
2. Create a flow.
In the Flow configuration pane that appears, name your flow (such as SecurityFlow). Choose
Create flow.
3. Add the device models to the flow.
Search for the MotionSensor device mode. Select the device model and drag it into the flow
designer. Do the same for the Camera and Screen device models.
24
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
In the flow designer, select the edge of the MotionSensor device model and connect it to the
Camera device model. Also connect the Camera device model to the Screen device model.
In the trigger editor that appears in the right pane, for Condition, choose StateChanged. For Action,
choose ThingsGraph.startFlow.
6. Update the camera device modle action.
Choose Publish at the upper right of the page. This creates the flow and adds it to the list of flows
that can be deployed.
25
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
On the Things page, choose the motion sensor thing that you created earlier. Then choose Associate
with device.
2. On the Select device model page, choose HCSR501MotionSensor. Choose Associate. This step
associates the HCSR501MotionSensor motion sensor thing in your registry with the motion sensor
device model in your flow. The HCSR501MotionSensor device implements the capability of the
motion sensor device model.
26
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
3. After you return to the Select device model page, refresh the page to verify that the motion sensor
thing is associate with the HCSR501MotionSensor device. Repeat the previous two steps for the
RaspberryPiCamera and RaspberryPiScreen devices.
Select the menu icon at the upper left of the page, and then choose Flows to return to the
Flows page. Select the box next to the flow that you just created, and then choose Create flow
configuration.
A flow configuration contains the details that are specific to a single deployment. On the Describe
flow configuration page, select your flow and enter a flow configuration name. The flow
configuration name can't contain spaces.
On the Configure target page, enter the name of your Amazon S3 bucket and the AWS IoT
Greengrass group to which your AWS IoT Greengrass core device belongs. Amazon S3 buckets are
globally unique, so your bucket name will be different from the one in the following screen shot.
Choose Next.
27
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
The Map Things page provides an interface for selecting the specific things to include in your
deployment. The menus under each device model in your deployment contain all of the things that
you associated with the device model. Because you're getting started, the menus for each device
model on this page will include only one thing (the thing that you've associated with each device
model).
On the Map Things page, for motionSensor, select the motion sensor thing that you created earlier.
Select the screen and camera things for the Camera and Screen device models. Choose Next.
5. View the trigger.
On the Set up triggers page, the GraphQL that defines the motion event trigger appears in the
editor. This GraphQL specifies the event that triggers the flow. When the motion sensor detects a
person moving, the ThingsGraph.startFlow function initiates the flow. You don't need to edit
this code.
Choose Review.
28
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
On the Review and create page, review the information you entered for your flow configuration.
Choose Create.
7. Deploy.
When the Flow configuration created message appears, choose Deploy now.
Refresh the Deployments page to verify that the flow has deployed. After a successful deployment,
the Deployments page displays Deployed in target in the Status column.
Turn on your Raspberry Pi, motion sensor, camera, and screen. Position the motion sensor and camera so
that they are directly in front of you. Wave your hand over the motion sensor. The camera takes a picture
of you and displays it on the screen.
29
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
To find this endpoint, open the AWS IoT console (https://console.aws.amazon.com/iot/), and then
choose Settings. You can also find the endpoint by using the aws iot describe-endpoint AWS CLI
command.
If you're using an Amazon Trust Services (ATS) root CA, use the following AWS CLI command to find your
custom endpoint. For more information about certificates and ATS endpoints, see X.509 Certificates and
AWS IoT.
30
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
Follow these steps to run all three Python scripts and observe the mock devices interacting in the flow.
1. Open three terminal sessions on your Linux environment. In one terminal, navigate to the ms
directory. To run the ms.py script, run the following command.
python ms.py -e custom endpoint -r root CA file path -c certificate file path -
k private key file path -n motion sensor thing name
After the script starts running, it displays the following output every 10 seconds. This indicates that
the mock motion sensor has detected motion.
2. In the second terminal, navigate to the camera directory. Run the camera.py script by using the
following command.
python camera.py -e custom endpoint -r root CA file path -c certificate file path -
k private key file path -n camera thing name
After the script starts running, it displays the following output every 10 seconds. This indicates that
the motion sensor trigger has prompted the mock camera to capture an image and publish it to the
/capture/finished MQTT topic.
3. In the third terminal, navigate to the screen directory. Run the screen.py script by using the
following command.
python screen.py -e custom endpoint -r root CA file path -c certificate file path -
k private key file path -n screen thing name
After the script starts running, it displays the following output every 10 seconds. This indicates that
the mock screen has received the image from the mock camera.
31
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
The flow runs every 60 seconds and calls three service models: one that reads data from an Amazon
Simple Storage Service (Amazon S3) bucket, one that analyzes the data, and one that saves the results of
the analysis to the Amazon S3 bucket.
Prerequisites
To create this example, you need the following resources.
Note
You must create the AWS IoT Greengrass group and Amazon S3 bucket in the same AWS Region.
The AWS IoT Things Graph entities that you create must also be in the same Region as these
resources.
• An AWS account.
• An AWS IoT Greengrass core, version 1.7 or later.
• An AWS IoT Greengrass group.
• Node.js installed on your AWS IoT Greengrass core device.
• An Amazon S3 bucket that contains a file named HelloWorld.txt.
• An AWS IoT Greengrass IAM role that has access to your S3 bucket.
Add this role to your AWS IoT Greengrass group. For information about how to configure IAM roles for
AWS IoT Greengrass, see Configure IAM Roles.
• A Lambda IAM role that has access to your S3 bucket.
Perform the steps in Setting Up Your Environment. Make sure that you've created an IAM role for AWS
IoT Greengrass (step 4 in the Create an AWS IoT Greengrass Group procedure in that topic). Attach the
AmazonS3FullAccess policy to give it access to your S3 bucket.
On the Settings page of your group, make sure that Greengrass container is selected under Lambda
runtime environment.
1. Follow the instructions in Create a Simple Lambda Function to create three Lambda functions
named GetS3Object, WordCount, and SaveToS3.
Note
The sample won't work if you use any other function names.
2. The code for these functions is in the Lambdas.zip file. Don't add any triggers. Choose Node.js
6.10 as your runtime. Use an IAM role that has read/write access to your Amazon S3 bucket.
In the SaveToS3 function, replace the value of bucket with the name of your S3 bucket.
Each Lambda function is a service model in the flow. Copy the Lambda Amazon Resource Names
(ARNs) so that you can use them in your service model definitions.
32
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
3. After you copy and save the functions in the Lambda console, on the Actions menu, choose
Publish new version. You must use version 1 for each Lambda function.
2. Deploy the Lambda functions to AWS IoT Greengrass.
To do this, follow the instructions in Configure the Lambda Function for AWS IoT Greengrass.
2. Create a flow.
In the Flow configuration pane that appears, enter a name for your flow. Choose Create flow.
3. Add the service models to the flow.
On the Logic tab, choose Clock, and then drag it into the flow designer.
On the Service tab, search for the getS3Lambda service model. Choose the service model and
drag it into the flow designer. Do the same for the wordCountLambda and saveResponseLambda
service models.
In the flow designer, select the edge of the ClockTrigger service model and connect it to
the getS3Lambda service model. Then connect the getS3Lambda, wordCountLambda, and
saveResponseLambda service models in the same way.
33
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
In the trigger editor that appears in the right pane, for Frequency, enter 60, and then select seconds
from the menu on the right. For Action, choose ThingsGraph.startFlow.
6. Add the getS3Lambda service model action.
a. In the flow designer, choose the getS3Lambda service model. In the action editor that
appears in the right pane, select No action configured. In the list that appears, select
getS3ObjectAsString.
b. Expand Inputs. Choose Define Input, and then enter the names of your Amazon S3 bucket and
file as the values for bucket and key.
c. Expand Output, and then enter getS3LambdaResult.
7. Add the wordCountLambda service model action.
a. In the flow designer, select the wordCountLambda service model. In the action
editor that appears in the right pane, choose No action configured. For Action box,
choose wordCount. Expand Inputs, choose Define Input, and then for message, enter
${getS3LambdaResult.message}.
b. Expand Output, and then enter wordCountLambdaResult.
8. Add the saveResponseLambda service model action.
Choose Publish at the upper right of the page. This creates the flow and adds it to the list of flows
that can be deployed.
On the Describe flow configuration page, select your flow and enter a flow configuration name. The
flow configuration name can't contain spaces. Choose Greengrass, and then choose Next.
3. Configure the target.
34
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
On the Configure target page, enter the name of your Amazon S3 bucket and the AWS IoT
Greengrass group to which your AWS IoT Greengrass core device belongs. Amazon S3 buckets are
globally unique, so your bucket name will be different from the one in the following screen shot.
Choose Next.
4. Select things.
This example contains only service models, so you don't have to select any things to use in the flow.
Choose Next.
5. View the trigger.
On the Define trigger page, the following GraphQL appears in the editor. This GraphQL specifies the
time intervals at which the flow runs. This flow runs every 60 seconds. You don't need to edit this
code.
Choose Review.
35
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
On the Review and create page, review the information you entered for your flow configuration.
Choose Create.
7. Deploy.
When the Flow configuration created message appears, choose Deploy now.
Refresh the Deployments page to verify that the flow has deployed. After a successful deployment,
the Deployments page displays Deployed in target in the Status column.
36
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
The flow is triggered when the motion detector detects a person moving. The motion detector sends a
message to the camera, which takes a picture and sends it to the Amazon Rekognition service model. The
service model sends the image to display to the screen. The service model doesn't process the results of
the DetectFaces API or send anything other than the image to the screen.
You can modify this example by adding a service model between the Amazon Rekognition service and
the screen. The additional service model can process the results (such as determining whether the image
should be displayed on the screen) before sending the image to the screen.
Prerequisites
To create this example, you need the following resources:
• An AWS account
• A Raspberry Pi running AWS IoT Greengrass version 1.7 or later
• An Aukru HC-SR501 motion sensor
• A Raspberry Pi 7" touchscreen display
• A Raspberry Pi camera module v2-8 megapixel,1080p
• An Amazon S3 bucket
Now you've configured your Raspberry Pi to communicate with the motion sensor, camera, and screen.
Install AWS IoT Greengrass on the same Raspberry Pi to which you attached your motion sensor, camera,
and screen.
Perform the steps in Setting Up Your Environment on your Raspberry Pi. Make sure that you've created
an IAM role for AWS IoT Greengrass (step 4 in the Create an AWS IoT Greengrass group procedure in
that topic). Attach the AmazonS3FullAccess policy to give it access to your S3 bucket.
37
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
Note
The AWS IoT Greengrass group and Amazon S3 bucket that you use in this example must be
created in the same AWS Region. The AWS IoT Things Graph entities that you create must also
be in the same Region as these resources.
Create Things
Open the AWS IoT console and create three things: one thing for your motion sensor, and two things for
the camera and screen that are attached to your Raspberry Pi.
For instructions on how to create things in the registry, see Register a Device in the Registry.
On the Greengrass tab in the AWS IoT console, choose your group, choose Devices, and then add the
three new things to your AWS IoT Greengrass group.
For general information about AWS IoT concepts, see What is AWS IoT?
2. Create a flow.
In the Flow configuration pane that appears, name your flow (such as RekognitionFlow). Choose
Create flow.
3. Add the device models and service model to the flow.
1. Search for the MotionSensor device model. Select the device and drag it into the flow designer.
2. Search for the CameraRkgnExample device model. Select the device model and drag it into the
flow designer.
3. On the Services tab, search for the Rekognition service model. Select the service model and drag
it into the flow designer.
4. On the Devices tab, do the same for the Screen device model.
38
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
In the flow designer, select the edge of the MotionSensor device model and connect it to the
CameraRkgnExample device model. Then connect the CameraRkgnExample device model,
Rekognition service model, and the Screen device model in the same way.
In the trigger editor that appears in the right pane, for Condition, choose StateChanged. For Action,
choose ThingsGraph.startFlow.
6. Update the camera device model action.
Choose Publish at the upper right of the page. This creates the flow and adds it to the list of flows
that can be deployed.
Select the menu icon at the upper left of the page. Then choose Things.
39
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
On the Things page, select the motion sensor thing that you created earlier. Then choose Associate
with device.
2. On the Select device model page, choose HCSR501MotionSensor. Choose Associate. This step
associates the HCSR501MotionSensor motion sensor thing in your registry with the motion sensor
device model in your flow. The HCSR501MotionSensor device implements the capability of the
motion sensor device model.
40
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
3. After you return to the Select device model page, refresh the page to verify that the motion sensor
thing is associate with the HCSR501MotionSensor device. Repeat the previous two steps for the
RaspberryPiCameraRkgnExample and RaspberryPiScreen devices.
Select the menu icon at the upper left of the page, and then select Flows to return to the Flows
page. On the Flows page, select the box next to the flow that you just created, and then choose
Create flow configuration.
On the Describe flow configuration page, select your flow, and then enter a flow configuration
name. The flow configuration name can't contain spaces. Choose Greengrass, and then choose Next.
3. Configure the target.
On the Configure target page, enter the name of your Amazon S3 bucket and the AWS IoT
Greengrass group to which your AWS IoT Greengrass core device belongs. Amazon S3 buckets are
globally unique, so your bucket name will be different from the one in the following screen shot.
Choose Next.
41
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
The Map Things page provides an interface for selecting the specific things that you'll include in
your deployment. The menus under each device model in your deployment contain all of the things
that you associated with the device model. Because you're getting started, the menus for each
device model on this page will include only one thing (the thing that you've associated with each
device model).
On the Map Things page, for motionSensor, select the motion sensor thing that you created earlier.
Select the camera and screen things for the Camera and Screen device models. Choose Next.
5. View the trigger.
On the Define trigger page, the GraphQL that defines the motion event trigger for the flow appears
in the editor. When the motion sensor detects motion, the ThingsGraph.startFlow function
initiates the flow. You don't need to edit this code.
Choose Review.
42
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
On the Review and create page, review the information you entered for your flow configuration.
Choose Create.
7. Deploy.
When the Flow configuration created message appears, choose Deploy now.
Refresh the Deployments page to verify that the flow has deployed. After a successful deployment,
the Deployments page displays Deployed in target in the Status column.
43
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
1. The following AWS IoT Things Graph Data Model (TDM) code contains the definition of the flow used
in this example.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID.
{
query SecurityFlow($camera: string!, $screen: string!) @workflowType(id:
\"urn:tdm:REGION/ACCOUNT ID/default:Workflow:SecurityFlow\") {
variables {
cameraResult @property(id: \"urn:tdm:aws/examples:property:CameraStateProperty\")
}
steps {
step(name: \"Camera\", outEvent: [\"cameraStepDone\"]) {
DeviceActivity(deviceModel: \"urn:tdm:aws/examples:deviceModel:Camera\", out:
\"cameraResult\", deviceId: \"${camera}\") {
capture
}
}
step(name: \"Screen\", inEvent: [\"cameraStepDone\"]) {
DeviceActivity(deviceModel: \"urn:tdm:aws/examples:deviceModel:Screen\",
deviceId: \"${screen}\") {
display(imageUrl: \"${cameraResult.lastClickedImage}\")
}
}
}
}
}
2. Enter the following command to create the flow. This command assumes that you're working in a
Linux or Unix environment. For other environments, use the equivalent of the cat utility.
44
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
3. The following TDM code contains the definition of the system used in this example. The console
creates this system for you.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID.
{
type SecurityFlow @systemType(id: \"urn:tdm:REGION/ACCOUNT ID/
default:System:SecurityFlow\", description: \"Home Security System\") {
motionSensor: Device @thing(id: \"urn:tdm:aws/examples:deviceModel:MotionSensor\")
camera: Device @thing(id: \"urn:tdm:aws/examples:deviceModel:Camera\")
screen: Device @thing(id: \"urn:tdm:aws/examples:deviceModel:Screen\")
SecurityFlow: Flow @workflow(id: \"urn:tdm:REGION/ACCOUNT ID/
default:Workflow:SecurityFlow\")
}
}
5. Enter the following commands to associate the things you created in your registry with the device
models used in the flow.
Replace the MotionSensorName, CameraName, and ScreenName placeholders with the names of
the things you created earlier.
6. The following TDM code contains the definition of the flow configuration used in this example.
The TDM definition is inside the definition object. For more information, see Creating Flow
Configurations.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID. Replace the MotionSensorName, ScreenName, and CameraName placeholders with
the names of the things you created earlier.
{
query Room215 @deployment(id: \"urn:tdm:REGION/ACCOUNT ID/default:Deployment:Room215\",
systemId: \"urn:tdm:REGION/ACCOUNT ID/default:System:SecurityFlow\") {
motionSensor(deviceId: \"MotionSensorName\")
screen(deviceId: \"ScreenName\")
camera(deviceId: \"CameraName\")
triggers {MotionEventTrigger(description: \"a trigger\") {
condition(expr: \"devices[name == 'motionSensor'].events[name ==
'StateChanged'].lastEvent\")
action(expr: \"ThingsGraph.startFlow('SecurityFlow', bindings[name ==
'camera'].deviceId, bindings[name == 'screen'].deviceId)\")
45
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
}
}
}
}
Replace the GREENGRASS GROUP and S3 BUCKET with the names of your AWS IoT Greengrass
group and Amazon S3 bucket.
When the operation completes, the AWS CLI returns the following deployment summary as a JSON
object. Use the id value in the summary block as the TDM URN of the flow configuration.
{
"summary": {
"status": "PENDING_DEPLOYMENT",
"greengrassGroupName": "ThingsGraphGrnGr",
"target": "GREENGRASS",
"arn": "arn:aws:iotthingsgraph:REGION:ACCOUNT ID:default#Deployment#Room215",
"updatedAt": 1555021747.176,
"id": "urn:tdm:REGION/ACCOUNT ID/default:Deployment:Room215",
"createdAt": 1555021747.176
}
}
8. Enter the following command to deploy the flow configuration to your AWS IoT Greengrass group.
Use the TDM URN value returned in the previous step as the value of the id parameter.
9. To verify the deployment, follow the steps in either Run the Flow with Real Devices (p. 29) or Run
the Flow with Mock Devices (p. 30).
46
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
1. The following AWS IoT Things Graph Data Model (TDM) code contains the definition of the flow used
in this example.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID. Replace the S3 BUCKET IN SaveToS3 placeholder with the name of the Amazon
S3 bucket that you're using in the SaveToS3 Lambda function.
{
query TextProcessing @workflowType(id: \"urn:tdm:REGION/ACCOUNT ID/
default:Workflow:TextProcessing\") {
variables {
getS3LambdaResult @property(id: \"urn:tdm:aws/
examples:property:getS3ObjectAsStringResponse\")
wordCountLambdaResult @property(id: \"urn:tdm:aws/
examples:property:wordCountResponse\")
}
steps {
step(name: \"getS3Lambda", outEvent: [\"getS3LambdaDone\"]) {
WebserviceActivity(webservice: \"urn:tdm:aws/examples:Service:getS3Lambda\", out:
\"getS3LambdaResult\") {
getS3ObjectAsString(bucket: \"S3 BUCKET IN SaveToS3\", key: \"HelloWorld.txt\")
}
}
step(name: \"wordCountLambda", inEvent: [\"getS3LambdaDone\"], outEvent:
[\"wordCoundLambdaDone\"]) {
WebserviceActivity(webservice: \"urn:tdm:aws/examples:Service:wordCountLambda\",
out: \"wordCountLambdaResult\") {
wordCount(message: \"${getS3LambdaResult.message}\")
}
}
step(name: \"saveResponseLambda\", inEvent: [\"wordCoundLambdaDone\"]) {
WebserviceActivity(webservice: \"urn:tdm:aws/examples:Service:saveResponseLambda
\") {
save(response: \"${wordCountLambdaResult}\")
}
}
}
}
}
2. Enter the following command to create the flow. This command assumes that you're working in a
Linux or Unix environment. For other environments, use the equivalent of the cat utility.
3. The following TDM code contains the definition of the system used in this example. Because the flow
contains no devices or device models, this system contains only the flow.
47
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID.
{
type TextProcessing @systemType(id: \"urn:tdm:REGION/ACCOUNT ID/
default:System:TextProcessing", description: \"Text processing system\") {
TextProcessing: Flow @workflow(id: \"urn:tdm:REGION/ACCOUNT ID/
default:Workflow:TextProcessing\")
}
}
5. The following TDM code contains the definition of the flow configuration used in this example.
The TDM definition is inside the definition object. For more information, see Creating Flow
Configurations.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID.
{
query LambdaDeployment @deployment(id: \"urn:tdm:REGION/ACCOUNT ID/
default:Deployment:LambdaDeployment\", systemId: \"urn:tdm:REGION/ACCOUNT ID/
default:System:TextProcessing\") {
triggers {
TimeTrigger(description: \"Time based trigger\") {
condition(expr: \"every 60 seconds\")
action(expr: \"ThingsGraph.startFlow('TextProcessing')\")
}
}
}
}
6. Enter the following command to create the flow configuration. Replace GREENGRASS GROUP and S3
BUCKET with the names of your AWS IoT Greengrass group and Amazon S3 bucket.
When the operation completes, the AWS CLI returns the following deployment summary as a JSON
object. Use the id value in the summary block as the TDM URN of the flow configuration.
{
"summary": {
"status": "PENDING_DEPLOYMENT",
"greengrassGroupName": "ThingsGraphGrnGr",
48
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
"target": "GREENGRASS",
"arn": "arn:aws:iotthingsgraph:REGION:ACCOUNT
ID:default#Deployment#LambdaDeployment",
"updatedAt": 1555022420.184,
"id": "urn:tdm:REGION/ACCOUNT ID/default:Deployment:LambdaDeployment",
"createdAt": 1555022420.184
}
}
7. Enter the following command to deploy the flow configuration to your AWS IoT Greengrass group.
Use the TDM URN value returned in the previous step as the value of the id parameter.
1. The following AWS IoT Things Graph Data Model (TDM) code contains the definition of the flow used
in this example. Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with
your AWS Region and account ID.
{
query RekognitionFlow($cameraRkgnExample: string!, $screen: string!) @workflowType(id:
\"urn:tdm:REGION/ACCOUNT ID/default:Workflow:RekognitionFlow\") {
variables {
cameraRkgnExampleResult @property(id: \"urn:tdm:aws/
examples:property:CameraStatePropertyRkgnExample\")
rekognitionResult @property(id: \"urn:tdm:aws:Property:Json\")
}
steps {
step(name: \"CameraRkgnExample\", outEvent: [\"cameraStepDone\"]) {
DeviceActivity(deviceModel: \"urn:tdm:aws/examples:deviceModel:CameraRkgnExample
\", out: \"cameraRkgnExampleResult\", deviceId: \"${cameraRkgnExample}\") {
capture
}
}
step(name: \"Rekognition\", inEvent: [\"cameraStepDone\"], outEvent:
[\"rekognitionStepDone\"]) {
49
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
2. Enter the following command to create the flow. This command assumes that you're working in a
Linux or Unix environment. For other environments, use the equivalent of the cat utility.
3. The following TDM code contains the definition of the system used in this example. The console
creates this system for you.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID.
{
type RekognitionFlow @systemType(id: \"urn:tdm:REGION/ACCOUNT ID/
default:System:RekognitionFlow\") {
motionSensor: Device @thing(id: \"urn:tdm:aws/examples:deviceModel:MotionSensor\")
cameraRkgnExample: Device @thing(id: \"urn:tdm:aws/
examples:deviceModel:CameraRkgnExample\")
screen: Device @thing(id: \"urn:tdm:aws/examples:deviceModel:Screen\")
RekognitionFlow: Flow @workflow(id: \"urn:tdm:REGION/ACCOUNT ID/
default:Workflow:RekognitionFlow\")
}
}
5. Enter the following commands to associate the things you created in your registry with the device
models used in the flow.
Replace the MotionSensorName, CameraName, and ScreenName placeholders with the names of
the things you created earlier.
50
AWS IoT Things Graph User Guide
AWS IoT Greengrass Flow Examples
6. The following TDM code contains the definition of the flow configuration used in this example.
The TDM definition is inside the definition object. For more information, see Creating Flow
Configurations.
Copy this code to a file. Replace the REGION and ACCOUNT ID placeholders with your AWS Region
and account ID. Replace the MotionSensorName, ScreenName, and CameraName placeholders with
the names of the things you created earlier.
{
query Lobby @deployment(id: \"urn:tdm:REGION/ACCOUNT ID/default:Deployment:Lobby\",
systemId: \"urn:tdm:REGION/ACCOUNT ID/default:System:RekognitionFlow\")
{
motionSensor(deviceId: \"MotionSensorName\")
screen(deviceId: \"ScreenName\")
cameraRkgnExample(deviceId: \"CameraName\")
triggers { MotionEventTrigger(description: \"a trigger\") {
condition(expr: \"devices[name == 'motionSensor'].events[name ==
'StateChanged'].lastEvent\")
action(expr: \"ThingsGraph.startFlow('RekognitionFlow', bindings[name ==
'cameraRkgnExample'].deviceId, bindings[name == 'screen'].deviceId)\")
}
}
}
}
7. Enter the following command to create the flow configuration. Replace the GREENGRASS GROUP
and S3 BUCKET with the names of your AWS IoT Greengrass group and Amazon S3 bucket.
When the operation completes, the AWS CLI returns the following deployment summary as a JSON
object. Use the id value in the summary block as the TDM URN of the flow configuration.
{
"summary": {
"status": "PENDING_DEPLOYMENT",
"greengrassGroupName": "ThingsGraphGrnGr",
"target": "GREENGRASS",
"arn": "arn:aws:iotthingsgraph:REGION:ACCOUNT ID:default#Deployment#Lobby",
"updatedAt": 1555022871.418,
"id": "urn:tdm:REGION/ACCOUNT ID/default:Deployment:Lobby",
"createdAt": 1555022871.418
}
}
8. Enter the following command to deploy the flow configuration to your AWS IoT Greengrass group.
Use the TDM URN value returned in the previous step as the value of the id parameter.
51
AWS IoT Things Graph User Guide
Using the Example Mock Devices
This topic explains what these scripts do, and how you can modify them to test your flows when you
don't have real devices.
Motion Sensor
In the example flows that include a motion sensor, a camera, and a screen, the motion sensor publishes
a JSON object that indicates that it detects motion. Because the motion sensor mock device isn't real, it
sends the message every 10 seconds.
Camera
The camera must both subscribe and publish to MQTT topics because it takes input and generates
output. The camera subscribes to a topic where AWS IoT Things Graph publishes the instruction to take a
picture. After the camera takes the picture, it publishes a JSON object containing the URI of the resulting
image to another topic.
Screen
The screen subscribes to a topic where AWS IoT Things Graph publishes the image URI. Because the
screen mock device isn't real, it simply prints the image URI to standard output.
Flow Sequence
You could use the flow's components in a more real-world scenario, such as a door entry system in which
a facial recognition service verifies the identity of the person who triggers the motion sensor. A door
opens or remains closed depending on the result that the service sends.
52
AWS IoT Things Graph User Guide
Motion Sensor
The motion sensor publishes to the /motion topic. The camera subscribes to the /capture topic and
publishes to the /capture/finished topic. The screen subscribes to the /display topic.
Each MQTT topic used in the flow begins with the name of the thing associated with a device in the
flow. The following list contains the names of each MQTT topic and the device that subscribes and/or
publishes to it. This is the sequence that the devices follow in the flow:
Now let's look at the details of what each mock device does in this sequence.
Motion Sensor
The motion sensor mock device sends the following JSON to Motion Sensor Thing Name/motion
every 10 seconds.
{"isMotionDetected": true}
When the motion sensor publishes this message, it tells AWS IoT Things Graph that the motion sensor's
state changed. The isMotionDetected value and Boolean data type match the single field in the
MotionSensorState entity, as defined in the Aukru HCSR501 motion sensor definition.
The capability implementation in the Aukru HCSR501 motion sensor definition specifies the MQTT topic
to which the motion sensor publishes the message.
Note
If the MQTT message occurs as part of a device event, you'll find the relevant topic or topics
in the Event block. If it occurs as part of a device action, you'll find the relevant topics in the
Action block.
MQTT {
MotionSensorCapability(id: "urn:tdm:aws/
examples:capability:MotionSensorCapability") {
...
Event(name: "StateChanged") {
Subscribe(topic: "$macro(${systemRuntime.deviceId}/motion)") {
responsepayload(property: "urn:tdm:aws/
examples:property:MotionSensorStateProperty")
}
}
}
}
53
AWS IoT Things Graph User Guide
Camera
When the motion sensor's state changes, AWS IoT Things Graph receives the message on the topic
specified in the StateChanged event: the device ID (the name of the thing in the AWS IoT registry that
is being used in the flow) and /motion. This is the topic to which the motion sensor publishes.
Camera
The camera mock device listens for capture commands that AWS IoT Things Graph publishes to Camera
Thing Name/capture. Because the flow doesn't specify any input values for the camera action, the
JSON object published to this topic is empty. The camera then publishes the following JSON to Camera
Thing Name/capture/finished.
{"imageUri":"Image URI"}
The imageUri value and string data type match the single field in the CameraState entity, as defined
in the Raspberry Pi camera definition.
The capability implementation in the Raspberry Pi camera definition specifies the MQTT topics to which
the camera subscribes and publishes messages. These topics are inside the Publish block of the Action
block.
MQTT {
CameraCapability(id: "urn:tdm:aws/examples:capability:CameraCapability") {
...
Action(name: "capture") {
Publish {
Request(topic: "$macro(${systemRuntime.deviceId}/capture)") {
params
}
Response(topic: "$macro(${systemRuntime.deviceId}/capture/
finished)") {
responsePayload(property: "urn:tdm:aws/
examples:property:CameraStateProperty")
}
}
}
}
}
When the value of the property of lastClickedImage in the device's state changes, AWS IoT Things
Graph publishes an empty request to the device ID (thing name)/capture topic. It then expects
the camera to publish a response to the device ID (thing name)/capture/finished topic.
Screen
After receiving the imageUri, AWS IoT Things Graph publishes a JSON object that is identical to the one
that the camera sends to the Screen Thing Name/display topic.
54
AWS IoT Things Graph User Guide
Adapting the Mock Devices
The capability implementation in the Raspberry Pi screen definition specifies the MQTT topic to which
the screen subscribes. This topic is inside the Publish block of the Action block.
MQTT {
ScreenCapability(id: "urn:tdm:aws/examples:capability:ScreenCapability") {
...
Action(name: "display") {
params {
param(name:"imageUrl" property:"urn:tdm:aws:property:String")
}
Publish {
Request(topic: "$macro(${systemRuntime.deviceId}/display)") {
params {
param(name: "imageUri", property: "urn:tdm:aws/
examples:property:CameraStateProperty", value: "${imageUrl.value}")
}
}
}
}
}
}
AWS IoT Things Graph gets the image URI from the camera, and then passes it as a parameter to the
Action implementation. The Action implementation tells AWS IoT Things Graph to publish the image
URI to the device ID (thing name)/display topic.
• How to use the AWS IoT Device SDK for Python and the AWS IoT Greengrass Core SDK to subscribe
and post to MQTT topics in the cloud, and in an AWS IoT Greengrass group.
• At a high level, how MQTT devices interact with AWS IoT Things Graph when they perform steps in a
flow.
• The mock device scripts in Creating a Flow in an AWS IoT Greengrass Group with Devices also
demonstrate how to discover and connect to an AWS IoT Greengrass group so that devices in the
group can interact with each other. This is the necessary first step before devices start sending
messages to AWS IoT Things Graph when it's running on an AWS IoT Greengrass core device.
When you adapt the mock devices, you need to change only the MQTT topics and JSON payloads to
match the topics, inputs, and outputs that you've specified in your own flows.
When you adapt the Python mock device scripts, look for the lines containing
myAWSIoTMQTTClient.subscribe and myAWSIoTMQTTClient.publish. For example, the
cloudcamera.py script subscribes to the thingName/capture topic on line 129 of the file.
The first parameter of the subscribe method specifies the topic to which the mock device subscribes.
You can use this method to subscribe to any MQTT topic that you've specified in your flow. if you want
the mock device to do something other than print a message whenever it receives a message on the
topic, you can create your own callback function .
55
AWS IoT Things Graph User Guide
Adapting the Mock Devices
The cloudcamera.py script publishes to the thingName/capture/finished topic on line 120 of the
file.
The first parameter of the publish method specifies the topic to which the mock device publishes.
You can use this method to publish to any MQTT topic that you've specified in your flow. The second
parameter specifies the JSON object that contains the message to publish. You can change this value to
match the input and output values that you've specified in your flow.
56
AWS IoT Things Graph User Guide
Modeling by Device Communication Protocol
Modeling Entities
This section describes how to create and work with the entities that compose a workflow (flow) after you
create them in the AWS IoT Things Graph Data Model (TDM).
Entities include Properties, States, Events, Actions, Capabilities, Mappings, Devices, and Services.
After you create these entities in TDM, you upload them to your namespace by using the
UploadEntityDefinitions API.
For complete example device models and services, see Example Device and Service Definitions.
Topics
• Modeling by Device Communication Protocol (p. 57)
• MQTT Device Modeling 101 (p. 62)
• Modbus Device Modeling 101 (p. 68)
• Service Modeling 101 (p. 73)
• Creating and Uploading Entities (p. 80)
• Versioning and Entity Modeling (p. 88)
• Viewing Models and Things in the AWS IoT Things Graph Console (p. 88)
The topics in this section describe how you define devices and their interactions.
• MQTT
• Modbus
For information about defining services that use HTTP (REST) and AWS Lambda functions, see Service in
the AWS IoT Things Graph Data Model Reference.
MQTT
AWS IoT Things Graph enables interaction through the MQTT protocol by specifying MQTT as the
communication protocol in the device definition. This topic describes how to model an MQTT device in
GraphQL.
The following GraphQL shows how to define a device (a camera) that uses the MQTT protocol. This
example assumes that the state, event, and capability implemented in the device are already defined.
57
AWS IoT Things Graph User Guide
MQTT
For more information about defining devices, see the Things Data Model Reference, and the Device
construct specifically.
Key elements:
• Implementations of the device's State and Action - A device implementation can also implement a
device Event.
• The Publish block inside the Action implementation - This block contains the Request and
Response definitions.
• The Request definition - This definition specifies the MQTT request topic and the parameters, if any,
that are sent to it.
• The Response definition - This optional definition specifies the MQTT response topic (if one exists)
and the payload that is sent to it.
The following GraphQL defines another GraphQL device (a motion sensor). This example implements a
device Event that contains a Subscribe block. This block specifies the MQTT topic to which the motion
sensor subscribes.
{
type DemoMotionSensor @deviceModel(id: "urn:tdm:REGION/ACCOUNT ID/
default:deviceModel:DemoMotionSensor",
capability: "urn:tdm:REGION/ACCOUNT ID/default:capability:DemoMotionSensorCap")
{ignore:void}
58
AWS IoT Things Graph User Guide
Modbus
Modbus
AWS IoT Things Graph enables interaction through the Modbus protocol by specifying Modbus as the
communication protocol in the device definition.
This topic describes how to model a Modbus device in GraphQL. It also describes the types of Modbus
interactions that the Things Data Model (TDM) currently supports, and the data transformations that
occur when data types are modeled using the AWS IoT Greengrass Modbus-RTU Protocol Adapter.
Prerequisites
For instructions on how to create things in the registry, see Register a Device in the Registry.
Note
To add your devices to your AWS IoT Greengrass group, you need to register them as things
with credentials, even though your devices don't need to use these credentials when your
flows are running.
59
AWS IoT Things Graph User Guide
Modbus
Action(name: "getSprinklerHeadAngle") {
Params
ReadHoldingRegisters {
Response {
responsePayload(property: "urn:tdm:aws:Property:UInt16")
}
}
}
Action(name: "setSprinklerHeadAngle") {
Params {
param(name:angle, property: "urn:tdm:aws:Property:UInt16")
}
WriteSingleRegister {
Request(Address: 1) {
params {
param(name:angle,
property: "urn:tdm:aws:Property:UInt16",
value: "${angle}")
}
}
}
}
}
}
}
}
Key elements:
• The serverId argument passed to the Modbus protocol block - The value of this argument specifies
the Modbus endpoint ID to which AWS IoT Things Graph sends messages.
• Implementations of the device's State and Actions - Modbus defines no event protocol for
messages to be sent to the master, so the device definition contains no Event implementations.
60
AWS IoT Things Graph User Guide
Modbus
Interaction Flow
AWS IoT Things Graph interacts with Modbus devices by using the AWS IoT Greengrass Modbus RTU
Protocol Adapter connector. The following diagram shows the flow that occurs when a flow invokes a
Modbus device.
Payload Translations
When AWS IoT Things Graph interacts with Modbus devices, most simple types and lists of simple types
that are supported in the AWS IoT Things Graph Data Model (TDM) can be mapped to Modbus payloads.
However, complex objects can't be mapped.
The following tables describe the expected behavior when AWS IoT Things Graph serializes and
deserializes Modbus data.
Coil Interactions
TDM data type Modbus serialization Example TDM data Example Modbus
registers
61
AWS IoT Things Graph User Guide
MQTT Device Modeling 101
TDM data type Modbus serialization Example TDM data Example Modbus
registers
[10, 0, -4, 14] [1, 0, 1, 1]
Register Interactions
TDM data type Modbus serialization Example TDM data Example Modbus
registers
Int8 and UInt8 values Writes integers, two per (Int8)1 [0x1000]
register. If there is an
odd number of integers [(int8)3, (int8)5, (int8)4] [0x0305][0x04000]
(including one integer),
the value is written to [(UInt8)14, (UInt8)7] [0xD700]
MSB (most significant
byte).
Int16 and UInt16 values Writes integers, one per [(Int16)17, (Int16)1] [0x0010][0x0001]
register.
Int32 and UInt32 values Writes one integer per [0x00123400, 0x00F0] [0x0012][0x3400]
two registers. MSB is [0x0000][0x00F0]
written first.
Int64 and UInt64 values Writes one integer per 0x11223344 [0x0000][0x0000]
four registers. MSB is [0x1122][0x3344]
written first.
We'll use a motion sensor and a camera as reference points, but you can apply the process that this topic
describes to any device that uses the MQTT communication protocol. The devices that we model here are
the Aukru HC-SR501 motion sensor and the Raspberry Pi Camera.
62
AWS IoT Things Graph User Guide
Creating Your Abstract Device Model
The Aukru-HC-SR501.zip and RaspberryPiCamera.zip files contain all of the GraphQL code discussed in
this topic.
When you define a device, you need to create two pieces. The first piece is the abstract device model.
This piece generically defines what a type of device does. The second piece is the device definition, which
implements the model. The device definition specifies the communication protocol used by the device.
Devices that use different protocols can inherit from the same device model.
Before you define your device, look in the AWS IoT Things Graph console to determine whether an
abstract model for the type of device you're defining already exists. If so, you can skip to the task of
defining your device.
If you can't find an existing abstract device model for your device in the console, you have to define one.
For this exercise, assume that no model for a motion sensor device currently exists.
Motion Sensor
63
AWS IoT Things Graph User Guide
Creating Your Device's Capability (Motion Sensor)
capability: "urn:tdm:aws/examples:capability:MotionSensorCapability") {
ignore:void
}
Camera
The motion sensor device capability requires the following two TDM entities:
The Event also requires a complex Property that represents an instance of the device's State. This
Property is the payload that the device publishes to an MQTT topic whenever it detects motion.
Start defining your device's capability by thinking about the functions that it serves. A motion sensor
device detects when a body or part of a body moves within the sensor's range. When a motion sensor
detects a body in motion, it generates a notification that this event has occurred. Therefore, its capability
definition requires only a single event.
A motion detector also has two states: no motion detected and motion detected. The motion detected
event changes the state, so you need to include the state and the event in your capability. You can
represent this state as a Boolean value. The following GraphQL defines this state.
When it detects motion, the sensor sends a message to an MQTT topic. This message contains a property
that describes the current state of the sensor (in this case, the state of its isMotionDetected property
changing from false to true). To make this possible, you need to create a complex property that is an
instance of the motion sensor's state. The following GraphQL defines this property.
Use this property as the payload that the motion sensor device sends when the motion detected event
triggers a change in its state. The following GraphQL defines this Event and specifies the complex
property as the payload that it publishes to an MQTT topic.
64
AWS IoT Things Graph User Guide
Creating Your Device's Capability (Camera)
Note
A complex property is any property that contains more than one property or that is an instance
of a state.
You specify the MQTT topic to which the device publishes this payload later when you create your device
definition.
Now you're ready to define the device's capability. The capability contains both the
MotionSensorState that you created earlier and an instance of the MotionSensorEvent that is
named StateChanged. The TDM URN that uniquely identifies this capability matches the one that you
used when you created the motion sensor abstract device model.
You use the StateChanged event name when you implement the device's capability in the device
definition.
The Action also requires a complex Property that represents an instance of the device's State. This
Property is the payload that the device publishes to an MQTT topic whenever it captures an image.
A camera captures and stores images. We'll store the last image that the camera has captured in its state.
The following GraphQL defines this state.
After it captures an image, the camera sends a message to an MQTT topic. This message contains a
property that describes the current state of the camera (in this case, the location of the last image it
has captured). Just as you did with the motion sensor, you need to create a complex property that is an
instance of the camera's state. The following GraphQL defines this property.
65
AWS IoT Things Graph User Guide
Creating Your Device Definitions
Use this property as the payload that the camera sends when it captures an image and its state changes.
The following GraphQL defines this Action and specifies the complex property as the value that it
publishes to an MQTT topic.
You specify the MQTT topic to which the device publishes this payload later when you create your device
definition.
Now you're ready to define the device's capability. The capability contains both the CameraState that
you created earlier and an instance of the Capture action, which is conveniently named capture. The
TDM URN that uniquely identifies this capability matches the one that you used when you created the
camera abstract device model.
You use the capture event name when you implement the device's capability in the device definition.
Your device definition contains an MQTT block. This block implements the capability that you defined
earlier. It also specifies the MQTT topic to which the device publishes its payload (the complex property
that specifies that the device's state has changed). The following GraphQL contains the motion sensor
device definition.
66
AWS IoT Things Graph User Guide
Creating Your Device Definitions
responsepayload(property: "urn:tdm:aws/
examples:property:MotionSensorStateProperty")
}
}
}
}
}
Key features:
• The two parameters included after the @device declaration are the IDs of the device and the abstract
device model from which the device inherits.
• The MQTT block contains the state that you created earlier, and the Boolean property that you
specified in the state definition.
• The MQTT block also contains the Event block. This block takes a name argument whose value
matches the event name (StateChanged) that you specified in the capability definition.
• An event uses a Subscribe block to specify where the event notification will be published. The
Subscribe block takes a topic argument that specifies the MQTT topic to which the device
publishes its notification. In this case, the definition uses the macro keyword to include the value of
the system variable that stores the name of the thing (in the AWS IoT registry) that you've associated
with the device in a specific flow deployment. This is a good way to ensure that things in multiple flow
deployments are publishing to unique MQTT topics.
• The responsepayload block takes a property argument that specifies the payload that the device
sends to the MQTT topic. In this case, the device sends the value of the complex property that you
created earlier.
Key features:
• The two parameters included after the @device declaration are the IDs of the device and the abstract
device model from which the device inherits.
67
AWS IoT Things Graph User Guide
Modbus Device Modeling 101
• The MQTT block contains the state that you created earlier, and the String property that you
specified in the state definition.
• The MQTT block also contains the Action block. This block takes a name argument whose value
matches the event name (StateChanged) that you specified in the capability definition.
• An action uses a Publish block to specify where the action publishes its output. The Publish block
contains Request and Response blocks. The Request block specifies the MQTT topic that sets
the action in motion when notifications are published to it. You use the Response block to send a
notification that indicates that the action is complete. This notification contains the location of the last
image that the camera has captured.
• The responsepayload block inside the Response block takes a property argument that specifies
the payload that the device sends to the MQTT topic. In this case, the device sends the value of the
complex property that you created earlier.
The Aukru-HC-SR501.zip and RaspberryPiCamera.zip files contain all of the GraphQL code discussed
in this topic. Download them to work with the code, and then upload any of your changes to AWS IoT
Things Graph yourself.
We'll use a weather monitoring device as a reference point, but you can apply the process that this topic
describes to any device that uses the Modbus communication protocol. The weather monitoring device
that we model here is the Elsner P03 Weather Station (be sure to read the specification's description).
The Elsner-Weather-Station.zip file contains all of the GraphQL code discussed in this topic.
The Elsner P03 Weather Station measures conditions in the physical environment. From the device's
description in the specification, we know that this device performs the following functions:
When you define a device, you need to create two pieces. The first piece is the abstract device model.
This piece generically defines what a type of device does. The second piece is the device definition, which
implements the model. The device definition specifies the communication protocol used by the device.
Devices that use different protocols can inherit from the same device model.
Before you define your device, look in the AWS IoT Things Graph console to determine whether an
abstract model for the type of device you're defining already exists. If so, you can skip to the task of
defining your device.
68
AWS IoT Things Graph User Guide
Creating Your Abstract Device Model
If you can't find an existing abstract device model for your device in the console, you have to define one.
For this exercise, assume that no model for a weather monitoring device currently exists.
Because this device uses the Modbus protocol, AWS IoT Things Graph communicates only with the
master polling device. The master device doesn't receive inputs from other devices, so when you model
a Modbus device in TDM, you don't need to define any events. Modbus device capabilities contain only
actions.
Knowing this, you can start by creating an abstract TDM device model. (The REGION and ACCOUNT ID
values are specific to your account. The Suffix value is 1 until you create different versions of your
weather station.)
type
WeatherStation @deviceModel(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:deviceModel:WeatherStation_{{SUFFIX}}",
capability: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:capability:WeatherStationCapability_{{SUFFIX}}"){
IGNORE: VOID
69
AWS IoT Things Graph User Guide
Creating Your Abstract Device Model
Next, you need to define the capability that you included in your abstract model. Look through your
product specification and note all of the actions that the master device performs and the registers that
it uses to read and write data. A typical weather station device needs to read data only from the devices
that it's polling, so all of your actions will be "get" operations.
Because you're creating a model for a weather station, you need to create a capability that includes
recognizing rain and measuring temperature, wind speed, and the brightness of sunlight from the east,
west, and south.
type
WeatherStationCapability @capabilityType(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:capability:WeatherStationCapability_{{SUFFIX}}") {
getOutdoorTemperature: GetOutdoorTemperature @action(id: "urn:tdm:{{REGION}}/
{{ACCOUNT_ID}}/default:action:GetOutdoorTemperature_{{SUFFIX}}")
getIlluminanceOfSun_south: GetIlluminanceOfSun_south @action(id: "urn:tdm:
{{REGION}}/{{ACCOUNT_ID}}/default:action:GetIlluminanceOfSun_south_{{SUFFIX}}")
getIlluminanceOfSun_west: GetIlluminanceOfSun_west @action(id: "urn:tdm:{{REGION}}/
{{ACCOUNT_ID}}/default:action:GetIlluminanceOfSun_west_{{SUFFIX}}")
getIlluminanceOfSun_east: GetIlluminanceOfSun_east @action(id: "urn:tdm:{{REGION}}/
{{ACCOUNT_ID}}/default:action:GetIlluminanceOfSun_east_{{SUFFIX}}")
getLight: GetLight @action(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:action:GetLight_{{SUFFIX}}")
getWindSpeed: GetWindSpeed @action(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:action:GetWindSpeed_{{SUFFIX}}")
getRainCheck: GetRainCheck @action(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:action:GetRainCheck_{{SUFFIX}}")
}
The device functions described in the Elsner P03 Weather Station specification map to the actions that
you included in the device model capability.
• The three action types for getIlluminanceOfSun correspond with the device's three brightness
sensors.
• The getLight action corresponds with its recognition of twilight and dawn.
• The getRainCheck action corresponds with the precipitation recognition function, and the
getOutdoorTemperature and getWindSpeed actions correspond with the device's temperature and
wind strength measurement functions.
The specification also contains a table named P03-Modbus output string to the master. This table
contains the following information:
70
AWS IoT Things Graph User Guide
Creating Your Abstract Device Model
The following extract from the table can help you understand how the information in the specification
maps both to your action definitions and to the device definition that you create when the abstract
device model is complete.
temperature xx.x
°C
4 Outdoor L
Temperature
This extract tells you that the temperature measurement is stored at register address 0, and its size in
bytes is 2. It contains a sign (for above and below 0) and uses the Celsius scale. You know from this that
you can use the built-in TDM data type Int16 as the return type of the getOutdoorTemperature
action. You also know that you need to read 2 bytes to get the value. The extract also tells you that the
device stores the south sunlight measurement at register address 1, and that its size is also 2 bytes. This
value can also be returned as Int16.
In fact, all but one of the values that the actions measure can be returned with the Int16 data type. The
rain sensor measurement (at register address 7) stores a 1-byte Boolean value.
When you create the action definitions, you use your understanding of the data types to be returned.
When you create the device definition, you use the information about register addresses, data types, and
sizes in bytes.
You can now define the following actions with your knowledge of the device, what it does, and how it
performs its actions.
type
GetOutdoorTemperature @actionType(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:action:GetOutdoorTemperature_{{SUFFIX}}") {
return: DegreesCelsius @property(id: "urn:tdm:aws:Property:Int16")
}
type
GetIlluminanceOfSun_south @actionType(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:action:GetIlluminanceOfSun_south_{{SUFFIX}}") {
return: KiloLux @property(id: "urn:tdm:aws:Property:Int16")
}
type
GetIlluminanceOfSun_west @actionType(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:action:GetIlluminanceOfSun_west_{{SUFFIX}}") {
return: KiloLux @property(id: "urn:tdm:aws:Property:Int16")
}
type
GetIlluminanceOfSun_east @actionType(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:action:GetIlluminanceOfSun_east_{{SUFFIX}}") {
return: KiloLux @property(id: "urn:tdm:aws:Property:Int16")
}
type
GetLight @actionType(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:action:GetLight_{{SUFFIX}}") {
71
AWS IoT Things Graph User Guide
Creating the Definition for Your Device
• The Modbus endpoint ID to which AWS IoT Things Graph sends messages
• The address of each register from which the master device gets each piece of information returned by
each action
• The number of bytes to read
• The data type of each measurement value
The following example shows how these values are used in a device definition. (For more information
about the elements of a Modbus device definition, see Modbus.)
query
ModbusElsnerWeatherStation @device(id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:device:ModbusElsnerWeatherStation_{{SUFFIX}}",
deviceModel: "urn:tdm:{{REGION}}/
{{ACCOUNT_ID}}/default:deviceModel:WeatherStation_{{SUFFIX}}") {
Modbus(ServerId:"2") {
Capability (id: "urn:tdm:{{REGION}}/{{ACCOUNT_ID}}/
default:capability:WeatherStationCapability_{{SUFFIX}}") {
Action(name: "getOutdoorTemperature") {
Params
ReadInputRegisters {
Request (Address: 0, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getIlluminanceOfSun_south") {
Params
ReadInputRegisters {
Request (Address: 1, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getIlluminanceOfSun_west") {
Params
72
AWS IoT Things Graph User Guide
Service Modeling 101
ReadInputRegisters {
Request (Address: 2, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getIlluminanceOfSun_east") {
Params
ReadInputRegisters {
Request (Address: 3, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getLight") {
Params
ReadInputRegisters {
Request (Address: 4, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getWindSpeed") {
Params
ReadInputRegisters {
Request (Address: 5, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getRainCheck") {
Params
ReadInputRegisters {
Request (Address: 6, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
}
}
}
The two parameters included after the @device declaration are the IDs of the device and device models.
The serverId value inside the Modbus protocol block is the Modbus endpoint ID. Each request inside
the ReadInputRegisters blocks includes the register address and read count for each value that the
device returns. The data type of each return value is included in the responsePayload blocks.
The Elsner-Weather-Station.zip file contains all of the GraphQL code discussed in this topic. Download it
to work with it, and then upload it to AWS IoT Things Graph yourself.
73
AWS IoT Things Graph User Guide
Modeling an AWS Service
The approaches that this topic takes to modeling services can be applied to other AWS services and
Lambda functions.
The ServiceModels101.zip file contains all of the GraphQL code discussed in this topic.
Note
The Amazon Rekognition and getS3Lambda service models discussed in this topic are available
in the AWS IoT Things Graph console. The example in Creating a Flow with Lambda Functions
uses the getS3Lambda service discussed here. The example in Creating a Flow with Devices and
a Service uses the Amazon Rekognition service discussed in this topic.
Before you get started writing your model, you need to understand the requirements of the underlying
AWS service. You can find this information in the Amazon Rekognition API Reference.
Your service model must include these parameters in the calls that it makes to the DetectFaces API.
The AWS IoT Things Graph runtime adds the X-Amz-Date header to your requests automatically, so
your model doesn't have to account for that. Therefore, your HTTP request definition will include the
following header parameters.
headerParams {
param(name:"Accept", property:"urn:tdm:aws:Property:String", value:"application/json")
74
AWS IoT Things Graph User Guide
Modeling an AWS Service
The headerParams block sets the required header parameters of the request. Amazon Rekognition
requires you to specify the x-amz-json-1.1 content type and the REST endpoint (X-Amz-Target) for
the capability that you want to use (RekognitionService.DetectFaces). In this example, the AWS
IoT Things Graph service expects a return value of json, so you also include an Accept header.
Next, you need to look at the reference documentation for the DetectFaces API. This API requires
you to pass an image as either a BLOB (a Base64-encoded binary data object) or as an S3Object. This
example service passes an Amazon S3 object, so the HTTP request definition includes the following body
parameters.
bodyParams {
param(name:"", property:"urn:tdm:aws:Property:String",
value:"$macro({\"Image\":{\"S3Object\":{\"Bucket\":\"${bucketName.value}\",\"Name\":
\"${itemName.value}\"}}})")
}
The bodyParams block can define the name-value pairs separately, or you can pass the name-value pairs
in a JSON object. This example uses a JSON object, which is why the name attribute is an empty string.
The $macro function replaces placeholders wrapped inside curly braces and prepended by dollar signs
(${}) with variables whose values are supplied by the service activity. The service that we're defining
requires the Amazon S3 bucket name and item name (also called the S3 object key name) to be supplied
as parameters to its activity.
The @actionType directive assigns a URN value that uniquely identifies the new action. The
DetectFaces action consists of two string properties that set the Amazon S3 bucket and item names.
The return keyword assigns a name to the return value (RkgnResponseProperty) and sets its
property type to JSON.
75
AWS IoT Things Graph User Guide
Modeling an AWS Service
The REST keyword inside the @service declaration defines this as an HTTP AWS IoT Things Graph
service that uses a REST interface to make calls to the underlying AWS service. The Action name
corresponds with the name of the action in the RekognitionCap capability definition.
The HttpPost block contains the Request and Response definitions. We've already seen the
headerParams and bodyParams blocks. The $macro function used to compose the HTTP request URL
substitutes the ${systemConfig.awsRegion} placeholder with the user's AWS Region. (You can also
use $systemConfig.accountId when you need to retrieve the user's account ID.)
If the underlying web service is an AWS service, the Request block also requires values for auth and
awsServiceName. Signature Version 4 (SigV4) is how AWS authenticates information sent in HTTP
requests. Currently authentication is supported only for AWS services.
76
AWS IoT Things Graph User Guide
Modeling an AWS Lambda Function
The Response block sets the content type of the HTTP response as a JSON object. This corresponds with
the return type that you specified in the DetectFaces action definition.
The params block contains the two parameters that must be sent to the service when it's used in a flow.
In Creating a Flow with Devices and a Service, the WebServiceActivity definition for the Amazon
Rekognition service model (which you add when you're creating the flow) retrieves these values from the
CameraRkgnExample device.
{
WebserviceActivity(webservice: "urn:tdm:aws/examples:service:Rekognition", out:
"rekognitionResult") {
detectFaces(bucketName: "${cameraResult.s3BucketName}", itemName:
"${cameraResult.s3ItemName}")
}
}
The WebServiceActivity definition expects the camera to send the image as an Amazon S3 bucket.
Your own flow might need to work differently, and your camera might not be able to pass images in
this way. If your camera sends images in another format, your DetectFaces action will need to contain
other properties to account for the differences.
The example in Creating a Flow with Devices and a Service doesn't do anything with the Amazon
Rekognition response. It simply passes the image to the screen device. You could fill in this gap by
writing an AWS Lambda function that processes the results and applies logic before sending the image
to the screen. You could include this function in your flow if you implement it as an AWS IoT Things
Graph service. The following section shows you how to do that.
const params = {
Bucket: bucket,
Key: key,
};
The service model definition needs a corresponding params section in its action block.
params {
param(name: "bucket", property:"urn:tdm:aws:property:String")
77
AWS IoT Things Graph User Guide
Modeling an AWS Lambda Function
The getS3Lambda code fetches the object from the bucket and returns an object that contains its
value as a string and the length of the string. The following GraphQL shows the corresponding action
definition.
The @actionType directive assigns a URN value that uniquely identifies the new action.
The getS3ObjectAsStringAction action consists of two string properties that set the
Amazon S3 bucket and object names. The return keyword assigns a name to the return
value (getS3ObjectAsStringResponse) and sets its property type to urn:tdm:aws/
examples:property:getS3ObjectAsStringResponse. This is not a built-in property type. It's a
complex property that contains both the string and the length. You need to define this property type.
You begin by creating a state that contains string and Int32 values that represent the content of the
Amazon S3 object and the length of the string.
This state consists of a String property named message and an Int32 property named length. Now
you can create a complex property that is an instance of this state.
78
AWS IoT Things Graph User Guide
Modeling an AWS Lambda Function
You enable interaction with the Lambda function by specifying AwsLambda as the communication
protocol inside the service definition. If your Lambda function runs in a AWS IoT Greengrass group,
specify InvokeGreengrassLambda inside the Action block. If your Lambda function runs in the cloud,
specify InvokeCloudLambda instead.
The AwsLambda keyword inside the @service declaration defines this as an AWS IoT Things Graph
service that implements an AWS Lambda function. The Action name corresponds with the name of the
action in the getS3Capability capability definition.
You can use a Lambda function that runs in the cloud with the InvokeCloudLambda block, which works
in the same way.
79
AWS IoT Things Graph User Guide
Creating and Uploading Entities
The Response block sets the content type of the response as the getS3ObjectAsStringResponse
property that you created. This corresponds with the return type that you specified in the
getS3ObjectAsStringAction action definition.
The params block contains the two parameters that must be sent to the service when it's used in a flow.
In Creating a Flow with Lambda Functions, the WebServiceActivity definition for the getS3Object
service model (which you add when you're creating the flow) sets these values.
{
WebserviceActivity(webservice: "urn:tdm:aws/examples:Service:getS3Lambda", out:
"getS3LambdaResult") {
getS3ObjectAsString(bucket: "tg-test-gg", key: "HelloWorld.txt")
}
}
The ServiceModels101.zip file contains all of the GraphQL code discussed in this topic. Download it to
work with it, and then upload it to AWS IoT Things Graph yourself.
This topic describes how to complete these tasks by using either the AWS CLI or the AWS IoT Things
Graph console.
These definitions create a barcode reader and another device that does something with the reader
output, with all of the TDM entities that compose the devices.
Note
Before uploading your models, you must wrap all of your definitions between opening and
closing curly braces, as in the following example.
{
# Basic type definitions
type
String @propertyType(id: "urn:tdm:REGION/ACCOUNT ID/default:property:String", dataType:
String) {
IGNORE: VOID
}
type
80
AWS IoT Things Graph User Guide
Step 1. Define the Entities
type
Barcode @propertyType(id: "urn:tdm:REGION/ACCOUNT ID/default:property:Barcode",
instanceOf: "urn:tdm:REGION/ACCOUNT ID/default:state:BarcodeType") {
IGNORE: VOID
}
# Action definitions
type
DeviceA_ReadBarcode @actionType(id: "urn:tdm:REGION/ACCOUNT ID/
default:action:DeviceA_ReadBarcode") {
return: Property @property(id: "urn:tdm:REGION/ACCOUNT ID/default:property:Barcode")
}
type
DeviceB_Action @actionType(id: "urn:tdm:REGION/ACCOUNT ID/default:action:DeviceB_Action")
{
input: Property @property(id: "urn:tdm:REGION/ACCOUNT ID/default:property:Barcode")
}
# Capability definitions
type
DeviceA @capabilityType(id: "urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceA") {
readBarcode: Action @action(id: "urn:tdm:REGION/ACCOUNT ID/
default:action:DeviceA_ReadBarcode")
}
type
DeviceB @capabilityType(id: "urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceB") {
doSomething: Action @action(id: "urn:tdm:REGION/ACCOUNT ID/
default:action:DeviceB_Action")
}
type
DeviceA @deviceModel(id: "urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceA",
capability: "urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceA") {
IGNORE: VOID
}
81
AWS IoT Things Graph User Guide
Step 2. Upload the Entity Definitions
}
Response(topic: "DeviceA/out") {
responsePayload(property: "urn:tdm:REGION/ACCOUNT ID/
default:property:Barcode")
}
}
}
}
}
}
query
DeviceB @device(id: "urn:tdm:REGION/ACCOUNT ID/default:device:DeviceB", deviceModel:
"urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceB") {
MQTT {
Capability(id: "urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceB") {
Action(name: "doSomething") {
params {
param(name: "input", property: "urn:tdm:REGION/ACCOUNT ID/
default:property:Barcode")
}
Publish {
Request(topic: "DeviceB/in") {
params {
param(name: "readId", property: "urn:tdm:REGION/ACCOUNT ID/
default:property:Barcode", value: "${input.value}")
}
}
}
}
}
}
}
}
These models create the properties, states, actions, and capabilities, and the two devices that contain
these other entities.
The UploadEntityDefinitions API consumes a JSON object with two parameter values:
language and text.
Currently, the only supported value for language is GraphQL. The value of text is a set of TDM
definitions implemented in GraphQL. The resulting JSON looks like the following example.
{
"language": "GRAPHQL",
"text" : "string containing the GRAPHQL models"
}
82
AWS IoT Things Graph User Guide
Step 2. Upload the Entity Definitions
You can construct the JSON payload in any way that your development framework and language
support. For convenience, the following example contains a valid JSON object that you can copy into
a file if you don't want to create one yourself.
{
"language": "GRAPHQL",
"text": "{type String @propertyType(id: 'urn:tdm:REGION/ACCOUNT ID/
default:property:String', dataType: String) {IGNORE: VOID} type Boolean
@propertyType(id: 'urn:tdm:REGION/ACCOUNT ID/default:property:Boolean',
dataType: Boolean) {IGNORE: VOID} type BarcodeType @stateType(id:
'urn:tdm:REGION/ACCOUNT ID/default:state:BarcodeType') {id: Property
@property(id: 'urn:tdm:REGION/ACCOUNT ID/default:property:String')} type
Barcode @propertyType(id: 'urn:tdm:REGION/ACCOUNT ID/default:property:Barcode',
instanceOf: 'urn:tdm:REGION/ACCOUNT ID/default:state:BarcodeType') { IGNORE:
VOID} type DeviceA_ReadBarcode @actionType(id: 'urn:tdm:REGION/ACCOUNT ID/
default:action:DeviceA_ReadBarcode') {return: Property @property(id: 'urn:tdm:REGION/
ACCOUNT ID/default:property:Barcode')} type DeviceB_Action @actionType(id:
'urn:tdm:REGION/ACCOUNT ID/default:action:DeviceB_Action') { input: Property
@property(id: 'urn:tdm:REGION/ACCOUNT ID/default:property:Barcode')} type DeviceA
@capabilityType(id: 'urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceA')
{ readBarcode: Action @action(id: 'urn:tdm:REGION/ACCOUNT ID/
default:action:DeviceA_ReadBarcode')} type DeviceB @capabilityType(id: 'urn:tdm:REGION/
ACCOUNT ID/default:capability:DeviceB') {doSomething: Action @action(id:
'urn:tdm:REGION/ACCOUNT ID/default:action:DeviceB_Action')} type DeviceB
@deviceModel(id: 'urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceB', capability:
'urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceB') {IGNORE: VOID} type DeviceA
@deviceModel(id: 'urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceA', capability:
'urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceA') {IGNORE: VOID} query
DeviceA @device(id: 'urn:tdm:REGION/ACCOUNT ID/default:device:DeviceA', deviceModel:
'urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceA') { MQTT { Capability(id:
'urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceA') { Action(name: 'readBarcode')
{ Publish {Request(topic: 'DeviceA/in') {params} Response(topic: 'DeviceA/out')
{responsePayload(property: 'urn:tdm:REGION/ACCOUNT ID/default:property:Barcode')}}}}}}
query DeviceB @device(id: 'urn:tdm:REGION/ACCOUNT ID/default:device:DeviceB',
deviceModel: 'urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceB') { MQTT
{Capability(id: 'urn:tdm:REGION/ACCOUNT ID/default:capability:DeviceB') {Action(name:
'doSomething') {params {param(name: 'input', property: 'urn:tdm:REGION/ACCOUNT
ID/default:property:Barcode')} Publish { Request(topic: 'DeviceB/in') { params
{param(name: 'readId', property: 'urn:tdm:REGION/ACCOUNT ID/default:property:Barcode',
value: '${input.value}')}}}}}}}}"
}
After you construct the JSON payload that contains the GraphQL definitions, upload it to your
namespace by using the following CLI command.
This command is executed asynchronously. Before using any of these entities, check whether the
execution is complete by using the get-upload-status command, as in the following example.
83
AWS IoT Things Graph User Guide
Step 2. Upload the Entity Definitions
3. On the Create device model page, enter a name for your model. You can choose Upload a GraphQL
file or Code in a GraphQL editor.
If you choose to upload a GraphQL file, you can use the same JSON definition document that you
created in Upload the Entity Definition (CLI) (p. 82).
For this example, choose Code in a GraphQL editor. Then choose Next.
84
AWS IoT Things Graph User Guide
Step 2. Upload the Entity Definitions
4. On the Provide GraphQL page, copy the GraphQL for your model into the editor. Then choose
Import. Verify that your new model is included in the list on the Models page.
85
AWS IoT Things Graph User Guide
Step 3. Associate Devices with Things
86
AWS IoT Things Graph User Guide
Step 3. Associate Devices with Things
2. On the Things page, select the check box next to the AWS IoT thing from your registry to associate
with a device that you created. Choose Associate.
3. On the Select device model page, choose the device to associate with your thing. Then choose
Associate.
4. On the Things page, reload the page and verify that your device and thing are associated.
87
AWS IoT Things Graph User Guide
Versioning and Entity Modeling
5. Repeat steps 2 and 3 for ThingB and any other things you want to associate with devices.
For more information about creating and managing a flow that contains these entities, see Creating and
Deploying Flows.
Uploading Entities
The UploadEntityDefinitions API takes two optional parameters that enable you to create versions of
your namespace. If you set the value of the deprecateExistingEntities parameter to true, AWS
IoT Things Graph deprecates all of the existing entities in the current version of your namespace before it
uploads the new entity definitions. This creates a new version of your namespace.
Existing deployments of flows that use deprecated or updated entity definitions continue to work
because they're associated with earlier versions of the namespace.
If you add any entity definitions from your private namespace to the public namespace, you must update
your own flows to use the version of the entity that's in the public namespace.
For more information about namespaces, see AWS IoT Things Graph Namespaces.
This topic describes the features of the models and things sections and explains how to use them.
88
AWS IoT Things Graph User Guide
Models List
Models List
The main page of the models section contains a list of all of the devices and device models in your
namespace and in the public namespace, as shown in the following screenshot.
The Models list page displays services, devices, and device models. It also shows their AWS IoT Things
Graph Data Model URNs.
To create a model, choose Create Model. Follow the instructions to upload a file that contains all the
components (properties, state, actions, events, and capability) of your service, device, or device model.
You can also edit the model in a GraphQL editor in the browser, as shown in the following screenshot.
The MotionSensor device model definition appears in the browser-based GraphQL editor.
For more information about creating device definitions with the AWS IoT Things Graph Data Model, see
the AWS IoT Things Graph Data Model Reference and Example Device and Service Definitions.
Model Details
To see details about each service, device, or device model, select the linked name in the Device class/
subclass column. (You can also select the box next to the name, and then choose View details.) The
default Details tab on the page that's displayed provides summary information about the definition, as
shown in the following screenshot.
The Model details page contains the URN of the service, device, or device model. It also displays the
properties, actions, and events in the definition.
If you're viewing a device model, the Device models and Associated things tabs also appear. The Device
models tab displays all of the devices in your namespace and in the public namespace that implement
the device model and its capability. The following screenshot shows one device that implements the
MotionSensor device model.
The Device models section for the MotionSensor device model displays the HCSR501MotionSensor
device.
If you're viewing a device model, the Associated things tab displays all of the things in your AWS IoT
registry that are associated with the devices that implement the device model. You can also search for
associated things from this page.
The Associated things tab for the MotionSensor device model displays the associated things and their
ARNs.
Model Definition
You can view the definition of a service, device, or device model in two ways. To download a file that
contains the definition, choose Download model. To view the definition in the browser, choose View
definition. The complete model definition appears in a new window.
View definition displays the MotionSensor definition, including its capability, state, event, and property.
When you select the Details tab, Edit model and Edit appear on the right side of the screen and are
enabled. The two buttons perform the same operation. To edit the definition, choose Edit or Edit Model.
Follow the instructions to upload a file containing updated versions of the components (properties, state,
actions, events, and capability) of your service, device, or device model. You can also edit the model in a
GraphQL editor in the browser.
89
AWS IoT Things Graph User Guide
Associating Things with Devices
After you associate a thing with a device, you can include that thing in a deployment that includes a
flow that contains the device or a device model from which the device inherits. The following screenshot
shows an example of the things list.
The MotionSensor1 thing is associated with the HCSR501MotionSensor device. the Associated entity ID
column displays the AWS IoT Things Graph Data Model URN of each device.
To associate a thing with a device, select the thing and then choose Associate with model. The Select
device model list appears. You can page through the list or use the Search device models box to find
the device you want.
A thing can be associated with only one device. To dissociate a thing with a device, select the thing and
then choose Dissociate with model.
90
AWS IoT Things Graph User Guide
Creating and Deploying Flows (AWS IoT Greengrass)
Topics
• Creating and Deploying Flows (AWS IoT Greengrass) (p. 91)
• Creating and Deploying Flows (Cloud) (p. 99)
• Revising Flows (p. 107)
• Adding Triggers to Flows (p. 108)
• Working with Choice Nodes (p. 110)
Prerequisites
Note
The AWS IoT Greengrass group and Amazon S3 bucket must be created in the same AWS
Region. The AWS IoT Things Graph entities that you create must also be in the same Region as
these resources.
• An AWS account
• An AWS IoT Greengrass core, version 1.7 or later
Create a directory named thingsgraph at the root of your core. For information on how to configure
Greengrass logs, see Monitoring with AWS IoT Greengrass Logs
• An Amazon S3 bucket
• An AWS IoT Greengrass IAM role that has access to your S3 bucket
Add this role to your Greengrass group. For information on how to configure IAM roles for Greengrass,
see Configure IAM Roles.
• Completion of the steps in Creating and Uploading Models
We provide procedures for creating and deploying flows using either the AWS CLI or the AWS IoT Things
Graph console. Both the AWS CLI and the console use the two devices that you created in Creating and
Uploading Models.
Note
You must create a thingsgraph directory at the root of your AWS IoT Greengrass core device.
If this directory doesn't exist, deployments to your core device won't work.
Topics
91
AWS IoT Things Graph User Guide
Create and Deploy a Flow (CLI)
The following GraphQL contains a definition of a flow that sends a message from a barcode reader
to another device.
{
query
BarcodeReaderFlow($device1Id: String, $device2Id: String) @workflowType(id:
"urn:tdm:REGION/ACCOUNT ID/default:Workflow:BarcodeReaderFlow") {
variables {
barcode @property(id: "urn:tdm:REGION/ACCOUNT ID/default:property:Barcode")
}
steps {
step(name: "DeviceA", outEvent: ["step1_done"]) {
DeviceActivity(deviceModel: "urn:tdm:REGION/ACCOUNT ID/
default:deviceModel:DeviceA", deviceId: "${device1Id}", out: "barcode") @device(id:
"urn:tdm:REGION/ACCOUNT ID/default:device:DeviceA") {
readBarcode
}
}
step(name: "DeviceB", inEvent: ["step1_done"]) {
DeviceActivity(deviceModel: "urn:tdm:REGION/ACCOUNT ID/
default:deviceModel:DeviceB", deviceId: "${device2Id}") @device(id:
"urn:tdm:REGION/ACCOUNT ID/default:device:DeviceB") {
doSomething(input: "${barcode}")
}
}
}
}
}
After you model the flow, you create it by using the CreateWorkflowTemplate API. This API
consumes a JSON object that contains two parameter values: language and text.
Currently, the only supported value for language is GraphQL. The value of text is a set of TDM
definitions implemented in GraphQL.
{
"language": "GRAPHQL",
"text": "{query BarcodeReaderFlow($device1Id: String, $device2Id: String)
@workflowType(id: 'urn:tdm:REGION/ACCOUNT ID/default:Workflow:BarcodeReaderFlow')
{variables {barcode @property(id: 'urn:tdm:REGION/ACCOUNT ID/
default:property:Barcode')} steps {step(name: 'DeviceA', outEvent: ['step1_done'])
{DeviceActivity(deviceModel: 'urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceA',
deviceId: '${device1Id}', out: 'barcode') {readBarcode}} step(name: 'DeviceB',
inEvent: ['step1_done']) {DeviceActivity(deviceModel: 'urn:tdm:REGION/ACCOUNT
92
AWS IoT Things Graph User Guide
Create and Deploy a Flow (CLI)
After you construct the JSON payload that contains the GraphQL definition of the flow, you create
the flow in your namespace by using the following CLI command.
In this step, you define a system that contains the flow you just created, and the devices that you
modeled and associated with two things in your registry (as described in Getting Started with
Models).
The following GraphQL contains a system that includes your flow and those two things. The URNs in
the example are the unique identifiers of the device models that are associated with the things you
created in Getting Started with Models.
{
type
securitySystem @systemType(id: 'urn:tdm:REGION/ACCOUNT ID/
default:system:BarcodeReaderFlow') {
device1: Thing @thing(id: 'urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceA')
device2: Thing @thing(id: 'urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceB')
barcodeReaderFlow: Workflow @workflow(id: 'urn:tdm:REGION/ACCOUNT ID/
default:Workflow:BarcodeReaderFlow')
}
}
After you define the system, you create it by using the CreateSystemTemplate API. This API
consumes a JSON object that contains two parameter values: language and text.
Currently, the only supported value for language is GraphQL. The value of text parameter is a set
of TDM definitions implemented in GraphQL.
{
"language": "GRAPHQL",
"text": "{type securitySystem @systemType(id: 'urn:tdm:REGION/ACCOUNT ID/
default:system:BarcodeReaderFlow') {device1: Thing @thing(id: 'urn:tdm:REGION/ACCOUNT
ID/default:deviceModel:DeviceA') device2: Thing @thing(id: 'urn:tdm:REGION/ACCOUNT
ID/default:deviceModel:DeviceB') barcodeReaderFlow: Workflow @workflow(id:
'urn:tdm:REGION/ACCOUNT ID/default:Workflow:BarcodeReaderFlow')}}"
}
After you construct the JSON payload that contains the GraphQL definition of the flow, you create
the flow in your namespace by using the following CLI command.
93
AWS IoT Things Graph User Guide
Create and Deploy a Flow (CLI)
The following GraphQL defines a flow configuration for the system that you just created. It passes a
trigger to the flow that starts the flow every 10 seconds.
{
query
BarcodeReaderFlow @deployment(id: 'urn:tdm:REGION/ACCOUNT ID/
default:deployment:BarcodeReaderFlow', systemId: 'urn:tdm:REGION/ACCOUNT ID/
default:system:BarcodeReaderFlow') {
device1(deviceId: 'DeviceA')
device2(deviceId: 'DeviceB')
triggers {
TenSecondTrigger(description: 'a trigger') {
condition(expr: 'every 10 seconds')
action(expr: 'ThingsGraph.startFlow(\"barcodeReaderFlow\", bindings[name ==
\"device1\"].deviceId, bindings[name == \"device2\"].deviceId)')
}
}
}
}
After you define the flow configuration, you create it by using the CreateSystemInstance API.
This API consumes a JSON object that contains two parameter values: language and text.
Currently the only supported value for language is GraphQL. The value of text is a set of TDM
definitions implemented in GraphQL.
{
"language": "GRAPHQL",
"text": "{ query BarcodeReaderFlow @deployment(id: 'urn:tdm:REGION/ACCOUNT
ID/default:deployment:BarcodeReaderFlow', systemId: 'urn:tdm:REGION/ACCOUNT ID/
default:system:BarcodeReaderFlow') {device1(deviceId: 'DeviceA') device2(deviceId:
'DeviceB') triggers {TenSecondTrigger(description: 'a trigger') {condition(expr:
'every 10 seconds') action(expr: 'ThingsGraph.startFlow(\"barcodeReaderFlow\",
bindings[name == \"device1\"].deviceId, bindings[name == \"device2\"].deviceId)')}}}}"
}
target
The target type for your deployment. For AWS IoT Greengrass deployments, specify
GREENGRASS.
s3BucketName
The name of the Amazon S3 bucket where AWS IoT Things Graph will deploy the dependency
closure of the flow configuration.
94
AWS IoT Things Graph User Guide
Create and Deploy a Flow (AWS IoT Things Graph console)
greengrassGroupName
The name of the AWS IoT Greengrass group where the flow will run. AWS IoT Things Graph
deploys the AWS Lambda function to this group and configures it to use the flow configuration
stored in the specified S3 bucket. It also adds subscriptions to any MQTT topics specified in your
device definitions, and adds the devices in your flow to the group.
After you construct the JSON payload that contains the GraphQL definition of the flow
configuration, upload it to your namespace by using the following CLI command. The output of this
command includes an ID for your flow configuration. You use this value when you deploy the flow
configuration.
Deploy your flow configuration to the AWS IoT Greengrass group that you specified in its
configuration by using the DeploySystemInstance API. This API adds AWS IoT Things Graph, your
devices, and your flow to the AWS IoT Greengrass group that you specified when you created the
flow configuration. It also adds the configuration and its dependencies to the S3 bucket that you
specified.
When this flow configuration is deployed, you can check the device logs on your AWS IoT Greengrass
core device to verify that the flow is running every 10 seconds.
In the Flow configuration pane, enter a name for your flow. This name can't contain any spaces.
95
AWS IoT Things Graph User Guide
Create and Deploy a Flow (AWS IoT Things Graph console)
On the Logic tab, choose Clock, and then drag it into the flow designer.
Search for DeviceA, which is a barcode reader that you created in Creating and Uploading Models.
Select the device and drag it into the flow designer. Do the same for DeviceB.
In the flow designer, select the edge of ClockTrigger and connect it to DeviceA. Connect DeviceA
and DeviceB in the same way.
The event appears between the two devices because DeviceA passes an output (the bar code) to
DeviceB. You can pass this output to multiple devices and services by connecting this event to them,
as in the following image.
This is the correct way to pass output to multiple entities. Directly connecting one device or service
to multiple devices or services causes a syntax error when you try to publish the flow.
5. Update the ClockTrigger.
In the trigger editor that appears in the right pane, for Frequency, enter 10, and then select seconds
from the menu on the right. For Action, choose ThingsGraph.startFlow.
6. Update the device action for DeviceA.
In the flow designer, select DeviceB. Select No action configured in the action editor that appears
in the right pane. Select readBarcode from the drop-down box that appears. Select the arrow that
appears to the left of the Output option. Enter deviceAResult in the text box that appears under
Output.
Click the surface of the flow designer to close the action editor.
7. Update the device action for DeviceB.
96
AWS IoT Things Graph User Guide
Create and Deploy a Flow (AWS IoT Things Graph console)
In the flow designer, select DeviceB. Select No action configured in the action editor that appears
in the right pane. Select doSomething from the drop-down box that appears. Select Define Input
under the Inputs option. Enter ${deviceAResult} in the pop-up box that appears. Select the Save
Input button
Click the surface of the flow designer to close the action editor.
8. Publish the flow.
Choose Publish at the upper right of the page. This creates the flow and adds it to the list of flows
that can be deployed. Then choose Go to flow list to verify that your flow is created.
9. Start creating the flow configuration.
On the Flows list page, select the check box next to the flow that you just created, and then choose
Create flow configuration.
On the Describe flow configuration page, select your flow and enter a deployment name. The
deployment name can't contain spaces. Choose Greengrass, and then choose Next.
11. Configure the target.
On the Configure target page, enter the name of your Amazon S3 bucket and the AWS IoT
Greengrass group to which your AWS IoT Greengrass core device belongs. Choose Next.
97
AWS IoT Things Graph User Guide
Create and Deploy a Flow (AWS IoT Things Graph console)
On the Map Things page, from the menu under deviceA, select the thing that you associated with
this device in Creating and Uploading Models. Do the same for deviceB. Choose Next.
13. View the trigger.
On the Set up triggers page, the following GraphQL appears in the editor. This GraphQL specifies
the time intervals at which the flow runs. This flow runs every 10 seconds. You don't need to edit
this code.
Choose Review.
98
AWS IoT Things Graph User Guide
Creating and Deploying Flows (Cloud)
On the Review and create page, review the information you entered for your flow configuration.
Choose Create.
15. Deploy
When the Flow configuration created message appears, choose Deploy now.
After a successful deployment, the Deployments page displays Deployed in target in the Status
column.
Prerequisites
99
AWS IoT Things Graph User Guide
Create and Deploy a Flow (CLI)
• An AWS account
• An IAM role that is configured according to the instructions in Prepare for Cloud Deployments
• Completion of the steps in Creating and Uploading Models
We provide procedures for creating and deploying flows using either the AWS CLI or the AWS IoT Things
Graph console. Both the AWS CLI and the console use the two devices that you created in Creating and
Uploading Models.
Topics
• Create and Deploy a Flow (CLI) (p. 100)
• Create and Deploy a Flow (AWS IoT Things Graph console) (p. 103)
The following GraphQL contains a definition of a flow that sends a message from a barcode reader
to another device.
{
query
BarcodeReaderFlow($device1Id: String, $device2Id: String) @workflowType(id:
"urn:tdm:REGION/ACCOUNT ID/default:Workflow:BarcodeReaderFlow") {
variables {
barcode @property(id: "urn:tdm:REGION/ACCOUNT ID/default:property:Barcode")
}
steps {
step(name: "DeviceA", outEvent: ["step1_done"]) {
DeviceActivity(deviceModel: "urn:tdm:REGION/ACCOUNT ID/
default:deviceModel:DeviceA", deviceId: "${device1Id}", out: "barcode") @device(id:
"urn:tdm:REGION/ACCOUNT ID/default:device:DeviceA") {
readBarcode
}
}
step(name: "DeviceB", inEvent: ["step1_done"]) {
DeviceActivity(deviceModel: "urn:tdm:REGION/ACCOUNT ID/
default:deviceModel:DeviceB", deviceId: "${device2Id}") @device(id:
"urn:tdm:REGION/ACCOUNT ID/default:device:DeviceB") {
doSomething(input: "${barcode}")
}
}
}
}
}
After you model the flow, you create it by using the CreateWorkflowTemplate API. This API
consumes a JSON object that contains two parameter values: language and text.
Currently, the only supported value for language is GraphQL. The value of text is a set of TDM
definitions implemented in GraphQL.
100
AWS IoT Things Graph User Guide
Create and Deploy a Flow (CLI)
{
"language": "GRAPHQL",
"text": "{query BarcodeReaderFlow($device1Id: String, $device2Id: String)
@workflowType(id: 'urn:tdm:REGION/ACCOUNT ID/default:Workflow:BarcodeReaderFlow')
{variables {barcode @property(id: 'urn:tdm:REGION/ACCOUNT ID/
default:property:Barcode')} steps {step(name: 'DeviceA', outEvent: ['step1_done'])
{DeviceActivity(deviceModel: 'urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceA',
deviceId: '${device1Id}', out: 'barcode') {readBarcode}} step(name: 'DeviceB',
inEvent: ['step1_done']) {DeviceActivity(deviceModel: 'urn:tdm:REGION/ACCOUNT
ID/default:deviceModel:DeviceB', deviceId: '${device2Id}') {doSomething(input:
'${barcode}')}}}}}"
}
After you construct the JSON payload that contains the GraphQL definition of the flow, you create
the flow in your namespace by using the following CLI command.
In this step, you define a system that contains the flow you just created, and the devices that you
modeled and associated with two things in your registry (as described in Getting Started with
Models).
The following GraphQL contains a system that includes your flow and those two things. The URNs in
the example are the unique identifiers of the device models that are associated with the things you
created in Getting Started with Models.
{
type
securitySystem @systemType(id: "urn:tdm:REGION/ACCOUNT ID/
default:system:BarcodeReaderFlow") {
device1: Thing @thing(id: "urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceA")
device2: Thing @thing(id: "urn:tdm:REGION/ACCOUNT ID/default:deviceModel:DeviceB")
barcodeReaderFlow: Workflow @workflow(id: "urn:tdm:REGION/ACCOUNT ID/
default:Workflow:BarcodeReaderFlow")
}
}
After you define the system, you create it by using the CreateSystemTemplate API. This API
consumes a JSON object that contains two parameter values: language and text.
Currently, the only supported value for language is GraphQL. The value of text parameter is a set
of TDM definitions implemented in GraphQL.
{
"language": "GRAPHQL",
101
AWS IoT Things Graph User Guide
Create and Deploy a Flow (CLI)
After you construct the JSON payload that contains the GraphQL definition of the flow, you create
the flow in your namespace by using the following CLI command.
The following GraphQL defines a flow configuration for the system that you just created. It passes a
trigger to the flow that starts the flow every 10 seconds.
{
query
BarcodeReaderFlow @deployment(id: 'urn:tdm:REGION/ACCOUNT ID/
default:deployment:BarcodeReaderFlow', systemId: 'urn:tdm:REGION/ACCOUNT ID/
default:system:BarcodeReaderFlow') {
device1(deviceId: 'DeviceA')
device2(deviceId: 'DeviceB')
triggers {
TenSecondTrigger(description: 'a trigger') {
condition(expr: 'every 10 seconds')
action(expr: 'ThingsGraph.startFlow(\"barcodeReaderFlow\", bindings[name ==
\"device1\"].deviceId, bindings[name == \"device2\"].deviceId)')
}
}
}
}
After you define the flow configuration, you create it by using the CreateSystemInstance API.
This API consumes a JSON object that contains two parameter values: language and text.
Currently the only supported value for language is GraphQL. The value of text is a set of TDM
definitions implemented in GraphQL.
{
"language": "GRAPHQL",
"text": "{ query BarcodeReaderFlow @deployment(id: 'urn:tdm:REGION/ACCOUNT
ID/default:deployment:BarcodeReaderFlow', systemId: 'urn:tdm:REGION/ACCOUNT ID/
default:system:BarcodeReaderFlow') {device1(deviceId: 'DeviceA') device2(deviceId:
'DeviceB') triggers {TenSecondTrigger(description: 'a trigger') {condition(expr:
'every 10 seconds') action(expr: 'ThingsGraph.startFlow(\"barcodeReaderFlow\",
bindings[name == \"device1\"].deviceId, bindings[name == \"device2\"].deviceId)')}}}}"
}
102
AWS IoT Things Graph User Guide
Create and Deploy a Flow (AWS IoT Things Graph console)
For cloud deployments, the CreateSystemInstance API also requires two additional parameters:
target
The target type for your deployment. For cloud deployments, specify CLOUD.
flowActionsRoleArn
The ARN of the IAM role that AWS IoT Things Graph assumes when it executes the flow. This
role must have read and write access to Lambda and AWS IoT and any other AWS services that
the flow uses when it executes.
After you construct the JSON payload that contains the GraphQL definition of the flow
configuration, upload it to your namespace by using the following CLI command. The output of this
command includes an ID for your flow configuration. You use this value when you deploy the flow
configuration.
Deploy your flow configuration to the cloud by using the DeploySystemInstance API.
The following command shows how to deploy a flow configuration by using the AWS CLI.
In the Flow configuration pane, enter a name for your flow. This name can't contain any spaces.
103
AWS IoT Things Graph User Guide
Create and Deploy a Flow (AWS IoT Things Graph console)
On the Logic tab, choose Clock, and then drag it into the flow designer.
Search for DeviceA, which is a barcode reader that you created in Creating and Uploading Models.
Select the device and drag it into the flow designer. Do the same for DeviceB.
In the flow designer, select the edge of ClockTrigger and connect it to DeviceA. Connect DeviceA
and DeviceB in the same way.
The event appears between the two devices because DeviceA passes an output (the bar code) to
DeviceB. You can pass this output to multiple devices and services by connecting this event to them,
as in the following image.
This is the correct way to pass output to multiple entities. Directly connecting one device or service
to multiple devices or services causes a syntax error when you try to publish the flow.
5. Update the ClockTrigger.
In the trigger editor that appears in the right pane, for Frequency, enter 10, and then select seconds
from the menu on the right. For Action, choose ThingsGraph.startFlow.
6. Update the device action for DeviceA.
In the flow designer, select DeviceB. Select No action configured in the action editor that appears
in the right pane. Select readBarcode from the drop-down box that appears. Select the arrow that
appears to the left of the Output option. Enter deviceAResult in the text box that appears under
Output.
Click the surface of the flow designer to close the action editor.
7. Update the device action for DeviceB.
In the flow designer, select DeviceB. Select No action configured in the action editor that appears
in the right pane. Select doSomething from the drop-down box that appears. Select Define Input
104
AWS IoT Things Graph User Guide
Create and Deploy a Flow (AWS IoT Things Graph console)
under the Inputs option. Enter ${deviceAResult} in the pop-up box that appears. Select the Save
Input button
Click the surface of the flow designer to close the action editor.
8. Publish the flow.
Choose Publish at the upper right of the page. This creates the flow and adds it to the list of flows
that can be deployed. Then choose Go to flow list to verify that your flow is created.
9. Start creating the flow configuration.
On the Flows list page, select the check box next to the flow that you just created, and then choose
Create flow configuration.
On the Describe flow configuration page, select your flow and enter a deployment name. The
deployment name can't contain spaces. Choose Cloud, and then choose Next.
11. Configure the target.
On the Configure target page, enter the ARN of the role that you created in Prepare for Cloud
Deployments. Choose Next.
105
AWS IoT Things Graph User Guide
Create and Deploy a Flow (AWS IoT Things Graph console)
On the Map Things page, from the menu under deviceA, select the thing that you associated with
this device in Creating and Uploading Models. Do the same for deviceB. Choose Next.
On the Set up triggers page, the following GraphQL appears in the editor. This GraphQL specifies
the time intervals at which the flow runs. This flow runs every 10 seconds. You don't need to edit
this code.
Choose Review.
106
AWS IoT Things Graph User Guide
Revising Flows
On the Review and create page, review the information you entered for your flow configuration.
Choose Create.
15. Deploy
When the Flow configuration created message appears, choose Deploy now.
After a successful deployment, the Deployments page displays Deployed in target in the Status
column.
Revising Flows
After you deploy a flow, you might want to revise it. Each flow is associated with a namespace version.
When you revise or create a flow, you should specify a compatible namespace version. This ensures that
the flow continues to work even if the entities in your namespace are revised or deprecated.
107
AWS IoT Things Graph User Guide
Adding Triggers to Flows
The UpdateFlowTemplate also takes the compatibleNamespaceVersion parameter. You can use
compatibleNamespaceVersion to associate the updated version of the flow with a version of the
namespace that is compatible with your flow updates.
Because flows aren't versioned, you can't update earlier implementations of a flow. You can revise only
the latest version of a flow.
For more information about namespaces, see AWS IoT Things Graph Namespaces.
You add time-based triggers to a flow using the Logic tab in the flow designer in the AWS IoT Things
Graph console. A time-based trigger starts a flow after an interval of time that you define passes.
You can also use a device as a trigger if its capability contains at least one event. You specify a set of
conditions that the event creates that triggers the flow.
This topic describes how to use the AWS IoT Things Graph console to include time-based and device
triggers in your flows.
Time-Based Triggers
To include a time-based trigger, on the Logic tab, choose Clock, and then drag it into the flow designer.
This adds a node named ClockTrigger to the designer.
In the trigger editor that appears in the right pane, for Frequency, enter any number. Then from the
menu on the right, select the type of time interval to use. Your choices are seconds, minutes, hours,
days, weeks, months, and years.
108
AWS IoT Things Graph User Guide
Device Triggers
For Action, choose ThingsGraph.startFlow. This is currently the only option for Action.
Device Triggers
When you include a device that has one or more events and no actions in its capability, the device is
automatically a trigger, and the Set as Trigger switch in the right pane is disabled. This sort of device can
only be a trigger and never a step in a flow.
When you use an event that has one or more actions and no events in its capability, the device is
automatically a step and the Set as Trigger switch is disabled.
When you include a device that has one or more events and one or more actions, the device is a step by
default, but the Set as Trigger switch is enabled. If you choose to set the device as a trigger, the trigger
editor appears in the right pane. From the Condition event menu in this editor, select the event to use.
For Action, choose ThingsGraph.startFlow. This is currently the only option for Action.
The following screenshot shows a button that has a ButtonPressed event in its capability. This event
is selected under Condition event. The ButtonPressed event returns a payload that consists of one
Boolean value named isLightOn. This value is stored in the lastEvent variable. The lastEvent
variable stores values emitted by the trigger device's last event.
109
AWS IoT Things Graph User Guide
Triggers and Flow Configurations
You can use the values stored in the lastEvent variable to write an expression that starts a flow
whenever a condition is met. You enter this expression in the Condition expression field. In this case, the
button's ButtonPressed event starts the flow when the value of lastEvent.isLightOn is false. To
start the flow every time the event occurs, leave the Condition expression field blank.
You can write more complex expressions depending on the number and types of values emitted by the
trigger event. For example, if a device emits a lastEvent variable that two properties named type and
value, you could write the following expression.
This topic shows you how to use choice nodes to create a time-based flow that turns a light on and off
depending on the time of day. It assumes that your namespace includes a service that implements an
AWS Lambda function that returns the hour of the day as an Int. It also assumes that your namespace
contains a device model for a light that has TurnOn and TurnOff actions.
This example is for demonstration purposes only. You can apply the approach in this example any
workflow (flow) that contains the following elements.
110
AWS IoT Things Graph User Guide
Create the Flow
• A service that implements a Lambda function that returns information about a current condition, such
as time or temperature.
For information about how to create a service, see Service Modeling 101.
• A device or device model that contains the equivalent of TurnOn and TurnOff actions.
For examples that show how to create devices with actions, see Example Device and Service
Definitions. For more detailed information about creating a model, see AWS IoT Things Graph Data
Model Reference.
1. Open the AWS IoT Things Graph console, and then choose Create flow.
2. Create a flow.
111
AWS IoT Things Graph User Guide
Create the Flow
On the Logic tab, choose Clock, and then drag it into the flow designer.
On the Service tab, search for your Lambda service. Choose the service and drag it into the flow
designer.
On the Logic tab, choose Choice, and then drag it into the flow designer.
On the Devices tab, choose your device or device model, and then drag it into the flow designer.
Drag this same device into the flow designer a second time.
The two instances of the device or device model represent different steps that can occur in the flow,
depending on the choice node output.
In the flow designer, connect the ClockTrigger to the Lambda function. Connect the Lambda
function to the choice node. Connect the choice node to both instances of the device.
The flow designer displays one event between the Lambda function and the choice node, and one
event between the choice node and each instance of the device or device model. You can change the
default name of the event that follows the Lambda function. The other events will be named after
events that you create in the choice node.
112
AWS IoT Things Graph User Guide
Configure Events and Choice Node Logic
In the flow designer, select the ClockTrigger. In the trigger editor that appears in the right pane,
for Frequency, enter 1, and then select hours from the menu on the right. For Action, choose
ThingsGraph.startFlow.
In the flow designer, select the service. In the action editor that appears in the right pane, select
No action configured. Select the action that generates the output for the choice node. Provide
a variable name to store the output. The logic in the choice node uses the value or values in this
output to create events.
113
AWS IoT Things Graph User Guide
Configure Events and Choice Node Logic
In the flow designer, select the choice node. In the choice editor that appears in the right pane, enter
a value for Choice title.
4. Configure the condition for the first rule in the choice node.
Enter an expression that evaluates the output from the Lambda service. In this example, the rule
evaluates the current hour to determine whether the current hour is at night: ${getHourResult >
14}.
114
AWS IoT Things Graph User Guide
Configure Events and Choice Node Logic
5. Configure the event for the first rule in the choice node.
Choose Add event. Enter an event name. In this example, the rule creates an event named isNight
whenever the expression in the condition evaluates to true.
115
AWS IoT Things Graph User Guide
Configure Events and Choice Node Logic
6. Configure the condition for the second rule in the choice node.
Choose Add rule. Expand Rule B. Optionally, enter a title for the rule.
Enter an expression that evaluates the output from the Lambda service. In this example, the
rule evaluates the current hour to determine whether the current hour is in the daytime:
${getHourResult <= 13}.
116
AWS IoT Things Graph User Guide
Configure Events and Choice Node Logic
7. Configure the event for the second rule in the choice node.
Choose Add event. Enter an event name. In this example, the rule creates an event named isDay
whenever the expression in the condition evaluates to true.
117
AWS IoT Things Graph User Guide
Configure Events and Choice Node Logic
Expand Default rule. This rule determines what happens when the output from the previous step
is unexpected. You can create new events and variables for this rule. This example defaults to the
isNight event.
Note
The default event is required.
118
AWS IoT Things Graph User Guide
Configure Events and Choice Node Logic
Choose one of the events that follow the choice node. Enter the name of one of events that you
created in the choice node. Choose the other event, and enter the name of the other choice node
event. When you start typing, the flow designer prompts you to autocomplete the events that you
created in the choice node.
119
AWS IoT Things Graph User Guide
Using Conditional Logic in Choice Nodes
Select the device or device model that is connected to the isNight event. Choose No action
configured, and select the turnOn action.
Select the device or device model that is connected to the isDay event. Choose No action
configured, and select the turnOff action.
In this example, the same device executes one of two possible steps, depending on the events that are
emitted by the choice node. The same device can be used in multiple steps and perform different actions
depending on the events emitted by the choice node. You can use choice nodes to execute more complex
logic depending on the number of rules, the complexity of the expressions in the rules, and the number
of variables that you create.
For more information about expressions in choice nodes, see Using Conditional Logic in Choice Nodes.
Topics
• Adding Choice Nodes and Rules to Your Flow (p. 120)
• Writing Expressions in Rules (p. 123)
Example
A clock triggers a service that checks the time of day every hour. A choice node decides whether to turn a
light on or off depending on the current time.
1. Choose the Logic tab on the right side of the flow designer.
120
AWS IoT Things Graph User Guide
Using Conditional Logic in Choice Nodes
121
AWS IoT Things Graph User Guide
Using Conditional Logic in Choice Nodes
The choice activity editor displays a text box that you use to add an optional title. The editor also
contains one rule named Rule A and a default rule. Choose Add rule to add more rules.
Example
The following image shows what the flow designer canvas looks like when you configure the choice node
and connect it to the potential next steps (the light turns on or off).
Rules tie conditions to events. If a condition in the rule is met, the choice node fires an event specified in
the rule. You name each event that follows the choice node after the events that you create in the rules.
The default rule specifies which event to use when conditions in the other rules aren't met. The default
rule is required. The events connect the choice node to conditional steps in the flow.
122
AWS IoT Things Graph User Guide
Using Conditional Logic in Choice Nodes
The following table lists the data types of the values used in these expressions.
getHourResult Int
getHourResultA Int
getHourResultB Int
String Concatenation
The following example shows how to concatenate strings inside expressions.
The following table lists the data types of the values used in this expression.
message String
getHourResult Int
Logical Operators
Use the following operators for logical AND, OR, and NOT.
Logic Operator
AND &&
123
AWS IoT Things Graph User Guide
Using Conditional Logic in Choice Nodes
Logic Operator
OR ||
NOT !
Example
The following table lists the data types of the values used in this expression.
getHourResult Int
isDay Boolean
isNight Boolean
124
AWS IoT Things Graph User Guide
Creating Systems
Topics
• Creating Systems (p. 125)
• Creating Flow Configurations (AWS IoT Greengrass) (p. 126)
• Creating Flow Configurations (Cloud) (p. 133)
• Viewing Flow Configurations and Flow Executions in the AWS IoT Things Graph Console (p. 141)
Creating Systems
A system is a collection of devices, services, and a workflow (flow) that interact with each other in an IoT
system. A system consists of AWS IoT and AWS IoT Things Graph flows.
When you create a flow in the AWS IoT Things Graph console, the console creates a system for you. For
example, the system in Creating a Flow with Devices and a Service contains RekognitionFlow. The
following AWS IoT Things Graph Data Model (TDM) code shows the underlying definition of the system
created in that example. Replace the REGION and ACCOUNT ID placeholders with your AWS Region and
account ID.
In this system:
• @systemType declaration creates a system whose identifier is the TDM URN inside the parentheses.
• motionSensor: MotionSensor, etc. are used to assign the device or device models and the flow to
names (on the left side of each colon) that the flow configuration uses. The flow configuration uses the
flow name to start the flow. It uses the device and device model names to assign specific things in your
registry to each device or device model. In the flow configuration, these names must match the names
in the system exactly.
• @thing declarations specify the devices or device models in the system.
• @workflow declarations specify the flows in the system. You don't need to specify services in the
system definition.
• You can include more than one flow in a system (as long as you write the TDM yourself). This enables
you to deploy more than one flow at a time.
125
AWS IoT Things Graph User Guide
Creating Flow Configurations (AWS IoT Greengrass)
The following command shows how to create a system by using the AWS CLI.
For more information about creating a system programmatically, see CreateSystemTemplate in the AWS
IoT Things Graph API Reference
This section describes the structure of a flow configuration and shows how to create one with the AWS
CLI and the AWS IoT Things Graph console.
Topics
• Creating a Flow Configuration in the AWS CLI (p. 126)
• Creating a Flow Configuration in the AWS IoT Things Graph console (p. 129)
triggers {
MotionEventTrigger(description: 'a trigger') {
condition(expr: "devices[name == 'motionSensor'].events[name ==
'StateChanged'].lastEvent.value")
126
AWS IoT Things Graph User Guide
Creating a Flow Configuration in the AWS CLI
Now that you have a complete deployment definition, you can create the flow configuration by using the
AWS CLI.
The values that follow the flow name inside the action can be any valid flow parameters. The following
example triggers show some of the values and path expressions that you can use inside the action block
of a trigger.
127
AWS IoT Things Graph User Guide
Creating a Flow Configuration in the AWS CLI
• target parameter – Specifies the target type of the deployment. For AWS IoT Greengrass
deployments, specify GREENGRASS.
• greengrass-group-name parameter – Specifies the name of the AWS IoT Greengrass group to which
the flow configuration is deployed.
• s3-bucket-name parameter – Specifies the Amazon S3 bucket that's used to store and deploy the
resource file of the flow configuration.
When the operation completes, the AWS CLI returns the following deployment summary (as a JSON
object).
{
"summary": {
"status": "PENDING_DEPLOYMENT",
"greengrassGroupName": "AWS IoT Greengrass Group Name",
"target": "GREENGRASS",
"arn": "arn:aws:iotthingsgraph:REGION:ACCOUNT ID:default#Deployment#Lobby",
"updatedAt": 1547245009.256,
"id": "urn:tdm:REGION/ACCOUNT ID/default:Deployment:Lobby",
"createdAt": 1547245009.256
}
}
• The status value in the summary object is PENDING_DEPLOYMENT when a flow configuration is
created.
• The id value in the summary block is the TDM URN of the flow configuration.
The following command uses the id value to deploy the flow configuration to the target.
For more information about creating a flow configuration programmatically, see CreateSystemInstance
in the AWS IoT Things Graph API Reference.
128
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
Select the menu icon at the upper left of the page, and then select Flows to return to the Flows
page. On the Flows page, select the box next to the flow that you just created, and then choose
Create flow configuration.
On the Describe flow configuration page, select your flow, and then enter a flow configuration
name. The flow configuration name can't contain spaces. Choose Greengrass, and then choose Next.
129
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
On the Configure target page, enter the name of your Amazon S3 bucket and the AWS IoT
Greengrass group to which your AWS IoT Greengrass core device belongs. Choose Next.
130
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
The Map Things page provides an interface for selecting the specific things that you'll include in
your deployment. The menus under each device in your deployment contain all of the things that
you associated with the device. Because you're getting started, the menus for each device on this
page will include only one thing (the thing that you've associated with each device).
On the Map Things page, under the motionSensor device, select the motion sensor thing that you
created earlier. Select the camera and screen things for the Camera and Screen devices. Choose
Next.
On the Define trigger page, the GraphQL that defines the motion event trigger for the flow appears
in the editor. When the motion sensor detects motion, the ThingsGraph.startFlow function
initiates the flow. You don't need to edit this code.
Choose Review.
131
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
On the Review and create page, review the information you entered for your flow configuration.
Choose Create.
132
AWS IoT Things Graph User Guide
Creating Flow Configurations (Cloud)
7. Deploy.
When the Flow configuration created message appears, choose Deploy now.
After a successful deployment, the Deployments page displays Deployed in target in the Status
column.
133
AWS IoT Things Graph User Guide
Creating a Flow Configuration in the AWS CLI
deployment definition. The attributes in the definition specify other required resources, such as the IAM
role that AWS IoT Things Graph assumes when it executes the flow in the cloud.
This section describes the structure of a flow configuration and shows how to create one with the AWS
IoT Things Graph console and the AWS CLI.
Topics
• Creating a Flow Configuration in the AWS CLI (p. 134)
• Creating a Flow Configuration in the AWS IoT Things Graph console (p. 136)
triggers {
MotionEventTrigger(description: 'a trigger') {
condition(expr: "devices[name == 'motionSensor'].events[name ==
'StateChanged'].lastEvent.value")
action(expr: "ThingsGraph.startFlow('RekognitionFlow', bindings[name ==
'cameraRkgnExample'].deviceId, bindings[name == 'screen'].deviceId)")
}
}
}
134
AWS IoT Things Graph User Guide
Creating a Flow Configuration in the AWS CLI
• The triggers block contains one or more triggers. The MotionEventTrigger in this example
consists of a condition that triggers the flow and the action that starts when the trigger condition
is met.
• The condition uses two path expressions to identify a device that is used in a flow and one of that
device's events, with a predicate expression that determines whether the device has detected
motion. If the lastEvent value sent by the motionSensor device is true, a non-empty string, or
a numeric value other than zero (0), the devices[name == 'motionSensor'].events[name
== 'StateChanged'].lastEvent.value expression evaluates to true. This signifies that
a motion detected event has occurred. If you want the expression to evaluate to true every
time the event is fired, use devices[name == 'motionSensor'].events[name ==
'StateChanged'].lastEvent.
• The action uses the ThingsGraph.startFlow function, which initiates the specified flow. The flow
name matches the name of the flow in the system definition. The bindings path expressions specify
the names of the things that are used in the flow.
Now that you have a complete deployment definition, you can create the flow configuration by using the
AWS CLI.
The values that follow the flow name inside the action can be any valid flow parameters. The following
example triggers show some of the values and path expressions that you can use inside the action block
of a trigger.
• target parameter – Specifies the target type of the deployment. For cloud deployments, specify
CLOUD.
• flow-actions-role-arn parameter – Specifies the role that AWS IoT Things Graph assumes when
it executes the flow in the cloud. For instructions on how to create this role, see Prepare for Cloud
Deployments.
135
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
When the operation completes, the AWS CLI returns the following deployment summary (as a JSON
object).
{
"summary": {
"status": "PENDING_DEPLOYMENT",
"greengrassGroupName": "AWS IoT Greengrass Group Name",
"target": "GREENGRASS",
"arn": "arn:aws:iotthingsgraph:REGION:ACCOUNT ID:default#Deployment#Lobby",
"updatedAt": 1547245009.256,
"id": "urn:tdm:REGION/ACCOUNT ID/default:Deployment:Lobby",
"createdAt": 1547245009.256
}
}
• The status value in the summary object is PENDING_DEPLOYMENT when a flow configuration is
created.
• The id value in the summary block is the TDM URN of the flow configuration.
The following command uses the id value to deploy the flow configuration to the target.
For more information about creating a flow configuration programmatically, see CreateSystemInstance
in the AWS IoT Things Graph API Reference.
Select the menu icon at the upper left of the page, and then select Flows to return to the Flows
page. On the Flows page, select the box next to the flow that you just created, and then choose
Create flow configuration.
136
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
On the Describe flow configuration page, select your flow, and then enter a flow configuration
name. The flow configuration name can't contain spaces. Choose Cloud, and then choose Next.
On the Configure target page, enter the ARN of the role that you created in Prepare for Cloud
Deployments. Choose Next.
137
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
The Map Things page provides an interface for selecting the specific things that you'll include in
your deployment. The menus under each device in your deployment contain all of the things that
you associated with the device. Because you're getting started, the menus for each device on this
page will include only one thing (the thing that you've associated with each device).
On the Map Things page, under the MotionSensor device, select the motion sensor thing that you
created earlier. Select the camera and screen things for the Camera and Screen devices. Choose
Next.
On the Define trigger page, the GraphQL that defines the motion event trigger for the flow appears
in the editor. When the motion sensor detects motion, the ThingsGraph.startFlow function
initiates the flow. You don't need to edit this code.
138
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
Choose Review.
On the Review and create page, review the information you entered for your flow configuration.
Choose Create.
139
AWS IoT Things Graph User Guide
Creating a Flow Configuration in
the AWS IoT Things Graph console
7. Deploy.
When the Flow configuration created message appears, choose Deploy now.
After a successful deployment, the Deployments page displays Deployed in target in the Status
column.
140
AWS IoT Things Graph User Guide
Viewing Flow Configurations and Flow
Executions in the AWS IoT Things Graph Console
The deployment details page also provides a list of flow executions. Each flow execution links to a page
that contains the messages that each flow execution sent. These messages provide information such as
the time when each step begins executing, when it completes successfully, and when it fails.
This topic describes the features of the flow configurations and flow executions pages and how to access
them.
Flow Configurations
The main page of the flow configurations section lists all of the flow configurations that you've created.
For each flow configuration, t also lists the ID (an AWS IoT Things Graph Data Model [TDM] URN),
the status, and date created. For AWS IoT Greengrass deployments, it lists the name of the AWS IoT
Greengrass group that is the deployment target of the flow configuration.
To see more detailed summary data about a flow configuration, click its name. The next page displays
general configuration information about the flow configuration.
The Assigned Things section of this page also displays the things from your AWS IoT registry that you
assigned to the devices or device models in the flow.
141
AWS IoT Things Graph User Guide
Flow Executions
Flow Executions
To see a list of flow executions for the flow configuration, choose the Flow executions tab. The Flow
executions page contains a list that shows every execution of the flow after you deployed it. A flow
execution begins every time a trigger starts a flow, and it ends at the successful or unsuccessful
completion of the flow.
You can use this page to determine when the flow in your flow configuration is failing to complete. If
you're looking for details about flow executions within a specific time frame, you can search for the
execution start date and time.
To view the messages for a specific flow execution, select the flow execution, and then choose View
details in the upper right of the page.
The Flow executions messages page displays messages for each step and activity in the flow. It indicates
when a step is scheduled, when a step starts, and when an activity starts. It displays the values of the
flow parameters and the inputs that AWS IoT Things Graph passed to each step and activity in the flow.
It also indicates when a failure occurred. You can use this page to troubleshoot flow execution failures.
142
AWS IoT Things Graph User Guide
Flow Executions
143
AWS IoT Things Graph User Guide
Monitoring with CloudWatch
• Amazon CloudWatch monitors your AWS resources and the applications you run on AWS in real
time. You can collect and track metrics, create customized dashboards, and set alarms that notify
you or take actions when a metric reaches a threshold that you specify. For example, you can have
CloudWatch track CPU usage or other metrics of your Amazon EC2 instances and automatically launch
new instances when needed. For more information, see the Amazon CloudWatch User Guide.
• Amazon CloudWatch Events delivers a near real-time stream of system events that describe changes in
AWS resources. CloudWatch Events enables automated event-driven computing, because you can write
rules that watch for certain events and trigger automated actions in other AWS services when these
events happen. For more information, see the Amazon CloudWatch Events User Guide.
• Amazon CloudWatch Logs lets you monitor, store, and access your log files from Amazon EC2 instances,
CloudTrail, and other sources. CloudWatch Logs can monitor information in the log files and notify
you when certain thresholds are met. You can also archive your log data in highly durable storage. For
more information, see the Amazon CloudWatch Logs User Guide.
• AWS CloudTrail captures API calls and related events made by or on behalf of your AWS account
and delivers the log files to an Amazon S3 bucket that you specify. You can identify which users
and accounts called AWS, the source IP address from which the calls were made, and when the calls
occurred. For more information, see the AWS CloudTrail User Guide.
Topics
• Monitoring AWS IoT Things Graph with Amazon CloudWatch (p. 144)
• Logging AWS IoT Things Graph API Calls with AWS CloudTrail (p. 146)
CloudWatch collects data only for cloud deployments of flow configurations. CloudWatch isn't available
for AWS IoT Greengrass deployments.
144
AWS IoT Things Graph User Guide
AWS IoT Things Graph Metrics
Example
The following AWS CLI example enables data collection for a new flow configuration.
The following tables list the metrics and dimensions for AWS IoT Things Graph.
Metric Description
145
AWS IoT Things Graph User Guide
Dimensions for AWS IoT Things Graph Metrics
Dimension Description
If you create a trail, you can enable continuous delivery of CloudTrail events to an Amazon S3 bucket,
including events for AWS IoT Things Graph. If you don't configure a trail, you can still view the most
recent events in the CloudTrail console in Event history.
Using the information that CloudTrail collects, you can determine the request that was made to AWS IoT
Things Graph, the IP address from which the request was made, who made the request and when, and
more details.
To learn more about CloudTrail, see the AWS CloudTrail User Guide.
For an ongoing record of events in your AWS account, including events for AWS IoT Things Graph, create
a trail. A trail enables CloudTrail to deliver log files to an Amazon Simple Storage Service (Amazon S3)
bucket. By default, when you create a trail in the console, the trail applies to all AWS Regions. The trail
logs events from all Regions in the AWS partition and delivers the log files to the Amazon S3 bucket that
you specify.
You can also configure other AWS services to further analyze and act on the event data collected in
CloudTrail logs. For more information, see the following:
146
AWS IoT Things Graph User Guide
Understanding AWS IoT Things Graph Log File Entries
CloudTrail logs all AWS IoT Things Graph actions. They're documented in the AWS IoT Things Graph
API Reference. For example, calls to the UploadEntityDefinitions, CreateSystemInstance and
CreateFlowTemplate actions generate entries in the CloudTrail log files.
Every event or log entry contains information about who generated the request. The identity
information helps you determine the following:
• Whether the request was made with root or AWS Identity and Access Management (IAM) user
credentials.
• Whether the request was made with temporary security credentials for a role or federated user.
• Whether the request was made by another AWS service.
CloudTrail log files contain one or more log entries. An event represents a single request from any
source and includes information about the requested action, the date and time of the action, request
parameters, and so on.
CloudTrail log files aren't an ordered stack trace of the public API calls, so they don't appear in any
specific order.
Example
The following CloudTrail log entry shows information about the UploadEntityDefinitions action.
{
"eventVersion": "1.05",
"userIdentity": {
"type": "IAMUser",
"principalId": "principal-id",
"arn": "arn:aws:iam::123456789012:user/TodRunner",
"accountId": "123456789012",
"accessKeyId": "access-key-id",
"userName": "TodRunner"
},
"eventTime": "2019-02-22T22:56:35Z",
"eventSource": "iotthingsgraph.amazonaws.com",
"eventName": "UploadEntityDefinitions",
"awsRegion": "us-east-1",
"sourceIPAddress": "127.0.0.1",
"userAgent": "aws-internal/3 aws-sdk-java/1.11.498 Mac_OS_X/10.12.6
Java_HotSpot(TM)_64-Bit_Server_VM/25.181-b13 java/1.8.0_181",
"requestParameters": {
"document": {
"language": "GRAPHQL",
"text": "{type Uri @propertyType(id: \"urn:tdm:us-east-1/123456789012/
default:Property:UriAcceptanceSimpleFlow\", dataType: STRING){ignore:void}\ntype
MotionDetected @propertyType(id: \"urn:tdm:us-east-1/123456789012/
default:Property:MotionDetectedAcceptanceSimpleFlow\", dataType: String)
147
AWS IoT Things Graph User Guide
Understanding AWS IoT Things Graph Log File Entries
148
AWS IoT Things Graph User Guide
Understanding AWS IoT Things Graph Log File Entries
default:State:QualityStateAcceptanceSimpleFlow') { Brightness:
Float64 @property(id:'urn:tdm:aws:Property:Float64'),
Sharpness: Float64 @property(id:'urn:tdm:aws:Property:Float64')}\ntype
ResponseState @stateType(id:'urn:tdm:us-east-1/123456789012/
default:State:ResponseStateAcceptanceSimpleFlow') { FaceDetails:
[FaceDetailsProperty] @property(id:'urn:tdm:us-east-1/123456789012/
default:Property:FaceDetailsPropertyAcceptanceSimpleFlow'), OrientationCorrection:
String @property(id:'urn:tdm:aws:Property:String')}\n type Capture @actionType(id:
\"urn:tdm:us-east-1/123456789012/default:Action:CaptureAcceptanceSimpleFlow
\") { return : Uri @property(id: \"urn:tdm:us-east-1/123456789012/
default:Property:UriAcceptanceSimpleFlow\") }\n type Display @actionType(id:
\"urn:tdm:us-east-1/123456789012/default:Action:DisplayAcceptanceSimpleFlow
\") { url : Uri @property(id: \"urn:tdm:us-east-1/123456789012/
default:Property:UriAcceptanceSimpleFlow\") }\n type Switch @actionType(id:
\"urn:tdm:us-east-1/123456789012/default:Action:SwitchAcceptanceSimpleFlow
\") { input : Boolean @property(id: 'urn:tdm:aws:Property:Boolean')
}\n type MatchImage @actionType(id: \"urn:tdm:us-east-1/123456789012/
default:Action:MatchImageAcceptanceSimpleFlow\") {\n url : Uri @property(id:
\"urn:tdm:us-east-1/123456789012/default:Property:UriAcceptanceSimpleFlow
\")\n return : Boolean @property(id: 'urn:tdm:aws:Property:Boolean')\n
}\n\n type CreateQueue @actionType(id: \"urn:tdm:us-east-1/123456789012/
default:action:CreateQueueAcceptanceSimpleFlow\") {\n queueName: String
@property(id: 'urn:tdm:aws:Property:String')\n }\n\n type SendMessage @actionType(id:
\"urn:tdm:us-east-1/123456789012/default:action:SendMessageAcceptanceSimpleFlow
\") {\n message: String @property(id: 'urn:tdm:aws:Property:String')\n
}\n\n type DetectFaces @actionType(id: \"urn:tdm:us-east-1/123456789012/
default:action:DetectFacesAcceptanceSimpleFlow\") {\n bucketName: String
@property(id: 'urn:tdm:aws:Property:String')\n itemName: String @property(id:
'urn:tdm:aws:Property:String')\n return: ResponseProperty @property(id:
'urn:tdm:us-east-1/123456789012/default:Property:ResponsePropertyAcceptanceSimpleFlow')\n
}\n\n type MotionDetectedEvent @eventType(id: \"urn:tdm:us-east-1/123456789012/
default:Event:MotionDetectedEventAcceptanceSimpleFlow\",
payload: \"urn:tdm:us-east-1/123456789012/
default:Property:MotionDetectedAcceptanceSimpleFlow\") {ignore:void}\n
type CameraCap @capabilityType(id: \"urn:tdm:us-east-1/123456789012/
default:Capability:CameraCapAcceptanceSimpleFlow\") { STATE: CameraState @state(id:
\"urn:tdm:us-east-1/123456789012/default:State:CameraStateAcceptanceSimpleFlow
\") capture: Capture @action(id: \"urn:tdm:us-east-1/123456789012/
default:Action:CaptureAcceptanceSimpleFlow\") }\n type CameraCap_V2 @capabilityType(id:
\"urn:tdm:us-east-1/123456789012/default:Capability:CameraCap_V2AcceptanceSimpleFlow
\") { STATE: CameraState_V2 @state(id: \"urn:tdm:us-east-1/123456789012/
default:State:CameraState_V2AcceptanceSimpleFlow\") capture: Capture @action(id:
\"urn:tdm:us-east-1/123456789012/default:Action:CaptureAcceptanceSimpleFlow
\") }\n type ScreenCap @capabilityType(id: \"urn:tdm:us-
east-1/123456789012/default:Capability:ScreenCapAcceptanceSimpleFlow\")
{ STATE: ScreenState @state(id: \"urn:tdm:us-east-1/123456789012/
default:State:ScreenStateAcceptanceSimpleFlow\") display: Display @action(id:
\"urn:tdm:us-east-1/123456789012/default:Action:DisplayAcceptanceSimpleFlow
\") }\n type MotionSensorCap @capabilityType(id: \"urn:tdm:us-
east-1/123456789012/default:Capability:MotionSensorCapAcceptanceSimpleFlow\")
{ STATE: MotionSensorState @state(id: \"urn:tdm:us-east-1/123456789012/
default:State:MotionSensorStateAcceptanceSimpleFlow\") motionDetected:
MotionDetectedEvent @event(id: \"urn:tdm:us-east-1/123456789012/
default:Event:MotionDetectedEventAcceptanceSimpleFlow\") }\n type
MlLambdasCap @capabilityType(id: \"urn:tdm:us-east-1/123456789012/
default:Capability:MlLambdasCapAcceptanceSimpleFlow\") {\n
matchImageLocal: MatchImage @action(id: \"urn:tdm:us-east-1/123456789012/
default:Action:MatchImageAcceptanceSimpleFlow\")\n matchImageGlobal: MatchImage
@action(id: \"urn:tdm:us-east-1/123456789012/default:Action:MatchImageAcceptanceSimpleFlow
\")\n }\n\n type SqsCap @capabilityType(id: \"urn:tdm:us-
east-1/123456789012/default:capability:SqsCapAcceptanceSimpleFlow
\") {\n createQueue: CreateQueue @action(id: \"urn:tdm:us-
east-1/123456789012/default:action:CreateQueueAcceptanceSimpleFlow\")\n
sendMessage: SendMessage @action(id: \"urn:tdm:us-east-1/123456789012/
default:action:SendMessageAcceptanceSimpleFlow\")\n }\n\n type
RekognitionCap @capabilityType(id: \"urn:tdm:us-east-1/123456789012/
149
AWS IoT Things Graph User Guide
Understanding AWS IoT Things Graph Log File Entries
default:capability:RekognitionCapAcceptanceSimpleFlow\") {\n
detectFaces: DetectFaces @action(id: \"urn:tdm:us-east-1/123456789012/
default:action:DetectFacesAcceptanceSimpleFlow\")\n }\n\n type
LightCap @capabilityType(id: \"urn:tdm:us-east-1/123456789012/
default:Capability:LightCapAcceptanceSimpleFlow\") { state: LightState @state(id:
\"urn:tdm:us-east-1/123456789012/default:State:LightStateAcceptanceSimpleFlow
\") switch: Switch @action(id: \"urn:tdm:us-east-1/123456789012/
default:Action:SwitchAcceptanceSimpleFlow\") }\n type Camera @deviceModel(id:
\"urn:tdm:us-east-1/123456789012/default:DeviceModel:CameraAcceptanceSimpleFlow
\", capability: \"urn:tdm:us-east-1/123456789012/
default:Capability:CameraCapAcceptanceSimpleFlow\"){ IGNORE : VOID
}\n type Camera_V2 @deviceModel(id:\"urn:tdm:us-east-1/123456789012/
default:DeviceModel:Camera_V2AcceptanceSimpleFlow\",
capability: \"urn:tdm:us-east-1/123456789012/
default:Capability:CameraCap_V2AcceptanceSimpleFlow\"){ IGNORE :
VOID }\n type Screen @deviceModel(id:\"urn:tdm:us-east-1/123456789012/
default:DeviceModel:ScreenAcceptanceSimpleFlow\", capability:
\"urn:tdm:us-east-1/123456789012/default:Capability:ScreenCapAcceptanceSimpleFlow
\"){ IGNORE : VOID }\n type MotionSensor @deviceModel(id: \"urn:tdm:us-
east-1/123456789012/default:DeviceModel:MotionSensorAcceptanceSimpleFlow
\", capability: \"urn:tdm:us-
east-1/123456789012/default:Capability:MotionSensorCapAcceptanceSimpleFlow
\") { IGNORE : VOID }\n type Light @deviceModel(id: \"urn:tdm:us-
east-1/123456789012/default:DeviceModel:LightAcceptanceSimpleFlow\",
capability: \"urn:tdm:us-east-1/123456789012/
default:Capability:LightCapAcceptanceSimpleFlow\") { IGNORE : VOID
}\n query PhyCamera @device(id: \"urn:tdm:us-east-1/123456789012/
default:Device:PhyCameraAcceptanceSimpleFlow\", deviceModel:
\"urn:tdm:us-east-1/123456789012/default:DeviceModel:CameraAcceptanceSimpleFlow
\") { MQTT { CameraCap(id: \"urn:tdm:us-east-1/123456789012/
default:Capability:CameraCapAcceptanceSimpleFlow\") { state {
lastClickedImage(name: \"lastImage\", property: \"urn:tdm:us-
east-1/123456789012/default:Property:UriAcceptanceSimpleFlow\")
} Action(name: \"capture\") { Publish {
Request(topic: \"camera/capture\") {
params } Response(topic:
\"camera/capture/finished\") { responsePayload(property:
\"urn:tdm:us-east-1/123456789012/default:Property:UriAcceptanceSimpleFlow\")
} } } }
} }\n query PhyCamera_V2 @device(id: \"urn:tdm:us-east-1/123456789012/
default:Device:PhyCamera_V2AcceptanceSimpleFlow\", deviceModel:
\"urn:tdm:us-east-1/123456789012/default:DeviceModel:Camera_V2AcceptanceSimpleFlow
\") { MQTT { CameraCap_V2(id: \"urn:tdm:us-east-1/123456789012/
default:Capability:CameraCap_V2AcceptanceSimpleFlow\") { state {
lastClickedImage(name: \"lastImage\", property: \"urn:tdm:us-
east-1/123456789012/default:Property:UriAcceptanceSimpleFlow\") }
Action(name: \"capture\") { Publish {
Request(topic: \"camera_v2/capture\") { params
} Response(topic: \"camera_v2/capture/
finished\") { responsePayload(property: \"urn:tdm:us-
east-1/123456789012/default:Property:UriAcceptanceSimpleFlow\")
} } } } } }\n query PhyScreen
@device(id: \"urn:tdm:us-east-1/123456789012/default:Device:PhyScreenAcceptanceSimpleFlow
\", deviceModel: \"urn:tdm:us-east-1/123456789012/
default:DeviceModel:ScreenAcceptanceSimpleFlow\") { MQTT { ScreenCap(id:
\"urn:tdm:us-east-1/123456789012/default:Capability:ScreenCapAcceptanceSimpleFlow\")
{ state { currentDisplayImage(name: \"displayUri\",
property: \"urn:tdm:us-east-1/123456789012/default:Property:UriAcceptanceSimpleFlow\")
} Action(name: \"display\") { params {
param(name:\"url\", property:\"urn:tdm:us-east-1/123456789012/
default:Property:UriAcceptanceSimpleFlow\") }
Payload { Request(topic: \"screen/display\") {
params { param(name: \"imageUri\",
property: \"urn:tdm:us-east-1/123456789012/
default:Property:UriAcceptanceSimpleFlow\", value:
\"${url.value}\") } }
150
AWS IoT Things Graph User Guide
Understanding AWS IoT Things Graph Log File Entries
151
AWS IoT Things Graph User Guide
Understanding AWS IoT Things Graph Log File Entries
152
AWS IoT Things Graph User Guide
Namespace Management
Namespace versioning protects your flows, systems, and deployment configurations from breaking when
you update or create devices and device models (either your own or ones that get added when you sync
with the public namespace). Changes that aren't backward compatible don't break existing deployments
or even new deployments of flows that contain the earlier versions.
Additionally, this topic describes how to delete existing entities from your namespace, and deprecate and
delete flows, systems, and deployment configurations.
Namespace Management
A namespace is the container for entities created by using the AWS IoT Things Graph Data Model (TDM)
language. These entities are associated with a specific account. The namespace is part of the URN for
each entity.
In the following example, the namespace is everything before the device name (DL05PLCUnits).
urn:tdm:REGION/ACCOUNT_ID/default:deviceModel:DL05PLCUnits
The following are the entities that are stored in your namespace:
• Properties
• States
• Events
• Actions
• Capabilities
• Mappings
• Devices
• Device Models
• Services
When you first upload an entity definition, AWS IoT Things Graph creates a namespace for you. This
namespace is in sync with the current version of the public namespace. AWS IoT Things Graph provides
a ValidateEntityDefinitions API that you can use to debug your TDM before you upload your entity
definitions. After confirming that your TDM is valid, you upload the definitions by using either the
UploadEntityDefinitions API or the AWS IoT Things Graph console.
AWS IoT Things Graph creates a new version of your namespace when you make a backward-
incompatible change. The following are examples of actions that prompt the creation of a new
namespace version:
153
AWS IoT Things Graph User Guide
Deleting Systems, Flows, and Namespaces
• You update any existing entity (property, action, event, and so on) in your namespace.
• You sync your namespace with the public namespace.
• You deprecate the existing entities in your namespace and replace them with a new set of entities.
You can update existing entities by using either the AWS IoT Things Graph console or the
UploadEntityDefinitions API. The UploadEntityDefinitions API has two optional Boolean parameters that
enable you to perform the other two actions:
• syncWithPublicNamespace
• deprecateExistingEntities
After the UploadEntityDefinitions operation completes, there is a short delay before the entities
are available in flows. When you're writing tests and scripted solutions, take this delay into account.
When you create a flow, by default AWS IoT Things Graph uses entities in the current version of your
namespace. When you deploy a flow, by default AWS IoT Things Graph validates it against the current
version of your namespace. This means that if you attempt to deploy a flow that contains entities that
are incompatible with the current namespace, by default the deployment fails. A flow that contains
deprecated entities also fails.
To specify an earlier namespace that contains entities that are compatible with a flow, use the optional
compatibleNamespaceVersion parameter of the CreateFlowTemplate API. If you create the flow with
this parameter, AWS IoT Things Graph validates your flow against the version value that you set with this
parameter when you deploy the flow. The CreateSystemTemplate also has this optional parameter, so
ensure that your system and flow are using the same namespace version when you deploy them.
When you create a flow in the AWS IoT Things Graph console, the console silently creates a system that
contains the flow for you. When you delete the flow, the AWS IoT Things Graph console also silently
deletes the system that contains the flow.
154
AWS IoT Things Graph User Guide
Deleting Flow Configurations
The DeleteFlowTemplate and DeleteSystemTemplate APIs enable you to delete a flow or system that
is deprecated. After you delete a flow, any system that contains the flow no longer updates or deploys.
After you delete a system, any deployment configuration that contains the system no longer updates or
deploys. Existing deployments that contain the flow continue to run because they use a snapshot of the
workflow that's taken at the time of deployment. The same is true for deployments that contain deleted
systems. You must delete all flows in a system before you delete the system.
To delete a namespace, use the DeleteNamespace API. Before you delete the namespace, you must
delete all systems, flows, and flow configurations that use entities in the namespace. Existing flow
deployments continue to work after you delete a namespace. AWS IoT Things Graph creates a snapshot
of the flow, flow configuration, system, and entities for each deployment.
1. Undeploy the flow configuration. This step removes the configuration from the AWS IoT Greengrass
group or the cloud.
2. Delete the flow configuration. This step removes the deployment configuration from AWS IoT Things
Graph.
The following procedure shows how to delete a deployment configuration by using the AWS IoT Things
Graph console.
On the Deployments page, select the flow configuration to delete. In the upper right of the page,
choose Undeploy. Enter Undeploy, and then choose Undeploy in the box that appears.
2. Delete the deployment configuration.
On the Deployments page, select the flow configuration to delete. In the upper right of the page,
choose Delete. Enter delete, and then choose Delete in the box that appears.
The UndeploySystemInstance and DeleteSystemInstance APIs also perform these two actions.
155
AWS IoT Things Graph User Guide
Data Protection in AWS IoT Things Graph
This documentation helps you understand how to apply the shared responsibility model when using
AWS IoT Things Graph. The following sections show you how to configure AWS IoT Things Graph to meet
your security and compliance objectives. You also learn how to use other AWS services that help you to
monitor and secure your AWS IoT Things Graph resources.
Control Plane
The AWS IoT Things Graph control plane uses IAM policies to define what a user can do. You can create
policies that assign permissions for every available action in the AWS IoT Things Graph API.
For example, the following policy assigns permission for a user to use the CreateSystemInstance API.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iotthingsgraph:CreateSystemInstance"
],
"Resource": [
"*"
]
}
}
{
"Version": "2012-10-17",
156
AWS IoT Things Graph User Guide
Control Plane
"Statement": [
{
"Effect": "Allow",
"Action": [
"iotthingsgraph:*"
],
"Resource": [
"*"
]
}
]
}
• s3:REST.GET.OBJECT
• s3:REST.PUT.OBJECT
• iot:CreateTopicRule
• iot:ListTopicRules
• iot:GetTopicRule
• iot:DescribeThing
• iot:ListThingPrincipals
• iot:UpdateThing
• iot:AddThingToThingGroup
• iot:DescribeThingGroup
• iot:CreateThingGroup
• iot:ListThingsInThingGroup
• iot:DeleteThingGroup
• iot:RemoveThingFromThingGroup
• greengrass:CreateGroupVersion
• greengrass:CreateDeployment
• greengrass:GetDeviceDefinitionVersion
• greengrass:CreateDeviceDefinitionVersion
• greengrass:CreateDeviceDefinition
• greengrass:GetFunctionDefinitionVersion
• greengrass:CreateFunctionDefinitionVersion
• greengrass:CreateFunctionDefinition
• greengrass:GetResourceDefinitionVersion
• greengrass:CreateResourceDefinitionVersion
• greengrass:CreateResourceDefinition
• greengrass:GetSubscriptionDefinitionVersion
• greengrass:CreateSubscriptionDefinitionVersion
• greengrass:CreateSubscriptionDefinition
• greengrass:ListGroups
• greengrass:GetGroupVersion
• greengrass:GetConnectorDefinitionVersion
• greengrass:CreateConnectorDefinition
• greengrass:CreateConnectorDefinitionVersion
• iam:PassRole
157
AWS IoT Things Graph User Guide
Data Plane
Namespaces
Every entity that you use in a workflow must belong to your namespace. See Namespaces for more
information.
Entities stored in an account's namespace are available to all users in an account. All users in the account
have read and write access to all entity definitions in the namespace.
Because you deploy AWS IoT Things Graph to AWS IoT Greengrass, you need to set up AWS IoT
Greengrass security by following the steps in Configuring Greengrass Security in the AWS IoT Greengrass
Developer Guide. When you deploy a workflow, you provide AWS IoT Things Graph with an IAM service
role. This role should contain all of the policies required for AWS IoT Things Graph to publish and
subscribe to all of the MQTT topics that are used in the workflow. For more information about IAM roles,
see Using IAM Roles.
Data Plane
AWS IoT Things Graph runs as an AWS Lambda function on the AWS IoT Greengrass core device. When
new workflows are deployed to AWS IoT Greengrass, AWS IoT Things Graph creates entries in the
subscription table for communication between the devices in the workflow and the AWS IoT Things
Graph Lambda function.
AWS IoT Things Graph therefore creates subscriptions to all of the MQTT topics that the devices in your
workflow use. The subscription table is used by the AWS IoT Greengrass core device for authorization of
all communications. The AWS IoT Things Graph Lambda function mediates communications among the
devices in the workflow.
158
AWS IoT Things Graph User Guide
Aukru HCSR501 Motion Sensor
Each topic in this section shows a single device definition. The definitions include the parent device
model, properties, states, actions, events, and capabilities that the device or service requires.
Some of these models are available in the AWS IoT Things Graph console. Each topic notes when that's
the case.
Service Definitions
• Rekognition
• getS3Lambda
• wordCount
• saveResponse
159
AWS IoT Things Graph User Guide
Raspberry Pi Camera
Raspberry Pi Camera
The following GraphQL shows the device definition for the Raspberry Pi Camera that is available in the
AWS IoT Things Graph console. This device is used in Creating a Flow with Devices.
# Camera state.
type CameraState @stateType(id: "urn:tdm:aws/examples:state:CameraState") {
lastClickedImage : Uri @property(id: "urn:tdm:aws:property:String")
}
# The Capture action takes no arguments and returns the state of the device after
completing.
type Capture @actionType(id:"urn:tdm:aws/examples:action:Capture") {
return : CameraStateProperty @property(id: "urn:tdm:aws/
examples:property:CameraStateProperty")
}
160
AWS IoT Things Graph User Guide
Raspberry Pi Camera (for Amazon Rekognition)
# Camera capability.
type CameraCapability @capabilityType(id: "urn:tdm:aws/
examples:capability:CameraCapability") {
STATE: CameraState @state(id: "urn:tdm:aws/examples:state:CameraState")
capture: Capture @action(id: "urn:tdm:aws/examples:action:Capture")
}
This camera definition includes a response payload that contains an Amazon Simple Storage Service
(Amazon S3) bucket name and the name of an item in the bucket. Amazon Rekognition requires the
Amazon S3 bucket and item names as input parameters.
# Camera state.
type CameraStateRkgnExample @stateType(id: "urn:tdm:aws/
examples:state:CameraStateRkgnExample") {
lastClickedImage : Uri @property(id: "urn:tdm:aws:property:String"),
s3BucketName : bucketName @property(id: "urn:tdm:aws:property:String"),
s3ItemName : itemName @property(id: "urn:tdm:aws:property:String")
}
161
AWS IoT Things Graph User Guide
Raspberry Pi Screen
# The Capture action takes no arguments and returns the state of the device after
completing.
type CaptureRkgnExample @actionType(id:"urn:tdm:aws/examples:action:CaptureRkgnExample") {
return : CameraStatePropertyRkgnExample @property(id: "urn:tdm:aws/
examples:property:CameraStatePropertyRkgnExample")
}
# Camera capability.
type CameraCapabilityRkgnExample @capabilityType(id: "urn:tdm:aws/
examples:capability:CameraCapabilityRkgnExample") {
STATE: CameraStateRkgnExample @state(id: "urn:tdm:aws/
examples:state:CameraStateRkgnExample")
capture: CaptureRkgnExample @action(id: "urn:tdm:aws/
examples:action:CaptureRkgnExample")
}
Raspberry Pi Screen
The following GraphQL shows the device definition for the Raspberry Pi Screen that is available in the
AWS IoT Things Graph console. This device is used in Creating a Flow with Devices and in Creating a Flow
with Devices and a Service.
# Screen state.
162
AWS IoT Things Graph User Guide
HW Group Damocles Mini
# The Display action takes an image URL as input, returns void, and displays the image.
type Display @actionType(id: "urn:tdm:aws/examples:action:Display") {
imageUrl : String @property(id: "urn:tdm:aws:property:String")
}
# Screen capability.
type ScreenCapability @capabilityType(id: "urn:tdm:aws/
examples:capability:ScreenCapability") {
STATE: ScreenState @state(id: "urn:tdm:aws/examples:state:ScreenState")
display: Display @action(id: "urn:tdm:aws/examples:action:Display")
}
MQTT {
ScreenCapability(id: "urn:tdm:aws/examples:capability:ScreenCapability") {
state {
currentDisplayImage(name: "displayUri", property:
"urn:tdm:aws:property:String")
}
Action(name: "display") {
params {
param(name:"imageUrl" property:"urn:tdm:aws:property:String")
}
Publish {
Request(topic: "$macro(${systemRuntime.deviceId}/display)") {
params {
param(name: "imageUri", property: "urn:tdm:aws/
examples:property:CameraStateProperty", value: "${imageUrl.value}")
}
}
}
}
}
}
}
For more information about how to create a Modbus device model, see Modbus Device Modeling 101.
That topic explains how to translate details from the product specification into the device definition.
163
AWS IoT Things Graph User Guide
HW Group Damocles Mini
# Action definitions
type GetBoolean @actionType(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetBoolean") {
return: Boolean @property(id: "urn:tdm:aws:Property:Boolean")
}
# Capability definition
type DamoclesMiniCapability @capabilityType(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:capability:DamoclesMiniCapability") {
getDiscreteInput1Value: GetBoolean @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetBoolean")
getDiscreteInput2Value: GetBoolean @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetBoolean")
getDiscreteInput3Value: GetBoolean @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetBoolean")
getDiscreteInput4Value: GetBoolean @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetBoolean")
getOutput1Value: GetBoolean @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetBoolean")
setOutput1Value: SetBoolean @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:SetBoolean")
getOutput2Value: GetBoolean @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetBoolean")
setOutput2Value: SetBoolean @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:SetBoolean")
getInput1Counter: GetInputCounter @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetInputCounter")
setInput1Counter: SetInputCounter @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:SetInputCounter")
getInput2Counter: GetInputCounter @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetInputCounter")
setInput2Counter: SetInputCounter @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:SetInputCounter")
getInput3Counter: GetInputCounter @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetInputCounter")
setInput3Counter: SetInputCounter @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:SetInputCounter")
getInput4Counter: GetInputCounter @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:GetInputCounter")
setInput4Counter: SetInputCounter @action(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:action:SetInputCounter")
}
164
AWS IoT Things Graph User Guide
HW Group Damocles Mini
ignore: void
}
# Modbus RTU
# Device definition (physical device)
query ModbusDamoclesMini @device(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:device:ModbusDamoclesMini", deviceModel: "urn:tdm:aws/examples/modbus/
hwgroup/damocles2mini:deviceModel:DamoclesMini") {
Modbus(ServerId: "1") {
Capability(id: "urn:tdm:aws/examples/modbus/hwgroup/
damocles2mini:capability:DamoclesMiniCapability") {
Action(name: "getDiscreteInput1Value") {
Params
ReadDiscreteInputs {
Request(Address: 100, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDiscreteInput2Value") {
Params
ReadDiscreteInputs {
Request(Address: 101, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDiscreteInput3Value") {
Params
ReadDiscreteInputs {
Request(Address: 102, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDiscreteInput4Value") {
Params
ReadDiscreteInputs {
Request(Address: 103, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getOutput1Value") {
Params
ReadCoils {
Request(Address: 200, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "setOutput1Value") {
Params {
param(name: "inputBoolean", property: "urn:tdm:aws:Property:Boolean")
}
WriteSingleCoil {
Request(Address: 200) {
params {
param(name: "inputBoolean", property: "urn:tdm:aws:Property:Boolean", value:
"${inputBoolean.value}")
}
165
AWS IoT Things Graph User Guide
HW Group Damocles Mini
}
}
}
Action(name: "getOutput2Value") {
Params
ReadCoils {
Request(Address: 201, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "setOutput2Value") {
Params {
param(name: "inputBoolean", property: "urn:tdm:aws:Property:Boolean")
}
WriteSingleCoil {
Request(Address: 201) {
params {
param(name: "inputBoolean", property: "urn:tdm:aws:Property:Boolean", value:
"${inputBoolean.value}")
}
}
}
}
Action(name: "getInput1Counter") {
Params
ReadInputRegisters {
Request(Address: 201, ReadCount: 2)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int32")
}
}
}
Action(name: "setInput1Counter") {
Params {
param(name: "inputCounterValue", property: "urn:tdm:aws:Property:Int32")
}
WriteMultipleRegisters {
Request(Address: 201, WriteCount: 2) {
params {
param(name: "inputCounterValue", property: "urn:tdm:aws:Property:Int32",
value: "${inputCounterValue.value}")
}
}
}
}
Action(name: "getInput2Counter") {
Params
ReadInputRegisters {
Request(Address: 203, ReadCount: 2)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int32")
}
}
}
Action(name: "setInput2Counter") {
Params {
param(name: "inputCounterValue", property: "urn:tdm:aws:Property:Int32")
}
WriteMultipleRegisters {
Request(Address: 203, WriteCount: 2) {
params {
param(name: "inputCounterValue", property: "urn:tdm:aws:Property:Int32",
value: "${inputCounterValue.value}")
}
166
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
}
}
}
Action(name: "getInput3Counter") {
Params
ReadInputRegisters {
Request(Address: 205, ReadCount: 2)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int32")
}
}
}
Action(name: "setInput3Counter") {
Params {
param(name: "inputCounterValue", property: "urn:tdm:aws:Property:Int32")
}
WriteMultipleRegisters {
Request(Address: 205, WriteCount: 2) {
params {
param(name: "inputCounterValue", property: "urn:tdm:aws:Property:Int32",
value: "${inputCounterValue.value}")
}
}
}
}
Action(name: "getInput4Counter") {
Params
ReadInputRegisters {
Request(Address: 207, ReadCount: 2)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int32")
}
}
}
Action(name: "setInput4Counter") {
Params {
param(name: "inputCounterValue", property: "urn:tdm:aws:Property:Int32")
}
WriteMultipleRegisters {
Request(Address: 207, WriteCount: 2) {
params {
param(name: "inputCounterValue", property: "urn:tdm:aws:Property:Int32",
value: "${inputCounterValue.value}")
}
}
}
}
}
}
}
}
CoolAutomation CoolMasterNet
The following GraphQL shows the device definition for the CoolAutomation CoolMasterNet. This device
is a communication bridge that connects home automation systems with heating, ventilation, and air
conditioning systems. Therefore, this device definition is just a template. You can rename the actions
based on the resources of the device that's connected to the bridge.
For more information about how to create a Modbus device model, see Modbus Device Modeling 101.
That topic explains how to translate details from the product specification into the device definition.
167
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
The CoolmasterNet uses virtual addresses (VAs). In this definition, the register addresses are examples.
You must update them to reflect your own VA configuration. For more information, see the VA's
Configuration section in the product specification.
{
# Manufacturer: Cool Automation
# Model: CoolMasterNet
# Action definitions
type GetOperationMode @actionType(id: "urn:tdm:aws/examples/modbus/coolautomation/
coolmasternet:action:GetOperationMode") {
return: OperationMode @property(id: "urn:tdm:aws:Property:Int16")
}
168
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
169
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
# Capability definition
type CoolMasterNetCapability @capabilityType(id: "urn:tdm:aws/examples/modbus/
coolautomation/coolmasternet:capability:CoolMasterNetCapability") {
getOperationMode: GetOperationMode @action(id: "urn:tdm:aws/examples/modbus/
coolautomation/coolmasternet:action:GetOperationMode")
setOperationMode: SetOperationMode @action(id: "urn:tdm:aws/examples/modbus/
coolautomation/coolmasternet:action:SetOperationMode")
getFanSpeed: GetFanSpeed @action(id: "urn:tdm:aws/examples/modbus/coolautomation/
coolmasternet:action:GetFanSpeed")
170
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
171
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
# Modbus RTU
# Device definition (physical device)
query ModbusCoolMasterNet @device(id: "urn:tdm:aws/examples/modbus/coolautomation/
coolmasternet:device:ModbusCoolMasterNet", deviceModel: "urn:tdm:aws/examples/modbus/
coolautomation/coolmasternet:deviceModel:CoolMasterNet") {
Modbus(ServerId: "1") {
Capability(id: "urn:tdm:aws/examples/modbus/coolautomation/
coolmasternet:capability:CoolMasterNetCapability") {
Action(name: "getOperationMode") {
Params
ReadHoldingRegisters {
Request(Address: 0, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "setOperationMode") {
Params {
param(name: "inputOperationMode", property: "urn:tdm:aws:Property:Int16")
}
WriteSingleRegister {
Request(Address: 0) {
params {
param(name: "inputOperationMode", property: "urn:tdm:aws:Property:Int16",
value: "${inputOperationMode.value}")
}
}
}
}
Action(name: "getFanSpeed") {
Params
ReadHoldingRegisters {
Request(Address: 1, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "setFanSpeed") {
Params {
param(name: "inputFanSpeed", property: "urn:tdm:aws:Property:Int16")
}
WriteSingleRegister {
Request(Address: 1) {
172
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
params {
param(name: "inputFanSpeed", property: "urn:tdm:aws:Property:Int16", value:
"${inputFanSpeed.value}")
}
}
}
}
Action(name: "setTemperature") {
Params {
param(name: "inputTemperature", property: "urn:tdm:aws:Property:Int16")
}
WriteSingleRegister {
Request(Address: 2) {
params {
param(name: "inputTemperature", property: "urn:tdm:aws:Property:Int16",
value: "${inputTemperature.value}")
}
}
}
}
Action(name: "getTemperatureSetting") {
Params
ReadHoldingRegisters {
Request(Address: 2, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getRoomTemperature_H") {
Params
ReadHoldingRegisters {
Request(Address: 6, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getRoomTemperature_I") {
Params
ReadInputRegisters {
Request(Address: 1, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getSwitchState_H") {
Params
ReadHoldingRegisters {
Request(Address: 3, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "setSwitchState_H") {
Params {
param(name: "inputSwitchOnOff_H", property: "urn:tdm:aws:Property:Int16")
}
WriteSingleRegister {
Request(Address: 3) {
params {
param(name: "inputSwitchOnOff_H", property: "urn:tdm:aws:Property:Int16",
value: "${inputSwitchOnOff_H.value}")
}
173
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
}
}
}
Action(name: "getSwitchState_C") {
Params
ReadCoils {
Request(Address: 0, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "setSwitchState_C") {
Params {
param(name: "inputSwitchOnOff_C", property: "urn:tdm:aws:Property:Boolean")
}
WriteSingleCoil {
Request(Address: 0) {
params {
param(name: "inputSwitchOnOff_C", property: "urn:tdm:aws:Property:Boolean",
value: "${inputSwitchOnOff_C.value}")
}
}
}
}
Action(name: "getSwingSetting") {
Params
ReadHoldingRegisters {
Request(Address: 5, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "setSwingSetting") {
Params {
param(name: "inputSwingSetting", property: "urn:tdm:aws:Property:Int16")
}
WriteSingleRegister {
Request(Address: 5) {
params {
param(name: "inputSwingSetting", property: "urn:tdm:aws:Property:Int16",
value: "${inputSwingSetting.value}")
}
}
}
}
Action(name: "getFilterSign_H") {
Params
ReadHoldingRegisters {
Request(Address: 4, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "setFilterSign_H") {
Params {
param(name: "inputFilterSign_H", property: "urn:tdm:aws:Property:Int16")
}
WriteSingleRegister {
Request(Address: 4) {
params {
param(name: "inputFilterSign_H", property: "urn:tdm:aws:Property:Int16",
value: "${inputFilterSign_H.value}")
}
174
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
}
}
}
Action(name: "getFilterSign_C") {
Params
ReadCoils {
Request(Address: 1, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "setFilterSign_C") {
Params {
param(name: "inputFilterSign_C", property: "urn:tdm:aws:Property:Boolean")
}
WriteSingleCoil {
Request(Address: 1) {
params {
param(name: "inputFilterSign_C", property: "urn:tdm:aws:Property:Boolean",
value: "${inputFilterSign_C.value}")
}
}
}
}
Action(name: "getExternalTerminalsStatus") {
Params
ReadCoils {
Request(Address: 2, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getInhibitIndoorUnitOnOperationSetting") {
Params
ReadCoils {
Request(Address: 3, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "setInhibitIndoorUnitOnOperationSetting") {
Params {
param(name: "inputInhibitIndoorUnitOnOperationSetting", property:
"urn:tdm:aws:Property:Int16")
}
WriteSingleCoil {
Request(Address: 3) {
params {
param(name: "inputInhibitIndoorUnitOnOperationSetting", property:
"urn:tdm:aws:Property:Int16", value: "${inputInhibitIndoorUnitOnOperationSetting.value}")
}
}
}
}
Action(name: "getAnalogInput1") {
Params
ReadInputRegisters {
Request(Address: 13, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
175
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
Action(name: "getAnalogInput2") {
Params
ReadInputRegisters {
Request(Address: 14, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getDigitalOutput1") {
Params
ReadCoils {
Request(Address: 9, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalOutput2") {
Params
ReadCoils {
Request(Address: 10, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalOutput3") {
Params
ReadCoils {
Request(Address: 11, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalOutput4") {
Params
ReadCoils {
Request(Address: 12, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalOutput5") {
Params
ReadCoils {
Request(Address: 13, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalOutput6") {
Params
ReadCoils {
Request(Address: 14, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "setDigitalOutput1") {
Params {
param(name: "inputDigitalOutput1", property: "urn:tdm:aws:Property:Boolean")
176
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
}
WriteSingleCoil {
Request(Address: 9) {
params {
param(name: "inputDigitalOutput1", property: "urn:tdm:aws:Property:Boolean",
value: "${inputDigitalOutput1.value}")
}
}
}
}
Action(name: "setDigitalOutput2") {
Params {
param(name: "inputDigitalOutput2", property: "urn:tdm:aws:Property:Boolean")
}
WriteSingleCoil {
Request(Address: 10) {
params {
param(name: "inputDigitalOutput2", property: "urn:tdm:aws:Property:Boolean",
value: "${inputDigitalOutput2.value}")
}
}
}
}
Action(name: "setDigitalOutput3") {
Params {
param(name: "inputDigitalOutput3", property: "urn:tdm:aws:Property:Boolean")
}
WriteSingleCoil {
Request(Address: 11) {
params {
param(name: "inputDigitalOutput3", property: "urn:tdm:aws:Property:Boolean",
value: "${inputDigitalOutput3.value}")
}
}
}
}
Action(name: "setDigitalOutput4") {
Params {
param(name: "inputDigitalOutput4", property: "urn:tdm:aws:Property:Boolean")
}
WriteSingleCoil {
Request(Address: 12) {
params {
param(name: "inputDigitalOutput4", property: "urn:tdm:aws:Property:Boolean",
value: "${inputDigitalOutput4.value}")
}
}
}
}
Action(name: "setDigitalOutput5") {
Params {
param(name: "inputDigitalOutput5", property: "urn:tdm:aws:Property:Boolean")
}
WriteSingleCoil {
Request(Address: 13) {
params {
param(name: "inputDigitalOutput5", property: "urn:tdm:aws:Property:Boolean",
value: "${inputDigitalOutput5.value}")
}
}
}
}
Action(name: "setDigitalOutput6") {
Params {
param(name: "inputDigitalOutput6", property: "urn:tdm:aws:Property:Boolean")
}
177
AWS IoT Things Graph User Guide
CoolAutomation CoolMasterNet
WriteSingleCoil {
Request(Address: 14) {
params {
param(name: "inputDigitalOutput6", property: "urn:tdm:aws:Property:Boolean",
value: "${inputDigitalOutput6.value}")
}
}
}
}
Action(name: "getDigitalInput1") {
Params
ReadDiscreteInputs {
Request(Address: 9, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalInput2") {
Params
ReadDiscreteInputs {
Request(Address: 10, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalInput3") {
Params
ReadDiscreteInputs {
Request(Address: 11, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalInput4") {
Params
ReadDiscreteInputs {
Request(Address: 12, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalInput5") {
Params
ReadDiscreteInputs {
Request(Address: 13, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
Action(name: "getDigitalInput6") {
Params
ReadDiscreteInputs {
Request(Address: 14, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Boolean")
}
}
}
}
}
}
178
AWS IoT Things Graph User Guide
Deuta AL-511-00 IP-DALI-BRIDGE V2
For more information about how to create a Modbus device model, see Modbus Device Modeling 101.
That topic explains how to translate details from the product specification into the device definition.
{
# Manufacturer: Deuta
# Model: AL-511-00 IP-DALI-BRIDGE V2
# Action definitions
type GetVersion @actionType(id: "urn:tdm:aws/examples/modbus/deuta/
dalibridge:action:GetVersion") {
return: VersionNumber @property(id: "urn:tdm:aws:Property:Int16")
}
179
AWS IoT Things Graph User Guide
Deuta AL-511-00 IP-DALI-BRIDGE V2
# Capability definition
type DALILightControllerCapability @capabilityType(id: "urn:tdm:aws/examples/modbus/deuta/
dalibridge:capability:DALILightControllerCapability") {
getMainVersion_HW: GetVersion @action(id: "urn:tdm:aws/examples/modbus/deuta/
dalibridge:action:GetVersion")
getSubVersion_HW: GetVersion @action(id: "urn:tdm:aws/examples/modbus/deuta/
dalibridge:action:GetVersion")
getMainVersion_SW: GetVersion @action(id: "urn:tdm:aws/examples/modbus/deuta/
dalibridge:action:GetVersion")
getSubVersion_SW: GetVersion @action(id: "urn:tdm:aws/examples/modbus/deuta/
dalibridge:action:GetVersion")
getSerialNumber_LSB: GetSerialNumber @action(id: "urn:tdm:aws/examples/modbus/deuta/
dalibridge:action:GetSerialNumber")
180
AWS IoT Things Graph User Guide
Deuta AL-511-00 IP-DALI-BRIDGE V2
181
AWS IoT Things Graph User Guide
Deuta AL-511-00 IP-DALI-BRIDGE V2
Action(name: "getSubVersion_HW") {
Params
ReadHoldingRegisters {
Request(Address: 3, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getMainVersion_SW") {
Params
ReadHoldingRegisters {
Request(Address: 4, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getSubVersion_SW") {
Params
ReadHoldingRegisters {
Request(Address: 5, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getSerialNumber_LSB") {
Params
ReadHoldingRegisters {
Request(Address: 6, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getSerialNumber_MSB") {
Params
ReadHoldingRegisters {
Request(Address: 7, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getAnalogInputVoltage") {
Params
ReadHoldingRegisters {
Request(Address: 24, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getAnalogInputPercent") {
Params
ReadHoldingRegisters {
Request(Address: 25, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "getDigitalThresholdValue_low") {
Params
ReadHoldingRegisters {
182
AWS IoT Things Graph User Guide
Deuta AL-511-00 IP-DALI-BRIDGE V2
183
AWS IoT Things Graph User Guide
Deuta AL-511-00 IP-DALI-BRIDGE V2
184
AWS IoT Things Graph User Guide
Amazon Rekognition DetectFaces API
}
}
Action(name: "setAnalogInputGradient") {
Params {
param(name: "inputAnalogInputGradient", property: "urn:tdm:aws:Property:Int16")
}
WriteSingleRegister {
Request(Address: 33) {
params {
param(name: "inputAnalogInputGradient", property:
"urn:tdm:aws:Property:Int16", value: "${inputAnalogInputGradient.value}")
}
}
}
}
Action(name: "getSupplyVoltageStatus") {
Params
ReadHoldingRegisters {
Request(Address: 34, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
Action(name: "setDALIcommand") {
Params {
param(name: "inputCommand", property: "urn:tdm:aws:Property:Int16")
}
WriteSingleRegister {
Request(Address: 1001) {
params {
param(name: "inputCommand", property: "urn:tdm:aws:Property:Int16", value:
"${inputCommand.value}")
}
}
}
}
Action(name: "getDALIanswer") {
Params
ReadHoldingRegisters {
Request(Address: 2001, ReadCount: 1)
Response {
responsePayload(property: "urn:tdm:aws:Property:Int16")
}
}
}
}
}
}
}
# Amazon Rekognition DetectFaces action. This action takes Amazon S3 bucket and item names
as input and
185
AWS IoT Things Graph User Guide
getS3Lambda
# returns a JSON object that contains the response of the Amazon Rekognition DetectFaces
API.
type DetectFaces @actionType(id: "urn:tdm:aws/examples:action:DetectFaces") {
bucketName: String @property(id: "urn:tdm:aws:Property:String")
itemName: String @property(id: "urn:tdm:aws:Property:String")
return: RkgnResponseProperty @property(id: "urn:tdm:aws:Property:Json")
}
getS3Lambda
The following GraphQL shows the definition for the getS3Lambda service that is available in the AWS
IoT Things Graph console. This service is used in Creating a Flow with Lambda Functions.
186
AWS IoT Things Graph User Guide
wordCount
# The getS3ObjectAsStringAction takes Amazon S3 bucket and item names as input and returns
the
# contents of the file as a string.
type getS3ObjectAsStringAction @actionType(id: "urn:tdm:aws/
examples:action:getS3ObjectAsStringAction") {
bucket: String @property(id: "urn:tdm:aws:property:String"),
key : String @property(id: "urn:tdm:aws:property:String"),
return : getS3ObjectAsStringResponse @property(id: "urn:tdm:aws/
examples:property:getS3ObjectAsStringResponse")
}
# Service definition for getS3Lambda. It's implemented as an AWS IoT Greengrass Lambda
function.
query getS3Lambda @service(id: "urn:tdm:aws/examples:Service:getS3Lambda") {
AwsLambda {
getS3Capability(id: "urn:tdm:aws/examples:capability:getS3Capability") {
Action(name: "getS3ObjectAsString") {
params {
param(name: "bucket", property:"urn:tdm:aws:property:String")
param(name: "key", property:"urn:tdm:aws:property:String")
}
InvokeGreengrassLambda {
Request(arn:"$macro(arn:aws:lambda:${systemConfig.awsRegion}:
${systemConfig.awsAccountId}:function:GetS3Object:1)") {
params {
param(name: "bucket", property:"urn:tdm:aws:property:String",
value: "${bucket.value}")
param(name: "key", property:"urn:tdm:aws:property:String",
value: "${key.value}")
}
}
Response {
responsePayload(property: "urn:tdm:aws/
examples:property:getS3ObjectAsStringResponse")
}
}
}
}
}
}
wordCount
The following GraphQL shows the definition for the wordCount service that is available in the AWS IoT
Things Graph console. This service is used in Creating a Flow with Lambda Functions.
187
AWS IoT Things Graph User Guide
saveResponse
# The wordCountAction takes a string as input and returns the number of unique words and
the
# most frequently used word in the string.
type wordCountAction @actionType(id: "urn:tdm:aws/examples:action:wordCountAction") {
message: String @property(id: "urn:tdm:aws:property:String"),
return: wordCountResponse @property(id: "urn:tdm:aws/
examples:property:wordCountResponse")
}
# Service definition for wordCount. It's implemented as an AWS IoT Greengrass Lambda
function.
query wordCount @service(id: "urn:tdm:aws/examples:Service:wordCountLambda") {
AwsLambda {
wordCountCapability(id: "urn:tdm:aws/examples:capability:wordCountCapability")
{
Action(name: "wordCount") {
params {
param(name: "message", property:"urn:tdm:aws:property:String")
}
InvokeGreengrassLambda {
Request(arn: "$macro(arn:aws:lambda:${systemConfig.awsRegion}:
${systemConfig.awsAccountId}:function:WordCount:1)") {
params {
param(name: "message",
property:"urn:tdm:aws:property:String", value: "${message.value}")
}
}
Response {
responsePayload(property: "urn:tdm:aws/
examples:property:wordCountResponse")
}
}
}
}
}
}
saveResponse
The following GraphQL shows the definition for the saveResponse service that is available in the AWS
IoT Things Graph console. This service is used in Creating a Flow with Lambda Functions.
188
AWS IoT Things Graph User Guide
saveResponse
# The saveResponseAction takes the response of the wordCount service as input and saves it
to a location
# in Amazon S3 that is specified in the AWS Lambda function that the service exposes.
type saveResponseAction @actionType(id: "urn:tdm:aws/examples:action:saveResponseAction") {
response: wordCountResponse @property(id: "urn:tdm:aws/
examples:property:wordCountResponse")
}
# Service definition for saveResponse. It's implemented as an AWS IoT Greengrass Lambda
function.
query saveResponse @service(id: "urn:tdm:aws/examples:Service:saveResponseLambda") {
AwsLambda {
saveResponseCapability(id: "urn:tdm:aws/
examples:capability:saveResponseCapability") {
Action(name: "save") {
params {
param(name: "response", property:"urn:tdm:aws/
examples:property:wordCountResponse")
}
InvokeGreengrassLambda {
Request(arn: "$macro(arn:aws:lambda:${systemConfig.awsRegion}:
${systemConfig.awsAccountId}:function:SaveToS3:1)") {
params {
param(name: "response", property:"urn:tdm:aws/
examples:property:wordCountResponse", value: "${response.value}")
}
}
}
}
}
}
}
189
AWS IoT Things Graph User Guide
AWS IoT Greengrass Deployments
AWS IoT Things Graph then performs the following actions on these two resources:
• Generates a deployment artifact containing the dependency closure of the flow configuration, and
saves it to the Amazon S3 bucket. The file name of this artifact is a concatenation of flow-flow
name.tar.gz. If you delete this file after the deployment is complete, your existing deployment will
work, but redeployments won't.
• Deploys the AWS IoT Things Graph connector to the AWS IoT Greengrass group and configures it to
use the configuration stored in the S3 bucket.
• Adds the devices specified in the flow configuration.
• Subscribes the AWS IoT Things Graph connector and the devices to the MQTT topics specified in the
device definitions.
Note
You must create a thingsgraph directory at the root of your AWS IoT Greengrass core device.
Deployments to your core device won't work if this directory doesn't exist. Don't modify the files
that are put in this directory. For more information on setting up your AWS IoT Greengrass core,
see Setting Up Your Environment for AWS IoT Greengrass Deployments.
After your first deployment of a flow configuration to your AWS IoT Greengrass core device, AWS IoT
Things Graph deploys the AWS IoT Things Graph connector to your AWS IoT Greengrass core device. AWS
IoT Things Graph also installs a database file named ThingsGraph.db and a directory named engine to
the thingsgraph directory that you created when you set up your AWS IoT Greengrass core.
For more information about the steps that are required to deploy AWS IoT Things Graph and flows to an
AWS IoT Greengrass group, see Creating and Deploying Flows. For more information about setting up
your AWS IoT Greengrass group for AWS IoT Things Graph, see Setting Up Your Environment.
190
AWS IoT Things Graph User Guide
Verifying Flows in Your AWS IoT Greengrass Group
[INFO]-bootstrapping DB
[INFO]-bootstrapping entities
[INFO]-bootstrapping entities done
[INFO]-bootstrapping DB done
[INFO]-FlowsBootstrap: registered SDC: urn:tdm:Region/Account ID/
default:Deployment:MyExample01_V001
[INFO]-Initialized ThingsGraph Runtime vx.x.x
The log entries that begin with bootstrapping indicate that the ThingsGraph.db file is being created
and populated by entities, as specified by the dependency closure that AWS IoT Things Graph has
uploaded to your Amazon S3 bucket. These entities include the device models, systems, and flow
templates that you specified in your system flow configuration (SDC).
The FlowsBootstrap entry indicates that your SDC has been added to your AWS IoT Greengrass group.
The Initialized ThingsGraph Runtime entry indicates that AWS IoT Things Graph has successfully
installed and is running on your core device.
Later entries in the log file relate to the execution of the flow. These two entries indicate that the trigger
condition has been met and the flow execution has begun.
The bracketed text in the first entry contains the trigger condition logic that you specified for your flow
(a time interval in this case). The FlowSchedulerClientGreengrassImpl: StartFlowExecution:
entry indicates that the flow has begun executing. The following three entries contain information about
this instance of the flow. The value of flowInstanceId is a concatenation of the flow ID (a URN), the
timestamp, the name of the trigger, and a universally unique identifier (UUID). The value of flowParams
contains the parameters that have been passed to the flow (the device ID in this case).
After the flow execution begins, a series of StateTransition entries appears in the log. The first
occurs at the very beginning, and indicates that the StartFlowExecutionTask has been performed.
[INFO]-[StateTransition-urn:tdm:Region/Account ID/
default:Workflow:MyExample03_V001_2019-03-12T2
0:55:37.041Z_TenSecondTrigger_2ba7d218-2b9e-4005-ad96-8779d589dac2]
ExecutionStarted(super=StateTransitionMessage(super=Message
(super=com.amazonaws.iotflowengine.messages.ExecutionStarted@93227493, messageId=1939,
flowInstanceId=urn:tdm:Region/Account ID/
default:Workflow:MyExample03_V001_2019-03-12T20:55:37.041Z_TenSecondTrigger_2ba7d218-2b9e-4005-
ad96-8779d589dac2,
191
AWS IoT Things Graph User Guide
Verifying Flows in Your AWS IoT Greengrass Group
createdAt=1552424137043)), flowParams={"device1Id":"DeutaBridgeV2"},
templateId=urn:tdm:Region/Account ID/default:Workflow:MyExam
ple03_V001, version=0, accountId=Account ID,
additionalContextParams={"SystemTemplateId":"urn:tdm:Region/Account ID/defa
ult:System:MyExample03_V001"})
StateTransition entries include the same values for flowInstanceId and flowParams that occur
in the preceding entries.
After each step in the flow is executed, corresponding log entries for StateTransition appear in the
log file, as in the following example for step 2 of a flow.
[INFO]-[StateTransition-urn:tdm:Region/Account ID/
default:Workflow:MyExample03_V001_2019-03-12T21:12:08.661Z_TenSecondTrigger_b190369e-6b44-4d14-8468-7d5
StepSucceeded(super=StateTransitionMessage(super=Message(super=com.amazonaws.iotflowengine.messages.Ste
messageId=12053, flowInstanceId=urn:tdm:Region/Account ID/
default:Workflow:MyExample03_V001_2019-03-12T21:12:08.661Z_TenSecondTrigger_b190369e-6b44-4d14-8468-7d5
createdAt=1552425129450)),
stepId=step2, result={"__type":"com.aws.iot.tg.core.ast.tdm.PropertyValue",
"property":
{"__type":"com.aws.iot.tg.core.ast.tdm.Property","propertyAlias":"_","propertyTypeUrn":
{"__type":"com.aws.iot.tg.core.ast.tdm.URN","id":"urn:tdm:aws:Property:Int16"}},"value":0})
The log file also contains entries that provide information about the requests being sent to the devices
and the responses from the devices. The requests and responses are represented as JSON payloads. The
following example shows a successful request from AWS IoT Things Graph to a Modbus device, and the
response sent by the device. If the device uses the MQTT protocol, the request and response entries
would show the MQTT topics to which the devices are subscribed. (AWS IoT Things Graph creates these
subscriptions when you deploy the flow.)
These request and response entries are where you can verify that your devices are interacting correctly
in the flow. You can use these logs to determine whether any of the devices in your flow are having
connectivity issues, or whether their certificates are set up correctly. In those cases, you'll see in the log
file that certain devices in the flow aren't returning responses.
For more information about troubleshooting AWS IoT Things Graph flows, see Troubleshooting AWS IoT
Things Graph.
192
AWS IoT Things Graph User Guide
General Deployment Issues with AWS IoT Things Graph
If your deployment target is an AWS IoT Greengrass group, you might run into issues that relate directly
to AWS IoT Greengrass. For AWS IoT Greengrass troubleshooting information, see Troubleshooting AWS
IoT Greengrass. You also need to configure your AWS IoT Greengrass group to work with AWS IoT Things
Graph. For information about setting up an environment for deploying AWS IoT Things Graph workflows
(flows), see Setting Up Your Environment.
In the AWS IoT Things Graph console, you see The deployment to your AWS IoT Greengrass
Deployed in target in the Status column for your might have failed.
system instance, but your flow isn't running.
• On the AWS IoT console (https://
console.aws.amazon.com/iot/), choose the
AWS IoT Greengrass tab. Choose the AWS IoT
Greengrass group you're using for AWS IoT
Things Graph flow deployments. Check the
status of your latest deployment. Issues in your
AWS IoT Greengrass group might be related to
a failed deployment to AWS IoT Greengrass.
For AWS IoT Greengrass troubleshooting
information, see Troubleshooting AWS IoT
Greengrass.
• Or the failed deployment might be related to an
AWS IoT Greengrass group or core that isn't set
up for AWS IoT Things Graph.
193
AWS IoT Things Graph User Guide
Modbus Flow Deployment Issues
with AWS IoT Things Graph
Symptom Solution
In that file, you should see the following entry,
which indicates that the trigger condition has
been met and the flow has started.
FlowSchedulerClientGreengrassImpl:
StartFlowExecution:
Your flow contains a service that exposes the On the AWS IoT console (https://
capability of an AWS Lambda function. (For an console.aws.amazon.com/iot/), go to the AWS IoT
example that contains these kinds of services, see Greengrass tab. Choose the AWS IoT Greengrass
Creating a Flow with Lambda Functions.) The AWS group you're using for AWS IoT Things Graph flow
IoT Greengrass deployment fails with an error deployments, and then choose the Lambdas tab.
message indicating that the Lambda function
doesn't exist in your AWS IoT Greengrass group. Verify that you've added the Lambda function
used in your service to the group. Also verify that
you're using the correct version of the function.
For example, the AWS IoT Things Graph services
used in Creating a Flow with Lambda Functions
require you to add version 1 of each function to
your group.
Your flow contains a Modbus device. The flow Make sure that you've installed the Modbus-RTU
appears to have deployed, but it isn't running. Protocol Adapter.
Your flow contains a Modbus device. The AWS Make sure that you've added your device to your
IoT Greengrass deployment fails with this error: AWS IoT Greengrass group as a local resource. For
unable to load the group file downloaded file instructions about how to add local resources to
Path path doesn't exist. a group, see Access Local Resources with Lambda
Functions. Because AWS IoT Things Graph runs as
a Lambda function on your core device, you don't
have to add a Lambda function. AWS IoT Things
Graph uses this local resource. Also make sure that
the source path for your device (which represents
the physical Modbus serial port) is correct on the
AWS IoT Greengrass tab on the AWS IoT console
(https://console.aws.amazon.com/iot/).
194
AWS IoT Things Graph User Guide
What Is the AWS IoT Things Graph Data Model?
Data models and mappings created in this framework enable automation engineers to build workflows
consisting of devices from multiple manufacturers. Because the IoT devices and their properties are
represented and mapped in TDM, devices can interoperate and communicate with each other without
any transformations or low-level code on the devices. For example, TDM can map equivalent units of
measure across devices that use different scales, such as Fahrenheit and Celsius.
Additionally, the TDM framework enables IoT automation engineers to build workflows consisting of
device models created in TDM. Physical devices can be assigned to device models, and their interactions
in a workflow can be defined in TDM. Engineers can then deploy multiple instances of a workflow using
different sets of concrete devices in each deployment. Engineers can also swap a given device from one
manufacturer with a device from another manufacturer because both devices and their properties are
represented in the same device model.
TDM consists of a set of core constructs, including and most importantly PropertyTypes. TDM also
consists of a set of specialized constructs that support IoT-specific constructs, including State, Device,
and Capability.
The following sections describe both the core and the IoT-specific concepts of TDM. They also describe
how to use GraphQL syntax to create and extend TDM constructs.
Topics
• What Is the AWS IoT Things Graph Data Model? (p. 195)
• AWS IoT Things Graph Data Model and GraphQL (p. 198)
• AWS IoT Things Graph Data Model Core Constructs (p. 202)
• IoT Domain Constructs (p. 209)
The following snippet from an example discussed in Mapping shows how this works. It creates a simple
translation of one way of representing the on/off property of a device (an enum) into an alternative way
of representing the same concept.
195
AWS IoT Things Graph User Guide
GraphQL Syntax
name:'OnOffEnum_to_OnOffInt',
from:'urn:tdm:aws:Property:OnOffEnum s',
to:'urn:tdm:aws:Property:OnOffInt t')
In the following topics, we discuss the syntax at greater length. For now we can focus just on the from
and the to properties. A lot of devices can have on/off states, so this property isn't nested deeply in
the property hierarchy, but it's a basic, granular concept. Two representations of it can be precisely
translated in both directions, and this mapping can be used across all devices that represent the on/off
state in one of these two ways.
GraphQL Syntax
TDM is expressed with GraphQL syntax. TDM constructs are compliant with the GraphQL standard, but
TDM uses GraphQL in a distinct and highly specialized way.
TDM doesn't use GraphQL as a query language or as a server runtime for executing queries. Instead, TDM
uses GraphQL as a tool for creating a type system consisting of IoT devices and data concepts. GraphQL
provides a powerful and concise way of defining the types and structures common in IoT. Since Graphs
are useful tools for modeling real-world objects (such as IoT devices) and GraphQL models things as
graphs, its syntax is a convenient vehicle for modeling the IoT conceptual space.
You can look at the GraphQL documentation for a thorough understanding of GraphQL and what you
can do with it. However, to understand how it's used in TDM, you need to understand only a handful of
core concepts.
Types
GraphQL uses types to define the structure of objects in a schema. The given type of an object must
define the object's structure. For example, an employee address book would need to define an object
type for Employee.
The following example shows how you might define an Employee in GraphQL.
type Employee {
id: ID!
firstname: String!
middlename: String
lastname: String!
location: Building!
phonenumbers: [PhoneNumber!]!
}
Queries
196
AWS IoT Things Graph User Guide
GraphQL Syntax
Queries in GraphQL are typically used to execute queries on objects within a GraphQL schema. However,
TDM uses queries in much the same way as types. A query in TDM is simply a way of defining objects
that have a greater degree of complexity than the type syntax supports. The original purpose of
GraphQL queries is to request fields on objects. Because a GraphQL schema can contain nested types
(as in the Employee example, which contains both Building and PhoneNumber objects), queries on
GraphQL objects can contain nested structures. A query requesting the name and address of a particular
employee, for example, could look like the following example.
query {
Employee(id: 1000) {
name
building {
name
address {
streetAddress
zipcode
}
}
}
}
In TDM, GraphQL queries aren't used for executing queries on objects that are defined in a GraphQL
schema. In TDM, queries are used for representing complex concepts, such as Mappings.
Directives
A directive is an instruction attached to a field that begins with the @ symbol. Directives in GraphQL are
generally attached to query fields and are meant to manipulate the results of a query in any way defined
by the server runtime. The GraphQL standard currently defines only two directives: @include(if:
Boolean expression) and @skip(if: Boolean expression). You can use these directives to
specify the conditions under which a field gets included in a result set. TDM uses directives in a very
different way.
In TDM, directives play a fundamental role in defining IoT concepts. Instead of defining query behavior,
TDM directives are conceptually the equivalent of statements and type declarations.
In the following example, the @enumType directive tells AWS IoT Things Graph to create a simple ON/
OFF enum. Notice that this enum is used in the preceding mapping snippet.
The directive follows the enum GraphQL object type specification and name. In this context, it means
"create an enum with the following properties and structure." The directive takes one or more arguments
that specify the properties of the object to create. In this case, the enum type requires only a TDM URN.
As in regular GraphQL objects, the fields inside the curly braces define the structure of the object. The
enum contains only two fields, ON and OFF. These fields also have directives attached to them. In this
case, the @enumValue directive tells AWS IoT Things Graph to create enum values with the values
specified by the arguments inside the parentheses: value: 0 and value: 1.
TDM combines these three GraphQL concepts—types, queries, and directives—into a rich and expressive
tool for defining IoT applications.
197
AWS IoT Things Graph User Guide
AWS IoT Things Graph Data Model and GraphQL
Now that you have a general understanding of these concepts, see AWS IoT Things Graph Data Model
and GraphQL for more information about how TDM works.
TDM doesn't use other GraphQL concepts, such as mutations and subscriptions, and it doesn't interact
with a GraphQL server or runtime. Although it uses GraphQL in a way that is different from its original
purposes, TDM is fully compatible with GraphQL. It extends GraphQL in a way that is analogous to the
way in which the C++ programming language extends C.
Instead of querying data from a GraphQL server, TDM enables you to create models of IoT devices and
stateful web applications, and define how they interact within an IoT system.
For more information about GraphQL and how to use it more generically, see the GraphQL
documentation.
The following sections describe how specific GraphQL concepts are implemented in TDM, and how the
TDM constructs fit together at the highest level.
Type
TDM uses GraphQL types to describe IoT concepts that can be represented as data structures without
requiring complex payloads or logic. Types in TDM are the basic building blocks of an IoT system. The
TDM constructs that are described as types are Properties, States, Events, Actions, Capabilities, and
Systems.
The following example uses a GraphQL type to create a property named imageUri. The example
demonstrates additional TDM concepts that are discussed in later sections. This property is a relatively
simple structure with two arguments. It also contains no payload.
Note
TDM keywords and variables are case insensitive.
The @propertyType directive (discussed in the section called “Using Directives” (p. 199)) specifies this
as a TDM Property. The first argument assigns a unique identifier according to the TDM URN scheme.
The second argument specifies the data type of this property as a string.
The ignore:void name-value pair between the braces indicates that this type contains no payload.
GraphQL syntax requires a trailing brace block with one or more field definitions. This name-value pair
works around that requirement in cases where no payload is required.
Query
TDM uses GraphQL queries to describe IoT concepts that are represented by logic and/or complex data
structures that can't be described by the syntax of GraphQL types. TDM queries contain structured data
198
AWS IoT Things Graph User Guide
Using Directives
with logic that must be executed when IoT devices and services are interacting with each other. The TDM
constructs that are described as queries are Mappings, Devices, Services, and Workflows.
All of these constructs represent dynamic IoT interactions or direct participants in these interactions.
Mappings translate data received from one device into standards and formats that other devices can
understand. Workflows describe how devices in an IoT system interact in real time. Triggers start
workflows, and devices interact with each other within workflows. Additionally, all of these constructs
require relatively complex syntax to describe them.
The following example describes a device named myMotionSensor. This device inherits from the
MotionSensor device model and implements a capability associated with that device model. The
capability contains a state and an event. The state, in turn, contains properties.
The specific TDM concepts demonstrated in this example are discussed in sections that follow in this
guide. The example demonstrates the general shape of a TDM query and the complexity that it supports.
The @device directive specifies this as a TDM Device. As in the property definition, the first argument
assigns a unique identifier according to the TDM URN scheme. The second argument contains another
TDM URN that specifies the device model from which this device inherits its capability. The definition
then implements the device model's capability by including a State and an Event. A capability can also
include an Action. If the device model's capability includes an Action, the device must implement it as
well.
Using Directives
TDM uses GraphQL directives extensively for implementing concepts that are specific to the IoT domain.
Directives can be attached to any field to insert domain-specific information. The preceding examples
demonstrate how directives are used to specify a specific TDM construct (the propertyType and
device directives). In TDM, directives play the role of statements. When you see a directive in a type or
query definition, it means "create an instance of this type".
TDM supports two kinds of directives: definition and usage. You use definition directives to create
instances of a type of construct. For example, the @propertyType directive tells AWS IoT Things Graph
to create a property. The following example creates a property named MotionDetected by using the
@propertyType definition directive.
199
AWS IoT Things Graph User Guide
Using Directives
The @propertyType directive tells AWS IoT Things Graph to create a property. The first argument
contains a TDM URN that uniquely identifies the new property. This URN must be in the property
branch of the TDM URN scheme. The URN scheme and the directive must match. The second argument
specifies the property's data type, which in this case is the built-in primitive Boolean. The ignore:void
name-value pair between the braces specifies an empty payload.
A usage directive is a specific instance of a type. For example, after you create the MotionDetected
property type, you can use it to construct a State by using the @property usage directive, as in the
following example.
The @stateType directive tells AWS IoT Things Graph to create a state definition. The
urn:tdm:aws:property:MotionSensorState argument uniquely identifies the new state and
types it as a state by placing it under the state branch of the TDM URN scheme. The URN scheme and
the directive must match. The first piece of the payload between the braces specifies the name of the
state as it will be used when a device implements the state. The pieces of the payload that follow the
first colon specify the property that the state contains by name, by usage directive, and by URN. The
@property directive in this example means "use the property specified by this URN".
Notice that the isMotionDetected state name appears as part of the state implementation in the
preceding device definition example.
state {
isMotionDetected(name:"lastMotionDetected",
property:"urn:tdm:aws:property:MotionDetected")
}
Directives and URNs provide a way of implementing type safety in GraphQL structures. When you create
a TDM construct by constructing a GraphQL type or query, you must create a unique URN that places
the construct inside a conceptual hierarchy that matches the type specified by the directive. When you
use an instance of the type, you must supply a URN that already exists and that sits at a location in the
conceptual hierarchy that matches the type specified by the directive.
The following table contains the usage and definition directives in TDM.
Definition Usage
@actionType @action
@capabilityType @capability
@deployment
@deviceModel @device
@enumType @enum
@enumValue
200
AWS IoT Things Graph User Guide
Creating a Device with GraphQL
Definition Usage
@eventType @event
@mapping
@propertyType @property
@service
@stateType @state
@systemType @system
@thing
@workflowType @workflow
The sections following this topic describe how to use each directive to construct and/or use the specific
TDM constructs.
• Property (type @propertyType): The attributes of a device, such as the color and brightness of a
light bulb and the click time of a camera.
• Device Model (type @deviceModel): An abstraction of a device that contains a capability. For
example, you use a device model definition to create abstract definitions of things like light bulbs and
cameras.
• Device (query @device): A device type that inherits from the device model and implements the
device model's capability. Cameras and light bulb models produced by specific manufacturers would be
defined as devices.
• Capability (type @capabilityType): The actions, events, and state associated with the device.
A light bulb's capability would include its brightness (part of its state), the action of changing its
brightness, and a power on/off event. A camera's capability would include its burst delay interval (part
of its state), the action of capturing an image, and the camera click event.
• Action (type @actionType): The device's ability to perform a function. A light bulb can change its
brightness, and a camera can capture an image. Both are examples of actions.
• Event (type @eventType): The device's ability to communicate externally with other devices and
services. A light bulb can send a notification that it has been turned on or off, and a camera can send a
notification that it has been clicked. Both are examples of events.
• State (type @stateType): The properties that describe the device at a specific point in time. A light
bulb has properties like brightness and color. A camera has properties like image URI (for a specific
image that it has captured) and click time (for the time when an image was captured). A state is a
collection of these properties.
• Mapping (query @mapping): Symmetrical, forward, and/or reverse transformations of properties and
measurements that enable different device types to understand each other. A mapping can transform
an enum-based brightness rating into a rating based on a numerical range. It can also convert the
burst delay property of a camera from milliseconds into seconds.
The following diagram shows how all of these constructs fit together in a device model.
201
AWS IoT Things Graph User Guide
AWS IoT Things Graph Data Model Core Constructs
TDM has a set of built-in data types that support standard primitive data types, and the more complex
data types that are specific to the IoT domain. TDM also uses a URN scheme for identifying all types in
the system and organizing them into hierarchies.
Topics
• Built-in Data Types (p. 202)
• URN ID Scheme (p. 203)
• Properties (p. 205)
• Enum Types (p. 207)
• Expressions (p. 207)
202
AWS IoT Things Graph User Guide
URN ID Scheme
URN ID Scheme
TDM URNs provide a hierarchical way of typing devices, properties, and entities. They provide
organizational information (such as physical location) about a type and semantic information (such as
color or the URI for an image).
• Hierarchical namespace
• Metatype
• Hierarchical semantic type path (delimited with '/') that is an instance of the metatype
203
AWS IoT Things Graph User Guide
URN ID Scheme
urn
Fixed identifier that is the URN namespace for the AWS IoT Things Graph Data Model.
namespace
Identifier provided by the user. There are two kinds of namespaces: public and private. The public
namespace contains the built-in entities (such as primitive properties) supported by AWS IoT Things
Graph. A user's private namespace contains entities, workflows, and other AWS IoT Things Graph
entities that the user creates. Private namespaces are versioned, and they track and synchronize with
the public namespace. For more information about namespaces, see the definition in the Glossary.
metatype
The hierarchical path that specifies an instance of the metatype. When the metatype is Action or
Event, the sem-type-path values specify a capability and an action or event that is an instance of
the capability, as in the following example.
urn:tdm:aws:action:camera/capture
Enum urn:tdm:aws:enum:actionStatus
Category urn:tdm:aws:category:color
Device urn:tdm:aws:device:flashlight
Property urn:tdm:aws:property:switch
State urn:tdm:aws:state:brightness
Capability urn:tdm:aws:capability:camera
Action urn:tdm:aws:action:camera/capture
Event urn:tdm:aws:event:camera/clicked
Annotation urn:tdm:aws:annotation:cameraUsage
Mapping urn:tdm:aws:mapping:brightnessRangeEnumToNumber
Workflow urn:tdm:aws:flow:simpleHomeSecurity
204
AWS IoT Things Graph User Guide
Properties
Properties
The PropertyType construct is used to define the attributes of a device. For example, a device named
Light Bulb might have properties like PowerState, Brightness, and Color.
Note
The ignore:void name-value pair specifies an empty body payload.
PropertyType Facets
The PropertyType construct is defined by property facets. There are two kinds of facets:
• Definition - These facets help create or define a PropertyType. Example definition facets include
Name, DataType, Accuracy, and Uom. You can specify the Uom and Accuracy facets with instance
values. For example, a PropertyType named Length that has a Uom facet can be assigned an
instance value of 10 inches or 10 feet.
• Usage - These facets help customize a PropertyType within a specific scope. Example usage facets
are calculated values like Condition and Expr.
Definition Facets
SemTypeId
The semantic type hierarchical path asserts an "is-a" relationship contract between parents and
children in the path. This relationship establishes semantic equivalence and doesn't imply structural
equivalence. The subype is a semantically equivalent alternate of its parent type for the purpose
of interoperability in an IoT workflow. For example, a brightness property expressed by a range of
numbers between 1 and 100 is semantically equivalent to a brightness property expressed as an
enum.
Example: urn:tdm:aws:property:length
DataType
Required. A value from the built-in enum DataType. See Built-in Data Types for the possible values
for this facet.
You can also limit the range of an integer property type by using the minValue and maxValue
attributes, as in the following example. The property type definition creates an on/off property that
is represented as a 0 for off and 1 for on.
205
AWS IoT Things Graph User Guide
Properties
Description
A URN that specifies a complex property's type. This value is required whenever the property's
DataType value is not one of the built-in primitive data types.
Uom
Optional. A value from the built-in enum under the semantic path at this URN:
urn:tdm:aws:enum:uom. This value specifies the unit of measure associated with the property's
value.
Example: urn:tdm:aws:uom:base/mass
Accuracy
Optional. A float32 value that describes the closeness of a measurement's value to the true value.
This value can be expressed as either a +/- absolute value or a percentile value. TDM doesn't process
this value.
IsAbstract
Optional. A Boolean value that specifies whether the PropertyType can be used in a concrete type.
The default value is false. An abstract PropertyType is usually the root of a property hierarchy.
IsGlobalId
Optional. A Boolean that specifies whether the value of a property is unique across all instances
of the type that contains the property. The default value is false. It applies only to non-nullable
identifier properties. If the value is true, the instances of the type that contains the property can be
used by reference. A DeviceCatalog is an example of the kind of type that would have this facet
set to true.
MinLength, MaxLength
Optional. Number values that specify in bytes the minimum and maximum length of a string
property. The default value of MinLength is 0. The default value of MaxLength is 4096. When both
values are the same, the property has a fixed length.
MinValue, MaxValue
Optional. Number values that specify the minimum and maximum values of a numeric property. The
numeric property can be of any type of int, uint, and float.
Usage Facets
IsRequired
Optional. A Boolean value that specifies whether a property is required for every type that contains
the property. The default value is false.
Default
Applicable only to properties for which the IsRequired facet has been set to true. A variant-typed
facet that specifies the default value of a property.
Condition
Optional. A Boolean expression that evaluates other properties of the type that contains the
property. If the expression evaluates to true, the property value is included. If the expression
206
AWS IoT Things Graph User Guide
Enum Types
Optional. A Boolean facet that specifies whether the property is read-only. The default value is
false.
Multiplicity
Optional. An enum facet that specifies the number of values that a property can have. The default
value is Multiplicity.Multivalued. A value of Multiplicity.Singlevalued limits the
number of values of a property to 1.
Enum Types
The EnumType construct defines an enumeration that associates unique identifiers to integer values
within a specified scope.
Examples
Expressions
TDM provides several ways to specify values whenever you define or use TDM constructs. You can often
specify literal values, but on many occasions you might need to evaluate information before specifying a
particular value.
Workflows need to manipulate and evaluate data before determining what actions to take. For example,
certain steps can't be taken unless a given condition is met. In that case, a Boolean expression might be
appropriate.
Mappings use expressions to transform information from one device into representations that other
devices can understand. A service or device definition might require end user input, and this input can be
represented as variables in TDM expressions.
The following list contains the types of expressions that TDM supports. Variables can be used in
expressions. In TDM, variable names begin with $. Each expression type is followed by a set of examples.
Literal
Expressions that are static instances of the built-in primitive data types.
207
AWS IoT Things Graph User Guide
Expressions
Predicate
True
False
10 < 13
$aValue > $bvalue
(10 + 11) == 21
Path
Expression that enables navigation through a complex object. TDM supports path expressions that
use both the forward slash (/ ) and dot (.) notations.
image.value
image/value
users[name == 'rob'].height
Arithmetic
Expression that results in a numeric value. The values used in an arithmetic expression can be other
kinds of expressions.
1 + 2
100UL - 3.4L
'abc' + 1 + 2
(3 / 4) / (5 / 4)
users[name == 'rob'].height * 0.9
Ternary
$aValue < $bvalue ? 'This is returned if $aValue is less than $bValue' : 'This is
returned if $aValue is not less than $bValue'
IsNull
Expression that uses two ? symbols to determine whether the value to the left of the operator is
null. If the value to the left of the operator is null, the value to the right is returned. If the value to
the left of the operator is not null, the value to the left is returned.
208
AWS IoT Things Graph User Guide
IoT Domain Constructs
Function calls
TDM supports a set of utility functions. These functions wrap the utility functions in java.lang.math
and java.lang.string. All of these begin with tdm.lib. Array type parameters aren't supported.
InstanceOf
TDM supports the use of instance methods on primitive data types. These are similar to instance
methods in Java, such as String.substring() and Integer.doubleValue().
Macro
TDM supports interpolation of values into a string by wrapping expressions inside ${}.
You can use expressions in all kinds of TDM definitions, but they're especially important in Workflow
and Mapping constructs. (See Workflows and Mappings for examples.) The examples in those sections
demonstrate how to use expressions to evaluate and manipulate data supplied by devices and services.
Topics
• State (p. 210)
• Mapping (p. 211)
• Event (p. 215)
• Action (p. 215)
• Capability (p. 216)
• Device Model (p. 216)
• Device (p. 217)
• Service (p. 219)
• Workflow (p. 221)
• System (p. 225)
• Trigger (p. 226)
209
AWS IoT Things Graph User Guide
State
State
The State construct is a set of properties that represent the inner state of a device at a point in time.
You can also create complex properties that are composed of States.
Examples
210
AWS IoT Things Graph User Guide
Mapping
Mapping
The Mapping construct bridges differences across multiple representations of the same concept. It
converts semantically equivalent data from one representation to another. A Mapping creates a single
semantic view of data that originates from multiple sources.
TDM supports directional (forward and backward) and symmetrical mappings. The keywords Forward,
Reverse, and Symmetric specify the mapping direction. TDM validates mappings by identifying
duplications and gaps in the mapping space.
Mappings enable the AWS IoT Things Graph runtime to transform different representations of the
equivalent properties. A relatively simple example of how mappings can work is the on/off status of
a device. One possible representation of a device's on/off status is as an integer (0/1). The following
example uses the built-in int data type to define this kind of on/off property.
The next example shows how to create an on/off enum and use it to represent the on/off property of a
device.
The properties use different data types, but they represent the same concept. You can transform these
representations in both directions by using the following mapping.
211
AWS IoT Things Graph User Guide
Mapping
forward {
map(expr:'s == ON => 1'), # If enum value is ON, map 1 from property s to property
t.
map(expr:'s == OFF => 0') # If enum value is OFF, map 0 from property s to property
t.
}
reverse {
map(expr:'t == 1' => ON), # If integer value is 1, map ON from property t to
property s.
map(expr:'t == 0' => OFF) # If integer value is 0, map OFF from propery t to
property s.
}
}
This example uses the @mapping directive to create the OnOffEnum_to_OnOffInt under the mapping
metatype. It assigns the URN of the OnOffEnum property to the from field and the URN of the
OnOffInt property to the to field. A Forward mapping uses a set of expressions to transform values
of the from property into values of the to property. A Reverse mapping uses a list of expressions to
transform values of the to property into values of the from property.
The enum property alias is defined as s, and the integer property alias is defined as t. The Forward
mapping transforms the enum property of ON into the integer property of 1, and the enum property of
OFF into the integer property of 0. The Reverse mapping transforms the integer values into the enum
values.
The expressions inside the braces contain the logic that transforms the values back and forth. For details
about how to construct and use TDM expressions, see Expressions.
Additional Examples
The following example creates a mapping between two simple properties that represent brightness. The
example creates the following constructs:
# Create concrete property brightnessSimpleRange that sets the possible values for the
brightness property
type brightnessSimpleRangeProperty @propertyType(
id:"urn:tdm:aws:property:brightness/brightnessSimpleRange",
description: "Brightness value: low-medium-high",
dataType:"urn:tdm:aws:enum:SimpleRange”){ignore:void}
212
AWS IoT Things Graph User Guide
Mapping
# Create concrete property brightnessNumber that sets the possible values for the
brightness property
type brightnessNumberProperty @propertyType(
id:"urn:tdm:aws:property:brightness/brightnessNumber",
description: "Brightness value from 0-100",
dataType:"urn:tdm:aws:dataType:int32”,
min:0, max:100 ) {ignore:void}
The following example creates a symmetrical mapping between to complex properties that represent
color. It creates the following constructs:
213
AWS IoT Things Graph User Guide
Mapping
forward( # All properties used in Min() must be in same hierarchy or explicitly mapped
map(expr:"Math.min(f.red, f.blue, f.green) => t.white")
)
reverse( # All t.* properties must be mapped; If property has to be skipped, map to
NULL.
map(expr:"t.white => NULL")
)
}
The following example uses the mappings and properties from the previous two examples to create an
additional complex mapping. It creates the following constructs.
• A state that contains the numerical range representation of brightness and the RGB representation of
color
• A state that contains the enum representation of brightness and the RGBW representation of color
• An abstract property named brightColor
• A concrete complex property composed of the first state (numerical range brightness and RGB color)
• A concrete complex property composed of the second state (enum representation of brightness and
RGBW color)
• A mapping between the two new complex properties
214
AWS IoT Things Graph User Guide
Event
Event
The Event construct describes a notification from a device that some action has been taken on it, such
as a click of a camera. The structure of this construct contains the following information:
The following example creates an event that is published whenever a camera is clicked.
Action
The Action construct is an abstract representation of a device performing an instance of its capability,
such as a camera capturing an image. An Action takes properties as its parameters and returns
properties as its output.
The following examples create three kinds of camera capture actions. The three actions vary according
the types of parameters they take (if parameters are present). The first example describes the simplest
kind of camera capture. The other two make the camera capture more complex by passing parameters
that set a delay in milliseconds and picture resolution. All three return an image URL as output. The
return keyword inside the braces and followed by a colon precedes the return value's name, type
(@property directive), and URN.
215
AWS IoT Things Graph User Guide
Capability
type cameraAdvancedCaptureAction
@actionType(id:"urn:tdm:aws:Action:cameraCapture/cameraDelayedCapture/
cameraAdvancedCapture") {
delay_ms : uint16 @property(id:"urn:tdm:aws:property:uint16"),
resolution : enumLowMediumHigh @property(id:"urn:tdm:aws::property:resolution/
enumLowMediumHigh"),
return : imageLinkUri @property(id:"urn:tdm:aws:property:imageLink/
imageLinkUri”)
}
Capability
The Capability construct describes a piece of functionality that is implemented by an IoT device. A
Capability can extend one or more pre-existing Capabilities. It's a package containing a State
and a set of Actions and Events. A Capability definition consists of the following:
• A unique identifier
• At most, one State
• A set of Actions
• A set of Events
The following example creates a camera capability consisting of the cameraState state, the
cameraCapture action, and the cameraClicked event created in the previous examples.
Device Model
The DeviceModel construct describes an abstraction of an IoT device or a stateful service. A
DeviceModel must implement one Capability. It represents a conceptual device and isn't tied to any
specific manufacturer.
The following example creates a camera device model that contains the camera capability created in the
previous example.
216
AWS IoT Things Graph User Guide
Device
Device
The Device construct describes a specific IoT device that implements the Capability of a
DeviceModel.
This is not a concrete device, but an abstract definition of a device. After a device is defined in TDM,
concrete devices can be mapped to the device definition.
The following pseudocode describes what happens at a conceptual level when you create a device.
Key Concepts
deviceUrn
The URN that uniquely identifies the device model from which the device inherits.
actionName
217
AWS IoT Things Graph User Guide
Device
topicPath
GraphQL Example
The following example creates a camera device that implements the camera device model.
218
AWS IoT Things Graph User Guide
Service
• The URN that uniquely identifies the device model (second argument).
• The communication protocol used by the device. Possible values are ModBus (for local
communication), HTTP (for remote communication), and MQTT (for both local and remote
communication).
• The name and unique identifier (URN) of the capability that the device implements.
• The Action name and implementation.
• The Request definition. This definition specifies the MQTT request topic and the parameters, if any,
that are sent to it.
• The Response definition. This definition specifies the MQTT response topic and the payload (an image
URL) that is sent to it.
• The Event implementation.
Service
The Service construct describes either an AWS Lambda or a RESTful web service that can be called
from a Workflow.
Conceptually a Service is analogous to a Device, because it can be called inside a workflow step. The
structure of a Service is also similar to that of a Device. The primary difference is that the Action
of a Service is a call to the web service or an invocation of a Lambda function. The Service structure
contains the input and output parameters of the web service or Lambda call.
The following example creates a Service that invokes a Lambda function. The Lambda function uses
Amazon Rekognition to match an image passed from the workflow with another image.
219
AWS IoT Things Graph User Guide
Service
The following example creates a Service that calls a web service. The web service creates a queue and
then sends a message that contains the queue name.
220
AWS IoT Things Graph User Guide
Workflow
This example contains the following key elements that differ from the AWS Lambda service.
You implement a service in a Workflow in a way that is nearly identical to a device implementation. See
the WebServiceActivity implementation in Workflow for a sample implementation of a Service.
Workflow
The Workflow construct (also called flow) describes an automated process that consists of multiple
devices and stateful services.
Workflow takes a set of parameters and consists of an array of steps that are connected to events. Input
events can trigger a step, and a step can generate an output event. Each step can represent a Lambda
function, a device action, or a web application method.
221
AWS IoT Things Graph User Guide
Workflow
The following pseudocode defines what happens at a conceptual level when you create a workflow.
Key concepts
workflowUrn
Variable name.
varType
Variable type.
stepName
Optional description.
conditionExpr
Input or output event name. The step either waits for it to start, or publishes it on completion.
222
AWS IoT Things Graph User Guide
Workflow
eventUrn
A Boolean condition.
onPassExpr
OnError is evaluated when the activity fails or times out. The Retries are evaluated in the
specified order. On exhaustion of all Retries, control falls to the Catch clause.
GraphQL Example
The following GraphQL creates a workflow that monitors door entry in a building. A camera takes a
picture of the person entering the building, which triggers a face detection service. The face detection
service then displays an image of the person on a screen. The example also handles camera errors and
failure.
steps {
# Set of steps.
223
AWS IoT Things Graph User Guide
Workflow
backoffRate:2.0, maxAttempts:2),
Retry(name:"foo2", errorEquals:["ErrorC"], interval:”5 sec”),
Retry(name:"foo3", condition:"${Error IN ('ErrorD', 'ErrorE')}", interval:”5
sec”)
}
Catches {
Catch(name:'catch1',condition:"${Error=='ErrorE'}",
expr:”$cameraFailed.IsTrue=true]")
}
}
OnSuccess {
# Validation of image captured by the camera
Check(name:"validation1", condition:"${lib.fileSize(cameraImage) > 100}" ) {
OnPass { stmt(expr:"${imageOK=true}") }
OnFail { stmt(expr:”$cameraFailed.IsTrue=true)"}
# Raise cameraFailed Event
}
}
}
This example contains the following key elements that differ from the AWS Lambda service:
• A set of arguments and their data types. This example passes three non-nullable device URNs, a
camera burst delay setting with a default value of 0, and an image URL (with a default value) for failed
image captures.
• The workflowType directive and its unique URN.
• A set of workflow variables and their data types (and property URNs).
• A list of steps with names and descriptions.
• Each step has an activity specification. Possible values are DeviceActivity and
WebServiceActivity.
224
AWS IoT Things Graph User Guide
System
• A DeviceActivity is specified by a device model and the ID of the concrete device in the workflow.
• The device or service activity that the device or service in each step performs. These activities are
specified in the device model's capability. They are implemented in the concrete device's definition.
• Error handling with the OnError, Retries, Retry, Catches, and Catch. The OnError clause is
evaluated when the activity fails or times out. The Retries clause is then evaluated in the specified
order until all Retry clauses have been attempted. If all of the retries fail, control falls to the Catches
clause. These clauses have the same semantics as Retry and Catch in AWS Step Functions. The
OnSuccess clause also contains additional validation to ensure that the camera captured a valid
image.
The workflow makes extensive use of Expressions to determine how the workflow proceeds, depending
on whether the camera works and the condition of the image that it returns. The web service activity, for
example, doesn't run unless a valid image is captured. See Expressions for more information about how
to use expressions.
System
The System construct describes a collection of devices, services, and workflows that interact with each
other in an IoT system.
For example, a security system can consist of entry sensors, cameras, light bulbs, and a door monitoring
workflow. A System can be composed of other systems to create arbitrarily complex systems of systems.
The following pseudocode shows what happens at a conceptual level when you create a system.
CREATE SYSTEM systemUrn [Description text] ‘{‘ [deviceRole deviceUrn [Description text]
[,]]*
[serviceRole serviceUrn [Description
text] [,]]*
[workflowRole flowUrn [Description text]
[,]]* ‘}’
Key concepts
systemUrn
GraphQL Example
225
AWS IoT Things Graph User Guide
Trigger
{
# Devices and Services: Begin
entrySensor: MotionSensorDevice @thing(id: "urn:tdm:aws:device:motionSensor"),
entryCamera: CameraDevice @thing(id: "urn:tdm:aws:device:camera"),
cameraLight: LightBulbDevice @thing(id: "urn:tdm:aws:device:lightBulb"),
faceDetection: FaceDetectionService @thing(id: "urn:tdm:aws:service:faceDetection"),
# Devices and Services: End
The following example creates a system that represents a professional camera room. It contains a
set of cameras and light bulbs, and a service that combines the images taken by the cameras into 3D
visualizations.
combineImages:CombineImagesFor3DVisualizationService
@service(id:"urn:tdm:aws:service:combineImagesFor3DVisualization")
}
Trigger
The Trigger construct defines the conditions that start a workflow.
Workflows can take parameters, including the device IDs to use in the workflow and other variables that
help dictate the flow of control. The parameters of a workflow are specified in the System Deployment
Configuration (SDC). SDC triggers have two components: a condition and some number of actions.
The condition specifies whether to trigger a new flow, and an action specifies exactly what to do if the
condition is true.
Because the parameters and triggers for a workflow are defined in a Deployment Configuration,
expressions are also useful in that context. Triggers have two components: a condition and a set of one
226
AWS IoT Things Graph User Guide
Trigger
or more actions. The condition specifies whether to trigger a new workflow, and an action specifies what
the workflow does if the condition is true. The following example shows some ways of using expressions
in the context of deployment configurations. This example also appears in Deployment Configuration.
triggers {
MotionDetectedTrigger(description: "an example trigger") {
condition(expr: "devices[name == 'entrySensor'].events[name ==
'motionDetected'].lastEvent.value") # Path expressions used inside a predicate
expression
action(expr: "ThingsGraph.startFlow('motionDetectionFlow',
devices.entrySensor.motionEvent)") # Initiate workflow
The first condition uses two path expressions to identify a device that is used in a workflow
and one of that device's events, with a predicate expression that determines whether the
device has detected motion. The devices[name == 'entrySensor'].events[name ==
'motionDetected'].lastEvent.value expression evaluates to true if the lastEvent value sent by
the entrySensor device is true, a non-empty string, or a numeric value other than 0. This signifies that
a motion detected event has occurred.
The second condition uses the same combination of path expressions inside a predicate
expression to determine whether a given motion has ended. The devices[name ==
'entrySensor'].events[name == 'motionDetected'].lastEvent.value == false
evaluates to true if the lastEvent value sent by the entrySensor device is false, an empty string, or 0.
This signifies that the sensor is no longer detecting motion.
The actions specified in this definition use the ThingsGraph.startFlow function, which initiates the
specified workflow and, where necessary, sends the devices.entrySensor.motionEvent to the
workflow.
TDM also supports time intervals as conditional expressions in triggers. For example, if you want an
action to occur every 5 minutes, you can specify that interval in the condition, as in the following
example.
You can express the duration of a time interval in a condition expression with the following values:
• Seconds
227
AWS IoT Things Graph User Guide
Deployments
• Minutes
• Hours
• Days
• Weeks
• Months
• Years
The actions specified in this definition use the ThingsGraph.startFlow function, which initiates the
specified workflow and, where necessary, sends the devices.entrySensor.motionEvent to the
workflow.
For more information about the types of expressions that you can use in TDM, see Expressions.
Deployments
The System construct creates an abstract structure that consists of devices and services.
The devices implemented in a specific instance of a System have a physical presence. TDM supplies
constructs that associate Systems with physical structures and that arrange the positioning of devices in
those structures.
The topics in this section describe the constructs that TDM provides for locating systems in physical
locations.
Deployment
The Deployment construct associates a physical location with specific devices and the triggers that start
the workflows in which they are used.
The following example creates a Deployment for the door entry security system.
Note
Note that this example makes extensive use of Expressions. For more information about how to
construct and use expressions, see Expressions.
triggers {
MotionDetectedTrigger(description: "an example trigger") {
condition(expr: "devices[name == 'entrySensor'].events[name ==
'motionDetected'].lastEvent.value") # Path expressions used inside a predicate
expression
action(expr: "ThingsGraph.startFlow('motionDetectionFlow',
devices.entrySensor.motionEvent)") # Initiate workflow
228
AWS IoT Things Graph User Guide
Deployments
action(expr: "ThingsGraph.startFlow('motionDetectionFlow',
devices.entrySensor.motionEvent)") # Initiate workflow
action(expr: "ThingsGraph.startFlow('logEventFlow')")
# Initiate workflow
}
}
}
}
The first condition uses two path expressions to identify a device that is used in a workflow
and one of that device's events, with a predicate expression that determines whether the
device has detected motion. The devices[name == 'entrySensor'].events[name ==
'motionDetected'].lastEvent.value expression evaluates to true if the lastEvent value sent by
the entrySensor device is true, a non-empty string, or a numeric value other than 0. This signifies that
a motion detected event has occurred.
The second condition uses the same combination of path expressions inside a predicate
expression to determine whether a given motion has ended. The devices[name ==
'entrySensor'].events[name == 'motionDetected'].lastEvent.value == false
evaluates to true if the lastEvent value sent by the entrySensor device is false, an empty string, or 0.
This signifies that the sensor is no longer detecting motion.
TDM also supports time intervals as conditional expressions. For example, if you want an action to occur
every 5 minutes, you can specify that interval in the condition, as in the following example.
You can express the duration of a time interval in a condition expression with the following values:
• Seconds
• Minutes
• Hours
• Days
• Weeks
• Months
• Years
229
AWS IoT Things Graph User Guide
Tag Basics
This topic describes tags and shows you how to create them.
Tag Basics
Tags enable you to categorize your AWS IoT Things Graph resources in different ways, for example, by
purpose, owner, or environment. This is useful when you have many resources of the same type—you can
quickly identify a specific resource based on the tags you've assigned to it.
Each tag consists of a key and optional value, both of which you define. For example, you could define
a set of tags for your system instances that helps you track them by location. We recommend that you
create a set of tag keys that meets your needs for each kind of resource. Using a consistent set of tag
keys makes it easier for you to manage your resources.
The Tag Editor in the AWS Management Console provides a central, unified way to create and manage
your tags. For more information, see Working with Tag Editor in Working with the AWS Management
Console.
You can also work with tags by using the AWS CLI and the AWS IoT Things Graph API. You can associate
tags with system instances when you create them by using the "Tags" field in the following command:
• CreateSystemInstance
You can add, modify, or delete tags for existing resources that support tagging by using the following
commands:
• TagResource
• ListTagsForResource
• UntagResource
• You can edit tag keys and values, and you can remove tags from a resource at any time.
• You can set the value of a tag to an empty string, but you can't set the value of a tag to null.
• If you add a tag that has the same key as an existing tag on that resource, the new value overwrites
the old value.
• If you delete a resource, any tags associated with the resource are also deleted.
230
AWS IoT Things Graph User Guide
Using Tags with IAM Policies
.
• Tag keys and values are case sensitive.
• Don't use the "aws:" prefix in your tag names or values because it's reserved for AWS use. You can't
edit or delete tag names or values with this prefix. Tags with this prefix don't count against your tags
per resource limit.
• If your tagging schema is used across multiple services and resources, remember that other services
might have restrictions on allowed characters. Generally, allowed characters are letters (uppercase
and lowercase), spaces, and numbers that can be represented in UTF-8, and the following special
characters: + - = . _ : / @
You use the Condition element (also called the Condition block) with the following condition context
keys and values in an IAM policy to control user access (permissions) based on a resource's tags:
Note
The condition context keys and values in an IAM policy apply only to those AWS IoT actions
where an identifier for a resource that's capable of being tagged is a required parameter. For
example, the use of CreateFlowTemplate will not be allowed or denied on the basis of condition
context keys and values, because no taggable resource (thing groups, thing types, topic rules,
jobs, or security profile) is referenced in this request.
Controlling Access Using Tags in the AWS Identity and Access Management User Guide has additional
information about using tags. The IAM JSON Policy Reference section of that guide has detailed syntax,
descriptions, and examples of the elements, variables, and evaluation logic of JSON policies in IAM.
The following example policy applies two tag-based restrictions. An IAM user restricted by this policy
cannot do the following:
• Give a resource the tag "env=prod" (in the example, see the line "aws:RequestTag/env" :
"prod")
• Modify or access a resource that has an existing tag "env=prod" (in the example, see the line
"aws:ResourceTag/env" : "prod")
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Deny",
231
AWS IoT Things Graph User Guide
Using Tags with IAM Policies
"Action" : "iotthingsgraph:*",
"Resource" : "*",
"Condition" : {
"StringEquals" : {
"aws:RequestTag/env" : "prod"
}
}
},
{
"Effect" : "Deny",
"Action" : "iotthingsgraph:*",
"Resource" : "*",
"Condition" : {
"StringEquals" : {
"aws:ResourceTag/env" : "prod"
}
}
},
{
"Effect": "Allow",
"Action": [
"iotthingsgraph:*"
],
"Resource": "*"
}
]
}
You can also specify multiple tag values for a given tag key by enclosing them in a list, as shown.
"StringEquals" : {
"aws:ResourceTag/env" : ["dev", "test"]
}
Note
If you use tags to allow or deny users access to resources, you must consider explicitly denying
users the ability to add those tags to or remove them from the same resources. Otherwise, a
user could circumvent your restrictions and gain access to a resource by modifying its tags.
232
AWS IoT Things Graph User Guide
Create Resources
The resources and infrastructure that you generate from a template is called a stack. You can define
all of your resources in one template or refer to resources from other stacks. For more information
about AWS CloudFormation templates and features, see What Is AWS CloudFormation? in the AWS
CloudFormation User Guide.
Creating Resources
AWS CloudFormation templates are JSON or YAML documents that describe the properties and
relationships of AWS resources.
• Flows (workflows)
In AWS CloudFormation templates, the structure and syntax of AWS IoT Things Graph resources are
based on the AWS IoT Things Graph API. For example, you create a flow by assigning values to the
definition and compatibleNamespaceVersion parameters. For more information, see AWS IoT
Things Graph API Reference.
233
AWS IoT Things Graph User Guide
Glossary
Action
An abstract representation of a device that performs an instance of its capability, such as a camera
capturing an image.
Camera example: The Camera device model in the AWS IoT Things Graph console has a capture
action.
Capability
An abstract representation of a specific piece of functionality that a device can perform, such as the
ability to capture an image.
Motion sensor example: The motion sensor device model in the AWS IoT Things Graph console has a
MotionSensorCapability that contains its capture action.
Device model
An abstract representation of a device as a set of actions, events, and states. A model separates a
device interface from its underlying implementation. Models are like building blocks that you can
snap together and integrate into any number of IoT applications. IoT applications can interact with
the model (and thereby the underlying device) by using the device capabilities that it exposes. AWS
IoT Things Graph includes built-in models. Users can also create their own with the AWS IoT Things
Graph model editor. Devices inherit from the device model and implement its capability.
Motion sensor example: You can find the motion sensor device model in the AWS IoT Things Graph
console. The Aukru HCSR501 Motion Sensor device (also available in the AWS IoT Things Graph
console) implements the generic motion sensor device model.
Device
Motion sensor example: The Aukru HCSR501 Motion Sensor is an example of a device. You can find it
in the AWS IoT Things Graph console. This device inherits from the motion sensor device model that
is also available in the AWS IoT Things Graph console.
Event
An abstract representation of a change in some condition or of an action that was taken on it, such
as the click of a camera.
Motion sensor example: The motion sensor device model in the AWS IoT Things Graph console has a
StateChanged event that occurs whenever the sensor detects motion.
Flow (or workflow)
A definition of the logical interactions and orders of execution between the devices and services.
Flows consist of device models and services. Flows define how the devices and services interact after
a triggering event occurs. A flow lists these interactions as a sequence of steps. Each step contains an
action on a device or web service, and the related inputs to and outputs from that action.
234
AWS IoT Things Graph User Guide
Flow configuration
An information model that enables AWS IoT Things Graph to convert the output message of
one device into the expected format for the next device in the flow. Mappings bridge differences
between the devices and enable them to work together. Mappings enable you to build IoT
applications that use a variety of devices from different manufacturers.
AWS IoT Things Graph includes mappings for basic types, such as Float32ToFloat64 and
JSONToString.
Namespace
The container for entities (for example, models), created using the Things Graph Data Modeling
(TDM) language, that are associated with a specific account. The namespace is part of the URN
for each entity. When you upload TDM entities for the first time, AWS IoT Things Graph creates a
namespace for you. The namespace consists of your AWS Region, your account ID, and default. The
pattern is REGION/ACCOUNT ID/default. For example, a TDM instance created in the us-west-2
Region looks like this: us-west-2/012345678910/default.
Each user has a unique private namespace that you can synchronize with the public namespace.
A visual representation of a workflow step in the AWS IoT Things Graph workflow designer.
Property
The basic building block of a state, which describes the state of a device, such as its color or
accuracy.
AWS IoT Things Graph provides several built-in simple properties, such as Int32.
Service Model
A web service or an AWS Lambda function that you can call from a workflow. Its role in a workflow is
analogous to that of a device (p. 234) or device model (p. 234).
The Rekognition service model in the AWS IoT Things Graph console exposes the Amazon
Rekognition DetectFaces API.
State
The motion sensor device model in the AWS IoT Things Graph console has a MotionSensorState.
This contains a Boolean property that indicates whether the sensor has detected motion.
TDM URN
A URN that provides a hierarchical way of typing devices, properties, and entities. It contains
organizational information (such as physical location) about a type, and semantic information (such
as color or the URI for an image).
The following TDM URN is the ID of the Aukru HCSR501 Motion Sensor device.
urn:tdm:aws/examples:device:HCSR501MotionSensor
235
AWS IoT Things Graph User Guide
236
AWS IoT Things Graph User Guide
ccxxxvii