Chapters

33 Reference: IoT Code Pattern Library

prototyping
iot
code
pattern

33.1 Start With the Behavior to Prove

This section: Start With the Behavior to Prove — Picture a learner copying a sensor example that works once on a desk.

Treat Every Snippet as an Unproved Starting Point

Picture a learner copying a sensor example that works once on a desk. In the project, the pin differs, the reply arrives late, and a missing field causes a restart. Code that runs is not yet code that fits the new boundary.

Turn the desk-ready sensor snippet into a tested starting point.

  1. Illustrated scene: A copied sensor example works once on a desk.

    A copied sensor example works once on a desk.

  2. Illustrated scene: A new pin, late reply, or missing field can make it restart.

    A new pin, late reply, or missing field can make it restart.

  3. Illustrated scene: State the snippet's limits, then change one boundary and test it.

    State the snippet's limits, then change one boundary and test it.

  4. Illustrated scene: Reuse it only when the changed code proves the intended behavior.

    Reuse it only when the changed code proves the intended behavior.

A copied sensor snippet earns reuse by surviving one changed boundary.

A protocol is an agreed set of message and timing rules. Bluetooth Low Energy (BLE) is a short-range radio system. General purpose input output (GPIO) pins connect software to simple hardware signals. Hypertext Transfer Protocol (HTTP) carries web requests and replies. JavaScript Object Notation (JSON) is a text shape for named data. Message Queuing Telemetry Transport (MQTT) carries named messages through a service.

Choose one snippet and state its input, output, timing, resource, error, and safety assumptions. Run it unchanged and keep the result. Then alter one boundary, such as the pin, message field, delay, disconnect, or restart. Record the changed code and evidence that the intended behaviour still holds. Reject secret values or unsafe defaults before reuse.

This process does not make a snippet production-ready. Hardware, libraries, and field conditions differ. The deeper sections group patterns by task and show how to adapt, test, and review each boundary without mistaking copied code for proof.

A snippet should prove one behavior before it becomes project code. Run the original, change one boundary, and keep the output that shows the adaptation worked so the learner can separate reusable pattern from project-specific risk.

33.2 Learning Objectives

This section: Learning Objectives

  • Implement common IoT code patterns for sensor reading, MQTT messaging, and HTTP communication on ESP32
  • Apply power management techniques including deep sleep with timer and GPIO wakeup
  • Use JSON serialization and ring buffers for efficient IoT data handling
  • Configure BLE beacons and LoRa point-to-point communication for wireless IoT projects

33.3 Snippets Are Starting Points

This section: Snippets Are Starting Points — In Figure 33.1, A code snippet is useful when it shortens the first working path without hiding the engineering assumptions.

In Figure 33.1, A code snippet is useful when it shortens the first working path without hiding the engineering assumptions. The ESP32, Arduino core, PubSubClient, ArduinoJson, HTTPClient, Wire, Wi-Fi, BLE, and LoRa examples in this hub should be read as patterns: each one shows a small behavior, the library calls involved, and the checks a learner must repeat in their own circuit or network. A snippet is not a finished design record. It is a compact example of one boundary, such as a sensor read, a publish attempt, a JSON conversion, a sleep cycle, or a wireless advertisement.

Five-step route for reusing an IoT code snippet: run the original, verify local context, change one boundary, capture the acceptance check, and record before promoting to project code.
Figure 33.1: Safe snippet reuse keeps the example inside a route of boundaries, retries, tests, and evidence rather than treating pasted code as proof.

In Figure 33.1, The right question is not "can I paste this?" The right question is "which assumptions must I confirm before this becomes project code?" Pins, voltage levels, I2C addresses, MQTT broker settings, JSON buffer sizes, sleep intervals, Wi-Fi reconnect behavior, and battery current all depend on the final hardware and deployment context. Even a short DHT22 example carries assumptions about sampling interval and invalid reads. A PubSubClient example carries assumptions about broker reachability, keepalive timing, topic policy, client identity, and payload length. A deep-sleep example carries assumptions about wake source, boot reason, sensor warm-up, and whether the active current pulse is acceptable for the battery.

  • Use the snippet for shape: control flow, library setup, error handling, and common API calls.
  • Verify the local context: board revision, pins, sensor supply, payload size, broker policy, firmware version, and library version.
  • Promote only after testing: run the snippet on target hardware, record assumptions, and add a regression check or bench note before reusing it.

The library is therefore organized for transfer, not blind copying. Start with the smallest snippet that matches the behavior you need, then keep the acceptance check visible: serial output, a broker message, an HTTP status, an I2C scan, a wake reason, a measured current trace, or a repeatable host test. When that proof is missing, the snippet is still a learning aid, but it has not yet become project code.

33.4 Adapt One Boundary at a Time

This section: Adapt One Boundary at a Time — The safest way to reuse snippets is to change one boundary, run it, and inspect the result before moving to the next boundary.

The safest way to reuse snippets is to change one boundary, run it, and inspect the result before moving to the next boundary. For a DHT22 or analog sensor snippet, first confirm wiring, sensor power, sampling interval, ADC range, and invalid-read behavior. For I2C scanner code, confirm pullups, SDA/SCL pins, bus speed, address conflicts, and whether Wi-Fi is using ESP32 ADC or bus resources. For MQTT or HTTP snippets, confirm client ID, topic policy, QoS choice, timeout, retry delay, TLS need, and payload size. If several of those change at once, a failure no longer tells you where the real mismatch lives.

Use concrete tooling around the copy step. PlatformIO or Arduino IDE can pin board and library versions, which keeps a working example reproducible after the next library update. Serial Monitor output catches boot loops, missing credentials, bad pins, and sensor read failures quickly. Logic-analyzer traces can prove an I2C or SPI transaction is actually leaving the board. Broker logs and Wireshark captures show whether MQTT, HTTP, DNS, TCP, and TLS are failing in the firmware, the network, or the server. Measured current traces are the only reliable way to check whether a sleep snippet saves the power it claims to save.

  1. Run the original snippet first. Confirm it compiles and produces the expected serial, packet, or sensor output.
  2. Change one project parameter. Adjust pin, interval, endpoint, topic, credential, payload, or power mode separately.
  3. Capture the acceptance check. Save the serial log, broker message, current trace, bus scan, or API response that proves the adaptation worked.

As the snippet grows, move magic values out of the example body and into a visible configuration boundary: pins, topics, endpoints, thresholds, retry limits, and sleep intervals should be easy to review. ArduinoJson Assistant can size JSON documents before heap pressure appears on the board. PubSubClient buffer settings should be checked before a payload is blamed on the broker. ESP32 deep-sleep wake reasons should be logged before a wakeup path is trusted. FreeRTOS task timing should be inspected when the example moves from a single loop into concurrent sensor, radio, and display work.

A good reuse record is short but specific: source snippet, hardware revision, library versions, changed parameters, observed output, and the remaining risk. That record lets another learner decide whether the snippet still fits their board or whether it needs a fresh adaptation pass.

33.5 Snippets Hide State Boundaries

This section: Snippets Hide State Boundaries — Small snippets look linear, but IoT behavior is stateful.

Small snippets look linear, but IoT behavior is stateful. A reconnect loop crosses Wi-Fi association, DNS, TCP, MQTT session state, broker policy, keepalive timing, and payload retry behavior. A deep-sleep example crosses wake source configuration, RTC memory, boot reason, sensor warm-up, radio startup, and battery pulse current. A JSON parser crosses buffer sizing, message schema, missing fields, numeric range, and heap pressure. Each boundary can succeed in isolation while the whole device still fails under timing, network, or power pressure.

The hidden boundary is ownership. The snippet owns a tiny behavior. The learner owns hardware limits, credentials, timing, error handling, security, logging, and maintainability. A production path must replace placeholder credentials, public brokers, blocking loops, unbounded retries, and demo delays with project-specific configuration, timeouts, observability, and failure handling. It must also make security decisions explicit: credentials should not be hard-coded into examples that become repository code, TLS settings should not be copied without understanding certificate and endpoint policy, and diagnostic logs should not leak secrets while trying to explain a connection failure.

The state-machine view helps explain why. A reliable device is usually not "read sensor, publish, delay" forever. It has boot, configure, sample, validate, publish, backoff, sleep, fault, and recovery states. Interrupts, timers, queues, and network callbacks may enter that state machine at awkward times. Without bounded retries, a radio outage can turn into a battery drain. Without input validation, one malformed payload can poison downstream logic. Without an evidence record, a later maintainer cannot tell whether a value came from a tested requirement, a copied demo, or a temporary experiment.

This is why the library is a learning hub, not a certification source. The snippet gets a learner to a measurable behavior; the project tests decide whether that behavior is reliable, secure, and efficient enough to keep. The best under-the-hood outcome is not more code. It is a clear separation between reusable pattern, project-specific configuration, measured acceptance check, and the failure paths that still need design attention.

This section:

For Beginners: Code Snippet Library

A code snippet is a small piece of programming code that demonstrates a specific task, such as reading a temperature sensor or sending data over Wi-Fi. This library contains 15 searchable example snippets for Arduino or ESP32 projects; choose one as a starting pattern, adapt it, and test it on the selected board.

This section:

This section:

In 60 Seconds

A searchable collection of 15 IoT code snippets covering sensors, MQTT, HTTP, BLE, LoRa, deep sleep, and data handling. Filter by category, difficulty, or keyword to find a starting pattern, then verify it on your selected board and library versions.

This section:

This section:

Quick Check: Responsible Snippet Use

This section:

Putting Numbers to It

Context: ESP32 deep sleep with 5-minute timer wakeup for battery-powered sensor. Comparing active vs sleep power.

Formula: Battery life = Battery capacity (mAh)Average current draw (mA)\frac{\text{Battery capacity (mAh)}}{\text{Average current draw (mA)}}

Worked example: 2,000 mAh battery. Without sleep: Active 100 mA continuously = 2000100=20\frac{2000}{100} = 20 hours. With deep sleep: Active 100 mA for 10 s every 5 min (96.7% sleep at 10 µA). Average: (100 mA×10300)+(0.01 mA×290300)=3.33+0.0097≈3.34(100 \text{ mA} \times \frac{10}{300}) + (0.01 \text{ mA} \times \frac{290}{300}) = 3.33 + 0.0097 \approx 3.34 mA. Battery life: 20003.34≈600\frac{2000}{3.34} \approx 600 hours = 25 days (30× improvement).

33.6 Code Snippet Library

This section: Code Snippet Library — Treat the library as a set of controlled starting states, not finished firmware.

Treat the library as a set of controlled starting states, not finished firmware. Begin with the snippet whose hardware, protocol, and expected output most closely match the current test. Run it unchanged to establish a baseline; then alter one boundary such as a pin, interval, endpoint, or power mode and repeat the observation. This sequence keeps a failed build attributable to one change and turns adaptation into evidence the next developer can replay.

15 Example Code Snippets

Browse or search these 15 example IoT code snippets. Each includes an explanation of key concepts and assumptions to verify.

How to Use This Library
  1. Start from a relevant example snippet and check its board and library assumptions.
  2. Adapt one parameter at a time (pin, interval, endpoint, power mode).
  3. Validate behavior on hardware before adding complexity.

33.7 Snippet Browser

This section: Snippet Browser


33.8 Quick Reference Tables

This section: Quick Reference Tables

33.8.1 Common Pin Configurations

ModuleSPI (SCK/MISO/MOSI/SS)I2C (SDA/SCL)UART (TX/RX)
ESP32 DevKit18/19/23/521/221/3
ESP32-S312/13/11/108/943/44
ESP826614/12/13/154/51/3
Arduino Uno13/12/11/10A4/A50/1

33.8.2 Library Quick Reference

TaskLibraryInstall Command
MQTTPubSubClientpio lib install "PubSubClient"
JSONArduinoJsonpio lib install "ArduinoJson"
HTTPHTTPClientBuilt-in (ESP32)
LoRaLoRapio lib install "LoRa"
BLEESP32 BLEBuilt-in (ESP32)
Wi-FiWi-FiBuilt-in

33.9 Common Reference Patterns

This section: Common Reference Patterns — These short reference patterns complement the snippet library above with compact, print-friendly code idioms.

These short reference patterns complement the snippet library above with compact, print-friendly code idioms.

33.9.1 Sensor Reading Pattern

# Pseudo-code for robust sensor reading
def read_sensor_with_retry(sensor, max_retries=3):
    for attempt in range(max_retries):
        try:
            value = sensor.read()
            if is_valid(value):
                return value
        except SensorError:
            time.sleep(0.1 * (2 ** attempt))  # Exponential backoff
    return None  # Or raise exception

# Moving average filter
class MovingAverage:
    def __init__(self, window=10):
        self.window = window
        self.values = []

    def add(self, value):
        self.values.append(value)
        if len(self.values) > self.window:
            self.values.pop(0)
        return sum(self.values) / len(self.values)

33.9.2 MQTT Connection Pattern

# Robust MQTT connection with reconnection
def connect_mqtt(client, broker, port=1883):
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            client.subscribe("device/+/command")
        else:
            print(f"Connection failed: {rc}")

    def on_disconnect(client, userdata, rc):
        while True:
            try:
                client.reconnect()
                break
            except:
                time.sleep(5)

    client.on_connect = on_connect
    client.on_disconnect = on_disconnect
    client.connect(broker, port, keepalive=60)

33.9.3 Deep Sleep Pattern

# ESP32 deep sleep with wake sources
import machine
import esp32

def enter_deep_sleep(seconds):
    # Configure wake sources
    # For a classic ESP32 board that exposes GPIO33, connect a normally-open button from GPIO33 to GND; provide a board-verified pull-up that remains effective during deep sleep.
    esp32.wake_on_ext0(pin=machine.Pin(33, machine.Pin.IN, machine.Pin.PULL_UP), level=esp32.WAKEUP_ALL_LOW)

    # Set timer wake
    machine.deepsleep(seconds * 1000)

# Check wake reason
wake_reason = machine.wake_reason()
if wake_reason == machine.PIN_WAKE:
    handle_button_press()
elif wake_reason == machine.RTC_WAKE:
    send_sensor_data()

33.10 Contributing Snippets

This section: Contributing Snippets — Have a useful code snippet?

Have a useful code snippet? Follow this format:

**Title**: Brief descriptive title
**Category**: Sensors/Actuators/MQTT/HTTP/BLE/LoRa/Power/Data/Security
**Platform**: Arduino/ESP32/ESP8266/Raspberry Pi
**Difficulty**: Beginner/Intermediate/Advanced
**Tags**: relevant, searchable, keywords
**Description**: What this snippet does
**Code**: Working, tested code
**Explanation**: Key concepts and gotchas
Match Code to Hardware

The Mistake (illustrative scenario): A developer copied an ESP32 MQTT example directly from this library, deployed to 50 devices, and found 30% failed to connect. The code worked perfectly in testing.

What Went Wrong:

// Snippet showed generic ESP32 pins
#define DHT_PIN 4    // Works on ESP32 DevKit V1
#define LED_PIN 2    // Built-in LED on most boards

The Problem: Developer used ESP32-S2 boards where: First, ESP32-S2 boot strapping uses GPIO0, GPIO45, and GPIO46; GPIO2 is not a boot-mode strap. Next, GPIO 4 has an ADC channel assignment that must be checked against the sensor and exact board. Then, the built-in LED pin depends on the exact board model.

Impact:

First, pin behavior and boot symptoms must be verified against the exact board documentation and measured on the affected hardware. Next, Debugging took 6 hours to identify a hardware variant mismatch.

How to Avoid:

First, Check your exact board model before copying pins:.

// Example only: define a verified board identifier and pin map for your exact board.
#if defined(ESP32_DEV_KIT_V1)
  #define DHT_PIN 4
  #define LED_PIN 2
#elif defined(ESP32_S2_MINI)
  #define DHT_PIN 1
  #define LED_PIN 15  // Verify for the exact ESP32-S2 board model
#else
  #error "Select and verify the exact board pin map"
#endif

First, Test on one device first: Never deploy untested code to multiple devices.

First, Read the datasheet: Verify every GPIO pin for your specific board (not “ESP32 in general”).

First, Document hardware dependencies: Add comments like // Tested on ESP32 DevKit V1 only.

Cost of this mistake: 6 hours debugging + 30 device replacements (wrong board ordered) + project delay = ~$2,000 in wasted time and materials.

Lesson: Code snippets are starting points, not copy-paste solutions. Hardware matters.

This section:

Map Code Categories to Tasks

This section:

This section:

Use Code Snippets in Projects

Place these steps in the correct order for adapting library snippets.

This section:

This section:

Key Takeaway

Fifteen example code snippets provide starting patterns for common IoT tasks; verify pin assignments and library versions for your specific board before deploying.

This section:

Common Pitfalls

This section: Common Pitfalls

Know Snippet Parameters

Code snippets use hardcoded values (broker address, port, QoS level, topic names) that must be customized for each deployment. Copying and running without adapting these parameters causes connection failures, incorrect behavior, or unintended data routing. Always read each snippet’s comments to understand which values require customization.

Harden Snippets Before Production

Library snippets prioritize clarity over security — they often use plaintext connections, hardcoded credentials, or skip certificate verification. Never deploy library code directly to production. Treat snippets as starting points requiring TLS configuration, secure credential storage, and input validation before deployment.

Check Snippet Dependency Versions

A snippet using paho-mqtt==1.x APIs may fail with paho-mqtt==2.x which introduced breaking changes. Always check the library version requirements documented in each snippet and test in an isolated environment before integrating into your project.

Knowledge Check
Code Challenge

33.12 Summary

This section: Summary — This chapter collects reusable code snippets for IoT learning tasks.

This chapter collects reusable code snippets for IoT learning tasks. Use snippets as starting points for experiments, then adapt, test, and document the assumptions before using them in a project.

Find help

3 reviewed answers.

Where should I start in a module?

Open the module page from the sidebar to see its chapters in order. Use the module map to return to a topic you need.

Modules and paths

Reviewed

What can I try when a project does not work?

Check the symptom, then work through the diagnostic steps. Keep the error message and the smallest example that reproduces it.

When you are stuck

Reviewed

How do interactive examples work?

Use the interactive guide to check how examples and simulations work before changing your project.

Interactive examples guide

Reviewed