Contents
About the Site
Some stuff about the site - as with my main site, the details are the same:
Site
This is a static HTML site created using Alexis Métaireau's Pelican static blog generator with all items starting their life written in reStructuredText.
Theme
Using Daan Debie's pelican-Bootstrap3. I would recommend this as it is very extensible and full of useful configurations options - in short, it is awesome!
In addition because this theme supports bootswatch I am using Thomas Park's simplex bootstrap theme extension.
Graphs
This site makes extensive use of HighCharts, written in JavaScript.
Weather Observation Hardware and Software
Hardware
All the Weather Report data is sampled and provided by a Maplin WH1080 weather station. The Soil Temperature data is collected by my own soil temperature monitoring system, which became operational in late 2014. Data from the various systems is stored and processed by a Raspberry Pi - the credit card sized ARM based single board computer.
Software
The Raspberry Pi runs Raspbian OS as its core operating system. The weather station data is retrieved and collated with the help of pywws software, written and maintained by Jim Easterbrook. All other software functionalities for the data gathering, both on a Pi and a Linux box are provided by a couple of Python based personal projects hosted at Bitbucket.
Code Samples
Below are a few code samples. Have fun.
Dew Point Calculation
Below is a sample of the Python code I use to derive the dew point temperature. It uses two separate samples from the weather station: air temperature and external relative humidity. I am indebted to Rob Tillaart, whose C code I originally borrowed the formula from.
def dewpoint(temperature, humidity):
"""
Dew point function NOAA - returns dew point, as calculated from
temperature and relative humidity.
Reference (1): http://playground.arduino.cc/main/DHT11Lib
Reference (2): http://wahiduddin.net/calc/density_algorithms.htm
Reference (3): http://www.colorado.edu/geography/weather_station/Geog_site/about.htm
"""
try:
# Cast them, just in case
tempf = float(temperature)
humf = float(humidity)
except ValueError as error:
return ''
else:
# (2) Saturation Vapour Pressure = ESGG(T)
ratio = 373.15 / (273.15 + tempf)
rhs = -7.90298 * (ratio - 1)
rhs += 5.02808 * math.log10(ratio)
rhs += -1.3816e-07 * (pow(10, (11.344 * (1 - 1/ratio))) - 1)
rhs += 8.1328e-3 * (pow(10, (-3.49149 * (ratio - 1))) - 1)
rhs += math.log10(1013.246)
# factor -3 is to adjust units - Vapour Pressure SVP * humidity
vapourpressure = pow(10, rhs - 3) * humf;
# (3) DEWPOINT = F(Vapour Pressure)
dwpt = math.log(vapourpressure/0.61078)
# Done
return (241.88 * dwpt) / (17.558 - dwpt)
Pressure at Station Calibration
In order to keep my weather station relative pressure reading accurate, I get the system to periodically recalibrate against a known and trusted source. In this case, EGNJ, my local airport gives out a METAR information feed, which looks something like this:
EGNJ 301920Z 01009KT 9999 FEW012 SCT016 BKN032 11/09 Q1016
The Qnnnn code at the end of the METAR data above is the current altimeter setting - the mean sea level pressure in millibars (or hPA if you prefer). There are web sites out there which will pick up the METAR feeds and publish them on the net, such as aviatorjoe, the one I use.
import feedparser
import metar.Metar
import math
def pressure_reference(local_alt, airport_code, air_temp=15.0):
"""
Returns a reference MSLP pressure from a local METAR feed - usually provided
by a nearby airport.
local_alt is your weather station altitude from sea level in metres.
airport_code is the ICAO 4 letter code (in my case, EGNJ).
air_temp is the local air temperature and defaults to 15C if not supplied
"""
# Get the MSLP from the METAR feed
airport = 'http://rss.aviatorjoe.net/3/{0}.rss'.format(airport_code)
feed = feedparser.parse(airport)
try:
summ = feed.entries[0]['summary']
data = metar.Metar.Metar(summ)
airport_mslp = data.press.value()
abs_press = (1-(local_alt*0.0065)/(air_temp+(0.0065*local_alt)+273.15))
abs_press = abs_press**-5.275
except Exception:
return -1
else:
return math.ceil(airport_mslp/abs_press*10)/10
The above, is buried in calling code in a file called run.py - this in turn is called by the exceedingly simple script below:
#!/bin/bash
OUTPUT=$(python /home/pi/wsdatproc/run.py press_ref)
if [ $OUTPUT -ne -1 ]
then
/usr/local/bin/pywws-setweatherstation --pressure $OUTPUT
fi
Environmental Lapse Rate Calculation
As mentioned on the weather report page, this is really just a little bit of fun - there is no intention of presenting the freeze altitude in a scientifically accurate manner implied here. In order to underline the inaccuracy of the whole enterprise, some heavy rounding takes place to keep the numbers looking sensible. There is no point in estimating the freezing level at three thousand metres to the nearest millimetre! Please excuse the code; it is rather mundane and makes a huge number of assumptions.
import math
def calc_elr(air_temp):
"""
Returns environmental lapse rate dependent on temperature
See: http://en.wikipedia.org/wiki/Lapse_rate#Environmental_lapse_rate
Treat this with the caveats within the documentation above.
elr = 1000/6.49
"""
if air_temp <= 0.0:
return 0
res = round(float(air_temp) * 1000/6.49, 2)
# Round to nearest 10 if greater than 1000m
if res > 1000:
return math.ceil(res / 10.0) * 10
# Round to nearest 1 if greater than 100m
if res > 100:
return math.ceil(res / 1.0) * 1
# Round to nearest 0.1 if greater than 10m
if res > 10:
return round(res, 1)
return res