根据日出和日落自动调整显示亮度

Ask Ubuntu中有类似的问题和答案指出这些解决方案:

  • f.lux®软件让您的生活更美好
  • Redshift根据您周围的环境调整屏幕的色温。
  • GNOME的新夜灯function旨在帮助您更好地睡眠
  • 根据白天设置初始启动背景亮度

但他们要么需要手动输入日出和日落时间,要么只调整颜色平衡并在晚上添加更多红色。

我正在寻找一种解决方案,每天自动获取日出和日落时间,并物理调整显示亮度。 此外,我想要一个60到120分钟的过渡效果,所以我没有注意到显示的变化。

在阴天重新配置(外面调光)或当太阳发生在两层三层建筑物而不是屋顶(日落前更亮)之间时,应该是一个快速简单的过程。

介绍

这是一个bash解决方案,无需安装其他程序。 它需要一个互联网连接(如果你正在阅读这个,你有一个),以自动获得每天的日出和日落时间。 它提供了用户友好的配置屏幕。 它使用cron自动启动,无需用户交互。

这个答案分为多个部分

  • 使用cron每天自动获取日出和日落时间
  • 配置亮度设置和转换时间
  • 主要脚本根据时间调整亮度
  • 使用cron每次启动时自动启动display-auto-brightness
  • 从暂停状态恢复即时/透明亮度调整
  • 摘要

使用cron每天自动获取日出和日落时间

有许多网站可以报告您所在位置的日出和日落时间。 此脚本使用( https://www.timeanddate.com/ ),这是一个众所周知的网站很长一段时间。

使用sudo powers编辑文件/usr/local/bin/sun-hours并粘贴:

 #!/bin/bash # Called daily from /etc/cron.daily/sun-hours while true; do ### "-q"= quiet, "-O-" pipe output echo $(wget -q -O- https://www.timeanddate.com/sun/canada/edmonton | grep -oE 'Sunrise Today.{35}' | awk -F\> '{print $3}' | tr --delete "<") > /tmp/sunrise echo $(wget -q -O- https://www.timeanddate.com/sun/canada/edmonton | grep -oE 'Sunset Today.{35}' | awk -F\> '{print $3}' | tr --delete "<") > /tmp/sunset ## If network is down files will have one byte size size1=$(wc -c < /tmp/sunrise) size2=$(wc -c < /tmp/sunset) if [ $size1 -gt 1 ] && [ $size2 -gt 1 ] ; then cp /tmp/sunrise /usr/local/bin/sunrise cp /tmp/sunset /usr/local/bin/sunset chmod 666 /usr/local/bin/sunrise chmod 666 /usr/local/bin/sunset rm /tmp/sunrise rm /tmp/sunset exit 0 else logger "/etc/cron.daily/sun-hours: Network is down. Waiting 5 minutes to try again." sleep 300 fi done 

在保存脚本之前,将两次出现的/canada/edmonton替换为您自己的国家/canada/edmonton地区和城市。 访问网站www.timeanddate.com获取确切的姓名或号码。 例如,“巴黎,美国”有几十个名字,因此它们将包含一个数字,例如/worldclock/@5205082用于“巴黎,美国宾夕法尼亚州”。

使用cron每天运行sun-hours脚本

使用sudo powers编辑文件/etc/cron.daily/sun-hours并粘贴:

 #!/bin/sh # # Each day /etc/cron.daily/sun-hours will get sunrise and sunset times. sleep 60 # give time for network to come up. /usr/local/bin/sun-hours 

使用sudo chmod a+x ___/sun-hours将这两个文件标记为可执行文件,其中“___”是每个文件的目录。

使用Conky每天监控日出/日落时间的变化

Conky是一种用于监控系统的流行工具。 以下是显示日出,日落和亮度设置的命令:

 ${color orange}${voffset 2}${hr 1} ${color}${goto 5}Day: ${color green}${execpi 300 cat /usr/local/bin/sunrise} ${color}Night: ${color green}${execpi 300 cat /usr/local/bin/sunset} ${color}Level: ${color green}${execpi 10 cat cat /sys/class/backlight/intel_backlight/brightness} ${color orange}${voffset 2}${hr 1} 

这就是它的样子:

显示 - 自动亮度

注意:此Conky代码使用intel_backlight ,您需要根据显示适配器进行更改,如下面的部分所述。

配置亮度设置和转换时间

您不希望显示器在日出时变为全亮度,在日落时变为完全昏暗。 需要一个过渡期。 另外,需要一个配置文件来记录全亮度和完全暗淡的变量。 这是配置屏幕:

显示自动亮度配置

屏幕使用标准zenity命令构建,因此现有值显示在带有“(value)”标签的标签中,如果需要,您可以键入新值。 否则,当新值为空时,将保留现有文件。

如果不同,请将intel_backlight替换为显示驱动程序。 要找出你的名字,请使用: ls /sys/class/backlight/*/brightness

使用sudo powers创建文件/usr/local/bin/auto-brightness-config并粘贴以下代码:

 #!/bin/bash # Read hidden configuration file with entries separated by " " into array IFS=' ' read -ra CfgArr < /usr/local/bin/.auto-brightness-config # Zenity form with current values in entry label # because initializing multiple entry data fields not supported output=$(zenity --forms --title="Display Auto Brightness Configuration" \ --text="Enter new settings or leave entries blank to keep (existing) settings" \ --add-entry="/sys/class/backlight/??????/brightness driver : (${CfgArr[0]})" \ --add-entry="Day time maximum display brightness : (${CfgArr[1]})" \ --add-entry="Transition minutes after sunrise to maximum : (${CfgArr[2]})" \ --add-entry="Night time minimum display brightness : (${CfgArr[3]})" \ --add-entry="Transition minutes before sunset to minimum : (${CfgArr[4]})") IFS='|' read -a ZenArr <<<$output # Split zenity entries separated by "|" into array elements # Update non-blank zenity array entries into configuration array for i in ${!ZenArr[@]}; do if [[ ${ZenArr[i]} != "" ]]; then CfgArr[i]=${ZenArr[i]} ; fi done # write hidden configuration file using array (fields automatically separated by " ") echo "${CfgArr[@]}" > /usr/local/bin/.auto-brightness-config 

使用以下方法将文件标记为可执

 chmod a+x /usr/local/bin/auto-brightness-config 

主程序display-auto-brightness

使用sudo powers创建文件/usr/local/bin/display-auto-brightness并粘贴以下代码:

 #!/bin/bash # NAME: display-auto-brightness # PATH: /usr/local/bin # DESC: Set display brightness based on min/max values, sun rise/set time # and transition minutes. # CALL: Called from cron on system startup with @reboot option. # DATE: Feb 17, 2017. Modified: Dec 2, 2017. # NOTE: Only sleep for 1 minute to make display brightness changes gradual. # Configuration file can change any time so variables reread when waking. # The file is maintained by /usr/local/bin/auto-brightness-config script. # Sunrise and sunset time obtained from www.dateandtime.com using # /usr/local/bin/sun-hours script. The script is called from cron using # /etc/cron.daily/cron-daily-sun-hours. Variables stored in am/pm format # in /usr/local/bin/sunrise and /usr/local/bin/sunset. # When suspending at 6 am it might be dark with setting at 300. When # resuming at 4:30pm it might be full sun and setting needs to be 2000. # It will take between 1 and 59 seconds to adjust screen brightness with # sudden jump in brightness. To correct this create kill sleep command # during suspend with /lib/systemd/system-sleep/display-auto-brightness # script. # TODO: Add support for external monitors connected via HDMI / DisplayPort. # xrandr --output HDMI-0 --brightness .799 # xrandr --output DP-1-1 --brightness 1.15 if [[ $(id -u) != 0 ]]; then # root powers needed to call this script echo display-auto-brightness must be called with sudo powers exit 1 fi # global variable LastSetting="" function set-and-sleep { if [[ "$1" != "$LastSetting" ]]; then sudo sh -c "echo $1 | sudo tee $backlight" echo "$1" > "/tmp/display-current-brightness" LastSetting="$1" fi sleep 60 } re='^[0-9]+$' # regex for valid numbers function calc-level-and-sleep { # Parms $1 = number of minutes for total transition # $2 = number of seconds into transition secTotal=$(( $1 * 60 )) # Convert total transition minutes to seconds Adjust=$( bc <<< "scale=6; $transition_spread * ( $2 / $secTotal )" ) Adjust=$( echo $Adjust | cut -f1 -d"." ) # Truncate number to integer if ! [[ $Adjust =~ $re ]] ; then Adjust=0 # When we get to last minute $Adjust can be non-numeric fi calc_bright=$(( $min_bright + $Adjust )) set-and-sleep "$calc_bright" } while true ; do # Although variables change once a day it could be weeks between reboots. sunrise=$(cat /usr/local/bin/sunrise) sunset=$(cat /usr/local/bin/sunset) # Read hidden configuration file with entries separated by " " into array IFS=' ' read -ra CfgArr < /usr/local/bin/.auto-brightness-config backlight="/sys/class/backlight/${CfgArr[0]}/brightness" max_bright="${CfgArr[1]}" after_sunrise="${CfgArr[2]}" min_bright="${CfgArr[3]}" before_sunset="${CfgArr[4]}" # Current seconds secNow=$(date +"%s") secSunrise=$(date --date="$sunrise today" +%s) secSunset=$(date --date="$sunset today" +%s) # Is it night time? if [ "$secNow" -gt "$secSunset" ] || [ "$secNow" -lt "$secSunrise" ]; then # MINIMUN: after sunset or before sunrise nightime setting set-and-sleep "$min_bright" continue fi # We're somewhere between sunrise and sunset secMaxCutoff=$(( $secSunrise + ( $after_sunrise * 60 ) )) secMinStart=$(( $secSunset - ( $before_sunset * 60 ) )) # Is it full bright day time? if [ "$secNow" -gt "$secMaxCutoff" ] && [ "$secNow" -lt "$secMinStart" ]; then # MAXIMUN: after sunrise transition AND before nightime transition set-and-sleep "$max_bright" continue fi # Daytime - nightime = transition brightness levels transition_spread=$(( $max_bright - $min_bright )) # Are we between sunrise and full brightness? if [ "$secNow" -gt "$secSunrise" ] && [ "$secNow" -lt "$secMaxCutoff" ]; then # Current time - Sunrise = progress through transition secPast=$(( $secNow - $secSunrise )) calc-level-and-sleep $after_sunrise $secPast continue fi # Are we between beginning to dim and sunset (full dim)? if [ "$secNow" -gt "$secMinStart" ] && [ "$secNow" -lt "$secSunset" ]; then # Sunset - Current time = progress through transition secBefore=$(( $secSunset - $secNow )) calc-level-and-sleep $before_sunset $secBefore continue fi # At this stage brightness was set with manual override outside this program # or exactly at a testpoint, then it will change next minute so no big deal. sleep 60 # reset brightness once / minute. done # End of forever loop 

使用以下方法将文件标记为可执

 chmod a+x /usr/local/bin/display-auto-brightness 

注意: 2017年8月26日未成功修订,以纠正当最后一个亮度等级等于最小亮度或最大亮度并且当前分钟的调整值为空(零)时程序将停止的错误。 2017年12月2日成功修复,但直到2018年2月17日才发布。哎呀!

使用cron每次启动时自动启动display-auto-brightness

Cron用于每次启动时启动主应用程序。 使用sudo权限创建文件/etc/cron.d/display-auto-brightness并复制到:

 SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin @reboot root /usr/local/bin/display-auto-brightness 

从暂停状态恢复即时亮度调整

您可以在太阳升起之前的早上6点暂停您的计算机,并且您的设置为300.您可以在太阳明亮时下午4点恢复计算机,设置应为2000但是您必须等待1到59秒才能display-auto-brightness重置显示。 当显示器重置时,变化是戏剧性的。 要解决此问题,需要使用systemd脚本。 创建包含以下内容的文件/lib/systemd/system-sleep/display-auto-brightness

 #!/bin/sh # NAME: display-auto-brightness # PATH: /lib/systemd/system-sleep/ # DESC: Restart display brightness when resuming from suspend # CALL: Automatically called when system goes to sleep and wakes up # DATE: August 2017. Modified: June 10, 2018. # NOTE: Gives instant display brightness adjustment instead of waiting 1 to 59 seconds. logger -t "logger -t "test" "\$0=$0, \$1=$1, \$2=$2" test" "\$0=$0, \$1=$1, \$2=$2" case $1/$2 in pre/*) echo "/lib/systemd/system-sleep/display-auto-brightness: Going to $2..." ;; post/*) # March 28, 2018 On AW17R3 this script runs too fast sleep 2 echo "/lib/systemd/system-sleep/display-auto-brightness: Resuming from $2..." # Find running tree processes containing "display-auto" AND "sleep" ProgramTree=$(pstree -g -p | grep display-auto | grep sleep) # echo's below will print in /var/log/syslog. Comment out with # to suppress echo "pstree -g -p | grep display-auto | grep sleep" echo "=============================================" echo "$ProgramTree" # extract sleep program ID within `pstree`. eg we would want "16621" below: # |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(16621,1308) pID=$(echo "$ProgramTree" | cut -f 6 -d '(' ) pID=$(echo "$pID" | cut -f1 -d",") kill $pID # kill sleep command forcing screen brightness to adjust immediately rm /tmp/display-current-brightness echo "display-auto-brightness: sleep pID: '$pID' has been killed." ;; esac 

使用以下方法将文件标记为可执

 chmod a+x /lib/systemd/system-sleep/display-auto-brightness 

摘要

显示当前亮度级别是系统托盘

除了前面介绍的Conky示例之外, 指示符-sysmonitor还可以通过bash在系统托盘中显示当前亮度:

显示自动亮度系统

在该系统布局示例中,亮度设置为418并且在日落之前约为20分钟。 在日落时,该值将为250,白天全亮度为1200.在此机器上,intel_backlight = 4882是可能的,但是,如果您在室内窗帘打开,屏幕就像盯着太阳。

使用以下代码设置系统托盘指示器:

 #!/bin/bash if [ -f ~/.lock-screen-timer-remaining ]; then text-spinner Spinner=$(cat ~/.last-text-spinner) # read last text spinner used Minutes=$(cat ~/.lock-screen-timer-remaining) systray=" $Spinner Lock screen in: $Minutes" else systray=" Lock screen: OFF" fi if [ -f /tmp/display-current-brightness ]; then Brightness=$(cat /tmp/display-current-brightness) systray="$systray Brightness: $Brightness" else systray="$systray Brightness: OFF" fi echo "$systray" # sysmon-indidicator will put echo string into systray for us. exit 0 

此问答( 可以在系统托盘中显示BASH作为应用程序指示器吗? )描述如何设置指示器 - 系统监视器。

未来的改进

  • 将此答案的bash脚本迁移到github
  • 使用xrandr添加对外部监视器的支持
  • 使用xrandr添加对更多红色/更少蓝色的支持

我刚刚编写了一个程序,它几乎可以满足您的需求。 它会根据网络摄像头拍摄的图像改变屏幕亮度,以获得周围的亮度。 您可以自己选择检测亮度和调光速度的间隔。

https://github.com/Wandersalamander/Dimmer