Jonathan Eskow
Published © CC BY-NC

PiHub

Desktop information center using the Raspberry Pi 2 B

IntermediateFull instructions provided2,754
PiHub

Things used in this project

Hardware components

Raspberry Pi 2 Model B
Raspberry Pi 2 Model B
×1
Adafruit Blue and White LCD screen with keypad
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

enclosureOdd

Odd numbered pieces for enclosure

enclosureEven

Even number pieces for enclosure

buttonsRound

You need to print 3 of these

buttonsFlattened

you need to print 2 of these

Schematics

piHub mock up

Since the Adafruit shield I used is unavailable in the Adafruit fritzing library, I created a quick mock up to show placement of buttons, screen, and i2c chip.

Code

piHub.py

Python
import RPi.GPIO as GPIO # import GPIO
import time #import time
from urllib2 import Request, urlopen, URLError #import URL tools
import pywapi #import weather api
import string #import string
import datetime #import date time lib
import json #import json lib for parsing
import unirest #import unirest
import math#import math
import threading #import threading for use with time

import Adafruit_CharLCD as LCD#import LCD screen and claim object

#initialize LCD
lcd = LCD.Adafruit_CharLCDPlate()

#this function uses pywapi and pings the NOAA site to recieve weather information from a hard coded
#station, station identities can be found at w1.weather.gov/xml/current_obs/seek.php?state=az&Find=Find
def weather():
    try: #try catch

        result = pywapi.get_weather_from_noaa('KPHL') #ping pywapi to contact NOAA

        weather = string.lower(result['weather']) + " \n" + result['temp_f'] + " F." #give parsed weather information

        lcd.message(weather) #print weather information to lcd screen

    except URLError, e: #if API cannot be contacted throw URL error
        lcd.message('could not connect to weather service'), e
        

#this function pings numbersapi to give trivia
def trivia():
    lcd.clear() #clear lcd screen
    request = Request('http://numbersapi.com/random/trivia') #request is from numbers API

    while True:
        try:
            response = urlopen(request) #use urlopen library to get response
            trivia = response.read() #read response from API

            while len(trivia) < 80:
        
                if len(trivia) > 60: #if entry is greater than 60 characters, break it up into two messages
                  s = trivia
                  lcd.message(s[0:len(trivia)/2])#slice trivia message in half and post first half

                  lcd.message("\n") #start new line

                  lcd.message(s[len(trivia)/2:len(trivia)]) #slice trivia and print second half
            
                else: #if message is small just print without breaking up
                  lcd.message(trivia) 

                while True: 
                    #loop through to use button
                    if lcd.is_pressed(LCD.SELECT): #while select button is pressed, scroll left
                        lcd.move_left()
                        time.sleep(.1)

                    elif ((lcd.is_pressed(LCD.RIGHT))or (lcd.is_pressed(LCD.DOWN)) or (lcd.is_pressed(LCD.LEFT))):
                        break
                    else:
                        continue

                if ((lcd.is_pressed(LCD.RIGHT))or (lcd.is_pressed(LCD.DOWN)) or (lcd.is_pressed(LCD.LEFT))):
                    break
                else:
                    continue
    
        except URLError, e: #if API cannot be contacted throw URL error
            lcd.message('could not connect to trivia api'), e

        if ((lcd.is_pressed(LCD.RIGHT))or (lcd.is_pressed(LCD.DOWN)) or (lcd.is_pressed(LCD.LEFT))):
            break
        else:
            continue

                    
#this function calls a fact API and gives back a famous quote
def quote():
    lcd.clear() #clear LCD

    while True:
        try:
            response = unirest.post("https://andruxnet-random-famous-quotes.p.mashape.com/cat=famous", #use unirest to ping quote API
            headers=
                {
                    "X-Mashape-Key": "<your API key here>", #use API key from Mashape.com
                    "Content-Type": "application/x-www-form-urlencoded", #define content type
                    "accept": "application/json" #confirm JSON format
                },
                params={ "parameter": 23, "foo": "bar"}#parameters for JSON
                )

            quote = response.raw_body #create variable for raw JSON response
            json_string = quote #identify JSON response as string
            parsed_json = json.loads(quote)#create variable foor JSON parse

            quoteParse = (parsed_json['quote']) + " -" + (parsed_json['author']) #create variable for Parsed response

            while True: #as with trivia API, filter out responses of over 80 characters
                if len(quoteParse) > 80:
                    break
        
                elif len(quoteParse) > 60: #if length of parsed quote is over 60, break it up among two lines
                    s = quoteParse
                    lcd.message(s[0:len(quoteParse)/2]) #slice parsed message, post first half

                    lcd.message("\n") #new line

                    lcd.message(s[len(quoteParse)/2:len(quoteParse)]) #slice parsed message, post second half

                else: #if parsed quote is short, do nothing and just post quote
                    lcd.message(quoteParse)
    
                while True:
                   #loop through each button to check, as the select button is pressed, scroll left
                   if lcd.is_pressed(LCD.SELECT):
                       lcd.move_left()
                       time.sleep(.1)

                   elif (lcd.is_pressed(LCD.RIGHT))or (lcd.is_pressed(LCD.UP)) or (lcd.is_pressed(LCD.LEFT)):
                        break
                   else:
                        continue

                if (lcd.is_pressed(LCD.RIGHT))or (lcd.is_pressed(LCD.UP)) or (lcd.is_pressed(LCD.LEFT)):
                        break
                else:
                        continue
    
        except URLError, e: #if API cannot be contacted throw URL error
            lcd.message('could not connect to quote api'), e
            
        if (lcd.is_pressed(LCD.RIGHT))or (lcd.is_pressed(LCD.UP)) or (lcd.is_pressed(LCD.LEFT)):
            break
        else:
            continue
    
#this function calls a time API and gives accurate time based off of a timestamp generated from JSON

def giveTime():
    
    lcd.clear()
    try:
        response = unirest.get("http://api.timezonedb.com/?zone=America/New_York&format=json&key=<your API key here>", #receive time data from timezone API
        headers =
            {
            "key": "<your API key here>", #use key generated
            "accept": "application/json" #verify json response
            },
        )
        timeZone = response.raw_body #give raw JSON respons
        json_int = timeZone #parse timeStamp to integer to allow timestamp corrections
        parsed_json = json.loads(timeZone) #parse JSON call

        timeStamp = (parsed_json["timestamp"] + 14400) #timestamp plus offset
        
        value = datetime.datetime.fromtimestamp(timeStamp) #use timeStamp with date time library to format date and time

        readOut = (value.strftime('%Y-%m-%d %I:%M %p')) #format date and time
        
        lcd.message(readOut)  #readout formatted time data
       
    except URLError, e:
            lcd.message('could not contact time api'),e

      
#enter Main Method

lcd.message('Welcome to PiHub!')

while True:
            #loop through each button to check
    if lcd.is_pressed(LCD.RIGHT):
        lcd.clear()
        weather()
        

    if lcd.is_pressed(LCD.LEFT):
        lcd.clear()
        giveTime()
       

    if lcd.is_pressed(LCD.UP):
        lcd.clear()
        trivia()
        

    if lcd.is_pressed(LCD.DOWN):
        lcd.clear()
        quote()
        

##    if lcd.is_pressed(LCD.SELECT):
##        break

GPIO.cleanup()#clean up

pihub shell

SH
###BEGIN INIT INFO
# Provides: PiHub automatic startup
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: PiHub project
# Description: gives weather,time,trivia,and quotes
### END INIT INFO

#! /bin/sh
# /etc/init.d/pihub

USER=pi
HOME=/home/pi

export USER HOME

case "$1" in
    start)
       echo "Starting PiHub"
       sudo python "/home/pi/piHub_1.py"     
       ;;

    stop)
       echo "Stopping PiHub"
       /usr/bin/pihub -kill :0
       ;;
    
    *)
       echo "Usage: /etc/init.d/pihub {start|stop}"
       exit 1
    ;;
esac

exit 0

Github

https://github.com/adafruit/Adafruit_Python_CharLCD.git

Credits

Jonathan Eskow

Jonathan Eskow

5 projects • 19 followers
Electronics Engineer at NextFab and ECE undergrad at Temple University

Comments