Chapters

12 Device State Machines: Transition Contracts

design-patterns
state
machine

12.1 Start With the Decision

This section: Start With the Decision — A transition contract states when a device may change state.

A transition contract states when a device may change state. An event asks for the change. A guard is a condition that must pass before an action runs. A timeout sets the limit for waiting. A transition contract connects current state, event, guard, action, target state, timeout, and log output.

12.2 Route Overview

This section: Route Overview — This is part 2 of 2.

This is part 2 of 2. Review Device State Machines: Modes and Safety for the preceding evidence.

12.3 Learning Objectives

This section: Learning Objectives

  • Define transition contract with explicit inputs, errors, and change rules.
  • Validate references with a concrete scenario and pass criteria.

12.4 Chapter Roadmap

This section: Chapter Roadmap

  • Transition Contract
  • Knowledge Check: Transition Review
  • Pattern 1: Connection Lifecycle
  • Knowledge Check: Connection Lifecycle
  • Pattern 2: Sampling and Power
  • Pattern 3: Actuator Safety
  • Safety Review Rule
  • Knowledge Check: Safety Recovery
  • Pattern 4: Cloud Shadow Reconciliation
  • Checkpoint: Reusable IoT Patterns
  • Hierarchical and Parallel State Machines
  • Knowledge Check: State Explosion
  • Implementation Pattern
  • Knowledge Check: Rejected Events
  • Architecture Review Checklist
  • Checkpoint: Implementation and Review
  • Common Pitfalls
  • Label the Diagram
  • Code Challenge
  • Summary
  • Key Takeaway
  • Knowledge Check
  • Quiz: State Machine Patterns
  • Interactive Quiz: Match State Machine Pattern Concepts
  • Interactive Quiz: Sequence the Steps
  • Try It Yourself: State Machine Design Record
  • References
  • What’s Next
  • Navigation

12.5 Transition Contract

This section: Transition Contract — Every transition should be readable enough that firmware, cloud, QA, and operations teams can review it together.

Every transition should be readable enough that firmware, cloud, QA, and operations teams can review it together.

Before writing a transition table, inspect Figure 12.1 to see where eligibility, side effects, and evidence belong. The visual matters because mixing those responsibilities makes retries unsafe and field failures difficult to reconstruct.

A transition contract connects current state, event, guard, action, target state, timeout, and log output
Figure 12.1: A transition contract connects current state, event, guard, action, target state, timeout, and log output
  1. Blueprint Bina: Bina stands inside one clearly bounded device-state room.

    Bina starts from the device current state.

  2. Blueprint Bina: A message arrives and lights one candidate door from that room.

    An event points to a possible transition.

  3. Blueprint Bina: Bina checks the event against a shield-shaped condition at the door.

    The guard decides whether that door may open.

  4. Blueprint Bina: Beyond the open door, Bina operates one control lever.

    The action runs only on the allowed path.

  5. Blueprint Bina: Bina and the device settle in a different marked room after the action.

    The device enters its new stable state.

  6. Blueprint Bina: A clock opens a separate safe return door from a waiting room and drops a record into a log tray.

    A timeout gives a waiting state a logged exit.

Current state plus an event chooses a path, a guard decides, an action runs, and the device reaches a stable target; timeout must offer a logged escape.

In Figure 12.1, Current state and Event select a candidate transition; Guard decides whether that event is permitted before Action performs work. Only then does Target name the new stable state. Check Timeout for the missing-event path and Log for the record of what occurred. That ordering supplies the test structure used throughout the chapter: given a state and event, assert the guard result, action, target, timer behavior, and audit output. The diagram completes the evidence for Transition Contract.

Current state The only mode where this transition is valid.

Event The external or internal signal that asks for a transition, such as timer expired, command received, packet acknowledged, sensor fault, or watchdog warning.

Guard A condition that must be true before the transition is allowed, such as battery above threshold, door closed, authorization valid, or retry budget remaining.

Action The work performed during the transition, such as enabling a radio, starting a timer, writing a command record, logging a fault, or disabling an actuator.

Target state The next valid mode. For safety paths, this should often be SAFE_OFF, ERROR, or LOCKOUT.

Timeout and log Any state that waits must have a timeout, and every meaningful transition should leave enough trace data for field diagnosis.

TRANSITIONS = {
    ("IDLE", "sample_timer", "battery_ok"): ("WAKE_SENSOR", "power_sensor"),
    ("WAKE_SENSOR", "sensor_ready", "within_deadline"): ("SAMPLE", "read_sensor"),
    ("SAMPLE", "sample_ok", "network_available"): ("TRANSMIT", "send_message"),
    ("SAMPLE", "sample_ok", "network_unavailable"): ("BUFFER", "store_locally"),
    ("TRANSMIT", "ack_received", "always"): ("SLEEP", "schedule_next_wake"),
    ("TRANSMIT", "deadline_expired", "always"): ("BUFFER", "store_locally"),
    ("ANY", "watchdog_warning", "always"): ("SAFE_OFF", "disable_outputs"),
}

12.6 Pattern 1: Connection Lifecycle

This section: Pattern 1: Connection Lifecycle — A connection state machine protects the device from chaotic reconnect behavior and gives the cloud a clear view of whether the device is online, degraded, or intentionally disabled.

A connection state machine protects the device from chaotic reconnect behavior and gives the cloud a clear view of whether the device is online, degraded, or intentionally disabled.

ESP32 Wi-Fi states narrated tour

Play silently with captions on provisional storyboard timing; narration audio is pending. Production pacing is not protocol time. Choose Reduced motion for a complete still at each beat.

Play the tour to open the workbench. Pause, replay a beat, or read the full transcript below. Situations marked CANNOT SHOW keep the existing frame and provide captions only.

Full transcript — ESP32 Wi-Fi states (8 beats)

B1 — Bound connection failure
You are keeping a battery powered sensor connected long enough to upload its measurements. The wireless access point has become unavailable. Repeated scans use battery power while the upload waits. Your job is to give connection failure a controlled exit instead of draining the battery through continuous attempts.

Model caption: A battery sensor needs an upload opportunity. An unavailable access point calls for controlled retries to avoid continuous scanning.

B2 — Guard and timeout contract
A state machine describes the device's current mode and the changes it allows. A guard is a condition that must pass before an action runs. A timeout limits how long a waiting state can last.

Model caption: An event requests a change; a guard must pass before an action; a timeout limits waiting.

B3 — Connection success path
For a successful connection, starting the wireless interface triggers a connection attempt. The radio scans for its configured network, then associates with the access point. Next it waits for an Internet Protocol address, called an IP address. Receiving that address resets the retry count and starts application traffic.

Model caption: Start → scan → association → address acquisition → Online. Receiving an Internet Protocol address resets retries and starts application traffic.

B4 — Unavailable access point
For your sensor, the access point is unavailable, so the scan times out instead. The device enters the disconnected state and inspects the failure reason. In the outage example, the retry limit is four and the backoff base is four seconds. Backoff means waiting before another attempt.

Model caption: The scan times out. Inspect the missing-access-point reason; the preset allows four retries with a four-second backoff base.

B5 — First retry arithmetic
Calculate the first retry delay. Start with attempt number one and subtract one, giving zero. Keep the larger of zero and zero. Two raised to zero is one. Multiply the four second base by one, giving four seconds. Choose the smaller of sixty seconds and four seconds. The first retry delay is four seconds.

Model caption: Attempt one: one minus one is zero; maximum with zero stays zero; two to zero is one; four times one is four; minimum with sixty is four seconds.

B6 — Retry guard and fallback
The retry guard allows another attempt only while the retry count is less than four. The handler waits, increases the count, and tries connecting again. The model summarizes exhausted retries by moving to fallback. For a battery device, fallback can mean deep sleep followed by another attempt later.

Model caption: The retry condition is count less than four. Exhaustion leads to fallback; deep sleep and a later attempt are possible battery-device behavior. The model omits the intervening retries.

B7 — Faster scans misconception
The misconception is that scanning faster will fix an unavailable access point. Faster attempts cannot supply the missing access point. Continuous scanning consumes power; a delayed retry gives the failure a controlled response, and the retry limit provides an exit.

Model caption: Faster scans cannot supply a missing access point. Continuous scans use power; delay and a retry limit give failure a controlled response.

B8 — Waiting time and exit
Give connection failure a waiting time and an exit, so recovery has limits.

Model caption: Give connection failure a waiting time and an exit, so recovery has limits.

Offline Radio or client is inactive. Credentials may be missing, provisioning may be incomplete, or a retry delay may be running.

Connecting The device activates the network, starts a bounded connection attempt, and waits for success or timeout.

Online The session is established. Heartbeats, subscriptions, telemetry, and command channels are active.

Reconnecting The previous connection failed. Retry uses backoff and jitter while the device keeps local work bounded.

Degraded The device cannot reach the cloud but can still sample, buffer, or run local safety rules.

Required Transitions

connect_requested, connected, connection_timeout, heartbeat_lost, retry_timer, credentials_invalid, disable_requested, and local_mode_required.

Review Trap

Do not reconnect every device at the same fixed interval. Connection retries need backoff, jitter, and a maximum local buffer policy.

12.7 Pattern 2: Sampling and Power

This section: Pattern 2: Sampling and Power — Sampling state machines keep energy, latency, and data quality decisions visible.

Sampling state machines keep energy, latency, and data quality decisions visible. They also prevent work from happening in the wrong power mode.

Energy claims need a time sequence, not just a list of modes. Consult Figure 12.2 to see when the radio leaves Low Power, how long it waits for traffic or acknowledgement, and where it returns to sleep. This diagram tests Pattern 2: Sampling and Power.

A duty-cycle state machine and timing view follow the radio from low power through activity and back to sleep.
Figure 12.2: Sensor duty cycling state machine with listen, receive, transmit, and sleep states

Trace Figure 12.2 from Sleep (Low Power) through Listen. A received packet moves into Receive, whereas local data takes the Transmit path and waits at Wait ACK before the cycle can close. Compare that active interval with the Energy Savings timeline below it: the long sleep band, not the mere presence of a sleep state, is what reduces average power. The pattern therefore connects transition timing and acknowledgement policy to the battery-life claim.

Sleep

Only wake sources remain active. The next event may be a timer, interrupt, command, or safety alarm.

Wake

Power rails, clocks, sensors, and communication interfaces are enabled in a known order.

Sample

The device reads sensors, validates values, and applies quality checks.

Process

The device filters, compresses, aggregates, or classifies data while the active budget remains available.

Transmit

The device sends data if the network is available and a deadline remains.

Buffer

If transmission is not possible, bounded local storage preserves the sample and the device returns to sleep.

Power estimates belong in a design record using the selected hardware datasheets and measured firmware behavior. Avoid copying generic current and battery-life numbers into the state-machine pattern itself.

12.8 Pattern 3: Actuator Safety

This section: Pattern 3: Actuator Safety — Actuator state machines need stricter recovery rules than telemetry workflows.

Actuator state machines need stricter recovery rules than telemetry workflows. The safe state should be easy to enter, and dangerous states should be hard to re-enter accidentally.

Safe Off Outputs disabled. This is the default after reset, unknown state, watchdog warning, or serious fault.

Armed Preconditions are satisfied, but motion or output has not started. Guards are checked again before activation.

Active The actuator is moving or energized. Time limits, sensor checks, and emergency events are monitored continuously.

Limited The system is still operating but reduced. It may slow, derate, or move to a safer position.

Emergency Stop Output stops immediately and the fault is logged. Recovery may require inspection.

Lockout Automatic recovery is blocked. A qualified operator or explicit service workflow must reset the system.

Safety Review Rule

If a transition can energize an actuator, it needs a guard. If a fault can leave the actuator energized, it needs a hardware or independent protection path, not only application logic.

12.9 Pattern 4: Cloud Shadow Reconciliation

This section: Pattern 4: Cloud Shadow Reconciliation — Cloud shadows, device twins, and desired-reported property models are state reconciliation patterns.

Cloud shadows, device twins, and desired-reported property models are state reconciliation patterns. They work best when the device treats cloud instructions as events and reports its actual state honestly.

Cloud reconciliation becomes unsafe when desired and observed state are treated as one value. Use Figure 12.3 to separate the application’s request from the device’s report and to locate the delta that drives a legitimate transition. This diagram tests Pattern 4: Cloud Shadow Reconciliation.

AWS device shadow diagram showing a physical device, device shadow document, application, and reported, desired, and delta state fields
Figure 12.3: AWS device shadow state reconciliation

In Figure 12.3, the Application writes a desired value such as Set Temperature, while the Physical Device publishes reported state through the named MQTT Topics. The delta exists only while those values differ; it is not proof that the actuator already changed. This distinction carries the running transition contract into the cloud: version the request, apply it idempotently on the device, and acknowledge the resulting reported state before declaring reconciliation complete. The diagram completes the evidence for Pattern 4: Cloud Shadow Reconciliation.

Desired State

The cloud records an intended configuration or command. The device should validate it before applying it.

Applying

The device has accepted a desired change and is attempting local work.

Reported State

The device publishes what actually happened, including version, timestamp, and result.

Rejected State

The device rejects an invalid, stale, unsafe, or unsupported desired state and reports why.

Never let the cloud shadow pretend an unsafe command succeeded. Report rejected and degraded states explicitly so operators can distinguish command failure from delayed connectivity.

This section:

Blueprint Bina, Architecture and system-design domain expertCheckpoint: Reusable IoT Patterns

You now know:

  • Connection lifecycle machines bound retry behavior with backoff, jitter, budgets, and degraded local modes.
  • Sampling and power machines protect battery life by returning to sleep when transmit or validation fails.
  • Actuator and cloud-shadow machines must report rejected, unsafe, stale, and lockout behavior honestly.

This section:

12.10 Hierarchical and Parallel State Machines

This section: Hierarchical and Parallel State Machines — Simple FSMs are enough for many devices.

Simple FSMs are enough for many devices. When the state count grows, use hierarchy or parallel regions rather than multiplying every combination into a new flat state.

One flat machine would multiply every link, buffer, command, and service mode into an unmanageable cross-product. Inspect Figure 12.4 to see how independent machines retain their own states while exchanging a small set of explicit events.

Separate link, buffer, command, and service state machines coordinate through event contracts instead of one flat cross-product state model
Figure 12.4: Coordinating separate state machines with events

Read Figure 12.4 across the Link machine, Buffer machine, Command machine, and Service machine rather than inventing one combined state. When the link changes from offline to online, it can emit an event that lets the buffer flush without rewriting command logic. A separate command_expired event allows the command machine to reject stale work even if the service is otherwise healthy. The event contracts preserve coordination while keeping each machine testable, which is the reason to introduce parallel state machines here.

Hierarchical States

Put shared behavior in parent states. For example, CONNECTED can contain IDLE, SAMPLING, and TRANSMITTING, while connection-loss handling remains defined once at the parent level.

Parallel Regions

Keep independent concerns separate. A device may have one state machine for connectivity and another for actuator safety. Do not combine them into every possible cross-product state.

State Explosion

If every new feature doubles the state count, the model is doing too much in one flat machine.

Shared Events

Global events such as watchdog warning, shutdown, factory reset, or emergency stop should have reviewed priority over local transitions.

12.11 Implementation Pattern

This section: Implementation Pattern — A table-driven state machine is often easier to review and test than a long chain of conditional branches.

A table-driven state machine is often easier to review and test than a long chain of conditional branches.

from dataclasses import dataclass


@dataclass(frozen=True)
class Transition:
    source: str
    event: str
    guard: str
    target: str
    action: str


class DeviceStateMachine:
    def __init__(self, initial_state, transitions, actions, guards):
        self.state = initial_state
        self.transitions = transitions
        self.actions = actions
        self.guards = guards

    def dispatch(self, event, context):
        candidates = [
            t for t in self.transitions
            if t.event == event and t.source in (self.state, "ANY")
        ]
        for transition in candidates:
            guard = self.guards.get(transition.guard, lambda _: False)
            if guard(context):
                previous = self.state
                self.actions[transition.action](context)
                self.state = transition.target
                context.log_transition(previous, event, self.state)
                return self.state
        context.log_rejected_event(self.state, event)
        return self.state

Why This Helps

The transition table is reviewable, testable, and easy to compare with a diagram or design record.

What It Does Not Solve

You still need good guards, timeout events, action idempotency, safe defaults, and tests for rejected events.

12.12 Architecture Review Checklist

This section: Architecture Review Checklist — Use this checklist before implementing firmware, cloud workflows, or device-twin reconciliation.

Use this checklist before implementing firmware, cloud workflows, or device-twin reconciliation.

State inventory Each state has a clear purpose, allowed actions, entry behavior, exit behavior, and owner.

Event inventory External events, internal timers, watchdog warnings, cloud commands, operator actions, and sensor faults are all named.

Transition contract Each transition defines source, event, guard, target, action, timeout, and log behavior.

Invalid events The design says whether each invalid event is ignored, rejected, logged, escalated, or routed to safe state.

Waiting states Every waiting state has timeout and cancellation behavior.

Safety states Unsafe outputs default to safe off after reset, unknown state, watchdog warning, or serious fault.

Persistence The design identifies which state is persisted across reboot and which state must be recomputed.

Observability Transition logs include previous state, event, guard result, target state, timestamp, firmware version, and correlation ID when available.

Tests Unit tests cover happy paths, invalid events, timeout paths, power loss, repeated commands, and recovery from persisted state.

This section:

Blueprint Bina, Architecture and system-design domain expertCheckpoint: Implementation and Review

You now know:

  • Table-driven dispatch keeps diagrams, code, logs, and tests aligned around the same transition rows.
  • Rejected events are not leftovers; they are explicit behavior that must be logged or routed safely.
  • The review checklist checks ownership, events, guards, waiting states, safety states, persistence, observability, and tests before release.

This section:

12.13 Common Pitfalls

This section: Common Pitfalls

  1. Blueprint Bina crosses out a state stuck at an endless waiting loop in red; the same panel adds a clock limit leading to a named safe failure path.

    Wrong: A state can wait forever. Add a time limit and a safe failure path.

Correct the belief that a state may wait forever for a packet, sensor, or reply.

Hidden State in Flags

Many flags can create impossible combinations. Replace them with named states or separate parallel state machines.

No Timeout Transition

Waiting forever for a packet, sensor, or acknowledgement is a field failure waiting to happen.

Unsafe Automatic Recovery

Some faults should require inspection, manual reset, or a service workflow before reactivation.

Logging Only Errors

Transition history matters before the error. Log meaningful normal transitions too, at a bounded rate.

Diagram and Code Drift

If the diagram and transition table are maintained separately, they will diverge. Prefer one source of truth.

Flat Model Overgrowth

Large flat models become unreadable. Use hierarchy, parallel regions, or split machines by concern.

12.14 Summary

This section: Summary — Test how the device handles timeouts, saved states, and recovery.

Test how the device handles timeouts, saved states, and recovery. Record the next state for each event.

12.15 Key Takeaway

This section: Key Takeaway — Use a state machine whenever device behavior depends on mode, history, safety, or connectivity.

Use a state machine whenever device behavior depends on mode, history, safety, or connectivity. Explicit states, events, guards, actions, timeouts, and rejected-event logs make field failures easier to prevent and diagnose.

12.16 Knowledge Check

This section: Knowledge Check

12.17 Try It Yourself: State Machine Design Record

This section: Try It Yourself: State Machine Design Record — Choose one IoT workflow and complete a design record before coding.

Choose one IoT workflow and complete a design record before coding.

state_machine: device-command-lifecycle
initial_state: SAFE_OFF
states:
  - SAFE_OFF
  - ARMED
  - ACTIVE
  - LIMITED
  - EMERGENCY_STOP
  - LOCKOUT
events:
  - arm_requested
  - start_requested
  - stop_requested
  - limit_exceeded
  - watchdog_warning
  - inspected_reset
transition_example:
  source: ACTIVE
  event: limit_exceeded
  guard: sensor_reading_is_valid
  action: reduce_output_and_log_fault
  target: LIMITED
  timeout: move_to_emergency_stop
invalid_event_policy:
  in_lockout: reject_and_log
observability:
  transition_log_fields:
    - previous_state
    - event
    - guard_result
    - target_state
    - timestamp
    - firmware_version
tests:
  - invalid_event_in_each_state
  - timeout_from_each_waiting_state
  - reboot_from_each_persisted_state
  - emergency_stop_priority

Review the record with someone who owns operations or safety. The best state-machine reviews find missing events before they become field failures.

12.18 What’s Next

This section: What’s Next

Design Patterns Hub

Return to the module hub and compare state-machine patterns with the rest of the IoT architecture pattern set.

SOA Resilience Patterns

Connect timeout, fallback, circuit-breaker, and retry behavior to explicit state transitions.

WSN Duty Cycling

Deepen the sampling and power-management side of state-machine design.

Digital Twins

Apply reported and desired state ideas to cloud and device synchronization.

12.20 Continue Your Route

This section: Continue Your Route — This is the last part of this chapter.

This is the last part of this chapter. Return to Device State Machines: Modes and Safety or continue from the design-patterns module index.

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