Weather Station By Raspberry Pi

Update 2 11/15/2015

I recently bought a wifi-controlled plug, however, it only can be controlled in LAN. The possibilities with Raspberry Pi are unlimited, I found a API written in Python which allows me to control this smart plug through Pi. I am now able to let the Pi take over the smart plug by analyzing the data from the light sensor, which, I guess, is a good news for my cat Tina. Generally we cannot reach home before 6 pm, when it is already dark. Although Feline can see in the dark, the yellow light makes her feel warm, at least this is what I think.

Update 1 11/13/2015:

A triple GPIO extension was installed on the Raspberry Pi, I can use one GPIO for the LCD display and one for the sensors. Here is a quick look of the whole system.

Weather_Station_Update1

The joy stick on the LCD display hat is programmed in such a way that

‘left’ –> Display home condition
‘right’ –> outside weather
‘up’ –> Turn on the backlight
‘down’ –> Turn off the backlight
‘press’ –> Turn off the display

Now the weather station is also able to send updates through twitter (by Twython), please take a look at it here.


 

我在Raspberry Pi完成的最新项目是一个天气监测站,可以同时监测室内和室外天气状况,并且还可以记录室内光亮程度。室外天气的数据是调用Wunderground的API,天气站可以显示当前天气情况和未来一小时的天气情况,并且如果预报出将会下雨或者下雪,天气站会自动发送电子邮件告知。室内情况有两块传感器实现,天气状态和光亮分别由BME280TSL2561传感器提供。两块传感器通过I2C接口与Raspberry Pi连接,事实证明I2C设备可以通过并联得到两个不同的地址,具体的布线不在此赘述,可以分别参考Adafruit的连接说明,然后将其并联即可。

程序基于Python 2.0,在Linux环境下使用需要super user权限。

weather_station weather

主程序

from cls_readXML import *
from cls_sendEmail import *
from Adafruit_BME280 import *
from fn_lumen import *
from tsl2561 import TSL2561 as lightSensor
import os
import time
#======================================================================================
myWeather = readXML()
myEmail = email()
zipCode = '60616'

sensor = BME280(mode=BME280_OSAMPLE_8)

email_receiver = ['receiver@gmail.com']
email_alertReceiver = ['receiver01@gmail.com','receiver02@gmail.com']
email_subject = 'Current Weather'
email_message = ''
#======================================================================================
#Variable initilization
myGeo = []
myForecast = []
myTemperature = ''
myHumidity = ''
myWeatherCondition = ''
myFeelslikeT = ''
myTime = ''
#======================================================================================
while(True):
    os.system('clear')
    myGeo = myWeather.getInfo(zipCode, 'display_location')
    myTemperature = myWeather.getInfo(zipCode, 'temp_f')[0]
    myHumidity = myWeather.getInfo(zipCode, 'relative_humidity')[0]
    myWeatherCondition = myWeather.getInfo(zipCode, 'weather')[0]
    myFeelslikeT = myWeather.getInfo(zipCode,'feelslike_f')[0]
    myTime = myWeather.getInfo(zipCode,'observation_time')[0]
    myForecast = myWeather.checkForecast(zipCode)

    degrees = sensor.read_temperature()
    pascals = sensor.read_pressure()
    hectopascals = pascals / 100
    humidity = sensor.read_humidity()

    degrees = degrees * 1.8 + 32.0

    tsl = lightSensor(debug=1)
    lumen = tsl.lux()
    lumen_reco = checkLum(lumen)

    forecast = 'Expect {} in the next hour.\nChance of Rain: {}%.\n'.format(myForecast[1],myForecast[3])

    msg_outside = ('Current Weather in {}'.format(myGeo[0]) + '\n\n' +
           myTime + '\n\n' +
           'Weather: {}'.format(myWeatherCondition) + '\n' +
           'Temperature: {} F \t Feels like: {} F'.format(myTemperature, myFeelslikeT) + '\n' +
           'Humidity: {}'.format(myHumidity)
           )
    msg_home = 'Temperature = {0:0.3f} deg F'.format(degrees) + '\n' + 'Pressure = {0:0.2f} hPa'.format(hectopascals) + '\n' + 'Humidity = {0:0.2f} %'.format(humidity)  + '\n' + 'Light: {}'.format(lumen_reco)
    msg = msg_outside + '\n\n' + 'Current Condition at Home\n\n' + msg_home + '\n\n' + forecast
    badWeather = ['snow','rain','rain showers','snow showers','thunderstorm']
    for bad in badWeather:
        if myForecast[1].lower() == bad:
            myEmail.sendEmail(email_alertReceiver,'Weather Alert',forecast)
    print(msg)
    email_message = msg
    myEmail.sendEmail(email_receiver, email_subject, email_message)
    time.sleep(1200)

类库 01

#from urllib.request import urlopen
import urllib2
from bs4 import BeautifulSoup

key = 'Enter Your Own Key Here'

class readXML():
#===================================================================
    def getInfo(self, arg_zip, arg_type):
   
        zipcode = arg_zip
        type = arg_type
        info = []
        url='http://api.wunderground.com/api/' + key + '/conditions/q/' + zipcode + '.xml'
        try:
            #weather_html = urlopen(url)
      weather_html = urllib2.urlopen(url)
        except HTTPError as e:
            return ['Error', e]
        else:
            weather_obj = BeautifulSoup(weather_html.read(), 'html.parser')
            for child in weather_obj.find(type).children:
                if child.string == '\n':
                    pass
                else:
                    info.append(child.string)
            return info
#===================================================================
    def _init_(self):
        pass
#===================================================================
    def checkUV(self, arg_uv):
        info = ''
        suggestion = ''
        try:
            uv = int(arg_uv)
        except:
            return 'UV Index is not a number!'
        else:
            if uv <= 2: 
                info = 'low'
                suggestion = 'Cover up and Apply SPF 30+ sunscreen'
            elif uv > 2 and uv <=5:
                info = 'moderate'
                suggestion = 'Apply SPF 30+ sunscreen every 2 hours'
            elif uv > 5 and uv <= 7:
                info = 'high'
                suggestion = 'Reduce time in the sun between 10 a.m. and 4 p.m. \n Apply SPF 30+ sunscreen every 2 hours'
            elif uv > 7 and uv <= 10:
                info = 'very high'
                suggestion = 'Reduce time in the sun between 10 a.m. and 4 p.m. \n Apply SPF 30+ sunscreen every 2 hours'
            elif uv > 10:
                info = 'extreme'
                suggestion = 'Reduce time in the sun between 10 a.m. and 4 p.m. \n Apply SPF 30+ sunscreen every 2 hours'
            else:
                info = 'UV index out of range'
                suggestion = 'No suggestions'
#===================================================================
    def checkForecast(self, arg_zip):
        zipcode = arg_zip
  url = 'http://api.wunderground.com/api/' + key + '/hourly/q/' + zipcode +'.xml'
  myForecast = []
  tempStorage = []
  try:
      forecast_html = urllib2.urlopen(url)
  except:
      return 'Something is wrong.'
  else:
      forecast_obj = BeautifulSoup(forecast_html, 'html.parser')
      keyWord = ['hour','condition','humidity','pop']
      for entry in keyWord:
    myForecast.append(forecast_obj.find(entry).string)
      for child in forecast_obj.find('temp').children:
    if child != '\n':
              tempStorage.append(child.string)
      myForecast.append(tempStorage[0])
      tempStorage = []
      return myForecast

类库 02

import smtplib

class email():
#===================================================================
    def _init_(self):
        pass
#===================================================================
    def sendEmail(self, arg_to, arg_sub, arg_txt):
        TO = arg_to
        Subject = arg_sub
        Text = arg_txt

        gmail_sender = 'sender@gmail.com'
        gmail_pswd = 'enter password here'

        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.ehlo()
        server.starttls()
        server.login(gmail_sender,gmail_pswd)

        BODY = '\r\n'.join(['To: %s' % TO,
                    'From: %s' % gmail_sender,
                    'Subject: %s' % Subject,
                    '', Text])

        try:
            server.sendmail(gmail_sender, TO, BODY)
            return 'Sent successfully'
        except:
            return 'error sending email'

        server.quit()

Twitter

from twython import Twython

def send_tweet(arg_msg):
  consumer_key='YOUR_OWN_KEY'
  consumer_secret = 'YOUR_OWN_KEY'
  access_key = 'YOUR_OWN_KEY'
  access_secret = 'YOUR_OWN_KEY'
  verdict = 0
  api = Twython(consumer_key, consumer_secret, access_key, access_secret)
  if len(arg_msg) <= 140:
    try:
      api.update_status(status=arg_msg)
    except:
      verdict = 2
    else:
      verdict = 1
  else:
    verdict = 0
  return verdict

Smart Plug

import spx

def SmartPlug(arg_lumen, arg_currentHour):
  Night = range(16,23)
  dark = 100
  try:
    plug = spx.Smartplug('SMART_PLUG_IP')
    if arg_lumen < dark and arg_currentHour in Night:
      p.on()
    else:
      p.off()
    return 'Protocal has been successfully applied to the Smart plug'
  except:
    return 'Protocal failed to be in effect!'

同时,为了使两块传感器工作,还需要添加Adafruit I2C 的驱动器BME280驱动TSL2561驱动