Skip to content

Architecture

This page is the map of the finished lab. Read it before Deploy from the cloud; the pages after that only build the pieces shown here.

RGB: green = button loop · blue = cloud command · red = edge model.

Zones never talk to AWS. They use mTLS MQTT to Moquette
aws.greengrass.clientdevices.mqtt.Moquette — local MQTT broker on the core. Not Mosquitto; client devices connect here over mTLS.
. The MQTT bridge
aws.greengrass.clientdevices.mqtt.Bridge — maps topics between LocalMqtt (Moquette), Pubsub (components), and IotCore.
is the only process that crosses LocalMqtt ↔ Pubsub ↔ IoT Core.

ESP32 → Greengrass core → IoT Core → rules → S3 · DynamoDB · CloudWatch, then the control and ML return paths.

ESP32-S3 zonesBOOT · temp · RGB
→
NUC · Greengrass V2
MoquetteMQTT BridgeGgEdgeLoopZoneAnomalyLogManager
→
IoT Coretopics
→
S3telemetry lake
DynamoDBzone state
CloudWatchmetric · alarm · logs
Control · blue RGB
Alarm
→
SNS
→
Lambda
→
IoT Core
→
GgEdgeLoopblue RGB
ML · red RGB
S3 lake
→
SageMaker
→
S3 artifacts
→
ZoneAnomalyred RGB
Zones stay on the LAN. The bridge is the only path into IoT Core. Rules fan out telemetry; alarm and SageMaker close the loop back to the zones.

Every bridge mapping, rule artifact, and component pub/sub.

1 · On the core (every MQTT hop)

ESP32-S3 zonesmTLS → Moquette :8883
  • pubgg-edge/sensorBOOT press/release
  • pubgg-edge/telemetry/<thing>every 10 s
  • subgg-edge/actuator/<thing>RGB green · blue · red
⇄
NUC · Greengrass V2
MoquetteLocalMqtt broker
MQTT Bridge9 topic mappings
Pubsub IPCcomponent bus
GgEdgeLoop 1.1.0sub sensor + command · pub actuator + ack
ZoneAnomaly 1.0.0sub telemetry · pub inference + red actuator
LogManager→ CloudWatch Logs · 60 s

Bridge routes from greenhouse-cloud.json (reset /mqttTopicMapping then merge):

MappingTopicSource → targetConsumer
SensorLocalToPubsubgg-edge/sensorLocalMqtt → PubsubGgEdgeLoop (button)
SensorLocalToIotCoregg-edge/sensorLocalMqtt → IotCoreconsole optional
TelemetryLocalToPubsubgg-edge/telemetry/+LocalMqtt → PubsubZoneAnomaly
TelemetryLocalToIotCoregg-edge/telemetry/+LocalMqtt → IotCorerules S3 · DDB · CW
ActuatorPubsubToLocalgg-edge/actuator/+Pubsub → LocalMqttRGB on zone
ActuatorPubsubToIotCoregg-edge/actuator/+Pubsub → IotCorerule actuator_ddb
CommandIotCoreToPubsubgg-edge/cloud/command/+IotCore → PubsubLambda / manual
AckPubsubToIotCoregg-edge/cloud/ack/+Pubsub → IotCorerule ack_ddb
InferencePubsubToIotCoregg-edge/inference/+Pubsub → IotCorerule inference_ddb

2 · Data up (IoT rules)

IoT Corebridged topics land here
→
gg-edge/telemetry/+telemetry-to-s3S3 PutObjecttelemetry/thing=…/dt=…/ts.json
gg-edge/telemetry/+telemetry-to-dynamodbDDB PutItemkind=telemetry
gg-edge/telemetry/+telemetry-to-cloudwatchPutMetricDataChipTempC-<thing>
gg-edge/actuator/+actuator-to-dynamodbDDB PutItemkind=actuator
gg-edge/cloud/ack/+ack-to-dynamodbDDB PutItemkind=cloud-ack
gg-edge/inference/+inference-to-dynamodbDDB PutItemkind=inference
S3 data laketelemetry archive
DynamoDBzone-state · 4 kinds
CloudWatchGgEdge/Greenhouse

3 · Control down (blue RGB)

  1. metric ChipTempC-<thing> → alarm ALARM/OK
  2. SNS topic (email + Lambda)
  3. Lambda publishes gg-edge/cloud/command/<thing> blue
  4. Bridge CommandIotCoreToPubsub → GgEdgeLoop → actuator/<thing>
  5. GgEdgeLoop ack → gg-edge/cloud/ack/<thing> → rule → DynamoDB

4 · Edge inference (red RGB)

S3 laketrain input
→
SageMakersklearn → ONNX
→
S3 artifactszone-anomaly-model
→
Thing-groupZoneAnomaly 1.0.0
→
red RGB + inference/+~20 s · two-sided
Zones never open a socket to AWS. The bridge is the only LocalMqtt ↔ Pubsub ↔ IoT Core crossing. Last actuator message wins on the wire; DynamoDB kind=actuator records source.

Act 1 installed with greengrass-cli
Greengrass CLI — local tool under /greengrass/v2/bin/greengrass-cli for listing components and creating local deployments on the core.
. Act 2 moves that same stack to a Thing-group deployment from S3 and turns on LogManager.

Act 1 — now
greengrass-cli local install
→
Act 2 — this page
  1. Upload artifact to S3
  2. Register component version (1.1.0)
  3. Thing-group deployment replaces the root set
NUC corecloud-managed stack · GgEdgeLoop 1.1.0
→
CloudWatch Logs/aws/greengrass/…
  • The button loop keeps working — only the install source moves from local disk to S3.
  • A Thing-group deploy replaces the whole root set, so the stack ships complete (client-device components, Cli, LogManager, GgEdgeLoop).
  • LogManager uploads component logs to CloudWatch every 60 s.
ComponentSubscribesPublishes

GgEdgeLoop 1.1.0

gg-edge/sensor, gg-edge/cloud/command/+

gg-edge/actuator/<thing> (green or blue), gg-edge/cloud/ack/<thing>

ZoneAnomaly 1.0.0

gg-edge/telemetry/+

gg-edge/inference/<thing>, gg-edge/actuator/<thing> (red)

The cloud command (blue RGB) path, in order:

  1. 1CloudWatch alarmChipTempC metric breaches → ALARM
  2. 2SNS topicfans out to email + Lambda
  3. 3Lambdapublishes the command (blue)gg-edge/cloud/command/<thing>
  4. 4IoT Core → BridgeCommandIotCoreToPubsub → Pubsub
  5. 5GgEdgeLoopdrives the actuatorgg-edge/actuator/<thing>
  6. 6ESP32-S3 zoneRGB turns blue
  7. 7DynamoDBack rule records the commandgg-edge/cloud/ack/<thing>
The down-path never blocks the LAN loop. To test it without waiting for an alarm, publish straight to gg-edge/cloud/command/<thing> — same bridge mapping and GgEdgeLoop handling.
ColorPublisherTopic pathPage
green

GgEdgeLoop (button)

sensor → Pubsub → actuator → LocalMqtt

Prove the LAN loop
blue

GgEdgeLoop (cloud command)

IoT Core → command → Pubsub → actuator

Cloud commands
redZoneAnomaly

telemetry → Pubsub → actuator

Edge inference

Last message wins on the wire. DynamoDB kind=actuator records source so you can see which layer acted last.

Next: Deploy from the cloud.