1 điểm bởi GN⁺ 17 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Vì phòng ngủ nóng và nhạy cảm với thân nhiệt, tác giả đã mua Sleep.me Chilipad 2.0 với giá 1.700 USD và phát triển bedctl để điều khiển cloud API của nhà sản xuất
  • Chilipad kết hợp một tấm topper mỏng có nước tuần hoàn với bơm, bình chứa và bộ điều nhiệt; hỗ trợ đặt lịch nhiệt độ theo ngày trong tuần và cấu hình mô-đun bắt đầu từ một bên giường
  • API cho phép truy vấn thiết bị tại /devices/devices/{:id}, dùng PATCH để điều khiển nhiệt độ, trạng thái hoạt động, độ sáng màn hình, múi giờ, v.v.; cũng có thể kiểm tra mực nước và nhiệt độ nước hiện tại
  • bedctl viết bằng Zig, gồm thư viện không phụ thuộc và một CLI mỏng; dự định mở rộng thành thư viện động libbedctl có giao diện C trong tương lai
  • Theo dõi giấc ngủ ban đầu cho thấy thời gian ngủ phục hồi tăng và số lần thức giấc ban đêm giảm, nhưng mới chỉ dùng vài ngày nên vẫn là giai đoạn trăng mật, chưa thể đánh giá hiệu quả dài hạn

Vì sao cần điều chỉnh nhiệt độ giường

  • Giấc ngủ giúp ích cho miễn dịch, chức năng nhận thức và phục hồi sau hoạt động thể chất, nhưng các tiêu đề về sức khỏe có thể làm mất sắc thái khoa học, nên tác giả coi trọng việc liệu chúng có được giới y khoa hoặc đồng thuận chuyên gia hậu thuẫn hay không
  • Do ADHD, dòng suy nghĩ cứ tiếp diễn khiến khó ngủ; thói quen đọc sách trên giường giúp giảm kích thích và gửi tín hiệu đi ngủ cho hệ thần kinh
  • Do đặc điểm tự kỷ, tác giả nhạy cảm với một số kết cấu và cảm giác nhất định, đồng thời khó điều hòa thân nhiệt; để ngủ được thì nhiệt độ và trọng lượng chăn phải phù hợp
  • Căn hộ mới ở Portland chỉ có điều hòa trong phòng khách và không có quạt trần, nên phòng ngủ ở tầng cao trở thành nơi nóng nhất về đêm
    • Tác giả cũng lắp cảm biến nhiệt độ và xác nhận phòng ngủ là nơi nóng nhất trong căn hộ
  • Giấc ngủ thất thường, việc dùng thuốc kích thích, phòng ngủ ngột ngạt và nhạy cảm thân nhiệt cộng lại khiến tác giả quyết định chi tiền cho thiết bị điều chỉnh nhiệt độ giường

Vì sao chọn Chilipad 2.0

  • Chilipad 2.0 điều khiển nhiệt độ giường bằng cách nối một topper nệm mỏng chứa nước với thiết bị gồm bơm, bình chứa và bộ điều nhiệt
  • BedJet, loại thổi không khí bằng quạt, bị loại vì vào mùa hè luồng gió lạnh thổi trực tiếp vào chân
  • Eight Sleep bị loại khỏi danh sách mua vì mẫu rẻ nhất cũng 3.000 USD, cần đăng ký thuê bao và còn kèm cả tính năng AI
  • Chilipad là sản phẩm mô-đun, có thể mua thiết bị cho một bên giường trước nên giá ban đầu thấp hơn
    • Nếu lắp hai bộ, hai bên có thể đặt nhiệt độ khác nhau, hữu ích cho các cặp đôi có cảm nhận nhiệt khác nhau
  • Đây là sản phẩm kết nối Internet nhưng hỗ trợ chế độ máy bay và tặng kèm remote Bluetooth
    • Tác giả chưa kiểm tra liệu chế độ máy bay chỉ tắt Wi-Fi hay chặn mọi kết nối không dây
    • Ban đầu tác giả hiểu nhầm là API cục bộ, nhưng thực tế thiết bị giao tiếp với dịch vụ đám mây
  • Nhà sản xuất cung cấp developer API, bộ sưu tập Postman, Swagger UI trực tuyến và schema OpenAPI

Cấu hình thiết bị Chilipad

  • Chilipad gồm dock là bộ điều khiển và cover có nước tuần hoàn
    • dock chứa bộ điều nhiệt, bơm và bình chứa
    • Tác giả đặt nó ở cuối giường và gần cửa phòng để giảm việc không khí nóng từ bộ trao đổi nhiệt lan ngược vào phòng ngủ
  • cover gồm ba lớp: lớp đáy, hydrolayer làm từ màng TPU và cover phía trên
    • Mở khóa kéo cover phía trên để lắp hydrolayer vào bên người dùng nằm
    • Mặt trên dùng vải mát khi chạm và lớp đệm mỏng, nên không cảm nhận trực tiếp hydrolayer

Sleep.me API

  • Xác thực và ví dụ Postman

    • Để dùng API, trước tiên phải tạo token người dùng; tài liệu chỉ truy cập được khi có tài khoản
    • Ví dụ Postman hữu ích khi tài liệu thiếu chi tiết, nhưng cần tài khoản công ty riêng và cấu hình cũng phức tạp
    • Tác giả thích các lựa chọn thay thế như script hurl mã nguồn mở hơn
    • Hầu hết ví dụ có lỗi chính tả ở tên biến
    • Phải dùng {{SleepMeAPI_Url}} có phân biệt chữ hoa/thường, không phải {{SleepMeAPI_URL}}
    • Ví dụ “Set Device Status” đặt set_temperature_f thành 69 và thermal_control_status thành standby
  • Endpoint và cấu trúc phản hồi

    • API cung cấp hai loại endpoint: danh sách thiết bị và từng thiết bị riêng lẻ
    • GET /devices: trả về danh sách thiết bị gắn với token
    • GET /devices/{:id}: trả về toàn bộ thông tin của một thiết bị cụ thể
    • PATCH /devices/{:id}: thay đổi thuộc tính thiết bị
    • Mỗi mục trong /devices chứa ID thiết bị, tên do người dùng đặt và attachments
    • Không chắc attachments có nghĩa là các thiết bị khác được kết nối hay không
    • Phản hồi chi tiết được chia thành các object about, control, status
      • about: thông tin chỉ đọc gồm phiên bản firmware, IP bên ngoài, IP LAN, địa chỉ MAC, model và số serial
      • control: các thuộc tính có thể thay đổi như độ sáng màn hình, đơn vị nhiệt độ hiển thị, nhiệt độ đặt, trạng thái điều khiển nhiệt và múi giờ
      • status: trạng thái chỉ đọc như có kết nối API hay không, có thiếu nước hay không, mực nước từ 0~100 và nhiệt độ nước hiện tại
    • Thuộc tính control có thể khác nhau theo thiết bị; đôi khi trả về các khóa không có trong tài liệu như brightness_level
    • thermal_control_statusactive hoặc standby, cho biết thiết bị có đang chủ động điều chỉnh nhiệt độ hay không
  • Giá trị nhiệt độ và điều khiển thiết bị

    • Nhiệt độ Fahrenheit được xử lý là số nguyên, nhiệt độ Celsius là số thực
    • Khoảng bình thường là 55~115°F theo Fahrenheit, 13.0~48.0°C theo Celsius
    • MAX_COLD được biểu diễn bằng -1 hoặc -1.0, MAX_HEAT bằng 999 hoặc 999.0
    • Khi ở trạng thái chờ, status.water_temperature_* bằng -1 có vẻ là giá trị sentinel nhưng không được tài liệu hóa
    • Khi thay đổi thuộc tính thiết bị, chỉ đưa các khóa muốn đổi vào JSON body rồi gửi request PATCH
    • Để chỉ đặt nhiệt độ Fahrenheit thành 73, gửi { "set_temperature_f": 73 }
    • Không cần bao gồm mọi khóa điều khiển hoặc bọc bằng { "control": ... }
    • Cách request này được xác nhận qua bộ sưu tập Postman, không phải tài liệu chính thức

Cấu trúc và cách dùng bedctl

  • bedctl được xây dựng quanh mô-đun Zig, còn CLI là wrapper mỏng gọi thư viện đó
  • Tên gọi theo quy ước thêm hậu tố -ctl cho chương trình điều khiển, đồng thời phản ánh việc “bed cuttle” nghe giống “bed cuddle”
  • Các lệnh chính như sau
    • bedctl devices: xem tên và ID thiết bị đã đăng ký với token
    • bedctl status: xem firmware, địa chỉ mạng, model, nhiệt độ đặt, trạng thái hoạt động, mực nước và nhiệt độ quan sát được
    • bedctl set temp 74: đặt nhiệt độ mục tiêu
  • Token và ID thiết bị có thể chỉ định bằng biến môi trường hoặc truyền qua các cờ --token, --device

Vì sao chọn Zig và các phụ thuộc

  • Tác giả dùng Rust khoảng 5 năm trong công việc và từ 2018 cho sở thích cá nhân, nhưng muốn phản hồi tức thì và gánh nặng tinh thần thấp hơn nên triển khai bằng Zig, ngôn ngữ gần đây tác giả ưa thích
  • Trên M1 Max MacBook Pro, zig build check --watch -fincremental cập nhật trong khoảng 75ms
  • Phụ thuộc bên ngoài duy nhất của CLI là argument parser, được trích xuất và sửa từ mã TigerBeetle, rồi điều chỉnh cho Zig 0.16.0
  • Thư viện không có phụ thuộc nào ngoài thư viện chuẩn Zig và dùng std.http.Client cho request HTTP
  • CLI không liên kết với libc, và thư viện động trong tương lai cũng dự kiến được cấu hình không cần libc
  • Nhờ khả năng cross-compile mặc định của Zig, có thể tạo bản build cho các nền tảng được hỗ trợ mà không cần truy cập trực tiếp hệ thống đích

Mô hình dữ liệu và hệ thống kiểu

  • Các struct cốt lõi là Device cho danh sách thiết bị và DeviceStatus cho phản hồi chi tiết
    • Device gồm id, name, attachments
    • DeviceStatus gồm Device.About, Device.Control, Device.Status
  • Thuộc tính Control có thể không tồn tại tùy model, nên độ sáng, đơn vị hiển thị, nhiệt độ đặt, trạng thái hoạt động và múi giờ được biểu diễn bằng giá trị tùy chọn
  • Thay vì dùng nguyên chuỗi JSON, tác giả tận dụng anonymous enum của Zig
    • Đơn vị nhiệt độ là .c.f
    • Trạng thái điều khiển nhiệt là .active.standby
  • Với nhiệt độ đặt theo Fahrenheit, tác giả gán tên enum có ý nghĩa cho một số giá trị nguyên cụ thể
    • Có thể dùng .max_cold thay vì phải nhớ -1
    • Nhiệt độ thông thường có thể truyền bằng literal số nguyên như 78
  • Tác giả chưa tìm được cách chỉ dùng kiểu để giới hạn khoảng hợp lệ 55~115°F, và cũng không kiểm tra riêng trước khi request
  • Giá trị Celsius là số thực nên không thể biểu diễn khoảng cho phép bằng kiểu

Trải nghiệm triển khai HTTP client bằng Zig

  • HTTP client chuẩn của Zig yêu cầu quy trình ở mức thấp hơn so với abstraction URI, body và send đơn giản
    • Tạo object URI
    • Sửa URI để chỉ định path
    • Tạo object request bằng URI cơ sở, header và thiết lập kết nối
    • Gửi request head
    • Nhận response head
    • Tạo reader cho body
    • Đọc body phản hồi từ reader
  • Có thể kiểm soát chính xác, nhưng khác với Rust, nơi có thể hạ xuống mức thấp khi cần, trong Zig cảm giác như luôn phải làm công việc mức thấp
  • Phần triển khai /devices gửi request GET có header xác thực bằng sendBodiless(), sau đó đọc phản hồi tối đa 64.000 byte và parse JSON thành []const Device
  • Dù dùng parseFromSliceLeaky, nhờ cấu hình arena allocator không phơi ra bên ngoài nên không có vấn đề giải phóng bộ nhớ

Kế hoạch mở rộng thành thư viện động

  • Mục tiêu cuối cùng là tạo thư viện động không phụ thuộc dùng được từ các ngôn ngữ cấp cao hơn
  • Cấu trúc dự kiến như sau
    • Mô-đun Zig bedctl
    • CLI bedctl dùng trực tiếp mô-đun Zig
    • libbedctl cung cấp giao diện C cho mô-đun Zig
    • bedctl-dl dùng thư viện động và tự kiểm chứng giao diện C
  • Nếu có wrapper Python, tác giả muốn dùng trong Home Assistant, nhưng không có kế hoạch tự viết
  • Bản build thư viện động và giao diện vẫn chưa sẵn sàng, dự kiến sẽ được thêm trong thời gian gần

Trải nghiệm giấc ngủ sau vài ngày sử dụng

  • Trong vài ngày sử dụng, tác giả chủ quan cảm thấy ngủ sâu, và thiết bị theo dõi thể lực cũng cho thấy giai đoạn ngủ phục hồi dài hơn, số lần thức giấc ban đêm ít hơn
  • Ngay cả hôm uống whisky, tác giả vẫn ngủ ngon hơn bình thường, nhưng không nên diễn giải điều này là rượu tốt cho giấc ngủ
    • Rượu vẫn có hại cho sức khỏe và giấc ngủ; chỉ có thể là thiết bị đã phần nào giảm sự suy giảm giấc ngủ
  • Thiết bị mới được dùng vài ngày và bedctl cũng được viết trong khoảng 3 đêm, nên kết quả vẫn còn ở giai đoạn trăng mật
  • Khi ban đầu đặt nhiệt độ quá thấp, tác giả cảm thấy lạnh như nằm trên chỗ ướt, nhưng cảm giác đó biến mất sau khi điều chỉnh nhiệt độ
  • Tác giả không đo trực tiếp thời gian chuyển đổi, nhưng cảm giác nhanh gần 1 phút hơn là 10 phút
    • Lượng nước cần đổ vào dưới 1 gallon nên nhiệt dung cần làm nóng hoặc làm lạnh không lớn

Remote, quạt và sử dụng sưởi

  • Remote mặc định có dạng núm xoay lớn kèm màn hình cảm ứng, nên dễ đổi nhiệt độ tức thì trong lúc tinh chỉnh nhiệt độ đặt lịch
  • Cảm giác xoay núm không thật thỏa mãn, nhưng nó rung theo từng đơn vị nhiệt độ nên có thể điều chỉnh mà không cần nhìn màn hình
    • Ngay cả khi đeo mặt nạ ngủ, vẫn biết mức thay đổi nhờ phản hồi xúc giác
  • Tác giả cũng cần luồng gió nhẹ, nên trước đây phải vừa chỉnh lưu lượng đủ làm mát phòng, vừa không thổi trực tiếp vào người hoặc làm khô đường thở
  • Sau khi dùng Chilipad, chỉ cần bật quạt ở mức thấp nhất
  • Tăng nhiệt độ lên một chút vào buổi sáng tạo cảm giác ấm áp dễ chịu, và tác giả mong chờ chức năng làm ấm giường trước vào mùa đông
  • Trải topper lên làm giảm phần nào độ thoáng khí của mặt dưới
    • Không có cảm giác như nằm trên nhựa, nhưng ở nhiệt độ cao, vùng da tiếp xúc với giường có cảm giác hơi ẩm mồ hôi rất nhẹ
    • Đây là trải nghiệm do đặc điểm điều hòa thân nhiệt cá nhân, nên người dùng khác có thể không giống vậy
  • Trải nghiệm ban đầu nhìn chung tích cực, và tác giả có thể đăng nội dung tiếp theo sau khi cấu hình xong thư viện động

1 bình luận

 
Ý kiến trên Lobste.rs
  • Đăng bài này ngay trước khi đi ngủ đúng với chủ đề

    • Tò mò không biết nếu đặt bedctl để hạ nhiệt độ thật thấp vào một thời điểm nhất định thì có thể dùng nó để đánh thức hay không
  • Cả tiêu đề lẫn bài viết đều rất hay. Không biết bạn đã thử chăn trọng lực chưa, và nó có thực sự hiệu quả không

    • Trước đây tôi từng dùng chăn trọng lực và nhìn chung khá thích, nhưng đã bỏ nó khi chuyển nhà. Tuy vậy, nó không giúp ích cho điều hòa thân nhiệt, nên không phải là lời giải tôi muốn ở đây
      Tùy cách làm mà nó có thể kém thoáng khí và cũng khá đắt. Sau khi mua Chilipad thì cũng ngại nói là đắt, nhưng sản phẩm tôi đã ghi nhớ để xem sau là https://bearaby.com/products/tree-napper với kiểu dệt mở có vẻ thoáng khí
  • Tôi đang tìm hiểu mấy sản phẩm kiểu này và nghĩ rằng rồi sẽ thử dùng một lần. Theo video này, giải pháp đáng tiền nhất là cái xô, nhưng như vậy thì chắc sẽ không có API

    • Tôi cũng đã xem video đó, nhưng cái xô của Home Depot có lẽ sẽ không vượt qua được bài kiểm tra chấp thuận của vợ/chồng vốn còn chẳng tồn tại 😅
  • Một bài khá liên quan: https://trufflesecurity.com/blog/removing-jeff-bezos-from-my-bed (thảo luận)

  • Ở đoạn so sánh Fahrenheit và Celsius, có lẽ bạn không định viết Celsius is the better temperature

  • Bài viết khá vui và tôi cũng rất đồng cảm với cách suy nghĩ của bạn, như phần nói về quạt chẳng hạn, nhưng tôi vẫn chưa rõ chính xác là với công việc này thì bạn đã điều khiển được những gì
    Đoạn nói rằng trải nghiệm làm tiến sĩ vật lý khiến bạn nghi ngờ các tin tức về khoa học và sức khỏe cho tới khi được kiểm chứng có thể bị đọc theo hướng khá nguy hiểm, gần giống với tâm lý hoài nghi vaccine. Tuy vậy, tôi hiểu ý là quá trình làm tiến sĩ khiến bạn không còn tiếp nhận các “sự thật” trên báo chí theo kiểu trắng đen, và tôi tò mò không biết cụ thể điều gì đã để lại vết thương như vậy

    • Ý chính thực ra là hoàn toàn ngược lại. Chỉ vì tôi là nhà vật lý không có nghĩa là trực giác của tôi về y học cũng trở nên đặc biệt, nên thay vì đọc vài bài báo rồi đóng vai bác sĩ, tốt nhất là theo các chuyên gia đã nghiên cứu lĩnh vực đó. Đây không phải là mù quáng phục tùng thẩm quyền, mà là thừa nhận khả năng mình sai, đồng thời cũng mong người khác tôn trọng chuyên môn của tôi trong số ít lĩnh vực mà tôi đã nghiên cứu
      Khi bài báo về vaccine của Andrew Wakefield xuất hiện, những người chỉ đọc một mẩu tin ngắn của nhà báo sau khi xem phần tóm tắt đã quả quyết rằng vaccine cực kỳ nguy hiểm, và cả giáo viên sinh học trung học có bằng thạc sĩ động vật học lẫn ba tiến sĩ vật lý đều phản đối vaccine. Nhưng đồng thuận của giới y khoa vẫn luôn là vaccine an toàn, hiệu quả và là một trong những công cụ mạnh nhất để cứu người, và tất cả các nhà nghiên cứu y khoa mà tôi từng gặp đều nhất trí như vậy
      Điều khiến tôi tổn thương trong quá trình làm tiến sĩ là tôi nhận ra khoảng cách giữa những phát hiện thực sự trong lĩnh vực của mình và cách tin tức đưa tin lớn đến mức nào. Vì không thể hiểu trọn vẹn mọi lĩnh vực, ta nên tin bác sĩ về y học, nhà sinh thái học về môi trường, và nhà khí hậu học về khí hậu. Tôi đã thấy những tiến sĩ vật lý cố “phản biện” chuyên gia bằng toán cấp hai và khoa học cấp một, trong khi chuyên gia thật sự hiểu khoảng cách khổng lồ giữa kiến thức ở trường lớp và kiến thức về thế giới thực. Chính vì đã chứng kiến khoảng cách đó trong lĩnh vực mình học, nên ở những lĩnh vực tôi chưa học, tôi lại càng tin chuyên gia hơn
  • Nếu cứ có thể ném các trường dữ liệu vào theo bất kỳ cấu trúc nào mình muốn, thì gần như chắc chắn bộ xử lý đang làm kiểu tìm kiếm regex như re.search('set_temperature_f\": (\\d+)',...)