IoT/IIoT¶
The G3 module embedded software image includes components enabling its use in
Internet of Things and/or Industrial Internet of Things applications. these
components are controlled by the standard chkconfig
command and are disabled
by default.
Note
In general, IoT/IIoT applications will require Trusted Platform Module (TPM) hardware to be installed in the G3 module. This is standard on the G3MTBR which is intended for IoT gateway applications. All other modules support the addition of a TPM on an application specific daughter card via the I2C bus.
The following sections discuss enabling and configuring the IoT/IIoT related sofware components.
TPM¶
Getting Started with the Trusted Platform Module (TPM)¶
Note
The following instructions require the use of your favorite terminal based text editor. If you do not have a preferred text editor, vim and Gnu nano come pre-installed. If you are not already familiar with vim, we recommend that you stick with Gnu nano. You can find a cheat sheet at the Gnu nano website.
To start, run the following commands in your bash shell while logged into the target as root…
1# Set the DTB to one that supports TPM2 and reboot.
2fw_setenv mender_dtb_name stm32mp1-g3mtbr-none.dtb
3reboot
4
5# Add TPM2 PKCS11 Store environment variable to .bashrc.
6# This enables using the TPM2 in your current shell environment.
7echo "export TPM2_PKCS11_STORE=/data/opt/tpm2-pkcs11/" >> ~/.bashrc
8source ~/.bashrc
Configure OpenSSL to use the Trusted Platform Module (TPM) by adding the settings below to
/etc/ssl/openssl.cnf
beneathHOME = .
on line 13 and before# Extra OBJECT IDENTIFIER info
.
1# Add support for the TPM2
2openssl_conf = openssl_init
3[openssl_init]
4engines=engine_section
5
6[engine_section]
7pkcs11 = pkcs11_section
8
9[pkcs11_section]
10engine_id = pkcs11
11dynamic_path = /usr/lib/engines-1.1/pkcs11.so
12MODULE_PATH = /usr/lib/libtpm2_pkcs11.so.0
13init = 0
Connecting to AWS Greengrass V1¶
Add TPM2_PKCS11_STORE
to the Greengrass init.d service so the file looks like below.
The TPM2 will not work correctly with Greengrass on boot unless the environment
variable TPM2_PKCS_STORE
is defined and configured beforehand:
Error
Nick - What is the path to the GG init script?
1#!/bin/sh
2# levels start kill
3#===================================
4# chkconfig: 45 80 20
5# description: AWS IoT Greengrass
6
7export TPM2_PKCS11_STORE=/data/opt/tpm2-pkcs11/
8GG_LAUNCHER="$(find /data/greengrass -type f -name greengrassd)"
9
10case "${1}" in
11 start | stop | restart)
12 ${GG_LAUNCHER} ${1}
13 ;;
14 *)
15 echo "Usage: $0 {start|stop|restart}"
16 exit 1
17 ;;
18esac
Run:
1/usr/bin/tpm2-gg-setup.sh
Copy the generated device certificate to your host computer:
1scp root@<ip-address>:/data/greengrass/certs/deviceCert.csr .
Important
You will need to substitute the IP address of your target in the command above.
Upload your device certificate and associate it with your Greengrass Core policy:
On the left, under AWS IOT, select
Secure->Certificates
then on the right selectAdd certificate->Create certificate
.Select “Create certificate with certificate signing request (CSR)” then upload your deviceCert.csr file from the previous step and select
Create
.If successful, a pop-up will appear prompting you to download the results. Download both the
Device certificate
and the RSAAmazon trust services endpoint
, and copy both of them to/data/greengrass/certs
on your target.Activate the new certificate by checking its box on the left and selecting
Actions->Activate
.Select your newly created certificate and select
Attach policies
then select your Greengrass core’s associated policy and selectAttach policies
Edit the Greengrass configuration file,
/data/greengrass/config/config.json
, so the following fields match:
1"runtime" : {
2 "cgroup" : {
3 "useSystemd" : "no"
4 },
5},
6"crypto": {
7 "caPath" : "file:///data/greengrass/certs/root.ca.pem",
8 "PKCS11": {
9 "OpenSSLEngine": "/usr/lib/engines-1.1/pkcs11.so",
10 "P11Provider": "/usr/lib/libtpm2_pkcs11.so.0",
11 "slotLabel": "greengrass",
12 "slotUserPin": "123456"
13 },
14 "principals": {
15 "SecretsManager" : {
16 "privateKeyPath" : "file:///data/greengrass/certs/hash-setup.private.key"
17 },
18 "IoTCertificate" : {
19 "privateKeyPath" : "file:///data/greengrass/certs/hash-setup.private.key",
20 "certificatePath" : "file:///data/greengrass/certs/hash-setup.cert.pem"
21 },
22 "MQTTServerCertificate" : {
23 "privateKeyPath" : "file:///data/greengrass/certs/hash-setup.private.key",
24 "certificatePath" : "file:///data/greengrass/certs/hash-setup.cert.pem"
25 }
26 }
27}
Restart Greengrass and test local MQTT broker to AWS Cloud connection
AWS Greengrass¶
Warning
A credit card is necessary to sign up for AWS, even though it’s free to use if you stay under the AWS Free Tier limits.
The following documentation is meant as a suppliment to the official AWS Greengrass V1 documentation. We recommend first reviewing Amazon’s documentation to get the most value out of our documentation.
Interacting with the AWS Greengrass Daemon¶
You can perform the following actions in your bash shell on the target:
Start/Stop/Restart:
1/etc/init.d/greengrass start|stop|restart
Greengrass Logs:
1tail -f /data/greengrass/ggc/var/log/system/runtime.log
Greengrass Lambda Logs:
1tail -f /data/greengrass/ggc/var/log/*/*/*.log
Getting Started with the AWS Greengrass Daemon¶
Create the Greengrass Group and Core. Follow this procedure from AWS EXACTLY! Adjust the Group and Core names for your use. Stop when it instructs you to install Greengrass software (step 11) because the Greengrass software is already installed and ready to be configured.
Error
Nick - step 11? there is no step 11 here… is this in the referenced doc? If yes, there should be a hyperlink to it.
Configure Greengrass Group:
When running AWS IoT Greengrass initially without Docker, all Lambda functions must run without containerization. In this step, set the default containerization for the group to
No container
. Do this before you deploy the group for the first time.In the AWS IoT console, choose Greengrass, and then choose
Groups
.Choose the group whose settings you want to change.
Choose
Settings
.Under
Lambda runtime environment
, chooseNo container
.Choose
Update default Lambda execution configuration
. Review the message in the confirmation window, and then chooseContinue
.
Download your AWS core security resources and copy them to your gateway. Replace
hash-setup
with the file you downloaded in step 1:
1scp hash-setup.tar.gz root@<ip-address>:/data/greengrass
Important
You will need to substitute the IP address of your target in the command above.
Untar your AWS core security resources (from step 3) to
/data/greengrass
:
1tar zxvf /data/greengrass/hash-setup.tar.gz -C /data/greengrass/
Edit the Greengrass config file,
/data/greengrass/config/config.json
, so the following fields match:
1"runtime" : {
2 "cgroup" : {
3 "useSystemd" : "no"
4 }
5},
6"crypto" : {
7 "principals" : {
8 "SecretsManager" : {
9 "privateKeyPath" : "file:///data/greengrass/certs/hash-setup.private.key"
10 },
11 "IoTCertificate" : {
12 "privateKeyPath" : "file:///data/greengrass/certs/hash-setup.private.key",
13 "certificatePath" : "file:///data/greengrass/certs/hash-setup.cert.pem"
14 }
15 },
16 "caPath" : "file:///data/greengrass/certs/root.ca.pem"
17}
Create a lambda function in Greengrass by following these instructions. Step 10 is optional since aliases are not required.
Error
Nick - step 10? there is no step 10 here… is this in the referenced doc? If yes, there should be a hyperlink to it.
When creating your Python lambda, make sure to choose the python3.8 runtime
Under Basic settings, your Handler name must match the convention:
filname.name_of_function_handle
Configure your newly added lambda function using these instructions, stopping at step 15.
Error
Nick - step 15? there is no step 15 here… is this in the referenced doc? If yes, there should be a hyperlink to it.
In step 7, you don’t have to set the timeout to 25, but make sure you remember to change the Lambda Lifecycle to
Make this function long-lived and keep it running indefinitely
Error
Nick - step 7? we’re in step 7 here… is this in the referenced doc? If yes, there should be a hyperlink to it.
Deploy your lambda using these instructions.
Verify that the lambda is running on the core device using these instructions.
Connecting Greengrass to a MQTT Broker¶
By default, the G3 module platform runs mosquitto for its local MQTT broker, but other MQTT brokers exist as well. Below are basic instructions to connect the local mosquitto broker to AWS Greengrass in order to forward MQTT messages to and from the AWS Cloud:
Ensure that mosquitto and Greengrass are running by checking the output of the following commands:
1/etc/init.d/mosquitto status
2ps -elf | grep greengrass
Using the skills you learned in Getting Started, copy the code below and create a new lambda in a file named
MqttClient.py
. Under “Basic settings”, your Handler name will beMqttClient.function_handler
:
1import logging
2import os
3import json
4from threading import Timer
5
6import greengrasssdk
7import paho.mqtt.client as mqtt
8
9# Creating a greengrass core sdk client
10iot_data = greengrasssdk.client('iot-data')
11
12logger = logging.getLogger(__name__)
13logger.setLevel(logging.INFO)
14streamHandler = logging.StreamHandler()
15formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
16streamHandler.setFormatter(formatter)
17logger.addHandler(streamHandler)
18
19GROUP_ID = None
20THING_NAME = None
21THING_ARN = None
22HOST = 'localhost'
23PORT = 1883
24USERNAME = None
25PASSWORD = None
26MQTT_SUB = "#"
27TIMER_INTERVAL = 1
28
29if 'USERNAME' in os.environ:
30 USERNAME = os.environ['USERNAME']
31
32if 'PASSWORD' in os.environ:
33 PASSWORD = os.environ['PASSWORD']
34
35# The callback for when the client receives a CONNACK response from the server.
36def on_connect(client, userdata, flags, rc):
37 logger.info("Connected with result code " + str(rc))
38
39 # Subscribing in on_connect() means that if we lose the connection and
40 # reconnect then subscriptions will be renewed.
41 client.subscribe(MQTT_SUB)
42
43# The callback for when a PUBLISH message is received from the server.
44def on_message(client, userdata, msg):
45 logger.info('on_message received')
46 topic = msg.topic
47
48 # Publish the message to the MQTT server
49 logger.info('Publishing message to |GG| from broker on topic [' + topic + ']')
50
51 payload = msg.payload
52 try:
53 json_payload = json.dumps(str(payload.decode("utf-8")))
54 except UnicodeDecodeError:
55 payload = payload.hex()
56
57 try:
58 iot_data.publish(topic=topic, payload=payload)
59 except Exception as error:
60 logger.error('An exception occurred: {}'.format(error))
61
62
63mqtt_client = mqtt.Client()
64mqtt_client.on_connect = on_connect
65mqtt_client.on_message = on_message
66
67mqtt_client.username_pw_set(USERNAME, PASSWORD)
68
69def greengrass_mqtt_client_loop():
70 error = None
71
72 try:
73 mqtt_client.connect(HOST, PORT, 60)
74 # Blocking call that processes network traffic, dispatches callbacks
75 # and handles reconnecting.
76 mqtt_client.loop_forever()
77 logger.info('Should never get Here')
78 except ConnectionRefusedError as e:
79 # Connection refused, try connecting again in 5 seconds
80 error = ('Connection to the MQTT server failed [' + str(e) + '], '
81 'make sure it is running and the settings are correct')
82 except Exception as e:
83 # Something else went wrong
84 error = 'Something went wrong [' + str(e) + ']'
85
86 # If we get here we'll start log the error, if any, and loop again
87 if error is not None: logger.error(error)
88 logger.error('Reconnecting')
89 Timer(TIMER_INTERVAL, greengrass_mqtt_client_loop).start()
90
91# Asynchronously schedule this function to run in TIMER_INTERVAL seconds.
92# We don't call the function immediately in case the MQTT configuration
93# is incorrect.
94Timer(TIMER_INTERVAL, greengrass_mqtt_client_loop).start()
95
96# This is invoked when a message is received from |GG|
97def function_handler(event, context):
98 try:
99 inbound_topic = context.client_context.custom['subject']
100
101 # Publish the message to the MQTT server
102 logger.info('Publishing message to broker from |GG| on topic [' +
103 inbound_topic + ']')
104
105 mqtt_client.publish(inbound_topic, json.dumps(event))
106 except Exception as error:
107 logger.error('An exception occurred: {}'.format(error))
108
109 return
Add MQTT topic subscriptions to lambda function(s) to transport MQTT data to and from the local MQTT broker and the AWS Cloud and vice versa. This step and the following steps use the MQTT topics of
foo
andbar
as an example, as seen below:Source
Target
Topic
MqttLambda
IoT Cloud
foo
IoT Cloud
MqttLambda
bar
Deploy the lambda to the Greengrass Core.
Verify MQTT traffic from local broker to AWS Cloud:
1mosquitto_pub -h <ip_address> -t foo -m "from local broker"
Important
You will need to substitute the IP address of your target in the command above.
Now check the AWS IoT Test Console to check if the message on topic
foo
was received.Verify MQTT traffic from AWS Cloud to local broker:
1mosquitto_sub -h <ip_address> -v -t bar
Important
You will need to substitute the IP address of your target in the command above.