Chapters

33 Reference: IoT Code Pattern Library

prototyping
iot
code
pattern

33.1 Start With the Behavior to Prove

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.

Telemetry means readings and status sent by a remote device. 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

After completing this chapter, you will be able to:

  • 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

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

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

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.

For Beginners: Code Snippet Library

A code snippet is a small, ready-to-use piece of programming code that solves a specific task — like reading a temperature sensor or sending data over Wi-Fi. This library collects over 100 tested snippets that you can copy directly into your IoT projects on Arduino or ESP32 platforms. Think of it as a recipe book for IoT programming: find the recipe you need, copy it, and adapt it to your project.

In 60 Seconds

A searchable, copy-paste-ready collection of 100+ tested IoT code snippets covering sensors, MQTT, HTTP, BLE, LoRa, deep sleep, and data handling for Arduino and ESP32 platforms. Filter by category, difficulty, or keyword to find exactly the code pattern you need.

Quick Check: Responsible Snippet Use

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 10s every 5 min (99.9% sleep at 10 µA). Average: (100 mA×10300)+(0.01 mA×290300)=3.33+0.00973.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.34600\frac{2000}{3.34} \approx 600 hours = 25 days (30× improvement).

33.6 Code Snippet Library

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.

100+ Ready-to-Use Code Snippets

Browse or search our curated collection of IoT code snippets. Each snippet is tested, documented, and includes explanations of key concepts.

How to Use This Library
  1. Start from a tested snippet, not a blank file.
  2. Adapt one parameter at a time (pin, interval, endpoint, power mode).
  3. Validate behavior on hardware before adding complexity.

33.7 Snippet Browser


33.8 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

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
    esp32.wake_on_ext0(pin=machine.Pin(0), 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.TIMER_WAKE:
    send_sensor_data()

33.10 Contributing Snippets

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: 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, GPIO 2 is reserved for strapping pin (boot mode selection). Next, GPIO 4 has different ADC channel assignment. Then, LED is on GPIO 15, not GPIO 2.

Impact:

First, Devices that successfully booted had random GPIO 4 sensor readings (ADC conflict). Next, Some devices entered boot loop (GPIO 2 LED initialization during boot). Then, Debugging took 6 hours to identify hardware variant mismatch.

How to Avoid:

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

// GOOD: Board-specific definitions
#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  // ESP32-S2 built-in LED
#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.

Map Code Categories to Tasks

Use Code Snippets in Projects

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

Key Takeaway

Tested, well-documented code snippets accelerate IoT development by providing proven patterns for common tasks — always verify pin assignments and library versions for your specific board before deploying.

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 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.