Hammerspoon 自动化:Mac 和 Windows 主机高效切换显示器输入源

DDC/IC指令自动化切换DELL显示器输入源

ROG_Strix_Scope_II_96_Wireless

MacBook 和 Win 主机共享一套键鼠和显示器,因为显示器不带 KVM 切换功能,键鼠是通过外接 USB 切换器进行切换。显示器通过 USB-C 和 Mac 连接,通过 DP 和 PC 连接。

这样切换键鼠很方便,我只要按一下线控开关就在物理上实现了 USB 键鼠上行的切换。但是这个方案有个痛点,按下线控开关切换键鼠 USB 上行的同时,无法做到显示器输入源的切换。

大致拓扑如下

Keyboard_Mouse_and_Display_Topology

因为 DELL U2720Q 上带有 USB 3.0 HUB ,所以拓扑上 USB 切换器连接 Mac 的上行是接在显示器上,这样显示器和 MacBook 只需要一根 USB-C 线连接就可以实现外接显示、键鼠控制、充电、有线网卡等功能。

DDC/CI 协议切换输入源

m1ddc 这个项目可以实现M系列芯片的 Mac 通过 DDC/CI 协议发送指令控制显示器的输入源切换,以我的 DELL U2720Q 为列。

将输入源切换至 USB-C

1
m1ddc set input 27

将输入源切换至 DP

1
m1ddc set input 15

检测 USB 设备连接状态控制输入源切换

前面也提到现在的痛点,按下线控开关切换键鼠 USB 上行的同时,无法做到显示器的切换。为了解决这个“最后一公里”的问题,我的构想是在 Mac 上检测 USB 设备连接状态的变化来实现显示器输入源切换的控制。如果某个 USB 设备连接或断开了则运行某项指令。

Hammerspoon 可以实现我上述的想法,它桥接操作系统与 Lua 脚本引擎,我们能通过 Lua 脚本高效地与系统 API 沟通。

目录大致结构如下

1
2
3
4
5
.
├── Spoons
├── init.lua
└── modules
    └── usb_script.lua

我们可以在 modules文件夹下创建各种功能性的 Lua 脚本,再到入口 init.lua中导入你需要的功能性脚本。

首先要确定检测的 USB 设备名称,具体信息可以到 macOS 的系统报告中查看。

usbhub_device_manager

下面是我在 modules目录下创建的usb_script.lua 脚本,作用是监听指定 USB 设备连接或断开状态,触发切换显示器输入源。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
usbWatcher = nil
--m1ddc命令
local ChangeMonitorInput2USBC = "/Users/zhxchen/Documents/m1ddc/m1ddc set input 27"
local ChangeMonitorInput2DP = "/Users/zhxchen/Documents/m1ddc/m1ddc set input 15"

function usbDeviceCallback(data)
    if (data["productName"] == "USB 2.0 Hub") then--匹配的设备名
        if (data["eventType"] == "added") then
            hs.execute(ChangeMonitorInput2USBC)
        elseif (data["eventType"] == "removed") then
            hs.execute(ChangeMonitorInput2DP)
        end
    end
end
 
usbWatcher = hs.usb.watcher.new(usbDeviceCallback)
usbWatcher:start()

init.lua文件中插入以下代码

1
require("modules.usb_script")

上述配置都完成以后,记得在 HammerspoonReload Config

最后

在两台不同的操作系统主机切换显示器和键鼠只需要按一次 USB 切换器的线控开关,在解决这个“最后一公里”的过程中接触了开源免费的 Hammerspoon ,真的好用(括弧笑)。