Sleep Solutions

Sleep Solutions

Dockpro Bed Cooling System controls the temperature of your sleep. Non-wearable sleep tracker allows to gain insights into sleep metrics, including HRV, respiratory rate, and sleep staging.

INTRODUCTION

The Chilipad 2.0 is an enhanced version of the original Chilipad. The device improves consumers' sleep by cooling or warming the water circulating through a mattress pad to a requested temperature. A closed-loop control system drives water through a pair of thermoelectric coolers (TECs) and past several temperature sensors to hold the water at the requested setpoint.

The control unit — internally named DockPro (DP723) — has a small LCD with a custom UI and physical buttons to navigate its menu system. It connects to the home WiFi network, provisioned over Bluetooth via BluFi from a companion phone app.

The second device is a nightstand remote control — internally named Remote Dock (RM360). It pairs to the control unit over a private Thread mesh network, and the two exchange state and commands through a compact, custom UDP protocol. The remote has a larger round touchscreen and a rotary encoder, and adds its own sensing: an mmWave presence radar, an ambient light sensor, and a haptic driver, layered on top of the shared temperature-control experience.

Both devices report telemetry and receive commands and firmware updates via MQTT over AWS IoT Core, with staged, approval-gated OTA rollouts to production fleets.

SleepMe engaged IOMICO in 2024 to modernize the existing Chilipad control firmware and to build the companion remote device's firmware from scratch, working alongside SleepMe's in-house hardware team. The two teams held weekly reviews to align on features, hardware bring-up, and bugs throughout the engagement.

BACKGROUND

SleepMe's original Chilipad ran a single-device firmware with no companion display beyond the unit's own small screen, and no wireless mesh link between devices. Chilipad 2.0 set out to turn that into a two-device product — a control unit plus a dedicated nightstand remote — while re-platforming the control firmware itself. That created two parallel engineering fronts:

  • A firmware to modernize: the existing control-unit codebase needed a cleaner module boundary (BSP, HAL, control, comms, UI) and new capabilities — an adaptive fan controller, a manufacturing/calibration CLI, cloud-managed OTA — without destabilizing a design already in production.

  • A firmware to build from zero: the remote had no prior firmware at all. It needed its own LVGL touch UI built from SquareLine Studio exports, a driver layer for new hardware (round RGB LCD, capacitive touch, presence radar, haptics), and a reliable link back to the control unit.

  • A two-MCU, two-device problem: both devices pair an ESP32-S3 application processor with an ESP32-H2 radio co-processor for Thread, communicating over a text-based OpenThread CLI bridged across UART — a link that turned out to have real framing and timing pitfalls under load (see Lessons Learned).

  • A hard real-time constraint hiding in a consumer UX: pairing two devices by hand needs to feel instant. Early pairing flows could take up to a minute to fail; the target experience is a code on screen in seconds and a fully synced pair in under two.

BUSINESS OBJECTIVES

IOMICO joined the SleepMe team to pursue the following objectives:

  • Remote Device From Scratch: design and build the Remote Dock firmware — UI, sensing, and Thread connectivity to the control unit — from an empty repository to a production-track product.

  • Control Firmware Modernization: migrate and harden the DockPro firmware with a modular architecture, an adaptive fan/thermal control system, and a manufacturing-grade CLI.

  • Reliable Device Pairing: design a Thread-based pairing protocol that is both fast (target: under 5 seconds to a visible code, under 2 seconds to complete) and resistant to accidental cross-pairing between nearby units.

  • Cloud Connectivity & OTA: implement MQTT-based telemetry, remote configuration, and staged over-the-air firmware updates through AWS IoT Core.

  • Manufacturing Readiness: provide the tooling — CLI commands, calibration routines, factory-pairing scripts — needed to test, calibrate, and provision units on a production line.

  • Fleet-Safe Delivery: build a CI/CD pipeline that lets new firmware roll out to canary, then general, device fleets with explicit approval gates at each stage.

BUSINESS PROBLEM/OPPORTUNITY:

The project addressed several strategic challenges and opportunities:

  • A Consumer-Grade Pairing Experience: turning a mesh-networking protocol (Thread) into something a first-time user completes by glancing at two screens and pressing one button, with cryptographic device binding underneath.

  • Cross-Device Protocol Design: defining and keeping in lock-step a shared command set (setpoint, power, errors, WiFi handoff, presence, keepalives) implemented independently on two firmware codebases that must never drift apart.

  • Constrained UI Memory: delivering a Figma-designed, animation-rich touch UI on an MCU where flash and RAM are shared with OTA partitions and MQTT buffers.

  • Fleet-Wide Update Safety: the opportunity to ship firmware to thousands of deployed units with confidence, via a staged rollout pipeline rather than a single all-or-nothing flash.

  • Manufacturing-Line Support: giving SleepMe's production line a fast, scriptable way to calibrate water-level sensors, pair Thread credentials, and validate hardware before units ship.

DEVELOPMENT APPROACH

To support continuous delivery alongside SleepMe's own hardware and firmware teams, the project was structured using the Kanban methodology, allowing work to flow across feature development, driver bring-up, and protocol design without artificial sprint boundaries.

Tools and Processes

  • JIRA: backlog management, task tracking, and delivery control.

  • GitHub: source control and pull-request review across both firmware repositories.

  • CircleCI: automated builds inside versioned Docker dev containers, with a staged, approval-gated release pipeline (dev canary → dev general → production canary → alpha/internal → production general) targeting AWS IoT Thing Groups per stage.

  • Weekly reviews: ongoing coordination with SleepMe's hardware team on bring-up, feature scope, and open bugs.

Delivery Strategy

As new features and modules were developed, both teams tested them exhaustively before merging to avoid accumulating hard-to-trace bugs across two interdependent firmware images. Quality assurance ran in parallel with development rather than as a separate phase, so every feature or refactor met its acceptance criteria — on real hardware, across both devices — before landing in the stable firmware.

TECHNICAL DETAILS

System Architecture

The Chilipad 2.0 consists of two devices:

  • Control unit

    • ESP32-S3 as the main application processor.

    • ESP32-H2 to run the OpenThread stack.

    • ST7789 with a 320x172 display to run the LVGL UI.

    • Power electronics to control pumps and TECs.

    • Custom water level sensors to track the water levels in multiple reservoirs.

    • Multiple temperature sensors to feed the control system and keep the device's temperature in check.

  • Remote unit

    • ESP32-S3 as the main application processor.

    • ESP32-H2 to run the OpenThread stack.

    • ST7701 with a 480x480 round display and touch screen to run LVGL UI.

    • Rotary encoder and haptic driver to provide user interaction feedback.

    • LD2410C to detect human presence to provide smart functions.

    • Ambient Light Sensor to track ambient light and manage screen brightness.

The firmware is developed on FreeRTOS in C, using a modular architecture in which each component is isolated (BSP, HAL, control, comms, thread, UI) and interacts with others only through provided APIs, with thread-safe mechanisms—mutexes, event groups, and queues—where needed. Both devices expose a custom serial CLI (get/set/exec syntax) for diagnostics, calibration, and manufacturing.

Device Pairing — The devices bind to each other over Thread using a two-network handshake: a well-known PairingNetwork for discovery, then a provisioned network whose credentials (network key, extended PAN ID, mesh prefix, PSKC) are deterministically derived from the control unit's serial number via HKDF-SHA256 — so a control unit and its remote always agree on the same private network without ever transmitting the derivation key over the air. Pairing itself combines two independent 4-digit values: a random, on-screen visual-confirmation code that the user checks by eye on both devices, and a SHA-256 (dock_mac ‖ remote_mac)-derived authorization hash that the devices compute independently to cryptographically bind the pairing to that specific device pair. Once bound, an OpenThread Pending Dataset rotates both devices onto the provisioned network atomically, avoiding the full stop/restart/re-attach cycle that a naive implementation would require.

Cross-Device Command Protocol — Once paired, the two devices exchange a compact, 2-character command via UDP over the Thread mesh (setpoint, power, temperature, errors, WiFi handoff, presence, keepalives), with an ACK/retry layer and heartbeat-based connection health tracking on both ends.

Cloud Connectivity — Both devices connect to WiFi (provisioned via BluFi on the control unit and then shared over Thread with the remote) and maintain a TLS-secured MQTT session to AWS IoT Core through a coreMQTT-Agent-based wrapper, publishing telemetry and shadow state and receiving cloud commands and configuration. Firmware updates are delivered as staged, cloud-triggered OTA images (HTTPS and MQTT-based) and rolled out to fleets through the CI/CD pipeline's canary-then-general Thing Group targeting.

KEY RESULTS & ACHIEVEMENTS

To date, the collaboration has achieved the following:

  1. Build Containers: the two devices track different ESP-IDF versions (4.4.8 for the control unit, 5.3.2 for the remote), which made a shared local toolchain impractical. Dedicated dev containers were built for each workspace, with a split flash/monitor workflow: builds run in Docker, while flashing and serial access occur on the host.

  2. Control Firmware Modernization: migrated and re-architected the DockPro firmware into isolated BSP/HAL/control/comms/thread / UI modules, and added a multi-signal adaptive fan controller that blends H-Bridge thermal pressure, setpoint feed-forward, and TEC PWM effort into a single composite pressure value, with hysteresis, slew-rate limiting, sensor-glitch rejection, and a hard-temperature emergency override.

  3. Manufacturing CLI: a get / set/exec serial command interface (50+ parameters) was built for both devices, covering setpoint control, sensor readouts, water-level sensor calibration, WiFi provisioning, factory reset, and Thread-credential generation from a unit's serial number — used on the production line to test, calibrate, and provision units, and paired with custom Python tooling for live PID-loop tuning and bench testing.

  4. Thread Pairing Protocol: designed and implemented a two-network Thread pairing handshake — a shared discovery network plus a per-device provisioned network derived via HKDF-SHA256 — combining a user-visible confirmation code with a MAC-derived authorization hash, and iteratively re-engineered its timing (event-driven Thread attach, batched dataset writes, Pending Dataset rotation) to cut pairing time from up to a minute to a multi-second target.

  5. LVGL User Interface: migrated Figma designs to LVGL through SquareLine Studio, with a strict separation between auto-generated UI export code and hand-written screen-controller logic — keeping re-exports from SquareLine a clean drop-in and avoiding excessive memory footprint from a literal image-for-image migration.

  6. Custom Drivers: wrote standardized drivers from scratch for new remote-device hardware — the ST7701 round display, CST816S touch controller, LD2410C mmWave presence radar, DRV2605L haptic driver, and ambient light sensor — each following a consistent _init/_start/_suspend/_resume/_delete task lifecycle.

  7. Cloud & OTA: implemented an MQTT wrapper over AWS coreMQTT-Agent (automatic reconnection with backoff, resubscription, thread-safe pub/sub) and staged, CI/CD-driven OTA delivery through canary and general AWS IoT Thing Groups across dev and production accounts.

LESSONS LEARNED

  1. UI Memory Footprint: a one-to-one migration from a Figma design can be expensive in terms of memory footprint, especially when many images are involved, and flash is already split with OTA partitions. Routing the export through SquareLine Studio and LVGL's own asset tooling shrank the footprint substantially compared to a literal pixel-for-pixel port.

  2. Docker-Based Builds Pay for Themselves: investing in per-project dev containers — pinned to each firmware's exact ESP-IDF version — delivered real dividends in developer onboarding, build reproducibility, and CI parity, at the cost of a slightly more involved local dev/flash workflow.

  3. Split-Then-Classify, Not Classify-Then-Split: the UART link between each MCU and its Thread radio co-processor multiplexes CLI echoes, completion markers, and asynchronous UDP notifications over a single stream, delivered via arbitrarily chunked reads. Several early fixes tried to classify each chunk as "CLI" or "UDP" before it was complete, and each one eventually dropped or corrupted a message under real traffic. The durable fix was architectural, not a smarter heuristic: accumulate bytes until a full line is available and classify only complete lines. Never make a routing decision on a partial message.

  4. Document In Place: comprehensive READMEs and architecture docs living next to the code they describe (fan control, Thread pairing, LVGL screens, MQTT wrapper) meaningfully reduced onboarding time between the two teams and kept the protocol shared by both firmwares from drifting apart silently.

  5. Fail Gracefully, Never Silently: critical paths were written to degrade rather than break — the Thread dataset installer falls back to a slower, proven per-field configuration sequence if the fast batched path fails, so a firmware bug can't leave a unit bricked in the field; the fan controller keeps its last known-good state and skips a tick outright if a temperature reading looks physically implausible, rather than acting on bad data.

  6. Design the Two-Device Protocol as One Contract: with independent control and remote codebases exchanging a shared command set over Thread, keeping both sides' command tables, timeouts, and pairing state machines in lockstep requires treating the protocol itself — documented and mirrored file-for-file — as a first-class deliverable, not an implicit side effect of each firmware's own logic.

CONCLUSION

The SleepMe engagement demonstrates IOMICO's ability to simultaneously modernize a firmware already in production and build a companion device's firmware from a blank repository — while keeping both in sync over a hand-built wireless protocol. By re-architecting the DockPro control firmware, designing the Remote Dock from scratch, and engineering a fast, secure Thread pairing experience between them, IOMICO helped SleepMe turn the Chilipad into a genuinely two-device product backed by cloud connectivity, staged OTA delivery, and manufacturing-ready tooling. The result is not only a more capable product, but a firmware platform and set of documented protocols that SleepMe's team can keep building on.

Our services

Embedded Software Development

Industry

Healthcare

Technology

ESP32-S3/H2, BLE, WiFi, Thread, Embedded C, LVGL, C/C++, AWS IoT, OTA

Team

Project Manager

DevOps

Firmware Developer

Contact us

Address

400 Union Ave. SE,

Suite 200 

Olympia, WA 98501

Instant Messenger
Social Media

Contact us

Address

400 Union Ave. SE,

Suite 200 

Olympia, WA 98501

Instant Messenger
Social Media

Contact us

Address

400 Union Ave. SE,

Suite 200 

Olympia, WA 98501

Instant Messenger
Social Media