Monday, February 29, 2016

Weather Station

I decided to pick this project up again after it got interrupted by my move to San Francisco. I have a couple weeks between jobs and thought I could get this working in that time frame.
The goal is to make a solar powered Raspberry Pi weather station with accompanying website (available here). The weather station would take a picture of the view from the roof of my apartment building every 10 seconds, posting that picture on the website. Additionally a temperature and humidity sensor would take data and store it on google spreadsheets at the same rate. A graph of this would be visible on the website. At night the Pi would take all the pictures and make a timelapse video of the day, upload that to youtube and that video would display on the front page of the website.
 A lot to promise!

Today's post is a bit dry as it is entirely code, but if you are interested in doing something similar yourself, it will be useful.

As of today, I have code that can...
  • take data from the temperature and humidity sensor (Available Here)
  • write data to google spreadsheets
  • take a picture with the picamera
  • store that picture on dropbox

I am working on writing code to...

  • take a set of jpeg images and create a .mov (hopefully using ffmpeg)
  • upload that .mov to youtube
  • managing the images (will delete each day's pictures from local storage)
  • schedule everything using crontab

I will get to writing the code for...

  • the entire website
  • managing dropbox's images (I would run out of space in about 10 days without managing storage).


So I'll start by documenting what I have done.


Interfacing With The DHT22 Sensor

This took a lot of trial and error. I ended up finding this tutorial and, while the website looks ridiculous, it worked like a charm!

Bash commands / packages to install:

sudo apt-get install git
cd ~
git clone https://github.com/adafruit/Adafruit_Python_DHT.git
cd Adafruit_Python_DHT
sudo apt-get update
sudo apt-get install build-essential python-dev
sudo python setup.py install


Python code:

import Adafruit_DHT as dht 
import datetime 
h,t = dht.read_retry(dht.DHT22, 4)


Writing Data To Google Sheets

First, create a spreasheet where your data will sit. Delete all but one row (there are only 1000 rows so if you delete rows 2-1000 you will be left with only the first row).

Next is a bit tricky because while Google updates its APIs regularly it doesn't, apparently, always keep its documentation up to date. I followed google's own documentation (found here), but ran into problems. Two hours later, I found the solution here.

So, if you are doing this yourself, follow the google tutorial, just replace the python in step 6 with what I have below (with certain things replaced to refer to your own project, of course).

Bash commands / packages to install:

pip install PyOpenSSL pip install --upgrade oauth2client

Python code:

import json
import gspread from oauth2client.service_account 
import ServiceAccountCredentials 

#The following refers to the json file created by google. It must be placed in the same directory as this script.

json_key = 'WeatherStation-41a4ca0f181e.json' #replace with your own

scope = ['https://spreadsheets.google.com/feeds']

#this service account credentials part was what was not documented.
credentials = ServiceAccountCredentials.from_json_keyfile_name(json_key, scope)

gc = gspread.authorize(credentials)
sht = gc.open('WeatherStationData') #the name of the spreadsheet
wrksht = sht.worksheet('Sheet1') #the name of the worksheet

wrksht.append_row([datetime.datetime.now(), t, h]) #append the data


Picamera

This is well documented and easy to use. All information can be found here.
I chose to use the date and time as the file name for a couple of reasons. One is that the pictures have a lot to do with time, so if I ever need to find one taken at a particular time, I search by file name. The other reason is that the date and time is always unique so I know I won't have any file naming errors.
However, if you do use datetime.datetime.now() you have to do two things:

  1. Change the date and time of your pi to local time from Universal Time (for your convenience and sanity)
  2. Replace all strange characters like ':' with '_' so you make sure you know the naming format
I did a little more with naming and replaced all non-numeric characters with '_' and removed the sub-second digits as they were not necessary for this project.

Bash commands / packages to install:


Enable picamera
sudo raspi-config


Change date and time
sudo dpkg-reconfigure tzdata


Install picam library
sudo apt-get update
sudo apt-get install python-picamera


Note: This is for python 2.7. If you want to use python 3, read the tutorial.


Python code:

import picamera 
import datetime 

#define filename as year_month_day_hour_minute_second.jpg
temp = str(datetime.datetime.now()) 
print temp file_name = '' 
for char in temp: 
     if char == ":" or char == "-" or char == " ": #want to replace all with '_'
          file_name += "_" 
     elif char == ".": #exclude fractional seconds
          break
     else: file_name += char
file_name += ".jpg" 

#take picture 
camera = picamera.PiCamera() 
camera.capture(file_name)


Storing Picture on Dropbox

This takes a little extra than just the dropbox api. This tutorial walks you through the entire procedure in painful detail. So painful, in fact, that I won't rehash it here.

Bash commands / packages to install:


Read the tutorial!

Python code:

from subprocess import call
photofile = "/home/pi/Documents/weatherprojects/Dropbox-Uploader/dropbox_uploader.sh upload /home/pi/Documents/weatherprojects/{} {}".format(file_name, file_name) 
call ([photofile], shell=True)


That's all for now!