- Ein Ingenieur, bei dem 2020 Typ-1-Diabetes diagnostiziert wurde, baute ein persönliches Monitoring-System auf Go-Basis, um das Management seines Blutzuckers wie Incident Response zu behandeln
- Da es für Libre keine offizielle API oder SDK gibt, war eine direkte Anbindung schwierig, aber über Miao Miao und die Tomato-App fand er einen Weg, alle 2 Minuten Blutzuckerdaten an einen externen Endpoint zu senden
- Mit einem Go-Echo-Server und Deployment über Encore prüfte er das Anfrageformat von Tomato, wandelte den SGV-Wert um und zeigte ihn in einem Grafana-Dashboard als Echtzeit-Blutzucker-Gauge an
- Ein Telegram-Bot hinterlässt Kontext-Anmerkungen wie Mahlzeiten, Bewegung und Insulininjektionen, und ein alle 5 Minuten laufender Cron erzeugt einen incident.io-Incident, wenn der Blutzucker unter den Grenzwert fällt
- Dieser Workflow mit Benachrichtigungen, Eskalationen und Reports funktioniert als System für persönliche Gesundheits-Observability, damit niedriger Blutzucker oder Messlücken nicht allein bewältigt werden müssen
Typ-1-Diabetes als Incident-Response-Problem behandeln
- Typ-1-Diabetes ist eine Autoimmunerkrankung, bei der die Bauchspeicheldrüse kaum oder gar kein Insulin produziert, das benötigt wird, um Kohlenhydrate in Energie umzuwandeln
- Insulin muss per Injektion zugeführt werden, und die benötigte Menge hängt von der Nahrung und verschiedenen weiteren Faktoren ab
- Typ 1 entsteht nicht durch den Lebensstil, und es gibt derzeit keine Heilung
- Der Blutzucker muss fortlaufend überwacht werden
- Ist er zu lange zu hoch, kann das zu Organschäden und einer verkürzten Lebenserwartung führen
- Ist er zu niedrig, kann das schon nach kurzer Zeit lebensgefährlich werden
- Wenn der Blutzucker zu stark absinkt, kann man unter Umständen nicht mehr sicher essen oder trinken und braucht die Hilfe anderer
- Bei jedem Essen oder Getränk muss die Menge an Kohlenhydraten und die nötige Insulinmenge berechnet werden, und selbst Bewegung wie ein kurzer Spaziergang muss unter Berücksichtigung des aktiven Insulins im Körper eingeplant werden
- Situationen, in denen die Sichtbarkeit des Blutzuckers verloren geht, lassen sich ähnlich behandeln wie ein Zustand von 0 Observability in einem Produktionssystem
- Im Job würde man einen Incident ausrufen und ihn erst schließen, wenn die Sichtbarkeit wiederhergestellt ist
- Niedriger Blutzucker ist das erste Signal, dass etwas nicht stimmt, und erfordert sofortiges Handeln
Mit Libre, Miao Miao und Tomato einen Datenpfad finden
- Das am Arm befestigte Libre-Gerät kann den Blutzucker auslesen, wenn ein Smartphone in die Nähe gehalten wird
- Das Gerät muss alle 2 Wochen ausgetauscht werden
- Fällt der Blutzucker unter eine bestimmte rote Linie, müssen Kohlenhydrate aufgenommen werden
- Verlässt er den grünen Bereich, kann man Maßnahmen wie eine Insulingabe in Betracht ziehen
- Bewegung, Gewichtszunahme und Krankheit verändern die Insulinsensitivität, deshalb ist Blutzuckermanagement ein ständig wanderndes Ziel
- Zeigt Libre einen Fehler an, lassen sich weder Blutzuckerwerte vom Gerät ablesen noch Warnungen bei gefährlichen Werten empfangen
- Libre ist ein geschlossenes Gerät, daher ist es ohne API oder SDK schwer, direkt an die Daten zu kommen
- Miao Miao wird auf dem Libre angebracht, scannt etwa alle 2 Minuten und sendet die Ergebnisse an die Tomato-App
- Selbst wenn die Standard-Libre-App einen Fehler anzeigt, veröffentlicht der Pfad über Miao Miao weiterhin Daten
- Die Standard-App scheint starke Blutzuckerschwankungen als Ausreißer zu behandeln und keine Daten zu senden; der Nutzer wollte solche Daten aber selbst beurteilen
- Die Tomato-App hatte eine Funktion, Blutzuckerwerte alle 5 Minuten als Google-Calendar-Events zu veröffentlichen, sodass der Blutzucker in einer Apple-Watch-Complication sichtbar war
Tomato-Anfragen mit einem Go-Echo-Server prüfen
- In den Einstellungen der Tomato-App gab es ein Eingabefeld für eine Daten-Sync-URL für Nightscout
- Als statt einer Nightscout-URL die Adresse eines selbst betriebenen Webservers eingetragen wurde, erschien im Gateway-Log folgender Pfad
/id/e1d67817-4591-4e8e-9bca-58a07a1087d8/api/v1/devicestatus
- Um den Anfrage-Body zu prüfen, schrieb er einen einfachen Echo-Server in Go
- Für Deployment und Betrieb nutzte er encore.dev, wodurch sich das Monitoring-System kostenlos betreiben ließ
// encore:api public raw method=POST path=/id/:id/api/v1/devicestatus
func Echo(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", req.Header.Get("Content-Type"))
if _, err := io.Copy(w, req.Body); err != nil {
http.Error(w, "Failed to echo request", http.StatusInternalServerError)
return
}
}
- Ein Echo-Server gibt die vom Client gesendeten Daten unverändert zurück und ist nützlich zur Fehlersuche bei Netzwerkproblemen oder zum Testen des Verhaltens einer Anwendung
- Mit derselben Methode prüfte er weitere Anfragen und erhielt eine Antwort mit den Blutzuckerdaten
- date: 1696171541297
sgV: 73
delta: 0
sysTime: 1696171541381
dateString: "2023-10-01T14:45:41.297Z"
_id: "dOUXaI8HcaulCGrQfxe23UE0"
type: "sgv"
device: "Tomato"
direction: "Flat"
sgV ist der Blutzuckerwert; um ihn auf die im Vereinigten Königreich verwendete Einheit umzurechnen, wurde er durch 18 geteilt
- Die Antwort enthält außerdem Datum, Uhrzeit und Trendrichtung
- Dieser Aufruf erfolgt alle 2 Minuten
Grafana-Dashboard und Blutzucker-Gauge
- Der empfangene Blutzuckerwert wurde als Gauge-Metrik gesetzt
- Ein Gauge ist eine Metrik für einen einzelnen Wert, der steigen oder fallen kann, und wird für schwankende Größen wie Speichernutzung, gleichzeitige Requests oder Temperatur verwendet
- Der Blutzuckerwert wurde als
newValue / 18 umgerechnet und gespeichert
var BloodSugar = metrics.NewGauge[float64]{
name: "blood_sugar",
metrics.GaugeConfig{},
}
BloodSugar.Set(float64(newValue) / 18)
if err := insertReading(ctx, newValue); err != nil {
rlog.Error(msg: "failed to insert blood sugar, proceeding", keysAndValues: "db_err", err)
}
- Die Blutzuckerdaten wurden nach dem Best-Effort-Prinzip zusätzlich in Postgres gespeichert
- Ein Fehler beim Schreiben in die DB soll die übrige Logik nicht scheitern lassen, daher wird nur ein Log geschrieben und dann fortgefahren
- Das Grafana-Dashboard zeigt in Echtzeit ein Blutzucker-Gauge, das alle 2 Minuten aktualisiert wird
- Der Zielbereich für den Blutzucker liegt idealerweise zwischen 4 und 9
- Wenn man das Dashboard teilt oder zu Hause einen Monitor dafür aufstellt, lässt sich der Blutzuckerstatus auf einen Blick erfassen
Mit einem Telegram-Bot Blutzucker-Kontext ergänzen
- Der reine Blutzuckerwert reicht nicht aus; wie beim Monitoring komplexer Systeme ist Kontext entscheidend
- Steigt der Blutzucker direkt nach einer Mahlzeit, ist das möglicherweise nicht sofort besorgniserregend, wenn bereits Insulin gespritzt wurde
- Grafana unterstützt Annotationen, aber sich einzuloggen und sie manuell zu hinterlassen, ist umständlich
- Deshalb wurde ein Telegram-Bot gebaut, der bei jeder Nachricht per Webhook eine Annotation hinzufügt
// encore:api public raw method=POST path=/webhook
func Webhook(w http.ResponseWriter, req *http.Request) {
body, err := io.ReadAll(req.Body)
if err != nil {
http.Error(w, "could not read request body", http.StatusBadRequest)
return
}
defer req.Body.Close()
var update Update
err = json.Unmarshal(body, &update)
if err != nil {
http.Error(w, "could not unmarshal JSON", http.StatusBadRequest)
return
}
}
- Der Webhook nimmt die Anfrage entgegen, validiert die Nachricht, unmarshalt das JSON und sendet das Verarbeitungsergebnis an Telegram zurück
- Nach der Nachrichtenvalidierung wird eine Ganzzahl geparst und der Annotations-Service aufgerufen
- Der Annotations-Service vergibt je nach Aktivität Tags
func getTags(ctx context.Context, activity string) []string {
a := strings.ToLower(activity)
switch a {
case "walk", "run", "ran", "gym":
return []string{"exercise"}
case "eat", "ate":
return []string{"food eaten"}
case "inject":
return []string{"inject"}
default:
return []string{"other"}
}
}
- In Grafana lassen sich Farben pro Tag festlegen und Annotation-Queries konfigurieren
- Wenn Kontext wie Mahlzeiten, Bewegung oder Insulininjektionen im Graphen erscheint, können sowohl der Betroffene selbst als auch andere Betrachter des Dashboards die Blutzuckersituation leichter interpretieren
Niedrigen Blutzucker in einen Incident verwandeln
- Die Sichtbarkeit des Blutzuckers war nun gegeben, aber ohne Alarmierung ist eine Reaktion in Echtzeit schwierig
- Nach Anweisung des Pflegepersonals soll bei einem Blutzuckerwert unter 4 mit der Behandlung begonnen werden
- Dafür wurde ein kleiner Cron geschrieben, der alle 5 Minuten die Messwerte prüft und bei Unterschreitung eines vordefinierten Schwellenwerts einen Incident auslöst
var _ = cron.NewJob(
id: "monitor-blood",
cron.JobConfig{
Title: "monitor blood to check if there is reason to open an incident",
Every: 5 * cron.Minute,
Endpoint: BloodIncidentCron,
},
)
if r < BloodLowerLimit {
if err := triggerIncident(ctx); err != nil {
return fmt.Errorf("failed to trigger an incident: %w", err)
}
}
- Dem Telegram-Bot wurde außerdem Code hinzugefügt, um mit der Nachricht
"i need help" manuell einen Incident zu öffnen
- Wird ein Incident ausgelöst, erstellt ein separater Microservice einen Incident in incident.io
- incident.io wurde gewählt, weil es dem internen Incident-Tool von Cloudflare am ähnlichsten ist und vollständig in Go geschrieben wurde
payload := Payload{
IdempotencyKey: idemKey.String(),
Mode: incidentModeStandard,
Name: fmt.Sprintf("Matt's blood sugar is currently #%s", blood),
SeverityID: incidentSeverityCritical,
Summary: "Matt's blood sugar is low!",
Visibility: "public",
}
- Durch den Einsatz eines echten Incident-Tools lassen sich Eskalationsrichtlinien definieren und Reports etwa über die im Incident-Status verbrachte Zeit einsehen
- Der Workflow in incident.io kann Regeln ähnlich wie bei Zapier konfigurieren und SMS-Benachrichtigungen an Abonnenten senden
- Im Beispiel-Workflow wird beim Öffnen eines Incidents zunächst eine SMS an ihn selbst gesendet; bleibt der Incident 20 Minuten lang offen, wird automatisch an Partner oder Geschwister eskaliert
Reports und künftige Verbesserungen
- Mit einem Incident-Tool lassen sich Reports darüber erstellen, wie häufig Vorfälle mit niedrigem Blutzucker im Zeitverlauf auftreten
- Der Beispiel-Graph zeigt Demo-Daten für den Blog; die echten Daten sind zum Glück deutlich unspektakulärer
- Wenn sich Ereignisse mit niedrigem Blutzucker häufen, kann das ein Signal sein, dass die aktuelle Behandlung nicht passend ist, und eine Grundlage für ein Gespräch mit dem Arzt liefern
- Zu den aktuellen oder geplanten Verbesserungen gehören:
- Automatisches Schließen: Derzeit werden Incidents manuell geschlossen, um die Daten zu prüfen; weil einige zu spät geschlossen wurden und dadurch eskalierten, könnte ein automatisches Schließen erfolgen, wenn etwa 15 Minuten lang stabile Werte gehalten werden
- Daten-Dialog: Es werden bereits mehrere Jahre Blutzuckerdaten gespeichert, und künftig soll ein LLM trainiert werden, um Fragen wie „Warum falle ich immer um 15 Uhr ab?“ zu beantworten und dabei auch andere Daten wie Google Calendar einzubeziehen
- Graph-Erweiterung: Der aktuelle Graph ist einfach, aber es könnten Kennzahlen wie hba1c ergänzt werden, um den Erfolg des Diabetes-Managements zu bewerten
- Stärkere Ausfallsicherheit: Da das System wichtig ist, gilt: Je mehr Fehler verhindert werden, desto besser
Ein persönliches Gesundheits-Betriebssystem aus Code
- Direkt nach der Diagnose von Typ 1 bestand die Angst, dass die Krankheit das Leben stark erschweren würde
- Dieses Projekt hilft dabei, den Zustand zu verstehen, zu managen und zu überwachen
- Das Blutzuckermanagement wurde wie ein verteiltes System behandelt und zu einem persönlichen Betriebssystem mit Observability, Alarmierung, Incidents, Eskalationen und Reports ausgebaut
- Programmierkenntnisse machen es möglich, das Management einer Krankheit, die bis in die 1920er Jahre einem Todesurteil gleichkam, zumindest teilweise zu automatisieren
1 Kommentare
Hacker-News-Kommentare
Ich lebe seit 16 Jahren mit Diabetes und der Ton des Autors ist großartig und bewundernswert. Wenn ich wegen der Krankheit traurig oder wütend bin, will ich diesen Text wieder lesen und mich an den Moment erinnern, in dem ich sicher war, dass ich das alles tragen kann
Es ist nicht leicht. Weder mental noch praktisch, und bei mir war es über viele Jahre eher „fröhlich außer Kontrolle“
Erst gestern habe ich zum ersten Mal in meinem Diabetes-Leben 36 Stunden im Zielbereich gesehen und wirklich geweint. 36 Stunden lang war alles zu 100 % grün. Vielleicht habe ich es jetzt verstanden
Dass meine Lebensqualität ein paar Jahre später um etwa 60 % gestiegen ist, verdanke ich einem mit dem CGM verbundenen Mikro-Infusor, dem Erfahrungsaustausch mit anderen Diabetikern, der Installation einer NightScout-VM, damit ich Blutzucker und Trend überall auf Handy, Uhr, Desktop-Widgets, Wecker und Kühlschrank sehen kann, sowie dem Zählen von Kohlenhydraten mit deutscher Präzision und dem exakt 15 Minuten vorher gesetzten Bolus vor dem Essen. Ich hasse es wirklich, so leben zu müssen, aber es wirkt
Halt durch. Lass nicht nach
Der Schreibstil ist wirklich gut, das Lesen hat Spaß gemacht. Zufällig arbeite ich im Bereich Penetrationstests, und einer meiner Kollegen hat Typ-1-Diabetes
Nachdem ich den Überblick in diesem Text und die dadurch entstehende Komplexität gesehen habe, habe ich noch mehr Mitgefühl für meinen Kollegen, der all diese Schwierigkeiten jeden Tag überwindet und trotzdem einer der freundlichsten und zugänglichsten Menschen im Team ist
Nach der Lektüre dieses Textes spürt man allerdings erst richtig, welches Maß an Selbstdisziplin dafür nötig ist
Natürlich könnte es auch wie bei Penetrationstests darum gehen, in Systeme einzudringen und sie zu knacken, und ich frage mich, ob das seine Arbeit ist
Kürzlich habe ich von einem Fall gelesen, in dem ein Mitarbeiter, von dem alle eine Beförderung erwarteten, sie nicht bekam. Sein einziges „Vergehen“ war, einem Kollegen kurz zu sagen, dass sein Auto kaputt sei und er es ständig reparieren müsse
Die Beförderung hätte ein gewisses Maß an Pendeln erfordert, und der Manager sagte angeblich: „Ich wollte dich befördern, aber ich habe gehört, dass dein Auto in schlechtem Zustand ist.“
Nachdem Matt diesen Vortrag auf der GopherConSG gehalten hatte, sprachen wir über das Problem, dass wir unsere eigenen Daten nicht besitzen. Beeindruckend fand ich, wie komplex die Sache ist, weil auf Seiten der Datenanbieter, also der Unternehmen, die den Blutzucker überwachen, viel rechtliche Verantwortung lastet, und ich verstehe, warum große Firmen zögern, sich zu öffnen
Andererseits wirkt es ziemlich unfair, dass Nutzer keinen Zugang zu Daten haben, die ihnen rechtmäßig gehören und die sie für konkretes Handeln nutzen können
Ich habe gestern etwas dazu gebaut: ein tmux-Plugin, das Blutzuckerdaten als Terminal-Statussymbol anzeigt
Ich habe selbst Typ-1-Diabetes und nutze ein Dexcom-CGM; im Moment funktioniert es für dieses Setup, aber ich würde gern auch andere Geräte unterstützen und den Funktionsumfang erweitern. Wer Interesse hat, kann es hier ansehen
https://github.com/Cian911/tmux-xdrip
Die Idee von Miao Miao ist interessant. Als Typ-1-Diabetiker ist das Freestyle Libre für mich wirklich ein erstaunliches Gerät, das mein Leben verändert hat, aber die Software ist ziemlich schlecht
Ich habe vor mehr als einem Jahr einen Bug gemeldet, aber Abbott hat bis heute nicht eingeräumt, dass es ein Bug ist. Dabei gibt es online und in den App-Bewertungen bei Google Play viele Meldungen zum selben Problem
Für alle, die es interessiert oder Druck auf Abbott ausüben können, damit sie es anerkennen: Es gibt einen Bug, bei dem es nichts bringt, LibreLink zur Ausnahmeliste für den Bitte-nicht-stören-Modus hinzuzufügen, und sobald der Bitte-nicht-stören-Modus aktiv ist, erscheint sofort die Warnung, dass „Alarme nicht verwendet werden können“. In einer Arbeitsumgebung ist es unpraktisch, wenn mit dem Bitte-nicht-stören-Modus auch die Blutzuckeralarme abgeschaltet werden
Etwas am Rand verwandt: Vor sechs Monaten wurde bei mir obstruktive Schlafapnoe diagnostiziert, und ich muss beim Schlafen ein CPAP-Gerät benutzen, das mit konstantem Druck Luft zuführt, um das Verschließen der Atemwege zu verhindern. Nicht ganz so missionskritisch wie Typ-1-Diabetes, aber diese Geräte zeichnen viel mehr Logs auf, als ich erwartet hatte
Beim Lesen dieses Textes habe ich mich gefragt, ob es im Bereich Schlafapnoe ähnliche Hacks für Monitoring oder schwerere Fälle gibt
OSCAR kenne ich bereits und nutze es mit großer Dankbarkeit, aber mich interessiert, was es sonst noch gibt
1: https://www.sleepfiles.com/OSCAR/
Bei der Schlafstudie wurden in der schlimmsten Phase etwa 48 Atemaussetzer pro Stunde registriert. Wenn sich die Zunge in die Atemwege zurückrollt, wird Atmen ziemlich schwierig
Interessant, aber ich frage mich, ob es einen Grund gibt, sich nicht mit Open-Source-Software in diesem Bereich wie Nightscout, xDrip usw. zu beschäftigen
Das ist kein neues Problem, und viele Leute haben es bereits mit deutlich funktionsreicheren und gut funktionierenden Lösungen gelöst
Scott Hanselman bloggt seit Jahren und macht YouTube-Videos über Typ-1-Diabetes und verschiedene technische Hacks dazu. Früher hat er sogar einmal seinen Blutzucker in der Terminal-Eingabeaufforderung anzeigen lassen: https://www.youtube.com/watch?v=_meKUIm9NwA
Die Stellen „In diesem Zeitraum kann man den Blutzucker nicht mit dem Gerät messen, und selbst wenn der Blutzucker gefährliche Werte erreicht, bekommt man keine Benachrichtigung. Dieser Fehler hatte die Angewohnheit, gerade in den stressigsten Momenten aufzutreten“ und „Beim Nachsehen schien es, als würde die Haupt-App keine Daten mögen, bei denen sich der Blutzuckerwert plötzlich stark ändert und deshalb wie ein Ausreißer wirkt“ klingen wie ein lebensgefährlicher Bug
Streng genommen sollte man auf Basis von CGM-Daten allein keine Therapieentscheidungen treffen
Bei Dexcom-Sensoren können manche Apps Rohwerte abrufen und diesen Prozess umgehen. Bei Libre, zumindest beim Libre 3, habe ich gesehen, dass Daten nachträglich ergänzt werden, wenn das System in bestimmten Situationen entscheidet, dass es sich nicht um einen falschen Messwert handelt, sondern darum, dass sich der Blutzucker schnell verändert
Es gibt auch Diabetes-Warnhunde, auch wenn sie nicht technisch basiert sind
Ich habe kürzlich gelernt, dass gut trainierte Hunde sehr erfolgreich technische Monitoring- und Alarmsysteme ergänzen und ihre Halter warnen können