1 pontos por GN⁺ 16 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • Por causa de um quarto quente e sensibilidade à temperatura corporal, comprou um Sleep.me Chilipad 2.0 por US$ 1.700 e desenvolveu o bedctl para controlar a API em nuvem do fabricante
  • O Chilipad combina um topper fino com circulação de água com uma bomba, reservatório e controlador de temperatura, e oferece configuração modular com agendamento de temperatura por dia da semana e instalação começando por um lado da cama
  • A API consulta dispositivos em /devices e /devices/{:id} e usa PATCH para controlar temperatura, estado de funcionamento, brilho da tela, fuso horário etc., além de permitir verificar o nível da água e a temperatura atual da água
  • Escrito em Zig, o bedctl é composto por uma biblioteca sem dependências e uma CLI enxuta, com plano futuro de expansão para uma biblioteca dinâmica libbedctl com interface C
  • No rastreamento inicial do sono, o tempo de sono restaurador aumentou e os despertares noturnos diminuíram, mas ainda é cedo para julgar o efeito de longo prazo por ser apenas uma fase de lua de mel de poucos dias de uso

Por que eu precisava controlar a temperatura da cama

  • O sono ajuda na imunidade, na função cognitiva e na recuperação após atividade física, mas manchetes sobre saúde podem perder nuances científicas, então dou importância a saber se há respaldo de profissionais de saúde ou consenso de especialistas
  • Por causa do TDAH, os pensamentos continuam vindo e é difícil pegar no sono, então reduzo estímulos lendo na cama e mando um sinal de hora de dormir para o sistema nervoso
  • Por traços de autismo, sou sensível a certas texturas e sensações e também tenho dificuldade de regular a temperatura corporal, então para conseguir dormir a temperatura e o peso do cobertor precisam estar adequados
  • O novo apartamento em Portland tem ar-condicionado só na sala e não tem ventilador de teto, então o quarto no andar alto vira o espaço mais quente da casa à noite
    • Também confirmei com um sensor de temperatura que o quarto é o lugar mais quente do apartamento
  • Combinando sono irregular, uso de estimulantes, quarto abafado e sensibilidade à temperatura corporal, decidi gastar dinheiro em um dispositivo de controle de temperatura da cama

Por que escolhi o Chilipad 2.0

  • O Chilipad 2.0 controla a temperatura da cama conectando um topper fino cheio de água a uma unidade com bomba, reservatório e controlador de temperatura
  • O BedJet, que sopra ar com um ventilador, foi descartado porque no verão o vento frio bateria diretamente nos pés
  • O Eight Sleep foi descartado porque até o modelo mais barato custa US$ 3.000, exige assinatura e ainda inclui recursos de IA
  • O Chilipad é um produto modular que pode ser comprado começando por um lado da cama, então o preço inicial é mais baixo
    • Se instalar duas unidades, dá para configurar cada lado com uma temperatura diferente, o que é útil para casais com percepções térmicas diferentes
  • Embora seja um produto conectado à internet, ele oferece modo avião e inclui um controle remoto Bluetooth por padrão
    • Não verifiquei se o modo avião desliga só o Wi‑Fi ou bloqueia toda conexão sem fio
    • No começo entendi errado e achei que fosse uma API local, mas na prática ele se comunica com um serviço em nuvem
  • O fabricante fornece uma API para desenvolvedores, uma coleção do Postman, uma Swagger UI online e um esquema OpenAPI

Estrutura do dispositivo Chilipad

  • O Chilipad é composto pelo dock, que é a unidade de controle, e por uma cover com circulação de água
    • O dock contém o controlador de temperatura, a bomba e o reservatório
    • Ele foi colocado perto dos pés da cama e da porta para reduzir a recirculação do ar quente expelido pelo trocador de calor para dentro do quarto
  • A cover é formada por três camadas: uma base, a hydrolayer feita com membrana de TPU e a cover superior
    • Abrindo o zíper da cover superior, o usuário instala a hydrolayer no lado onde dorme
    • A parte superior usa um tecido frio ao toque e um acolchoado fino, então a hydrolayer não é sentida diretamente

API da Sleep.me

  • Autenticação e exemplos no Postman

    • Para usar a API, primeiro é preciso gerar um token de usuário, e a documentação só pode ser acessada com uma conta
    • Os exemplos do Postman ajudam quando faltam detalhes na documentação, mas exigem uma conta empresarial separada e também são complicados de configurar
    • Prefiro alternativas como scripts hurl de código aberto
    • A maioria dos exemplos tem erro de digitação nos nomes de variáveis
    • É preciso usar {{SleepMeAPI_Url}}, com distinção entre maiúsculas e minúsculas, e não {{SleepMeAPI_URL}}
    • O exemplo “Set Device Status” define set_temperature_f como 69 e thermal_control_status como standby
  • Endpoints e estrutura das respostas

    • A API oferece dois tipos de endpoint: um para a lista de dispositivos e outro para dispositivos individuais
    • GET /devices: retorna a lista de dispositivos vinculados ao token
    • GET /devices/{:id}: retorna as informações completas de um dispositivo específico
    • PATCH /devices/{:id}: altera propriedades do dispositivo
    • Cada item de /devices inclui o ID do dispositivo, o nome definido pelo usuário e attachments
    • Não está claro se attachments significa outros dispositivos conectados
    • A resposta detalhada é dividida nos objetos about, control e status
      • about: informações somente leitura como versão do firmware, IP externo, IP da LAN, endereço MAC, modelo e número de série
      • control: propriedades alteráveis como brilho da tela, unidade de temperatura exibida, temperatura configurada, estado do controle térmico e fuso horário
      • status: estado somente leitura como conexão com a API, falta de água, nível da água de 0 a 100 e temperatura atual da água
    • As propriedades de control podem variar por dispositivo, e às vezes são retornadas chaves não documentadas como brightness_level
    • thermal_control_status pode ser active ou standby e indica se o aparelho está regulando ativamente a temperatura
  • Valores de temperatura e controle do dispositivo

    • Temperaturas em Fahrenheit são tratadas como inteiros, e em Celsius como números de ponto flutuante
    • O intervalo normal é 55~115°F em Fahrenheit e 13.0~48.0°C em Celsius
    • MAX_COLD é representado como -1 ou -1.0, e MAX_HEAT como 999 ou 999.0
    • Quando está em espera, status.water_temperature_* igual a -1 parece ser um valor sentinela, mas isso não está documentado
    • Ao alterar propriedades do dispositivo, basta enviar no corpo JSON apenas a chave que você quer mudar em uma requisição PATCH
    • Para definir só a temperatura em Fahrenheit como 73, envie { "set_temperature_f": 73 }
    • Não é necessário incluir todas as chaves de controle nem envolver com { "control": ... }
    • Essa forma de requisição foi confirmada pela coleção do Postman, não pela documentação oficial

Estrutura e uso do bedctl

  • O bedctl foi construído em torno de um módulo em Zig, e a CLI é um wrapper fino que chama essa biblioteca
  • O nome segue a convenção de colocar o sufixo -ctl em programas de controle e também brinca com o fato de “bed cuttle” soar como “bed cuddle”
  • Os principais comandos são os seguintes
    • bedctl devices: consulta nomes e IDs dos dispositivos registrados no token
    • bedctl status: consulta firmware, endereços de rede, modelo, temperatura configurada, estado de funcionamento, nível da água e temperatura observada
    • bedctl set temp 74: define a temperatura alvo
  • O token e o ID do dispositivo podem ser definidos por variáveis de ambiente ou passados pelas flags --token e --device

Por que escolhi Zig e as dependências

  • Usei Rust no trabalho por cerca de 5 anos e como hobby desde 2018, mas queria feedback imediato e menor carga mental, então implementei isso em Zig, que venho preferindo recentemente
  • Em um MacBook Pro M1 Max, zig build check --watch -fincremental atualiza em cerca de 75ms
  • A única dependência externa da CLI é um argument parser extraído e modificado do código do TigerBeetle e adaptado para o Zig 0.16.0
  • A biblioteca não tem dependências além da biblioteca padrão do Zig e usa std.http.Client para requisições HTTP
  • A CLI não faz link com libc, e o plano é que a futura biblioteca dinâmica também funcione sem libc
  • Com o recurso padrão de compilação cruzada do Zig, é possível gerar builds para plataformas suportadas sem acessar diretamente o sistema de destino

Modelo de dados e sistema de tipos

  • As structs principais são Device, para a lista de dispositivos, e DeviceStatus, para a resposta detalhada
    • Device inclui id, name e attachments
    • DeviceStatus é composto por Device.About, Device.Control e Device.Status
  • Como propriedades de Control podem não existir dependendo do modelo, brilho, unidade de exibição, temperatura configurada, estado de operação e fuso horário são representados como valores opcionais
  • Em vez de usar strings JSON diretamente, ele aproveita enums anônimos do Zig
    • As unidades de temperatura são .c e .f
    • Os estados de controle térmico são .active e .standby
  • A temperatura configurada em Fahrenheit usa nomes de enum significativos para certos valores inteiros
    • Em vez de memorizar -1, é possível usar .max_cold
    • Temperaturas comuns podem ser passadas como literais inteiros, como 78
  • Não foi encontrada uma forma de restringir pelo tipo o intervalo válido de 55~115°F, e também não há validação separada antes da requisição
  • Como valores em Celsius são de ponto flutuante, o intervalo permitido também não pôde ser expresso no tipo

Experiência implementando o cliente HTTP em Zig

  • O cliente HTTP padrão do Zig exige um procedimento mais de baixo nível do que uma abstração simples de URI/corpo/send
    • criar um objeto URI
    • modificar a URI para definir o caminho
    • criar um objeto de requisição com URI base, cabeçalhos e configuração de conexão
    • enviar os cabeçalhos da requisição
    • receber os cabeçalhos da resposta
    • criar um reader para o corpo
    • consumir o corpo da resposta a partir do reader
  • Isso permite controle detalhado, mas, diferentemente do Rust, onde é possível descer ao baixo nível só quando necessário, no Zig a sensação é de estar fazendo trabalho de baixo nível o tempo todo
  • A implementação de /devices envia uma requisição GET com cabeçalho de autenticação usando sendBodiless(), lê a resposta até 64.000 bytes e faz o parse do JSON como []const Device
  • Embora use parseFromSliceLeaky, não há problema com liberação de memória graças à configuração de arena allocator não exposta externamente

Plano de expansão para biblioteca dinâmica

  • O objetivo final é criar uma biblioteca dinâmica sem dependências que possa ser usada em linguagens de mais alto nível
  • A estrutura planejada é a seguinte
    • módulo Zig bedctl
    • CLI bedctl que usa diretamente o módulo Zig
    • libbedctl que fornece uma interface C para o módulo Zig
    • bedctl-dl, que usa a biblioteca dinâmica e valida por conta própria a interface C
  • Se surgir um wrapper para Python, gostaria de usá-lo no Home Assistant, mas não pretende escrevê-lo pessoalmente
  • O build e a interface da biblioteca dinâmica ainda não estão prontos, mas a ideia é adicioná-los em breve

Experiência de sono após alguns dias de uso

  • Nos poucos dias de uso, subjetivamente dormiu muito bem, e o rastreador de atividade também mostrou mais tempo em sono restaurador e menos despertares noturnos
  • Mesmo no dia em que bebeu uísque, dormiu melhor do que o normal, mas isso não deve ser interpretado como se álcool fosse bom para o sono
    • O álcool continua sendo prejudicial à saúde e ao sono; no máximo, o dispositivo pode ter reduzido parcialmente a piora do sono
  • Como o aparelho foi usado por apenas alguns dias e o bedctl também foi escrito ao longo de cerca de 3 noites, os resultados ainda estão em fase de lua de mel
  • Quando a temperatura foi ajustada baixa demais no início, houve uma sensação fria como se estivesse deitado em algo molhado, mas isso desapareceu depois de corrigir a temperatura
  • O tempo de transição não foi medido diretamente, mas pareceu mais próximo de 1 minuto do que de 10 minutos
    • Como é preciso menos de 1 galão de água para encher, a capacidade térmica a aquecer ou resfriar não é tão grande

Uso de controle remoto, ventilador e aquecimento

  • O controle remoto padrão tem formato de disco grande com tela sensível ao toque, o que facilita mudar a temperatura imediatamente enquanto se ajusta a programação
  • O toque do disco não é muito satisfatório, mas ele vibra a cada unidade de temperatura, permitindo ajustar sem olhar para a tela
    • Mesmo usando máscara de dormir, dá para perceber o quanto mudou por meio do feedback háptico
  • Também é necessário um leve fluxo de ar, então antes era preciso equilibrar ao mesmo tempo um nível que resfriasse o quarto sem bater diretamente no corpo nem ressecar as vias respiratórias
  • Depois de passar a usar o Chilipad, basta deixar o ventilador na potência mínima
  • De manhã, aumentar um pouco a temperatura fica aconchegante, e no inverno há expectativa de aproveitar a função de pré-aquecer a cama
  • Colocar o topper reduz um pouco a ventilação vinda de baixo
    • Não chega a parecer que você está deitado sobre plástico, mas em temperaturas mais altas a pele em contato com a cama pareceu ficar levemente úmida de suor
    • Essa pode ser uma experiência ligada à regulação térmica pessoal e pode não se aplicar a outros usuários
  • A experiência inicial é positiva no geral, e talvez seja publicado um acompanhamento depois que a biblioteca dinâmica estiver pronta

1 comentários

 
Comentários no Lobste.rs
  • Publiquei este texto logo antes de dormir, de forma bem apropriada ao tema

    • Fico curioso se, configurando o bedctl para baixar bastante a temperatura em um horário específico, ele também poderia ser usado para acordar alguém
  • O título e o texto são excelentes. Fico curioso se você também já testou cobertor ponderado e se ele realmente funcionou

    • Usei um cobertor ponderado no passado e, no geral, gostava dele, mas me desfiz dele quando me mudei. Só que ele não ajudava no controle da temperatura corporal, então não era a solução que eu queria aqui
      Dependendo de como é fabricado, pode ter pouca respirabilidade e também ser caro. Depois de comprar o Chilipad, até fico sem graça de reclamar de preço, mas um produto que deixei anotado para olhar depois é este, com uma estrutura de trama aberta que parece bem respirável: https://bearaby.com/products/tree-napper
  • Estive pesquisando produtos desse tipo e penso em testar algum dia. Segundo este vídeo, a solução com melhor custo-benefício é um balde, mas nesse caso provavelmente não teria API

    • Também vi esse vídeo, mas acho que o balde da Home Depot não passaria no inexistente teste de aprovação do cônjuge 😅
  • Texto um tanto relacionado: https://trufflesecurity.com/blog/removing-jeff-bezos-from-my-bed (discussão)

  • No trecho comparando Fahrenheit e Celsius, acho que a intenção não era escrever Celsius is the better temperature

  • O texto é divertido, e me identifiquei bastante com a forma de pensar, como na parte sobre ventiladores, mas não fica claro o que passou a ser possível controlar com esse trabalho
    O parágrafo dizendo que, por causa da experiência no doutorado em física, você desconfia de reportagens sobre ciência e saúde até que sejam comprovadas pode ser lido como algo perigosamente parecido com desconfiança de vacinas. Ainda assim, entendo que a ideia é que o doutorado o fez deixar de aceitar os “fatos” da imprensa em termos preto no branco, e fico curioso sobre o que exatamente deixou essa marca

    • O ponto é exatamente o oposto. Ser físico não torna minhas intuições sobre medicina especiais, então o melhor é seguir especialistas que estudaram a área, em vez de ler alguns artigos e fingir que sou médico. Não se trata de obedecer cegamente à autoridade, mas de reconhecer a possibilidade de eu estar errado e de adotar a mesma postura que eu gostaria que outros tivessem em relação à minha expertise nas poucas áreas que pesquisei
      Quando o artigo de Andrew Wakefield sobre vacinas saiu, pessoas que só tinham lido uma matéria curta de um jornalista baseada no resumo passaram a afirmar categoricamente que vacinas eram absolutamente perigosas, e até um professor de biologia do ensino médio com mestrado em zoologia e três doutores em física aderiram ao movimento antivacina. Mas o consenso da comunidade médica continuou sendo que vacinas são seguras, eficazes e uma das ferramentas mais poderosas para salvar vidas, e todos os pesquisadores médicos que conheci concordavam com isso
      O motivo de o doutorado ter me marcado foi perceber o tamanho do abismo entre as descobertas reais da minha área e a forma como elas apareciam nas notícias. Como não dá para entender completamente todas as áreas, devemos confiar nos médicos para medicina, nos ecólogos para meio ambiente e nos climatologistas para clima. Vi doutores em física “refutarem” especialistas com matemática de ensino fundamental II e ciência de ensino fundamental I, mas especialistas de verdade sabiam que existe uma diferença enorme entre conhecimento escolar e conhecimento sobre a realidade. Como vi esse abismo na área que estudei, nas áreas que não estudei acabei confiando ainda mais nos especialistas
  • Se dá para jogar campos arbitrários na estrutura desejada, quase certamente o handler está fazendo uma busca com regex do tipo re.search('set_temperature_f\": (\\d+)',...)