
WunderGround Personal Weather Station (PWS) HOW-TO for the Davis
Weather Wizard III on Linux
Background:
Years ago while living on a mountain top at 8850ft where the winds blow
9 months a year and are sustained 60mph I purchased a Davis Weather
Wizard III. Recently I purchased a WeatherLink module and had it
connected to a Windows PC. While this was interesting I did not
what to run a PC full time just to update weather info. Another
project of mine utilized a Linksys NSLU2 NAS device with an Intel
IXP425 processor. This low power NAS device was a perfect fit for
the task. So I set off to find a way to get an unsupported
weather station to run on a special purpose device. This how-to
details what was done as well as showcases the results. You could
easily run this on a PC or other dedicated device as well.
Disclaimer:
Use the information below AT YOUR OWN RISK! I will not be held
responsible if you destroy your system during any parts of this HOW-TO.
Hardware:

About the NSLU2:
A brief overview of the device can be found here.
More detailed information can be found here.
Hardware Requirements:
- NSLU2
- External hard drive
- Weather Wizard III Station (Rain gauge optional)
- WeatherLink (Serial)
- Serial to USB dongle
The NSLU2-Linux site also shows many modifications that can be done to
the NSLU2. I performed the one located here
which doubles the processor speed. My setup also uses an old
Maxtor OneTouch hard drive.
Software Requirements:
- Debian Linux - A very detailed how-to for getting Debian running
on the NSLU2 is found here.
If you have an NSLU2 running an older version of unslung or SlugOS
instructions for upgrading can be found here.
- MySQL Server - During the installation be sure to create a root
password.
# apt-get install mysql-server-5.0 libdbd-mysql-perl
- Next create the database.
# mysql -p
Enter password:
mysql> create database meteo;
Query OK, 1 row affected
mysql> exit
Bye
- Debian build dependencies
# apt-get build-dep debian-installer
- Meteo - Information on Meteo can be found here. I seems development
has moved to a commercial version but the version available here worked
for me after modifying a bunch of files to add include statments to get
it to build on GCC 4.3.2. To save you the trouble you can
download the modified source here.
There are other dependencies which will be needed in order to get Meteo
to build successfully. Unfortunately I did not create a list but
all missing dependencies were available as standard Debian
packages. Remember apt-cache
search is your friend. If you get errors during the build
process search and install the missing packages. First let's get
the ones we know about.
# apt-get install libxml2 libxml2-dev libpng12-0 libpng12-dev libpng3 libgd2-xpm gettext gettext-base liblocate-gettext-perl
# cd your-source-dir
# tar xvf meteo-0.9.15-modified.tar
# cd meteo-0.9.15-modified
# ./configure
# make
# make install
- Create a PWS on Wunderground - Go to Wunderground and
register. Once registered login and create a personal weather
station. You will need information such as the altitude of your
station, longitiude and latitude and station name. Once you have
created the station Wunderground will give you a station ID. You
will need this to move forward.
- Next follow the instructions provided on the Meteo site to set up
the datebase here.
- Now you will need a meteo.xml file that corresponds to the
Weather Wizard III. I have created such a file and placed the
file here so you can easily see all the places where you will need to
make edits. This file is located in /usr/local/share/meteo. You should
be able to copy and past this into your editor of choise.
<!--
meteo.xml ** graph configuration file (fixes colors and scales for the
meteo graphs) This version expresses the graphs we were used
to in previous release completely in the new XML syntax.
(c) 2001 Dr. Andreas Mueller, Beratung und Entwicklung
$Id: meteo.xml,v 1.32 2004/05/08 20:09:31 afm Exp $
-->
<meteo>
<!--
database configuration
each meteo instance has exactly one database, which may hold data
for several stations (as in the sample installation, where the
database holds data for the stations in Gurin and Altendorf)
-->
<database>
<hostname>localhost</hostname>
<dbname>meteo</dbname>
<user>meteo</user>
<password>public</password>
<writer>YOUR USER NAME</writer>
<writerpassword>YOUR USER PASSWORD</writerpassword>
<!-- the msgqueue tag is required if the meteodequeue process is used,
which is highly recommended. Make sure the file referenced here
exists, as it is needed by SysV IPC to generate a msgqueue id. -->
<msgqueue>/tmp/meteodb-queue.log</msgqueue>
<!-- the updatefile tag is only necessary if the database updates
cannot be sent to a database directly. Use the file generated
by this directive to update the database off line. -->
<!-- <updatefile>file:///home/jeff/weather/meteo-queue.log</updatefile. -->
<prefix>meteo</prefix>
</database>
<!--
station configuration
for each station, define the type, the connection method (using url and
possibly speed) und the sensors. Use the meteosensors program to find out
what sensors your particular station knows about. The sensor configuration
here only affects what meteopoll will read and store in the database.
You are still free to add other data manually and use the meteodraw program
to draw graphs of this data.
Fully qualified field names are formed by the name attributes of the
station and sensor tags and the contents of the field tags. The Altendorf
station below has the following fully qualified fields:
Altendorf.inside.temperature
Altendorf.inside.humidity
Altendorf.inside.barometer
Altendorf.outside.temperature
Altendorf.outside.humidity
Altendorf.outside.rain
Altendorf.outside.wind
-->
<station name="INSERT YOUR STATION ID HERE">
<url>file:///dev/ttyUSB0</url>
<type>Wizard</type>
<speed>2400</speed>
<sensors>
<!-- each sensor name must appear in the sensor table in the db-->
<!-- each field name must appear in the mfield table in the db -->
<sensor name="inside">
<field>temperature</field>
</sensor>
<sensor name="outside">
<field>temperature</field>
<field>rain</field>
<field>wind</field>
</sensor>
</sensors>
<averages>
<sensor name="inside">
<average name="temperature" base="temperature" operator="avg"/>
<average name="temperature_min" base="temperature" operator="min"/>
<average name="temperature_max" base="temperature" operator="max"/>
</sensor>
<sensor name="outside">
<average name="temperature" base="temperature" operator="avg"/>
<average name="temperature_min" base="temperature" operator="min"/>
<average name="temperature_max" base="temperature" operator="max"/>
</sensor>
<sensor name="outside">
<average name="wind" base="wind" operator="wind"/>
<average name="winddir" base="wind" operator="avg"/>
<average name="windgust" base="wind" operator="max"/>
</sensor>
<sensor name="outside">
<average name="rain" base="rain" operator="sum"/>
<average name="raintotal" base="rain" operator="sum"/>
</sensor>
</averages>
<sun method="compute"/>
</station>
<!--
Graph configurations
Each graph has a name by which it can be referenced. The meteodraw program
uses the name look up the XML specification of the graph. The name will
be used to form the file name for the produced graph (together with the
time label), so it should be a legal part of a filename, in particular it
should not contain /, and shell metacharacters will cause file names
that are clumsy to handle in shell scripts.
-->
<graphs lockfile="lockfile" running="3" queued="10">
<graph name="INSERT YOUR STATION ID HERE.temperature-new" offset="-10800"
height="300" width="600" bgcolor="#ffffff" fgcolor="#000000">
<!-- label and axis definitions -->
<leftlabel align="center">Temperatur grad F</leftlabel>
<rightlabel align="center">relative Humidity %</rightlabel>
<leftaxis type="dynamic" maxname="tt" minname="dd" min="-100" max="100"
origin="0" maxtickcount="20"
first="-100"
last="100" step="10" format="%.1f" ticks="yes" gridlines="yes"/>
<rightaxis min="0" max="100" first="0" last="100" step="20" format="%3.0f"
ticks="yes" gridlines="no"/>
<!-- the graphwindow tag defines the area inside the image where the
data will be plotted -->
<graphwindow llx="55" lly="19" urx="545" ury="293"/>
<!-- the channels contains the query definitions that tell meteodraw
how to retrieve the data from the database, and give it symbolic
names, and thq channel tags that describe how the data should
be plotted -->
<channels>
<!--
the query tag describes how data has to be retrived and modified
before graphing.
-->
<query>
<!-- give certain data sets in the DB a symbolic name -->
<select name="t">ENTER YOUR STATION ID HERE.temperature</select>
<select name="tmax">ENTER YOUR STATION ID HERE.temperature_max</select>
<select name="tmin">ENTER YOUR STATION ID HERE.temperature_min</select>
<!-- perform some arithmetic on the data sets, give the result
again a symbolic name -->
<data name="tt">
<function name="floor" limit="-50">
<function name="ceil" limit="50">
<value name="t"/>
</function>
</function>
</data>
</query>
<!-- draw graphs for the datasets as specified in the previous tags -->
<channel color="#aaaaff" type="range" scale="left"
namelower="dewpointmin" nameupper="dewpointmax"/>
<channel color="#0000ff" type="curve" scale="left" name="dewpoint"/>
<channel color="#ffaaaa" type="range" scale="left"
namelower="tmin" nameupper="tmax"/>
<channel color="#654321" type="curve" scale="left" name="tt"/>
<channel color="#dddddd" type="nodata" name="t"/>
</channels>
</graph>
<!-- Temperature graph -->
<graph name="ENTER YOUR STATION ID HERE.temperature_outside" offset="-25200"
height="288" width="600" bgcolor="#ffffff" fgcolor="#000000">
<leftlabel align="center">Temperature (deg F)</leftlabel>
<leftaxis type="static" min="-15" max="110"
first="-10" last="100" step="10" format="%.0f"
ticks="yes" gridlines="yes"/>
<graphwindow llx="55" lly="19" urx="556" ury="278"/>
<channels>
<query>
<select name="t">ENTER YOUR STATION ID HERE.outside.temperature</select>
<select name="tmin">ENTER YOUR STATION ID HERE.outside.temperature_min</select>
<select name="tmax">ENTER YOUR STATION ID HERE.outside.temperature_max</select>
</query>
<channel color="#ffb4b4" type="range" scale="left"
nameupper="tmax" namelower="tmin"/>
<channel color="#b40000" type="curve" scale="left" name="t"/>
<channel color="#e6e6e6" type="nodata" name="t"/>
</channels>
</graph>
<!-- inside Temperature graph -->
<graph name="ENTER YOUR STATION ID HERE.temperature_inside" offset="-25200"
height="288" width="600" bgcolor="#ffffff" fgcolor="#000000">
<leftlabel align="center">Temperature (deg F)</leftlabel>
<leftaxis type="static" min="40" max="100"
first="50" last="90" step="10" format="%.0f"
ticks="yes" gridlines="yes"/>
<graphwindow llx="55" lly="19" urx="556" ury="278"/>
<channels>
<query>
<select name="t">ENTER YOUR STATION ID HERE.inside.temperature</select>
<select name="tmin">ENTER YOUR STATION ID HERE.inside.temperature_min</select>
<select name="tmax">ENTER YOUR STATION ID HERE.inside.temperature_max</select>
</query>
<channel color="#ffb4b4" type="range" scale="left"
nameupper="tmax" namelower="tmin"/>
<channel color="#b40000" type="curve" scale="left" name="t"/>
<channel color="#e6e6e6" type="nodata" name="t"/>
</channels>
</graph>
<!-- Wind -->
<graph name="ENTER YOUR STATION ID HERE.wind" offset="-25200"
height="288" width="600" bgcolor="#ffffff" fgcolor="#000000">
<leftlabel align="center">Speed (mph)</leftlabel>
<rightlabel align="center">Azimut (deg) 360=N 270=W 180=S 90=E</rightlabel>
<leftaxis type="static" min="0" max="100"
first="0" last="50" step="5" format="%.0f"
ticks="yes" gridlines="yes"/>
<rightaxis type="static" min="-540" max="360"
first="0" last="360" step="180" format="%.0f"
ticks="yes" gridlines="yes"/>
<graphwindow llx="55" lly="19" urx="556" ury="278"/>
<channels>
<query>
<select name="azi">ENTER YOUR STATION ID HERE.outside.winddir</select>
<select name="v">ENTER YOUR STAATION ID HERE.outside.wind</select>
<select name="vmax">ENTER YOUR STATION ID HERE.outside.windgust</select>
</query>
<!-- note that there are some cultural differences with the wind
letters below. In Switzerland, Nordwind means wind _from_ the
north, which is wind with azimut 180deg. In other places, the
letters may be interpreted just the other way round, so you
will prefer to use letters="NESW" (pointed out by Mark Trettin)
-->
<channel type="windbackground" scale="right"
northcolor="#e0e0ff" southcolor="#ffe0e0"
westcolor="#e0ffe0" eastcolor="#ffffc8"
letters="SWNE" />
<channel color="#6464ff" type="curve" scale="right" name="azi"/>
<channel color="#006400" type="histogram" scale="left" name="vmax"/>
<channel color="#00ff00" type="histogram" scale="left" name="v"/>
<channel color="#ffffff" type="lowdata" name="vmax" limit="0.1"/>
<channel color="#e6e6e6" type="nodata" name="azi"/>
</channels>
</graph>
<!-- Rain -->
<graph name="ENTER YOUR STATION ID HERE.rain" offset="-25200"
height="288" width="600" bgcolor="#ffffff" fgcolor="#000000">
<leftlabel align="center">Precipitation (in)</leftlabel>
<rightlabel align="center">Total rain (in)</rightlabel>
<leftaxis interval="300" type="static" min="0" max="6"
first="0" last="6" step="1" format="%.0f"
ticks="yes" gridlines="yes"/>
<leftaxis interval="1800" type="static" min="0" max="10"
first="0" last="10" step="2" format="%.0f"
ticks="yes" gridlines="yes"/>
<leftaxis type="static" min="0" max="30"
first="0" last="30" step="10" format="%.0f"
ticks="yes" gridlines="yes"/>
<rightaxis type="dynamic" minname="totalrain" maxname="totalrain"
origin="0" maxtickcount="10" step="10" ticks="yes" gridlines="no"
format="%3.0f" />
<graphwindow llx="55" lly="19" urx="556" ury="278"/>
<channels>
<query>
<select name="rain">COSUPER9.outside.rain</select>
<data name="totalrain">
<function name="accumulate">
<value name="rain"/>
</function>
</data>
</query>
<channel color="#0000ff" type="histogram" scale="left" name="rain"/>
<channel color="#00ffff3f" type="curve" scale="right" name="totalrain"/>
<channel color="#f3f3f33f" type="nodata" name="rain"/>
</channels>
</graph>
<!-- observatory graphs -->
<graph name="OBS.outside"
height="144" width="500" bgcolor="#ffffff" fgcolor="#000000">
<leftlabel align="center">moisture</leftlabel>
<rightlabel align="center">clouds</rightlabel>
<leftaxis type="static" min="0" max="100" first="0" last="100"
step="10" format="%.0f" ticks="yes" gridlines="yes"/>
<rightaxis type="static" min="0" max="100" first="0" last="100"
step="10" format="%.0f" ticks="yes" gridlines="yes"/>
<graphwindow llx="55" lly="19" urx="455" ury="139"/>
<channels>
<query>
<select name="m">OBS.outside.moist</select>
<select name="c">OBS.outside.clouds</select>
</query>
<channel color="#00ff00" type="curve" scale="left" name="m"/>
<channel color="#ff0000" type="curve" scale="right" name="c"/>
</channels>
</graph>
</graphs>
</meteo>
- Next start the meteopoll process. This is the main process
that communicates with the station and enters data into the
database. There are a number of flags which we will need to
use.
# meteopoll -s YOUR_STATION_ID -f /usr/local/share/meteo/meteo.xml -l file:///var/log/meteo.log -b mysql -m /path/to/mapfile
Here the -m flag instructs Meteo to generate the mapfile which
is an XML file created every minute. The mapfile is used to
determine some of the values to be uploaded to Wunderground. You will
need to run Meteo with the mapfile for the upload program to
work. You should see two meteopoll process running. This is
normal.
- Next download the meteo-wu-wizard.pl program here
and edit to match your configuration where indicated. Then make
the program executable.
# chmod +x meteo-wu-wizard.pl
- Finally add a cron entry to run the meteo-wu-wizard.pl program.
I find that the best update interval is 5 minutes. You can go
shorter but risk the NSLU2 thrashing out of control if they are too
short. On a standard PC the interval could be < 1 minute.
# m h dom mon dow command
*/5 * * * * /usr/bin/perl /path/to/meteo-wu-wizard.pl > /dev/null 2&>1
Notes:
If you have trouble check the logs first! Run meteopoll with the
debug level turned up. man meteopoll to find out how to do this.
Meteo is a very flexable program. If you want to create your own
.png images files you should see the meteoavg man page. There are
also other useful tools in the /usr/local/bin folder reated to the
inner workings of Meteo. Have a look if you are interested.
Also I am not a programmer. I'm a hacker. This is the
method I used to get things working. If you have a better one
that's free let me know. If you find errors in my code let me
know and I'll update this HOW-TO. (jeff at markleyhut . com)
If you found this HOW-TO useful and are using the upload program
please HELP A BROTHER OUT and
donate!
Troubleshooting:
One area to check if things ar not working is to make sure the
temperature unit values in the mfield table is set correctly.
Also check that the ID's for the other wind and rain values match what
is in the meteo.xml file. Mine are as follows:
mysql> select * from mfield;
+-----------------+-----+-------+-------------------+
| name | id | unit | class |
+-----------------+-----+-------+-------------------+
| temperature | 0 | F | TemperatureValue |
| temperature_min | 1 | F | TemperatureValue |
| temperature_max | 2 | F | TemperatureValue |
| humidity | 10 | % | HumidityValue |
| humidity_max | 11 | % | HumidityValue |
| humidity_min | 12 | % | HumidityValue |
| wetness | 20 | index | LeafwetnessValue |
| wetness_min | 21 | index | LeafwetnessValue |
| wetness_max | 22 | index | LeafwetnessValue |
| barometer | 30 | inHg | PressureValue |
| barometer_min | 31 | inHg | PressureValue |
| barometer_max | 32 | inHg | PressureValue |
| solar | 40 | W/m2 | SolarValue |
| uv | 41 | index | UVValue |
| rain | 50 | in | Rain |
| raintotal | 51 | in | Rain |
| rainrate | 52 | in/h | RainRate |
| wind | 60 | mph | Wind |
| winddir | 61 | deg | NULL |
| windgust | 62 | mph | WindSpeed |
| windx | 63 | mph | NULL |
| windy | 64 | mph | NULL |
| moisture | 70 | cb | MoistureValue |
| waterlevel | 71 | m | LevelValue |
| waterlevel_min | 72 | m | LevelValue |
| waterlevel_max | 73 | m | LevelValue |
| sunrise | 100 | unix | TimeValue |
| sunset | 101 | unix | TimeValue |
| battery | 110 | V | VoltageValue |
| transmitter | 111 | V | TransmitterStatus |
| duration | 120 | s | NULL |
| samples | 121 | | NULL |
+-----------------+-----+-------+-------------------+
My Station table looks like this:
mysql> select * from sensor;
+---------+----+-----------+
| name | id | stationid |
+---------+----+-----------+
| inside | 0 | 1 |
| outside | 1 | 1 |
| rain | 2 | 1 |
| wind | 3 | 1 |
| console | 4 | 2 |
| iss | 5 | 2 |
| soil1 | 6 | 2 |
| console | 7 | 3 |
+---------+----+-----------+
Copyright
© 2012 Jeff Markley