Irene Kwon
Published

All-in-One Morning Updates with PocketBeagle

PocketBeagle tablet device that displays the weather (highs and lows) for the day as well as the news headlines of the day.

BeginnerFull instructions provided1,783
All-in-One Morning Updates with PocketBeagle

Things used in this project

Hardware components

PocketBeagle
BeagleBoard.org PocketBeagle
×1
Adafruit 2.8" TFT LCD with Touchscreen Breakout Board w/ MicroSD Socket
×1
EDIMAX Wi-Fi Nano USB Adapter N150
×1
Cylewet 25Pcs 12x12x7.3mm Momentary Tact Tactile Push Button Switch Touch Switch Micro Switch 4 Pins SMD PCB with Cap for Arduino (Pack of 25) CYT1009
×1
Resistor 1k ohm
Resistor 1k ohm
×1

Hand tools and fabrication machines

Soldering Station, 110 V
Soldering Station, 110 V

Story

Read more

Schematics

Complete Circuit Diagram of PocketBeagle and Components

Code

Script to Display News Headlines and Weather Data

Python
Imports the individual scripts for each task (gathering news headlines and weather data) to display on the LCD screen
"""
--------------------------------------------------------------------------
Display News Headlines and Daily Weather Forecast on LCD Screen
--------------------------------------------------------------------------
License:   
Copyright 2019 Irene Kwon

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors 
may be used to endorse or promote products derived from this software without 
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------
Software API:
    
    * adafruit_rgb_display
        * used to interface ILI9341 LCD Screen with PocketBeagle
    * Adafruit_Blinka
        * used for circuit python to then use digitalio
  
--------------------------------------------------------------------------
Background Information: 
 
    * Base code/instructions:
        * https://learn.adafruit.com/adafruit-2-dot-8-color-tft-touchscreen-breakout-v2/python-wiring-and-setup

--------------------------------------------------------------------------
Outline:
    
    - Set up the PocketBeagle and LCD screen
    - Import/use the functions to gather the necessary data
    - Display text on LCD screen
    - Control display with button
    
"""
# ------------------------------------------------------------------------------
# Setup for LCD Display/Interfacing with Display
# ------------------------------------------------------------------------------

#Import necessary libraries
import os
import digitalio
import board
from PIL import Image, ImageDraw, ImageFont
import adafruit_rgb_display.ili9341 as ili9341


#Define the CS, DC, and Reset pins
cs_pin    = digitalio.DigitalInOut(board.P2_2)
dc_pin    = digitalio.DigitalInOut(board.P2_4)
reset_pin = digitalio.DigitalInOut(board.P2_6)

# Config for display baudrate (default max is 24mhz):
BAUDRATE  = 24000000

# Setup the SPI bus
spi       = board.SPI()

# Create the display
disp      = ili9341.ILI9341(spi, rotation=90, 
                            cs=cs_pin, dc=dc_pin, rst=reset_pin, baudrate=BAUDRATE)


# ------------------------------------------------------------------------------
# Setup Button
# ------------------------------------------------------------------------------

import time
import Adafruit_BBIO.GPIO as GPIO

BUTTON0    = "P2_8"

# ------------------------------------------------------------------------------
# Setup FinalNews.py and FinalWeather.py and Outputs Desired
# ------------------------------------------------------------------------------

import FinalNews
import FinalWeather
import textwrap
 
DH_raw      = str(FinalWeather.high)
DL_raw      = str(FinalWeather.low)
DC_raw      = str(FinalWeather.curr)

News_Header = str(FinalNews.header)
Article     = FinalNews.article
News_Info   = News_Header.splitlines()

# ------------------------------------------------------------------------------
# Functions
# ------------------------------------------------------------------------------

def setup():
    GPIO.setup(BUTTON0, GPIO.IN)
    print("Setup Complete")
    
# End def

def setup_wifi():
    os.system("connmanctl enable wifi")
    os.system("connmanctl agent on")
    os.system("connmanctl connect wifi_74da38de508b_526963652056697369746f72_managed_none")
# End def

            
# For displaying on the LCD Screen
def cleanstring(string):
    cleana = string.replace("(", "")
    cleanb = cleana.replace(")", "")
    cleanc = cleanb.replace("'", "")
    cleand = cleanc.replace(",", "")
    
    def createRGB(disp):
        
        if disp.rotation % 180 == 90:
            height = disp.width   # we swap height/width to rotate it to landscape!
            width  = disp.height
        else:
            width  = disp.width   # we swap height/width to rotate it to landscape!
            height = disp.height
        image = Image.new('RGB', (width, height))
     
        # Reset the screen to black
        draw = ImageDraw.Draw(image)
        
        draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
        disp.image(image)
        
        # Display the desired output
        if ("Headlines" in cleand):
            size = 16
        else:
            size = 20
            
        fnt = ImageFont.truetype('Pillow-master/Tests/fonts/FreeMono.ttf', size)
        
        draw.text((0,0), text=cleand, fill = (255,255,255), font=fnt)
        disp.image(image)
        
    return createRGB(disp)
    # End def
# End def

def WeatherUpdate(DL_raw, DH_raw, DC_raw):
    temps     = [DC_raw, DL_raw, DH_raw][0:]
    all_temps = "\n".join(temps)
    cleanstring(all_temps)
    
# End def

def NewsUpdate(News_Info, Article):
    newslist = News_Info + Article
    news     = newslist[1:]
    all_news    = "\n".join(news)
    cleanstring(all_news)
    
def task():
    initialize        = True
    button_press      = 0
    button_press_time = 0.0
    
    while(1):
        try:
            # Wait for button press
            #print("Here")
            while(GPIO.input(BUTTON0) == 1):
    #            print("Here1")
                pass #don't do anything if 1, just keep coming back to check condition
            
            # Record time
            button_press_time = time.time()
            
            # Wait for button release
            while(GPIO.input(BUTTON0) == 0):
                pass
            
            # If instantaneously pressed (ie less than 2)
            if ((time.time() - button_press_time) > 2.0): #if beyond 2 seconds
                exit() #exits out of script
            else:
                button_press += 1
    #            print(button_press)
                #Times the button is pressed: display news (even) or weather (odd)
                
                # Run on the first button press to initialize the wifi
                if initialize:
                    setup_wifi()
                    initialize = False
                    
                if (button_press % 2) == 1:
                    WeatherUpdate(DL_raw, DH_raw, DC_raw)
                else:
                    NewsUpdate(News_Info, Article)
        except:
            pass

# End def

#-------------------------------------------------------------------------------
# Main Script
#-------------------------------------------------------------------------------

if __name__ == '__main__':
    
    setup()
    try:
        task()
    except KeyboardInterrupt:
        pass

Individual Script to Gather Weather Data

Python
"""
--------------------------------------------------------------------------
Gathering Weather Forecast (Daily Highs and Lows) from OpenWeatherMap
--------------------------------------------------------------------------
License:   
Copyright 2019 Irene Kwon

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors 
may be used to endorse or promote products derived from this software without 
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------
Software API:
    
    * pyowm
        * Python library for OpenWeatherMap API
        * Free subscription only allows for current weather
  
--------------------------------------------------------------------------
Background Information: 
 
    * Information about pyowm
        * https://buildmedia.readthedocs.org/media/pdf/pyowm/latest/pyowm.pdf

--------------------------------------------------------------------------
Outline:
    
    - Get an API key for OpenWeather
    - Retrieve daily forecast

"""

from pyowm import OWM

#Load with the API_key for openweather
API_key  = 'ada0a3424a34c9445c81fba49df33410'
owm      = OWM(API_key)

#For Houston (city ID = 46990066)
obs      = owm.weather_at_id(4699066)

#Retrieve daily lows and highs as well as the current temperature
w        = obs.get_weather()
temp     = w.get_temperature('fahrenheit')

#Set up strings for displaying the daily forecasts
m_symbol = '\xb0' + 'F'
curr     = ('Current Temp: ', temp['temp'], m_symbol)
high     = ('Daily High: ', temp['temp_max'], m_symbol)
low      = ('Daily Low: ', temp['temp_min'], m_symbol)

#Prints the temperatures
if __name__ == '__main__':

    print(curr)
    print(high)
    print(low)

Individual Script to Gather News Headlines

Python
"""
--------------------------------------------------------------------------
Scraping News Headlines (from New York Times)
--------------------------------------------------------------------------
License:   
Copyright 2019 Irene Kwon

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors 
may be used to endorse or promote products derived from this software without 
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------
Software API:
    
    soup.find_all
      - Finds all instances of the search keys in the parentheses
    
    requests.get
      - Get/retrieve data from the given url
  
--------------------------------------------------------------------------
Background Information: 
 
    * Base code (adapted below):
        * https://stackoverflow.com/questions/55033291/scraping-headlines-from-news-website-homepages-using-beautifulsoup-in-python/
    * Information about libraries:
        * https://www.crummy.com/software/BeautifulSoup/bs4/doc/

--------------------------------------------------------------------------
Outline:
    
    - News headlines from New York Times
    - Scraping news headlines off of nytimes.com
    - Print the top 10 headlines
    
"""
#Import necessary packages
import requests 
from bs4 import BeautifulSoup
import json
import datetime
import textwrap

#Retrieve data from New York Times
url = "https://www.nytimes.com/"
r   = requests.get(url)
now = datetime.datetime.now()
now = now.strftime('%A, %B %d, %I:%M %p')

#Parse the script on the page
r_html = r.text
soup   = BeautifulSoup(r_html, "html.parser")

scripts = soup.find_all('script')
for script in scripts:
    if 'preloadedData' in script.text:
        jsonStr = script.text
        jsonStr = jsonStr.split('=', 1)[1].strip()
        jsonStr = jsonStr.rsplit(';', 1)[0]
        jsonObj = json.loads(jsonStr)

#Print the first 10 headlines
count   = 0
header  = ('%s\nHeadlines\n%s\n' %(url, now))
article = []

for ele, v in jsonObj['initialState'].items():
    try:
        if v['headline'][0] != '{':
            article.append(v['headline'])
            count += 1
    except:
        continue
    if count == 10:
        break

GitHub for Complete Code

Credits

Irene Kwon

Irene Kwon

1 project • 0 followers
Thanks to Erik Welsh.

Comments