Control the Eight Sleep Pod 3 locally and automatically!
Ten Sleep communicates with the bed's firmware (frakenfirmware
) by pretending
to be the DAC. This means that, once setup, you CANNOT use the Eight Sleep
mobile app to control the bed.
- Automatically set bed temperature every night
- Create a custom temperature profile
- Set a heat and/or vibration wakeup alarm
- Control settings and monitor remotely via API
To use Ten Sleep you must disassemble the Eight Sleep Pod 3, modify the SD card's rootfs.tar.gz
to add your SSH key + root password, and reset the Pod. Then power the Pod while holding the small
button on the back, which performs a factory reset from rootfs.tar.gz
. Now you can disable
Eight Sleep's update service and Add Ten Sleep.
- Note: the default SSH port for Pod 3 is
8822
. - Disable Updates:
systemctl disable --now swupdate-progress swupdate defibrillator eight-kernel telegraf vector
Eventually I will add thorough tutorial for this, but for now I would recommend Bo Lopker's Tutorial and the ninesleep instructions.
Build with:
cargo build --target aarch64-unknown-linux-musl
- Modify
settings.json
to suit your needs scp
the binary,tensleep.service
, andsettings.json
to the Podssh
in, sign in as root- Move the binary and json to
/opt/tensleep
- Move the service file to
/etc/systemd/system
- Stop the DAC
systemctl disable --now dac
- Enable the Ten Sleep
systemctl enable --now tensleep
The entire API is JSON based.
Some endpoints can throw an error (labeled Errorable) which has the standard type:
{"error": ErrorString, "details": DetailsString}
(details is optional).
GET /health
→
{"status": "OK" | "UNAVAILABLE"}
Returns whether it can communicate to frakenfirmware
GET /state
(Errorable) →
{
"target_heat_level_left": i32,
"target_heat_level_right": i32,
"heat_level_left": i32,
"heat_level_right": i32,
"heat_time_left": u32,
"heat_time_right": u32,
"sensor_label": String,
"water_level": bool,
"priming": bool,
"settings": String,
}
Returns state/variables directly from frakenfirmware.
sensor_label
looks something like 20600-0001-F00-0001089C
,
and settings
looks something like BF61760162676C190190626772190190626C621864FF
GET|POST /prime
(Errorable) →
{"response": ResponseString}
Tells frakenfirmware to prime the bed. This process can take awhile.
You can check when its done with GET /state
.priming.
Settings Format:
{
"temp_profile": [i32; 3],
"time_zone": String,
"sleep_time": String,
"alarm": {
"time": TimeString,
"vibration":{
"pattern": "double" | "rise",
"intensity": u8,
"duration": u16,
"offset": u16
},
"heat": {
"temp": i32,
"offset": u16
}
}
}
GET /settings
(Errorable) → all settings
GET /setting/SETTING+
(Errorable) → specified setting
- Example:
GET /setting/alarm/vibration/duration
POST /settings
(Errorable): set all settings
→
{ "message": "Settings updated successfully", "settings": NewSettings }
POST /setting/SETTING+
(Errorable): set specified setting
→
{ "message": "Setting updated successfully", "settings": NewSettings }
- Example:
POST /setting/alarm/vibration/duration -d 600
This project was inspired by ninesleep. I have completely rewritten all of bobobo1618's code so the license is now excluded.
This project is not affiliated with or endorsed by Eight Sleep.
If you encounter issues with this project please make an issue on this repository. If you have changes you want to be made please make a PR.
For anything else please contact me at mail@liamsnow.com.