ESP32-C6 Smart Control for Cybex E-Priam Stroller — Home Assistant integration, extended rocking timer, and OTA updates
A native ESP-IDF firmware for ESP32-C6 that acts as a BLE-to-WiFi bridge for the Cybex E-Priam electric stroller. Control rocking, drive modes (ECO/TOUR/BOOST), and monitor battery via Home Assistant, MQTT, or a beautiful web interface.
Keywords: Cybex E-Priam, smart stroller, baby tech, ESP32 BLE, Home Assistant stroller, MQTT baby monitor, electric pram hack, nursery automation
I was getting tired of Cybex never updating their useless app, so I decided to create my own. This lets you integrate your E-Priam to Home Assistant or anything eating MQTT.
Your child will love the Auto-mode, because the default max duration on the E-Priam is 30 minutes — the exact same as a baby's sleep cycle. With Auto it will automatically jump back to 30 minutes when it reaches 10 minutes left on the timer.
The config page lets you translate the entity names sent over MQTT. That's just a shortcut for you to be able to push it to HomeKit and say: "Hey Siri, turn on rocking"
- BLE Connection - Automatic discovery and connection to E-Priam stroller
- BLE Notifications - Real-time updates from stroller (battery, status)
- Web Interface - Beautiful mobile-friendly control panel
- Home Assistant - Full MQTT integration with auto-discovery
- Rocking Control - 30min to 3 hour duration options with countdown
- Auto-Renew Mode - Continuous rocking that auto-renews before timeout
- Battery Monitoring - Real-time battery percentage from stroller
- Drive Modes - ECO, TOUR, BOOST mode switching
- OTA Updates - Over-the-air firmware updates via web browser
- Live BLE Log - Real-time connection status in web UI
This project has been developed and tested with:
- Seeed Studio XIAO ESP32-C6 - Recommended, compact and reliable
Should work with any ESP32-C6 board, but only the XIAO ESP32-C6 has been verified:
| Board | Status | Notes |
|---|---|---|
| Seeed XIAO ESP32-C6 | ✅ Tested | Recommended |
| ESP32-C6-DevKitC-1 | Should work | |
| Other ESP32-C6 boards | Should work |
- Cybex E-Priam stroller with electronic drive unit
- WiFi network (2.4 GHz)
- USB-C cable for flashing
- Optional: MQTT broker for Home Assistant integration
pip install platformioEdit src/main.c and update these values:
#define MQTT_BROKER "mqtt://YOUR_MQTT_BROKER_IP"
#define MQTT_USER "your_mqtt_username"
#define MQTT_PASS "your_mqtt_password"
#define WIFI_SSID "YourWiFiNetwork"
#define WIFI_PASS "YourWiFiPassword"pio run --target uploadAfter flashing, the ESP32-C6 will:
- Connect to your WiFi network
- Get an IP address via DHCP
- Start scanning for the E-Priam stroller
Check your router's DHCP leases or use:
arp -a | grep -i espressifAccess the web interface at http://<device-ip>/
| Indicator | Description |
|---|---|
| BLE (green/red) | Connected to stroller |
| MQTT (green/red) | Connected to broker |
| Battery XX% | Stroller battery level |
| Mode | Current drive mode (ECO/TOUR/BOOST) |
| Auto (green/red) | Auto-renew status |
| Button | Description |
|---|---|
| 5m / 15m / 30m | Start rocking with timer |
| Auto | Continuous rocking (auto-renews at 10 min remaining) |
| Stop | Stop rocking |
| Button | Description |
|---|---|
| ECO | Energy-saving mode |
| TOUR | Normal mode |
| BOOST | Maximum power mode |
| URL | Description |
|---|---|
/ |
Main control interface |
/config |
Configure entity names for Home Assistant |
/ota |
Upload new firmware over-the-air |
/api/status |
JSON status endpoint |
/api/log |
BLE log (newest first) |
The device automatically publishes MQTT discovery messages. Entities appear automatically in Home Assistant.
| Entity | Type | Description |
|---|---|---|
sensor.epriam_battery |
Sensor | Battery percentage |
switch.epriam_rocking |
Switch | Rocking on/off |
switch.epriam_autorenew |
Switch | Auto-renew mode |
select.epriam_mode |
Select | Drive mode (ECO/TOUR/BOOST) |
number.epriam_intensity |
Number | Rocking intensity (0-100%) |
binary_sensor.epriam_connected |
Binary Sensor | BLE connection status |
sensor.epriam_ip |
Sensor | Device IP address |
automation:
- alias: "Start rocking when baby monitor triggers"
trigger:
- platform: state
entity_id: binary_sensor.baby_crying
to: "on"
action:
- service: switch.turn_on
target:
entity_id: switch.epriam_autorenewcurl http://<ip>/api/statusResponse:
{
"connected": true,
"mqtt": true,
"battery": 69,
"battery_leds": 2,
"drive_mode": 1,
"rocking": true,
"auto_renew": false,
"intensity": 50,
"remaining_sec": 245,
"rock_minutes": 5
}# Drive modes
curl http://<ip>/api/mode/eco
curl http://<ip>/api/mode/tour
curl http://<ip>/api/mode/boost
# Rocking control
curl "http://<ip>/api/rock/start?min=15&intensity=50"
curl http://<ip>/api/rock/stop
curl http://<ip>/api/rock/autorenew
# BLE scan
curl http://<ip>/api/rescan-
Build new firmware:
pio run
-
Navigate to
http://<device-ip>/ota -
Select file:
.pio/build/esp32-c6/firmware.bin -
Click "Start OTA" and wait for completion
-
Device reboots automatically
- Check the BLE log on the web interface
- Ensure the stroller is powered on
- Move ESP32-C6 closer (< 3 meters recommended)
- Press "Scan" button in web UI
- Check serial output:
pio device monitor
- RSSI should be above -85 dBm for reliable connection
- Optimal range is 1-2 meters from stroller
- The E-Priam BLE module (Microchip RN4871) has limited range
- Verify broker IP, username, and password in code
- Check that MQTT broker is running
- Verify Home Assistant MQTT integration is configured
The E-Priam uses a Microchip RN4871 BLE module.
Manufacturer ID: 0x078D
Service UUID: a1fc0101-78d3-40c2-9b6f-3c5f7b2797df
| Characteristic | UUID Suffix | Description |
|---|---|---|
| Status | 0102 | Read status bytes |
| Drive Mode | 0103 | Write-only: 1=ECO, 2=TOUR, 3=BOOST |
| Rocking | 0104 | Write: [0x01, minutes, intensity%] or [0x00] |
| Battery LED | 0105 | Read: LED count (1-3) |
Start: [0x01, minutes, intensity]
- minutes: 0 = continuous, 1-30 = timer
- intensity: 0-100 percent
Stop: [0x00]
RAM: ~15% (50KB of 328KB)
Flash: ~33% (1.4MB of 4MB)
If the ESP32 keeps failing to connect with reason=0x3E, the stroller may need a reset:
- Lower the handle bar from fully extended to the lowest position
- Extend the handle bar back to fully extended
- Turn the E-Priam off
- Turn the E-Priam on
This typically happens after using the official Cybex app, which can leave the stroller's BLE in an unresponsive state.
The drive mode characteristic (0x0103) is write-only — it cannot be read. The firmware tracks the mode locally after sending a write command.
Entity names can be customized via the /config page. These are stored in NVS (non-volatile storage) and persist across reboots.
Default names (Norwegian):
- Device: "Cybex E-Priam"
- Battery: "Batteri"
- Rocking: "Vugging"
- Auto-renew: "Auto-forny"
- Mode: "Modus"
- Intensity: "Intensitet"
- Connected: "Tilkoblet"
# Clone repository
git clone https://github.com/yourusername/Priam.git
cd Priam/esp32-c6
# Install dependencies (handled by PlatformIO)
pio pkg install
# Build
pio run
# Upload to device
pio run --target upload
# Monitor serial output
pio device monitoresp32-c6/
├── src/
│ └── main.c # All firmware code
├── platformio.ini # PlatformIO configuration
├── partitions.csv # Flash partition table
├── sdkconfig.defaults # ESP-IDF settings
└── README.md # This file
MIT License - See LICENSE file for details.
Pull requests are welcome! Please ensure code follows the existing style.
- BLE protocol reverse-engineering based on python-priam by @vincegio
- Built with ESP-IDF 5.5.1 via PlatformIO
- BLE stack: Apache NimBLE
