Project 8: Complete Cardputer Security Toolkit (Capstone)
Integrate WiFi tools, BLE/USB HID, IR control, GPS logging, and audio spectrum into one cohesive firmware with shared services, consistent UI, and robust power management.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Master |
| Time Estimate | 2–3 months |
| Main Programming Language | C/C++ (ESP-IDF) |
| Alternative Programming Languages | None (integration requires full control) |
| Coolness Level | Extreme |
| Business Potential | High (multi-tool field platform) |
| Prerequisites | Completed prior projects, strong RTOS skills |
| Key Topics | subsystem arbitration, settings, power management, OTA/safe boot |
1. Learning Objectives
By completing this project, you will:
- Integrate multiple complex subsystems without conflicts.
- Build a global service registry and enforce resource arbitration.
- Implement persistent settings with versioned migrations.
- Design power management strategies for a battery device.
- Implement OTA updates and safe boot recovery.
2. All Theory Needed (Per-Concept Breakdown)
2.1 Subsystem Arbitration and Global State Machines
Fundamentals
When multiple subsystems share hardware (WiFi, display, SD card), you must decide which one owns each resource at any time. Arbitration is the policy that prevents two modules from fighting for the same resource. A global state machine coordinates tool modes, transitions, and resource ownership so the device behaves predictably.
Deep Dive into the concept
A toolkit that combines WiFi sniffing, BLE HID, USB HID, IR, GPS, and audio must coordinate radios, buses, and CPU time. WiFi and BLE share the 2.4 GHz radio; they cannot always run at full capacity simultaneously. USB uses a separate peripheral but consumes CPU and DMA. The display and SD card share SPI bandwidth. Without arbitration, a WiFi sniffer may starve the UI or an audio analyzer may stutter when SD logging occurs.
A global state machine defines modes such as WIFI_SNIFFER, BLE_HID, IR_REMOTE, AUDIO_SPECTRUM, WARDIVE, and IDLE. Each mode declares which services it needs. The service registry then grants or denies access based on current mode and policy. For example, if WiFi sniffer is active, BLE HID might be paused or disabled. Mode transitions should include teardown and reinit steps so each subsystem is reset to a known state.
Arbitration can be implemented with a central “resource manager” that exposes acquire/release APIs. Each subsystem requests a resource and the manager checks availability. If denied, the subsystem can either wait or degrade. This makes conflicts explicit and testable. For example, if the user switches from WiFi sniffer to BLE HID, the manager should stop WiFi, wait for cleanup, then enable BLE. This is a deterministic transition, not a race.
UI should reflect arbitration decisions. If a tool cannot run because another tool is active, the UI should explain why. This reduces user confusion and prevents accidental misuse. In a capstone system, clarity is as important as raw functionality.
How this fits in projects
This builds on the mini-OS architecture from P06-custom-application-launcher-mini-os.md and integrates tools from all previous projects.
Definitions & key terms
- Arbitration → policy for exclusive access to shared resources
- Global state machine → central controller for mode transitions
- Resource manager → component granting/releasing resources
- Degrade → fallback behavior when resource is unavailable
Mental model diagram (ASCII)
[Mode Manager] -> [Resource Manager]
| |
v v
[Active Tool] [Shared Services]
How it works (step-by-step, with invariants and failure modes)
- User selects a tool mode.
- Mode manager requests required resources.
- Resource manager grants or denies.
- Tool initializes and runs.
- On exit, resources released and next tool can start.
Invariants: only one owner per resource; transitions are serialized. Failure modes: two tools run on same resource, causing crashes or corruption.
Minimal concrete example
if (!resource_acquire(WIFI)) return ERR_BUSY;
Common misconceptions
- “ESP32 can handle everything at once.” → Radios and buses have limits.
- “Conflicts are rare.” → They are common when subsystems grow.
- “Users will understand failures.” → Without explicit UI, they won’t.
Check-your-understanding questions
- Why can’t WiFi sniffer and BLE HID always run together?
- What does a resource manager do?
- Why is a global state machine necessary?
Check-your-understanding answers
- They share the radio and timing resources, causing conflicts.
- It grants or denies exclusive access to shared hardware.
- It ensures deterministic transitions and avoids race conditions.
Real-world applications
- Multi-tool industrial handhelds.
- Security assessment devices.
Where you’ll apply it
- This project: see §4.1 architecture and §5.10 Phase 1.
- Also used in:
P06-custom-application-launcher-mini-os.md.
References
- Embedded systems resource arbitration patterns.
- Making Embedded Systems – system integration chapters.
Key insight
Integration is mostly about enforcing boundaries, not adding features.
Summary
Centralize resource ownership and use a state machine to keep subsystems from colliding.
Homework/Exercises to practice the concept
- Define a table of resources required by each tool.
- Implement a resource acquire/release API.
Solutions to the homework/exercises
- List WiFi, BLE, USB, SD, Display, Audio, IR.
- Implement a bitmask and return ERR_BUSY if occupied.
2.2 Persistent Settings, Schema Migration, and Data Integrity
Fundamentals
A toolkit must remember settings across reboots: user preferences, last used tool, WiFi channels, and macro profiles. Settings storage must be versioned so you can change formats without breaking old data. This requires a schema version and migration logic.
Deep Dive into the concept
Settings are a form of data storage. Unlike logs, settings must survive updates and power loss. The ESP32 provides NVS (non-volatile storage), which stores key-value pairs with integrity checks. You should define a settings struct with a version field. On boot, read the version; if it’s older than the current schema, run a migration function that upgrades or resets fields. For example, if you add a new “default channel” setting in version 2, the migration should set it to a safe default when reading a version 1 record.
Data integrity requires validation. If settings are corrupt, you should reset to defaults and inform the user. Use checksums if you store binary blobs on SD. For settings stored in NVS, rely on NVS integrity, but still validate ranges (e.g., channel must be 1–13). For complex data like macro scripts or IR profiles, keep them as separate files with their own checksums. This isolates corruption and avoids breaking the entire system.
Migration must be deterministic. Define a migration path from each previous version to the current. Avoid “best effort” guessing. If you cannot migrate, reset and inform the user. This keeps the system predictable. Also consider exporting/importing settings as JSON so users can back up configurations. This aligns with the project’s emphasis on durability.
How this fits in projects
Settings storage builds on the logging and storage work from P01-wifi-packet-sniffer-network-analyzer.md and P05-wardriving-wifi-mapper.md.
Definitions & key terms
- Schema version → number indicating settings format
- Migration → transformation from old schema to new
- NVS → non-volatile storage on ESP32
- Validation → range checks and integrity checks
Mental model diagram (ASCII)
[Settings v1] -> [Migration] -> [Settings v2] -> [Validation]
How it works (step-by-step, with invariants and failure modes)
- Load settings blob and version.
- If version < current, run migrations.
- Validate fields and ranges.
- Save updated settings back to NVS.
Invariants: version always stored; migrations deterministic. Failure modes: corrupt data resets to defaults; invalid ranges cause crashes if unchecked.
Minimal concrete example
if (settings.version == 1) migrate_v1_to_v2(&settings);
Common misconceptions
- “Settings never change.” → They will as features grow.
- “NVS data is always valid.” → Validate ranges anyway.
- “Migration is optional.” → Without it, updates break users.
Check-your-understanding questions
- Why include a schema version?
- What should you do if migration fails?
- Why validate settings ranges?
Check-your-understanding answers
- To know how to interpret stored data and upgrade it.
- Reset to safe defaults and notify the user.
- To prevent invalid values from crashing subsystems.
Real-world applications
- Consumer devices with firmware updates.
- Industrial tools requiring long-term stability.
Where you’ll apply it
- This project: see §3.2 requirement 3 and §5.10 Phase 2.
- Also used in:
P06-custom-application-launcher-mini-os.mdfor settings persistence.
References
- ESP-IDF NVS documentation.
- Embedded data migration patterns.
Key insight
Settings are a contract with your users; breaking them breaks trust.
Summary
Version your settings, validate ranges, and implement deterministic migrations.
Homework/Exercises to practice the concept
- Define a settings struct with version and defaults.
- Write a migration from v1 to v2 that adds a field.
Solutions to the homework/exercises
- Include
version,default_mode,brightness,channel. - Add
channelwith default 6 when migrating.
2.3 Power Management, OTA Updates, and Safe Boot
Fundamentals
A battery-powered toolkit must manage power. It should dim the display, disable radios when idle, and sleep when inactive. OTA (over-the-air) updates let you deliver fixes without physical access, but they introduce risk: a failed update can brick the device. Safe boot strategies ensure recovery.
Deep Dive into the concept
Power management begins with measurement. You must know the current draw of each subsystem (WiFi, BLE, display, audio). Implement a power profile table and track active components. For example, when switching from WiFi sniffer to BLE HID, you can disable WiFi, reducing draw. The display is often the largest consumer; implement auto-dim and a “low power” mode with reduced refresh.
Sleep modes can extend battery life. Light sleep keeps RAM and wake sources (buttons, timers); deep sleep resets the CPU but saves more power. In a toolkit, you might use light sleep when idle and deep sleep for long inactivity. Provide a setting to configure timeout. If you enter sleep, ensure you flush logs and save settings.
OTA updates require a dual-partition strategy. ESP-IDF supports OTA partitions: you download firmware into the inactive partition, verify it, then reboot into it. If the new firmware fails, a rollback should occur. A safe boot counter can detect repeated crashes and revert to the previous firmware. Additionally, keep a “safe mode” boot: if the user holds a key during boot, the system boots with minimal services (no WiFi, no OTA) to allow recovery.
Power management and OTA are deeply linked. During OTA, you must ensure sufficient battery to avoid interruption. If the battery is low, defer the update. Log update status to the SD card or NVS. These details are what make a field-ready product.
How this fits in projects
Power and OTA concerns are the final integration layer on top of all previous projects.
Definitions & key terms
- Light sleep → low-power mode with RAM retained
- Deep sleep → lowest power mode, resets CPU
- OTA partition → inactive slot for firmware update
- Rollback → revert to previous firmware after failure
Mental model diagram (ASCII)
[Active Firmware] -> [OTA Download] -> [Verify] -> [Reboot]
^ |
+--------- Rollback ------------+
How it works (step-by-step, with invariants and failure modes)
- Check battery level and network availability.
- Download OTA to inactive partition.
- Verify checksum and signature.
- Reboot into new partition.
- If boot fails, rollback to previous firmware.
Invariants: never update on low battery; always verify image. Failure modes: power loss during OTA, corrupted image, boot loops.
Minimal concrete example
if (battery_pct < 30) return ERR_LOW_BATT;
Common misconceptions
- “OTA is just download and reboot.” → Verification and rollback are critical.
- “Sleep is optional.” → Battery devices demand power management.
- “Safe boot isn’t needed.” → Recovery is essential in the field.
Check-your-understanding questions
- Why use dual OTA partitions?
- What triggers a rollback?
- Why avoid OTA on low battery?
Check-your-understanding answers
- To keep a known-good firmware while updating.
- Repeated boot failures or explicit validation failure.
- Power loss during update can brick the device.
Real-world applications
- Consumer IoT devices and handheld tools.
- Industrial devices requiring safe firmware updates.
Where you’ll apply it
- This project: see §3.2 requirement 5 and §5.10 Phase 3.
References
- ESP-IDF OTA documentation.
- Power management guidelines for ESP32.
Key insight
A toolkit that can’t update or conserve power won’t survive real-world use.
Summary
Combine power profiling, sleep strategies, and OTA rollback to build a resilient device.
Homework/Exercises to practice the concept
- Measure current draw in each mode and log results.
- Implement a safe boot key combo that bypasses modules.
Solutions to the homework/exercises
- Use a USB power meter and record draw per mode.
- Check key state on boot and skip module init if pressed.
3. Project Specification
3.1 What You Will Build
A unified toolkit that:
- provides a home screen with multiple tools,
- shares services and settings,
- logs data to SD with consistent structure,
- supports OTA updates and safe boot.
3.2 Functional Requirements
- Mode manager: switch tools without reboot.
- Resource arbitration: enforce ownership of WiFi, BLE, SD, display.
- Settings persistence: versioned settings with migration.
- Power management: dim display, manage radios, sleep.
- OTA updates: safe update with rollback.
3.3 Non-Functional Requirements
- Reliability: stable mode switching under load.
- Performance: UI remains responsive across tools.
- Safety: OTA never bricks device.
3.4 Example Usage / Output
1) Boot to toolkit home screen
2) Switch between WiFi and BLE tools
3) Update firmware via OTA
3.5 Data Formats / Schemas / Protocols
- Shared settings schema (versioned).
- Unified logs folder structure (per tool).
3.6 Edge Cases
- Switch modes while SD is writing.
- OTA update interrupted by low battery.
- WiFi and BLE requested simultaneously.
3.7 Real World Outcome
A successful build behaves like a polished product: tools switch instantly, settings persist, battery life is acceptable, and OTA updates are safe. Logs are organized by tool and date.
3.7.1 How to Run (Copy/Paste)
idf.py set-target esp32s3
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
3.7.2 Golden Path Demo (Deterministic)
- Boot, switch between three tools 10 times.
- Perform OTA update with battery > 50%.
- Verify rollback works by simulating failure.
Failure demo (deterministic):
- Start OTA update with battery at 20%. Expected: OTA is refused, UI shows “LOW BATTERY,” and no partition switch occurs. Exit code: 2.
3.7.3 If CLI: exact terminal transcript
I (8100) toolkit: mode=WiFiSniffer
I (8101) toolkit: switch->BLEHID ok
I (8102) ota: download ok verify ok
I (8103) ota: rebooting into slot 1
Exit codes: 0 = success, 2 = OTA blocked (low battery), 3 = resource conflict, 4 = OTA verify failure.
3.7.4 If Web App
Not applicable.
3.7.5 If API
Not applicable.
3.7.6 If Library
Not applicable.
3.7.7 If GUI / Desktop / Mobile
Not applicable.
3.7.8 If TUI
+----------------------------+
| CARDPUTER TOOLKIT |
| [1] WiFi Sniffer |
| [2] Wardrive |
| [3] BLE HID |
| [4] USB HID |
| [5] IR Remote |
| [6] Spectrum |
+----------------------------+
4. Solution Architecture
4.1 High-Level Design
[Launcher] -> [Mode Manager] -> [Tool Modules]
|
v
[Resource Manager]
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Mode manager | tool switching | serialized transitions |
| Resource manager | arbitration | deny conflicting access |
| Settings service | persistent config | versioned schema |
| Power manager | sleep + dim | policies per mode |
| OTA manager | updates + rollback | dual partitions |
4.3 Data Structures (No Full Code)
typedef struct {
uint8_t version;
uint8_t default_mode;
uint8_t brightness;
} settings_t;
4.4 Algorithm Overview
Key Algorithm: Mode Transition
- Stop current tool and release resources.
- Apply new mode power profile.
- Acquire resources for new tool.
- Start tool and update UI.
Complexity Analysis:
- Time: O(1) per transition
- Space: O(1)
5. Implementation Guide
5.1 Development Environment Setup
idf.py set-target esp32s3
idf.py build
5.2 Project Structure
project-root/
├── main/
│ ├── mode_manager.c
│ ├── resource_manager.c
│ ├── settings.c
│ ├── power.c
│ ├── ota.c
│ └── ui.c
└── README.md
5.3 The Core Question You’re Answering
“How do I integrate multiple complex subsystems into one stable product?”
5.4 Concepts You Must Understand First
- Resource arbitration.
- Settings migration.
- Power management + OTA.
5.5 Questions to Guide Your Design
- Which tools can coexist, and which are mutually exclusive?
- How will you migrate settings across versions?
- How do you prevent OTA on low battery?
5.6 Thinking Exercise
Design a table of tool modes and required resources, then identify conflicts.
5.7 The Interview Questions They Will Ask
- How do you manage resource conflicts on embedded devices?
- What is your OTA rollback strategy?
- How do you ensure settings compatibility across versions?
5.8 Hints in Layers
Hint 1: Start with a launcher that switches between two tools.
Hint 2: Add a resource manager that denies conflicts.
Hint 3: Add settings and OTA last.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Systems integration | Making Embedded Systems | Ch. 9–10 |
| Software architecture | Clean Architecture | Ch. 1–3 |
5.10 Implementation Phases
Phase 1: Mode manager + resource arbitration (3–4 weeks)
Phase 2: Settings + persistence (2–3 weeks)
Phase 3: Power + OTA + safe boot (3–4 weeks)
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| Resource conflicts | deny or degrade | deny unless safe | predictable behavior |
| Settings | NVS or file | NVS + file for large data | durability |
| OTA policy | always | only if battery > 30% | reduce risk |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Integration Tests | mode switches | 100 transitions |
| Reliability Tests | OTA rollback | forced failure |
| Power Tests | battery draw | per-mode measurement |
6.2 Critical Test Cases
- Rapid mode switching without crashes.
- OTA update rollback after simulated failure.
- Power consumption within target range.
6.3 Test Data
Synthetic mode switch script
OTA test images
7. Common Pitfalls & Debugging
7.1 Frequent Mistakes
| Pitfall | Symptom | Solution |
|---|---|---|
| No resource arbitration | random crashes | enforce resource manager |
| No settings migration | upgrade breaks configs | add schema version |
| OTA without checks | bricked device | add verification + rollback |
7.2 Debugging Strategies
- Log mode transitions and resource grants.
- Simulate OTA failures to validate rollback.
7.3 Performance Traps
- Running WiFi + BLE + UI at max load without power budgeting.
8. Extensions & Challenges
8.1 Beginner Extensions
- Add per-tool themes or UI skins.
8.2 Intermediate Extensions
- Add backup/restore of settings to SD.
8.3 Advanced Extensions
- Add plug-in system for external modules.
9. Real-World Connections
9.1 Industry Applications
- Multi-tool cybersecurity devices.
- Field diagnostics platforms.
9.2 Related Open Source Projects
- ESP32 OTA examples.
9.3 Interview Relevance
- Systems integration and reliability engineering.
10. Resources
10.1 Essential Reading
- ESP-IDF OTA and power management docs.
10.2 Video Resources
- Embedded OTA update talks.
10.3 Tools & Documentation
- ESP-IDF resource manager patterns.
10.4 Related Projects in This Series
P01-wifi-packet-sniffer-network-analyzer.mdP06-custom-application-launcher-mini-os.md
11. Self-Assessment Checklist
11.1 Understanding
- I can explain resource arbitration.
- I can explain OTA rollback.
11.2 Implementation
- Modes switch without conflicts.
- Settings persist across reboots.
11.3 Growth
- I can design safe boot recovery flows.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Mode manager and two integrated tools.
Full Completion:
- All tools integrated with resource arbitration and settings.
Excellence (Going Above & Beyond):
- Safe OTA updates and power management policies.