1 Punkte von GN⁺ 17 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • Wegen eines heißen Schlafzimmers und Temperaturempfindlichkeit kaufte der Autor für 1.700 US-Dollar ein Sleep.me Chilipad 2.0 und entwickelte bedctl, um die Cloud-API des Herstellers zu steuern
  • Das Chilipad kombiniert einen dünnen Topper mit zirkulierendem Wasser mit Pumpe, Reservoir und Temperaturregler und unterstützt modulare Konfigurationen mit temperaturgesteuerten Zeitplänen nach Wochentagen sowie einem Start mit nur einer Bettseite
  • Die API liefert Geräte über /devices und /devices/{:id} und steuert per PATCH Temperatur, Betriebsstatus, Display-Helligkeit, Zeitzone und mehr; auch Wasserstand und aktuelle Wassertemperatur lassen sich abfragen
  • bedctl, geschrieben in Zig, besteht aus einer abhängigkeitslosen Bibliothek und einer schlanken CLI und soll später zu einer dynamischen Bibliothek libbedctl mit C-Schnittstelle erweitert werden
  • Beim ersten Schlaftracking nahmen die Erholungsschlafphasen zu und nächtliches Aufwachen ab, doch nach nur wenigen Tagen Nutzung ist es noch zu früh, die Langzeitwirkung zu beurteilen

Warum eine Bett-Temperaturregelung nötig war

  • Schlaf hilft dem Immunsystem, kognitiven Funktionen und der Erholung nach körperlicher Aktivität, aber in Gesundheits-Schlagzeilen kann die wissenschaftliche Nuance verloren gehen, daher ist wichtig, ob Aussagen von medizinischem Fachpersonal oder Expertenkonsens gestützt werden
  • Wegen ADHS kreisen die Gedanken weiter, was das Einschlafen erschwert; die Gewohnheit, im Bett zu lesen, half dabei, Reize zu reduzieren und dem Nervensystem ein Schlafsignal zu geben
  • Durch autistische Merkmale besteht Empfindlichkeit gegenüber bestimmten Texturen und Sinneseindrücken sowie Schwierigkeiten bei der Temperaturregulation, daher müssen zum Einschlafen Temperatur und Gewicht der Decke stimmen
  • Die neue Wohnung in Portland hat eine Klimaanlage nur im Wohnzimmer und keinen Deckenventilator, daher ist das hoch gelegene Schlafzimmer nachts der heißeste Raum
    • Ein installierter Temperatursensor bestätigte ebenfalls, dass das Schlafzimmer der wärmste Bereich der Wohnung ist
  • Unregelmäßiger Schlaf, die Einnahme von Stimulanzien, ein stickiges Schlafzimmer und Temperaturempfindlichkeit führten zusammen zur Entscheidung, Geld für eine Bett-Temperaturregelung auszugeben

Warum das Chilipad 2.0 gewählt wurde

  • Das Chilipad 2.0 steuert die Betttemperatur, indem es einen dünnen, mit Wasser gefüllten Matratzentopper mit einem Gerät verbindet, das Pumpe, Reservoir und Temperaturregelung enthält
  • BedJet, das Luft mit einem Ventilator einbläst, wurde ausgeschlossen, weil im Sommer kalte Luft direkt auf die Füße bläst
  • Eight Sleep kostet selbst in der günstigsten Variante 3.000 US-Dollar, erfordert ein Abonnement und enthält sogar AI-Funktionen, daher kam es nicht infrage
  • Das Chilipad ist modular, sodass man schon mit einem Gerät für nur eine Bettseite beginnen kann, was den Einstiegspreis senkt
    • Mit zwei Geräten lassen sich beide Seiten auf unterschiedliche Temperaturen einstellen, was für Paare mit unterschiedlichem Temperaturempfinden nützlich ist
  • Es ist zwar ein internetfähiges Produkt, unterstützt aber einen Flugmodus und liefert standardmäßig eine Bluetooth-Fernbedienung mit
    • Es wurde nicht geprüft, ob der Flugmodus nur Wi‑Fi deaktiviert oder alle Funkverbindungen blockiert
    • Anfangs wurde fälschlich eine lokale API vermutet, tatsächlich kommuniziert das Gerät aber mit einem Cloud-Service
  • Der Hersteller stellt eine Entwickler-API, eine Postman-Collection sowie eine online verfügbare Swagger-UI und ein OpenAPI-Schema bereit

Aufbau des Chilipad-Geräts

  • Das Chilipad besteht aus der Steuereinheit dock und dem wasserzirkulierenden cover
    • Das dock enthält Temperaturregler, Pumpe und Reservoir
    • Es wurde am Fußende des Betts und nahe der Zimmertür platziert, um zu verhindern, dass die vom Wärmetauscher abgegebene warme Luft wieder im Schlafzimmer verteilt wird
  • Das cover besteht aus drei Schichten: einer unteren Schicht, einer hydrolayer aus TPU-Membran und einem oberen cover
    • Durch Öffnen des Reißverschlusses des oberen cover lässt sich die hydrolayer auf der Seite installieren, auf der die Person schläft
    • Oben kommen ein kühl wirkender Stoff und eine dünne Polsterung zum Einsatz, sodass die hydrolayer nicht direkt spürbar ist

Sleep.me API

  • Authentifizierung und Postman-Beispiele

    • Für die Nutzung der API muss zunächst ein Benutzer-Token erzeugt werden; die Dokumentation ist nur mit einem Konto zugänglich
    • Die Postman-Beispiele helfen, wenn die Dokumentation zu wenig Details bietet, erfordern aber ein separates Firmenkonto und sind aufwendig eingerichtet
    • Bevorzugt werden Alternativen wie Open-Source-hurl-Skripte
    • In den meisten Beispielen gibt es Tippfehler bei Variablennamen
    • Statt {{SleepMeAPI_URL}} muss das groß-/kleinschreibungssensitive {{SleepMeAPI_Url}} verwendet werden
    • Das Beispiel „Set Device Status“ setzt set_temperature_f auf 69 und thermal_control_status auf standby
  • Endpunkte und Antwortstruktur

    • Die API bietet zwei Arten von Endpunkten: für Gerätelisten und für einzelne Geräte
    • GET /devices: Gibt die Liste der mit dem Token verknüpften Geräte zurück
    • GET /devices/{:id}: Gibt die vollständigen Informationen zu einem bestimmten Gerät zurück
    • PATCH /devices/{:id}: Ändert Geräteeigenschaften
    • Jeder Eintrag unter /devices enthält Geräte-ID, benutzerdefinierten Namen und attachments
    • Ob attachments andere verbundene Geräte meint, ist nicht sicher
    • Die Detailantwort ist in die Objekte about, control und status unterteilt
      • about: Nur lesbare Informationen wie Firmware-Version, externe IP, LAN-IP, MAC-Adresse, Modell und Seriennummer
      • control: Änderbare Eigenschaften wie Display-Helligkeit, angezeigte Temperatureinheit, Solltemperatur, Temperatursteuerungsstatus und Zeitzone
      • status: Nur lesbare Zustände wie API-Konnektivität, Wassermangel, Wasserstand von 0 bis 100 und aktuelle Wassertemperatur
    • Eigenschaften in control können je nach Gerät variieren; auch nicht dokumentierte Schlüssel wie brightness_level werden teils zurückgegeben
    • thermal_control_status ist active oder standby und gibt an, ob das Gerät die Temperatur aktiv regelt
  • Temperaturwerte und Gerätesteuerung

    • Fahrenheit-Temperaturen werden als Ganzzahlen, Celsius-Temperaturen als Fließkommazahlen behandelt
    • Der normale Bereich liegt bei 55~115°F bzw. 13.0~48.0°C
    • MAX_COLD wird als -1 oder -1.0, MAX_HEAT als 999 oder 999.0 dargestellt
    • Wenn im Standby status.water_temperature_* den Wert -1 hat, scheint das ein Sentinel-Wert zu sein, ist aber nicht dokumentiert
    • Beim Ändern von Geräteeigenschaften wird eine PATCH-Anfrage mit nur den zu ändernden Schlüsseln im JSON-Body gesendet
    • Um nur die Fahrenheit-Temperatur auf 73 zu setzen, wird { "set_temperature_f": 73 } gesendet
    • Es ist nicht nötig, alle Steuerungsschlüssel einzuschließen oder sie in { "control": ... } zu verpacken
    • Diese Request-Form wurde nicht durch die offizielle Dokumentation, sondern über die Postman-Collection bestätigt

Aufbau und Verwendung von bedctl

  • bedctl wurde rund um ein Zig-Modul gebaut; die CLI ist nur ein schlanker Wrapper, der diese Bibliothek aufruft
  • Der Name folgt der Konvention, Steuerprogramme mit dem Suffix -ctl zu versehen, und spielt auch darauf an, dass „bed cuttle“ wie „bed cuddle“ klingt
  • Die wichtigsten Befehle sind:
    • bedctl devices: Namen und IDs der für das Token registrierten Geräte abrufen
    • bedctl status: Firmware, Netzwerkadressen, Modell, Solltemperatur, Betriebsstatus, Wasserstand und gemessene Temperatur abrufen
    • bedctl set temp 74: Zieltemperatur setzen
  • Token und Geräte-ID lassen sich per Umgebungsvariablen festlegen oder mit den Flags --token und --device übergeben

Warum Zig gewählt wurde und welche Abhängigkeiten es gibt

  • Rust wurde beruflich etwa 5 Jahre und privat seit 2018 genutzt, doch für dieses Projekt wurde das zuletzt bevorzugte Zig gewählt, um unmittelbares Feedback und geringere mentale Last zu haben
  • Auf einem M1 Max MacBook Pro aktualisiert zig build check --watch -fincremental in etwa 75 ms
  • Die einzige externe Abhängigkeit der CLI ist ein aus dem Code von TigerBeetle extrahierter, angepasster und auf Zig 0.16.0 portierter argument parser
  • Die Bibliothek hat außer der Zig-Standardbibliothek keine Abhängigkeiten und verwendet für HTTP-Anfragen std.http.Client
  • Die CLI wird nicht mit libc gelinkt, und auch die geplante dynamische Bibliothek soll ohne libc auskommen
  • Dank der eingebauten Cross-Compilation von Zig lassen sich Builds für unterstützte Plattformen erzeugen, ohne direkt auf das Zielsystem zugreifen zu müssen

Datenmodell und Typsystem

  • Die zentralen Structs sind Device für Gerätelisten und DeviceStatus für Detailantworten
    • Device enthält id, name und attachments
    • DeviceStatus besteht aus Device.About, Device.Control und Device.Status
  • Da Control-Eigenschaften je nach Modell fehlen können, werden Helligkeit, Anzeigeeinheit, Solltemperatur, Betriebsstatus und Zeitzone als optionale Werte dargestellt
  • Statt JSON-Strings direkt zu verwenden, nutzt der Code anonyme Enums von Zig
    • Die Temperatureinheiten sind .c und .f
    • Die Zustände der Temperaturregelung sind .active und .standby
  • Für die in Fahrenheit gesetzte Zieltemperatur geben Enum-Namen bestimmten Ganzzahlen eine Bedeutung
    • Statt sich -1 zu merken, kann .max_cold verwendet werden
    • Normale Temperaturen lassen sich als Integer-Literale wie 78 übergeben
  • Es wurde kein Weg gefunden, allein über Typen den normalen Bereich von 55~115°F zu erzwingen, und vor dem Request erfolgt auch keine separate Validierung
  • Da Celsius-Werte Fließkommazahlen sind, lässt sich der erlaubte Bereich ebenfalls nicht über Typen ausdrücken

Erfahrungen mit der Implementierung des Zig-HTTP-Clients

  • Der HTTP-Client der Zig-Standardbibliothek verlangt einen niedrigeren Abstraktionsgrad als ein einfaches Schema aus URI, Body und send
    • URI-Objekt erstellen
    • URI ändern, um den Pfad festzulegen
    • Request-Objekt mit Basis-URI, Headern und Verbindungseinstellungen erstellen
    • Request-Header senden
    • Response-Header empfangen
    • Reader für den Body erstellen
    • Response-Body über den Reader konsumieren
  • Feine Kontrolle ist möglich, aber anders als in Rust, wo man nur bei Bedarf auf eine niedrigere Ebene geht, fühlt sich Zig so an, als arbeite man ständig auf niedriger Ebene
  • Die /devices-Implementierung sendet einen GET-Request mit Authentifizierungs-Header per sendBodiless(), liest die Antwort bis maximal 64.000 Byte und parst das JSON zu []const Device
  • Es wird parseFromSliceLeaky verwendet, aber dank eines nicht nach außen exponierten Arena-Allocator-Setups gibt es keine Probleme mit Speicherfreigabe

Geplante Erweiterung zur dynamischen Bibliothek

  • Das Endziel ist eine abhängigkeitslose dynamische Bibliothek, die sich aus höherwertigen Programmiersprachen verwenden lässt
  • Die geplante Struktur ist wie folgt:
    • Zig-Modul bedctl
    • CLI bedctl, die das Zig-Modul direkt verwendet
    • libbedctl, das dem Zig-Modul eine C-Schnittstelle bereitstellt
    • bedctl-dl, das die dynamische Bibliothek nutzt und die C-Schnittstelle selbst validiert
  • Falls ein Python-Wrapper entsteht, würde der Autor ihn gern mit Home Assistant nutzen, plant aber nicht, ihn selbst zu schreiben
  • Build und Schnittstelle der dynamischen Bibliothek sind noch nicht fertig und sollen in naher Zukunft ergänzt werden

Schlaferfahrung nach einigen Tagen Nutzung

  • In den wenigen Tagen der Nutzung wurde subjektiv besser geschlafen, und auch der Fitness-Tracker zeigte längere Erholungsschlafphasen und weniger nächtliches Erwachen
  • Selbst an Tagen mit Whiskey wurde besser geschlafen als sonst, was aber nicht so verstanden werden darf, dass Alkohol gut für den Schlaf sei
    • Alkohol bleibt gesundheitlich und für den Schlaf schädlich; möglich ist nur, dass das Gerät einen Teil der Verschlechterung abgefedert hat
  • Das Gerät wurde erst wenige Tage genutzt, und auch bedctl entstand in etwa drei Nächten, daher befinden sich die Ergebnisse noch in einer Honeymoon-Phase
  • Als die Temperatur anfangs zu niedrig eingestellt war, fühlte es sich kühl an, als würde man auf einer nassen Stelle liegen; nach Anpassung der Temperatur verschwand das
  • Die Umschaltzeit wurde nicht direkt gemessen, wirkte aber deutlich näher an 1 Minute als an 10 Minuten
    • Da zum Befüllen weniger als eine Gallone Wasser nötig ist, ist die zu erhitzende oder zu kühlende Wärmekapazität nicht groß

Fernbedienung, Ventilator und Heizen

  • Die mitgelieferte Fernbedienung ist ein großer Drehregler mit Touchscreen, mit dem sich die Temperatur während des Feintunings von Zeitplänen leicht sofort ändern lässt
  • Die Haptik des Reglers ist nicht besonders überzeugend, aber er vibriert pro Temperatureinheit, sodass sich Anpassungen auch ohne Blick auf das Display vornehmen lassen
    • Selbst mit Schlafmaske lässt sich die Änderung dank haptischem Feedback erkennen
  • Ein leichter Luftstrom wird weiterhin benötigt; früher musste dabei zugleich eine Stärke gewählt werden, die den Raum kühlt, aber weder direkt auf den Körper trifft noch die Atemwege austrocknet
  • Seit der Nutzung des Chilipad reicht es, den Ventilator nur auf der niedrigsten Stufe laufen zu lassen
  • Wenn die Temperatur morgens leicht erhöht wird, fühlt sich das gemütlich an, und im Winter wird eine Vorwärmfunktion fürs Bett erwartet
  • Durch den Topper nimmt die Atmungsaktivität der Unterlage etwas ab
    • Es fühlt sich nicht an, als läge man auf Plastik, aber bei höheren Temperaturen wirkte die Haut an den Kontaktstellen zum Bett minimal verschwitzt
    • Das kann an den persönlichen Eigenheiten der Temperaturregulation liegen und muss für andere Nutzer nicht genauso gelten
  • Der erste Eindruck ist insgesamt positiv; nach Fertigstellung der dynamischen Bibliothek könnte ein Folgebeitrag erscheinen

1 Kommentare

 
Lobste.rs-Kommentare
  • Passend zum Thema wurde dieser Beitrag direkt vor dem Einschlafen gepostet

    • Ich frage mich, ob man bedctl auch zum Aufwecken nutzen könnte, wenn man es so einstellt, dass die Temperatur zu einer bestimmten Uhrzeit sehr niedrig wird
  • Sowohl der Titel als auch der Beitrag sind großartig. Ich frage mich, ob auch Gewichtsdecken ausprobiert wurden und ob sie tatsächlich geholfen haben

    • Früher habe ich eine Gewichtsdecke benutzt und mochte sie im Großen und Ganzen, aber beim Umzug habe ich sie weggegeben. Für die Regulierung der Körpertemperatur hat sie allerdings nicht geholfen, also war das nicht die Lösung, die ich hier gesucht habe
      Je nach Machart kann sie schlecht belüftet und außerdem teuer sein. Nach dem Kauf eines Chilipad ist es mir zwar fast peinlich, etwas als teuer zu bezeichnen, aber ein Produkt, das ich mir für später gemerkt habe, weil es atmungsaktiv wirkt, ist das offen gewebte https://bearaby.com/products/tree-napper
  • Ich habe mich auch schon nach solchen Produkten umgesehen und denke, dass ich eines Tages selbst eines ausprobieren werde. Laut diesem Video ist ein Eimer die beste Lösung in Sachen Preis-Leistung, aber in dem Fall gibt es wohl keine API

    • Das Video habe ich auch gesehen, aber ich glaube nicht, dass ein Eimer von Home Depot den nicht existierenden Spouse Approval Test bestehen würde 😅
  • Ein einigermaßen verwandter Beitrag: https://trufflesecurity.com/blog/removing-jeff-bezos-from-my-bed (Diskussion)

  • Bei dem Vergleich von Fahrenheit und Celsius war vermutlich nicht Celsius is the better temperature gemeint

  • Der Beitrag ist unterhaltsam, und ich kann die Denkweise in vielen Punkten nachvollziehen, etwa beim Teil über Ventilatoren, aber es ist nicht klar, was sich mit dieser Arbeit nun steuern lässt
    Der Absatz darüber, dass man wegen der Erfahrung aus der Physikpromotion Wissenschafts- und Gesundheitsberichte anzweifelt, bis sie belegt sind, lässt sich leicht in eine gefährliche Richtung lesen, ähnlich wie Impfmisstrauen. Ich verstehe es aber so, dass die Promotion dazu geführt hat, mediale „Fakten“ nicht schwarzweiß zu sehen, und frage mich, was konkret diese Spuren hinterlassen hat

    • Gemeint ist genau das Gegenteil. Nur weil ich Physiker bin, werden meine Instinkte in medizinischen Fragen nicht automatisch besonders wertvoll, also ist es besser, den Fachleuten zu folgen, die das Gebiet tatsächlich erforscht haben, statt nach ein paar gelesenen Artikeln Arzt zu spielen. Es geht nicht um blinden Gehorsam gegenüber Autorität, sondern darum, die eigene Fehleranfälligkeit anzuerkennen und dieselbe Achtung vor Expertise zu zeigen, die ich mir in den wenigen Bereichen wünsche, die ich selbst erforscht habe
      Als Andrew Wakefields Impfstoff-Artikel erschien, sahen manche Leute nur einen kurzen Bericht eines Journalisten, der die Zusammenfassung gelesen hatte, und behaupteten dann mit absoluter Sicherheit, Impfstoffe seien gefährlich; sogar ein Biologielehrer an einer Highschool mit Master in Zoologie und drei promovierte Physiker sprachen sich gegen Impfungen aus. Der medizinische Konsens blieb jedoch, dass Impfstoffe sicher und wirksam sind und zu den stärksten lebensrettenden Maßnahmen überhaupt gehören, und auch alle medizinischen Forschenden, denen ich begegnet bin, waren sich darin einig
      Verletzend an der Promotionszeit war für mich, zu erkennen, wie groß die Lücke zwischen tatsächlichen Entdeckungen in meinem Fach und deren Darstellung in den Nachrichten ist. Da man nicht jedes Gebiet vollständig verstehen kann, sollte man in der Medizin Ärzten, bei Umweltfragen Ökologen und beim Klima Klimawissenschaftlern vertrauen. Ich habe promovierte Physiker erlebt, die meinten, Fachleute mit Mathematik auf Mittelschulniveau und Naturwissenschaft auf Grundschulniveau „widerlegen“ zu können, während echte Experten den enormen Unterschied zwischen Schulwissen und Wissen über die Realität kannten. Weil ich diese Lücke in den Bereichen gesehen habe, die ich selbst studiert habe, vertraue ich in den Bereichen, die ich nicht studiert habe, Experten umso mehr
  • Wenn man einfach beliebige Felder in der gewünschten Struktur hineinschmeißen kann, macht der Handler mit ziemlicher Sicherheit etwas wie eine Regex-Suche mit re.search('set_temperature_f\": (\\d+)',...)