PM2: AWS IoT Setup - Manual

Setting up the IoT Input Chain for Temperature Alarm

➡️ Background

In this section of the lab you will construct a demonstration of how an IoT setup can be used to detect the potential equipment failures based on a Temperature anomaly and create an Service notification to trigger the maintenance activities in SAP.

Technical Considerations

  1. For this workshop you’ll be using an AWS Cloud9 instance to simulate an Temperature Alarm. You can also use a Raspberry Pi to simulate an equipment failure.

  2. You will setup an IoT “Thing” in AWS IoT Core, once you have that setup you will run a small program to simulate data being sent to AWS IoT Core and then use the MQTT Test Client to view each MQTT message payload.

  3. Install CDK in your local environment. Follow the steps outlined in lab preparation section.

UNLESS OTHERWISE NOTED, ENSURE REGION SET TO US-EAST-1 (N. Virginia)

Step 1: Virtual Device and Data Generator

  1. Create a Cloud9 instance (t2.micro is sufficient). Sign in to the AWS Cloud9 console. Ask your instructor for sign-in instructions for this lab.

  2. After you sign in to the AWS Cloud9 console, in the top navigation bar, choose AWS Region US East to create the environment in.

Preparation menu

  1. Choose the large Create environment button in one of the locations shown. If you have no AWS Cloud9 environments yet, the button is shown on a welcome page.

  2. On the Name environment page, for Name, enter a name for your environment. To add a description to your environment, enter it in Description. Choose Next step

Preparation menu

  1. On the Configure settings page, for Environment type, choose one of the following options to create an EC2 backed environment:

    • Environment type : Create a new EC2 instance for environment (direct access).
    • Instance type : t2.micro (1 GiB RAM + 1 vCPU)
    • Platform : Amazon Linux 2

    Preparation menu

    • Cost-saving setting : Desired selection from the drop down. For this lab you can choose 4hours.
    • IAM role : Default.
    • Expand Network settings (advanced) : Leave the preselected default settings, AWS Cloud9 attempts to use the default VPC with its single subnet in the same AWS account and AWS Region as the new environment.
    • Click Next Step

    Preparation menu

  2. On the Review page, choose Create environment. Wait while AWS Cloud9 creates your environment. This can take several minutes.

  3. Execute following command to install numpy. NumPy is the fundamental package for array computing with Python.

pip3 install numpy

Preparation menu

  1. Clone the following github repo to you desk top.
git clone https://github.com/aws-samples/aws-connected-mobility-solution-telemetry-device-demo.git

Preparation menu

  1. Access the download directory path and install the requirements.
cd aws-connected-mobility-solution-telemetry-device-demo/

sudo pip3 install -r requirements.txt

  1. Install boto3
sudo python -m pip install boto3

Step 2: Create an IoT Device Thing in IoT Core, download keys and certs.

  1. Setup an IoT “Thing” in AWS IoT Core, once you have that setup you will run a small program to simulate data being sent to AWS IoT Core and then use the MQTT Test Client to view each MQTT message payload.

Preparation menu

  1. Log into your AWS console and make sure you can access the AWS IoT dashboard by selecting IoT Core in AWS Services search window. It should like the following. Click “Onboard” menu option. We’re going to select “Onboard a device” - click the Get started button to view the process overview screen:

Preparation menu

  1. After reviewing the onboarding procedures, click the Get started button.

Preparation menu

  1. Next, we’re going to pick our target operating system and development language. This is used to generate a full package for us to quickly connect to AWS IoT. For the hardware we’re working on today let’s pick Linux/OSX as our platform and Python for our SDK. Click Next

Preparation menu

  1. Ok so now we’re ready to get started. Click Next and then enter a name for your new Thing. For these labs let’s call our new thing as telemetryThing

Preparation menu

  1. On the next screen you can see that everything has been generated for you!

So let’s see exactly what was generated.

  • You’ll notice a security policy has been created for you allowing you to immediately send and receive messages.
  • A start.sh script has been created, this script will download any additional files needed including a sample application.
  • Finally, a Linux/OSX zip file containing all your certificates.

Preparation menu

  1. You should see Linux/OSX zip file containing all your certificates in your download folder.

Preparation menu

Do not lose this zip file, it contains your private key file which cannot be retrieved again.

  1. Once you have downloaded the zip file you’ll be able to click the Next step link. Click Done to complete the Wizard

Preparation menu

Step 3: Adjust our “Thing” Security Policy

➡️ The default security policy created by the above wizard will limit the topics your device can publish on. For the labs in this workshop we’re going to create a more open policy(just for the lab purpose). So we need to find and edit the policy that has been created already.

  1. In the IoT Console click on Manage - it will default to Things.
  • Find the thing you just created, in this case look for telemetryThing.
  • Click on your device to see it’s details.
  • Click on Security.
  • Click on the attached certificate - see below

Preparation menu

  1. You will see your certificate details. Click on Policies

Preparation menu

  1. Click on your policy, usually that’s telemetryThing-Policy
  • Click Edit Policy Document
  • Enter the following for your document and click Save as new version.
{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Effect": "Allow",
     "Action": [
       "iot:Publish",
       "iot:Subscribe",
       "iot:Connect",
       "iot:Receive"
     ],
     "Resource": [
       "*"
     ]
   }
 ]
}
  1. That’s it! your device can now publish and subscribe to any topics.

Quick Review

Let’s have a quick review.

  • Your certificates have been created and activated for you.
  • A security policy has been created and modified for the access we need.
  • The certificate and security policy have been attached to the thing “ratchet” that you created.

➡️ The above are the three requirement components to use AWS IoT.

Step 4: Copy files to your device

We need to put these certificates on our device or EC2 instance. Using the Cloud9 IDE we can easily upload these.

  1. Extract the certificates from the zip file you downloaded above.
  2. Open your Cloud9 environment. Select aws-connected-mobility-solution-telemetry-device-demo folder.
  3. Use the File -> Upload Local Files

Preparation menu

  1. Select files private.pem.key, -public.pem.key, -certifiate.pem.crt from you download folder and upload the files. Close upload window.
  2. Rename telemetryThing.cert.pem to telemetryThing-certificate.pem.crt
  3. Rename telemetryThing.private.key to telemetryThing-private.pem.key
  4. Rename telemetryThing.public.key to telemetryThing-public.pem.key

Preparation menu

Step 5: Get endpoint and root cert

  1. In Cloud9 IDE Terminal window execute the following commands

cd ~/environment/aws-connected-mobility-solution-telemetry-device-demo

  1. Download the cert.
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O root.ca.pem

Step 6: Setting up for Random Simulation without replay data

➡️ Background

  • When captured, simulated, reference or other data is not available, it is straightforward to configure the telemetryThing to use randomized telemetry.

This guide describes how to set that up and also shows the use of dot notation for property names:

To accomplish this, setup a generator script that emits a single row of header information, which gives the property names for the final payload (optionally using dot notation) and redirect the output to a named pipe.

The telemetryThing can then read from this pipe and send the data. This gives a great deal of control over the simulation and randomization of the data.

Step 6.1: Modify and copy the generator script in Cloud9
  1. Open the file gen.py from this AWS Cloud9 path $/environment/aws-connected-mobility-solution-telemetry-device-demo/samples.

    • As written in gen.py script, the FIRST metric is the timestamp in milliseconds that will be part of each record. The telemetryThing will also use this value for delay loop timing, so the gen.py script incorporates a matching delay between emission of records.
  2. Each parameter can have a method for randomization. In the example, Timestamp(ms) is randomized with a normal distribution with a mean of 5 seconds and a standard of deviation of 1 second.

  3. Additional parameters can be added to the metrics table below Timestamp(ms). While any method can be used to randomize, the np.random.choice method is handy to choose among a set of options, this set can be a single value to create a constant.

  4. In the example, note the measure names e.t and e.h. If the payload_strategy is set to DotLabelledPayload, these will be expanded to create a message payload like

{
    "Timestamp(ms)": 12345.6789,
    "e": {
        "t": 18.9,
        "h": 34.5
    },
    "l": "{c={o=AT&T, a=[{i=1704630, l=56986, c=310, n=410}]}"
}
  1. Run the gen.py script a few times in the terminal to ensure the data is being created as desired. It may be helpful to copy the script to the same directory as telemetryThing. You may also need to set the execute bit (chmod +x gen.py).
cd samples

python3 ./gen.py

Preparation menu

  1. You can stop the generator anytime using. You can restart the generator when you complete the rest of the below steps.
ctrl-c

Step 6.2: Create a named pipe

  1. Create a fifo to buffer the data from the generator to telemetryThing. Ensure you execute the command from this directory $ aws-connected-mobility-solution-telemetry-device-demo/
cd ~/environment/aws-connected-mobility-solution-telemetry-device-demo

mkfifo generated_data

Step 6.3: Configure telemetryThing

  1. Modify/Validate the Config.py file. Copy this file Config.py to below directory (drag and drop or cut and paste).

`/environment/aws-connected-mobility-solution-telemetry-device-demo`

  1. Copy the below code snippet into Config.py and save the file.

Preparation menu

state = {
    'file': 'file:///generated_data',
    'record_separator': '\t',
    'quote_records': True,

    #
    # Timestamp handling
    #
    'time_col_name': 'Timestamp(ms)',   # column name to use for time        
    'time_scale': 1000.0,               # units/second -- e.g. 1000.0 means stamps in milliseconds

    # Select a Strategy from MessagePayload.py to define how to format a payload from the record
    'payload_strategy': 'DotLabelledPayload',
    
    # Topic to publish messages, different payload_strategies may need different templates using local vars
    'topic_name': "dt/{deviceid}",
    
    # what to do at the end of the file... 'stop' or 'repeat'
    'at_end': 'repeat',
}   

This script is designed to execute the following steps:

  • read from the fifo ‘file:///generated_data’ with the proper formatting.
  • use the Timestamp(ms) column for timing
  • use the DotLabelledPayload strategy
  • Save the file.

Step 6.4: Start the Generator

  1. Go to the following path to start the generator.
cd samples

  1. Start the generator. Ensure you execute the below command from this folder /environment/aws-connected-mobility-solution-telemetry-device-demo/samples
python gen.py > generated_data

  1. Open a new terminal in Cloud 9.

Preparation menu

  1. Access to the github directory path.
cd aws-connected-mobility-solution-telemetry-device-demo/

  1. Here you will export an endpoint that allows you to connect to AWS IoT.
    • Each of your AWS IoT Thing has a REST API available at this endpoint.
    • This is also an important property to insert when using an MQTT client or the AWS IoT Device SDK. Execute the following commands in your Cloud9 IDE Terminal.

export ENDPOINT=$(aws iot describe-endpoint --endpoint-type iot:data-ats --query 'endpointAddress' --output text)

export CERT=$(ls *cert.pem)

export KEY=$(ls *private.key)

Inspect the variables
  • inspect the variables:
  • echo $ENDPOINT
  • echo $CERT
  • echo $KEY
  1. Start the telemetryThing with following command. If your thing name is diffrent that ‘telemetryThing’ change the name before executing the command line.
python3 ./telemetryThing.py -e $ENDPOINT -r root.ca.pem -c $CERT -k $KEY -n 'dt/telemetryThing'

Ensure you start the generator gen.py > generated_data before starting the telemetry device in this step. Keep this simulation running until you finish the lab.

  1. Observe output on the console in your cloud9 terminal.

Preparation menu

  1. Verify the message traffic.
  • Go to IoT Console to access IoT core service.
  • Click Test -> MQTT test client.

Preparation menu

  • Subscribe to topic ‘dt/#’
  • Observe that the messages are arriving in the test client. **May take 1-2 minutes before you see the message in AWS console.

Preparation menu

Results: You now have a random generator running and sending the data to IoT Core and ready for further integration. Spend a minute watching the messages and note how ‘noisy’ the data is. In the next section, we will create an analytics pipeline to smooth the data.

Step 7: Setting up SAP attributes in AWS IoT

➡️ In this step, you will map the SAP master data to AWS IoT registry. When there is an anomoly detected, AWS IoT will send a message with the maintained attributes to SNS to send an alert to Lambda to create a Service notfication in SAP.

  1. Login to IoT Core -> Manage -> Things>ThingName>Edit

Preparation menu

  1. Enter the following values in Set searchable thing attributes (optional) and click update.
  • Type = Compressor
  • Equipment= 299998888 (SAP Equipment number you used in the previous lab)
  • FunctLoc = MUM1-THA-AB-02 (SAP Functional location you used in the previous lab)
  • Click update.

Preparation menu

Step 8: Setting Acceptable Temperature range in a Dynamo table

  1. Open the DynamoDB console
  2. Choose Create Table. Preparation menu
  3. In the Create DynamoDB table screen, do the following:
  • On the Table name box, enter trackedEquipment with item.
  • Enter the Primary key as Type and Click Create

Preparation menu

  • Click Create Item.

Preparation menu

  • Copy and paste the follow items attributes by selecting Text option in pop-up window.
{
  "range": {
    "temperature": {
      "max": 10,
      "min": 2
    }
  },
  "Type": "Compressor"
}

Preparation menu

Step 9: Create Lambda funtion for the IoT Analytics setup

➡️ Lambda is references by the IoT Analytics setup to get the product range from the Dynamo DB to identify the temperature range to determine if there is a temperature fluctuation in the data sent from the IoT simulator.

  1. Open the Functions page on the Lambda console.

  2. Choose Create function.

  3. Select the Author from the scratch option.

  4. Under Basic information, do the following:

  • For Function name, enter getProductRange.
  • For Runtime, select Python 3.8 or latest version.
  • Choose Create function.

Preparation menu

  1. Paste the code for the lambda in the code souce section by selecting lambda_funtion.py and click Deploy.
import boto3
import json
import logging
import sys


logger = logging.getLogger()
logger.setLevel(logging.INFO)
streamHandler = logging.StreamHandler(stream=sys.stdout)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('trackedEquipment')


def lambda_handler(event, context):
    logger.info("events before processing: {}".format(event))
    transformedEvents = []
    for e in event:
        logger.info(e)
        # extract productid
        try:
            e['range'] = table.get_item(
                Key = {'Type': e['registry']['attributes']['Type']}
            )['Item']['range']
            logger.info("transformed event {}".format(e))
        except Exception as e:
            logger.info("Exception: " + str(type(e)))
            logger.info("couldn't find range for event {}".format(e))
        finally:
            transformedEvents.append(e)
    return transformedEvents

Preparation menu

  1. Click configuration -> Permission ->Click on the role name

Preparation menu

  1. Attach the Dynamo DB read access. Click attach policies -> DynamoDB read access ->Attach policy.

Preparation menu

  1. You must add a policy to grant AWS IoT Analytics permission to invoke your Lambda function. Run the following command in your AWS Cloud9 instance in a new terminal window OR issue the command from cloudshell with the name of your Lambda function(getProductRange).
aws lambda add-permission --function-name getProductRange --action lambda:InvokeFunction --statement-id iotanalytics --principal iotanalytics.amazonaws.com

Preparation menu

NOTE: For this lab we recommend you to jump ahead to set up the IoT Core Rules and then set up the pipeline so that the message previews can be inferred.

Step 10: Setting up IoT Core Rules.

➡️ AWS IoT rules send data from your devices to other AWS services. They listen for specific MQTT messages, format the data in the message payloads, and send the result to other AWS services.

  1. From the IoT Core Console, click ‘Act’/Rules and ‘Create’ a new rule.

  2. Input the following values in create a rule screen:

  • Name: trackerRule
  • Using SQL version: 2016-03-23
  • Rule query statement: Copy and paste the following sql query. Modify the following query with appropriate Thing name if your thing name is not telemetryThing
SELECT parse_time("yyyy-MM-dd'T'HH:mm:ssZ", timestamp() ) AS timestamp, topic(2) AS thingname, 
e.t AS temperature_degC, e.h AS humidity_percent, e.d AS dewpoint_degC, 
e.i AS heatIndex_degC, l AS location 
FROM 'telemetryThing' 

NOTE: This rule inserts an ISO8601 timestamp, the thingname (extracted from the topic), and expands the “shorthand” references to environmental conditions into more descriptive property names.

  1. Add Action to ‘Send a message to IoT Analytics’
  • Select Send a message to IoT Analytics

  • Click Configure Action.

    Preparation menu

  • Select Manually select IoT Analyics Channel and role.

  • Update channed name = trackerchannel

  • Click Create role and update role name as trackerIoT2AnalyticsRole, create new role and attach.

  • Click Add Action.

  • Click Create rule.

Preparation menu

Step 11: Setting up IoT Analytics.

➡️ AWS IoT Analytics automates the steps required to analyze data from IoT devices. AWS IoT Analytics filters, transforms, and enriches IoT data before storing it in a time-series data store for analysis

➡️ Integrated with AWS IoT Core—AWS IoT Analytics is fully integrated with AWS IoT Core so it can receive messages from connected devices as they stream in and identify anomaly based the defined ranges for an equipment in Dynamo DB

  1. On the AWS IoT Analytics console landing page, Click Channels->Then Click Create Channels

  2. Input the followin values:

  • Channel ID = trackerchannel
  • Choose storage type = AWS managed S3 bucket
  • Retain data in this store = Based on time
  • For = 1 day
  1. Click Next, then create channel (leave Iot Topic filter blank) and continue to Step 12.

Preparation menu

Step 12: Setting up IoT Analytics Pipeline

➡️ Pipeline activities enrich or transform message attributes, or filter entire messages out of your pipeline. Chaining activities together enables you to process and prepare messages before storing them.

  1. Create IAM role by choosing IoT service. See IAM documentation for more information. Select the following roles.
  • Create a new role in IAM - for IoT / IoT Use case.
  • THEN, edit that role to attach the policy.
  • Attach AWSIoTAnalyticsFullAccess policy
  • Give the role a NAME — trackerReadIoTDataRole
  • Edit, choose JSON. Copy/Paste
  • Attach, name policy ‘describeIoTThing’
  • Under trust relationship — edit if needed

Preparation menu

  • Create an inline service with following json snippet and attach to the role.
  {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:DescribeThing"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:<AWS Account number>:thing/*"
            ]
        }
    ]
}

Preparation menu

  • Ensure the trust relationship is for The identity provider(s) iotanalytics.amazonaws.com

Preparation menu

  1. On the AWS IoT Analytics console landing page actions menu select ‘Create a pipeline from this channel’. DON’T ignore ‘can’t find sample messge’ / keep retrying and verify messages are flowing before continuing.

Preparation menu

  1. Input Pipeline ID as trackerpipe. Click Next to the Attributes page. You shoud see the message from displayed from the IoT actions sent to the pipleline. Click Next.

Preparation menu

  1. In Enrich, transform, and filter messages page and click Add Activity

Preparation menu

  1. Add 3 Activities to the pipeline:. Please ensure you always click ‘update preview’ after adding each step mentioned below.
  • Choose Enrich messages with IoT Core Registry information. Input registy as attribute name, thingname for source for thing name select the IAM role that you created in previous step and click update preview.

Preparation menu

  • Click Add Activity in the same screen. Choose Remove Attributes from the message. You should check the values under the registry as shown in the below screen shot and click update preview.

Preparation menu

  • Click Add Activity in the same screen. Choose Transform message with Lambda Function and choose the lambda function you created in step 9.

Preparation menu

  1. Click Next.

  2. Setup a Data store output as a ‘Service-managed store’ with 1 day data retention. A data store receives and stores your messages.

  • Click create a new data store (opens new window).
  • Give name as trackerdatastore
    • AWS Managed S3 bucket / based on time / 1 day
    • JSON format
    • Create store
    • Create Pipeline

Note: It is not a database but a scalable and queryable repository of your messages. Processed data store messages are stored in an Amazon S3 bucket managed by AWS IoT Analytics or in one managed by you.

NOTE: This rule inserts an ISO8601 timestamp, the thingname (extracted from the topic), and expands the “shorthand” references to environmental conditions into more descriptive property names.

Step 13: Setting up IoT Events

  1. From the IoT Events Console. Click the hamburger menu->Inputs->Create Input:

Preparation menu

  1. Save the following code snippet as JSON in your local terminal and upload to input.
{
    "endTime": "2021-03-18T15:08:57+0000",
    "durS": 0,
    "thingname": "telemetryThing",
    "temperature_degC_mean": 17.91702618322083,
    "humidity_percent_mean": 35.12306710227172,
    "maxTemp_degC": 10,
    "minTemp_degC": 2,
    "location": "{c={o=AT&T, a=[{i=1707951, l=56986, c=310, n=410}]}}",
    "equipment": 299998888,
    "functloc": "MUM1-THA-AB-02",
    "type": "Compressor"
}

Preparation menu

  1. Name the input and note the name to connect it to IoT Analytics below (‘CDKSAPBlogEventsInput’ in this example).

Step 14: IoT Analytics: Data Set

  1. From the IoT Analytics Console, Click on ‘Data sets’ in the IoT Analytics Console and create a new data set. Setup a Data store output as a ‘Service-managed store’ with 1 day data retention. A data store receives and stores your messages. It is not a database but a scalable and queryable repository of your messages. Processed data store messages are stored in an Amazon S3 bucket managed by AWS IoT Analytics or in one managed by you.

Preparation menu

  1. Choose Sql and input tracker ID as CDKSAPBlogEventsInput and reference the datastore trackerdatastore created the above step.

Preparation menu

  1. Update the query section with the query. This query selects the most recent location information, but averages the temperature reading over the period. Also note that the range from Dynamo was previously injected into the message and the most recent value is selected here.
SELECT max(timestamp) AS endTime, (to_unixtime(from_iso8601_timestamp(max(timestamp))) - to_unixtime(from_iso8601_timestamp(min(timestamp)))) AS durS, max_by(thingname, timestamp) as thingname, avg(temperature_degC) AS temperature_degC_mean, avg(humidity_percent) AS humidity_percent_mean, max_by(range.temperature.max, timestamp) AS maxTemp_degC, max_by(range.temperature.min, timestamp) AS minTemp_degC, max_by(location, timestamp) AS location, max_by(registry.attributes.Equipment, timestamp) AS equipment, max_by(registry.attributes.FunctLoc, timestamp) AS functloc, max_by(registry.attributes.Type, timestamp) AS type FROM trackerdatastore

Note: Click Test Query to make sure it works.

  1. In the next screen, set a ‘Delta window’ with offset of ‘-5 seconds’ using this ‘Time field expression’ from_iso8601_timestamp(timestamp). Click Next.

Preparation menu

  1. Use this ‘Cron expression’ to run the query every minute. Click Next two times.

Preparation menu

  1. Add Configure the delivery rules of your analytics results.
  • S3 – select or create a new bucket.
  • Use default key expression : trackerDataSet/Version/!{iotanalytics:scheduleTime}_!{iotanalytics:versionId}.csv
  • Click Create role. Role name: trackerDataSetStorageRole or any desired name.
  • Click Add rule : Deliver result to IoTEvents
  • Select your IoT event created in previous step: trackerInput
  • Click Create role. Role name: trackerAnalytics2EventsRole or any desired name.
  1. Click create data set. Validate!

Preparation menu

Step 15: Creating Lambda for SAP integration.

  1. Clone the the following aws samples pacakge in AWS Cloud9. Or Use any local IDE (example Visual code) where you have aws cli installed

git clone https://github.com/aws-samples/aws-iot-sap-condition-monitoring-demo.git

  1. Execute the following command to set up local environment:
python3 -m venv .venv

source .venv/bin/activate

cd cdk-iot-analytics/

pip3 install -r requirements.txt

pip install \
    requests \
    xmltodict \
    -t ./cdk_sap_blog/sap/lambda_assets/layer/python/
  1. Execute the following command to configure stack variables in cdk.json in the following path.
~/cdk_sap_blog 

  • thing_name - “sap-iot-thing” (Any desired name)
  • sns_alert_email_topic - “TemperatureAlarm”
  • alarm_emails - “
  • odpEntitySetName - “<odpEntitySetName from previous step: ex - NOTIF_CREATESet>”
  • odpServiceName - “<odpServiceName from previous step example -ZPM_SERVICE_NOTIFICATION_SRV>”
  • sapHostName - “Your SAP host name”
  • sapPort - “8000” (For this example we will use sap http port maintained in SAP smicm transaction)
  • sapUsername - “SAP user name”
  • sapPassword - “password”

Preparation menu

  1. Deploy the latest version of cdk.

Ensure your run npm install -g npm from you local terminal to have the latest version of cdk

npm install -g npm

Preparation menu

  1. Access the following directory.

cdk-iot-analytics/

  1. Execute the following command to Bootstrap CDK to the target account/region.
cdk bootstrap aws://<account>/<region>

  • Validate the if you have bootstrapped to your account.

Preparation menu

  1. Deploy the SAP Stack. After successful execution, you should recieve a subscription notification to the emails in cdk.json/alarm_emails)
cdk deploy sap

  • Acknowlegde this message: Do you wish to deploy these changes = Y
  • Verify the successful deployment message in your local IDE.

Preparation menu

  • Make sure you confirm the subscription to receive the Alarm notification. Check the email account provided in cdk.json to confirm the SNS notification. This SNS topic will send notfication to Plant Maintenance worker.

Preparation menu

  1. Login into AWS Cloud Formation to validate the stack for sucessful deployment.

Preparation menu

  1. .Open the Functions page on the Lambda console.
  • Open the Lambda function CDK-SAP-Lab-OData-Function you created in the previous step. Copy the ARN to update in the IoT Events Model.

Preparation menu

Step 16: IoT Events - Detector models

  1. Create role called

  2. Create IAM role called trackerEventDetectorRole by choosing IoT service. See IAM documentation for more information.

  • Create a new role in IAM - for IoT / IoT Use case.
  • THEN, edit that role to attach the policy.
  • Attach the roles shown in the screen shot.
  • Under trust relationship — edit if needed

Preparation menu

  • Ensure the trust relationship is for The identity provider(s) iotevents.amazonaws.com
  • Copy the IAM ARN for the next step.

Preparation menu

  1. In the next step, login to your IoT Events Console, create a new Detector Model (hamburger menu/Detector models/Create detector model).

  2. Save the following code snippet as json file. Change the following ARN’s relating to you Lab Setup

  • Replace the Lambda ARN’s with your AWS Account Lambda ARN’s. (Hint - Four places)

    "lambda": { "functionArn": "arn:aws:lambda:us-east-1:<aws-account-number>:function:CDK-SAP-Lab-OData-Function",

    Preparation menu

  • Change the IAM ARN in line.

    Preparation menu

➡️ Modify Copy the below Code Snipped above described above.

  • Save the json snippet in you local terminal and name it as trackerEventDetectorModel.json
{
    "detectorModelDefinition": {
        "states": [
            {
                "stateName": "OverTemp",
                "onInput": {
                    "events": [],
                    "transitionEvents": [
                        {
                            "eventName": "overTempTooLong",
                            "condition": "timeout(\"hiTempDur\")",
                            "actions": [],
                            "nextState": "OverTempAlarm"
                        },
                        {
                            "eventName": "tempBelowMax",
                            "condition": "convert(Decimal,$input.trackerInput.temperature_degC_mean) < convert(Decimal,$input.trackerInput.maxTemp_degC)",
                            "actions": [],
                            "nextState": "TempInRange"
                        }
                    ]
                },
                "onEnter": {
                    "events": [
                        {
                            "eventName": "startTimer",
                            "condition": "true",
                            "actions": [
                                {
                                    "setTimer": {
                                        "timerName": "hiTempDur",
                                        "seconds": 300,
                                        "durationExpression": null
                                    }
                                }
                            ]
                        }
                    ]
                },
                "onExit": {
                    "events": [
                        {
                            "eventName": "deleteTimer",
                            "condition": "true",
                            "actions": [
                                {
                                    "clearTimer": {
                                        "timerName": "hiTempDur"
                                    }
                                }
                            ]
                        }
                    ]
                }
            },
            {
                "stateName": "TempInRange",
                "onInput": {
                    "events": [
                        {
                            "eventName": "readTemp",
                            "condition": "true",
                            "actions": [
                                {
                                    "setVariable": {
                                        "variableName": "temperature_degC",
                                        "value": "convert(Decimal, $input.trackerInput.temperature_degC_mean)"
                                    }
                                }
                            ]
                        }
                    ],
                    "transitionEvents": [
                        {
                            "eventName": "tempAboveMax",
                            "condition": "convert(Decimal, $input.trackerInput.temperature_degC_mean) > convert(Decimal, $input.trackerInput.maxTemp_degC)",
                            "actions": [],
                            "nextState": "OverTemp"
                        },
                        {
                            "eventName": "tempBelowMin",
                            "condition": "convert(Decimal,$input.trackerInput.temperature_degC_mean) < convert(Decimal,$input.trackerInput.minTemp_degC)",
                            "actions": [],
                            "nextState": "UnderTemp"
                        }
                    ]
                },
                "onEnter": {
                    "events": [
                        {
                            "eventName": "inRange",
                            "condition": "true",
                            "actions": [
                                {
                                    "lambda": {
                                        "functionArn": "arn:aws:lambda:us-east-1:114234835530:function:CDK-SAP-Blog-OData-Function",
                                        "payload": {
                                            "contentExpression": "'{\n    \"d\": {\n        \"Equipment\": \"${$input.trackerInput.Equipment}\",\n        \"FunctLoc\": \"${$input.trackerInput.FunctLoc}\",\n        \"ShortText\": \"Temperature Alarm[TempInRange:inRange]\",\n        \"LongText\": \"Temperature Alarm in ${$input.trackerInput.Type} Motor\"\n    }\n}'",
                                            "type": "JSON"
                                        }
                                    }
                                }
                            ]
                        },
                        {
                            "eventName": "sendAlert",
                            "condition": "true",
                            "actions": [
                                {
                                    "lambda": {
                                        "functionArn": "arn:aws:lambda:us-east-1:114234835530:function:CDK-SAP-Lab-OData-Function",
                                        "payload": {
                                            "contentExpression": "'{\n    \"d\": {\n        \"Equipment\": \"${$input.trackerInput.Equipment}\",\n        \"FunctLoc\": \"${$input.trackerInput.FunctLoc}\",\n        \"ShortText\": \"Temperature Alarm[TempInRange.sendAlert]\",\n        \"LongText\": \"Temperature Alarm in ${$input.trackerInput.Type} Motor\"\n    }\n}'",
                                            "type": "JSON"
                                        }
                                    }
                                }
                            ]
                        }
                    ]
                },
                "onExit": {
                    "events": []
                }
            },
            {
                "stateName": "UnderTemp",
                "onInput": {
                    "events": [],
                    "transitionEvents": [
                        {
                            "eventName": "underTempTooLong",
                            "condition": "timeout(\"loTempDur\")",
                            "actions": [],
                            "nextState": "UnderTempAlarm"
                        },
                        {
                            "eventName": "tempAboveMin",
                            "condition": "convert(Decimal,$input.trackerInput.temperature_degC_mean) > convert(Decimal,$input.trackerInput.minTemp_degC)",
                            "actions": [],
                            "nextState": "TempInRange"
                        }
                    ]
                },
                "onEnter": {
                    "events": [
                        {
                            "eventName": "startTimer",
                            "condition": "true",
                            "actions": [
                                {
                                    "setTimer": {
                                        "timerName": "loTempDur",
                                        "seconds": 300,
                                        "durationExpression": null
                                    }
                                }
                            ]
                        }
                    ]
                },
                "onExit": {
                    "events": [
                        {
                            "eventName": "deleteTimer",
                            "condition": null,
                            "actions": [
                                {
                                    "clearTimer": {
                                        "timerName": "loTempDur"
                                    }
                                }
                            ]
                        }
                    ]
                }
            },
            {
                "stateName": "OverTempAlarm",
                "onInput": {
                    "events": [],
                    "transitionEvents": [
                        {
                            "eventName": "tempBelowMax",
                            "condition": "convert(Decimal,$input.trackerInput.temperature_degC_mean) < convert(Decimal,$input.trackerInput.maxTemp_degC)",
                            "actions": [],
                            "nextState": "TempInRange"
                        }
                    ]
                },
                "onEnter": {
                    "events": [
                        {
                            "eventName": "sendAlert",
                            "condition": "true",
                            "actions": [
                                {
                                    "lambda": {
                                        "functionArn": "arn:aws:lambda:us-east-1:114234835530:function:CDK-SAP-Lab-OData-Function",
                                        "payload": {
                                            "contentExpression": "'{\n    \"d\": {\n        \"Equipment\": \"${$input.trackerInput.Equipment}\",\n        \"FunctLoc\": \"${$input.trackerInput.FunctLoc}\",\n        \"ShortText\": \"Temperature Alarm[OverTempAlarm.sendAlert]\",\n        \"LongText\": \"Temperature Alarm in ${$input.trackerInput.Type} Motor\"\n    }\n}'",
                                            "type": "JSON"
                                        }
                                    }
                                }
                            ]
                        }
                    ]
                },
                "onExit": {
                    "events": []
                }
            },
            {
                "stateName": "UnderTempAlarm",
                "onInput": {
                    "events": [],
                    "transitionEvents": [
                        {
                            "eventName": "tempAboveMin",
                            "condition": "convert(Decimal,$input.trackerInput.temperature_degC_mean) > convert(Decimal,$input.trackerInput.minTemp_degC)",
                            "actions": [],
                            "nextState": "TempInRange"
                        }
                    ]
                },
                "onEnter": {
                    "events": [
                        {
                            "eventName": "sendAlert",
                            "condition": "true",
                            "actions": [
                                {
                                    "lambda": {
                                        "functionArn": "arn:aws:lambda:us-east-1:114234835530:function:CDK-SAP-Lab-OData-Function",
                                        "payload": {
                                            "contentExpression": "'{\n    \"d\": {\n        \"Equipment\": \"${$input.trackerInput.Equipment}\",\n        \"FunctLoc\": \"${$input.trackerInput.FunctLoc}\",\n        \"ShortText\": \"Temperature Alarm[UnderTempAlarm.sendAlert]\",\n        \"LongText\": \"Temperature Alarm in ${$input.trackerInput.Type} Motor\"\n    }\n}'",
                                            "type": "JSON"
                                        }
                                    }
                                }
                            ]
                        }
                    ]
                },
                "onExit": {
                    "events": []
                }
            }
        ],
        "initialStateName": "TempInRange"
    },
    "detectorModelDescription": "Detect temperature in a given range.",
    "detectorModelName": "trackerEventDetectorModel",
    "evaluationMethod": "BATCH",
    "key": "thingname",
    "roleArn": "arn:aws:iam::114234835530:role/trackerEventDetectorRole"
}

  1. From the IoT Events Console, create a new Detector Model (hamburger menu/Detector models/Create detector model).

  2. Click ‘Import detector model’ and upload the model JSON (trackerEventDetectorModel.json).

Preparation menu

  1. Click Publish.

Preparation menu

  1. Click Save and Publish.

Preparation menu

Step 17: Testing the anomaly

  • The simulator uses the temperature_min/temperature_max variables you defined in gen.py

  • See the minimum temperature and maximum temperature in your Dynamo DB table maintained.

Preparation menu

  • On the AWS IoT Analytics console landing page, Click Datasets->Click run now in actions to validate the payload that is sent to IoT Events and Amazon S3 for storage.

Preparation menu

  • Next, from the IoT Events Console. Click the hamburger menu and click the Event Detector Model –> Click your Detector Model –> Click the key value in Detector section(IoT Inputs) –>Validate the state and temperature value. Here you should the values within Dynamo DB temperature range.

Preparation menu

  • Modify the temperature values which is outside the range of the temperature sent by the simulator payload. From min 12 and max 14 to any desired values.

Preparation menu

  • Go back to IoT Events Console. Click the hamburger menu and click the Event Detector Model –> Click your Detector Model –> Click the key value in Detector section(IoT Inputs) –>Validate the state and temperature value. Here you should see overtemp value based on the above screen shot values in Dynamo DB.

Preparation menu

  • Event Detector will see if the state of overtemp based on the temperature readings from the simulator. If the anomaly continues for > 5 minutes an alarm should be triggered to create a service notification in SAP and sent and SNS notification to the SNS subscriber list.

Preparation menu

  • Validate the service notification in SAP. Go to SAP Transaction IW23

    • Input the SAP Service Maintenance Notification generated. Click enter and verify the entries.

    Preparation menu

Congratulations, you have completed the integration between SAP and AWS AWS IoT services to enable Preventive Maintenance with AWS CDK.