Raspberry Pi on the IoT

Creating the Core

The first step is to create a core definition. (Please see the "Definitions" box.) The following command generates the JSON-like syntax that passes the core as a combination of the ARN of the certificate and the ARN of the thing.


A pattern that recurs in the Greengrass data model is definitions and definition versions. Commands that create something always follow the form create-<XXX>-definition. You can create an initial version in JSON format with the --initial-version option. If you change the definition, you need to create a new version of the component <XXX> with create-<XXX>-definition-version. If this is contained in another component (and they are all in group-definition), you need to create a new version of the surrounding object, up to the highest hierarchy level.

The subcomponent is always transferred in the form of its version (ARN or unique ID). If you query a specific component with get-<XXX>-definition, the response contains a LatestVersion field with the ID of the last version created. For example, if the ARN of a core definition is

arn:aws:greengrass:eu-central-1:566776501337:/greengrass/definition/cores/  37d2b2ac-b3ff-491d-b56d-071fbb9ade51

and the last version has the ID aae9c658-16fa-4c1b-91aa-ef54340552ac, the entire ARN of the last version of the core definition is given as the ARN of the core followed by /versions/<ID>, such as:

aws greengrass create-core-definition --name LM1_GG_Core --initial-version,Cores=[{CertificateArn=arn:aws:iot:eu-central-1:566776501337:cert/6c597228cf5e4da63ee7dc4364f5a282e431a1581014fbd3cd558b86878f4fdc,Id=LM_GG_Core_ID,SyncShadow=False,ThingArn=arn:aws:iot:eu-central-1:566776501337:thing/LM_Core}]'

The Cores=[] allows you to enter multiple cores between the square brackets.

If you want another Rasp Pi with its own certificate to supply data, you just create a new certificate and a new thing and repeat the steps above for the new device to create a new version of the definition with the command:

aws greengrass create-core-definition-version

Other arguments for a core include a unique ID and the Boolean value SyncShadow, which specifies whether you want to create a shadow object. The shadow object is not necessary, so the value is False. Listing 3 shows the return value that AWS sends in response to the command.

Listing 3

Return Core Definition


Because the resource belongs to the group and the function, the next step is to create a resource for access to /dev/gpiomem:

aws greengrass create-resource-definition --initial-version file://resource.json

The most time-consuming task is the resource definition (Listing 4). The function definition then follows, which, from Greengrass's point of view, is the combination of a Lambda ARN, the assignment of the resource just defined, and an ID. Before it can begin, however, you first have to create the AWS Lambda function in the Lambda area.

Listing 4

JSON Code for the Resource


Lambada with Lambda

The trick is now to create and distribute the code that will run on the Raspberry Pi (or Pis) with Amazon's Lambda platform, which is intended for the use of serverless computing on AWS computers. To begin, you set the code for AWS, which various mechanisms call, and the output can then be passed on to the AWS world.

Greengrass now lets you download Lambda functions to a core and run them there. To generate the Lambda function, you first download the AWS IoT Greengrass Core SDK under Software in the IoT console.

After unpacking, the aws_greengrass_core_sdk/examples/HelloWorld/greengrassHelloWorld folder contains a sample application and the greengrasssdk folder for Python, which is where the application presented here ends up.

Listing 5 shows the Python code to run on the Greengrass Core. The code assumes that a DHT22 sensor is connected to GPIO pin 4. Before you put the whole thing online, first run a function test with a version of the script that does not use the Greengrass functionality.

Listing 5

Lambda Function for the Core


In this case, the function requires downloading and installing the Adafruit DHT module from the Adafruit GitHub site [9]. Although the Lambda functions are encapsulated, they can use all the modules installed on the Pi. You might be familiar with the code in line 11 that initializes the client, which is reminiscent of the interaction between AWS and the boto3 client, except a slimmed down version is used here.

The Python file and the greengrasssdk folder are now packed into a ZIP file, which you use when creating the Lambda function. Before you generate the Lambda function, first define a role again that lets the function use the Lambda service:

aws iam create-role --role-name LM-Role --assume-role-policy-document file://lmrolle.json--path /service-role/

The JSON file containing the role definition is shown in Listing 6. Next, you create the Lambda function and upload:

Listing 6

JSON Role Definition


aws lambda create-function --role arn:aws:iam::566776501337:role/service-role/LM-Role--function-name LM-FunctionOnCore --runtime python2.7 --handler greengrassTemp.function_handler --zip-file fileb://gg.zip

The ARN that matches the role is provided by the response that AWS returns when it creates the role. The handler option is used in Lambda functions to react to a trigger event (during which data is transferred). Because the function is not event driven, but measures and publishes the temperature and then waits a minute and repeats the action, the body can be empty – but it must exist. The naming convention is the name of Python script without the <.name of the handler method> extension.

If you want to use Greengrass to trigger actions on the core after subscribing to an MQTT queue, you need to call precisely this method.

The AWS Lambda service manages the code in versions. Users cannot work without them. If the code changes, select Save | Actions | Publish new version. The code will not work before you do this. The same applies to the CLI:

aws lambda publish-version --function-name LM-FunctionOnCore

When assigning the Lambda to a Greengrass group, you specify either the version or an alias. If the code changes later, you then publish a new version and change the alias so that it points to the new version. Greengrass also distributes new code in this way. The automatically generated $Latest alias with which more experienced Lambda developers might be familiar will not work here.

The following command creates the alias with a reference to the new first version:

aws lambda create-alias --function-name LM-FunctionOnCore --name LMAlias --function-version 1

Again, AWS returns a JSON block; this time, the AliasArn field is important for the next call.

AWS uses one of several function definitions to assign Lambdas to a Greengrass group. On creating the function definition, you submit an initial version referencing the Lambda version that has just been created:

aws greengrass create-function-definition --name LM-LambdaFunctionDefinition --initial-version file://function.json

Listing 7 shows the content of the corresponding function.json file.

Listing 7



Granting read and write access to the resource is important. The argument for FunctionArn is the ARN of the generated alias. If something changes in the Lambda function, you need to publish a new version within the function. The alias to which the ARN refers here now points to this new version.


The missing component of the group is now the subscription, which regulates which members of the Greengrass group are allowed to send anything at all – and to whom. In the example here, I want the Lambda function on the device to be able to send to the IoT Core. The code uses iot/temperature as the theme (Listing 5, line 24), which could be inserted as a filter. In the first step, however, it could be a source of error, because a single typo is all it takes to filter out more than you want. To create the subscription, use:

aws greengrass create-subscription-definition --name GG-Subscription --initial-version 'Subscriptions=[{Id=GG-Abo-Id,Target=cloud,Subject=#,Source=arn:aws:lambda:eu-central-1:566776501337:function:LM-FunctionOnCore:LMAlias}]'

Finally, the last link in the chain that glues everything together is still missing: the Greengrass group itself. As with the core definition, the concept of versioning applies. The aws greengrass create-group command also has an --initialVersion option. The command that merges the previously created objects into a Greengrass group is:

aws greengrass create-group --name LM1TestGroup --initial-version file://groupsource.json

As expected, a JSON file lists all version ARNs of all components created (Listing 8). This step concludes the preparatory work. A click on the web console opens the group onscreen (Figure 1).

Listing 8



Figure 1: The Greengrass group created on the CLI appears in the web interface.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Programming Snapshot – Alexa

    Asking Alexa only for built-in functions like the weather report gets old quickly, and add-on skills from the skills store only go so far. With a few lines of code, Mike teaches this digital pet some new tricks.

  • WiFi Thermo-Hygrometer

    A WiFi sensor monitors indoor humidity and temperature and a Node-RED dashboard reports the results, helping you to maintain a pleasant environment.

  • Java 8

    In mid-March, Oracle released the eighth version of Java. In addition to small tweaks, the long-awaited release extends the core language, adding elements of functional programming – the first significant development since Java 5.

  • IoT with RabbitMQ

    Connect multiple protocols and servers together on your IoT projects.

  • JavaScript Alternatives

    JavaScript is the stuff of which many interactive web clients is made, but it comes with a fair amount of historical ballast. The creators of four alternative scripting languages seek to ditch the ballast.

comments powered by Disqus

Direct Download

Read full article as PDF:

Price $2.95