Night light mode for monitors

Recently I switched from Ubuntu 16.04 to Fedora 28 on my desktop PC. After the installation, I noticed that newer version of GNOME has added a night light feature which is the same as night shift on macOS and iOS and the f.lux software. The feature is great. However, it can only adjust the color temperature of the video output and the monitor’s brightness stays constant. As I work besides a big window, I need higher brightness during the day and lower brightness at night. Therefore, I decided to add a “night light” mode for my monitors as well.

DDC/CI

According to Wikipedia,

The Display Data Channel, or DDC, is a collection of protocols for digital communication between a computer display and a graphics adapter that enable the display to communicate its supported display modes to the adapter and that enable the computer host to adjust monitor parameters, such as brightness and contrast.

DDC/CI (Command Interface) standard was introduced in August 1998. It specifies a means for a computer to send commands to the monitor, as well as receive sensor data from the monitor, over a bidirectional link.

In a nutshell, this DDC/CI feature allows you to control the monitor with programs. On both of my Dell monitors (U2312HM and U2417H), it is supported. I believe many other modern monitors support this feature as well.

On my Fedora machine, I installed the ddccontrol program to communicate with the monitors using the command line. First, let’s install and check if any monitors are equipped with DDC/CI.

$ sudo dnf install ddccontrol
$ sudo ddccontrol -p # probe for supported monitors

The above command should tell you which monitor (the path should be /dev/i2c-*) is found. Once you get the path for your monitor, the brightness of the monitor can easily be read and adjusted.

$ sudo ddccontrol -r 0x10 dev:/dev/i2c-4 # check brightness of /dev/i2c-4
$ sudo ddccontrol -r 0x10 -w 50 dev:/dev/i2c-4 # set brightness of /dev/i2c-4 to 50

Run the above commands to test if this actually works for your monitor.

“Night light” mode

Now that the brightness can be adjusted with programs, the next step is to automate the whole process so that the brightness is adjusted according to the current time. Below is a script I wrote to set my two monitors’ brightness to 40 between 7:00 AM and 7:10 PM, and to 10 otherwise.

#!/bin/bash

SUNRISE=0700
SUNSET=1910
DAY_BRIGHTNESS=40
NIGHT_BRIGHTNESS=10

CURRENT_TIME=$(date +"%H%M")
echo $CURRENT_TIME

change_brightness () {
	for monitor in i2c-4 i2c-6; do
		CURRENT_BRIGHTNESS=$(ddccontrol -r 0x10 dev:/dev/$monitor | grep -Po "[0-9]+(?=/100)")
		echo Current monitor brightness is $CURRENT_BRIGHTNESS
		if [ "$CURRENT_BRIGHTNESS" -ne "$1" ]; then
			echo Setting monitor $monitor to $1 brightness
			ddccontrol -r 0x10 -w $1 dev:/dev/$monitor
		fi
	done
}

# during the day
if [ "$CURRENT_TIME" -gt "$SUNRISE" ] && [ "$CURRENT_TIME" -lt "$SUNSET" ]; then
	echo It is during day time.
	change_brightness $DAY_BRIGHTNESS
# at night
else
	echo It is during night time.
	change_brightness $NIGHT_BRIGHTNESS
fi

Add this script as a cron job by adding the following line to the end of the /etc/crontab file.

*/10 * * * * root /path/to/the/script.sh

This line tells cron to run this script as root every 10 minutes. If the current brightness doesn’t match with the pre-defined brightness for the current time interval, the script will adjust the brightness accordingly.

Conclusion

In conclusion, the DDC/CI feature allows us to easily adjust monitor settings with automated scripts instead of manually adjusting it by pressing buttons, which I used to do. The script I provided can be customized to any definition of day and night (depending on your location) and you can modify the crontab line to run the script more/less frequently. The DDC/CI standard also support a lot more than just adjusting brightness and contrast. Maybe you will find it useful for other settings as well.

 
comments powered by Disqus