mirror of
https://github.com/jbranchaud/til
synced 2026-07-02 23:58:25 +00:00
Add Read The Lid Angle Sensor For A MacBook as a Mac TIL
This commit is contained in:
@@ -10,7 +10,7 @@ working across different projects via [VisualMode](https://www.visualmode.dev/).
|
||||
|
||||
For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter).
|
||||
|
||||
_1793 TILs and counting..._
|
||||
_1794 TILs and counting..._
|
||||
|
||||
See some of the other learning resources I work on:
|
||||
|
||||
@@ -753,6 +753,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
||||
- [Open Finder.app To Specific Directory](mac/open-finder-app-to-specific-directory.md)
|
||||
- [Prevent Sleep With The Caffeinate Command](mac/prevent-sleep-with-the-caffeinate-command.md)
|
||||
- [Quickly Type En Dashes And Em Dashes](mac/quickly-type-en-dashes-and-em-dashes.md)
|
||||
- [Read The Lid Angle Sensor For A MacBook](mac/read-the-lid-angle-sensor-for-a-macbook.md)
|
||||
- [Require Additional JS Libraries In Postman](mac/require-additional-js-libraries-in-postman.md)
|
||||
- [Resize App Windows With AppleScript](mac/resize-app-windows-with-applescript.md)
|
||||
- [Resizing Both Corners Of A Window](mac/resizing-both-corners-of-a-window.md)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
# Read The Lid Angle Sensor For A MacBook
|
||||
|
||||
MacOS has a bunch of internal HID (Human Interface Device) data that can surface
|
||||
details about all kinds of "devices" that comprise your machine. Some obvious
|
||||
ones are the keyboard and trackpad as well as external mice and keyboards. The
|
||||
battery and power source details are another which is sometimes integrated into
|
||||
tools that display battery status (e.g.
|
||||
[`tmux-battery`](https://github.com/tmux-plugins/tmux-battery)), though it uses
|
||||
`pmset` directly). And many, many more.
|
||||
|
||||
One example I'd never considered is that there is a sensor for the lid angle of
|
||||
the laptop that can tell the system whether the lid is open or closed and how
|
||||
open it is (i.e. at what angle). There is no public interface for this lid angle
|
||||
sensor, but people exploring all the HID devices have found the identifiers that
|
||||
correspond to it (e.g.
|
||||
[`pybooklid`](https://github.com/tcsenpai/pybooklid/blob/main/pybooklid/macbook_lid.py)).
|
||||
|
||||
Here is a minimal script that uses `uv`, `hidapi` (python bindings), and
|
||||
`libhidapi` (shared runtime lib for those bindings):
|
||||
|
||||
```python
|
||||
#!/usr/bin/env -S uv run --quiet --script
|
||||
# /// script
|
||||
# requires-python = ">=3.10"
|
||||
# dependencies = ["hidapi"]
|
||||
# ///
|
||||
"""Print MacBook lid angle in degrees."""
|
||||
import os, sys
|
||||
|
||||
if sys.platform == "darwin":
|
||||
brew = "/opt/homebrew/lib"
|
||||
if os.path.exists(brew):
|
||||
os.environ["DYLD_LIBRARY_PATH"] = f"{brew}:{os.environ.get('DYLD_LIBRARY_PATH','')}"
|
||||
|
||||
import hid
|
||||
|
||||
VENDOR_ID, PRODUCT_ID = 0x05AC, 0x8104
|
||||
USAGE_PAGE, USAGE = 0x0020, 0x008A
|
||||
REPORT_ID = 1
|
||||
|
||||
def read_angle():
|
||||
for info in hid.enumerate(VENDOR_ID, PRODUCT_ID):
|
||||
if info.get("usage_page") == USAGE_PAGE and info.get("usage") == USAGE:
|
||||
d = hid.device()
|
||||
path = info["path"]
|
||||
d.open_path(path if isinstance(path, bytes) else path.encode())
|
||||
try:
|
||||
data = d.get_feature_report(REPORT_ID, 8)
|
||||
if data and len(data) >= 3:
|
||||
return float((data[2] << 8) | data[1])
|
||||
finally:
|
||||
d.close()
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
a = read_angle()
|
||||
if a is None:
|
||||
sys.exit("sensor not available")
|
||||
print(f"{a:.0f}")
|
||||
```
|
||||
|
||||
These IDs and usage values are the undocumented values that allow the script to
|
||||
navigate specifically to the lid angle sensor and specifically to the usage page
|
||||
and value that represent the current lid angle reading.
|
||||
|
||||
```
|
||||
VENDOR_ID, PRODUCT_ID = 0x05AC, 0x8104
|
||||
USAGE_PAGE, USAGE = 0x0020, 0x008A
|
||||
REPORT_ID = 1
|
||||
```
|
||||
|
||||
I added [this
|
||||
script](https://github.com/jbranchaud/dotfiles/blob/cbc7196607d1d6b25885f5387ca85b658bd765de/bin/lidangle)
|
||||
to [my dotfiles](https://github.com/jbranchaud/dotfiles) and made it executable
|
||||
(`chmod +x bin/lidangle`) so that I can try it out. I first ran it while it was
|
||||
closed and connected to my external monitor (`0`), then I opened it as far as it
|
||||
could go (`129`), and then I tried angling it close to what I thought was 90
|
||||
degress (`92`, so close).
|
||||
|
||||
```bash
|
||||
❯ lidangle
|
||||
0
|
||||
|
||||
❯ lidangle
|
||||
129
|
||||
|
||||
❯ lidangle
|
||||
92
|
||||
```
|
||||
Reference in New Issue
Block a user