Raymel Francisco

Posted on

# Automating your keyboard's backlit with Bash

You have a keyboard, it backlits at night, but not in day. You save a bit of energy, and your keyboard looks cool at night. Great!

### But... wait a minute.

I'm learning Bash lately, and I guess sharing my learning experience with you will be fruitful on my writing experience as well. Bear with me.

### Going back...

So I used a simple algorithm in making my keyboard a little bit smarter with Bash. Bash's syntax is a bit strange for me, and took me a day before getting used to it. But why Bash when I can do it with a language I'm comfortable with, like Python? Well, exposing yourself to new habits from time to time exercises your brain's neuroplasticity, which is good.

So here's how the backlit's simple algorithm works,

Living near the equator gives us full 12 hours of daylight/darkness everyday.
Therefore I shall conclude, that my keyboard must be cool in between 6pm and 6am, and eco-friendly between 6am and 6pm.

Thus, giving us this logic flow:

Time of day Switch backlit to When to switch backlit again?
6am to 5:59pm OFF Next 6 hours
6pm to 5:59am ON Next 6 hours

Okay then, so how do we compute the next 6 hours?

We need to use military time, in order to simplify things. Calculating up to 24th hour is easier to do. But since time is presented in 12hr format in my computer, I adjusted my formulas...

Time of day Next backlit switch Formula to next backlit switch (where h is the time of day)
6am to 5:59pm 6pm 18 - h
6pm to 11:59pm 6am (12 - h) + 6
12am to 6am 6am 6 - h

But wait, why those formulas?

Because 6pm is the 18th hour of day. The second formula is the same as the first, I just put it into the context of time resetting back to 0 at 12am. I guess, for the sake of a clearer view of the algorithm.

Okay, so now the keyboard knows when it should switch. Great.

But wait...

How should it switch... the scroll lock?

Well, for some keyboards, pressing the Scroll Lock key triggers backlit.

And for most Linux machines, you can control your keyboard LEDs using xset command.

From xset man page:

led

The led option controls the keyboard LEDs. This controls the turning on or off of one or all of the LEDs. It accepts an optional integer, a preceding dash(-) or an 'on/off' flag...

...For example, to turn on the Scroll Lock LED:
xset led named "Scroll Lock"

Cool.

So now we have all we need, we can now write the code.

while true; do

current_hr=\$((10#\$(date +'%H')))
current_min=\$((10#\$(date +'%M')))
six_am=6
six_pm=18

# sunrise
if [[ current_hr -eq six_am ]]; then

next_check=43200 # 12 hrs in s
xset -led named 'Scroll Lock'

echo 'Next check at' \$(date -d "now + \$next_check seconds")',' 'approx' \$((\$next_check/60/60)) 'hrs from now.'
sleep \$next_check

# sunset
elif [[ current_hr -eq six_pm ]]; then

next_check=43200 # 12 hrs in s
xset led named 'Scroll Lock'

echo 'Next check at' \$(date -d "now + \$next_check seconds")',' 'approx' \$((\$next_check/60/60)) 'hrs from now.'
sleep \$next_check

# midnight till before sunrise
elif [[ current_hr -lt six_am ]]; then

min_to_six=\$((\$((10#\$six_am*60 + 10#0)) - \$((10#\$current_hr*60 + 10#\$current_min))))
next_check=\$((\$min_to_six * 60))
xset led named 'Scroll Lock'

echo 'Next check at' \$(date -d "now + \$next_check seconds")',' 'approx' \$((\$next_check/60/60)) 'hrs from now.'
sleep \$next_check

# after sunrise till sunset
elif [[ current_hr -lt six_pm ]]; then

min_to_six=\$((\$((10#\$six_pm*60 + 10#0)) - \$((10#\$current_hr*60 + 10#\$current_min))))
next_check=\$((\$min_to_six * 60))
xset -led named 'Scroll Lock'

echo 'Next check at' \$(date -d "now + \$next_check seconds")',' 'approx' \$((\$next_check/60/60)) 'hrs from now.'
sleep \$next_check

# after sunset till before sunrise
elif [[ current_hr -gt six_pm ]]; then

hrs_to_twelve_am=\$((\$((10#24*60 + 10#0)) - \$((10#\$current_hr*60 + 10#\$current_min))))
min_to_six=\$((\$((10#\$hrs_to_twelve_am + 10#0)) + \$((10#6*60 + 10#0))))

next_check=\$((\$min_to_six * 60))
xset led named 'Scroll Lock'

echo 'Next check at' \$(date -d "now + \$next_check seconds")',' 'approx' \$((\$next_check/60/60)) 'hrs from now.'
sleep \$next_check
fi

done

Feel free to correct me or suggest simpler ways. I'll be glad and grateful to learn from you. ;)

This script is hosted in Github as well, as part of my personal and personalized Bash scripts.
https://github.com/raymelon/bash-wrappers/blob/master/auto-scrlck

Cheers!

That's what cron is for. 2 lines, 2 commands:

0 6 * * * root /path/to/xset -led named 'Scroll Lock'
0 18 * * * root /path/to/xset led named 'Scroll Lock'

Raymel Francisco

Cool. That is way simpler. Thanks!
I have a question though. Can we use cron to make the keyboard decide whether to turn on/off its backlit at startup? Any suggestions?

Just a baka

You may run it using @reboot in the same crontab or take advantage of your init system (sysvinit / systemd / etc). But you'll now have to calculate the desired led state (on/off) in your run command or script, which can be achieved by simply comparing the current 24-h formatted hour value with 6 and 18.

#!/bin/bash

current_hour=`date +%H`
led_value="led"

if [ \$current_hour -ge 6 ] && [ \$current_hour -lt 18 ];
then
led_value="-led"
fi

/path/to/xset \$led_value named 'Scroll Lock'

This can be compacted to an one (and ugly) one-liner and put everywhere. A bit more civilized way would be to leave it as a shell script.

# notice the cron.d syntax
@reboot root /path/to/our_super_script.sh
0 6,18 * * * root /path/to/our_super_script.sh