Close

Time and Temperature Dashboard

A project log for recordShelf

recordShelf is an LED based organization system for any type of flat media you store on a shelf.

blinkingthingblinkingthing 10/27/2016 at 20:590 Comments

Adding some practicality. Dashboard Mode.


A few weeks ago I started looking into other ways I could use this large array of LED's in my living room. I settled on trying to make a dashboard of sorts that displays the current time and temperature.

Time is displayed on the top 12 boxes, 1 full box is equivalent to an hour, each single pixel is equal to 3 minutes.

The color of the completed full hour boxes should be a gradient spread evenly throughout. Every 3 minutes are represented by an orange pixel.

Temperature is displayed in the bottom left hand corner of the shelf. There is a gradient spread out across two boxes that is revealed or hidden as the temperature rises and falls. I have it set to read between 50º-90º Fahrenheit as that seems relevant to my interest in Southern California. 1 pixel = 1º.

All this is handled by a python script that runs on the raspberry pi on boot. Weather is pulled from the openweathermap.org API.

If I want to go back into record selection mode, all I have to do is open the web browser and select a record as per usual. The dashboard script runs once a minute so it will pick back up and start doing it's thing again once you're done picking out a record.

python script below:

#!/usr/bin/env python

# Open Pixel Control client: Every other light to solid white, others dark.

import opc, time, datetime, sched, json, requests

#scheduler for clock
s = sched.scheduler(time.time, time.sleep)

#opc / LED related setup
totalPixels = 320
selectedNo = 0
boxes = [0] * 16
numPixels = 20
client = opc.Client('localhost:7890')

darkFrame = (0,0,0)
white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
yuck_green = (115, 147, 126)
steel_blue = (160, 185, 198)
orange = (245, 166, 91)
blankFrame = [ (0,0,0) ] * totalPixels
newFrame = blankFrame

#reset neopixels to black
client.put_pixels(blankFrame)
client.put_pixels(blankFrame)
time.sleep(0.2)

#openweathermaps api setup
# replace **OPENWEATHERMAPSAPI_KEY** with your own key..
key = '**OPENWEATHERMAPSAPI_KEY**'
#units = 'metric'
units = 'imperial'
cityid = '5368361'
 
def hex_to_RGB(hex):
  ''' "#FFFFFF" -> [255,255,255] '''
  # Pass 16 to the integer function for change of base
  return [int(hex[i:i+2], 16) for i in range(1,6,2)]


def RGB_to_hex(RGB):
  ''' [255,255,255] -> "#FFFFFF" '''
  # Components need to be integers for hex to make sense
  RGB = [int(x) for x in RGB]
  return "#"+"".join(["0{0:x}".format(v) if v < 16 else
            "{0:x}".format(v) for v in RGB])

def color_dict(gradient):
  ''' Takes in a list of RGB sub-lists and returns dictionary of
    colors in RGB and hex form for use in a graphing function
    defined later on '''
  return {"hex":[RGB_to_hex(RGB) for RGB in gradient],
      "r":[RGB[0] for RGB in gradient],
      "g":[RGB[1] for RGB in gradient],
      "b":[RGB[2] for RGB in gradient]}


def linear_gradient(start_hex, finish_hex, n):
  ''' returns a gradient list of (n) colors between
    two hex colors. start_hex and finish_hex
    should be the full six-digit color string,
    inlcuding the number sign ("#FFFFFF") '''
  # Starting and ending colors in RGB form
  s = hex_to_RGB(start_hex)
  f = hex_to_RGB(finish_hex)
  # Initilize a list of the output colors with the starting color
  RGB_list = [s]
  # Calcuate a color at each evenly spaced value of t from 1 to n
  for t in range(1, n):
    # Interpolate RGB vector for color at the current value of t
    curr_vector = [
      int(s[j] + (float(t)/(n-1))*(f[j]-s[j]))
      for j in range(3)
    ]
    # Add it to our list of output colors
    RGB_list.append(curr_vector)

  return color_dict(RGB_list)



print "Waiting one minute for first result...."

def everyMinute(sc):
	currentTime = datetime.datetime.now()
	currentHour = currentTime.hour
	currentMinute = currentTime.minute
	thirdMinute = round(currentMinute/3)
	#openweathermap
	url = requests.get('http://api.openweathermap.org/data/2.5/weather?id='+cityid+'&units='+units+'&APPID='+key)
	weather = json.loads(url.text)
	currentTemp = weather['main']['temp']
	currentCondition = weather['weather'][0]['description']	
	
	print ("Current hour = %s" %currentTime.hour)
	print ("Current minute = %s" %currentTime.minute)

	print (currentTemp, "F")
	print currentCondition
	
	temp = int(round(currentTemp))
	tempLed = temp-51
	print "Rounded Temp : ", temp, " | LED: ", tempLed

	#24 -> 12 conversion
	if currentHour > 11:
		currentHour = currentHour - 12
	
	sunset = linear_gradient("#FC5531","#474A6f", currentHour*20).get('r')
	sunset = linear_gradient("#FC5531","#474A6f", currentHour*20).get('g')
	sunset = linear_gradient("#FC5531","#474A6f", currentHour*20).get('b')
	
	#reset newFrame every minute 
	newFrame = [ (0,0,0) ] * (totalPixels/4) * 3
	
	#weather pixels
	weatherFrame = [(0,0,0)] * (totalPixels/8)
	weatherFrame = [(148,179,255), (148,179,255), (152,182,255), (152,182,255), (160,186,255), (160,186,255), (164,189,255), (164,189,255), (173,196,255), (173,196,255), (180,200,255), (180,200,255), (191,206, 255), (191,206, 255), (203,215,255), (203,215,255), (217,224,255), (217,224,255), (237,235,255), (237,235,255), (255,238,238), (255,238,238), (255,227,211), (255,227,211), (255,213,179), (255,213,179), (255,196,143), (255,196,143), (255, 176, 104), (255, 176, 104), (255,158, 77), (255,158, 77), (255,130, 47), (255,130, 47), (255, 97, 16), (255, 97, 16), (255, 64, 0), (255, 64, 0), (255, 22, 0), (255, 22, 0)]
	for led, val in enumerate(weatherFrame): #for each
		if led > tempLed:
			print led, tempLed
			weatherFrame[led] = darkFrame
	del temp
	del tempLed
	last2Frames = [(0,0,0)] * (totalPixels/8)
	weatherFrame.extend(last2Frames)
	
	newFrame.extend(weatherFrame)
	
	for i,box in enumerate(boxes): #for each box
		### hour limit
		if i <= currentHour:
			for led, val in enumerate(newFrame): #for each 
				if led > (i*20)-21 and led < (i*20):
					r = sunset[led]
					g = sunset[led]
					b = sunset[led]
					newFrame[led]=(r, g, b)
				if led > ((i+1)*20)-21 and led < (((i+1)*20)-21)+thirdMinute+1:
					newFrame[led]=orange		
				#else:
				#	blankFrame[idx]=(0,0,0)
			client.put_pixels(newFrame)
			client.put_pixels(newFrame)
			time.sleep(0.2)
	s.enter(60, 1, everyMinute, (sc,))

s.enter(60, 1, everyMinute, (s,))
s.run()

Discussions