Developing Your First Greengrass Publish Component on Raspberry Pi
Tags: greengrass, aws, iot
Published: 2023-07-20 14:13:19

In the [previous blog post](https://dev.to/iotbuilders/aws-iot-greengrass-components-deployment-with-gdk-using-github-actions-245m), we delved into the world of AWS IoT Greengrass V2, focusing on the usage of the Greengrass Development Kit (GDK) and how it can be automated with GitHub Actions. Today, we're going to take it a step further. We'll walk through the process of developing your first AWS IoT Greengrass Publish component on a Raspberry Pi.

## Step 1: Setting Up Your Environment

Before we start, ensure that you have your Raspberry Pi is set up by using the [Fleet Provisioning mehtod](https://dev.to/iotbuilders/fleet-provisioning-for-embedded-linux-devices-with-aws-iot-greengrass-4h8b) as we will be using now those GitHub Actions and the project we created in our previous blog post to deploy our component. In scenarios that you are working with a different OS, you would need to follow the instruction on [installing AWS IoT Greengrass](https://docs.aws.amazon.com/greengrass/v2/developerguide/quick-installation.html) as well.


## Step 2: Designing the Message Publisher Component

The first step in creating our messaging system is to create the message publisher component. This component will be responsible for sending data, such as sensor readings or application logs, to a specified topic. 

In the AWS IoT Greengrass, components are defined by a recipe, which is a JSON or YAML file that specifies the component's metadata, lifecycle, configuration, and dependencies. For our message publisher component, we'll need to define a recipe that includes the necessary AWS IoT Greengrass component to publish messages to a topic.

Here's an example of what the recipe might look like:


```
---
RecipeFormatVersion: "2020-01-25"
ComponentName: "{COMPONENT_NAME}"
ComponentVersion: "{COMPONENT_VERSION}"
ComponentDescription: "A component that publishes temperature data to AWS IoT Core"
ComponentPublisher: "{COMPONENT_AUTHOR}"
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.mqttproxy:
        'com.example.pub:mqttproxy:1':
          policyDescription: Allows access to publish the temperature to topic.
          operations:
            - aws.greengrass#PublishToTopic
          resources:
            - 'CPU/info'
Manifests:
  - Platform:
      os: all
    Artifacts:
      - URI: "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/com.example.pub.zip"
        Unarchive: ZIP
    Lifecycle:
      Run: "python3 -u {artifacts:decompressedPath}/com.example.pub/main.py"
```

In this recipe, we're creating a component with the name `com.example.pub`. This component is different from our previous examples due to the inclusion of an `accessControl:` configuration. This configuration allows the component to publish messages to a specific MQTT topic.

In our case, the `resource` is set to `CPU/info`. This setting means that our component has permission to publish only to the `CPU/info` MQTT topic. 

If you need the component to publish to multiple topics, you can extend the list of `resources` with additional topic names. Alternatively, if you want the component to have permission to publish to any topic, you can replace `CPU/info` with `*`. This wildcard character represents all possible topics, granting the component full publishing access. 


## Step 3: Implementing the Message Publisher Component

With the component designed, we can now move on to implementing the message publisher component. This involves writing the `main.py` script that we referenced in the component recipe.

The `main.py` script will use the AWS SDK for Python which uses `awsiot.greengrasscoreipc.clientv2` to interact with Greengrass IPC in order to publish messages to a specified AWS IoT topic. Here's an example of what the script would look like:


```
import os
import time
import json
import awsiot.greengrasscoreipc.clientv2 as clientV2

TOPIC="CPU/info"

def get_cpu_temp():
    temp_file = open("/sys/class/thermal/thermal_zone0/temp")
    cpu_temp = temp_file.read()
    temp_file.close()
    return float(cpu_temp)/1000

def main():
    # Create an IPC client.
    ipc_client = clientV2.GreengrassCoreIPCClientV2()

    while True:
        cpu_temp = get_cpu_temp()
        print("CPU temperature: {:.2f} C".format(cpu_temp))

        # Create a payload.
        payload = json.dumps({"temperature": cpu_temp})

        # Publish the payload to AWS IoT Core.
        resp = ipc_client.publish_to_iot_core(topic_name=TOPIC, qos="1", payload=payload)

        time.sleep(1)  # sleep for 1 second

    ipc_client.close()

if __name__ == "__main__":
    main()
```


In this script, we're creating a loop that continuously publishes a message to the `CPU/info` topic. The message contains a json payload with `temperature` value, which could be then extended further in a real-world application.

## Step 4: Deploying the Message Publisher Component

For deploying the new component to the device we should extend the `deployment.json.template:`

```
{
    "targetArn": "arn:aws:iot:$AWS_REGION:$AWS_ACCOUNT_ID:thinggroup/$THING_GROUP",
    "deploymentName": "Main deployment",
    "components": {
        "com.example.hello": {
            "componentVersion": "LATEST",
            "runWith": {}
        },
        "com.example.world": {
            "componentVersion": "LATEST",
            "runWith": {}
        },
        "com.example.pub": {
            "componentVersion": "LATEST",
            "runWith": {}
        }
    },
    "deploymentPolicies": {
        "failureHandlingPolicy": "ROLLBACK",
        "componentUpdatePolicy": {
            "timeoutInSeconds": 60,
            "action": "NOTIFY_COMPONENTS"
        },
        "configurationValidationPolicy": {
            "timeoutInSeconds": 60
        }
    },
    "iotJobConfiguration": {}
}
```

If you've followed our previous blog post, you should have your GitHub Actions set up for your repository. This setup allows for automatic deployment of your components. 

When you create a new component and commit it to your repository, make sure to add it to the `deployment.json.template`. This step is crucial as it ensures your component is included in the deployment process.

After committing the new component, the GitHub Actions workflow will trigger, resulting in the automatic deployment of your component to the targeted device, in this case, a Raspberry Pi.

Once deployed, the component will start running on the Raspberry Pi. It will begin publishing messages to the specified AWS IoT topic. 

To verify that your component is functioning correctly, you can subscribe to the topic in the AWS IoT Core console. Here, you'll be able to observe the incoming messages, confirming that your component is publishing as expected.

## Conclusion

In this blog post, we've walked through the process of developing a Greengrass Publish component on a Raspberry Pi. This is a great way to use the messaging system for your IoT applications, and I hope it helps you on your journey with AWS IoT Greengrass.

For reference, please refer to [this](https://github.com/aws-iot-builder-tools/greengrass-continuous-deployments) GitHub repo.
Stay tuned for more posts on advanced Greengrass component development and other IoT topics. Happy coding!

If you have any feedback about this post, or you would like to see more related content, please reach out to me here, or on [Twitter](https://twitter.com/nenadilic84) or [LinkedIn](https://www.linkedin.com/in/nenadilic84/).