Tags

, , , , , , ,

It took Arkwood and I a whole weekend to get this piece of shit working, so I will keep the post brief. Let’s just say that there were a few choice words between us as tempers frayed. And the poor postman, who made the mistake of delivering a parcel just at the moment I was struggling with the audio drivers. It’s a miracle that he’s not pressing charges.

Anyway, here’s the deal. We are using our Raspberry Pi to read random Wikipedia pages each time we press a button, and then using Google Text-To-Speech to speak out the article title. Was rather hoping to get this working with a random joke generator, but wasn’t in the mood come Sunday evening.

Okay, so this code gives us two classes, WebScraper to fetch our Wikipedia content, and WebSpeaker to translate the content into audio output i.e. talk to us. You’ll notice that both these classes inherit from WebAgent – kind of overkill just for the sake of a url, but one must practice one’s Python.

import requests
from BeautifulSoup import BeautifulSoup
import urllib
import subprocess

class WebAgent(object):

    # initialize class url
    def __init__(self, url):
        self.url = url

class WebScraper(WebAgent):

    # fetch content off webpage
    def fetch_content(self, tag, class_name):
        try:
            #get webpage
            request = requests.get(self.url)
            soup = BeautifulSoup(request.text)     
        
            #grab the content
            content = soup.find(tag, attrs={'class':class_name}).getText()

            return content
        except:
            print ("Error fetching webpage content")

class WebSpeaker(WebAgent):

    # converts text to speech
    def text_to_larynx(self, text):
        try:
            # truncate text as google only allows 100 chars
            text = text[:100]

            # encode the text
            query = urllib.quote_plus(text)

            # build endpoint
            endpoint = self.url + query

            # get google to translate, and mplayer to play audio
            subprocess.call(["mplayer", endpoint], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	    
            # debug endpoint
            #print(endpoint)
        except:
            print ("Error translating text")

WebScraper uses the requests package to get the webpage (word on the street says it is preferred over urllib2) and then harnesses Beautiful Soup to scrap the desired content. WebSpeaker is all about tarting up an endpoint to the Google translator, which MPlayer can utilise to play the translation.

One thing that was pretty cool, that I did not know about, is that Wikipedia has a random page generator. Try it:

http://en.wikipedia.org/wiki/Special:Random

Now, the MPlayer bit is where I really saw red. I just couldn’t get it to play the audio – gave me some Could not open/initialize audio device -> no sound crap. Well, seems that running the following snippet in the LXTerminal does the trick:

sudo modprobe snd_bcm2835

Another thing to note: the Google translation step has a habit of chopping off the first word or so from your speech, so you may want to stuff an arbitrary word at the front of your query parameter e.g. DELAY

http://translate.google.com/translate_tts?tl=en&q=DELAY+arkwood+dances+sensually

Right, so we have the nuts and bolts, now for the spanner.

from webagent import *
from time import sleep
import serial

# com port and speed
port = '/dev/ttyAMA0'
baud = 9600
 
# establish a serial connection
ser = serial.Serial(port=port, baudrate=baud)

while True:

    # if button pressed...
    if(is_button_pressed()):
        
        # ...then get an article and announce it! (then sleep a bit)
        article = WebScraper("http://en.wikipedia.org/wiki/Special:Random").fetch_content("h1", "firstHeading")
        WebSpeaker("http://translate.google.com/translate_tts?tl=en&q=").text_to_larynx(article)
        sleep(10.0)

All we need to do is use our WebScraper to get the Wikipedia content, and then use our WebSpeaker to announce it through our speakers (in my case, the HDMI cable to the TV set). The only other bit to account for is the use of the RasWIK wireless inventors kit, so that we only get an article when we press a button on our wireless board.

Here’s the RasWIK with a button wired up:

raswik_translation

And here’s the function that will check if the button has been pressed:

def is_button_pressed():

    # wait a mo...
    sleep(0.2)

    # write to Pin D10
    ser.write('a--D10READ--')
    
    # wait some more...
    sleep(0.2)
    
    # now read from Pin D10
    reply = ser.read(12)

    # grab the bit of the reply we care about
    message = reply[6:].strip('-')
    
    # return whether button is pressed down
    if(message == "LOW"):
        return True
    else:
        return False

Lovely. Now my runt of a Belgian friend and I can sit back on the sofa and request our random articles from Wikipedia to be spoken aloud. It is at this point that we wonder why we did it.

pi_translation

As always, life was made a little simpler with the use of Python Tools for Visual Studio, as we would not have wanted to code this up on our memory-creaking Pi. Oh, and it made sense to get the Python 2.7 interpreter, rather than constantly troubleshooting the version mismatch between PC and Pi. Hm, is there something better than IDLE to do debugging on Raspbian?

But no more questions, please. For both Arkwood and I are exhausted and undernourished. Time for pizza! And, given all the above code now works, I am less likely to do to the pizza delivery man with the pizza box what I did to the postman with the parcel. As the card attached to the flowers said, I am truly sorry. He will be out of hospital in a week.

Advertisements