Following on with my LCD screen and button combo I've built a simple BBC Weather Reporter.
We start by getting the weather from BBC Weather RSS for our area, to make manipulating the information easier I threw together a class for dealing with the results. Then I grab the parts I'm interested in and sent them to the USB.
On the Teensy I need to wait for the results, it's immature at the moment so I just use a timer for up to 10 seconds.
Then we print the data out, the only issue I can find is that the Teensy doesn't recognise degrees at the moment so I'm getting some funky characters.
Here's the Python:
#!/usr/bin/python2.7
import urllib2
from DayWeather import DayWeather
from lxml import etree
#Import my bits
from DayWeather import DayWeather
#IMPORT USB stuff
from time import sleep
import numpy as np
import sys
import serial, time
from serial.tools import list_ports
def getWeather():
url="http://open.live.bbc.co.uk/weather/feeds/en/2643743/3dayforecast.rss"
rawMetGroup = urllib2.urlopen(url).read()
root = etree.XML(rawMetGroup)
build_text_list = etree.XPath("//item")
items=build_text_list(root)
days = []
for item in items:
day = item.find("title").text.split(":")[0]
desc = item.find("description").text
dw = DayWeather(day,desc)
days.append(dw)
return days
if __name__ == "__main__":
ports = [port[0] for port in list_ports.comports()]
print "Using serial port %s" % (ports[-1])
serial = serial.Serial(ports[-1],baudrate=9600, timeout=0, writeTimeout=1)
serial.flushInput()
serial.flushOutput()
while True:
content = serial.readline() # Read the newest output from the Arduino
output=""
if content == "GetWeather":
weather = getWeather() #The Weather has been requested
for w in weather:
if len(output) > 0:
output = output +"#"
output=output+w.toString().encode('utf-8')
print output
serial.write(output)
sleep(.1) # Delay for one tenth of a second
Here's the Python Weather class:
# -- coding: utf-8 --
import string
class DayWeather:
def __init__(self,day,details):
self.day = day
self.details = details.split(",")
description = "A basic object to read an parse an BBC weather object from their RSS feed"
author = "Michael Davies"
def getPart(self,part):
for detail in self.details:
if detail.strip().startswith(part):
return detail.split(":")[1].strip()
return ""
def getDay(self):
return self.day
def getMaxTemp(self):
temp = self.getPart("Maximum")
return "Max:" + temp
def getMinTemp(self):
temp = self.getPart("Minimum Temperature")
return "Min:" + temp
def toString(self):
return self.day + "," + self.getMaxTemp() + "," + self.getMinTemp()
Here's the C for the Teensy:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
String weather[3][3];
void setup(){
pinMode(7, INPUT_PULLUP); //Set pin 7 to INPUT_PULLUP, this uses the inbuilt resistor on the pin
lcd.begin();
Serial.begin(9600); // USB is always 12 Mbit/sec
lcd.noBacklight();
}
void loop(){
checkButton(); //Simple Check
delay(250);
}
void checkButton(){
if (digitalRead(7) == LOW ) {
Serial.print("GetWeather");
lcd.backlight(); //Turn the light on
lcd.clear();
lcd.home(); //Start at row 1
lcd.print("LOADING"); //Show something is happening
getWeather();
displayMessage();
lcd.clear(); //Clear the result at the end
lcd.noBacklight();
}
}
void getWeather(){
//Check for up to 10 seconds
for (int t = 0; t<40; t++){
if (Serial.available()){
readUSBToWeather();
return;
}
delay(250);
}
return;
}
void readUSBToWeather(){
String content = ""; //Set up return variable
char character; //char to read from USB
int dayLine = 0; //Day Number
int infoLine = 0; //Line Number
while(Serial.available()) { //While there is more to read, do more
character = Serial.read(); //Read the char
if (character =='#') {
weather[dayLine][infoLine] = content;
content="";
dayLine++;
infoLine=0;
}else if( character == ','){
weather[dayLine][infoLine] = content;
content="";
infoLine++;
}else{
content.concat(character); //Add it to the return variable
}
delay (10); //make sure we don't act too quickly and assume it's over before it really is
}
if (content != ""){
weather[dayLine][infoLine] = content; //Put the last bits on the end
}
return;
}
void displayMessage(){
//If the first day has data assume the rest is full
if (weather[0][0] == ""){
lcd.clear();
lcd.home();
lcd.print("No Message");
delay (2000);
lcd.noBacklight();
return;
}
//For each day
for (int day = 0;day < 3; day++){
//For each other row in the data
for (int info = 1; info < 3; info++){
lcd.clear();//Empty the screen
lcd.setCursor(0, 0);//Make sure we are home
lcd.home(); //Start at row 1
lcd.print(weather[day][0]); //Put the day
lcd.setCursor(0, 1);//Set row 2
lcd.print(weather[day][info]); //Put the weather
delay (2000); //Show this for 2 seconds
}
}
weather[0][0] = ""; //empty our first day to ensure we don't print when we shouldn't
return;
}
Here's a quick picture of it working: