如何让EC2实例与AWS IoT MQTT数据进行交互?
Hey there! Since your Raspberry Pi is already successfully publishing to AWS IoT, we’re halfway to getting your EC2 server talking to the MQTT broker too. Let’s break this down into simple, actionable steps:
1. First, Lock Down IAM Permissions for EC2
Your EC2 instance needs explicit permission to interact with AWS IoT. Here’s how to set that up:
- Head to the IAM Console and create an IAM role for EC2 (if you don’t have one already).
- Attach a policy that grants MQTT-related access. For testing, you can use the managed
AWSIoTDataAccesspolicy, but for production, make a custom policy with only the actions you need:iot:Connect,iot:Subscribe,iot:Receive, andiot:Publish— restricted to your specific topics for security. - Attach this role to your EC2 instance via the EC2 Console (Instance Settings > Attach/Replace IAM Role).
2. Choose Your Node.js Tooling
You’ve got two reliable options for Node.js on EC2: the official AWS IoT SDK (recommended for native AWS integration) or the popular mqtt.js library with AWS SigV4 signing support. Let’s cover both.
Option 1: Use AWS IoT Device SDK v2 for JavaScript
This SDK handles AWS authentication automatically, so you don’t have to mess with manual signing.
First, install the SDK:
npm install aws-iot-device-sdk-v2
Then use this sample code to subscribe to your Raspberry Pi’s topic (replace placeholders with your details):
const { mqtt } = require('aws-iot-device-sdk-v2'); const { fromEnv } = require('aws-iot-device-sdk-v2/dist/auth'); async function connectToIoT() { // Auto-fetch credentials from EC2's attached IAM role const authConfig = await fromEnv(); const mqttClient = new mqtt.MqttClient(); // Replace with your AWS IoT ATS endpoint (found in IoT Console > Settings) const iotEndpoint = "your-iot-endpoint-ats.iot.your-region.amazonaws.com"; const connection = mqttClient.newConnection({ host_name: iotEndpoint, client_id: "EC2-MQTT-Client-123", // Use a unique ID (e.g., include EC2 instance ID) auth: authConfig, }); // Handle successful connection connection.on('connect', () => { console.log("Connected to AWS IoT from EC2!"); // Subscribe to your Raspberry Pi's topic (e.g., "raspberrypi/sensor/data") connection.subscribe("raspberrypi/sensor/data", (err) => { if (err) console.error("Subscribe failed:", err); else console.log("Subscribed to Raspberry Pi's sensor topic"); }); }); // Process incoming messages connection.on('message', (topic, payload) => { console.log(`Received from ${topic}: ${payload.toString()}`); }); // Handle connection errors connection.on('error', (err) => { console.error("Connection error:", err); }); await connection.connect(); } connectToIoT().catch(err => console.error("Fatal error:", err));
Option 2: Use mqtt.js with AWS SigV4 Signing
If you prefer the widely-used mqtt.js library, you’ll need to add SigV4 signing support (AWS requires this for MQTT authentication).
First, install dependencies:
npm install mqtt aws-sign-mqtt @aws-sdk/credential-provider-node
Then use this code to connect and subscribe:
const mqtt = require('mqtt'); const { signAwsRequest } = require('aws-sign-mqtt'); const { defaultProvider } = require('@aws-sdk/credential-provider-node'); async function connectWithMqttJs() { // Fetch credentials from EC2's IAM role const credentials = await defaultProvider()(); // Replace with your details const iotEndpoint = "your-iot-endpoint-ats.iot.your-region.amazonaws.com"; const awsRegion = "your-region"; // e.g., us-east-1 const targetTopic = "raspberrypi/sensor/data"; // Generate a signed MQTT connection URL const signedUrl = await signAwsRequest({ credentials, endpoint: iotEndpoint, region: awsRegion, protocol: 'mqtts', expires: 3600, // URL expires in 1 hour }); const client = mqtt.connect(signedUrl); client.on('connect', () => { console.log("Connected to AWS IoT via mqtt.js"); client.subscribe(targetTopic, (err) => { if (!err) console.log(`Subscribed to ${targetTopic}`); }); }); client.on('message', (topic, message) => { console.log(`Message received: ${message.toString()} (Topic: ${topic})`); }); client.on('error', (err) => { console.error("MQTT client error:", err); }); } connectWithMqttJs().catch(err => console.error("Fatal error:", err));
3. Critical Checks to Avoid Headaches
- EC2 Security Group: Make sure your instance’s security group allows outbound traffic on port 443 (HTTPS/MQTT over TLS) — this is required to connect to AWS IoT’s endpoint.
- Unique Client ID: Every MQTT client needs a unique ID. If you run multiple EC2 instances, generate a unique ID per instance (e.g., use the EC2 instance ID).
- Region Consistency: Double-check that your code uses the same AWS region as your IoT Thing and endpoint.
4. Publishing Messages from EC2 to AWS IoT
If you want your EC2 server to send commands or data to AWS IoT (e.g., trigger actions on your Raspberry Pi), add this snippet after connecting:
// Example: Publish a command to your Raspberry Pi const publishTopic = "raspberrypi/commands"; const message = JSON.stringify({ action: "take_sensor_reading" }); connection.publish(publishTopic, message, (err) => { if (err) console.error("Publish failed:", err); else console.log(`Sent command to ${publishTopic}`); });
内容的提问来源于stack exchange,提问作者Timothy Martin

