This repo is a jumpstart demo of AWS greengrass. It has 2 customized components to demostrate
- Local communication via IPC between components
- Device to cloud communication via MQTT
- Cloud to device communication via device shadow
This component send the sensors telemtries to IoT core. IoT Core topic and sending interval can be found in the recipe.
Example MQTT payload:
{
"timemillis": 1669671812573,
"pitch": 314.27,
"roll": 293.34,
"yaw": 106.97,
"temperature": 40.27,
"pressure": 1026.98,
"humidity": 28.74
}
This component send the joystick events (move up/down/left/right, press/hold/release) to local IPC and AWS IoT Core. The IPC and IoT Core topic can be found in the recipe.
Example MQTT payload:
{
"timemillis": 1669202845134,
"direction": "down",
"action": "released"
}
{
"timemillis": 1669202865267,
"direction": "left",
"action": "pressed"
}
The possible values of direction and action can be found at Sense Hat Document.
This component does the following:
- Maintain a number (0-9) and display it on LED
- When received joystick events via IPC
- Joystick up/down: increse/decrese the number (range between 0-9)
- Joystick left/right: change LED display to a random color
- Joystick press down: toggle LED number display on/off
- Support IoT Core Shadow, so there are two ways to update the display number:
- Use AWS IoT Core shadow to update the number remotely (cloud to device sync: every 10 seconds).
- Use the joystick to update the number locally.
The IPC and IoTCore topic, shadown name etc can be found in the recipe.
Note: In this component we are using GreengrassCoreIPCClientV2 (sensors and joystick are using v1), to avoid sync/async issue. With V2 the code is also cleaner. GreengrassCoreIPCClientV2 document can be found at here.
The display number can be updated either by local joystick or by remote shadow in iot core. The latest update (either from local or remote) overwrites others. Therefore, it is important for local to set the "desired" value back to remote shadow in cloud, so the remote shadow knows the new "desired" value and will not update it in the next shadow sync cycle.
See more at the document evice-shadow-empty-fields.
- Raspberry Pi 3b
- Raspberry Pi Sense Hat
- Raspbery Pi OS (64 bit)
- Sense Hat SDK
If you are using the Pi OS lite version, remember to install needed packages
sudo apt update
sudo apt install python3-pip
sudo apt install git
sudo apt install sense-hat #need reboot
Follow the steps in https://docs.aws.amazon.com/greengrass/v2/developerguide/getting-started.html
As a part of the installtion, create an IAM user with minimal permission (the role json can be found in minimal-greengrass-policy-for-device.json). You can deactive the key/secret after the device is provisioned.
- aws.greengrass.Cli
- aws.greengrass.ShadowManager (config)
- aws.greengrass.LocalDebugConsole
- aws.greengrass.LogManager (config)
- Install VS Code with Remote SSH extension
- In Remote SSH extension, enable ports forwarding for 1441 and 1442. Ensure it is set to HTTPS (not http by default). This is for access Greengrass LocalDebugConsole from your development laptop.
Check the development tips in the appendix
- Config the aws.greengrass.ShadowManager during deployment step. The sample config can be found at shadow-manager-config.json.
- Note: Make sure the shadow name is correct in the "synchronize" section in the config, otherwise the shadow wont be sync between cloud and device.
- If your code calls UpdateShadow API but the shadow does not exist, the call will creat the shadow. If you try to GetShadow but it does not exist, you will get ResourceNotExist error. In that case, you can manually create the (named) shadow in IoT core console. (In this demo, the shadow "NumberLEDNamedShadow" will be created automatically, so you do not need to create it manually.)
- For setting the shadow and sync to device, edit the default shadow document, in "desired" section, add the needed field: (you can skip the "reported" section)
{
"state": {
"desired": {
"number":9
}
}
}
- More details can be found in the sync-shadows-with-iot-core and ipc-local-shadows.
You can run in on Pi via VS Code remote SSH terminal. For deployment,
# ensure your terminal is at the root of this repo, that has folder Components
sudo /greengrass/v2/bin/greengrass-cli deployment create --recipeDir Components/recipes --artifactDir Components/artifacts --merge "com.example.sensehat.led=1.0.0"
sudo /greengrass/v2/bin/greengrass-cli --ggcRootPath /greengrass/v2 deployment create --remove "com.example.sensehat.led"
sudo /greengrass/v2/bin/greengrass-cli component list
The log file structure is at https://docs.aws.amazon.com/greengrass/v2/developerguide/monitor-logs.html
#greengrass system logs
sudo tail /greengrass/v2/logs/greengrass.log
# log of a componnet
sudo cat /greengrass/v2/logs/com.example.sensehat.joystick.log
With aws.greengrass.LogManager, you can also directly check cloudwatch. The log group is something like "/aws/greengrass/UserComponent/eu-west-1/com.example.sensehat.led"
After you deployed the aws.greengrass.LocalDebugConsole component and enabled 1441 and 1442 port forwarding, you can access the console https://localhost:1441/ from you local laptop
- Get access password (user name is "debug")
sudo /greengrass/v2/bin/greengrass-cli get-debug-password
- The console is using a self-signed https certificate, use firefox to bypass the warning (Edge cannot bypass)
By default the Greengrass user cannot have permission to access local hardware resources such as sense hat. There are two ways to solve it:
- In recipes, require RequiresPrivilege (recommended)
"RequiresPrivilege": true
- Manually add greengrass user to linux usergroups
# error msg from logs
# 2022-10-22T20:16:51.747Z [WARN] (Copier) linkcd.sensehat.HelloWorld: stderr. PermissionError: [Errno 13] Permission denied: '/dev/input/event1'.
# the user in the "input" group can acess /dev/input/event1
$ ls -l /dev/input/event1
# crw-rw---- 1 root input 13, 65 Sep 22 04:17 /dev/input/event1
# ggc_user is not in that group
$ groups ggc_user
# ggc_user : ggc_user ggc_group
# add ggc_user to "input" group
$ sudo addgroup ggc_user input
# Adding user `ggc_user' to group `input' ...
# Adding user ggc_user to group input
# Done.
#another error
# HelloWorld: stderr. PermissionError: [Errno 13] Permission denied: '/dev/fb0'. {scriptName=services.linkcd.sensehat.HelloWorld.lifecycle.Run, serviceName=linkcd.sensehat.HelloWorld, currentState=RUNNING}
# the user in "video" group can access /dev/fb0
$ ls -l /dev/fb0
# crw-rw---- 1 root video 29, 0 Sep 22 04:17 /dev/fb0
# add gcc_user to
$ sudo addgroup ggc_user video
# Adding user `ggc_user' to group `video' ...
# Adding user ggc_user to group video
# Done.