From a single sensor reading to a city-wide intelligent network — how billions of tiny devices reshape the physical world.
There are over 15 billion IoT devices active today. Your smart thermostat talks to the cloud every 30 seconds. A tractor in Iowa reports soil moisture to a farmer's phone. Traffic lights in Barcelona optimize flow using real-time data from thousands of buried sensors. A patient's insulin pump adjusts dosage based on continuous glucose readings.
This isn't science fiction. It's Tuesday.
The Internet of Things (IoT) is a simple idea with enormous consequences: take a physical thing, give it a sensor, connect it to the internet, and let software make it smarter. A thermostat becomes a climate optimization system. A light bulb becomes a security system. A cow becomes a health-monitored asset.
The evolution happened in three waves:
| Era | Name | What Changed | Example |
|---|---|---|---|
| 1990s-2005 | M2M (Machine-to-Machine) | Point-to-point connections, proprietary protocols | Vending machine reports stock via GSM |
| 2005-2018 | IoT | IP-based networking, cloud platforms, open standards | Smart home with WiFi sensors + AWS backend |
| 2018-present | AIoT (AI + IoT) | Edge ML, predictive analytics, autonomous decisions | Factory robot predicts own bearing failure |
Each domain has its own device types, protocols, cloud services, and constraints. A heart monitor has very different requirements than a smart streetlight. Let's explore five major IoT domains.
Click a domain to see its device types, protocols, and cloud services. Each domain has unique constraints.
Notice the pattern: every domain has the same four ingredients — sensors that perceive, a network that transports, a cloud that processes, and an application that acts. The specifics change (LoRa for agriculture, BLE for health wearables, 5G for industrial robots) but the architecture is universal.
Every IoT system, from a $5 soil sensor to a billion-dollar smart grid, is built from the same four layers. Understanding these layers is the skeleton key to designing any IoT solution.
The four-layer IoT architecture:
Let's trace a concrete path through all four layers. Imagine a greenhouse monitoring system:
| Layer | Component | Role | Data Shape |
|---|---|---|---|
| Perception | BME280 sensor | Measures temp, humidity, pressure | 3 floats, 12 bytes |
| Perception | ESP32 MCU | Reads sensor via I2C, runs firmware | JSON payload ~64 bytes |
| Network | WiFi (802.11n) | Sends MQTT packet to broker | ~128 bytes with headers |
| Platform | Azure IoT Hub | Receives, authenticates, routes | Message enters routing pipeline |
| Platform | Stream Analytics | Real-time aggregation + alerting | Windowed averages, threshold triggers |
| Platform | Cosmos DB | Time-series storage | JSON documents, partitioned by device |
| Application | Power BI dashboard | Visualization for greenhouse operator | Charts, maps, alert panels |
| Application | Azure Functions | Triggers irrigation if humidity < 40% | HTTP call to actuator endpoint |
json { "deviceId": "greenhouse-01", "timestamp": "2026-05-16T10:30:00Z", "temperature": 24.6, "humidity": 38.2, "pressure": 1013.25 }
At each layer, you make choices. Those choices cascade. Picking LoRaWAN at Layer 2 means your payload is limited to 51-222 bytes — you can't send raw images. Picking BLE means your range is ~100m — you need a gateway for anything larger than a room.
Select one component at each layer to build a complete IoT path. Watch the assembled pipeline and see constraints.
A sensor converts a physical quantity into an electrical signal. That signal gets digitized by an ADC (Analog-to-Digital Converter), processed by a microcontroller, and packaged for transmission. Every IoT system starts here — at the physical interface between the digital and analog worlds.
Sensor categories by what they measure:
| Category | Sensors | Output | Interface | Power |
|---|---|---|---|---|
| Environmental | BME280, SHT40, BMP390 | Temp, humidity, pressure | I2C / SPI | ~3.6 μA |
| Motion | MPU6050, LSM6DSO, BMI270 | Accel (g), gyro (dps) | I2C / SPI | ~0.5 mA |
| Location | u-blox NEO-M9N, DW3000 (UWB) | Lat/lon/alt or distance | UART / SPI | ~25 mA (GPS) |
| Chemical | SCD41 (CO2), pH probe, MQ-series | ppm, pH, resistance ratio | I2C / Analog | ~20 mA (active) |
| Optical | OPT3001 (lux), MAX30102 (SpO2) | Light intensity, heart rate | I2C | ~0.4 mA |
But here's the critical insight: you almost never want to send raw sensor data to the cloud.
The solution is edge processing — compute at the device or gateway level before transmitting. This is where the "intelligence" in AIoT lives.
Edge processing strategies:
| Strategy | What It Does | Bandwidth Reduction |
|---|---|---|
| Aggregation | Send min/max/mean per minute instead of raw | 600× |
| Delta encoding | Only send when value changes by > threshold | 10-100× |
| Edge inference | Run ML model locally, send only anomalies | 1000×+ |
| Compression | LZ4 or delta + Huffman on time series | 3-8× |
Worked example — let's calculate the edge vs cloud tradeoff:
If we also apply delta encoding (only report if temp changed by >0.5°C), we might only send 1 in 3 intervals:
Adjust sensor count and sampling rate. See raw bandwidth vs edge-processed bandwidth. The green zone shows what fits in LoRa; yellow in WiFi; red exceeds typical cellular budgets.
python # Edge aggregation on ESP32 (MicroPython) import time from machine import I2C, Pin from bme280 import BME280 i2c = I2C(0, scl=Pin(22), sda=Pin(21)) sensor = BME280(i2c=i2c) class EdgeAggregator: def __init__(self, window_sec=60, threshold=0.5): self.window = window_sec self.threshold = threshold self.buffer = [] self.last_sent = None def add_reading(self, temp, hum, pres): self.buffer.append((temp, hum, pres)) def should_send(self): if not self.buffer: return False avg_t = sum(r[0] for r in self.buffer) / len(self.buffer) if self.last_sent is None: return True return abs(avg_t - self.last_sent) > self.threshold def get_aggregate(self): """Returns {min, max, mean} for each channel.""" temps = [r[0] for r in self.buffer] result = { "temp_min": min(temps), "temp_max": max(temps), "temp_mean": sum(temps) / len(temps), } self.last_sent = result["temp_mean"] self.buffer = [] return result
Your sensor has a reading. Now it needs to get that reading to the cloud. The choice of connectivity technology is the most consequential architectural decision in IoT — it determines battery life, range, cost, and what data you can realistically transmit.
| Technology | Range | Bandwidth | Power | Cost/device | Best For |
|---|---|---|---|---|---|
| WiFi (802.11) | ~50m indoor | 10-100 Mbps | High (~100mA) | $2-5 | Home, building, AC-powered |
| BLE (Bluetooth 5) | ~100m | 2 Mbps | Low (~10μA sleep) | $1-3 | Wearables, beacons, health |
| LoRaWAN | 2-15 km | 0.3-50 kbps | Ultra-low | $5-10 | Agriculture, utilities, tracking |
| Cellular (4G/5G) | Nationwide | 10-1000 Mbps | High | $10-30 + plan | Vehicles, cameras, high-value assets |
| Zigbee/Thread | ~100m (mesh) | 250 kbps | Low | $2-5 | Smart home, lighting, HVAC |
| NB-IoT | Nationwide | ~100 kbps | Low | $5-15 + plan | Meters, trackers, infrequent data |
Once you've chosen how to connect, you need a protocol to structure the conversation. For IoT, that protocol is almost always MQTT (Message Queuing Telemetry Transport).
MQTT uses a publish/subscribe model. This is fundamentally different from HTTP's request/response:
| Concept | What It Means | Example |
|---|---|---|
| Broker | Central server that routes all messages | Azure IoT Hub, Mosquitto, HiveMQ |
| Publisher | Device that sends data | Temperature sensor publishes readings |
| Subscriber | Client that receives data it cares about | Dashboard subscribes to all farm sensors |
| Topic | Hierarchical address for messages | farm/field1/moisture |
| QoS | Delivery guarantee level | 0, 1, or 2 (see below) |
MQTT Topics are hierarchical strings separated by /. They support wildcards:
mqtt topics # Specific sensor farm/field1/moisture # All sensors in field1 (+ = single level wildcard) farm/field1/+ # All sensors in all fields (# = multi-level wildcard) farm/# # Real-world Azure IoT Hub topic format devices/{device-id}/messages/events/
QoS Levels — the trade-off between reliability and overhead:
| QoS | Name | Guarantee | Packets | Use Case |
|---|---|---|---|---|
| 0 | At most once | Fire-and-forget, may be lost | 1 (PUBLISH) | Frequent telemetry (temp every 5s) |
| 1 | At least once | Delivered, may duplicate | 2 (PUBLISH + PUBACK) | Important events (door opened) |
| 2 | Exactly once | Delivered exactly once | 4 (handshake) | Critical commands (medication dose) |
Click "Publish" to send a message. Watch it route through the broker to all matching subscribers. Change QoS to see the acknowledgment handshake.
python # MQTT publish with Paho client (the standard Python MQTT library) import paho.mqtt.client as mqtt import json, time def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client.subscribe("farm/+/moisture", qos=1) def on_message(client, userdata, msg): data = json.loads(msg.payload) print(f"{msg.topic}: moisture={data['value']}%") client = mqtt.Client(client_id="gateway-01") client.tls_set() # Enable TLS encryption client.username_pw_set("user", "password") client.on_connect = on_connect client.on_message = on_message client.connect("your-hub.azure-devices.net", 8883) client.loop_start() # Publish sensor data payload = json.dumps({"value": 42.5, "unit": "%"}) client.publish("farm/field1/moisture", payload, qos=1)
Your sensor published a message. It left the device over WiFi, became an MQTT packet, and hit the cloud. Now what? The cloud platform is where raw telemetry becomes actionable intelligence. We'll use Azure IoT as our reference architecture — the concepts map directly to AWS IoT Core and Google Cloud IoT.
The core Azure IoT services form a pipeline:
IoT Hub is the most critical component. It handles:
| Feature | What It Does | Why It Matters |
|---|---|---|
| Device Registry | Stores identity + auth for each device | You know exactly which devices are authorized |
| Message Routing | Routes messages to different endpoints by content | Temperature alerts go to Functions; all data goes to storage |
| Device Twins | JSON document per device: desired state + reported state | Configure devices remotely without custom protocol |
| Direct Methods | Synchronous RPC calls to devices | "Reboot now" or "take a photo" with response |
| DPS (Provisioning) | Zero-touch enrollment of new devices | Ship 10,000 devices; they self-register on first boot |
desired (what the cloud wants) and reported (what the device says its state is). Change desired.temperature_threshold to 30, and the device automatically receives the update and adjusts.json // Device Twin for greenhouse-01 { "deviceId": "greenhouse-01", "properties": { "desired": { "telemetryInterval": 60, "temperatureThreshold": 30, "firmwareVersion": "2.1.0" }, "reported": { "telemetryInterval": 60, "temperatureThreshold": 30, "firmwareVersion": "2.0.3", "battery": 78, "lastBoot": "2026-05-16T08:00:00Z" } } }
Notice: the desired firmware is 2.1.0 but reported is 2.0.3. The device sees this mismatch and initiates an OTA update. No human intervention required.
Stream Analytics query — detect temperature spikes in real-time:
sql -- Alert when any device exceeds threshold for 5 minutes SELECT deviceId, AVG(temperature) AS avg_temp, MAX(temperature) AS max_temp, System.Timestamp() AS window_end INTO alertOutput FROM iothub TIMESTAMP BY EventEnqueuedUtcTime GROUP BY deviceId, TumblingWindow(minute, 5) HAVING AVG(temperature) > 30
Watch telemetry flow from device through IoT Hub to analytics. Click "Send Alert" to trigger a threshold breach and see the alert path activate.
python # Register device and send telemetry with Azure IoT SDK from azure.iot.device import IoTHubDeviceClient, Message import json # Connection string from Azure Portal > IoT Hub > Device conn_str = "HostName=myhub.azure-devices.net;DeviceId=greenhouse-01;SharedAccessKey=..." client = IoTHubDeviceClient.create_from_connection_string(conn_str) client.connect() # Send telemetry payload = json.dumps({ "temperature": 24.6, "humidity": 38.2 }) msg = Message(payload) msg.content_type = "application/json" msg.content_encoding = "utf-8" msg.custom_properties["alert"] = "false" client.send_message(msg) print("Telemetry sent") # Listen for Device Twin updates (desired properties) def twin_patch_handler(patch): print(f"Received twin patch: {patch}") if "telemetryInterval" in patch: # Adjust our sending rate global INTERVAL INTERVAL = patch["telemetryInterval"] client.on_twin_desired_properties_patch_received = twin_patch_handler
You've designed the architecture. Now you need to actually write the firmware that runs on the microcontroller. This is embedded programming — writing software for devices with 256KB of RAM, no operating system (or a minimal RTOS), and the need to run for years on a coin cell battery.
Framework choices for IoT device programming:
| Framework | Language | Target MCUs | Complexity | Best For |
|---|---|---|---|---|
| Arduino | C++ (simplified) | AVR, ESP32, nRF52 | Low | Prototyping, hobby, education |
| ESP-IDF | C | ESP32 family | Medium-High | Production ESP32 products |
| Zephyr RTOS | C | 500+ boards | High | Commercial products, multi-vendor |
| Mbed OS | C++ | ARM Cortex-M | Medium | ARM ecosystem products |
| MicroPython | Python | ESP32, RP2040 | Low | Rapid prototyping, scripts |
The fundamental embedded programming loop is deceptively simple:
WiFi Provisioning — how does a headless device (no screen, no keyboard) connect to your WiFi network for the first time?
| Method | How It Works | UX Quality |
|---|---|---|
| Hardcoded | SSID/password in firmware | Terrible (can't change network) |
| SmartConfig | Phone broadcasts credentials via WiFi packet timing | Fragile (doesn't work on 5GHz) |
| BLE Provisioning | Phone connects via BLE, sends WiFi credentials | Excellent (industry standard) |
| AP Mode | Device creates hotspot, phone connects and configures | Good (no BLE hardware needed) |
OTA (Over-The-Air) Updates — critical for any deployed fleet. You cannot physically visit 10,000 sensors to update firmware.
c // ESP-IDF: Complete IoT device firmware skeleton // Connects to WiFi, publishes BME280 data via MQTT to Azure IoT Hub #include "esp_wifi.h" #include "esp_event.h" #include "mqtt_client.h" #include "esp_sleep.h" #include "driver/i2c.h" #define SLEEP_DURATION_US (60 * 1000000) // 60 seconds #define MQTT_BROKER "mqtts://myhub.azure-devices.net:8883" #define MQTT_TOPIC "devices/sensor-01/messages/events/" static esp_mqtt_client_handle_t mqtt_client; void wifi_init(void) { esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); wifi_config_t wifi_config = { .sta = { .ssid = "MyNetwork", .password = "MyPassword" } }; esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_set_config(WIFI_IF_STA, &wifi_config); esp_wifi_start(); esp_wifi_connect(); } void mqtt_publish_telemetry(float temp, float hum) { char payload[128]; snprintf(payload, sizeof(payload), "{\"temperature\":%.1f,\"humidity\":%.1f}", temp, hum); esp_mqtt_client_publish(mqtt_client, MQTT_TOPIC, payload, 0, 1, 0); // QoS 1 } void app_main(void) { wifi_init(); // ... wait for connection ... esp_mqtt_client_config_t mqtt_cfg = { .broker.address.uri = MQTT_BROKER, .credentials.authentication.certificate = device_cert, }; mqtt_client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_start(mqtt_client); // Read sensor float temp = bme280_read_temperature(); float hum = bme280_read_humidity(); // Publish mqtt_publish_telemetry(temp, hum); // Deep sleep esp_deep_sleep(SLEEP_DURATION_US); }
Watch an ESP32's power states cycle: boot → WiFi connect → MQTT publish → deep sleep. The bar shows current draw at each phase. See how sleep dominates the duty cycle.
Everything comes together now. We'll simulate a complete smart agriculture irrigation system end-to-end: soil moisture sensors in the field, LoRa radio to a gateway, MQTT to Azure IoT Hub, Stream Analytics for decision-making, and an irrigation valve that opens automatically when the soil is too dry.
The architecture:
Adjust rain level (left slider) to change soil moisture. Watch the entire pipeline react: sensor reads → LoRa packet → cloud processing → irrigation decision. Toggle failures to see graceful degradation.
What happens when the gateway goes offline? The sensor node stores readings in flash memory (up to 72 hours of data at 1-minute intervals = 4,320 readings × 8 bytes = 34 KB). When the gateway comes back, the node replays stored data with timestamps. The cloud sees the gap and processes the backlog. This is store-and-forward — a critical IoT resilience pattern.
What happens when the cloud goes down? The gateway itself has a local rule engine: "if latest moisture < 20%, open valve." This is edge fallback — the system degrades gracefully from "smart" (cloud analytics with historical context) to "functional" (simple threshold at the gateway).
In October 2016, the Mirai botnet enslaved 600,000 IoT devices (cameras, routers, DVRs) and used them to launch the largest DDoS attack in history, taking down Twitter, Netflix, Reddit, and GitHub for hours. The devices were compromised because they used default passwords like "admin/admin" and had no mechanism for firmware updates.
IoT security is not optional. It's existential. A compromised insulin pump can kill a patient. A hijacked traffic controller can cause accidents. A breached smart lock lets burglars in.
The OWASP IoT Top 10 (2024) — the most critical IoT vulnerabilities:
| # | Vulnerability | Real Attack | Defense |
|---|---|---|---|
| 1 | Weak/hardcoded passwords | Mirai botnet (default creds) | Unique per-device credentials, no defaults |
| 2 | Insecure network services | Open Telnet/SSH on cameras | Disable unused ports, firewall |
| 3 | Insecure ecosystem interfaces | Unauthed cloud API exposes all devices | OAuth2, API keys, rate limiting |
| 4 | Lack of secure update mechanism | No OTA = unpatched forever | Signed OTA with rollback |
| 5 | Insecure/outdated components | OpenSSL Heartbleed in camera firmware | SBOM tracking, auto-update deps |
| 6 | Insufficient privacy protection | Smart speaker recordings leaked | Edge processing, data minimization |
| 7 | Insecure data transfer | Unencrypted MQTT sniffed on WiFi | TLS 1.3, certificate pinning |
| 8 | Lack of device management | No way to revoke compromised device | Device registry with revocation |
| 9 | Insecure default settings | UPnP enabled by default on routers | Secure by default, opt-in features |
| 10 | Lack of physical hardening | JTAG debug port left accessible | Disable debug, fuse eFuse bits |
Defense layers for a secure IoT deployment:
| Layer | Mechanism | What It Prevents |
|---|---|---|
| Transport | TLS 1.3 / mTLS | Eavesdropping, man-in-the-middle |
| Identity | X.509 certificates (per-device) | Device impersonation |
| Boot | Secure Boot (signature verification) | Firmware tampering |
| Storage | Encrypted flash (AES-256) | Physical extraction of secrets |
| Update | Signed OTA with hash verification | Malicious firmware injection |
| Runtime | Attestation (TPM/secure enclave) | Runtime code modification |
| Network | Network segmentation (VLAN/firewall) | Lateral movement after breach |
Privacy — GDPR and IoT:
Under GDPR (and similar regulations worldwide), IoT data that can identify a person is personal data. A smart meter's consumption pattern reveals when you're home, when you sleep, what appliances you use. A fitness tracker knows your heart rate, location, and sleep quality.
Select an attack type to see which defenses mitigate it. Green = effective defense, red = vulnerable, yellow = partial protection.
4G gave us fast phones. 5G gives us a programmable network fabric for machines. The difference isn't just speed — it's three fundamentally different service types designed for three different use cases, all running simultaneously on the same physical infrastructure.
The three 5G service categories:
| Category | Full Name | Key Metric | IoT Application |
|---|---|---|---|
| eMBB | Enhanced Mobile Broadband | 20 Gbps peak | AR/VR, 4K video analytics, digital twins |
| URLLC | Ultra-Reliable Low Latency | <1ms, 99.999% reliable | Remote surgery, autonomous vehicles, industrial robots |
| mMTC | Massive Machine-Type Comms | 1 million devices/km² | Smart city sensors, agriculture, meters |
5G-enabled IoT applications that were impossible before:
| Application | Why 5G Enables It | Previous Limitation |
|---|---|---|
| Remote surgery | URLLC: <1ms haptic feedback | 4G: 30-50ms = surgeon feels lag = dangerous |
| Autonomous vehicles | URLLC: V2X communication at 200km/h | WiFi: range too short, 4G: latency too high for safety |
| Smart city (dense) | mMTC: 1M sensors per km² | 4G: ~100K devices/cell = congestion collapse |
| Precision agriculture | mMTC: thousands of sensors per field | LoRa: works but limited to 300 bytes/message |
| Digital twins | eMBB: real-time 3D model streaming | 4G: insufficient bandwidth for point clouds |
| Smart grid | URLLC + mMTC: instant fault detection across millions of nodes | Dedicated fiber = $$$, 4G = too slow for fault isolation |
Concrete example: smart city air quality network
Imagine deploying 10,000 air quality sensors (PM2.5, NO2, O3) across a city of 500 km². That's 20 sensors per km². Each reports every 5 minutes. With 5G mMTC:
The real value isn't raw capacity — it's the connection density. 10,000 devices can all be simultaneously connected without channel contention, sleeping most of the time, waking only to send their 64-byte payload.
Click each 5G category to see its latency, bandwidth, and device density characteristics visualized. Compare how the same physical network serves radically different needs.
You now understand the complete IoT stack: from sensor physics to cloud architecture, from MQTT packets to 5G network slicing, from edge processing to security hardening. Let's consolidate with decision frameworks you can use in real system design.
Protocol Selection Matrix — the cheat sheet for every IoT architect:
| Requirement | WiFi | BLE | LoRaWAN | Cellular | Thread/Zigbee |
|---|---|---|---|---|---|
| Range > 1km | No | No | Yes (15km) | Yes | No |
| Battery > 5yr | No | Maybe | Yes | No | Yes |
| Payload > 1KB | Yes | Yes | No (222B max) | Yes | Limited |
| Latency < 100ms | Yes | Yes | No (seconds) | Yes | Yes |
| Cost < $3 | Yes | Yes | Borderline | No | Yes |
| No infrastructure | Router needed | Phone needed | Gateway | Tower exists | Coordinator |
IoT Security Deployment Checklist:
Power Budget Calculator — will your battery last?
Example: ESP32 with 3000mAh battery, wakes 2s every 5 min:
To reach 1 year: either sleep longer (wake every 30 min = 465 days) or use LoRa (TX at 40mA for 100ms = 2+ years).
U.S. IoT Security Legislation:
| Law | Year | Scope | Key Requirements |
|---|---|---|---|
| California SB-327 | 2020 | All IoT sold in CA | Unique passwords, security appropriate to device function |
| Oregon HB 2395 | 2020 | All IoT sold in OR | Mirrors CA SB-327 requirements |
| IoT Cybersecurity Act | 2020 | US federal procurement | NIST compliance for government IoT purchases |
| NIST IR 8259 | 2020 | Guidelines (voluntary) | Baseline capabilities: ID, config, data protection, update |
| EU Cyber Resilience Act | 2024 | All digital products in EU | Security by design, 5-year update support, SBOM required |
Design Challenge: Design a city-wide air quality monitoring network for a city of 2 million people, 800 km².
Adjust active current, sleep current, duty cycle, and battery capacity. See projected battery life in real-time.
Connections:
| Want to Learn More About... | Go To |
|---|---|
| Real-time operating systems for embedded | RTOS & Scheduling (coming soon) |
| Machine learning at the edge | Transformers (attention for sequence data) |
| Sensor fusion algorithms | Kalman Filter (optimal state estimation) |
| Decision-making under uncertainty | MDPs (Markov Decision Processes) |
| Reinforcement learning for control | RL Algorithms (policy optimization) |