Saturday, 8 March 2014

BBC Weather Reporter LCD

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:



No comments:

Post a Comment