- ผู้เขียนซื้อ Sleep.me Chilipad 2.0 ราคา 1,700 ดอลลาร์ เพราะห้องนอนร้อนและไวต่ออุณหภูมิร่างกาย จึงพัฒนา
bedctlเพื่อควบคุม Cloud API ของผู้ผลิต - Chilipad ผสานท็อปเปอร์บางที่มีน้ำไหลเวียนเข้ากับปั๊ม ถังเก็บน้ำ และตัวควบคุมอุณหภูมิ พร้อมรองรับ โครงสร้างแบบโมดูลาร์ ทั้งการตั้งเวลาอุณหภูมิตามวันในสัปดาห์และการติดตั้งเริ่มจากฝั่งเดียวของเตียง
- API ใช้
/devicesและ/devices/{:id}เพื่อดูอุปกรณ์ และควบคุมอุณหภูมิ สถานะการทำงาน ความสว่างหน้าจอ เขตเวลา ฯลฯ ด้วยPATCHรวมถึงตรวจสอบระดับน้ำและอุณหภูมิน้ำปัจจุบันได้ bedctlที่เขียนด้วย Zig ประกอบด้วยไลบรารีแบบไม่มี dependency และ CLI แบบบาง โดยมีแผนจะขยายเป็นไลบรารีไดนามิกlibbedctlพร้อม C interface ในอนาคต- จากการติดตามการนอนช่วงแรก เวลานอนเพื่อการฟื้นตัวเพิ่มขึ้นและการตื่นกลางดึกลดลง แต่ยังเป็นเพียงช่วง ฮันนีมูน เพราะใช้งานมาได้ไม่กี่วัน จึงยังเร็วเกินไปที่จะตัดสินผลระยะยาว
เหตุผลที่ต้องควบคุมอุณหภูมิเตียง
- การนอนช่วยเรื่องภูมิคุ้มกัน การทำงานด้านการรับรู้ และการฟื้นตัวหลังใช้ร่างกาย แต่พาดหัวข่าวสุขภาพมักทำให้รายละเอียดเชิงวิทยาศาสตร์หายไป จึงให้ความสำคัญว่ามีบุคลากรทางการแพทย์หรือฉันทามติของผู้เชี่ยวชาญรองรับหรือไม่
- ด้วย ADHD จึงคิดไม่หยุดและหลับยาก และได้ใช้การอ่านหนังสือบนเตียงเป็นนิสัยเพื่อลดสิ่งกระตุ้นและส่งสัญญาณให้ระบบประสาทรู้ว่าเป็นเวลาเข้านอน
- ด้วยลักษณะออทิสติกจึงไวต่อพื้นผิวและความรู้สึกบางแบบ รวมถึงควบคุมอุณหภูมิร่างกายได้ยาก ดังนั้นการจะหลับได้ อุณหภูมิและน้ำหนักผ้าห่ม ต้องพอดี
- อพาร์ตเมนต์ใหม่ใน Portland มีแอร์เฉพาะห้องนั่งเล่นและไม่มีพัดลมเพดาน ทำให้ห้องนอนชั้นสูงเป็นพื้นที่ที่ร้อนที่สุดในตอนกลางคืน
- ยังติดตั้งเซ็นเซอร์อุณหภูมิเพื่อยืนยันว่าห้องนอนร้อนที่สุดในอพาร์ตเมนต์จริง
- เมื่อนอนหลับไม่เป็นเวลา การใช้ยากระตุ้น ห้องนอนที่อึดอัด และความไวต่ออุณหภูมิร่างกายมาซ้อนกัน จึงตัดสินใจยอมจ่ายกับอุปกรณ์ควบคุมอุณหภูมิเตียง
เหตุผลที่เลือก Chilipad 2.0
- Chilipad 2.0 ควบคุมอุณหภูมิเตียงโดยเชื่อมท็อปเปอร์ที่เป็นแผ่นบางมีน้ำอยู่ภายในเข้ากับอุปกรณ์ที่มีปั๊ม ถังเก็บน้ำ และตัวควบคุมอุณหภูมิ
- ตัด BedJet ที่ใช้พัดลมเป่าลมออก เพราะในหน้าร้อนลมเย็นจะพุ่งใส่เท้าโดยตรง
- Eight Sleep แม้รุ่นถูกสุดก็ราคา 3,000 ดอลลาร์ และต้องสมัครสมาชิก แถมยังมีฟีเจอร์ AI จึงไม่อยู่ในกลุ่มที่จะซื้อ
- Chilipad เป็นสินค้าที่ออกแบบแบบโมดูลาร์ สามารถซื้อสำหรับเตียงฝั่งเดียวก่อน จึงมีราคาระยะแรกต่ำกว่า
- หากติดตั้งสองเครื่อง ก็สามารถตั้งอุณหภูมิคนละฝั่งไม่เท่ากันได้ จึงเหมาะกับคู่ที่รู้สึกร้อนเย็นต่างกัน
- แม้เป็นผลิตภัณฑ์ที่เชื่อมต่ออินเทอร์เน็ต แต่รองรับ โหมดเครื่องบิน และมีรีโมต Bluetooth มาให้เป็นมาตรฐาน
- ยังไม่ได้ตรวจสอบว่าโหมดเครื่องบินปิดเฉพาะ Wi‑Fi หรือบล็อกการเชื่อมต่อไร้สายทั้งหมด
- ตอนแรกเข้าใจผิดว่าเป็น local API แต่จริง ๆ แล้วสื่อสารกับบริการคลาวด์
- ผู้ผลิตมี developer API, Postman collection, Swagger UI ออนไลน์ และ OpenAPI schema ให้
โครงสร้างอุปกรณ์ Chilipad
- Chilipad ประกอบด้วย dock ซึ่งเป็นตัวควบคุม และ cover ที่มีน้ำไหลเวียนอยู่ภายใน
- dock มีตัวควบคุมอุณหภูมิ ปั๊ม และถังเก็บน้ำอยู่ข้างใน
- วางไว้ปลายเตียงใกล้ประตูเพื่อลดการที่ลมร้อนจากเครื่องแลกเปลี่ยนความร้อนกระจายกลับเข้ามาในห้องนอน
- cover ประกอบด้วยสามชั้น ได้แก่ ชั้นล่าง hydrolayer ที่ทำจากแผ่น TPU และ cover ชั้นบน
- เปิดซิปของ cover ชั้นบนแล้วติดตั้ง hydrolayer ไว้ฝั่งที่ผู้ใช้จะนอน
- ชั้นบนใช้ผ้าที่สัมผัสแล้วเย็นและบุบาง ๆ ทำให้ไม่รู้สึกถึง hydrolayer โดยตรง
Sleep.me API
-
การยืนยันตัวตนและตัวอย่างใน Postman
- หากจะใช้ API ต้องสร้าง โทเค็น ของผู้ใช้ก่อน และเอกสารเข้าถึงได้เฉพาะผู้ที่มีบัญชี
- ตัวอย่างใน Postman ช่วยได้เมื่อรายละเอียดในเอกสารไม่พอ แต่ต้องมีบัญชีบริษัทแยกต่างหากและการตั้งค่าก็ซับซ้อน
- ชอบทางเลือกอย่างสคริปต์
hurlแบบโอเพนซอร์สมากกว่า - ตัวอย่างส่วนใหญ่มีการสะกดชื่อตัวแปรผิด
- ต้องใช้
{{SleepMeAPI_Url}}ที่แยกตัวพิมพ์เล็กใหญ่ ไม่ใช่{{SleepMeAPI_URL}} - ตัวอย่าง “Set Device Status” ตั้ง
set_temperature_fเป็น 69 และthermal_control_statusเป็นstandby
-
โครงสร้าง endpoint และ response
- API มี endpoint สองประเภทสำหรับรายการอุปกรณ์และอุปกรณ์รายตัว
GET /devices: คืนค่ารายการอุปกรณ์ที่เชื่อมกับโทเค็นGET /devices/{:id}: คืนค่าข้อมูลทั้งหมดของอุปกรณ์ที่ระบุPATCH /devices/{:id}: เปลี่ยนคุณสมบัติของอุปกรณ์- แต่ละรายการใน
/devicesมี ID ของอุปกรณ์ ชื่อที่ผู้ใช้ตั้ง และattachments - ยังไม่แน่ชัดว่า
attachmentsหมายถึงอุปกรณ์อื่นที่เชื่อมอยู่หรือไม่ - response แบบรายละเอียดแบ่งเป็นอ็อบเจ็กต์
about,control,statusabout: ข้อมูลอ่านอย่างเดียว เช่น เวอร์ชันเฟิร์มแวร์, external IP, LAN IP, MAC address, รุ่น และ serial numbercontrol: คุณสมบัติที่แก้ไขได้ เช่น ความสว่างหน้าจอ หน่วยอุณหภูมิที่แสดง อุณหภูมิที่ตั้งไว้ สถานะการควบคุมอุณหภูมิ และเขตเวลาstatus: สถานะอ่านอย่างเดียว เช่น การเชื่อมต่อ API ระดับน้ำน้อยหรือไม่ ระดับน้ำ 0~100 และอุณหภูมิน้ำปัจจุบัน
- คุณสมบัติใน
controlอาจต่างกันไปตามอุปกรณ์ และบางครั้งก็มีคีย์ที่ไม่มีในเอกสาร เช่นbrightness_level thermal_control_statusเป็นactiveหรือstandbyและใช้บอกว่าอุปกรณ์กำลังควบคุมอุณหภูมิอย่างจริงจังอยู่หรือไม่
-
ค่าอุณหภูมิและการควบคุมอุปกรณ์
- อุณหภูมิฟาเรนไฮต์ใช้จำนวนเต็ม ส่วนเซลเซียสใช้เลขทศนิยม
- ช่วงปกติคือ 55~115°F หรือ 13.0~48.0°C
MAX_COLDแสดงเป็น-1หรือ-1.0และMAX_HEATแสดงเป็น999หรือ999.0- เมื่ออยู่ในสถานะ standby แล้ว
status.water_temperature_*เป็น-1ดูเหมือนจะเป็นค่า sentinel แต่ไม่มีการบันทึกไว้ในเอกสาร - เมื่อต้องการเปลี่ยนคุณสมบัติของอุปกรณ์ ให้ใส่เฉพาะคีย์ที่ต้องการเปลี่ยนใน JSON body แล้วส่งคำขอ
PATCH - หากต้องการตั้งอุณหภูมิฟาเรนไฮต์อย่างเดียวเป็น 73 ให้ส่ง
{ "set_temperature_f": 73 } - ไม่จำเป็นต้องใส่คีย์ควบคุมทั้งหมด หรือห่อด้วย
{ "control": ... } - วิธีส่งคำขอนี้ยืนยันได้จาก Postman collection ไม่ใช่เอกสารทางการ
โครงสร้างและการใช้งาน bedctl
bedctlสร้างโดยมี Zig module เป็นแกนกลาง และ CLI เป็นเพียง wrapper แบบบางที่เรียกใช้ไลบรารีนั้น- ชื่อนี้ตามธรรมเนียมการเติม suffix
-ctlให้โปรแกรมควบคุม และยังพ้องเสียง “bed cuttle” คล้าย “bed cuddle” ด้วย - คำสั่งหลักมีดังนี้
bedctl devices: ดูชื่อและ ID ของอุปกรณ์ที่ลงทะเบียนกับโทเค็นbedctl status: ดูเฟิร์มแวร์ ที่อยู่เครือข่าย รุ่น อุณหภูมิที่ตั้งไว้ สถานะการทำงาน ระดับน้ำ และอุณหภูมิที่ตรวจวัดได้bedctl set temp 74: ตั้งอุณหภูมิเป้าหมาย
- สามารถกำหนดโทเค็นและ ID อุปกรณ์ผ่าน environment variable หรือส่งด้วยแฟล็ก
--token,--device
เหตุผลที่เลือก Zig และ dependency
- แม้จะใช้ Rust ในงานราว 5 ปี และใช้เป็นงานอดิเรกมาตั้งแต่ปี 2018 แต่ต้องการฟีดแบ็กที่ทันทีและภาระทางความคิดที่ต่ำกว่า จึงเลือกใช้ Zig ซึ่งกำลังชอบในช่วงนี้
- บน M1 Max MacBook Pro คำสั่ง
zig build check --watch -fincrementalอัปเดตได้ในราว 75ms - dependency ภายนอกเพียงตัวเดียวของ CLI คือ argument parser ที่ดึงและดัดแปลงมาจากโค้ด TigerBeetle และปรับให้เข้ากับ Zig 0.16.0
- ตัวไลบรารีไม่มี dependency นอกจาก Zig standard library และใช้
std.http.Clientสำหรับคำขอ HTTP - CLI ไม่ลิงก์กับ
libcและตั้งใจให้ไลบรารีไดนามิกในอนาคตก็ทำงานได้โดยไม่ต้องใช้libc - ด้วยความสามารถ cross-compile พื้นฐานของ Zig จึงสามารถสร้างบิลด์สำหรับแพลตฟอร์มที่รองรับได้โดยไม่ต้องเข้าถึงระบบเป้าหมายโดยตรง
แบบจำลองข้อมูลและ type system
- โครงสร้างหลักคือ
Deviceสำหรับรายการอุปกรณ์ และDeviceStatusสำหรับ response แบบละเอียดDeviceมีid,name,attachmentsDeviceStatusประกอบด้วยDevice.About,Device.Control,Device.Status
- คุณสมบัติใน
Controlอาจไม่มีในบางรุ่น จึงแทนค่าความสว่าง หน่วยแสดงผล อุณหภูมิที่ตั้งไว้ สถานะการทำงาน และเขตเวลาเป็นค่าทางเลือก - แทนที่จะใช้สตริง JSON ตรง ๆ ผู้เขียนใช้ anonymous enum ของ Zig
- หน่วยอุณหภูมิคือ
.cและ.f - สถานะควบคุมอุณหภูมิคือ
.activeและ.standby
- หน่วยอุณหภูมิคือ
- อุณหภูมิฟาเรนไฮต์ที่ตั้งไว้ใช้ enum name ที่มีความหมายกับค่าจำนวนเต็มบางค่า
- แทนที่จะจำ
-1ก็ใช้.max_coldได้ - ส่วนอุณหภูมิทั่วไปส่งเป็น integer literal เช่น
78ได้
- แทนที่จะจำ
- ยังหาวิธีจำกัดช่วงปกติ 55~115°F ด้วย type เพียงอย่างเดียวไม่ได้ และก็ไม่ได้มีการตรวจสอบแยกก่อนส่งคำขอ
- ค่าเซลเซียสเป็นเลขทศนิยม จึงไม่สามารถแสดงช่วงที่ยอมรับได้ด้วย type
ประสบการณ์ใช้งาน Zig HTTP client
- HTTP client มาตรฐานของ Zig ต้องใช้ขั้นตอนระดับล่างมากกว่านามธรรมง่าย ๆ แบบ URI/body/
send- สร้างอ็อบเจ็กต์ URI
- แก้ไข URI เพื่อกำหนด path
- สร้าง request object ด้วย base URI, header และการตั้งค่าการเชื่อมต่อ
- ส่ง request head
- รับ response head
- สร้าง body reader
- อ่าน response body จาก reader
- แม้จะควบคุมได้ละเอียด แต่ต่างจาก Rust ที่ลงไปทำงานระดับล่างเฉพาะตอนจำเป็น Zig ให้ความรู้สึกว่าต้องทำงาน ระดับล่าง อยู่ตลอด
- การทำ
/devicesส่งคำขอGETพร้อม authorization header ด้วยsendBodiless()แล้วอ่าน response ได้สูงสุด 64,000 ไบต์ ก่อน parse JSON เป็น[]const Device - แม้จะใช้
parseFromSliceLeakyแต่ก็ไม่มีปัญหาเรื่องการคืนหน่วยความจำเพราะมีการจัด arena allocator ภายในที่ไม่ได้เปิดเผยออกภายนอก
แผนขยายเป็นไลบรารีไดนามิก
- เป้าหมายสุดท้ายคือสร้าง ไลบรารีไดนามิกแบบไม่มี dependency ที่ภาษาในระดับสูงกว่านำไปใช้ได้
- โครงสร้างที่วางแผนไว้มีดังนี้
- Zig module
bedctl - CLI
bedctlที่ใช้ Zig module โดยตรง libbedctlที่ให้ C interface กับ Zig modulebedctl-dlที่ใช้ไลบรารีไดนามิกและใช้ตรวจสอบ C interface ด้วยตัวเอง
- Zig module
- หากมี Python wrapper ก็อยากนำไปใช้กับ Home Assistant แต่ไม่ได้ตั้งใจจะเขียนเอง
- การบิลด์ไลบรารีไดนามิกและอินเทอร์เฟซยังไม่พร้อม และมีแผนจะเพิ่มในเร็ว ๆ นี้
ประสบการณ์การนอนหลังใช้ไม่กี่วัน
- ช่วงไม่กี่วันที่ใช้งาน รู้สึกโดยส่วนตัวว่านอนหลับลึกขึ้น และ fitness tracker ก็แสดงว่า ช่วงการนอนเพื่อการฟื้นตัว ยาวขึ้น พร้อมจำนวนการตื่นกลางดึกลดลง
- แม้ในวันที่ดื่มวิสกี้ก็นอนดีกว่าปกติ แต่ไม่ควรตีความว่านั่นแปลว่าแอลกอฮอล์ดีต่อการนอน
- แอลกอฮอล์ยังคงเป็นผลเสียต่อสุขภาพและการนอน เพียงแค่อุปกรณ์อาจช่วยลดความแย่ลงได้บางส่วน
- ใช้อุปกรณ์มาเพียงไม่กี่วัน และ
bedctlเองก็เขียนขึ้นในเวลาราว 3 คืนเท่านั้น ดังนั้นผลลัพธ์ยังอยู่ในช่วงฮันนีมูน - ตอนแรกที่ตั้งอุณหภูมิต่ำเกินไป จะรู้สึกเย็นเหมือนนอนบนพื้นที่เปียก แต่หลังปรับอุณหภูมิก็หายไป
- ไม่ได้วัดเวลาเปลี่ยนผ่านโดยตรง แต่รู้สึกว่าเร็วจนใกล้ 1 นาทีมากกว่า 10 นาที
- น้ำที่ต้องเติมมีไม่ถึง 1 แกลลอน จึงไม่ได้มีความจุความร้อนมากนักให้ต้องทำความร้อนหรือทำความเย็น
การใช้รีโมต พัดลม และความร้อน
- รีโมตที่ให้มามีลักษณะเป็นปุ่มหมุนขนาดใหญ่พร้อมทัชสกรีน ทำให้เปลี่ยนอุณหภูมิได้ทันทีระหว่างที่ยังปรับตารางอุณหภูมิอยู่
- สัมผัสของปุ่มหมุนอาจไม่น่าพอใจนัก แต่มีการสั่นทุกครั้งที่เปลี่ยนหน่วยอุณหภูมิ จึงปรับได้โดยไม่ต้องมองหน้าจอ
- แม้ใส่ sleep mask อยู่ก็ยังรู้ได้จาก haptic feedback ว่าปรับไปมากแค่ไหน
- ยังต้องการการไหลเวียนของอากาศแบบอ่อน ๆ อยู่บ้าง ก่อนหน้านี้จึงต้องหาจุดสมดุลระหว่างแรงลมที่พอจะทำให้ห้องเย็นลง กับระดับที่ไม่เป่าโดนตัวตรง ๆ หรือทำให้ทางเดินหายใจแห้ง
- หลังใช้ Chilipad ก็เปิดพัดลมแค่ระดับต่ำสุดพอ
- ถ้าเพิ่มอุณหภูมิขึ้นเล็กน้อยในตอนเช้าจะรู้สึกอุ่นสบาย และคาดหวังว่าจะใช้ฟีเจอร์อุ่นเตียงล่วงหน้าในหน้าหนาวได้
- เมื่อปูท็อปเปอร์ลงไป การระบายอากาศจากด้านล่างจะลดลงบ้าง
- ไม่ถึงกับรู้สึกเหมือนนอนบนพลาสติก แต่ที่อุณหภูมิสูงจะรู้สึกว่าผิวหนังตรงที่สัมผัสเตียงมีเหงื่อชื้นเล็กน้อย
- นี่อาจเป็นประสบการณ์เฉพาะตัวจากลักษณะการควบคุมอุณหภูมิร่างกายของผู้เขียน และอาจไม่เหมือนผู้ใช้อื่น
- โดยรวมแล้วประสบการณ์ช่วงแรกเป็นบวก และมีโอกาสจะเขียนอัปเดตภายหลังเมื่อจัดทำไลบรารีไดนามิกเสร็จ
1 ความคิดเห็น
ความคิดเห็นจาก Lobste.rs
โพสต์นี้ได้เข้ากับธีมดีมาก เพราะลงตอน ก่อนหลับพอดี
bedctlให้ลดอุณหภูมิต่ำมากในเวลาที่กำหนด จะใช้ ปลุกให้ตื่น ได้ด้วยไหมทั้งชื่อและเนื้อหายอดเยี่ยมมาก อยากรู้ว่าเคยใช้ ผ้าห่มถ่วงน้ำหนัก ไหม และมันได้ผลจริงหรือเปล่า
ขึ้นอยู่กับวิธีผลิต มันอาจระบายอากาศไม่ดีและราคาแพงด้วย พอซื้อ Chilipad ไปแล้วจะมาบอกว่าแพงก็กระดากอยู่เหมือนกัน แต่ตัวที่จำไว้ว่าอยากลองดูทีหลังคือ https://bearaby.com/products/tree-napper ซึ่งเป็นโครงสร้างการทอแบบเปิดที่ดูเหมือนระบายอากาศได้ดี
กำลังดูสินค้าพวกนี้อยู่เหมือนกัน และคิดว่าสักวันคงลองใช้เอง ตามวิดีโอนี้ ทางออกที่คุ้มค่าที่สุดคือถัง แต่กรณีนั้นคงไม่มี API
บทความที่เกี่ยวข้องอยู่บ้าง: https://trufflesecurity.com/blog/removing-jeff-bezos-from-my-bed (วงสนทนา)
ตรงที่เทียบฟาเรนไฮต์กับเซลเซียส ดูเหมือนไม่น่าจะตั้งใจเขียนว่า Celsius is the better temperature
บทความสนุกมาก และก็เห็นด้วยกับวิธีคิดหลายส่วนรวมถึงเรื่องพัดลม แต่ยังไม่ชัดเจนว่าโปรเจกต์นี้ทำให้ ควบคุมอะไรได้บ้าง
ย่อหน้าที่บอกว่าประสบการณ์ปริญญาเอกด้านฟิสิกส์ทำให้สงสัยข่าววิทยาศาสตร์/สุขภาพจนกว่าจะพิสูจน์ได้ อาจถูกอ่านไปในทางอันตรายคล้ายความไม่ไว้วางใจวัคซีนได้ อย่างไรก็ตาม ฉันเข้าใจว่าเป็นการบอกว่าช่วงทำปริญญาเอกทำให้ไม่รับเอา “ข้อเท็จจริง” จากสื่อแบบขาวดำ และก็อยากรู้ว่าโดยเฉพาะแล้วอะไรที่ทิ้งบาดแผลไว้
ตอนที่งานวิจัยวัคซีนของ Andrew Wakefield ออกมา คนที่เห็นแค่ข่าวสั้น ๆ จากนักข่าวที่อ่านเพียงบทคัดย่อก็ฟันธงว่าวัคซีนอันตรายอย่างแน่นอน และถึงขั้นมีครูชีววิทยามัธยมปลายที่จบโทสัตววิทยา รวมถึงด็อกเตอร์ฟิสิกส์สามคน ออกมาต่อต้านวัคซีนด้วย แต่ ฉันทามติของวงการแพทย์ ยังคงชัดเจนว่าวัคซีนปลอดภัย มีประสิทธิภาพ และเป็นหนึ่งในเครื่องมือช่วยชีวิตที่ทรงพลังที่สุด และนักวิจัยการแพทย์ทุกคนที่ฉันพบก็เห็นตรงกัน
สาเหตุที่ช่วงปริญญาเอกทิ้งบาดแผลไว้ ก็เพราะฉันได้รู้ว่ามันมีช่องว่างใหญ่แค่ไหนระหว่างการค้นพบจริงในสาขาของตัวเองกับการรายงานข่าว เนื่องจากไม่มีทางเข้าใจทุกสาขาได้ทั้งหมด เรื่องการแพทย์ก็ควรเชื่อแพทย์ สิ่งแวดล้อมก็ควรเชื่อนักนิเวศวิทยา ภูมิอากาศก็ควรเชื่อนักภูมิอากาศวิทยา ฉันเคยเห็นด็อกเตอร์ฟิสิกส์พยายาม “หักล้าง” ผู้เชี่ยวชาญด้วยคณิตศาสตร์ระดับมัธยมต้นและวิทยาศาสตร์ระดับประถม แต่ผู้เชี่ยวชาญตัวจริงรู้ว่ามีความต่างมหาศาลระหว่างความรู้ระดับโรงเรียนกับความรู้เกี่ยวกับโลกจริง เพราะฉันเคยเห็นช่องว่างนั้นในสาขาที่ตัวเองเรียนมา จึงยิ่งเชื่อผู้เชี่ยวชาญมากขึ้นในสาขาที่ตัวเองไม่ได้เรียน
ถ้าโยนฟิลด์มั่ว ๆ ให้มีโครงสร้างตามต้องการได้ ตัว handler ก็น่าจะกำลังทำ การค้นหาด้วย regex ประมาณ
re.search('set_temperature_f": (\d+)',...)อยู่แทบจะแน่นอน