macOS 在 Sierra 10.12.4 就加的 Night Shift 功能, 对于用惯了 f.lux 的人来说没什么价值, 但当外接显示器两屏幕亮度不同色温调节不便时, 利用终端命令控制 Mac 内置的 Night Shift 开关, 搭配免费的 ControlPlane 情景模式工具, 就能实现多屏色温和亮度大致平衡.

Table of Contents

  1. Problem Statement
  2. Objective
  3. Requirements
  4. Step by Step Workflow
    1. Toggle Night Shift in Terminal
    2. Run Script Automatically When Context Changes

Problem Statement

Mac 笔记本外接显示器时, 对于非果厂自己的显示器(比如我是 AOC), 可能会出现显示器亮度调到最低还是很亮或是色调太冷的情况, 白天还好, 晚上就格外刺眼. 这时候没有办法直接降低亮度, 就只能考虑将屏幕变暖色调, 来减少对眼睛的刺激.

Objective

当检测到显示器时, 自动开启 Night Shift; 断开显示器时, 自动关闭 Night Shift.

Requirements

  • macOS System >= 10.12.4
  • 一个外接显示器

Step by Step Workflow

Toggle Night Shift in Terminal

First and foremost, 就是在终端控制 Night Shift. 但不像 Dock, Menubar 有很多长长的 default blah blah 黑魔法 one-liner, Night Shift 似乎没有自带的命令. 但已经有人写好了脚本, 可以在这里下载.

用法很简单, nshift n, 这里 0 <= n <= 100, 代表 Night Shift 强度, n 越大色温越暖, n = 0 关闭 Night Shift, 其实就对应系统设置里的大小:

由于我们只需要一次设置好开和关两个值就好, 不需要每次都 nshift 加一个数字. 根据个人爱好选择两个值, 分别对应内置显示器和外置显示器, 比如我的是 2 和 50.

写两个脚本 nshift_on.sh , nshift_off.sh:

nshift_on.sh:

1
2
#!/bin/sh
PathTonshift/nshift 50 # Sets strength to 50 to turn on nshift

nshift_off.sh:

1
2
#!/bin/sh
PathTonshift/nshift 2 # Sets strength to 2 to turn off nshift

开启 Allow executing file as program 权限:

1
$ chmod +x PathTonshift_on/nshift_on.sh PathTonshift_off/nshift_off.sh

这样以后我们每次开关 Night Shift 就可以直接在终端进行了:

1
2
$ PathTonshift_on/nshift_on.sh  # Turns on nshift
$ PathTonshift_off/nshift_off.sh # Turns off nshift

Run Script Automatically When Context Changes

已经有了控制 Night shift 的脚本, 再用 Alfred workflow 等工具就可以设置快捷键直接启动了, 但是仍然不够, 我们需要的是根据情景的全自动控制. 这就需要用到 ControlPlane 了. (这个 app 本来是用于调节在公司/星巴克/家等等的情景模式…)

ControlPlane 用伪代码表示 (毕竟看代码比看英语简单):

1
2
3
4
5
6
while ControlPlane is running:
confidence = getConfidence(Rules, Actions)
if confidence >= threshold:
switch Contexts
if defined ContextSwitchingActions:
do ContextSwitchingActions

先设置 General, 不是重点, 主要根据个人喜好,

接下来是 Contexts, 添加一个新的情景就好,

然后是 Evidence Sources, 由于这里只要看外接显示器, 所以只要选上Attached Monitor即可,

对于 Rules, 就选两个显示器分别对应之前设置的两个 Contexts 就行, 注意这里的 Confidence 要大于General中的阈值,

最后, Actions 就是设置两个行为, 来运行之前的两个脚本,

设置完了, 大功告成, 保持 ControlPlane 一直运行就能够实现插拔显示器自动开关 Night Shift 了🤘.