ชุดเครื่องมือควบคุมแสงไฟคีย์บอร์ด (backlight / RGB 3 โซน) สำหรับ Clevo N957TP6 / N9xTP6 ที่ใช้ BIOS ดัดแปลง (dsanke) บน Windows — สั่งงาน EC (Embedded Controller) โดยตรงผ่านไดรเวอร์ WinRing0 ไม่ต้องพึ่ง Control Center หรือ WMI ซึ่งใช้ไม่ได้บนเครื่องนี้
สถานะ: ใช้งานได้จริง ยืนยันบนฮาร์ดแวร์แล้ว ✅ — สี 3 โซน, ความสว่าง 4 ระดับ, เปิด/ปิดไฟ ผ่านการทดสอบด้วยสายตาทั้งหมด (ดูรายละเอียดท้ายไฟล์)
ภาพจริงจาก Dashboard บนเครื่อง (เปิดจาก tray icon หรือ
http://127.0.0.1:8787หลังรัน daemon) — แสดงการ์ดอุณหภูมิ/พัดลม, กราฟย้อนหลัง, แผงสลับโหมดเรียลไทม์ (Music/Ambient/Temp), Events viewer และแผงตั้งค่าแจ้งเตือน
ฟีเจอร์เด่น
| ฟีเจอร์ | รายละเอียด |
|---|---|
| 🎨 สีรายโซน | 3 โซน (ซ้าย/กลาง/ขวา) เลือกสีอิสระ + พาเลต 12 สีคลิกเดียวทั้งแถบ |
| 💡 ความสว่าง | 4 ระดับ (63/126/189/252) |
| ✨ โหมดเอฟเฟกต์ | Random / Dance / Tempo / Flash / Wave / Breathe / Cycle + ปรับความเร็ว 0–9 (ขึ้นกับเฟิร์มแวร์) |
| 🎵 Music reactive | ไฟกระพริบตามจังหวะเสียงระบบ — BASS/MID/TREBLE แยกโซน (WASAPI loopback + FFT) |
| 🌡️ Temperature reactive | ไล่สี cyan → เขียว → เหลือง → แดงตามความร้อน CPU/GPU (อ่านจาก EC RAM โดยตรง) กระพริบเตือน ≥90°C |
| ⌨️ Global hotkeys | ปุ่มลัดทำงานได้แม้โฟกัสอยู่ในเกม (กำหนดเองได้ผ่าน GUI) |
| 🔁 Daemon autostart | คืนค่าไฟเองหลัง boot / sleep / ต่อ dock + tray icon |
| 🖥️ Ambient mode | ไฟเปลี่ยนสีตามหน้าจอจริง (สไตล์ Ambilight, DirectX capture) |
| 🎛️ Color profiles | โปรไฟล์สีตั้งชื่อได้ (Gaming/Work/Night) สลับผ่าน GUI/tray/hotkey/CLI |
| 🎮 Game auto-profile | เปิดเกม (foreground = ไฟล์ .exe ที่กำหนด) → สลับโปรไฟล์อัตโนมัติ ปิดเกมแล้วกลับเอง · ตั้งกฎจาก Dashboard พร้อมปุ่ม "จับแอปฟื้กซ์" (v1.9.20) · แจ้งเตือนเมื่อสลับได้ (เปิดในแผงแจ้งเตือน) |
| ⏰ Day schedule | เปลี่ยนโปรไฟล์ตามเวลา (เช่น 22:00 → night) ข้ามเที่ยงคืนได้ |
| 🩺 Health check | daemon ตรวจ EC + อุณหภูมิ CPU เป็นระยะ เขียน status.json ให้เครื่องมืออื่นอ่าน (ดูย่อได้จาก tray) |
| 📊 Live Dashboard | เว็บสถานะสดที่ http://127.0.0.1:8787 — กราฟอุณหภูมิย้อนหลัง + เอนจินที่รัน (เปิดจาก tray) |
| 🔔 Toast แจ้งเตือน | Windows notification เมื่อ EC อ่านไม่ได้/กลับมาปกติ, CPU เกิน threshold, เอนจินหยุดเอง |
| 🧩 Hardware profiles | map เซ็นเซอร์ต่อรุ่น (hardware.profile) + --dump-ec --diff / ec_sensor_finder.py ช่วยหา address บนเครื่อง Clevo รุ่นอื่น |
| 🗂️ Event log | events.jsonl บันทึกเหตุการณ์ทั้งหมดแบบโครงสร้าง — วิเคราะห์ย้อนหลังได้ (--export-events) |
| 🌀 Fan monitor | อ่าน RPM/duty พัดลมสด ๆ (1 Hz) — ควบคุมไม่ได้โดย design ของ EC รุ่นนี้ (พิสูจน์แล้ว ดู RESEARCH.md) |
| 📦 ไฟล์เดียวจบ | แพ็กเป็น ClevoBacklight.exe ได้ (GUI + daemon + CLI + music + ambient) |
- ทำไมต้องเขียน EC ตรง?
- สถาปัตยกรรมของระบบ
- เริ่มใช้งานอย่างรวดเร็ว
- GUI — คู่มือทุกปุ่ม
- Music reactive mode
- CLI — คำสั่งทั้งหมด
- Daemon — ทำงานเบื้องหลัง + Hotkeys
- Autostart — เปิดเครื่องแล้วไฟกลับมาเอง
- settings.json — รูปแบบการตั้งค่า
- โปรโตคอล EC (สำหรับผู้อยากรู้)
- แพ็กเป็น ClevoBacklight.exe
- โครงสร้างไฟล์
- ผลการทดสอบบนเครื่องจริง
- แก้ปัญหา
- ข้อควรระวังด้านความปลอดภัย
ตรวจสอบบนเครื่องนี้แล้ว ช่องทางมาตรฐานทั้งหมดใช้ไม่ได้:
| ช่องทาง | สถานะ | เหตุผล |
|---|---|---|
WMI ของ Clevo (ABBC0F6D-…) |
❌ | DSDT มีบล็อก _WDG อยู่จริง แต่ไม่ถูกลงทะเบียนใน root\WMI (ไม่มี MOF) |
| Control Center 3.0 (Store) | ❌ | ต้องการไดรเวอร์ Insyde DCHU (GUID {86994C74-…}) ซึ่งไม่ได้ติดตั้ง — RGB ในแอปจึงกดแล้วไม่มีผล |
\\.\ACPI (IOCTL_ACPI_EVAL_METHOD_EX) |
❌ | symlink ไม่มีบน Windows build นี้ (26200) |
GetSystemFirmwareTable |
❌ | ถูกปิดแม้ยกระดับ admin |
| HID USB (ITE 8291) | ❌ | คีย์บอร์ดภายในเป็น PS/2 (ACPI\MSFT0001) ไม่มีคอนโทรลเลอร์ ITE แบบ USB |
ทางที่เหลือคือ เขียน EC RAM ตรง ๆ ผ่านพอร์ต 0x62/0x66 โดยใช้ไดรเวอร์ WinRing0x64.sys (ลงนาม Valid, v1.2.0.5) ที่โปรแกรมติดตั้ง/เรียกใช้เองแบบ on-demand — โปรโตคอล mailbox ทั้งหมดถอดรหัสจาก DSDT ของเครื่องนี้เอง (ไม่เดาจากเครื่องอื่น)
┌──────────────────────────────────────────────────────────────────┐
│ ชั้นผู้ใช้ (4 ทางเลือก) │
│ │
│ Clevo-Backlight-GUI.bat ──► clevo_backlight_gui.py (GUI+music) │
│ clevo_ec.py --color … ──► clevo_ec.py (CLI) │
│ clevo_music.py ──► โหมดตามเสียงเพลง (แยกต่างหากก็ได้) │
│ daemon (autostart) ──► clevo_daemon.py + tray + hotkeys │
│ + game watcher + day scheduler │
├──────────────────────────────────────────────────────────────────┤
│ config.py : settings.json (บันทึก/อ่าน/restore + hotkey parser) │
│ hotkeys.py : RegisterHotKey (global hotkey เธรดเดียว ปลอดภัย) │
│ clevo_music.py : WASAPI loopback → FFT → 3 แถบพลังงานเสียง │
│ clevo_ambient.py : DirectX screen capture → สีเฉลี่ยรายคอลัมน์ │
├──────────────────────────────────────────────────────────────────┤
│ clevo_ec.py : WinRing0 loader + EC port I/O + mailbox protocol │
│ (ถอดรหัสจาก DSDT ของเครื่องนี้) + CLI │
├──────────────────────────────────────────────────────────────────┤
│ WinRing0x64.sys (ลงนามแล้ว) ──► ports 0x62/0x66 ──► EC ──► LED │
└──────────────────────────────────────────────────────────────────┘
ทุกทางเลือกใช้ settings.json ไฟล์เดียวกัน — ตั้งค่าที่ไหนก็ได้ ที่เหลือ restore ให้เอง
ทางลัดที่ง่ายที่สุด:
ดับเบิลคลิก Clevo-Backlight-GUI.bat → GUI เปิดเลย (ขอ admin ครั้งเดียว)
ดับเบิลคลิก Install-Autostart.bat → ติดตั้ง daemon: ไฟคืนค่าเอง + hotkeys + tray
ดับเบิลคลิก Remove-Autostart.bat → ถอน daemon
(ถ้า build .exe แล้ว — ดู แพ็กเป็น ClevoBacklight.exe — ทั้งสอง .bat จะหยิบ exe มาใช้ให้เอง)
หรือแบบ command line (ต้องเปิด PowerShell แบบ Run as Administrator เอง):
python clevo_ec.py --on --color 00FF88 --brightness 3เปิดด้วย Clevo-Backlight-GUI.bat (หรือ python clevo_backlight_gui.py ใน terminal admin)
| ส่วน | คำอธิบาย |
|---|---|
| Power ON / OFF | เปิดหรือปิดไฟทั้งคีย์บอร์ด — กด ON จะใช้ค่าที่ตั้งไว้ทันที |
| บันทึกเป็นค่าเริ่มต้น | เซฟสถานะปัจจุบันลง settings.json — daemon จะใช้ค่านี้ตอน boot/resume |
| Brightness 0–3 | 4 ระดับ (raw 63/126/189/252) |
| Effect speed 0–9 | ความเร็วเอฟเฟกต์ (0 = เร็วสุด) — ใช้เมื่อโหมดไม่ใช่ Custom |
| Zone colors | คลิกแถบสีซ้าย/กลาง/ขวาเพื่อเปิดจานสี — เปลี่ยนเฉพาะโซนนั้น |
| Palette presets | 12 สีเตรียมไว้ — คลิกแล้ว apply ทั้งแถบทันที (แก้พาเลตได้ใน settings.json) |
| Effect mode | Custom / Random / Dance / Tempo / Flash / Wave / Breathe / Cycle |
| Music reactive | ดูหัวข้อถัดไป |
| Ambient (screen colors) | ดูหัวข้อ "Ambient mode" |
| Color profiles | ปุ่มโปรไฟล์ (● = กำลังใช้) — คลิกเพื่อ apply ทันที + บันทึกเป็นค่าหลัก |
| Global hotkeys | ปุ่ม "ตั้งค่า hotkeys…" — คลิกช่องแล้วกดคีย์ที่ต้องการ ระบบจับให้เอง |
| Status | แสดงผลการทำงานทุกคำสั่งแบบ real-time |
พฤติกรรมอัตโนมัติของ GUI:
- ทุกการเปลี่ยนแปลง บันทึกลง settings.json ทันที (ไม่ต้องกดเซฟ — ปุ่มบันทึกไว้ fix ค่าเริ่มต้นชัดเจน)
- เปิด GUI ขึ้นมา = apply ค่าที่เซฟไว้ทันที
- กลับจาก sleep (หายไป >60 วิ) = คืนค่าไฟอัตโนมัติหลัง 1.5 วิ — เผื่อ EC ตื่นไม่ทัน
- เปลี่ยนสี/เลือก preset จะเปิดไฟให้เองถ้ายังปิดอยู่ (ประสบการณ์ใช้งานลื่นกว่า)
- เริ่มการทำงานใด ๆ (สี/โหมด/preset) จะหยุด music mode ให้ก่อนเสมอ กันคำสั่งชนกัน
ไฟคีย์บอร์ดเต้นตามเสียงที่เครื่องกำลังเล่น (เพลง/วิดีโอ/เกม) โดยไม่ต้องไมโครโฟน — อ่านจาก WASAPI loopback ของการ์ดเสียงโดยตรง
เสียงระบบ → loopback 48kHz → FFT (Hanning window)
→ BASS 20–250 Hz → โซนซ้าย
→ MID 250–2 kHz → โซนกลาง
→ TREBLE 2–16 kHz → โซนขวา
แต่ละแถบ: RMS พลังงาน → adaptive noise floor (เงียบ = ดับ)
→ attack/decay envelope (ปลายขึ้นไว 0.55 / ปล่อยช้า 0.12)
→ beat detector (เบสกระโดด = แฟลชเพิ่ม 35%)
→ เขียนสีรายโซน (สีพื้น × พลังงาน) ทุก ~30ms
ใน GUI:
| คอนโทรล | คำอธิบาย |
|---|---|
| ▶ เริ่มตามเสียงเพลง / ■ หยุด | สลับโหมด — หยุดแล้วคืนสีคงที่เดิมให้เอง |
| สีไล่เฉดเดียว (checkbox) | ใช้สีเดียวไล่มืด→สว่าง 3 โซน (แก้สีที่ช่องสีข้าง ๆ) — ไม่ติ๊ก = ใช้สีรายโซนที่ตั้งไว้ |
| Sensitivity 0.2–3.0 | คูณกำไร — ปรับสดได้ระหว่างเล่น ไม่ต้องกดหยุด (เบา <0.8, ดัง ~1.0, หูตาย >1.5) |
| แถบ BASS/MID/TRE | เอฟเฟกต์เล็กแสดงพลังงานแต่ละแถบตามเวลาจริง (สีตามโซนจริงที่กำลังเขียน) |
ผ่าน CLI (รันแยกเลยก็ได้):
python clevo_music.py --list-devices # ดูอุปกรณ์ loopback ทั้งหมด
python clevo_music.py # ใช้สีรายโซนที่เซฟไว้
python clevo_music.py --color FF0080 # ไล่เฉดจากสีเดียว
python clevo_music.py --sensitivity 1.5 --floor 0.15
python clevo_ec.py --music --sensitivity 1.2 # ทางเลือกผ่าน CLI หลักพารามิเตอร์: --sensitivity (กำไร), --floor (ความสว่างขั้นต่ำ 0–1, default 0.12 กันสีจางจนจำไม่ได้), --interval (ช่วงห่างเขียน EC วินาที, default 0.03), --device (เลือกอุปกรณ์เสียงเฉพาะชื่อย่อย)
ข้อจำกัด: เสียงต้องเล่นผ่านอุปกรณ์ default output (Realtek Speakers ของเครื่องนี้มี loopback ให้ใช้); เสียงผ่าน HDMI/Bluetooth ต้องระบุ --device; ใช้ CPU ~1–2% (FFT block 1024)
ไฟคีย์บอร์ดเปลี่ยนสีตามสีหน้าจอจริง (สไตล์ Ambilight) — จับหน้าจอด้วย DirectX Desktop Duplication (ผ่าน mss), แบ่งเป็น 3 แถบแนวตั้งซ้าย/กลาง/ขวา แล้วส่งสีเฉลี่ยของแต่ละแถบเข้าโซนนั้น
หน้าจอ → จับเฟรม (DirectX/mss, ย่อเหลือ 96×54 จุด)
→ แถบซ้าย → สีเฉลี่ย → gamma 1.6 (ดันฉากมืดให้ยังเห็น hue)
→ แถบกลาง → สีเฉลี่ย → ┐
→ แถบขวา → สีเฉลี่ย → ┘
→ ผสมกับสีที่เซฟไว้ตาม Mix (0 = สีที่เซฟ, 1 = สีจอล้วน, default 0.35)
→ smoothing attack/decay (ไฟไหล่ลื่น ไม่กระพริบสั่น)
→ เขียน EC ทุก 0.25 วิ (ปรับได้)
ใน GUI: ปุ่ม ▶ เริ่มตามสีหน้าจอ / ■ หยุด + สไลเดอร์ Mix ปรับสดระหว่างเล่นได้
ผ่าน CLI (รันแยกเลยก็ได้):
python clevo_ambient.py # default mix 0.35
python clevo_ambient.py --mix 0.6 # สีจอชัดขึ้น
python clevo_ambient.py --interval 0.15 # ตอบสนองไวขึ้น (CPU ขึ้นตาม)
python clevo_ec.py --ambient --mix 0.5 # ทางเลือกผ่าน CLI หลักข้อจำกัด: ต้องมี mss (pip install mss) ไม่งั้น fallback เป็น PIL ImageGrab (ช้ากว่า); เนื้อหาป้องกันการจับ (Netflix/DRM) จะได้สีดำ — เป็นข้อจำกัดของระบบปฏิบัติการ; ใช้ CPU ~2–4% ที่ interval 0.25
โปรไฟล์ = ชุดค่า (brightness + สี 3 โซน + โหมด + ความเร็ว) ตั้งชื่อเก็บไว้สลับใช้ทันที — ค่าเริ่มต้นมี 3 โปรไฟล์: gaming (แดง สว่างสุด), work (ฟ้าอ่อน ระดับ 2), night (ส้ม หรี่สุด)
สลับโปรไฟล์ได้ 4 ทาง:
| ทาง | วิธี |
|---|---|
| GUI | คลิกปุ่มชื่อโปรไฟล์ (● = กำลังใช้) |
| Tray | คลิกขวา tray icon → เมนูโปรไฟล์ / "โปรไฟล์ถัดไป" |
| Hotkey | Ctrl+Alt+P = วนโปรไฟล์ถัดไป (แก้ได้ใน settings.json) |
| CLI | python clevo_ec.py --profile night |
การ apply โปรไฟล์จะเขียนทับค่าหลักทันที (เปิดไฟ + ตั้งค่าทุกอย่าง + mark active_profile + เซฟ settings.json) — daemon restore กลับเข้าโปรไฟล์ล่าสุดเสมอ และเอฟเฟกต์เรียลไทม์ (music/ambient) จะถูกหยุดก่อนสลับโปรไฟล์อัตโนมัติ
เพิ่ม/แก้โปรไฟล์: แก้ settings.json ตรง ๆ (ค่าผิดรูปจะถูก validate + fallback อัตโนมัติ):
"profiles": {
"gaming": {"brightness": 3, "colors": ["FF3B30", "FF3B30", "FF3B30"], "mode": "custom", "speed": 4},
"movie": {"brightness": 1, "colors": ["007AFF", "007AFF", "007AFF"], "mode": "breathe", "speed": 6}
}ทำงานเบื้องหลังใน daemon (ตั้งค่าใน GUI สองแผงล่าง, การ์ด "สลับโปรไฟล์อัตโนมัติตามแอป" บน Dashboard/มือถือ (v1.9.17) หรือแก้ settings.json ตรง ๆ)
🎮 Game auto-profile — ทุก ~5 วิ daemon ดูว่าหน้าต่างโฟกัสเป็นของโปรเซสไหน (อ่านชื่อ .exe แบบ light-weight ไม่แตะ title): ถ้าอยู่ในรายการ → apply โปรไฟล์นั้นทันที; ปิดเกม → กลับไปโปรไฟล์ restore_profile — เพิ่ม/ลบกฎจากหน้าเว็บได้ผ่าน POST /api/auto_profiles (ต้องเปิด allow_control; ลบกฎส่งค่า null)
"auto_profiles": {
"enabled": true,
"games": {"cyberpunk2077.exe": "gaming", "valorant.exe": "gaming"},
"restore_profile": "work",
"poll_seconds": 5
}⏰ Day schedule — เปลี่ยนโปรไฟล์ตามเวลาของวัน (นาฬิกาเครื่อง); ก่อนช่วงแรกของวันใช้ช่วงสุดท้ายข้ามเที่ยงคืน (เช่น 22:00 → night จะครอบคลุมถึง 07:59 ของเช้าถัดไป)
"schedule": {
"enabled": true,
"slots": [
{"time": "08:00", "profile": "work"},
{"time": "22:00", "profile": "night"}
]
}กติกา: เกมชนะ scheduler เสมอ (เปิดเกมตอนกลางคืนก็ได้โปรไฟล์ gaming) · ทุกกฎ debounce — ไม่เขียน EC ซ้ำถ้าสถานะไม่เปลี่ยน · แก้ค่าได้ระหว่างรัน daemon อ่านค่าใหม่ทุก poll ไม่ต้องรีสตาร์ท · ค่า .exe/ชื่อโปรไฟล์ที่ผิดจะถูก validate ทิ้งอัตโนมัติ
ไฟคีย์บอร์ดเปลี่ยนสีตามความร้อนจริงของเครื่อง — อ่านอุณหภูมิจาก EC RAM โดยตรง:
| แหล่ง | EC RAM | การยืนยัน |
|---|---|---|
| CPU | 0x07 |
อ่านได้ 45°C ตรงกับ Windows thermal zone (45.1°C) เป๊ะ |
| GPU | 0x08 |
คู่ CPU ตาม convention Clevo (ตรวจซ้ำด้วย --read ระหว่างเล่นเกม) |
≤35°C cyan-green หรี่ (idle) → 50°C เขียว → 62°C เหลือง → 75°C ส้ม
→ 85°C แดงส้ม → ≥95°C แดงสุด · ≥90°C กระพริบเตือน (1 Hz)
ความสว่างไล่ 35%→100% ตามความร้อน (35–85°C) · เปลี่ยนสีนุ่มไม่กระตุก · อ่านทุก 2 วิ
ใน GUI: แผง Temperature reactive — ▶ เริ่ม/■ หยุด + เลือกแหล่ง cpu/gpu + ตัวเลข °C แบบเรียลไทม์
python clevo_temp.py --source gpu # รันแยก
python clevo_ec.py --temp # ทางเลือกผ่าน CLI หลัก (default CPU)ถอดปลั๊ก = daemon จัดการให้เอง (เช็ก GetSystemPowerStatus ทุก 10 วิ):
| สถานะ | การกระทำ |
|---|---|
| บนแบต | จำกัดความสว่างไม่เกินระดับที่ตั้ง และ/หรือ apply โปรไฟล์ประหยัด (เช่น work หรี่ ๆ) — ไม่แก้ค่าที่เซฟไว้ |
บนแบต + ต่ำกว่า low_percent |
หรี่ตาม cap เดิม (ถ้าตั้ง low_percent ไว้) |
บนแบต + ต่ำกว่าครึ่งหนึ่งของ low_percent |
หรี่เหลือระดับ 1 (critical — เหลือไฟนิดเดียวกันพอเห็น) |
| เสียบปลั๊กกลับ | คืนค่าหลักจาก settings.json ทันที |
ตั้งค่าใน GUI แผง "Battery saver" (เปิดใช้งาน + โปรไฟล์บนแบต + ความสว่างสูงสุด + หรี่เพิ่มเมื่อแบตต่ำกว่า %) หรือแก้ settings.json: "battery": {"enabled": true, "profile": "", "brightness": 1, "low_percent": 25}
เปิด/ปิดได้ทุกอันจาก GUI แผง Notifications (หรือ settings notifications): EC ล่ม / EC กลับมา / CPU ร้อนเกินเกณฑ์ (75–100°C, hysteresis 5°) / พัดลมหยุดหมุน (RPM=0 ขณะ ≥ เกณฑ์−10°, dedup ต่อตอน)
daemon รวม history เป็นสถิติรายวัน (daily_stats.json เก็บ 60 วัน): อุณหภูมิเฉลี่ย/สูงสุด, RPM เฉลี่ย/สูงสุด, จำนวน EC fail, uptime — dashboard แผง "สรุปรายวัน" วาดกราฟแท่ง 30 วัน (สีตามพีค: เขียว/ส้ม/แดง) + ตาราง 14 วันล่าสุด · API: GET /api/daily
แผง สรุปรายสัปดาห์ จัดกลุ่มเป็น ISO week: พีคอุณหภูมิ/RPM, EC fail รวม, วันที่ร้อนสุดของสัปดาห์ + บอกชั่วโมงที่เคยวัดร้อนสุดจาก history (GET /api/weekly)
เปิด checkbox "อนุญาตให้ควบคุมไฟจากหน้าเว็บ" ในแผง Dashboard ของ GUI แล้วหน้าเว็บ (localhost หรือ LAN พร้อม token) จะมีปุ่ม: power เปิด/ปิด · ความสว่าง 0–3 · โปรไฟล์ทุกตัว · โหมดเรียลไทม์ music/ambient/temp (▶/■) · ⚡ Quick Actions (พรีเซ็ตกลางคืน/เกมมิ่ง/ทำงาน) — ส่งเป็น POST /api/cmd {"action": "power|brightness|profile|engine|light", ...} ผ่าน daemon (ปิดโดย default) · สั่ง EC เหมือนกด hotkey — ไม่แก้ settings ที่เซฟไว้
สั่งจาก Home Assistant / สคริปต์ (v1.9.21) — action light: สีต่อโซน 1–3 ช่อง (hex) + brightness + mode + speed โดยไม่บันทึกทับโปรไฟล์ และตั้ง restore ให้กลับโปรไฟล์เดิมเองหลัง N วินาที:
curl -X POST http://127.0.0.1:8787/api/cmd?token=TOKEN \
-H "Content-Type: application/json" \
-d '{"action":"light","zones":["ff0000","00ff00"],"brightness":2,
"mode":"breathe","speed":6,"restore":"work","restore_after":300}'HA example (rest_command):
rest_command:
kb_light:
url: http://PC-IP:8787/api/cmd?token=YOUR_TOKEN
method: POST
payload: '{"action":"light","zones":["{{ zones }}"],"brightness":{{ level }}}'ใส่ URL webhook ใน GUI แผง Notifications (หรือ notifications.discord_webhook) แล้วได้รับ:
- ทุก toast แจ้งเตือนที่ผ่านเกณฑ์ (EC ล่ม/กลับมา, CPU ร้อน, พัดลมหยุด)
- สรุปรายวันอัตโนมัติ ตอนเปลี่ยนวัน: อุณหภูมิเฉลี่ย/พีค, RPM เฉลี่ย, จำนวน EC fail
ไม่มี dependency เพิ่ม (HTTP ตรง) — webhook พลาดแล้ว log ไว้ใน daemon.log แทน crash
เหมือน Discord แต่ผ่านบอทของคุณเอง: สร้างบอทจาก @BotFather (ได้ token) → หา chat_id ของคุณ (เช่นจาก @userinfobot) → ใส่ทั้งสองค่าใน GUI แผง Notifications (token ซ่อนเป็น ***) จะได้แจ้งเตือน + สรุปรายวันเข้า Telegram (notifications.telegram_token / telegram_chat_id)
แผง สุขภาพเครื่อง ให้เกรด A–F จากข้อมูล 30 วันล่าสุด (คะแนนเต็ม 100): อุณหภูมิพีค (40 คะแนน) + วันพัดลมนิ่ง (30) + ความน่าเชื่อถือของ EC (30) — เกรด A ≥85, B ≥70, C ≥50, D ≥30, F ต่ำกว่า · ดูได้จาก GET /api/daily field health
daemon สำรอง settings.json + history.json + daily_stats.json ไป backups/ วันละ 1 ชุดอัตโนมัติ เก็บย้อนหลัง 7 ชุด + zip รายสัปดาห์ (week-<ISO>.zip เก็บ 4 สัปดาห์) — จัดการได้จากแผง สำรอง & กู้คืน บน Dashboard: ดูรายการ · ดาวน์โหลด zip · ปุ่ม "สำรองเดี๋ยวนี้" · กู้คืนแบบไม่ต้องรีสตาร์ท (settings reload ผ่าน loader ปกติ แล้วดันโปรไฟล์ active กลับเข้าไฟเอง)
python clevo_ec.py --list-backups # ดู stamp ที่มี
python clevo_ec.py --restore-backup 2026-09-17_12-00 # กู้คืน (มีผลทันทีตั้งแต่ v1.9.22)API: GET /api/backups (list) · GET /api/backups/<file> (ดาวน์โหลด) · POST /api/backups/restore {"file":"<stamp>__settings.json"}
ทุก release แนบ SHA256SUMS.txt (CI สร้างจาก zip + Setup) · daemon อ่าน digest จาก GitHub API แล้วตรวจไฟล์ที่ดาวน์โหลดก่อนใช้เสมอ — ไม่ผ่าน = ลบทิ้ง + toast เตือน + event download_rejected (release เก่าที่ไม่มี digest ยังใช้ได้เหมือนเดิม)
ซ้อมห่วงโซ่อัปเดตทั้งสายโดยไม่รอ release และไม่แตะค่าจริง — 3 ทางเลือก:
- Tray menu → "Run update self-test (ทดสอบห่วงโซ่อัปเดต)" — ผลแจ้งเป็น toast/notify
- Dashboard → การ์ด "🧪 Update self-test" กด ▶ Run update self-test — เห็นผลรายขั้นสด (prepare → disk → download+checksum → verify → restore-roundtrip → relaunch) ปิดหน้าแล้วกลับมายังตามต่อได้
- CLI →
ClevoBacklight.exe --update-selftest(headless — พิมพ์ JSON รายขั้น exit 0/1)
chip 🧬 sha บน Dashboard แสดง SHA-256 ของ exe ที่กำลังรัน พร้อมเทียบกับ digest ของ release ล่าสุด (ตรง = เขียว "= release ✓" · ต่าง = ส้ม ⚠ เช่น dev build) · CI build exe + installer ทุก push พร้อมรัน self-test บน exe จริงก่อนขึ้น tag · หน้า download (GitHub Pages) ดึง release ล่าสุดจาก GitHub API พร้อมปุ่มดาวน์โหลด + checksum แบบคัดลอกได้
นอกจากนี้ v1.9.23 เพิ่มการแจ้งเตือน backup/restore ครบวงจร (เกต on_backup/on_restore ในแผงแจ้งเตือน — backup ล้มเหลวแจ้งเสมอแม้ mute ทุกช่องทาง) · EC fail ต้องเจอต่อเนื่อง ec_fail_threshold ครั้ง (default 2) ก่อนแจ้ง พร้อมสำรองฉุกเฉินก่อนแจ้งเตือน · การกู้คืน/อัปเดตมี safety snapshot (pre-restore-…/pre-update-…) ก่อนทำเสมอ
python clevo_ec.py --read # อ่านค่า EC (ทดสอบการเชื่อมต่อ ไม่มีการเขียน)
python clevo_ec.py --on # เปิดไฟ
python clevo_ec.py --off # ปิดไฟ
python clevo_ec.py --brightness 2 # ความสว่าง 0-3
python clevo_ec.py --color FF8000 # สีทั้งคีย์บอร์ด (RRGGBB)
python clevo_ec.py --zone 2 --color FF0000 # เฉพาะโซน (0=ซ้าย 1=กลาง 2=ขวา)
python clevo_ec.py --mode breathe # random|dance|tempo|flash|wave|breathe|cycle
python clevo_ec.py --mode wave --speed 2
python clevo_ec.py --music # โหมดตามเสียงเพลง (Ctrl+C หยุด)
python clevo_ec.py --music --sensitivity 1.4
python clevo_ec.py --profile night # apply โปรไฟล์ชื่อ night (ดูหัวข้อ Color profiles)
python clevo_ec.py --ambient --mix 0.5 # โหมดตามสีหน้าจอ (Ctrl+C หยุด)
python clevo_ec.py --temp --source gpu # โหมดตามอุณหภูมิ (Ctrl+C หยุด)
python clevo_ec.py --temp --reg 0x07 # ระบุ address EC RAM ของเซ็นเซอร์เอง (เครื่องรุ่นอื่น)
python clevo_ec.py --ambient --mix 0.5 --interval 0.1 # ambient อัปเดตเร็วขึ้น
python clevo_ec.py --dump-ec # dump EC RAM 0x00-0xFF (ช่วยหาเซ็นเซอร์ temp/fan)
python clevo_ec.py --export-csv # export ประวัติ temp/fan เป็น CSV (ไม่ต้องแอดมิน)
python clevo_ec.py --save --color 00FF88 --brightness 3 # เซฟเป็นค่าเริ่มต้น
python clevo_ec.py --apply-saved # apply ค่าที่เซฟไว้ (ใช้ใน startup script ได้)คอมโบ: python clevo_ec.py --on --color 00FF88 --brightness 3 --save
หมายเหตุ: คำสั่งปกติจะ ซิงก์ลง settings.json ให้ด้วยเสมอ ยกเว้น --read — ดังนั้นสั่งผ่าน CLI แล้ว daemon/GUI จะ restore ตรงกับสิ่งที่ตั้งล่าสุดเสมอ
clevo_daemon.py (รันด้วย pythonw จึงไม่มีหน้าต่างดำ) ทำหน้าที่:
- Restore ตอน boot — apply ค่าจาก settings.json ทันทีที่เริ่มทำงาน
- Restore หลัง sleep/resume — ฟัง
WM_POWERBROADCASTตื่นมาหน่วง 4 วิ (ให้ EC พร้อม) แล้ว apply ใหม่ (debounce กัน resume storm) - Restore หลัง hotplug — จอเปลี่ยน/ต่อ dock (
WM_DISPLAYCHANGE,WM_DEVICECHANGE) ก็ apply ใหม่ - Automation — game auto-profile + day schedule (ดูหัวข้อก่อนหน้า) รันในเธรดแยก
- Single-instance guard — global mutex
Global\\ClevoBacklightDaemon: สั่งรันซ้ำ/task ยิงซ้ำ ตัวเก่าจะออกเองเงียบ ๆ ไม่มีสอง daemon แย่ง EC + hotkeys กัน - Global hotkeys — ทำงานจากที่ไหนก็ได้ แม้โฟกัสอยู่ในเกม/เบราว์เซอร์:
Ctrl+Alt+Lสลับเปิด/ปิดไฟCtrl+Alt+↑ / ↓เพิ่ม/ลดความสว่างCtrl+Alt+Cเปลี่ยนสีถัดไปในพาเลตCtrl+Alt+Pสลับโปรไฟล์ถัดไปCtrl+Alt+Mเปิด/ปิด โหมดเพลง (สั่งผ่าน daemon — ครั้งละหนึ่งเอนจิน ตัวอื่นถูกหยุดให้เอง)Ctrl+Alt+Aเปิด/ปิด โหมด AmbientCtrl+Alt+Kปิด daemon ทันที (ปุ่มฉุกเฉิน แก้ไม่ได้ by design)
- Tray icon — คลิกซ้ายที่ไอคอน = สลับเปิด/ปิด; คลิกขวา = เมนู (ความสว่าง, โปรไฟล์, โหมดเพลง/Ambient พร้อมเครื่องหมาย ▶/■ ตามสถานะจริง, พาเลตสี 12 สี, สีถัดไป, สถานะ: EC OK, CPU °C, ออก) — ไอคอนเปลี่ยนสีตามไฟจริง
- Health check — ทุก 60 วิ (ปรับได้ใน
health_check) อ่านอุณหภูมิ CPU จาก EC แล้วเขียนstatus.jsonข้างโปรแกรม ตัวอย่าง:ใช้จากสคริปต์/เครื่องมือมอนิเตอร์อื่นได้ทันที · ถ้า EC อ่านไม่ได้จะบันทึก{"time": "2026-09-17 02:00:00", "version": "1.7.0", "ec_ok": true, "cpu_temp": 47, "power": true, "engines": ["music"], "uptime_s": 86400}ec_ok: false+ ข้อความ error +seconds_since_last_okไว้ดูย้อนหลัง · ตัวเลขเดียวกันนี้โชว์ย่อในเมนู tray
Live Dashboard: daemon เปิดเว็บเซิร์ฟเวอร์เล็ก ๆ ที่ http://127.0.0.1:8787 (localhost เท่านั้น) — แสดงสถานะ EC, อุณหภูมิ, การ์ดพัดลม (RPM/duty), ไฟ, uptime, เอนจินที่รัน, กราฟอุณหภูมิ + กราฟ RPM พัดลมย้อนหลัง ~12 ชม. พร้อมสถิติ min/max/avg และปุ่ม ⬇ ดาวน์โหลด CSV (จาก history.json, รีโหลดตอน daemon เริ่มใหม่) เปิดจากเมนู tray "เปิด Dashboard" · API: GET /api/status (status + history) และ GET /api/history.csv (ดาวน์โหลดประวัติ, ปิดได้ด้วย dashboard.serve_history_csv)
เตือนพัดลมหยุดหมุน: ถ้าอ่านได้ RPM = 0 ขณะ CPU ร้อนถึงเกณฑ์ (temp_threshold − 10°) daemon จะส่ง toast แจ้งทันที (dedup ต่อตอน — เตือนรอบเดียวจนกว่าจะเย็นลงกว่า threshold − 15° จึงพร้อมเตือนใหม่) · ปิดได้ด้วย notifications.on_fan_stall
Toast notifications (ปิดได้ใน settings notifications): EC อ่านไม่ได้ → แจ้งทันที (watchdog เช็กทุก 10 วิ ระหว่างรอ health probe), กลับมาปกติ → แจ้งรอบเดียว (มี dedup), CPU ≥ threshold (ค่าเริ่ม 90, hysteresis 5°), เอนจิน (เพลง/ambient) หยุดเองเพราะ device หาย
Hardware profiles: ค่าเริ่มต้น n957tp6 (map ที่ยืนยันแล้ว: CPU=0x07, GPU=0x08) — เครื่องรุ่นอื่นแก้ hardware.profile / temp_reg_override ใน settings แล้วใช้ --dump-ec --label idle --save-dump a.json → โหลดหนัก → --dump-ec --label load --diff a.json หา address ที่ค่าวิ่งตามอุณหภูมิ
เปลี่ยนปุ่มลัด: ทำได้ 2 ทาง — GUI ปุ่ม "ตั้งค่า hotkeys…" หรือแก้ settings.json ตรง ๆ (ดูรูปแบบข้างล่าง) — hotkey ใหม่มีผลหลังรีสตาร์ท daemon
เปิด/ปิด daemon: ติดตั้งด้วย Install-Autostart.bat หรือรันมือใน terminal admin: pythonw clevo_daemon.py — log ทุกเหตุการณ์อยู่ที่ daemon.log · มีโหมดยูทิลิตี้ python clevo_daemon.py --restore-only (apply ครั้งเดียวแล้วจบ — ใส่สคริปต์อื่นได้)
Install-Autostart.bat จะ (self-elevate ผ่าน UAC):
- สร้าง Scheduled Task ชื่อ
ClevoBacklightDaemon(ONLOGON, RunLevel=Highest) — เลือกใช้dist\ClevoBacklight.exe --daemonถ้า build แล้ว ไม่งั้นใช้pythonw clevo_daemon.py - รัน daemon ทันที — tray icon โผล่ใน 2–3 วิ
Remove-Autostart.bat จะหยุด process + ลบ task (ไฟคงสถานะเดิมไว้ ไม่ดับ)
ทำไมใช้ Scheduled Task ไม่ใช่ Startup โฟลเดอร์/Registry Run? เพราะ daemon ต้องการ สิทธิ์ admin เพื่อโหลดไดรเวอร์ WinRing0 — Task แบบ
/RL HIGHESTยกระดับให้เองตั้งแต่ logon โดยไม่มีหน้าต่าง UAC กระโดดขึ้นทุกครั้ง
ไฟล์ถูกสร้างอัตโนมัติครั้งแรกที่รัน GUI/CLI/daemon แก้ตรง ๆ ได้ (ต้องปิด GUI ก่อน ไม่งั้นจะโดนเขียนทับ):
{
"power": true,
"brightness": 3,
"colors": ["00FF88", "00FF88", "00FF88"],
"mode": "custom",
"speed": 4,
"hotkeys": {
"toggle": "Ctrl+Alt+L",
"brightness_down": "Ctrl+Alt+Down",
"brightness_up": "Ctrl+Alt+Up",
"cycle_color": "Ctrl+Alt+C",
"cycle_profile": "Ctrl+Alt+P",
"music": "Ctrl+Alt+M",
"ambient": "Ctrl+Alt+A"
},
"palette": ["FF3B30", "FF9500", "FFCC00", "34C759", "00FF88",
"00C7BE", "30B0C7", "007AFF", "5856D6", "AF52DE",
"FF2D55", "FFFFFF"],
"profiles": {
"gaming": {"brightness": 3, "colors": ["FF3B30", "FF3B30", "FF3B30"],
"mode": "custom", "speed": 4},
"work": {"brightness": 2, "colors": ["30B0C7", "30B0C7", "30B0C7"],
"mode": "custom", "speed": 4},
"night": {"brightness": 0, "colors": ["FF9500", "FF9500", "FF9500"],
"mode": "custom", "speed": 4}
},
"active_profile": "",
"auto_profiles": {"enabled": false, "games": {}, "restore_profile": "", "poll_seconds": 5},
"schedule": {"enabled": false, "slots": []},
"engines": {"music_sensitivity": 1.0, "music_gradient": false,
"music_gradient_color": "FF0080", "ambient_mix": 0.35,
"ambient_interval": 0.25, "temp_source": "cpu", "temp_reg": null},
"health_check": {"enabled": true, "interval": 60},
"autostart": false
}colors— RRGGBB รายโซน [ซ้าย, กลาง, ขวา]mode—custom= ใช้สีจากcolors(คงที่) หรือชื่อโหมดเอฟเฟกต์speed— 0 เร็วสุด → 9 ช้าสุด (ใช้เมื่อ mode ≠ custom)hotkeys.*— รูปแบบMod+Mod+Key: Ctrl/Shift/Alt/Win + คีย์ (A–Z, 0–9, F1–F24, ลูกศร, PageUp/Down, Home/End, Insert/Delete, Space, Tab, Enter, Esc, Backspace, Pause, CapsLock, Numpad0–9) — คีย์เปล่า ๆ เช่นLอย่างเดียวห้ามใช้ (ชนกับการพิมพ์ทั่วไป)profiles— โปรไฟล์สีที่ตั้งชื่อได้ (ดูหัวข้อ Color profiles);active_profile— ชื่อโปรไฟล์ที่ใช้ล่าสุด (ว่าง = ไม่ได้ใช้โปรไฟล์)auto_profiles/schedule— กฎสลับโปรไฟล์อัตโนมัติ (ดูหัวข้อ Automation)engines— ค่าเริ่มต้นของโหมดเรียลไทม์ที่ daemon ใช้เมื่อสั่งผ่าน hotkey: music sensitivity/gradient, ambient mix/interval, แหล่งอุณหภูมิ และtemp_reg= address EC RAM ของเซ็นเซอร์ (null = ใช้ 0x07/0x08 มาตรฐาน — เครื่อง Clevo รุ่นอื่น map ต่างกันได้ ใช้--dump-ecเทียบค่าก่อน/หลังโหลดหนักเพื่อหา) · ตั้งค่าจาก GUI แผง "Engine defaults" ได้health_check— เปิด/ปิด + ความถี่ (วินาที, ต่ำสุด 15) ของการเขียนstatus.jsonhardware—profile= ชื่อรุ่นที่ระบบรู้จัก (n957tp6) +temp_reg_override(0–255 หรือ null) สำหรับเครื่องรุ่นอื่นnotifications—enabled/on_ec_fail/on_ec_recover/temp_threshold(60–110, ค่าเริ่ม 90) ของ toast แจ้งเตือน- ค่าที่ไม่ถูกต้องจะถูกเปลี่ยนกลับเป็นค่า default อัตโนมัติ (ป้องกันไฟล์เสียทำให้โปรแกรมเปิดไม่ได้)
อ่านสถานะพัดลม CPU/GPU จาก EC (register ถอดจาก DSDT RAM-mirror — DUT1/2 @ 0xCE/0xCF, RPM1/2 @ 0xD0/0xD2):
python clevo_ec.py --fan status # RPM + duty ครั้งเดียว
python clevo_ec.py --fan watch # มอนิเตอร์ต่อเนื่องทุก 1 วิ (Ctrl+C หยุด)
python clevo_ec.py --fan auto # (no-op — EC รันนโยบายตัวเองเสมอ)หรือแผง Fan monitor ใน GUI (ปุ่มอ่านสถานะ / ▶ เริ่มมอนิเตอร์ — อัปเดตทุก 1 วิ)
ทำไมสั่ง duty manual ไม่ได้? พิสูจน์บนเครื่องจริงแล้ว 3 ชั้น: (1) เขียน DUT แล้ว EC ทับกลับเองใน ~1 วิ (2) ยิงซ้ำ 4 Hz duty ค้างใน RAM แต่ RPM ไม่ขยับ = EC ไม่เอาค่าไปขับ PWM (3) DSDT ไม่มี write path ถึง DUT/RPM เลย — ดูรายละเอียดใน
RESEARCH.mdหัวข้อ 5.1 · unit test การันตีว่า monitor ไม่เขียน EC แม้ไบต์เดียว
แก้ไขจากเวอร์ชันก่อน: GPU temp คือ
0xC7 (VGAT)ตาม DSDT ไม่ใช่ 0x08 (0x08 =AC1trip point ที่ ACPI เขียนลงไป) — รายละเอียดในRESEARCH.md
ค่าเริ่มต้นเซิร์ฟเวอร์ dashboard ผูกกับ 127.0.0.1 เท่านั้น ถ้าต้องการดูจากมือถือ/เครื่องอื่น: ตั้งใน GUI แผง Dashboard (เปิดบน LAN + กรอก token) หรือแก้ settings:
"dashboard": {"enabled": true, "bind": "lan", "token": "รหัสลับยาว ๆ"}- LAN ต้องมี token — ถ้าไม่มี daemon จะ fallback เป็น loopback ให้เอง (ไม่มีทางเปิด LAN แบบไม่มีรหัส)
- ใส่ token ได้ทั้ง
?token=...ท้าย URL หรือ headerX-Auth-Token· ไม่ผ่าน = 401 - tray "เปิด Dashboard" ติด token ให้ใน URL อัตโนมัติ · เปลี่ยนค่ามีผลหลังรีสตาร์ท daemon (Ctrl+Alt+K แล้วเริ่มใหม่จาก task)
RESEARCH.md— สรุปการค้นคว้าทั้งหมด: ช่องทางที่ตัน + เหตุผล, การถอด DSDT ทีละคำสั่ง, สถาปัตยกรรม, บั๊ก/บทเรียน, ทางต่อยอดdocs/research.html— ฉบับเว็บ (เปิดในเบราว์เซอร์) ·docs/index.html— คู่มือย่อ
ถอดรหัสจาก acpi_table_0_DSDT.dsl (case 0x67 ของ SCMD, OperationRegion EC81) — คือสิ่งที่ WMBB(0, 0x67, ARGS) ของ ACPI ทำเบื้องหลัง:
Mailbox registers (EC RAM):
| ฟิลด์ | EC RAM | หน้าที่ |
|---|---|---|
| FCMD | 0xF8 | เขียนคำสั่งเพื่อ trigger |
| FDAT | 0xF9 | register id / ข้อมูล |
| FBUF | 0xFA | payload ไบต์ 1 |
| FBF1 | 0xFB | payload ไบต์ 2 |
| FBF2 | 0xFC | payload ไบต์ 3 |
คำสั่งทั้งหมด (ที่โปรแกรมนี้ใช้):
| ฟังก์ชัน | ลำดับที่เขียน |
|---|---|
| เปิดไฟ | FDAT=0x0C, FBUF=0x3F, FCMD=0xC4 |
| ปิดไฟ | FDAT=0x0C, FBUF=0x20, FCMD=0xC4 |
| ความสว่าง | FDAT=0x06, FBUF=63/126/189/252, FBF1=0x00, FBF2=raw, FCMD=0xCA |
| สีโซน 0/1/2 | FDAT=0x03/0x04/0x05, FBUF=BLUE, FBF1=RED, FBF2=GREEN, FCMD=0xCA |
| เอฟเฟกต์ | FDAT=flag, FCMD=0xC4 — 0x07 random, 0x08 dance, 0x09 tempo, 0x0A flash, 0x0B wave |
| Breathe | FDAT=0x03, FBUF=0x2A, FCMD=0xC4 |
| Cycle | FDAT=0x06, FBUF=0x01, FBF1=0x03, FCMD=0xC4 |
| ความเร็ว | FDAT=0x02, FBUF=0xFF−(speed×0x19), FCMD=0xC4 |
ข้อสังเกตสำคัญ: ค่า 0x02–0x0C ใน FDAT เป็น register id ภายในของ mailbox ไม่ใช่ที่อยู่ EC RAM ตรง ๆ (ยืนยันแล้วว่า EC RAM 0x02–0x0C จริงเก็บข้อมูลพัดลม/อุณหภูมิ) และหลัง EC ประมวลผลเสร็จ FCMD จะถูกเคลียร์กลับเป็น 0x00 เอง — ใช้เป็นสัญญาณว่าคำสั่งถูกรับ
การเข้าถึง EC RAM: โปรโตคอล ITE มาตรฐานผ่านพอร์ต 0x66 (คำสั่ง) / 0x62 (ข้อมูล): อ่าน = cmd 0x80+addr, เขียน = cmd 0x81+addr+value — พร้อมเช็ก IBF/OBF ทุกครั้ง และ hardening 3 ชั้น: (1) cross-process mutex Global\\ClevoBacklightEC ครอบทุกธุรกรรม mailbox — GUI/daemon/CLI รันพร้อมกันไม่มีคำสั่งสอดแทรกกลาง mailbox ได้ (2) retry ×3 พร้อม backoff เมื่อ EC ตอบช้า/timeout (3) drain OBF ทิ้งไบต์ค้างก่อนทุกธุรกรรม กัน timeout เก่าพิษภัยคำสั่งใหม่
รวมทุกอย่างเป็นไฟล์เดียว (GUI + daemon + CLI + music + ไดรเวอร์ในตัว) ด้วย PyInstaller:
ดับเบิลคลิก Build-Exe.bat → ได้ dist\ClevoBacklight.exe
หรือเอง: python -m PyInstaller --noconfirm --clean ClevoBacklight.spec
การใช้ exe (ยังต้อง admin เหมือนเดิม):
ClevoBacklight.exe → เปิด GUI
ClevoBacklight.exe --daemon → รัน daemon + tray (ใช้ใน scheduled task)
ClevoBacklight.exe --daemon --restore-only → apply ค่าที่เซฟครั้งเดียวแล้วจบ
ClevoBacklight.exe --on --color FF0080 --brightness 3 → CLI
ClevoBacklight.exe --music --sensitivity 1.2 → music mode
ClevoBacklight.exe --profile night → apply โปรไฟล์
ClevoBacklight.exe --ambient --mix 0.5 → ambient mode
ClevoBacklight.exe --smoke-test → ทดสอบทุกปุ่ม GUI กับ EC จริง
settings.json/daemon.logจะอยู่ข้าง ๆ ตัว exe (ไม่ใช่ temp dir ของ onefile)- ไดรเวอร์
WinRing0x64.sysฝังใน exe แล้ว — แจกทั้งโฟลเดอร์ dist ไปเครื่อง Clevo N9x รุ่นเดียวกันได้เลย - หลัง build ใหม่
Clevo-Backlight-GUI.batและInstall-Autostart.batจะหยิบ exe ใช้เองโดยอัตโนมัติ - ตรวจว่า build สมบูรณ์:
ClevoBacklight.exe --selftestจะเขียนselftest_ok.txt(ต้องมีsoundcard=True) - ซ้อมห่วงโซ่อัปเดตทั้งสาย (ไม่แตะค่าจริง):
ClevoBacklight.exe --update-selftest— พิมพ์ผลรายขั้น + exit 0/1 ใช้ได้ทั้งบน exe และ source · CI รันอัตโนมัติทุก build
| ไฟล์ | หน้าที่ |
|---|---|
clevo_ec.py |
แกนหลัก: WinRing0 loader + EC I/O + mailbox protocol + CLI (--music รวมอยู่) |
clevo_backlight_gui.py |
GUI (tkinter): ทุกฟีเจอร์ + music mode + บันทึก settings + resume hook + hotkey editor |
clevo_music.py |
Music-reactive engine: WASAPI loopback + FFT + MusicRenderer (CLI แยกได้) |
clevo_ambient.py |
Ambient engine: DirectX screen capture → 3 แถบสี → zones (CLI แยกได้) |
clevo_temp.py |
Temperature engine: อ่านอุณหภูมิ EC RAM (CPU 0x07 / GPU 0x08) → gradient สี + alarm blink |
clevo_daemon.py |
Daemon เบื้องหลัง: restore boot/sleep/hotplug + hotkeys + tray |
config.py |
settings.json (default/validate/save) + hotkey parser + app_base() (รองรับ frozen exe) |
hotkeys.py |
Global hotkey ผ่าน RegisterHotKey (เธรดเดียว ปลอดภัย) |
launcher.py |
Entry point เดียวของ exe — route ไป GUI/daemon/CLI/music |
ClevoBacklight.spec / Build-Exe.bat |
สูตร build PyInstaller + สคริปต์ build |
Clevo-Backlight-GUI.bat |
Launcher คลิกเดียว (self-elevate + เปิด GUI ไร้หน้าต่าง console) |
Install-Autostart.bat |
ติดตั้ง Scheduled Task + เริ่ม daemon (ใช้ exe ถ้ามี) |
Remove-Autostart.bat |
ถอน task + หยุด daemon |
settings.json |
การตั้งค่าปัจจุบัน (สร้างอัตโนมัติ) |
daemon.log |
Log เหตุการณ์ของ daemon |
CHANGELOG.md |
ประวัติการเปลี่ยนแปลงทุกเวอร์ชัน |
release.bat |
แพ็ก dist เป็น zip พร้อม README + CHANGELOG (ตั้งชื่อเวอร์ชันได้) |
test_clevo_ec_offline.py |
ทดสอบโปรโตคอลแบบ offline (mock EC, ไม่ต้อง admin) |
test_clevo_music.py |
ทดสอบ music engine offline (mock EC + สัญญาณสังเคราะห์) |
test_clevo_ambient.py |
ทดสอบ ambient engine offline (mock EC + จอสังเคราะห์) |
test_clevo_temp.py |
ทดสอบ temp engine offline (mapping สี/ความสว่าง + alarm blink + run loop) |
ec_probe_monitor_temp.py |
ยิงสัญญาณ resume/displaychange เข้าหน้าต่าง daemon + สำรวจแหล่งอุณหภูมิ (ต้อง admin) |
docs/index.html |
เว็บเอกสาร: คู่มือฉบับย่อ + ผัง GUI จำลอง + สถานะการทดสอบ (เปิดในเบราว์เซอร์) |
ec_music_test.py |
ทดสอบจริงบนฮาร์ดแวร์: เล่นเสียงสังเคราะห์ → วัด band, ambient จับจอจริง (ต้อง admin) |
test_all.bat |
รันตรวจทุกอย่างในคำสั่งเดียว (compile + audit + offline tests) — ใช้ก่อน build exe ทุกครั้ง |
audit_self_attrs.py |
ตัวตรวจ AST: หา self.x ที่อ้างถึงแต่ไม่มีในคลาส (จับ AttributeError ก่อนรัน) — รัน python audit_self_attrs.py ต้องขึ้น CLEAN |
gui_smoke_test.log |
ผลการรัน clevo_backlight_gui.py --smoke-test (ทดสอบทุกปุ่ม GUI กับ EC จริง, ต้อง admin) |
ec_calib_test.py / ec_mode_test.py |
ทดสอบบนฮาร์ดแวร์ (ต้อง admin) — สี/ความสว่าง + โหมดเอฟเฟกต์ 7 โหมด |
ec_read_test.py / ec_write_test.py / ec_power_test.py |
สคริปต์ทดสอบยุคก่อน (เก็บไว้อ้างอิง) |
tools/WinRing0x64.sys |
ไดรเวอร์ (ลงนาม v1.2.0.5) — โหลดอัตโนมัติเป็น service WinRing0_1_2_0 |
acpi_table_0_DSDT.dsl |
DSDT ของเครื่อง (แหล่งอ้างอิงโปรโตคอล) |
analysis/ |
สคริปต์วิเคราะห์ที่ใช้ระหว่างถอดรหัส (probe/disasm ฯลฯ) |
bios_extract/, tools/iasl.exe |
ของจากกระบวนการถอดรหัส BIOS (ลบทิ้งได้ถ้าไม่ต้องการ) |
- ✅ โหลด WinRing0 + อ่าน EC RAM ได้ทุกตำแหน่ง
- ✅ คำสั่งเขียนถูก EC รับทุกครั้ง (FCMD เคลียร์กลับ 0x00 หลังประมวลผล = mailbox มีชีวิต)
- ✅ สีรายโซน: เห็นแดง → เขียว → น้ำเงิน ชัดเจนทั้ง 3 สี (
ec_calib_test.py) - ✅ ความสว่าง: ไล่จางลงครบทั้ง 4 ระดับ (252/189/126/63)
- ✅ เปิด/ปิด + ขาวสว่างสุด: ยืนยันด้วยตา
- ✅ Offline tests ผ่านทั้งหมด (โปรโตคอล mailbox ตรง DSDT + music engine แยกแถบถูก band)
- ✅ exe build สำเร็จ + selftest ผ่าน (import ครบ, ไดรเวอร์ฝังครบ)
- ✅ โหมดเอฟเฟกต์ทั้ง 7: คำสั่งถูก EC รับหมดไม่มี error (
ec_mode_test.log) — การเคลื่อนไหวของแต่ละโหมดเป็นฝั่งเฟิร์มแวร์ ทดสอบด้วยตาได้:ec_mode_test.py(admin, ~90 วิ) - ✅ Music mode จริง end-to-end (
ec_music_test.py): เล่นโน้ตสังเคราะห์ออกลำโพงจริง → loopback แยกโซนถูกต้อง (100 Hz → BASS dominant 0.14/0.004/0.001, 3 kHz → TREBLE dominant) + เขียน EC 507 ครั้งระหว่างโน้ต - ✅ Ambient mode บนเครื่องจริง: จับสีหน้าจอจริงรายแถบ (ค่าสีจริงถูกบันทึกใน log) เขียน EC 705 ครั้งใน 6 วิ เริ่ม/หยุดสะอาด
- ✅ Monitor resume/hotplug ยืนยันจริง: ยิง
WM_POWERBROADCAST/WM_DISPLAYCHANGEเข้าหน้าต่าง daemon → daemon.log บันทัดresume -> re-apply→applied settings (resume)(+displaychange) - ✅ แหล่งอุณหภูมิยืนยันข้ามแหล่ง: EC RAM 0x07 = 45 == Windows ACPI thermal zone 45.1°C → CPU; 0x08 = GPU; smoke test อ่านจริงได้ 51°C
- ✅ GUI smoke test 58 ขั้น: PASS 0 failures (ครบทุกปุ่ม + temp + battery + profile management)
เปิด GUI/CLI แล้วขึ้น "Cannot access the EC" / OpenSCManager failed
→ ยังไม่ได้รันแบบ admin — ใช้ Clevo-Backlight-GUI.bat ซึ่งขอสิทธิ์เอง
กดปุ่มแล้วไฟไม่เปลี่ยน แต่สถานะขึ้น ok → ไฟอาจอยู่สถานะ "ปิด" จากรอบก่อน — กด Power ON ก่อน (โปรแกรมเปิดให้เองใน GUI แล้วกรณีเปลี่ยนสี/preset)
music mode ขึ้น "no loopback device found"
→ อุปกรณ์ default output ไม่มี loopback — รัน python clevo_music.py --list-devices ดูชื่อจริงแล้วระบุ --device <ชื่อย่อย>; เสียงผ่าน HDMI/USB DAC ต้องเลือกอุปกรณ์นั้นชัด ๆ
music mode ไฟกระพริบเกิน/แทบไม่ขยับ
→ ปรับ Sensitivity ใน GUI แบบสด (ลด 0.6–0.8 สำหรับเพลงดัง, เพิ่ม 1.5+ สำหรับเสียงเบา) หรือเพิ่ม --floor ให้ไฟไม่จมดำ
ambient mode ขึ้น "screen capture unavailable"
→ ติดตั้ง mss: pip install mss (Pillow ใช้แทนได้แต่ช้ากว่า); ตอนนี้จับเฉพาะจอหลัก
ดู Netflix/วิดีโอ DRM แล้ว ambient ไฟดับหมด → เฟรมพวกนี้ถูกป้องกันการจับระดับระบบ — เป็นข้อจำกัด ไม่ใช่บั๊ก
temp mode ไฟเป็นสีเดียวตลอด
→ ปกติถ้าโหลดไม่แปรปัน — ลองเปิดเกม/ยูเทสแหน่งให้ temp ขยับ แล้วดูสีไล่; เช็กค่าจริงด้วย python clevo_ec.py --read (0x07=CPU, 0x08=GPU)
เสียบ/ถอดปลั๊กแล้วไฟไม่เปลี่ยนตาม battery saver
→ daemon ต้องรันอยู่ (task ClevoBacklightDaemon) และเปิด checkbox "เปิดใช้งาน" ในแผง Battery saver แล้ว — ดูเหตุการณ์ที่ dist\daemon.log (power source -> battery)
ไฟกลับค่าหลัง sleep
→ daemon จัดการให้แล้วถ้าติดตั้ง autostart แล้ว — ไม่งั้นรัน python clevo_ec.py --apply-saved เองหลังตื่น (หรือเปิด GUI ทิ้งไว้เลย มันคืนค่าเอง)
ลืมว่าตั้ง hotkey อะไรไว้
→ เปิด settings.json ดู หรือกด Ctrl+Alt+K ถ้าอยากปิด daemon ทันที (ปุ่มนี้แก้ไม่ได้ by design)
daemon.log โต → ลบทิ้งได้ปลอดภัย มันสร้างใหม่ให้เอง
ไฟไม่กลับหลัง reboot แม้ติดตั้ง autostart แล้ว
→ เช็ค task: schtasks /Query /TN ClevoBacklightDaemon — ถ้าหายให้รัน Install-Autostart.bat ใหม่; ดูเหตุการณ์จริงที่ dist\daemon.log (log อยู่ข้าง ๆ ตัว exe)
รัน GUI/CLI ตอน daemon กำลังรัน → ทำงานร่วมกันได้ปลอดภัย — ทุกธุรกรรม EC ถูก cross-process mutex คุม (จำนวนครั้งเขียนเยอะเมื่อ daemon ทำ automation ก็ปกติ)
อยาก reset ทุกอย่างเป็นค่าโรงงาน → ลบ settings.json (ระบบสร้าง default ให้ใหม่: เขียว #00FF88 สว่างสุด, hotkey เดิม)
.exe กดแล้วไม่มีอะไรเกิดขึ้น
→ รันจาก terminal เพื่อดู error จริง หรือเช็ค selftest_ok.txt หลังรัน --selftest; onefile เปิดครั้งแรกช้า 2–4 วิเพราะคลายไฟล์ temp ตามปกติ
ก่อน build exe ทุกครั้ง
→ ดับเบิลคลิก test_all.bat — ตรวจ compile + AST audit + offline tests ในรอบเดียว (exit code 0 = build ได้)
อยากยืนยันว่า GUI ทุกปุ่มยังทำงานกับ EC จริง
→ รัน python clevo_backlight_gui.py --smoke-test (admin) — ทดสอบ power/ความสว่าง/โหมด/พาเลต/สีรายโซน/music แล้วคืนค่าเดิม ดูผลที่ gui_smoke_test.log
- การเขียน EC ผิดตำแหน่งอาจกระทบฟังก์ชันอื่น (พัดลม, ปุ่ม Fn, พลังงาน) — โปรแกรมนี้เขียนเฉพาะ mailbox ของ LED เท่านั้น และตรวจสอบลำดับ IBF/OBF ทุกธุรกรรม
- WinRing0 เปิด port I/O เต็มรูปแบบแก่ผู้ที่เรียกใช้ — เป็นที่รู้กันว่าถูก abuse โดยมัลแวร์บ้าง จึงควร: ไม่ติดตั้ง service แบบ boot-start (โปรแกรมนี้ใช้ demand-start เท่านั้น), ถอนติดตั้งด้วย
Remove-Autostart.batเมื่อไม่ใช้, ไม่ copy ไปเครื่องที่ไม่เชื่อถือ - Music mode อ่านเฉพาะเสียง output ของระบบเท่านั้น (loopback) — ไม่มีการอัดไมโครโฟน ไม่มีการบันทึก/ส่งเสียงไปไหน
- ตัว daemon มีปุ่มฉุกเฉิน
Ctrl+Alt+Kปิดทันทีเสมอ - โค้ดทั้งหมดอ่านได้ ไม่มี network call, ไม่มี telemetry, ไม่มี auto-update
