Unzip the downloaded PeppTalkProduct.zip
to a location of your choice. You will run Pepp Talk from inside this folder. Install the dependencies under the Dependencies section and set up the Apache sever under Preparing your Database with Apache. After you set up Apache, you just have to make one more edit. Go to the PeppTalkProduct
folder and open report_generator.sh
with your preferred text editor. Change the ABS
variable to be the absolute path to this folder. Now that everything is installed, see the Running Pepp Talk section.
Inside the PeppTalkProduct
folder is an install.sh
Shell Script. Running this script will install all our dependencies for you. However, this may install unnecessary files; for example, our script runs sudo apt-get upgrade
, which may install unnecessary files onto your system. If you are concerned with which files are installed on your system, please view the script and select the dependencies you wish to install. Please note however, that our product may not work if you do not install everything in the script.
Do note that if the Linux environment is not running on a Raspberry Pi, sudo rpi-update
will fail. This is OK as long as you are not running the Linux environment on a Raspberry Pi. If sudo rpi-update
fails and you are running on a Raspberry Pi, please refer to your Raspberry Pi's official documentation on this issue.
Below are the dependencies the script installs. Small descriptions are provided in case apt-get
or pip
fails and you have to install manually.
sudo apt-get install default-jdk
sudo apt-get install python 2.7.6
sudo apt-get install python-pip
sudo apt-get install apache2
sudo apt-get install python-dev
sudo apt-get install libapache2-mod-wsgi
sudo pip install bottle
sudo pip install UnQLite
sudo apt-get install curl
sudo pip install requests
sudo pip install datetime
sudo apt-get install Cython
sudo apt-get install festival
sudo apt-get install vlc
We are no longer using Beautiful Soup 4, a web scraping tool. You may still want to install Beautiful Soup 4 for use in your own Seeds. To do so, use:
sudo pip install beautifulsoup4
The PeppTalk Database wrapper is designed to run as a webservice.
You can use your favorite way of hosting Python WSGI files to host it.
Here we describe the way to deploy it so that it is configured to work with the example applications we have provided.
These instructions are designed for a Debian based box (like Raspbian or Ubuntu)
The PeppTalk Database wrapper requires several dependencies.
If you are not using apt-get
as your package manager, install these dependencies with your package manager of choice.
Run:
sudo apt-get install apache2
sudo apt-get install python-dev
sudo apt-get install libapache2-mod-wsgi
sudo apt-get install cython
sudo apt-get install python-pip
sudo pip install bottle
sudo pip install UnQLite
sudo apt-get install curl
Note that the capitalization matters for UnQLite.
We will make minimal changes to apache from its default configuration.
apache
is running by typing:> curl localhost:80
Running this command should display a default web page. For example, you might see the following:
<html>
<body>
<h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body>
</html>
cd /etc/apache2/
ports.conf
and the provided default site. You can use the test editor of your choice to edit ports.conf
such as nano
make sure to edit this file using sudo
because the file is read only
ports.conf
Find the lines that says
NameVirtualHost *:80
Listen 80
and replace 80
with 43508
. You can use any port you wish, as long as you keep the other componets of Pepp Talk up to date.
If NameVirtualHost
does not exist add it in with port 43508
etc/apache2/sites-enabled
Use your prefered text editor to edit the default site.
It is probably called 000-default
.
Again make sure to edit this file with sudo
.
In that file, within the virtual host tags, add this in the file:
WSGIScriptAlias /PeppTalk /var/www/pepptalk/app.wsgi
<Directory /var/www/pepptalk>
WSGIProcessGroup test
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
Also change the tag <VirtualHost *:80>
at the top of the file by replacing 80
with 43508
This will serve the pepptalk app WSGI to the /PeppTalk/
extension of your server URL.
apache2
directory. Open up apache.conf
in a text editor (remember to use sudo).
Near the bottom of apache2.conf
, above Include sites-enabled/
add the following line to the file:
WSGIDaemonProcess test
Now that apache
is configured to serve the WSGI, we need to place the python package and create the WSGI file to serve it.
cd /var/www
sudo mkdir pepptalk
sudo chmod 777 pepptalk
because we need to make sure the apache user is able to access our files.DatabaseWrapper
folder provided in the pepp talk download into /var/www/pepptalk.
sudo cp -r DatabaseWrapper /var/www/pepptalk
sudo chmod 777 DatabaseWrapper
app.wsgi
in the pepptalk folder. Add the following: import sys
sys.path.insert(0,"/var/www/pepptalk/DatabaseWrapper")
from pepp_wsgi import application
chmod 777 app.wsgi
sudo service apache2 restart
This restarts your server (which we want, since we have edited some config files).curl -H "Content-Type: application/json" -X POST -d '{"name":"weather"}' localhost:43508/PeppTalk/Seeds/
Congratulations, your listening server is now configured!
You may start your Apache server at anytime using
sudo service apache2 start
and stop your Apache server using
sudo service apache2 stop
In order to run Pepp Talk, you must have information inside the Database, populated using Seeds, and a User Template file. For more information on creating Seeds, see the Seeds section. For more information on User Templates, see the User Templates section. Once you have data in the database, locate the .template
file you would like to use to generate your Pepp Talk, and pass its path into the report_generator.sh
Shell Script. This path can be a local path or an absolute path. An example of passing in a template to the script is:
./report_generator.sh Template/Weather.template
VLC will open and play your Pepp Talk .wav
file after your Pepp Talk is generated (and then VLC will close after the .wav
file finishes playing), and if you have a default audio output device connected you should be hearing your Pepp Talk as well. If a .wav
file does not play, an error may have occurred, but check that you have a default audio output device connected.
After running Pepp Talk, the .txt
and .wav
outputs will be in the same location as the User Template.
Inside the DatabaseWrapper
folder is the wrapper.py
script. Inside this script is a bunch of methods to access the database directly. In order to use these methods, implement this class in a new Python script and add a main method that uses the methods in wrapper.py
to do your bidding to the Database. See wrapper.py
for more details.
Seeds are scripts are written to gather data from various sources to be fed into a Pepp Talk. These Seeds can be written in any language and communicate with the database through the REST API.
The Seeds folder contains an example folder that contains scripts that pull various different data sources like weather, finances, IoT devices, and news. These scripts gather the data and send it to the database. These serve as good examples of how to create a Seed for the Pepp Talk system.
Pepp Talk is designed to have Seeds written in various different languages. We recommend using Python, as our example scripts are written in Python.
$Name$
to the databaseIf $Name$
does not exist, this method will fail with a 303
response telling the user to create the method first.
We are adding data $D1$
to Seed $Name$
, which was retrieved at time $T1$
. The data, $D1$
is a nested JSON document that the user must know the structure of to create the report generator.
Post /PeppTalk/Seeds/$Name$
{
"data": $D1$,
"name": $Name1$,
"timestamp": $T1$
}
The database will return the JSON object passed in.
$Name$
, $Name2$
, and $Name3$
are stored in the database, the below will be returned from the call below. No data is expected on the call. If the database is empty, a 204
(No Content) will be returned.
Get /PeppTalk/Seeds
Will return
{
"name": [$Name$, $Name2$, $Name3$]
}
If $D1$
is data associated with Seed $Name1$
, the below will be returned for the call, with $T2$
as the time it was entered into the database. Names is a Seed. A request for a non-existent Seed will respond with a 400
(Bad Request) response code.
Get /PeppTalk/Seeds/$Name1
Will return
{
"data": $D1$,
"name": $Name1$,
"timestamp": $T1$,
"logtimestamp": $T2$
}
If you wish to access Seed entries in the database other than the most recent, append to the url that retrieves the data (e.g. /PeppTalk/Seeds/$Name1
) a forward slash and a number corresponding to how far back in the database you would like to go (i.e. /0
is most recent, /1
is one back, /4
is four back.).
Here is a full example, getting an entry 2 back (the 3rd one) from Seed Name1:
/PeppTalk/Seeds/$Name1/2
crontab -e
. The crontab takes form
m h dom mon dow command
The first five columns of the crontab are for scheduling how often tasks are run. See the man pages for cron and crontab for more details.
Be aware that the cron
daemon runs as a different user, which could require different permissions.
"""
Sample Output for College Park, MD; 3 day forecast
It is mostly cloudy in College Park, MD with a temperature of 62 degrees. Today has a high of 80 and a low of 57.
The forecast for Wednesday is mostly sunny with a high of 71 and a low of 50, Thursday is mostly cloudy with a
high of 75 and a low of 50, Friday is rain with a high of 77 and a low of 62.
"""
from seed import Seed
import requests, json
from datetime import datetime
class Forecast:
def __init__(self, location, condition, temp, high, low, daily_forecast):
self.location = location
self.condition = condition
self.temp = temp
self.high = high
self.low = low
self.daily_forecast = daily_forecast
def encode(self):
encoded = {}
encoded['location'] = self.location
encoded['condition'] = self.condition
encoded['temp'] = self.temp
encoded['high'] = self.high
encoded['low'] = self.low
encoded['forecast'] = []
for day in self.daily_forecast:
encoded['forecast'].append(day.encode())
return encoded
def __str__(self):
current = 'It is {} in {} with a temperature of {} degrees. '.format(self.condition, self.location, self.temp)
today = 'Today has a high of {} and a low of {}. '.format(self.high, self.low)
weather = ''
forecast_str = []
for f in self.daily_forecast:
forecast_str.append(str(f))
if forecast_str:
weather = 'The forecast for '
weather += ', '.join(forecast_str)
weather += "."
return current + today + weather
def __repr__(self):
return self.__str__()
class DailyForecast:
def __init__(self, day, condition, high, low):
self.day = day
self.condition = condition
self.high = high
self.low = low
def encode(self):
encoded = {}
encoded['day'] = self.day
encoded['condition'] = self.condition
encoded['high'] = self.high
encoded['low'] = self.low
return encoded
def __str__(self):
return '{} is {} with a high of {} and a low of {}'.format(self.day, self.condition, self.high, self.low)
def __repr__(self):
return self.__str__()
class WeatherSeed():
dbHost = "http://localhost:43508"
dbPath = "/PeppTalk/Seeds/"
def __init__(self):
self.name = "weather"
self.forecast = None
def retrieve_data(self, location, num):
print self.name
if num < 0 or num > 9:
print "ERROR: Please input the number of days weather forecast you want between 0 and 9."
return None
if not location:
print "ERROR: Please input a location."
return None
baseurl = "https://query.yahooapis.com/v1/public/yql?"
yql_query = "q=select * from weather.forecast where woeid in (select woeid from geo.places(1) where text=\"{}\")".format(location)
yql_url = baseurl + yql_query + "&format=json"
data = requests.get(yql_url).json()
if data['query']['results'] is None:
print "ERROR: There is no weather forecast for {}".format(location)
return None
day_dict = {'Mon': 'Monday', 'Tue':'Tuesday', 'Wed':'Wednesday', 'Thu':'Thursday', 'Fri':'Friday', 'Sat':'Saturday', 'Sun':'Sunday'}
weather = data['query']['results']['channel']['item']
condition = weather['condition']['text'].lower()
temp = int(weather['condition']['temp'])
high = int(weather['forecast'][0]['high'])
low = int(weather['forecast'][0]['low'])
daily_forecast = []
for day in range(1, num+1):
day_var = day_dict[weather['forecast'][day]['day']]
day_condition = weather['forecast'][day]['text'].lower()
day_high = int(weather['forecast'][day]['high'])
day_low = int(weather['forecast'][day]['low'])
day_forecast = DailyForecast(day_var, day_condition, day_high, day_low)
daily_forecast.append(day_forecast)
forecast = Forecast(location, condition, temp, high, low, daily_forecast)
self.forecast = forecast
def format_data_for_storage(self):
weather_json = {}
if self.forecast:
weather_json = self.forecast.encode()
return Seed(self.name, weather_json)
def send_to_database(self, seed):
weather_json = json.loads(seed.encode())
url = self.dbHost + self.dbPath
response = requests.post(url, json=weather_json)
if (response.status_code != 200) and (response.status_code != 201):
raise RuntimeError(
'Failed attempt to post to database. Response from ' + url + ' was ' + str(response. status_code))
url = url+self.name
response = requests.post(url, json=weather_json)
if (response.status_code != 200) and (response.status_code != 201):
raise RuntimeError(
'Failed attempt to post to database. Response from ' + url + ' was ' + str(response.status_code))
return response
def __str__(self):
if self.forecast:
return str(self.forecast)
else:
return ""
def __repr__(self):
return self.__str__()
def main():
location = "College Park, MD"
weather = WeatherSeed()
weather.retrieve_data(location, 3)
seed = weather.format_data_for_storage()
weather.send_to_database(seed)
if __name__ == '__main__':
main()
A User Template is a specially formatted text document that will be translated into a regular text document using the Genshi Templating Engine. It consists of two components: the specially formatted text that the user would like in a report, and a list of the Seeds that this report is pulling information from. User Templates are the instructions that create your very own Pepp Talk A User Template should be saved with the .template extension.
The Templates folder is a good place to keep all your User Templates. You do not need to place your User Templates inside this folder (even though we recommend it), as you will be manually passing in the path of a User Template in as a command line argument.
Inside the "Templates" folder is also a sub-folder called "Examples". There you will find several example User Templates that create Pepp Talks using the example Seeds we provided inside the "Seeds" folder. See The Seeds Folder section for more details on these seeds.
Scripts for our tool are written in a strict subset of the Genshi New Text Template language. The first line is expected to be a Genshi comment, delimited by {# ... #}
that contains a list of seeds from which data will be retrieved for use in the template. Each variable in the template is expected to be either an identifier contained in that list, or a retrieval from a dictionary with an identifier contained in that list, with a key corresponding to an entry in the database or a dictionary or key nested within that.
For instance, if the first line is
{# ["weather","finance","openHab"] #}
And the Weather Seed has the fields "location"
and "forecast"
, and "forecast"
is a nested structure with the field "hi"
and "low"
, valid variable identifiers would include (non-exhaustively) weather, weather["location"]
, weather["forecast"]
, and weather["forecast"]["hi"]
. It would not include weather["location"]["hi"]
. Errors in variable identifiers will be reported at run-time.
Scripts whose first line lack a list of Seeds are equivalent to scripts whose first line contains an empty list, and will only be valid if they contain no variables.
When you design your own Seeds, you will know their structure and the fields you can call.
In order to use a completed template, you must have information in the database, most likely populated by one or more Seeds. You can use a User Template by passing it to the report_generator.sh
Shell Script via command line argument. He is one such example.
./report_generator.sh Template/Weather.template
The following is an example User Template for the example weather Seed included with Pepp Talk:
{#["weather"]#}
Hi Kevin,
Currently, the temperature is ${weather['temp']} degrees.
Today's forecast is ${weather['condition']} with a high of ${weather['high']} degrees and low of ${weather['low']} degrees.
{% for forecast in weather['forecast'] %}
${forecast['day']}'s forecast is ${forecast['condition']} with a high of ${forecast['high']} degrees and low of ${forecast['low']} degrees.
{% end %}
If you are having trouble hearing your Pepp Talk, check that your audio device is connected to your Linux environment, and that the audio device is the Default Audio Output Device.
sudo rpi-update
Fails with "command not found"If the Linux environment is not running on a Raspberry Pi, sudo rpi-update
will fail. This is OK as long as you are not running the Linux environment on a Raspberry Pi. If sudo rpi-update
fails and you are running on a Raspberry Pi, please refer to your Raspberry Pi's official documentation on this issue.
.template file!
Make sure you have set the absolute path of the PeppTalkProduct
folder! Go to the PeppTalkProduct
folder and open report_generator.sh
with your preferred text editor. Change the ABS
variable to be the absolute path to this folder. If you are still having problems, please see the Installing Pepp Talk section.