IoT Cloud Platforms
Cloud platforms handle the hard parts of IoT at scale: device authentication, message routing, data storage, fleet management, and analytics. This topic compares the major platforms and shows you how to connect devices to each.
Platform Comparison
| Platform | Provider | Protocol | Free Tier | Best For |
|---|---|---|---|---|
| AWS IoT Core | Amazon | MQTT, HTTP, WebSocket | 250K msgs/month (12 mo) | Enterprise, scalable |
| Azure IoT Hub | Microsoft | MQTT, AMQP, HTTP | 8,000 msgs/day (F1) | Microsoft stack |
| Google Cloud IoT | MQTT, HTTP | Pay-per-use | BigQuery integration | |
| ThingSpeak | MathWorks | HTTP, MQTT | 3M msgs/year | Learning, MATLAB analytics |
| Adafruit IO | Adafruit | MQTT, HTTP | 30 msg/min, 10 feeds | Maker projects |
| HiveMQ Cloud | HiveMQ | MQTT | 100 connections | MQTT broker as service |
| Losant | Losant | MQTT, HTTP | 100 devices | Mid-scale, good UI |
ThingSpeak — Best for Learning
ThingSpeak is the fastest way to visualize IoT data. It requires almost no setup.
# MicroPython ESP32 → ThingSpeak (HTTP GET)
import urequests
import dht
from machine import Pin
import network, utime
# Your ThingSpeak credentials
WRITE_API_KEY = "YOUR_WRITE_API_KEY_HERE"
BASE_URL = "https://api.thingspeak.com/update"
def connect_wifi(ssid, password):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
while not wlan.isconnected():
utime.sleep_ms(500)
print(f"WiFi: {wlan.ifconfig()[0]}")
def send_to_thingspeak(field1=None, field2=None, field3=None):
"""Send up to 3 fields to ThingSpeak channel."""
params = f"api_key={WRITE_API_KEY}"
if field1 is not None: params += f"&field1={field1}"
if field2 is not None: params += f"&field2={field2}"
if field3 is not None: params += f"&field3={field3}"
url = f"{BASE_URL}?{params}"
try:
r = urequests.get(url, timeout=10)
entry_id = r.text.strip()
r.close()
if entry_id == "0":
print("ThingSpeak rejected data (rate limit?)")
return False
print(f"Sent to ThingSpeak, entry #{entry_id}")
return True
except Exception as e:
print(f"ThingSpeak error: {e}")
return False
connect_wifi("MySSID", "MyPassword")
sensor = dht.DHT22(Pin(4))
while True:
sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()
send_to_thingspeak(field1=temp, field2=hum)
utime.sleep(16) # ThingSpeak free tier: min 15s between updatesAWS IoT Core — Enterprise Grade
AWS IoT Core is the most mature and scalable IoT platform. Every device gets a unique X.509 certificate.
Architecture
ESP32 Device
│
│ MQTT over TLS (port 8883)
│ Client cert + private key
▼
AWS IoT Core (Broker)
│
├── IoT Rules Engine
│ │
│ ├── DynamoDB (per-device last reading)
│ ├── S3 (raw data archive)
│ ├── Lambda (alerting, processing)
│ └── SNS (email/SMS alerts)
│
└── AWS Timestream / InfluxDB (time-series storage)Device Setup (Python)
# Raspberry Pi / PC → AWS IoT Core with paho-mqtt
import paho.mqtt.client as mqtt
import ssl
import json
import time
# Download these from AWS IoT Core → Manage → Things → Your Thing → Certificates
ENDPOINT = "abc123-ats.iot.us-east-1.amazonaws.com"
CLIENT_CERT = "/path/to/device.cert.pem"
PRIVATE_KEY = "/path/to/device.private.key"
CA_CERT = "/path/to/AmazonRootCA1.pem" # Download from AWS
THING_NAME = "temperature-sensor-01"
# AWS IoT MQTT topic convention
TELEMETRY_TOPIC = f"devices/{THING_NAME}/telemetry"
SHADOW_UPDATE = f"$aws/things/{THING_NAME}/shadow/update"
SHADOW_GET = f"$aws/things/{THING_NAME}/shadow/get"
def on_connect(client, userdata, flags, rc):
print(f"AWS IoT: Connected (rc={rc})")
# Subscribe to device shadow (cloud-to-device configuration)
client.subscribe(f"$aws/things/{THING_NAME}/shadow/update/delta", qos=1)
def on_message(client, userdata, msg):
"""Handle shadow delta (desired state from cloud)."""
topic = msg.topic
data = json.loads(msg.payload)
print(f"Received shadow delta: {data}")
# Apply desired state
if "state" in data and "interval" in data["state"]:
new_interval = data["state"]["interval"]
print(f"Changing reporting interval to {new_interval}s")
def send_telemetry(client, temperature, humidity, battery_pct):
payload = json.dumps({
"device_id": THING_NAME,
"temperature": round(temperature, 2),
"humidity": round(humidity, 2),
"battery": battery_pct,
"timestamp": int(time.time())
})
client.publish(TELEMETRY_TOPIC, payload, qos=1)
print(f"Published: {payload}")
client = mqtt.Client(client_id=THING_NAME)
client.tls_set(
ca_certs = CA_CERT,
certfile = CLIENT_CERT,
keyfile = PRIVATE_KEY,
tls_version = ssl.PROTOCOL_TLS_CLIENT
)
client.on_connect = on_connect
client.on_message = on_message
client.connect(ENDPOINT, 8883, 60)
client.loop_start()
time.sleep(1)
for i in range(12):
send_telemetry(client, 24.5 + i * 0.1, 61.0, 87)
time.sleep(5)
client.loop_stop()
client.disconnect()Device Shadow (AWS) / Device Twin (Azure)
Device shadows maintain a virtual copy of device state in the cloud — useful for configuration and offline devices.
# Update device shadow with current and desired state
def update_shadow(client, thing_name, reported_state, desired_state=None):
"""
reported: what the device's actual current state is
desired: what the cloud wants the device to do
"""
shadow = {"state": {"reported": reported_state}}
if desired_state:
shadow["state"]["desired"] = desired_state
topic = f"$aws/things/{thing_name}/shadow/update"
client.publish(topic, json.dumps(shadow), qos=1)
# Report current firmware version and interval
update_shadow(client, THING_NAME,
reported_state={
"firmware": "1.4.2",
"interval": 30,
"status": "online"
}
)
# Request shadow state on reconnect
client.publish(f"$aws/things/{THING_NAME}/shadow/get", "", qos=1)Adafruit IO — Quick Maker Dashboards
# Python → Adafruit IO (MQTT)
import paho.mqtt.client as mqtt
import json
import time
AIO_USERNAME = "your_adafruit_username"
AIO_KEY = "your_adafruit_io_key"
# Adafruit IO topics: {username}/feeds/{feed-name}
TEMP_FEED = f"{AIO_USERNAME}/feeds/temperature"
HUM_FEED = f"{AIO_USERNAME}/feeds/humidity"
client = mqtt.Client()
client.username_pw_set(AIO_USERNAME, AIO_KEY)
def on_connect(c, ud, flags, rc):
print("Adafruit IO connected")
# Subscribe to receive dashboard input (sliders, buttons)
client.subscribe(f"{AIO_USERNAME}/feeds/led-control", qos=1)
def on_message(c, ud, msg):
value = msg.payload.decode()
print(f"Dashboard input [{msg.topic}]: {value}")
# value might be "ON", "OFF", or "50" (slider value)
client.on_connect = on_connect
client.on_message = on_message
client.connect("io.adafruit.com", 1883, 60)
client.loop_start()
for _ in range(10):
# Publish to individual feeds
client.publish(TEMP_FEED, "24.5", qos=1)
client.publish(HUM_FEED, "61.2", qos=1)
time.sleep(2) # Adafruit IO free: max 30 msgs/min
client.loop_stop()Serverless Processing with AWS Lambda
# AWS Lambda function — triggered by IoT Rule when T > 35°C
import boto3
import json
import os
sns = boto3.client('sns')
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['READINGS_TABLE'])
def lambda_handler(event, context):
"""
event contains the IoT message payload:
{
"device_id": "sensor-01",
"temperature": 37.2,
"humidity": 45.0,
"timestamp": 1704067200
}
"""
device_id = event['device_id']
temperature = event['temperature']
timestamp = event['timestamp']
# Store in DynamoDB
table.put_item(Item={
'device_id': device_id,
'timestamp': timestamp,
'temperature': str(temperature),
'humidity': str(event.get('humidity', 0))
})
# Send alert if temperature is too high
if temperature > 35:
message = (
f"🌡️ HIGH TEMPERATURE ALERT\n"
f"Device: {device_id}\n"
f"Temperature: {temperature}°C\n"
f"Threshold: 35°C"
)
sns.publish(
TopicArn=os.environ['ALERT_TOPIC_ARN'],
Subject="IoT Temperature Alert",
Message=message
)
print(f"Alert sent for {device_id}: {temperature}°C")
return {"statusCode": 200}Summary
- ThingSpeak is the fastest to get started — no certificate setup, free dashboard
- AWS IoT Core is the most scalable — X.509 certificates, rules engine, Lambda integration
- Azure IoT Hub integrates naturally with the Microsoft ecosystem (Azure Functions, Power BI)
- Device shadows maintain cloud-side state even when devices are offline — essential for configuration management
- Serverless (Lambda/Azure Functions) processes IoT events without managing servers
- Start with ThingSpeak or Adafruit IO for prototypes; migrate to AWS or Azure for production
Next, we'll look at time-series data collection and storage — the foundation for IoT analytics.