5 puntos por GN⁺ 2024-03-05 | 1 comentarios | Compartir por WhatsApp
  • Un ingeniero diagnosticado con diabetes tipo 1 en 2020 creó un sistema personal de monitoreo basado en Go para tratar el control de la glucosa como una respuesta a incidentes
  • Como Libre no tiene una API ni SDK oficiales, era difícil integrarlo directamente, pero encontró una ruta para enviar datos de glucosa cada 2 minutos a un endpoint externo pasando por Miao Miao y la app Tomato
  • Con un echo server en Go y un despliegue en Encore, verificó el formato de las solicitudes de Tomato, convirtió los valores SGV y los mostró en un panel de Grafana como un medidor de glucosa en tiempo real
  • Un bot de Telegram deja anotaciones de contexto como comidas, ejercicio e inyecciones de insulina, y un cron que se ejecuta cada 5 minutos crea un incidente en incident.io si la glucosa cae por debajo del umbral
  • Este flujo de trabajo, con alertas, escalamiento y reportes, funciona como un sistema de observabilidad de salud personal que evita tener que enfrentar en soledad una glucosa baja o vacíos de medición

Tratar la diabetes tipo 1 como un problema de respuesta a incidentes

  • La diabetes tipo 1 es una enfermedad autoinmune en la que el páncreas produce poca o nada de insulina, necesaria para convertir los carbohidratos en energía
  • La insulina debe suplementarse mediante inyecciones, y la dosis depende de lo que se come y de muchas otras variables
  • La tipo 1 no es una enfermedad causada por el estilo de vida y actualmente no tiene cura
  • La glucosa en sangre debe monitorearse continuamente
    • Si permanece demasiado alta por mucho tiempo, puede provocar daño en órganos y reducir la esperanza de vida
    • Si está demasiado baja, puede ser mortal incluso en poco tiempo
    • Si la glucosa baja demasiado, quizá no sea posible comer o beber de forma segura y se necesite ayuda de otra persona
  • Cada vez que se ve una comida o bebida hay que calcular la cantidad de carbohidratos y la insulina necesaria, e incluso un ejercicio como una caminata corta debe considerar cuánta insulina activa hay en el cuerpo
  • Una situación en la que se pierde visibilidad de la glucosa puede tratarse de forma similar a un estado de observabilidad cero en un sistema de trabajo
    • En el trabajo, se declararía un incidente y no se cerraría hasta recuperar la visibilidad
    • La glucosa baja es la primera señal de que algo va mal y requiere acción inmediata

Encontrar una ruta de datos con Libre, Miao Miao y Tomato

  • El dispositivo Libre, que se coloca en el brazo, permite leer la glucosa al acercarle el teléfono
    • El dispositivo debe reemplazarse cada 2 semanas
    • Si la glucosa cae por debajo de cierta línea roja, hay que consumir carbohidratos
    • Si sale del rango verde, se pueden considerar acciones como administrar insulina
  • El ejercicio, el aumento de peso y las enfermedades cambian la sensibilidad a la insulina, por lo que el control de la glucosa se vuelve un objetivo en constante movimiento
  • Si Libre muestra un error, no se puede leer la glucosa desde el dispositivo ni recibir alertas de niveles peligrosos
  • Libre es un dispositivo cerrado, por lo que es difícil obtener datos directamente sin una API o SDK
  • Miao Miao se monta sobre Libre, escanea aproximadamente cada 2 minutos y envía el resultado a la app Tomato
    • Aunque la app oficial de Libre mostrara errores, la ruta de Miao Miao seguía publicando datos
    • La app oficial parecía considerar los cambios bruscos de glucosa como valores atípicos y no enviaba los datos, pero el usuario quería poder juzgar esos datos por su cuenta
  • La app Tomato tenía una función para publicar la glucosa como eventos de Google Calendar cada 5 minutos, lo que permitía verla como una complicación en Apple Watch

Verificar las solicitudes de Tomato con un echo server en Go

  • En la configuración de la app Tomato había un campo para ingresar una URL de sincronización de datos para Nightscout
  • Al poner la dirección de un servidor web propio en lugar de una URL de Nightscout, apareció la siguiente ruta en los logs del gateway
/id/e1d67817-4591-4e8e-9bca-58a07a1087d8/api/v1/devicestatus
  • Para revisar el cuerpo de la solicitud, escribió un echo server sencillo en Go
  • Para desplegarlo y ejecutarlo usó encore.dev, lo que le permitió operar el sistema de monitoreo gratis
// 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
    }
}
  • Un echo server devuelve tal cual los datos enviados por el cliente, y es útil para resolver problemas de red o probar el comportamiento de una aplicación
  • Con el mismo método revisó otras solicitudes y obtuvo una respuesta que contenía datos de glucosa
- date: 1696171541297
sgV: 73
delta: 0
sysTime: 1696171541381
dateString: "2023-10-01T14:45:41.297Z"
_id: "dOUXaI8HcaulCGrQfxe23UE0"
type: "sgv"
device: "Tomato"
direction: "Flat"
  • sgV es el valor de glucosa, y se divide entre 18 para ajustarlo a la unidad usada en Reino Unido
  • La respuesta también incluye fecha, hora y dirección de la tendencia
  • Esta llamada ocurre cada 2 minutos

Panel de Grafana y medidor de glucosa

  • El valor de glucosa recibido se configuró como una Gauge metric
  • Un medidor es una métrica que representa un único valor que puede subir o bajar, y se usa para medir valores variables como uso de memoria, cantidad de solicitudes concurrentes o temperatura
  • El valor de glucosa se convierte y registra como newValue / 18
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)
}
  • Los datos de glucosa también se guardan en Postgres con un enfoque de mejor esfuerzo
    • Si falla el guardado en la DB, solo se deja un log y se continúa, para no hacer fallar el resto de la lógica
  • El panel de Grafana muestra en tiempo real un medidor de glucosa que se actualiza cada 2 minutos
  • El rango objetivo de glucosa idealmente está entre 4 y 9
  • Al compartir el panel o poner un monitor en casa, se puede revisar el estado de la glucosa de un vistazo

Agregar contexto de glucosa con un bot de Telegram

  • Los valores de glucosa por sí solos no son suficientes; como en el monitoreo de sistemas complejos, el contexto es importante
  • Aunque la glucosa suba justo después de comer, si ya se aplicó insulina quizá no sea una situación para preocuparse de inmediato
  • Grafana soporta anotaciones, pero tener que iniciar sesión y agregar anotaciones manualmente resulta engorroso
  • Se creó un bot de Telegram configurado para agregar una anotación mediante un webhook cada vez que recibe un mensaje
// 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
    }
}
  • El webhook recibe la solicitud, valida el mensaje, hace un unmarshal del JSON y devuelve el resultado del procesamiento a Telegram
  • Después de validar el mensaje, parsea un entero y llama al servicio de anotaciones
  • El servicio de anotaciones agrega etiquetas según el tipo de actividad
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"}
    }
}
  • En Grafana se pueden definir colores por etiqueta y configurar consultas de anotaciones
  • Cuando en la gráfica aparece contexto como comidas, ejercicio o inyecciones de insulina, tanto la persona como quienes ven el panel pueden interpretar más fácilmente la situación de la glucosa

Convertir la glucosa baja en un incidente

  • Ya se había logrado visibilidad sobre la glucosa, pero sin alertas era difícil responder en tiempo real
  • Según las indicaciones recibidas de la enfermera, si la glucosa baja de 4 hay que empezar el tratamiento
  • Se escribió un pequeño cron que revisa las mediciones cada 5 minutos y, si están por debajo de un límite inferior predefinido, dispara un incidente
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)
    }
}
  • Al bot de Telegram también se le agregó código para abrir un incidente manual con el mensaje "i need help"
  • Cuando se dispara un incidente, un microservicio separado crea un incidente en incident.io
  • Se eligió incident.io porque era lo más parecido a la herramienta interna de incidentes de Cloudflare y porque está escrito completamente en Go
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",
}
  • Usar una herramienta real de incidentes permite configurar políticas de escalamiento y ver reportes como el tiempo pasado en estado de incidente
  • Los workflows de incident.io permiten configurar reglas parecidas a Zapier y enviar alertas por SMS a suscriptores
  • En el workflow de ejemplo, cuando se abre un incidente se envía un SMS al propio usuario, y si no se cierra durante 20 minutos se escala automáticamente a su pareja o a sus hermanos

Reportes y mejoras futuras

  • Al usar una herramienta de incidentes, se pueden ver reportes de cuántos incidentes de glucosa baja ocurrieron a lo largo del tiempo
  • La gráfica de ejemplo usa datos de demostración para el blog; por suerte, los datos reales son mucho más aburridos
  • Si los eventos de glucosa baja aumentan, puede ser una señal de que el tratamiento actual no es el adecuado y servir como base para consultarlo con un médico
  • Las mejoras actuales o planificadas son las siguientes
    • Cierre automático: por ahora los incidentes se cierran manualmente para revisar los datos, pero algunas veces se cerraron tarde y escalaron; si la glucosa se mantiene estable unos 15 minutos, podrían cerrarse automáticamente
    • Conversar con los datos: se han almacenado años de datos de glucosa, y se quiere entrenar un LLM para hacer preguntas como “¿por qué siempre baja a las 3 p. m.?” y usar también otros datos como Google Calendar
    • Ampliar la gráfica: la gráfica actual es simple, pero se podrían agregar indicadores como hba1c para evaluar el éxito del control de la diabetes
    • Refuerzo contra fallas: como el sistema es importante, cuanto más se puedan prevenir fallas, mejor

Un sistema personal de operaciones de salud creado con código

  • Al inicio del diagnóstico de tipo 1 existía el temor de que la enfermedad hiciera la vida difícil
  • Este proyecto ayuda a entender, gestionar y monitorear la condición de tipo 1
  • El control de la glucosa se trata como un sistema distribuido, convirtiéndolo en un sistema personal de operaciones con observabilidad, alertas, incidentes, escalamiento y reportes
  • La capacidad de programar permite automatizar en cierta medida la gestión de una enfermedad que hasta la década de 1920 era una sentencia de muerte

1 comentarios

 
GN⁺ 2024-03-05
Opiniones en Hacker News
  • Llevo 16 años viviendo con diabetes, y el tono del autor me parece bueno y admirable. Cuando te sientas triste o enojado por la enfermedad, ojalá vuelvas a leer este texto y recuerdes este momento en el que estabas convencido de que podías con todo
    No es fácil. Ni mentalmente ni en lo práctico; en mi caso, durante varios años estuve casi “felizmente fuera de control”
    Ayer mismo, por primera vez en mi vida con diabetes, vi 36 horas dentro del rango objetivo y literalmente lloré. Fueron 36 horas 100% en verde. Quizá por fin lo entendí
    Que mi calidad de vida subiera años después hasta algo como 60% fue gracias a un microinfusor conectado a un CGM, a compartir experiencias con otras personas con diabetes, a instalar una VM de NightScout para ver la glucosa y la tendencia en el teléfono, el reloj, widgets de escritorio, el despertador y el refrigerador, y a contar carbohidratos con precisión alemana y aplicarme el bolo exactamente 15 minutos antes de comer. Odio vivir así, pero funciona
    Aguanta. No te desordenes

  • El estilo de escritura es realmente bueno y fue un gusto leerlo. Por coincidencia trabajo en pruebas de penetración, y uno de mis compañeros tiene diabetes tipo 1
    Ver el panorama que plantea este texto y las complejidades que implica me hizo empatizar más con ese compañero, que aun superando esas dificultades todos los días sigue siendo una de las personas más amables y accesibles del equipo

    • Se puede llevar una vida normal con diabetes, e incluso ser un tenista de élite: https://en.wikipedia.org/wiki/Alexander_Zverev#Personal_life
      Pero después de leer esto, de verdad se siente el nivel de autodisciplina necesario para vivir así
    • Si “pentesting” fuera probar plumas de insulina, se podría bromear con que parte de las pruebas se hacen con pluma y papel
      Claro que también podría ser lo de intentar entrar rompiendo sistemas, como en pruebas de penetración; me da curiosidad si eso es lo que hace
    • Parece que encontró un buen empleador. Muchas empresas no contratan a empleados enfermos o incluso los despiden, y en la práctica es común aconsejar no compartir información médica en el trabajo
      Hace poco leí un caso de un empleado del que todos esperaban que fuera ascendido, pero no lo fue. Su único “pecado” fue haberle comentado brevemente a un colega que su auto se descomponía y que estaba cansado de repararlo con frecuencia
      El ascenso requería cierto nivel de traslado, y al parecer el gerente le dijo: “iba a ascenderte, pero escuché que tu auto no está en buen estado”
  • Después de que Matt dio esta charla en GopherConSG, hablamos del problema de no ser dueños de nuestros propios datos. Me impresionó lo complejo que es el asunto por la gran responsabilidad legal que recae del lado del proveedor de datos, es decir, la empresa que monitorea la glucosa, y también entiendo por qué las grandes compañías dudan en abrirlos
    Por otro lado, parece bastante injusto que los usuarios no puedan acceder a datos que legítimamente son suyos y que pueden usar para tomar acciones reales

    • Esta parte nunca la entiendo. ¿Es parecido a comprar una pluma BIC y firmar un contrato de licencia obligatorio que diga que toda la entropía generada con esa pluma pertenece al fabricante de la herramienta y no al autor de los datos? Sin la persona, esos datos ni siquiera existirían
  • Ayer hice algo relacionado: un plugin de tmux que muestra datos de glucosa como ícono de estado en la terminal
    Yo también tengo diabetes tipo 1 y uso Dexcom como CGM; por ahora lo dejé funcionando para ese entorno, pero me gustaría soportar otros dispositivos y agregar más funciones. Si a alguien le interesa, puede verlo aquí
    https://github.com/Cian911/tmux-xdrip

    • Ojalá Dexcom se sincronizara directamente con el reloj. Llevo años esperando eso, aunque probablemente consumiría mucha batería del reloj
    • Como persona con diabetes tipo 1 que vive dentro de tmux, esto está genial. Tengo que probarlo cuanto antes
  • La idea de Miao Miao es interesante. Como persona con diabetes tipo 1, Freestyle Libre es un dispositivo increíble que realmente me cambió la vida, pero el software es bastante malo
    Reporté un bug hace más de un año, y Abbott todavía no lo reconoce como bug. Eso pese a que hay muchos reportes iguales en línea y en las reseñas de la app en Google Play
    Para quien tenga interés o pueda ayudar a que Abbott lo reconozca: el bug consiste en que poner LibreLink en la lista de apps exceptuadas del modo No molestar no sirve de nada; en cuanto entras en modo No molestar aparece de inmediato una advertencia de que “las alarmas no están disponibles”. Es molesto porque si activas No molestar en un entorno de trabajo, también se apagan las alarmas de glucosa

  • Algo un poco relacionado: hace 6 meses me diagnosticaron apnea obstructiva del sueño, y tengo que usar una máquina CPAP que insufla aire a una presión constante mientras duermo para evitar que se obstruyan las vías respiratorias. No es tan crítico para la misión como la diabetes tipo 1, pero estas máquinas registran muchos más logs de lo que esperaba
    Al leer este artículo me dio curiosidad si en el mundo de la apnea del sueño existe algo hackeado de forma similar para monitoreo o para casos más graves
    Ya conozco OSCAR y lo uso con mucho agradecimiento, pero también me pregunto qué más hay
    1: https://www.sleepfiles.com/OSCAR/

    • Yo diría que sí está directamente ligado a la vida. CPAP me cambió la vida, y la apnea del sueño no tratada durante mucho tiempo causa problemas cardíacos y muchos otros problemas de salud
      En mi estudio del sueño, en el peor momento se registraron unas 48 interrupciones de respiración por minuto. Cuando la lengua se te enrolla hacia la vía respiratoria, respirar se vuelve bastante difícil
    • Si soporta tu dispositivo, https://home.sleephq.com/ maneja muy bien estos datos
  • Es interesante, pero me pregunto por qué no revisó el software de código abierto de este ámbito, como Nightscout, xDrip, etc.
    No es un problema nuevo, y mucha gente ya lo resolvió con soluciones mucho más ricas en funciones y que funcionan bien

    • Sí lo revisé. Para lo que quería hacer, me pareció más rápido empezar desde cero, y también fue una experiencia de aprendizaje interesante
  • Scott Hanselman lleva años hablando en su blog y en YouTube sobre diabetes tipo 1 y varios hacks tecnológicos. Hace tiempo incluso hizo un hack para que la glucosa apareciera en el prompt de la terminal: https://www.youtube.com/watch?v=_meKUIm9NwA

  • Los pasajes “durante este periodo el dispositivo no puede medir la glucosa, y aunque la glucosa llegue a un nivel peligroso no recibes notificaciones; este error tenía la costumbre de aparecer en los momentos más estresantes” y “al revisar, parece que a la app principal no le gusta enviar datos cuando el nivel de glucosa cambia de golpe y parece un valor atípico” suenan como bugs que ponen en riesgo la vida

    • La mayoría de los sensores funcionan así. Se asume que el sensor siempre es preciso, pero en realidad no lo es. Por ejemplo, si mientras duermes te giras y quedas encima del sensor, la tira de glucosa oxidasa puede presionarse más hacia dentro del cuerpo y cambiar la lectura
      Estrictamente hablando, no deberías tomar decisiones de tratamiento basándote solo en datos de CGM
      En el caso de los sensores Dexcom, algunas apps pueden obtener los valores crudos y saltarse este proceso. En Libre, al menos en Libre 3, he visto que en ciertas situaciones rellena los datos más tarde cuando decide que no fue una lectura errónea, sino que la glucosa estaba cambiando rápidamente
  • No está basado en tecnología, pero también existen los perros de alerta para diabetes
    Últimamente estoy aprendiendo que un perro bien entrenado puede tener mucho éxito complementando sistemas tecnológicos de monitoreo y alerta para avisarle a su cuidador