Here’s my complete implementation for that Blinkodoro proof-of-concept in Python
from blinkstick import blinkstick
import psutil
import datetime
import time
import math
import colorsys
NR_LEDS = 8
POMODORO_LENGTH = 30
INTENSITY = 0.05
def led_data(minutes, seconds):
data = []
if 0 <= minutes < 25:
# Add blue pixels to show current Pomodoro.
for led in range(NR_LEDS):
if led < math.floor(minutes / 5):
data.append([240, 100])
elif led == math.floor(minutes / 5):
data.append([240, (minutes % 5 * 60 + seconds) / (60*5/100)])
else:
data.append([0, 0])
elif 25 <= minutes < 30:
for led in range(NR_LEDS):
# Start with three LEDs off.
if led <= 2:
data.append([0, 0])
# Add red pixels to show break.
elif 3 <= led < math.floor(minutes - 25 + 3):
data.append([0, 100])
elif led == math.floor(minutes - 25 + 3):
data.append([0, seconds / 60 * 100])
else:
data.append([0, 0])
return data
def set_leds(led_data):
i = 0
for led in led_data:
hue = led[0]
value = led[1]
rgb = colorsys.hsv_to_rgb(hue / 360.0, 1, value / 100 * INTENSITY)
time.sleep(0.1)
bstick.set_color(0, i, rgb[0] * 255, rgb[1] * 255, rgb[2] * 255)
i += 1
# Main loop
if __name__ == '__main__':
# First BlinkStick Strip.
time.sleep(0.1)
bstick = blinkstick.find_first()
if bstick is None or bstick.get_variant() != bstick.BLINKSTICK_STRIP:
print("No BlinkStick Strip found...")
exit()
else:
print("Blinkodoro started, showing process in current Pomodoro or break.")
minutes = 0
seconds = 0
# Go into a forever loop.
while True:
# Get current time: just the minute mark in current half hour.
minutes = datetime.datetime.now().minute % POMODORO_LENGTH
seconds = datetime.datetime.now().second
if minutes == 0:
time.sleep(10)
else:
# Determine LED data for current time.
data = led_data(minutes, seconds)
# Light LEDs according to LED data.
set_leds(data)
time.sleep(5)
Here’s a similar one in Ruby, exhibiting the similar error:
require 'yaml'
require 'color'
require './blinkstick'
HOUR = 60*60 # hour in seconds
# Color (gradient between two) used for LED color.
COLORS = [240, 359] # hue for blue is 240 degrees, for red 359 degrees.
# Ranges where blinkstick LED goes on.
LIGHT_ON = [ (25*60)..(29*60+29),
(55*60)..(59*60+29) ]
# Ranges where blinkstick LED blinks.
BLINK = [ (29*60+30)..(29*60+59),
(59*60+30)..(59*60+59) ]
def map(a, b, s)
v = s.clamp(a.min, a.max)
af, al, bf, bl = a.first, a.last, b.first, b.last
bf + (v - af)*(bl - bf)/(al - af)
end
# Turns on the LED, returning the necessary sleep time.
def turn_on(blinkstick, remaining)
puts "#{Time.now} turn_on"
$status = :on
# Brightness is function of remaining seconds: 300-0 -> 1-10
brightness = map([300,0], [1,10], remaining)
# Hue is for color between blue and red.
hue = map([300,0], COLORS, remaining)
# Create color, using hue and brightness.
color = Color::HSL.new(hue, 100, brightness)
color.to_rgb
# Set LED on BlinkStick to color.
sleep 0.1
blinkstick.color = color.to_rgb
# Sleep for two more seconds.
2
end
# Blinks the LED, returning the necessary sleep time.
def blink(blinkstick)
puts "#{Time.now} blink"
$status = :blink
sleep 0.1
blinkstick.off
# Set color, using hue and brightness.
color = Color::HSL.new(COLORS.last, 100, 10)
color.to_rgb
5.times do
# Set LED on BlinkStick to color, wait a while.
sleep 0.4
blinkstick.color = color.to_rgb
# Turn it off.
sleep 0.4
blinkstick.off
end
# Limited additional sleep time.
1
end
# Turns off the LED, returning the proper sleep time.
def turn_off(blinkstick)
puts "#{Time.now} turn_off"
$status = :off
sleep 0.5
blinkstick.off
# It's fine to sleep for five more seconds.
5
end
# Main script
$status = :off
$blinkstick = BlinkStick::find_all().first
# Make sure it's turned off at the start.
turn_off($blinkstick)
while true do
now = Time.now.to_i
seconds_in_hour = now % HOUR
sleep_for_seconds = 0
begin
if LIGHT_ON.any? do |range| range.include?(seconds_in_hour) end
sleep_for_seconds = turn_on($blinkstick, HOUR - seconds_in_hour)
elsif BLINK.any? do |range| range.include?(seconds_in_hour) end
sleep_for_seconds = blink($blinkstick)
else
sleep_for_seconds = turn_off($blinkstick)
end
rescue LIBUSB::ERROR_NO_DEVICE
STDERR.puts "Connection with BlinkStick lost... trying to connect again, just once."
$blinkstick = find_blinkstick($serial)
rescue LIBUSB::ERROR_INTERRUPTED
STDERR.puts "Transfer interrupted. Trying to connect again, just once."
$blinkstick = find_blinkstick($serial)
end
sleep sleep_for_seconds
end