AWS IoT Core

Concepts

The ScaleOut Digital Twin Cloud Service uses AWS IoT Core’s concept of topics to connect to data sources. A topic is a logical identifier for grouping messages sent by subscribers to AWS IoT Core, and AWS IoT Core’s clients connect to its message broker to publish or subscribe to topics. The cloud service’s AWS IoT Core connector uses two separate topics for each real-time digital twin instance: one for receiving messages from the corresponding data source, and another for sending responses back to the data source. Each data source sends messages to the cloud service on a topic name constructed as <model name>/<instance ID>, and it receives responses on a topic name supplied by the data source to the cloud service, for example, <model name>_RESPONSE/<instance ID>.

In addition, the connector needs a special topic, called Register that each data source uses to register itself and create its two topics. Each data source registers with the cloud service by publishing a JSON-formatted message to the Register topic with the following components:

  • “Model” : <model name>

  • “Id” : instance identifier

  • “Action” : “Register” or “Deregister”

  • “ResponseTopic” : <instance’s unique response topic name>

Note

The ScaleOut Java Digital Twin Client Library provides Java support for building registration messages using the RegsiterMessage class and for sending messages, as described below. Please consult the JavaDocs API Reference for details.

Data sources connect to AWS IoT Core as clients using a client identifier. The ScaleOut Digital Twin Cloud Service’s AWS IoT Core connector makes use of this client identifier to derive unique client IDs for its connections to AWS IoT Core. For this reason, your client ID needs to be supplied to the cloud service when creating an AWS IoT Core connector. (See below.)

AWS IoT Core tracks devices called “things.” Although the ScaleOut Digital Twin Cloud Service does not directly make use of things to interact with data sources (and instead relies on the use of topics), the AWS IoT Core connector needs artifacts associated with an AWS IoT Core thing in order to connect. In particular, it needs the client endpoint (a URI), client id, AWS Access Key Certificate, AWS Secret Key Certificate, and policy file. For this reason, you should create at least one thing in order to create these artifacts.

Also, the cloud service’s AWS IoT Core connector needs to ensure that the policy files used by the client thing(s) have the necessary permissions to allow connections to AWS IoT Core and to allow its topics to be used. In particular, the policy file must specify the following permissions:

  • iot:Publish and iot:Receive permissions on the “Register” topic and the topics used to send and receive from the digital twin model instances,

  • iot:Subscribe permission on the same topic filters as above, and

  • iot:Connect for the client IDs used by the AWS IoT Core connector

Note

The AWS IoT Core connector uniquely identifies its client IDs by adding a suffix of the form “-<MACHINE_NAME>” to your client id (supplied to the cloud service’s UI). For this reason, the policy file should use a wildcard (*) character after the client ID to allow these connections.

Here is a sample of a policy file:

{
  "Version": "2019-09-24",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Recieve"
      ],
      "Resource": [
                "arn:aws:iot:<REGION>:<ACCOUNT_ID>:topic/Registration",
        "arn:aws:iot:<REGION>:<ACCOUNT_ID>:topic/<MODEL>_RESPONSE/*",
        "arn:aws:iot:<REGION>:<ACCOUNT_ID>:topic/<MODEL>/*"
              ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Subscribe"
      ],
      "Resource": [
                "arn:aws:iot:<REGION>:<ACCOUNT_ID>:topicfilter/Registration",
        "arn:aws:iot:<REGION>:<ACCOUNT_ID>:topicfilter/<MODEL>_RESPONSE/*",
        "arn:aws:iot:<REGION>:<ACCOUNT_ID>:topicfilter/<MODEL>/*"
              ]
    },
    {
      "Effect": "Allow",
      "Action": [
                "iot:Connect",
      ],
              "Resource": [
                "arn:aws:iot:<REGION>:<ACCOUNT_ID>:client/<YOUR_CLIENT_ID>*"
              ]
    }
  ]
}

Creating an AWS IoT Core Connector

Prior to creating an AWS IoT Core connector using the cloud service’s UI, you should make sure that you have created a thing in AWS IoT Core and copied the artifacts described above that need to be shared with the cloud service’s AWS IoT Core connector. Also, be sure that your AWS IoT Core’s policy file(s) have been modified as described above to allow the connector to establish connections and exchange messages with data sources using topics. The following parameters need to be supplied to the UI when creating a connector:

  • connection name: an arbitrary string used to manage the connector in the cloud service’s UI

  • client endpoint: the URI used by your application’s things to connect to AWS IoT Core

  • client ID: the string ID used by your application when connecting to AWS IoT Core

  • AWS Access Key Certificate: the access key certificate supplied by AWS IoT Core when you created a thing

  • AWS Secret Key Certificate: the secret key certificate supplied by AWS IoT Core when you created a thing

Once the connector has been created, it automatically connects to AWS IoT Core and waits for registration messages from data sources. The connector establishes multiple connections to ensure high throughput and fast message handling.

Sending a Test Message

After creating an AWS IoT Core connector, you can register a data source and send the first message to its real-time digital twin instance through AWS IoT Core using the ScaleOut Java Digital Twin Client Library. To do this, first register a data source with the endpoint by sending a serialized JSON message to the “Register” topic. This registration message defines the topic used to send messages to a real-time digital twin model (“MyDigitalTwin” in the example below) and instance “23” and the response topic used by the instance to send messages back to the data source (“MyDigitalTwin_Response/23”). The following code snippet shows how to accomplish this:

// first, connect to AWS IoT through MQTT:
AWSIotMqttClient client = new AWSIotMqttClient(/* AWS connection credentials */);
client.connect();
System.out.println("MQTT client connected...");

// next, register this client
String registrationMessage = new RegistrationMessage(
       "MyDigitalTwin",   // the Digital Twin model
       "23",              // the Digital Twin id
       "MyDigitalTwin_Response/23", // the name of the response topic
       "Register");       // requested action
client.publish("Register", registrationMessage);

// also optionally subscribe this client to the response topic to receive messages back from the digital twin instance(s)
client.subscribe("MyDigitalTwin_Response/23");

// finally, send a message to a digital twin by sending a messages to the {model name}/{instance id} topic
client.publish("MyDigitalTwin/23", payload);

Note

It is important to register a real-time digital twin instance prior to publishing a message because messages sent to a topic with no registered subscribers will be lost.