Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: Deploy Edge AI models scalably using Edge Impulse and AWS IoT Greengrass

draft: true
cascade:
draft: true

minutes_to_complete: 120

who_is_this_for: This learning path is for Edge AI and embedded engineers who need to scalably deploy crafted ML for the Edge to thousands of edge devices.

learning_objectives:
- Basic understanding of Edge Impulses Edge ML Solution
- Basic hardware setup for Edge AI ML development with Edge Impulse
- Install AWS IoT Greengrass onto the edge device
- Configure the edge device with the custom integration between Edge Implulse and AWS IoT Greengrass

prerequisites:
- An [Edge Impulse Studio](https://studio.edgeimpulse.com/signup) account (workshop will walk through this).
- An AWS Account (if not being hosted by AWS Workshop Studio)

author: Doug Anson

### Tags
skilllevels: Introductory
cloud_service_providers: AWS
subjects: ML
armips:
- Cortex-M

tools_software_languages:
- Edge Impulse
- Edge AI

operatingsystems:
- Linux

### FIXED, DO NOT MODIFY
# ================================================================================
further_reading:
- resource:
title: Edge Impulse for beginners
link: https://docs.edgeimpulse.com/docs/readme/for-beginners
type: doc

weight: 1 # _index.md always has weight of 1 to order correctly
layout: "learningpathall" # All files under learning paths have this same wrapper
learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content.
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# ================================================================================
# FIXED, DO NOT MODIFY THIS FILE
# ================================================================================
weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation.
title: "Next Steps" # Always the same, html page title.
layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing.
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: 9. AWS Account Cleanup (Optional)
weight: 11

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Cleanup

**AWS workshop attendees**: The temporary AWS account given to you will automatically be deleted. No other action is necessary at this time.

**Personal AWS Accounts**: To minimize costs of your AWS resources, you can go to the AWS IoTCore Greengrass deployments page and revise your deployment. In the revision, remove the Edge Impulse custom component from the deployment and redeploy. This will shutdown the "runner" service on your edge device and will no longer send messages into IoTCore when inference results are present. Additionally, if using the EC2 edge device in the workshop, you will want to navigate to the EC2 dashboard, select your EC2 instance you created, and then set the instance state to "terminated" via the "Instance state" button/dropdown. You can also cancel your Greengrass deployments and delete both your Greengrass core device as well as your IoT Thing for your core device (all accomplished via the IoTCore dashboard).
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: 6. Custom Component Deployment
weight: 8

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Greengrass Component Deployment

In this section, we will create an AWS IoT Greengrass deployment that will download, prepare, install, and run our Edge Impulse "Runner" service on our edge device. When the "Runner" service starts, it will connect back to our Edge Impulse environment via the API key we inserted into AWS Secret Manager and will download and start to run our deployed ML model we created in Edge Impulse Studio! Let's get this started!

### 0. (Non-Camera Edge Devices Only): Additional Custom Component

If your edge device does not contain a camera (i.e. EC2 edge device), you will need to deploy an additional custom component. Please follow [these steps](./NonCameraCustomComponent.md) to get the additional component created. You will be selecting this component in addition to the custom component we created for the Edge Impulse "Runner" service.

### 1. Deploy the custom component to a selected Greengrass edge device or group of edge devices.

Almost done! We can now go back to the AWS Console -> IoT Core -> Greengrass -> Deployments page and select a deployment (or create a new one!) to deploy our component down to as selected edge device or group of gateways as needed:

Deploy to a group of devices:

![GGDeploy](./images/GG_Create_Deployment.png)

Deploy to a specific device (i.e. my EC2 Edge Device):

![GGDeploy](./images/GG_Create_Deployment_2.png)

In either case above we now press "Next" and select our newly created custom component:

![GGDeploy](./images/GG_Create_Deployment_3.png)

>**_NOTE:_**
>If you are using an edge device which does not have a camera, you will also need to select the "EdgeImpulseRunnerRuntimeInstallerComponent" custom component that you created above ("Non-Camera Edge Device Custom Component"):
>![GGDeploy](./images/GG_Create_Deployment_3a.png)

Press "Next" again, then select our custom component and press "Configure Component" to configure the "Runner" component:

![GGDeploy](./images/GG_Create_Deployment_4.png)

>**_NOTE:_**
>If you also have the Non-Camera component, it does NOT need to be configured... only the "EdgeImpulseLinuxRunnerServiceComponent" should be configured

#### Customizing a specific Deployment

We now see that our custom component we registered has a default configuration. We can, however, customize it specifically for our specific hardware configuration (i.e. to a specific device or group of similar devices...).

First lets recall the JSON we saved off when we configured our hardware. Lets customize our Greengrass deployment by clearing, copying, and pasting that JSON into the "Configuration to merge" window... then press "Confirm":

![GGDeploy](./images/GG_Create_Deployment_5.png)

You'll then see the previous page and continue pressing "Next" until you get to the "Deploy" page:

![GGDeploy](./images/GG_Create_Deployment_6.png)

> **_NOTE:_**
>When performing the deployment, its quite common to, when selecting one of our newly created custom components, to then "Customize" that component by selecting it for "Customization" and entering a new JSON structure (same structure as what's found in the component's associated YAML file for the default configuration) that can be adjusted for a specific deployment (i.e. perhaps your want to change the DeviceName for this particular deployment or specify "gst_args" for a specific edge device(s) camera, etc...). This highlights the power and utility of the component and its deployment mechanism in AWS IoT Greengrass.


> **_NOTE:_**
> The component deployment may take awhile depending on network speed/etc... the reason for this is that all of the required prerequisites to run the Edge Impulse "Runner" service have to be downloaded, setup, and installed.
>
> Back on the edge device via SSH, you can "tail" two different files to watch the progress of the installation/setup as well as the component operation (as root):
>
> % sudo su -
> # tail -f /greengrass/v2/logs/EdgeImpulseLinuxRunnerServiceComponent.log
> # tail -f /tmp/ei*log
>
> The first "tail" will log all of the installation activity during the component setup. The second "tail" (wildcarded) will be the log file of the "running" component. You can actually watch the Edge Impulse "Runner" output in that file if you wish.
>
> Both files are critical for debugging any potential issues with the deployment and/or component configuration.

Now that our custom component has been deployed, the component will install Edge Impulse's "Runner" runtime that will then, in turn, pull down and invoke our Edge Impulse's current Impulse (i.e. model...). We will next check that our model is running on our edge device!
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
title: 5. Edge Impulse Custom Component Creation
weight: 7

### FIXED, DO NOT MODIFY
layout: learningpathall
---

## Edge Impulse "Runner" Service Custom Component

We will utilize a Greengrass "Custom Component" to create and deploy the Edge Impulse runner service (the service that will run our Edge Impulse model on the edge device) including the required additional prerequisites (NodeJS install, libvips install). AWS IoT Greengrass' custom component feature is ideal to create custom components that can be specialized to prepare, run, and shutdown a given custom service.

Let's get started!

### 1. Clone the repo to acquire the Edge Impulse Component recipes and artifacts

Please clone this [repo](https://github.com/edgeimpulse/aws-greengrass-components) to retrieve the Edge Impulse component recipes (yaml files) and the associated artifacts.

### 2. Upload Edge Impulse Greengrass Component artifacts into AWS S3

First, you need to go to the S3 console in AWS via AWS Console -> S3. From there, you will create an S3 bucket. For sake of example, we name this bucket "MyS3Bucket123".

![CreateS3Bucket](./images/S3_Create_Bucket.png)

Next, the following directory structure needs to be created your new bucket:

./artifacts/EdgeImpulseServiceComponent/1.0.0

Next, navigate to the "1.0.0" directory in your S3 bucket and then press "Upload" to upload the artifacts into the bucket. You need to upload the following files (these will be located in the ./artifacts/EdgeImpulseServiceComponent/1.0.0 from your cloned repo). Please upload all of these files into S3 at the above directory location:

install.sh
run.sh
launch.sh
stop.sh

Your S3 Bucket contents should look like this:

![UploadToS3](./images/S3_Upload_Artifacts.png)

### 3. Customize the component recipe files

Next we need to customize our Greengrass component recipe YAML file to reflect the actual location of our artifacts stored in S3. Please replace ALL occurrences of "YOUR\_S3\_ARTIFACT\_BUCKET" with your S3 bucket name (i.e. "MyS3Bucket123"). Please do this to the "EdgeImpulseLinuxRunnerServiceComponent.yaml" file. Save the file.

Also FYI, we can customize the defaulted configuration of your custom component by editing, within "EdgeImpulseLinuxRunnerServiceComponent.yaml" file, the default configuration JSON. We won't need to do this for this workshop but its an useful option nonetheless.

The default configuration in "EdgeImpulseLinuxRunnerServiceComponent.yaml" contains the following JSON configuration settings for the component:

EdgeImpulseLinuxRunnerServiceComponent.yaml:
{
"node_version": "20.12.1",
"vips_version": "8.12.1",
"device_name": "MyEdgeImpulseDevice",
"launch": "runner",
"sleep_time_sec": 10,
"lock_filename": "/tmp/ei_lockfile_runner",
"gst_args": "__none__",
"eiparams": "--greengrass",
"iotcore_backoff": "5",
"iotcore_qos": "1",
"ei_bindir": "/usr/local/bin",
"ei_sm_secret_id": "EI_API_KEY",
"ei_sm_secret_name": "ei_api_key",
"ei_ggc_user_groups": "video audio input users",
"install_kvssink": "no",
"publish_inference_base64_image": "no",
"enable_cache_to_file": "no",
"ei_poll_sleeptime_ms": 2500,
"ei_local_model_file": "__none__",
"ei_shutdown_behavior": "__none__",
"cache_file_directory": "__none__",
"enable_threshold_limit": "no",
"metrics_sleeptime_ms": 30000,
"default_threshold": 50.0,
"threshold_criteria": "ge",
"enable_cache_to_s3": "no",
"s3_bucket": "__none__",
}

#### Attribute Description

The attributes in each of the above default configurations is outlined below:

* **node\_version**: Version of NodeJS to be installed by the component
* **vips\_version**: Version of the libvips library to be compiled/installed by the component
* **device\_name**: Template for the name of the device in EdgeImpulse... a unique suffix will be added to the name to prevent collisions when deploying to groups of devices
* **launch**: service launch type (typically just leave this as-is)
* **sleep\_time\_sec**: wait loop sleep time (component lifecycle stuff... leave as-is)
* **lock\_filename**: name of lock file for this component (leave as-is)
* **gst\_args**: optional GStreamer args, spaces replaced with ":", for custom video invocations
* **eiparams**: additional parameters for launching the Edge Impulse service (leave as-is)
* **iotcore\_backoff**: number of inferences to "skip" before publication to AWS IoTCore... this is used to control publication frequency (AWS $$...)
* **iotcore\_qos**: MQTT QoS (typically leave as-is)
* **ei\_bindir**: Typical location of where the Edge Impulse services are installed (leave as-is)
* **ei\_ggc\_user\_groups**: A list of additional groups the Greengrass service user account will need to be a member of to allow the Edge Impulse service to invoke and operate correctly (typically leave as-is). For JetPack v6.x and above, please add "render" as an additional group.
* **ei\_sm\_secret\_id**: ID of the Edge Impulse API Key within AWS Secret Manager
* **ei\_sm\_secret\_name**: Name of the Edge Impulse API Key within AWS Secret Manager
* **install\_kvssink**: Option (default: "no", on: "yes") to build and make ready the kvssink gstreamer plugin
* **publish\_inference\_base64\_image**: Option (default: "no", on: "yes") to include a base64 encoded image that the inference result was based on
* **enable\_cache\_to\_file**: Option (default: "no", on: "yes") to enable both inference and associated image to get written to a specified local directory as a pair: <guid>.img and <guid>.json for each inference identified with a <guid>
* **cache\_file\_directory**: Option (default: "__none__") to specify the local directory when enable_cache_to_file is set to "yes"
* **ei\_poll\_sleeptime\_ms**: time (in ms) for the long polling message processor (typically leave as-is)
* **ei\_local\_model\_file**: option to utilize a previously installed local model file
* **ei\_shutdown\_behavior**: option to alter the shutdown behavior of the linux runner process. (can be set to "wait\_for\_restart" to cause the runner to pause after running the model and wait for the "restart" command to be issued (see "Commands" below for more details on the "restart" command))
* **enable\_threshold\_limit**: option to enable/disable the threshold confidence filter (must be "yes" or "no". Default is "no")
* **metrics\_sleeptime\_ms**: option to publish the model metrics statistics (time specified in ms).
* **default\_threshold**: option to specify threshold confidence filter "limit" (a value between 0 < x <= 1.0). Default setting is 0.7
* **threshold\_criteria**: option to specify the threshold confidence filter criteria (must be one of: "gt", "ge", "eq", "le", or "lt")
* **enable\_cache\_to\_s3**: option to enable caching the inference image/result to an AWS S3 bucket
* **s3\_bucket**: name of the optional S3 bucket to cache results into

### 4. Register the custom component via its recipe file

From the AWS Console -> IoT Core -> Greengrass -> Components, select "Create component". Then:

1. Select the "yaml" option to Enter the recipe
2. Clear the text box to remove the default "hello world" yaml recipe
3. Copy/Paste the entire/edited contents of your "EdgeImpulseLinuxRunnerServiceComponent.yaml" file
4. Press "Create Component"

![CreateComponent](./images/GG_Create_Component.png)

If formatting and artifact access checks out OK, you should have a newly created component listed in your Custom Components AWS dashboard!

Next we will create a Greengrass Deployment to deploy our custom component to our edge devices.
Loading
Loading