mirror of
https://github.com/weewx/weewx.git
synced 2026-04-18 00:26:57 -04:00
3616 lines
152 KiB
HTML
3616 lines
152 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml">
|
|
|
|
<!-- $Revision$ -->
|
|
<!-- $Author$ -->
|
|
<!-- $Date$ -->
|
|
<!-- For some reason, the table of contents generator used in this document demands that all
|
|
heading elements be on one line. -->
|
|
|
|
<head>
|
|
<meta content="en-us" http-equiv="Content-Language" />
|
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
|
<title>weewx: Customization Guide</title>
|
|
<!-- CSS -->
|
|
<link href="weewx_docs.css" rel="stylesheet" />
|
|
<!-- JavaScript -->
|
|
<script src="samaxesjs.toc-1.5.min.js" type="text/javascript"></script>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1 class="title">Customizing weewx<br />
|
|
Version: 2.2
|
|
</h1>
|
|
<h1>Table of contents</h1>
|
|
<div id="technical_content">
|
|
<div id="toc">
|
|
</div>
|
|
<h1 id="Copyright">Copyright</h1>
|
|
<p>(c) 2009, 2010, 2011, 2012, 2013 by Tom Keffer <<a href="mailto:tkeffer@gmail.com">tkeffer@gmail.com</a>>
|
|
</p>
|
|
<p>This program is free software: you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
Foundation, either version 3 of the License, or (at your option) any later version.
|
|
</p>
|
|
<p>This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
</p>
|
|
<p>You should have received a copy of the GNU General Public License along with
|
|
this program. If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses</a>.
|
|
</p>
|
|
<h1 id="Introduction">Introduction</h1>
|
|
<p>This document covers the customization of <span class="code">weewx</span>.
|
|
It assumes that you have read and are reasonably familiar with the
|
|
<a href="usersguide.htm">Users Guide</a>. </p>
|
|
<p>It starts with an overview of the architecture of weewx. If you are only
|
|
interested in customizing the generated reports you can probably skip the overview
|
|
and proceed directly to the section <em>
|
|
<a href="#The_Standard_skin_configuration_file">The Standard skin configuration
|
|
file</a></em>. With this approach you can easily add new plot images, change
|
|
the titles of images, change the units used in the reports, and so on. </p>
|
|
<p>However, if your goal is a specialized application, such as adding alarms,
|
|
RSS feeds, etc., then it would be worth your while to read about the internal
|
|
architecture and how to customize it. </p>
|
|
<p>Most of the guide will cover any weather hardware, but the exact data types
|
|
are specific to the Davis Vantage series. Unless you are using an unusual type
|
|
you are unlikely to run into trouble. </p>
|
|
<h2>Warning</h2>
|
|
<p><span class="code">weewx</span> is still an experimental system and, as such,
|
|
its internal design is subject to change. Be prepared to do updates to any code
|
|
or customization you do! </p>
|
|
<h2>Overview of the weewx architecture</h2>
|
|
<p>At a high-level, <span class="code">weewx</span> consists of an engine class
|
|
called <span class="code">StdEngine</span>. It is responsible for loading "<em>services</em>",
|
|
then arranging for them to be called when key events occur, such as the arrival
|
|
of LOOP data. The default install of <span class="code">weewx</span> includes
|
|
the following services: </p>
|
|
<table class="center" style="width: 60%" summary="Overview of the weewx architecture">
|
|
<tr>
|
|
<td class="text_highlight">Service</td>
|
|
<td><strong>Function</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdConvert</td>
|
|
<td>Converts the units of the input to a target unit system (such as
|
|
US or Metric).</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdCalibrate</td>
|
|
<td>Adjust new LOOP and archive packets using calibration expressions.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdQC</td>
|
|
<td>Check quality of incoming data, making sure values fall within a
|
|
specified range.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdArchive</td>
|
|
<td>Archive any new data to the SQL databases.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdTimeSynch</td>
|
|
<td>Arrange to have the clock on the station synchronized at regular
|
|
intervals.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdPrint</td>
|
|
<td>Print out new LOOP and archive packets on the console.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdRESTful</td>
|
|
<td>Start a thread to manage
|
|
<a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">
|
|
RESTful</a> (simple stateless client-server protocols) connections;
|
|
such as those used by the Weather Underground or CWOP.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdReport</td>
|
|
<td>Launch a new thread to do report processing after a new archive
|
|
record arrives. Reports do things such as generate HTML files, generate
|
|
images, or FTP/rsync files to a web server. New reports can be added
|
|
easily by the user.</td>
|
|
</tr>
|
|
</table>
|
|
<p>It is easy to extend old services or to add new ones. The source distribution
|
|
includes an example new service called "<span class="code">MyAlarm</span>,"
|
|
which sends an email when an arbitrary expression evaluates
|
|
<span class="code">True</span>. These advanced topics are covered later in the
|
|
section <em><a href="#Customizing_the_weewx_service_engine">Customizing the
|
|
weewx service engine</a></em>. </p>
|
|
<h3 id="The_standard_reporting_service,_StdReportService">The standard reporting
|
|
service, <span class="code">StdReport</span></h3>
|
|
<p>For the moment, let us focus on the last service, <span class="code">weewx.wxengine.StdReport</span>,
|
|
the standard service for creating reports. This will be what most users will
|
|
want to customize even if it means changing just a few options. </p>
|
|
<h4>Reports</h4>
|
|
<p>The Standard Report Service runs zero or more <em>Reports.</em> Which reports
|
|
get run is set in the configuration file <span class="code">weewx.conf</span>,
|
|
in section <span class="code">[StdReport]</span>. </p>
|
|
<p>The default distribution of weewx includes two reports: </p>
|
|
<table class="center" style="width: 60%" summary="Standard reports included in weewx">
|
|
<tr>
|
|
<td class="text_highlight"><strong>Report</strong></td>
|
|
<td><strong>Default functionality</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">StandardReport</td>
|
|
<td>Generates day, week, month and year "to-date" summaries
|
|
in HTML, as well as the plot images to go along with them. Also generates
|
|
NOAA monthly and yearly summaries. </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">FTP</td>
|
|
<td>Arranges to upload everything in the <span class="code">public_html</span>
|
|
subdirectory up to a remote webserver.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">RSYNC</td>
|
|
<td>Like FTP, but uses rsync for transferring files to a remote webserver.</td>
|
|
</tr>
|
|
</table>
|
|
<p>Note that the FTP and RSYNC "reports" are a funny kind of report
|
|
in that it they don't actually generate anything. Instead, they use the
|
|
reporting service engine to arrange for things to be transferred to a remote
|
|
server. </p>
|
|
<h4>Skins</h4>
|
|
<p>Each report has a <em>Skin</em> associated with it. For most reports, the
|
|
relationship with the skin is an obvious one: it contains the templates, any
|
|
auxiliary files such as background GIFs or CSS style sheets, and a <em>skin
|
|
configuration file</em>, <span class="code">skin.conf</span>. If you will, the
|
|
skin controls the <em>look and feel </em>of the report. Note that more than
|
|
one report can use the same skin. For example, you might want to run a report
|
|
that uses US Customary units, then run another report against the same skin,
|
|
but using metric units and put the results in a different place. All this is
|
|
possible by either overriding configuration options in the weewx configuration
|
|
file <span class="code">weewx.conf</span> or the skin configuration file
|
|
<span class="code">skin.conf</span>. </p>
|
|
<p>Like all reports, the FTP and RSYNC "Reports" also use a skin,
|
|
and include a skin configuration file, although they are quite minimal. </p>
|
|
<p>Skins live in their own subdirectory located in <span class="code"><em>$HTML_ROOT</em>/skins</span>.
|
|
</p>
|
|
<h4>Generators</h4>
|
|
<p>To create their output, skins rely on one or more <em>Generators, </em>code
|
|
that actually create useful things such as HTML files or plot images. Generators
|
|
can also copy files around or FTP/rsync them to remote locations. The default
|
|
install of <span class="code">weewx </span>includes the following generators:
|
|
</p>
|
|
<table class="center" style="width: 60%" summary="Generators included in weewx">
|
|
<tr>
|
|
<td class="text_highlight">Generator</td>
|
|
<td><strong>Function</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.filegenerator.FileGenerator</td>
|
|
<td>Generates files from templates. Used to generate HTML and text files.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.imagegenerator.ImageGenerator</td>
|
|
<td>Generates graph plots.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.reportengine.FtpGenerator</td>
|
|
<td>Uploads data to a remote server using FTP.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.reportengine.RsyncGenerator</td>
|
|
<td>Uploads data to a remote server using rsync.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.reportengine.CopyGenerator</td>
|
|
<td>Copies files locally.</td>
|
|
</tr>
|
|
</table>
|
|
<p>Note that the three generators <span class="code">FtpGenerator</span>,
|
|
<span class="code">RsyncGenerator</span>, and <span class="code">CopyGenerator</span>
|
|
don't actually generate anything having to do with the presentation layer.
|
|
Instead, they just move files around. </p>
|
|
<p>Which generators are to be run for a given skin is specified in the skin's
|
|
configuration file <span class="code">skin.conf</span>, in section
|
|
<span class="code">[Generators]</span>.</p>
|
|
<h2 id="Databases">Databases</h2>
|
|
<p>There are two databases used by <span class="code">weewx</span>, which can
|
|
be implemented either by using <a href="http://www.sqlite.org/">SQLITE3</a>,
|
|
an open-source, lightweight SQL database, or <a href="http://www.mysql.com/">
|
|
MySQL</a>, an open-source, full-featured database server, or some combination
|
|
of the two of them.</p>
|
|
<ul>
|
|
<li>The <em>archive database</em>, given symbolic name '<span class="code">archive_database</span>'.
|
|
It is a big flat table, one record for each archive interval, keyed by
|
|
<span class="code">dateTime</span>, the time at the end of the archive interval.
|
|
</li>
|
|
<li>The <em>statistical database</em>, given symbolic name '<span class="code">stats_database</span>'.
|
|
It consists of a separate table for each observation type (that is, one
|
|
for '<span class="code">outTemp</span>', one for '<span class="code">barometer</span>',
|
|
etc.), each containing one record per day, keyed by the start time of the
|
|
day. </li>
|
|
</ul>
|
|
<p>How these abstract databases are bound to the real database is covered in
|
|
the <a href="usersguide.htm">Weewx User's Guide</a>, in section '<a href="usersguide.htm#[StdArchive]">[StdArchive]</a>'.</p>
|
|
<p>The important thing to remember is that the archive database contains a record
|
|
for every archive interval and, as such, represents the c<em>urrent conditions</em>
|
|
at the time of the observation. By contrast, the statistical database represents
|
|
the <em>aggregation of conditions over a day</em>. That is, it contains the
|
|
daily minimum, maximum, and the time of the minimum and maximum, for each observation
|
|
type. As you can imagine, the statistical database is much smaller because it
|
|
represents only a summary of the data. </p>
|
|
<p>The archive database is used for both generating plot data and in template
|
|
generation (where it appears as tag <span class="code">$current</span>). The
|
|
statistical database is used only in template generation (where it appears as
|
|
tags <span class="code">$day</span>, <span class="code">$week</span>,
|
|
<span class="code">$month</span>, <span class="code">$year</span>, and
|
|
<span class="code">$rainyear</span>, depending on the aggregation time period).
|
|
</p>
|
|
<h1 id="Opportunities_for_customizing_reports">Opportunities for customizing
|
|
reports</h1>
|
|
<p>This section discusses the two general strategies for customizing reports:
|
|
by changing options in one or more configuration file, or by changing the template
|
|
files. The former is generally easier, but occasionally the latter is necessary.
|
|
</p>
|
|
<h2>Changing options</h2>
|
|
<p>Changing an option means either modifying the main configuration file
|
|
<span class="code">weewx.conf</span>, or the skin configuration file for the
|
|
standard skin that comes with the distribution (nominally, file
|
|
<span class="code">skins/Standard/skin.conf</span>). </p>
|
|
<h3>Changing options in <span class="code">skin.conf</span></h3>
|
|
<p>With this approach, the user edits the skin configuration file for the standard
|
|
skin that comes with <span class="code">weewx</span>, located in
|
|
<span class="code"><em>$WEEWX_ROOT</em>/skins/Standard/skin.conf</span>, using
|
|
a text editor. For example, suppose you wish to use metric units in the presentation
|
|
layer, instead of the default US Customary Units. The section that controls
|
|
units is <span class="code">[Units][[Groups]]</span>. It looks like this:
|
|
</p>
|
|
<pre>
|
|
[Units]
|
|
[[Groups]]
|
|
group_altitude = foot
|
|
group_degree_day = degree_F_day
|
|
group_direction = degree_compass
|
|
group_moisture = centibar
|
|
group_percent = percent
|
|
group_pressure = inHg
|
|
group_radiation = watt_per_meter_squared
|
|
group_rain = inch
|
|
group_rainrate = inch_per_hour
|
|
group_speed = mile_per_second
|
|
group_speed2 = mile_per_second2
|
|
group_temperature = degree_F
|
|
group_uv = uv_index
|
|
group_volt = volt</pre>
|
|
<p> </p>
|
|
<p>To use metric units, you would edit this section to read: </p>
|
|
<pre>
|
|
[Units]
|
|
[[Groups]]
|
|
<span class="highlight"> group_altitude = meter</span>
|
|
<span class="highlight"> group_degree_day = degree_C_day </span>
|
|
group_direction = degree_compass
|
|
group_moisture = centibar
|
|
group_percent = percent
|
|
<span class="highlight"> group_pressure = mbar</span>
|
|
group_radiation = watt_per_meter_squared
|
|
<span class="highlight"> group_rain = mm</span>
|
|
<span class="highlight"> group_rainrate = mm_per_hour</span>
|
|
<span class="highlight"> group_speed = meter_per_second</span>
|
|
<span class="highlight"> group_speed2 = meter_per_second2</span>
|
|
<span class="highlight"> group_temperature = degree_C</span>
|
|
group_uv = uv_index
|
|
group_volt = volt</pre>
|
|
<p>The options that were changed have been <span class="highlight">highlighted</span>.
|
|
Details of the various unit options are given in <em><a href="#Units">Appendix
|
|
B: Units</a></em>. </p>
|
|
<p>Other options are available, such as changing the text label for various
|
|
observation types. For example, suppose your weather console is actually located
|
|
in a barn, not indoors, and you want the plot for the temperature at the console
|
|
to be labeled "Barn Temperature," rather than the default "Inside
|
|
Temperature." This can be done by changing the "<span class="code">inTemp</span>"
|
|
option located in section <span class="code">[Labels][[Generic]]</span> from
|
|
the default </p>
|
|
<pre>
|
|
[Units]
|
|
[[Generic]]
|
|
inTemp = Inside Temperature
|
|
outTemp = Outside Temperature
|
|
...</pre>
|
|
<p>to: </p>
|
|
<pre>
|
|
[Units]
|
|
[[Generic]]
|
|
<span class="highlight"> inTemp = Barn Temperature</span>
|
|
outTemp = Outside Temperature
|
|
...</pre>
|
|
<h3>Overriding options in <span class="code">skin.conf</span> from
|
|
<span class="code">weewx.conf</span></h3>
|
|
<p>This approach is very similar, except that instead of changing the skin configuration
|
|
file directly, you override its options by editing the main configuration file,
|
|
<span class="code">weewx.conf</span>. The advantage of this approach is that
|
|
you can use the same skin to produce several different output, each with separate
|
|
options. </p>
|
|
<p>Revisiting our example, suppose you want two reports, one in US Customary,
|
|
the other in Metric. The former will go in the directory <span class="code">
|
|
public_html</span>, the latter in a subdirectory, <span class="code">public_html/metric</span>.
|
|
If you just simply modify <span class="code">skin.conf</span>, you can get one,
|
|
but not both at the same time. Alternatively, you could create a whole new skin
|
|
by copying all the files to a new skin subdirectory then editing the new
|
|
<span class="code">skin.conf</span>. The trouble with this approach is that
|
|
you would then have <em>two</em> skins you would have to maintain. If you change
|
|
something, you have to remember to change it in both places. </p>
|
|
<p>But, there's a better approach: reuse the same skin, but override some of
|
|
its options. Here's what your <span class="code">[StdReport]</span> section
|
|
in <span class="code">weewx.conf</span> would look like: </p>
|
|
<pre class="tty">[StdReport]
|
|
#
|
|
# This section specifies what reports, using which skins, are to be generated.
|
|
#
|
|
|
|
# Where the skins reside, relative to WEEWX_ROOT:
|
|
SKIN_ROOT = skins
|
|
|
|
# Where the generated reports should go, relative to WEEWX_ROOT:
|
|
HTML_ROOT = public_html
|
|
|
|
# This report will use US Customary Units
|
|
[[USReport]]
|
|
# It's based on the Standard skin
|
|
skin = Standard
|
|
|
|
# This report will use metric units:
|
|
[[MetricReport]]
|
|
# It's also based on the Standard skin:
|
|
skin = Standard
|
|
# However, override where the results will go and put them in a subdirectory:
|
|
HTML_ROOT = public_html/metric
|
|
|
|
# And override the options that were not in metric units
|
|
[[[Units]]]
|
|
[[[[Groups]]]]
|
|
group_altitude = meter
|
|
group_pressure = mbar
|
|
group_rain = mm
|
|
group_rainrate = mm_per_hour
|
|
group_speed = meter_per_second
|
|
group_speed2 = meter_per_second2
|
|
group_temperature = degree_C
|
|
|
|
[[FTP]]
|
|
...
|
|
... (as before) </pre>
|
|
<p>We have done two things different from the stock reports. First (1), we've
|
|
renamed the first report from <span class="code">StandardReport </span>to
|
|
<span class="code">USReport </span>for clarity; and (2) we've introduced
|
|
a new report <span class="code">MetricReport</span>, just like the first, except
|
|
it puts its results in a different spot and uses different units. Both use the
|
|
same skin, the <span class="code">Standard </span>skin. </p>
|
|
<h2 id="Customizing_templates">Customizing templates</h2>
|
|
<p>If you cannot achieve the results you need by changing a configuration option,
|
|
you may have to modify the templates that come with <span class="code">weewx</span>,
|
|
or write your own. </p>
|
|
<p>Template modifications are preserved across upgrades (indeed, everything
|
|
in the <span class="code">./skins</span> subdirectory is preserved), so you
|
|
don't have to worry about losing changes.</p>
|
|
<p>Template generation is done using the
|
|
<a href="http://www.cheetahtemplate.org/">Cheetah</a> templating engine. This
|
|
is a very powerful engine, which essentially lets you have the full semantics
|
|
of Python available in your templates. As this would make the templates incomprehensible
|
|
to anyone but a Python programmer, <span class="code">weewx</span> adopts a
|
|
very small subset of its power. </p>
|
|
<p>The key construct is a 'dot' code, specifying what value you want.
|
|
For example: </p>
|
|
<pre class="tty">$month.outTemp.max
|
|
$month.outTemp.maxtime
|
|
$current.outTemp</pre>
|
|
<p>would code the max outside temperature for the month, the time it occurred,
|
|
and the current outside temperature, respectively. So, an HTML file that looks
|
|
like </p>
|
|
<pre class="tty">
|
|
<html>
|
|
<head>
|
|
<title>Current conditions</title>
|
|
</head>
|
|
<body>
|
|
<p>Current temperature = $current.outTemp</p>
|
|
<p>Max for the month is $month.outTemp.max, which occurred at $month.outTemp.maxtime</p>
|
|
</body>
|
|
</html></pre>
|
|
<p>would be all you need for a very simple HTML page that would display the
|
|
text (assuming that the unit group for temperature is <span class="code">degree_F</span>):
|
|
</p>
|
|
<p class="Example_output">Current temperature = 51.0°F <br />
|
|
Max for the month is 68.8°F, which occurred at 07-Oct-2009 15:15 </p>
|
|
<p>The format that was used to format the temperature (<span class="code">51.0</span>)
|
|
is specified in section <span class="code"><a href="#Units_StringFormats">[Units][[StringFormat]]</a></span>.
|
|
The unit label <span class="code">°F</span> is from section
|
|
<span class="code"><a href="#[[Labels]]">[Units][[Labels]]</a></span>, while
|
|
the time format is from <span class="code"><a href="#TimeFormats">[Labels][[Time]]</a></span>.
|
|
</p>
|
|
<h3>The dot code</h3>
|
|
<p>As we saw above, the dot codes can be very simple: </p>
|
|
<pre class="tty">## Output max outside temperature using an appropriate format and label:
|
|
$month.outTemp.max</pre>
|
|
<p>Most of the time, the dot code will "do the right thing" and is
|
|
all you will need. However, <span class="code">weewx</span> offers extensive
|
|
customization of the generate output for specialized applications such as XML
|
|
RSS feeds, or ridgidly formatted reports (such as the NOAA reports). This section
|
|
specifies the various options available. </p>
|
|
<p>There are two different versions of the dot code, depending on whether the
|
|
data is "current", or an aggregation over time. However, both versions
|
|
are very similar </p>
|
|
<h4>Time period <span class="code">$current</span></h4>
|
|
<p>Time period <span class="code">$current</span> represents a <em>current observation</em>.
|
|
An example would be the current barometric pressure: </p>
|
|
<pre>$current.barometer</pre>
|
|
<p>The dot code for a current observation looks like: </p>
|
|
<pre><em>$current.obstype[.optional_unit_conversion][.optional_formatting]</em></pre>
|
|
<p>Where: </p>
|
|
<p class="indent"><span class="code"><em>obstype</em></span> is an observation
|
|
type, such as <span class="code">barometer</span>. See <em>
|
|
<a href="#Archive_types">Appendix A, Archive Types</a></em> for a table of observation
|
|
types valid for time period <span class="code">current.</span> </p>
|
|
<p class="indent"><span class="code">optional_unit_conversion</span> is an optional
|
|
unit conversion tag. If provided, the results will be converted into the specified
|
|
units, otherwise the default units specified in the skin configuration file
|
|
(in section <span class="code">[Units][[Groups]]</span>) will be used. See the
|
|
section <em><a href="#Unit_conversion_options">Unit Conversion Options</a></em>
|
|
below. </p>
|
|
<p class="indent"><span class="code"><em>optional_formatting</em></span> is
|
|
an optional formatting tag that controls how the value will appear. See the
|
|
section <em><a href="#Formatting_options">Formatting Options</a></em> below.
|
|
</p>
|
|
<h4>Aggregation periods <span class="code">$day</span>, <span class="code">$week</span>,
|
|
<span class="code">$month</span>, <span class="code">$year</span>,
|
|
<span class="code">$rainyear</span></h4>
|
|
<p>The other time periods represent an <em>aggregation over time</em>. In addition
|
|
to the time period over which the aggregation will occur, they also require
|
|
an <em>aggregation type</em>. An example would be the week's total precipitation
|
|
(where the aggregation type is <span class="code"><em>sum</em></span>): </p>
|
|
<pre>$week.rain.sum</pre>
|
|
<p>The dot code for an aggregation over time looks like: </p>
|
|
<pre><em>$period.statstype.aggregation[.optional_unit_conversion][.optional_formatting]</em></pre>
|
|
<p>Where: </p>
|
|
<p class="indent"><span class="code"><em>period</em></span> is the time period
|
|
over which the aggregation is to be done. Possible choices are
|
|
<span class="code">day</span>, <span class="code">week</span>,
|
|
<span class="code">month</span>, <span class="code">year</span>,
|
|
<span class="code">rainyear</span>. </p>
|
|
<p class="indent"><span class="code"><em>statstype</em></span> is a statistical
|
|
type. See <em><a href="#Statistical_types">Appendix C, Statistical Types</a></em>,
|
|
for a table of statistical types. </p>
|
|
<p class="indent"><span class="code"><em>aggregation</em></span> is an aggregation
|
|
type. This is something like '<span class="code">min</span>', '<span class="code">sum</span>', '<span class="code">mintime</span>'.
|
|
If you ask for <span class="code">$month.outTemp.avg</span> you are asking for
|
|
the <em>average</em> outside temperature for the month. The table <em>
|
|
<a href="#Statistical_types">Appendix C: Statistical types</a></em> shows what
|
|
aggregation types are available for which types. </p>
|
|
<p class="indent"><span class="code">optional_unit_conversion</span> is an optional
|
|
unit conversion tag. If provided, the results will be converted into the specified
|
|
units, otherwise the default units specified in the skin configuration file
|
|
(in section <span class="code">[Units][[Groups]]</span>) will be used. See the
|
|
section <em><a href="#Unit_conversion_options">Unit Conversion Options</a></em>
|
|
below. </p>
|
|
<p class="indent"><span class="code"><em>optional_formatting</em></span> is
|
|
an optional formatting tag that controls how the value will appear. See the
|
|
section <em><a href="#Formatting_options">Formatting Options</a></em> below.
|
|
</p>
|
|
<h4 id="Unit_conversion_options">Unit conversion options</h4>
|
|
<p>The tag <span class="code"><em>optional_unit_conversion</em></span> can be
|
|
used with either current observations or aggregations. If supplied, the results
|
|
will be converted to the specified units. For example, if you have set
|
|
<span class="code">group_pressure</span> to inches of mercury (<span class="code">inHg</span>),
|
|
then the tag </p>
|
|
<p class="tty">Today's average pressure=$day.barometer.avg </p>
|
|
<p>would normally give a result such as </p>
|
|
<p class="Example_output">Today's average pressure=30.05 inHg </p>
|
|
<p>However, if you add "mbar" to the end, </p>
|
|
<p class="tty">$day.barometer.avg.mbar </p>
|
|
<p>then the results will be in millibars: </p>
|
|
<p class="Example_output">Today's average pressure=1017.5 mbar </p>
|
|
<p>If an inappropriate conversion is asked for, <em>e.g.</em>, </p>
|
|
<p class="tty">Today's average pressure=$day.barometer.degree_C </p>
|
|
<p>then the offending tag will be put in the output: </p>
|
|
<p class="Example_output">Today's average pressure=$day.barometer.degree_C
|
|
</p>
|
|
<p> </p>
|
|
<h4 id="Formatting_options">Formatting options</h4>
|
|
<p>The tag <span class="code"><em>optional_formatting</em></span> can be used
|
|
with either current observations or aggregations. It can be one of: </p>
|
|
<table class="center" style="width: 80%" summary="Formatting options">
|
|
<tr>
|
|
<td class="text_highlight">
|
|
<p><strong>Optional formatting tag</strong> </p>
|
|
</td>
|
|
<td>
|
|
<p><strong>Comment</strong> </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="text_highlight">
|
|
<p><em>(no tag)</em> </p>
|
|
</td>
|
|
<td>
|
|
<p>Value is returned as a string, formatted using an appropriate string
|
|
format from <span class="code">skin.conf</span>. A unit label from
|
|
<span class="code">skin.conf </span>is also attached at the end. </p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight"><span class="code">.string(<em>NONE_string</em></span>)</td>
|
|
<td>Value is returned as a string, formatted using an appropriate string
|
|
format from <span class="code">skin.conf</span>. If the value is
|
|
<span class="code">None</span>, the string <span class="code">NONE_string</span>
|
|
will be substituted if given, otherwise the value for
|
|
<span class="code">NONE</span> in <span class="code">
|
|
<a href="#Units_StringFormats">[Units][[StringFormats]]</a></span> will
|
|
be used. A unit label from <span class="code">skin.conf</span> will
|
|
be attached at the end.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight"><span class="code">.formatted</span></td>
|
|
<td>Value is returned as a string, formatted using an appropriate string
|
|
format and <span class="code">None</span> value from
|
|
<span class="code">skin.conf</span>. No label.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight"><span class="code">.format(<em>string_format</em>, <em>NONE_string</em>)</span></td>
|
|
<td>Value is returned as a string, using the string format specified
|
|
with <em>string_format</em>. If the value is <span class="code">None</span>,
|
|
the string <span class="code">NONE_string</span> will be substituted
|
|
if given, otherwise the value for <span class="code">NONE</span> in
|
|
<span class="code"><a href="#Units_StringFormats">[Units][[StringFormats]]</a></span>
|
|
will be used. A unit label from <span class="code">skin.conf</span>
|
|
will be attached at the end.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">.nolabel(string_format, NONE_string)</td>
|
|
<td>Value is returned as a string, using the string format specified
|
|
with <em>string_format</em>. If the value is <span class="code">None</span>,
|
|
the string <span class="code">NONE_string</span> will be substituted
|
|
if given, otherwise the value for <span class="code">NONE</span> in
|
|
<span class="code"><a href="#Units_StringFormats">[Units][[StringFormats]]</a></span>
|
|
will be used. No label will be attached at the end.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">
|
|
<p><span class="code">.raw</span> </p>
|
|
</td>
|
|
<td>Value is returned "as is" without being converted to a
|
|
string and without any formatting applied. You must be prepared to deal
|
|
with a <span class="code">None</span> value unless the value is converted
|
|
directly to a string. In this case, it will be converted to the empty
|
|
string (<span class="code">''</span>)</td>
|
|
</tr>
|
|
</table>
|
|
<p>Summary: </p>
|
|
<table class="center" style="width: 80%" summary="Summary of formatting options">
|
|
<tr>
|
|
<td class="text_highlight"><strong>Formatting tag</strong></td>
|
|
<td><strong>Format used</strong></td>
|
|
<td><strong>Label Used</strong></td>
|
|
<td><strong>NONE string</strong></td>
|
|
<td><strong>Returned value</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="text_highlight"><em>(no tag)</em></td>
|
|
<td>From <span class="code">skin.conf</span></td>
|
|
<td>From <span class="code">skin.conf</span></td>
|
|
<td>From <span class="code">skin.conf</span></td>
|
|
<td>string</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">.string</td>
|
|
<td>From <span class="code">skin.conf</span></td>
|
|
<td>From <span class="code">skin.conf</span></td>
|
|
<td>Optional user-supplied</td>
|
|
<td>string</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">.formatted</td>
|
|
<td>From <span class="code">skin.conf</span></td>
|
|
<td>No label</td>
|
|
<td>From <span class="code">skin.conf</span></td>
|
|
<td>string</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">.format</td>
|
|
<td>User-supplied</td>
|
|
<td>From <span class="code">skin.conf</span></td>
|
|
<td>Optional user-supplied</td>
|
|
<td>string</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">.nolabel</td>
|
|
<td>User-supplied</td>
|
|
<td>No label</td>
|
|
<td>Optional user-supplied</td>
|
|
<td>string</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">.raw</td>
|
|
<td>None</td>
|
|
<td>No label</td>
|
|
<td>None</td>
|
|
<td>native value</td>
|
|
</tr>
|
|
</table>
|
|
<p>Here are some examples with the expected results: </p>
|
|
<table class="center" summary="Formatting options with expected results">
|
|
<tr>
|
|
<td class="text_highlight"><strong>Tag</strong></td>
|
|
<td><strong>Result</strong></td>
|
|
<td><strong>Comment</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.outTemp </td>
|
|
<td class="code">45.2°F </td>
|
|
<td>String formatting and label from <span class="code">skin.conf</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.outTemp.string</td>
|
|
<td class="code">45.2°F</td>
|
|
<td>String formatting and label from <span class="code">skin.conf</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.UV.string</td>
|
|
<td class="code">N/A</td>
|
|
<td>This example assumes that the instrument has no UV sensor, resulting
|
|
in a <span class="code">None</span> value. The string specified by
|
|
<span class="code">NONE</span> in <span class="code">
|
|
<a href="#Units_StringFormats">[Units][[StringFormats]]</a></span> is
|
|
substituted.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.UV.string("No UV")</td>
|
|
<td class="code">No UV</td>
|
|
<td>This example assumes that the instrument has no UV sensor, resulting
|
|
in a <span class="code">None</span> value. The string supplied by the
|
|
user is substituted.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.outTemp.formatted </td>
|
|
<td class="code">45.2</td>
|
|
<td>String formatting from <span class="code">skin.conf</span>; no label</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.outTemp.format("%.3f") </td>
|
|
<td class="code">45.200°F</td>
|
|
<td>Specified string format used; label from <span class="code">skin.conf</span>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.dateTime</td>
|
|
<td class="code">02-Apr-2010 16:25</td>
|
|
<td>Time formatting and label from <span class="code">skin.conf</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.dateTime.format("%H:%M")</td>
|
|
<td class="code">16:25</td>
|
|
<td>Specified time format used; label from <span class="code">skin.conf</span>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.dateTime.raw</td>
|
|
<td class="code">1270250700</td>
|
|
<td>Unix epoch time, converted to string by template engine.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$current.outTemp.raw</td>
|
|
<td class="code">45.2</td>
|
|
<td>Float returned, converted to string by template engine.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.dateTime</td>
|
|
<td class="code">01-Apr-2010 00:00</td>
|
|
<td>Time formatting and label from <span class="code">skin.conf</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.outTemp.avg </td>
|
|
<td class="code">40.8°F</td>
|
|
<td>String formatting and label from <span class="code">skin.conf</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.outTemp.avg.string</td>
|
|
<td class="code">40.8°F</td>
|
|
<td>Time formatting and label from <span class="code">skin.conf</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.UV.avg.string</td>
|
|
<td class="code">N/A</td>
|
|
<td>This example assumes that the instrument has no UV sensor, resulting
|
|
in a <span class="code">None</span> value. The string specified by
|
|
<span class="code">NONE</span> in <span class="code">
|
|
<a href="#Units_StringFormats">[Units][[StringFormats]]</a></span> is
|
|
substituted.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.UV.avg.string("No UV")</td>
|
|
<td class="code">No UV</td>
|
|
<td>This example assumes that the instrument has no UV sensor, resulting
|
|
in a <span class="code">None</span> value. The string supplied by the
|
|
user is substituted.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.outTemp.avg.formatted </td>
|
|
<td class="code">40.8</td>
|
|
<td>String formatting from <span class="code">skin.conf</span>; no label</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.outTemp.avg.format("%.3f")</td>
|
|
<td class="code">40.759°F</td>
|
|
<td>Specified string format used; no label</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.outTemp.avg.raw </td>
|
|
<td class="code">40.7589690722</td>
|
|
<td>Float returned, converted to string by template engine</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$month.UV.avg.raw</td>
|
|
<td class="code"><em>(empty)</em></td>
|
|
<td><span class="code">None</span> value converted to empty string by
|
|
template engine.</td>
|
|
</tr>
|
|
</table>
|
|
<p>Note: </p>
|
|
<ul>
|
|
<li>Tags that take an argument (such as <span class="code">.string(NONE_string)</span>)
|
|
do not require parenthesis if the argument is omitted.Thus, you can specify
|
|
either <span class="code">$month.outTemp.string()</span> or
|
|
<span class="code">$month.outTemp.string</span>, if you want the default
|
|
value of <span class="code">NONE_string</span>. They produce the same results.
|
|
</li>
|
|
</ul>
|
|
<h3 id="Type_dateTime">Type <span class="code">dateTime</span></h3>
|
|
<p>While not an observation type, in many ways the time of an observation,
|
|
<span class="code">dateTime</span>, can be treated as one. A tag such as
|
|
<span class="code">$current.dateTime</span> represents the <em>current time</em>
|
|
(more properly, the time as of the end of the last archive interval). Similarly,
|
|
a tag such as <span class="code">$month.dateTime</span> represents the start
|
|
time of the month. Like true observation types, explicit formats can be specified,
|
|
except that they require a
|
|
<a href="http://docs.python.org/library/datetime.html#strftime-strptime-behavior">
|
|
strftime() <em>time format</em></a>, rather than a <em>string format:</em>
|
|
</p>
|
|
<pre>$month.dateTime.format("%B %Y)</pre>
|
|
<p>produces </p>
|
|
<pre>January 2010</pre>
|
|
<p>The returned string value will always be in <em>local time</em>. </p>
|
|
<p>The raw value of <span class="code">dateTime</span> is Unix Epoch Time (number
|
|
of seconds since 00:00:00 UTC 1 Jan 1970, <em>i.e.</em>, a large number), which
|
|
you must convert yourself to local time. It is guaranteed to never be
|
|
<span class="code">None</span>, so you don't worry have to worry about handling
|
|
a <span class="code">None</span> value. </p>
|
|
<h3>Tag <span class="code">$trend</span></h3>
|
|
<p>The tag <span class="code">$trend</span> is available for time trends, such
|
|
as barometer trends. Here are some examples:</p>
|
|
<table class="center" style="width: 40%" summary="Examples of using unit formats">
|
|
<tr>
|
|
<td class="text_highlight"><strong>Tag</strong></td>
|
|
<td><strong>Results</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$trend.barometer</td>
|
|
<td class="code">-.02 inHg</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$trend.outTemp</td>
|
|
<td class="code">1.1 °C</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$trend.time_delta</td>
|
|
<td class="code">10800 secs</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$trend.time_delta.hour</td>
|
|
<td class="code">3 hrs</td>
|
|
</tr>
|
|
</table>
|
|
<p>Note that the time delta over which the trend is calculated is also available.
|
|
This time delta is set by an option in the skin configuration file,
|
|
<span class="code"><a href="#[[Trend]]">time_delta</a></span>.</p>
|
|
<p>As a summary, the template expression</p>
|
|
<p class="tty"><p>The barometer trend over $trend.time_delta.hour is $trend.barometer.format("%+.2f").</p></p>
|
|
<p>would result in</p>
|
|
<p class="Example_output">The barometer trend over 3 hrs is +.02 inHg.</p>
|
|
<h3>Tag <span class="code">$unit</span></h3>
|
|
<p>The unit type, label, and string formats are also available, allowing you
|
|
to do highly customized labels: </p>
|
|
<table class="center" style="width: 40%" summary="Examples of using unit formats">
|
|
<tr>
|
|
<td class="text_highlight"><strong>Tag</strong></td>
|
|
<td><strong>Results</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$unit.unit_type.outTemp</td>
|
|
<td class="code">degree_C</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$unit.label.outTemp</td>
|
|
<td class="code">°C</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$unit.format.outTemp</td>
|
|
<td class="code">%.1f</td>
|
|
</tr>
|
|
</table>
|
|
<p>As a summary, the tag </p>
|
|
<pre>$day.outTemp.max.formatted$unit.label.outTemp</pre>
|
|
<p>would result in </p>
|
|
<pre>21.2°C</pre>
|
|
<p>(assuming metric values have been specified for <span class="code">group_temperature</span>),
|
|
essentially reproducing the results of the simpler tag <span class="code">$day.outTemp.max</span>.
|
|
</p>
|
|
<h3>Iteration</h3>
|
|
<p>For dot codes using an aggregation (<em>e.g.</em>, <span class="code">$day</span>,
|
|
<span class="code">$week</span>, <span class="code">$month</span>,
|
|
<span class="code">$year</span>, <span class="code">$rainyear</span>, then the
|
|
aggregation period can be iterated over by day or month. These are the only
|
|
two iteration periods available as of this version. </p>
|
|
<p>This example uses a Cheetah '<span class="code">for</span>' loop
|
|
to iterate over all months in a year, printing out each month's min and
|
|
max temperature (the iteration loop is highlighted): </p>
|
|
<pre>
|
|
<html>
|
|
<head>
|
|
<title>Year stats by month</title>
|
|
</head>
|
|
<body>
|
|
<p>Min, max temperatures by month:</p>
|
|
<span class="highlight"> #for $month in $year.months</span>
|
|
<p>$month.dateTime.format("%B"): Min, max temperatures: $month.outTemp.min $month.outTemp.max</p>
|
|
<span class="highlight"> #end for </span>
|
|
</body>
|
|
</html></pre>
|
|
<p>Produces results: </p>
|
|
<pre class="tty">
|
|
Min, max temperatures by month:
|
|
January: Min, max temperatures: 30.1°F 51.5°F
|
|
February: Min, max temperatures: 24.4°F 58.6°F
|
|
March: Min, max temperatures: 27.3°F 64.1°F
|
|
April: Min, max temperatures: 33.2°F 52.5°F
|
|
May: Min, max temperatures: N/A N/A
|
|
June: Min, max temperatures: N/A N/A
|
|
July: Min, max temperatures: N/A N/A
|
|
August: Min, max temperatures: N/A N/A
|
|
September: Min, max temperatures: N/A N/A
|
|
October: Min, max temperatures: N/A N/A
|
|
November: Min, max temperatures: N/A N/A
|
|
December: Min, max temperatures: N/A N/A</pre>
|
|
<p>See the NOAA template files <span class="code">NOAA/NOAA-YYYY.txt.tmpl</span>
|
|
and <span class="code">NOAA/NOAA-YYYY-MM.txt.tmpl</span> for examples using
|
|
iteration, as well as explicit formatting. </p>
|
|
<h3>Almanac</h3>
|
|
<p>If module <a href="http://rhodesmill.org/pyephem">pyephem</a> has been installed,
|
|
then <span class="code">weewx</span> can generate extensive almanac information
|
|
for the Sun, Moon, Venus, Mars, Jupiter, and other heavenly bodies, including
|
|
their rise, transit and set times, as well as their azimuth and altitude. Other
|
|
information is also available. </p>
|
|
<p>Here is a small sampling: </p>
|
|
<pre class="tty">
|
|
<html>
|
|
<head>
|
|
<title>Almanac data</title>
|
|
</head>
|
|
<body>
|
|
<p>Current time is $current.dateTime<p>
|
|
#if $almanac.hasExtras
|
|
<p>Sunrise, transit, sunset: $almanac.sun.rise $almanac.sun.transit $almanac.sun.set</p>
|
|
<p>Moonrise, transit, moonset: $almanac.moon.rise $almanac.moon.transit $almanac.moon.set</p>
|
|
<p>Mars rise, transit, set: $almanac.mars.rise $almanac.mars.transit $almanac.mars.set</p>
|
|
<p>Azimuth, altitude of mars: $almanac.mars.az $almanac.mars.alt</p>
|
|
<p>Next new, full moon: $almanac.next_new_moon $almanac.next_full_moon</p>
|
|
<p>Next summer, winter solstice: $almanac.next_summer_solstice $almanac.next_winter_solstice</p>
|
|
#else
|
|
<p>Sunrise, sunset: $almanac.sunrise $almanac.sunset</p>
|
|
#end if
|
|
</body>
|
|
</html></pre>
|
|
<p>If your installation has pyephem installed this would result in: </p>
|
|
<pre class="tty">
|
|
Current time is 29-Mar-2011 09:20
|
|
Sunrise, transit, sunset: 06:51 13:11 19:30
|
|
Moonrise, transit, moonset: 04:33 09:44 15:04
|
|
Mars rise, transit, set: 06:35 12:30 18:26
|
|
Azimuth, altitude of mars: 124.354959275 26.4808431952
|
|
Next new, full moon: 03-Apr-2011 07:32 17-Apr-2011 19:43
|
|
Next summer, winter solstice: 21-Jun-2011 10:16 21-Dec-2011 21:29</pre>
|
|
<p>Otherwise, a fallback position is used, resulting in </p>
|
|
<pre class="tty">
|
|
Current time is 29-Mar-2011 09:20
|
|
Sunrise, sunset: 06:51 19:30</pre>
|
|
<p>As shown in the example, you can test whether this extended almanac information
|
|
is available with the value <span class="code">$almanac.hasExtras</span>.
|
|
</p>
|
|
<p>The almanac information falls in two categories:</p>
|
|
<ul>
|
|
<li>Calendar events</li>
|
|
<li>Heavenly bodies</li>
|
|
</ul>
|
|
<p>We will cover each of these separately.</p>
|
|
<h4>Calendar events</h4>
|
|
<p>"Calendar events" do not require a heavenly body. They cover things such
|
|
as "<span class="code">next_solstice</span>", or "<span class="code">next_first_quarter_moon</span>".
|
|
The syntax here is </p>
|
|
<pre class="tty">$almanac.next_solstice </pre>
|
|
<p>or </p>
|
|
<pre class="tty">$almanac.next_first_quarter_moon</pre>
|
|
<p> Here's a table of the information that falls into this category:</p>
|
|
<table class="code" style="width: 60%">
|
|
<tr>
|
|
<td>previous_equinox</td>
|
|
<td>next_equinox</td>
|
|
<td>previous_solstice</td>
|
|
<td>next_solstice</td>
|
|
</tr>
|
|
<tr>
|
|
<td>previous_autumnal_equinox</td>
|
|
<td>next_autumnal_equinox</td>
|
|
<td>previous_vernal_equinox</td>
|
|
<td>next_vernal_equinox</td>
|
|
</tr>
|
|
<tr>
|
|
<td>previous_winter_solstice</td>
|
|
<td>next_winter_solstice</td>
|
|
<td>previous_summer_solstice</td>
|
|
<td>next_summer_solstice</td>
|
|
</tr>
|
|
<tr>
|
|
<td>previous_new_moon</td>
|
|
<td>next_new_moon</td>
|
|
<td>previous_first_quarter_moon</td>
|
|
<td>next_first_quarter_moon</td>
|
|
</tr>
|
|
<tr>
|
|
<td>previous_full_moon</td>
|
|
<td>next_full_moon</td>
|
|
<td>previous_last_quarter_moon</td>
|
|
<td>next_last_quarter_moon</td>
|
|
</tr>
|
|
</table>
|
|
<h4>Heavenly bodies</h4>
|
|
<p>The second category does require a heavenly body. This covers queries such
|
|
as, "When does Jupiter rise?" or, "When does the sun transit?" Examples are</p>
|
|
<p class="tty">$almanac.jupiter.rise</p>
|
|
<p>or</p>
|
|
<p class="tty">$almanac.sun.transit</p>
|
|
<p>To accurately calculate these times, <span class="code">weewx</span> automatically
|
|
uses the present temperature and pressure to calculate refraction effects. However,
|
|
you can override these values, which will be necessary if you wish to match
|
|
the almanac times published by the Naval Observatory
|
|
<a href="http://rhodesmill.org/pyephem/rise-set.html">as explained in the pyephem
|
|
documentation</a>. For example, to match the sunrise time as published by the
|
|
Observatory, instead of</p>
|
|
<p class="tty">$almanac.sun.rise</p>
|
|
<p>use</p>
|
|
<p class="tty">$almanac(pressure=0, horizon=-34.0/60.0).sun.rise</p>
|
|
<p>By setting pressure to zero we are bypassing the refraction calculations
|
|
and manually setting the horizon to be 34 arcminutes lower than the normal horizon.
|
|
This is what the Navy uses.</p>
|
|
<p>If you wish to calculate the start of civil twilight, you can set the horizon
|
|
to -6, and also tell <span class="code">weewx</span> to use the center of the
|
|
sun (instead of the upper limb, which it normally uses) to do the calcuation:</p>
|
|
<p class="tty">$almanac(pressure=0, horizon=-6.sun(use_center=1).rise</p>
|
|
<p>The general syntax is:</p>
|
|
<p class="tty">$almanac(pressure=<em>pressure</em>, horizon=<em>horizon</em>,<br />
|
|
temperature=<em>temperature_C</em>).<em>heavenly_body</em>(use_center=[01]).<em>attribute</em></p>
|
|
<p>As you can see, in addition to the horizon angle, you can also override atmospheric
|
|
pressure and temperature (degrees Celsius).</p>
|
|
<p>PyEphem offers an extensive list of objects that can be used for the
|
|
<span class="code"><em>heavenly_body</em></span> tag. All the planets and many
|
|
stars are in the list. </p>
|
|
<p>The <span class="code">attribute</span> tag can be one of </p>
|
|
<table class="code" style="width: 60%">
|
|
<tr>
|
|
<td>az</td>
|
|
<td>alt</td>
|
|
<td>a_ra</td>
|
|
<td>a_dec</td>
|
|
</tr>
|
|
<tr>
|
|
<td>g_ra</td>
|
|
<td>ra</td>
|
|
<td>g_dec</td>
|
|
<td>dec</td>
|
|
</tr>
|
|
<tr>
|
|
<td>elong</td>
|
|
<td>radius</td>
|
|
<td>hlong</td>
|
|
<td>hlat</td>
|
|
</tr>
|
|
<tr>
|
|
<td>sublat</td>
|
|
<td>sublong</td>
|
|
<td>next_rising</td>
|
|
<td>next_setting</td>
|
|
</tr>
|
|
<tr>
|
|
<td>next_transit</td>
|
|
<td>next_antitransit</td>
|
|
<td>previous_rising</td>
|
|
<td>previous_setting</td>
|
|
</tr>
|
|
<tr>
|
|
<td>previous_transit</td>
|
|
<td>previous_antitransit</td>
|
|
<td>rise</td>
|
|
<td>set</td>
|
|
</tr>
|
|
<tr>
|
|
<td>transit</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
</table>
|
|
<h2>Writing a custom generator</h2>
|
|
<p>To do more sophisticated customization it may be necessary to extend an existing
|
|
generator, or write your own. </p>
|
|
<h4 id="Extending_an_existing_generator">Extending an existing report generator</h4>
|
|
<p>In the section on <em><a href="#Customizing_templates">Customizing templates</a></em>,
|
|
we have seen how you can change a template and make use of the various tags
|
|
available such as <span class="code">$day.outTemp.max</span> for the maximum
|
|
outside temperature for the day. But, what if you want to introduce some new
|
|
data for which no tag is available? </p>
|
|
<p>If you wish to introduce a static tag, that is, one that will not change
|
|
with time (such as a Google analytics Tracker ID, or your name), then this is
|
|
very easy: simply put it in section <span class="code"><a href="#[Extras]">[Extras]</a></span>
|
|
in the skin configuration file. More information on how to do this can be found
|
|
there. </p>
|
|
<p>But, what if you wish to introduce a more dynamic tag, one that requires
|
|
some calculation, or that uses the database? Simply putting it in the
|
|
<span class="code">[Extras]</span> section won't do, because then it cannot
|
|
change. </p>
|
|
<p>The answer is to extend the default file generator<span class="code"> weewx.filegenerator.FileGenerator</span>
|
|
by subclassing, then override the function that returns the <em>search list</em>.
|
|
The search list is a list of dictionaries that the template engine searches
|
|
through, trying all keys in each dictionary, looking for a match for your tag.
|
|
For example, for the "ToDate" generator, you would override function
|
|
<span class="code">getToDateSearchList()</span>, and add a small dictionary
|
|
with your tag as the key to the list returned by the superclass. </p>
|
|
<p>Let's look at an example. The regular version of <span class="code">weewx</span>
|
|
offers statistical summaries by day, week, month, and year. Suppose we would
|
|
like to add two more: </p>
|
|
<ul>
|
|
<li>All-time statistics. This would allow us to display statistics such
|
|
as the all-time high or low temperature seen at your station;</li>
|
|
<li>Seven days statistics. While <span class="code">weewx</span> offers
|
|
the tag <span class="code">$week</span>, this is statistics <em>since Sunday
|
|
at midnight</em>. We would like to have statistics for a full week, that
|
|
is since midnight seven days ago.</li>
|
|
</ul>
|
|
<p>This example is included in the distribution as <span class="code">bin/examples/mygenerator.py</span>:
|
|
</p>
|
|
<pre class="tty">
|
|
import datetime
|
|
import time
|
|
|
|
from weewx.filegenerator import FileGenerator
|
|
from weewx.stats import TimeSpanStats
|
|
from weeutil.weeutil import TimeSpan
|
|
|
|
class MyFileGenerator(FileGenerator): # 1
|
|
|
|
def getToDateSearchList(self, archivedb, statsdb, valid_timespan): # 2
|
|
|
|
# First, get a TimeSpanStats object for all time. This one is easy
|
|
# because the object valid_timespan already holds all valid times to be
|
|
# used in the report.
|
|
all_stats = TimeSpanStats(valid_timespan,
|
|
statsdb,
|
|
formatter=self.formatter,
|
|
converter=self.converter) # 3
|
|
|
|
# Now get a TimeSpanStats object for the last seven days. This one we
|
|
# will have to calculate. First, calculate the time at midnight, seven
|
|
# days ago. The variable week_dt will be an instance of datetime.date.
|
|
week_dt = datetime.date.fromtimestamp(valid_timespan.stop) - datetime.timedelta(weeks=1) # 4
|
|
# Now convert it to unix epoch time:
|
|
week_ts = time.mktime(week_dt.timetuple()) # 5
|
|
# Now form a TimeSpanStats object, using the time span we just calculated:
|
|
seven_day_stats = TimeSpanStats(TimeSpan(week_ts, valid_timespan.stop),
|
|
statsdb,
|
|
formatter=self.formatter,
|
|
converter=self.converter) # 6
|
|
|
|
# Get the superclass's search list:
|
|
search_list = FileGenerator.getToDateSearchList(self, archivedb, statsdb, valid_timespan) # 7
|
|
|
|
# Now tack on my two additions as a small dictionary with keys 'alltime' and 'seven_day':
|
|
search_list += [ {'alltime' : all_stats,
|
|
'seven_day' : seven_day_stats} ] # 8
|
|
|
|
return search_list</pre>
|
|
<p>Going through the example, line by line: </p>
|
|
<ol>
|
|
<li>Subclass from class <span class="code">FileGenerator</span>. The new
|
|
class will be caled <span class="code">MyFileGenerator</span> </li>
|
|
<li>Override member function <span class="code">getToDateSearchList()</span>.
|
|
The parameters that will be passed in are:
|
|
<ul>
|
|
<li><span class="code">self</span> Python's way of indicating the instance
|
|
we are working with;</li>
|
|
<li><span class="code">archivedb</span> An instance of
|
|
<span class="code">weewx.archive.Archive</span>, holding the archive
|
|
database;</li>
|
|
<li><span class="code">statsdb</span> An instance of
|
|
<span class="code">weewx.stats.StatsDb</span>, holding the statistical
|
|
database;</li>
|
|
<li><span class="code">valid_timespan</span> An instance of the utility
|
|
class <span class="code">TimeSpan</span>. This will contain the valid
|
|
start and ending times of the "to date" summary period; nominally
|
|
all possible times. </li>
|
|
</ul>
|
|
</li>
|
|
<li>The class <span class="code">TimeSpanStats</span> represents a statistical
|
|
calculation over a time period. In our case, we will set it up to represent
|
|
the statistics over all possible times. The class takes 4 parameters.
|
|
<ul>
|
|
<li>The first is the timespan over which the calculation is to be done.
|
|
Here, we have a lucky coincidence: the variable <span class="code">valid_timespan</span>
|
|
already holds a <span class="code">TimeSpan</span> object representing
|
|
the domain of valid timespans, so we simply pass it in.</li>
|
|
<li>The second is the statistical database the calculation is to be
|
|
run against. We simply pass in <span class="code">statsdb</span>.</li>
|
|
<li>The third should be an instance of class <span class="code">weewx.units.Formatter</span>,
|
|
which contains information about how the results should be formatted.
|
|
We just pass in the formatter set up by our superclass,
|
|
<span class="code">self.formatter</span>.</li>
|
|
<li>The fourth should be an instance of <span class="code">weewx.units.Converter</span>,
|
|
which contains information about the target units (<em>e.g.</em>, "<span class="code">degree_C</span>")
|
|
that are to be used. Again, we just pass in the instance set up by our
|
|
superclass, <span class="code">self.converter</span>.</li>
|
|
</ul>
|
|
</li>
|
|
</ol>
|
|
<p>That one was relatively easy because we already had an instance of
|
|
<span class="code">TimeSpan</span>, <span class="code">valid_timespan</span>,
|
|
that represented the time over which we wanted to do the calculations. Setting
|
|
up an instance that will work for the last seven days is a bit trickier. Continuing
|
|
our example...</p>
|
|
<ol start="4">
|
|
<li>The object <span class="code">valid_timespan</span> holds the domain
|
|
of valid times, but we need not the time of the report, which will be
|
|
<span class="code">valid_timespan.stop</span>, but the time at midnight
|
|
seven days ago. So, we do a little Python date arithmetic to calculate this.
|
|
The object <span class="code">week_dt</span> will be an instance of
|
|
<span class="code">datetime.date</span>.</li>
|
|
<li>We convert it to unix epoch time.</li>
|
|
<li>Now we are ready to initialize an appropriate <span class="code">TimeSpanStats</span>
|
|
object. It's the same as in step #3, except we use our new timespan object.</li>
|
|
<li>Get the search list from the superclass. </li>
|
|
<li>Tack on our addition and return the results. The search list will now
|
|
consist of a list of dictionaries, including a small one we added on the
|
|
end that has two keys, '<span class="code">alltime</span>', and '<span class="code">seven_day</span>'.
|
|
If one of these keys is used, the appropriate <span class="code">TimeSpanStats</span>
|
|
object will be returned.</li>
|
|
</ol>
|
|
<p>With this approach, you can now include "all time" or "seven day"
|
|
statistics in your HTML templates: </p>
|
|
<pre class="tty">
|
|
...
|
|
<table>
|
|
<tr>
|
|
<td>Maximum temperature to date: </td>
|
|
<td>$alltime.outTemp.max</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Minimum temperature to date: </td>
|
|
<td>$alltime.outTemp.min
|
|
</tr>
|
|
<tr>
|
|
<td>Rain over the last seven days: </td>
|
|
<td>$seven_day.rain.sum
|
|
</tr>
|
|
... (more table entries)</pre>
|
|
<p>One additonal step is required: to tell the report service to run your generator
|
|
instead of the default generator. Modify option <span class="code">[Generators]generator_list</span>
|
|
in the skin configuration file <span class="code">skin.conf</span> to read:
|
|
</p>
|
|
<pre>generator_list = examples.mygenerator.MyFileGenerator, weewx.imagegenerator.ImageGenerator, weewx.reportengine.CopyGenerator</pre>
|
|
<p>NB: If you create a custom generator some place other than where
|
|
<span class="code">weewxd.py</span> resides, you may have to specify its location
|
|
in the environment variable <span class="code">PYTHONPATH</span>: </p>
|
|
<pre>export PYTHONPATH=/home/me/secret_location</pre>
|
|
<h2>Upgrades and user extensions</h2>
|
|
<p>In the examples above, we subclassed <span class="code">weewx</span> classes
|
|
to add functionality. Where should you put your new code? If you simply modify
|
|
the examples in place, then your changes will get overwritten the next time
|
|
you do an upgrade, forcing you to cut and paste any changes you have made.
|
|
</p>
|
|
<p>A better idea is to copy over the examples to the subdirectory
|
|
<span class="code"><em>$WEEWX_ROOT</em>/bin/user</span>, then modify them there.
|
|
This subdirectory is preserved through upgrades, so you won't have to redo
|
|
any changes you might have made. </p>
|
|
<h1 id="The_Standard_skin_configuration_file">Reference: The Standard skin configuration
|
|
file</h1>
|
|
<p>This section is a reference to the options appearing in the Standard skin
|
|
configuration file, found in <span class="code"><em>$WEEWX_ROOT</em>/skins/Standard/skin.conf</span>.
|
|
</p>
|
|
<p>It is worth noting that, like the main configuration file
|
|
<span class="code">weewx.conf</span>, UTF-8 is used throughout. The most important
|
|
options are up near the top of the file. The truly important ones, the
|
|
ones you are likely to have to customize for your station, are shown in
|
|
<span class="bold_n_blue"><strong>bold face and in blue</strong></span>. </p>
|
|
<h2 id="[Extras]" class="config_section">[Extras]</h2>
|
|
<p>This section is available to you to add any static tags that you might want
|
|
to be available in the templates. As an example, the stock
|
|
<span class="code">skin.conf</span> file includes two options:
|
|
<span class="code">radar_url</span>, which is available as tag
|
|
<span class="code">$Extras.radar_url</span>, and <span class="code">googleAnalyticsId</span>,
|
|
available as tag <span class="code">$Extras.googleAnalyticsId</span>. If you
|
|
take a look at the template <span class="code">index.html.tmpl</span> you will
|
|
see examples of testing for these tags (search the file for the string
|
|
<span class="code">radar_url</span> or <span class="code">googleAnalyticsId</span>
|
|
to find them). </p>
|
|
<p class="config_option">radar_url </p>
|
|
<p>If set, the NOAA radar image will be displayed. If commented out, no image
|
|
will be displayed. </p>
|
|
<p class="config_option">googleAnalyticsId </p>
|
|
<p>If you have a <a href="http://www.google.com/analytics/">Google Analytics
|
|
ID</a>, you can set it here. The Google Analytics Javascript code will then
|
|
be included, enabling analytics of your website usage. If commented out, the
|
|
code will not be included. </p>
|
|
<h4>Extending <span class="code">[Extras]</span></h4>
|
|
<p>Other tags can be added in a similar manner, including subsections. For example,
|
|
say you have added a video camera and you would like to add a still image with
|
|
a hyperlink to a page with the video. You want all of these options to be neatly
|
|
contained in a subsection. </p>
|
|
<pre>
|
|
[Extras]
|
|
[[video]]
|
|
still = video_capture.jpg
|
|
hyperlink = <a href="http://www.eatatjoes.com/video.html">http://www.eatatjoes.com/video.html</a></pre>
|
|
<p>Then in your template you could refer to these as: </p>
|
|
<pre>
|
|
<a href="$Extras.video.hyperlink">
|
|
<img src="$Extras.video.still" alt="Video capture"/>
|
|
</a></pre>
|
|
<h2 class="config_section">[Units]</h2>
|
|
<p>This section deals with Units and their formatting. </p>
|
|
<h3 class="config_section">[[Groups]]</h3>
|
|
<p>This subsection lists all the <em>Unit Groups</em> and specifies which unit
|
|
system is to be used for each one of them. </p>
|
|
<p>As there are many different observational measurement types (such as '<span class="code">outTemp</span>', '<span class="code">barometer</span>',
|
|
etc.) used in <span class="code">weewx</span> (more than 50 at last count),
|
|
it would be tedious, not to say possibly inconsistent, to specify a different
|
|
measurement system for each one of them. At the other extreme, requiring all
|
|
of them to be "U.S. Customary" or "Metric" seems overly
|
|
restrictive. <span class="code">Weewx</span> has taken a middle route and divided
|
|
all the different observation types into 12 different "<em>unit groups</em>."
|
|
A unit group is something like "<span class="code">group_temperature</span>."
|
|
It represents the measurement system to be used by all observation types that
|
|
are measured in temperature, such as inside temperature (type '<span class="code">inTemp</span>'),
|
|
outside temperature ('<span class="code">outTemp</span>'), dewpoint
|
|
('<span class="code">dewpoint</span>'), wind chill ('<span class="code">windchill</span>'),
|
|
and so on. If you decide that you want unit group <span class="code">group_temperature</span>
|
|
to be measured in "<span class="code">degree_C</span>" then you are
|
|
saying <em>all</em> members of its group will be reported in degrees Celsius.
|
|
</p>
|
|
<p>Note that the unit system is always specified in the singular. That is, specify "<span class="code">degree_C</span>"
|
|
or "<span class="code">foot</span>", not "<span class="code">degrees_C</span>"
|
|
or "<span class="code">feet</span>". See the Appendix <em>
|
|
<a href="#Units">Units</a></em> for more information, including a concise summary
|
|
of the groups, their members, and which options can be used for each group.
|
|
</p>
|
|
<p class="config_important"><a class="config_option" name="group_altitude">group_altitude</a>
|
|
</p>
|
|
<p>Which measurement unit to be used for altitude. Possible options are '<span class="code">foot</span>'
|
|
or '<span class="code">meter</span>'. </p>
|
|
<p class="config_option">group_direction </p>
|
|
<p>Which measurement unit to be used for direction. The only option is "<span class="code">degree_compass</span>".
|
|
</p>
|
|
<p class="config_option">group_moisture </p>
|
|
<p>The measurement unit to be used for soil moisture. The only option is "<span class="code">centibar</span>."
|
|
</p>
|
|
<p class="config_option">group_percent </p>
|
|
<p>The measurement unit to be used for percentages. The only option is "<span class="code">percent</span>".
|
|
</p>
|
|
<p class="config_important">group_pressure </p>
|
|
<p>The measurement unit to be used for pressure. Possible options are one of "<span class="code">inHg</span>"
|
|
(inches of mercury), "<span class="code">mbar</span>", or "<span class="code">hPa</span>."
|
|
</p>
|
|
<p class="config_option">group_radiation </p>
|
|
<p>The measurement unit to be used for radiation. The only option is "<span class="code">watt_per_meter_squared</span>."
|
|
</p>
|
|
<p class="config_important">group_rain </p>
|
|
<p>The measurement unit to be used for precipitation. Options are "<span class="code">inch</span>", "<span class="code">cm</span>,"
|
|
or "<span class="code">mm</span>." </p>
|
|
<p class="config_important">group_rainrate </p>
|
|
<p>The measurement unit to be used for rate of precipitation. Possible options
|
|
are one of "<span class="code">inch_per_hour</span>", "<span class="code">cm_per_hour</span>",
|
|
or "<span class="code">mm_per_hour</span>". </p>
|
|
<p class="config_important">group_speed </p>
|
|
<p>The measurement unit to be used for wind speeds. Possible options are one
|
|
of "<span class="code">mile_per_hour</span>", "<span class="code">km_per_hour</span>", "<span class="code">knot</span>",
|
|
or "<span class="code">meter_per_second</span>." </p>
|
|
<p class="config_important">group_speed2 </p>
|
|
<p>This group is similar to <span class="code">group_speed</span>, but is used
|
|
for calculated wind speeds which typically have a slightly higher resolution.
|
|
Possible options are one "<span class="code">mile_per_hour2</span>", "<span class="code">km_per_hour2</span>", "<span class="code">knot2</span>",
|
|
or "<span class="code">meter_per_second2</span>". </p>
|
|
<p><a class="config_important" name="group_temperature">group_temperature</a>
|
|
</p>
|
|
<p>The measurement unit to be used for temperatures. Options are "<span class="code">degree_F</span>"
|
|
or "<span class="code">degree_C</span>." </p>
|
|
<p class="config_option">group_volt </p>
|
|
<p>The measurement unit to be used for voltages. The only option is "<span class="code">volt</span>."
|
|
</p>
|
|
<h3 id="Units_StringFormats" class="config_section">[[StringFormats]]</h3>
|
|
<p>This sub-section is used to specify what string format is to be used for
|
|
each unit when a quantity needs to be converted to a string. Typically, this
|
|
happens with y-axis labeling on plots and for statistics in HTML file generation.
|
|
For example, the options </p>
|
|
<pre>
|
|
degree_C = %.1f
|
|
inch = %.2f</pre>
|
|
<p>would specify that the given string formats are to be used when formatting
|
|
any temperature measured in degrees Celsius or any precipitation amount measured
|
|
in inches, respectively. The
|
|
<a href="http://docs.python.org/library/string.html#format-specification-mini-language">
|
|
formatting codes are those used by Python</a>, a, and are very similar to C's
|
|
<span class="code">sprintf()</span> codes. </p>
|
|
<p>You can also specify what string to use for an invalid or unavailable measurement
|
|
(value '<span class="code">None</span>'). For example, </p>
|
|
<pre>NONE = " N/A "</pre>
|
|
<h3 id="[[Labels]]" class="config_section">[[Labels]]</h3>
|
|
<p>This subsection specifies what label is to be used for each measurement unit
|
|
type. For example, the options </p>
|
|
<pre>
|
|
degree_F = °F
|
|
inch = ' in'</pre>
|
|
<p>would cause all temperatures to have unit labels '<span class="code">°F</span>'
|
|
and all precipitation to have labels '<span class="code"> in</span>'.
|
|
If any special symbols are to be used (such as the degree sign above) they should
|
|
be encoded in UTF-8. This is generally what most text editors use if you cut-and-paste
|
|
from a character map. Labels used in plot images will be converted to Latin-1
|
|
first (this is all the Python Imaging Library can handle). </p>
|
|
<h3 id="TimeFormats" class="config_section">[[TimeFormats]]</h3>
|
|
<p>This sub-section is used for time labels. It uses
|
|
<a href="http://docs.python.org/library/datetime.html#strftime-behavior">strftime()</a>
|
|
formats. For example </p>
|
|
<pre>
|
|
week = %H:%M on %A
|
|
month = %d-%b-%Y %H:%M</pre>
|
|
<p>would specify that week data should use a format such as "<span class="code">15:20
|
|
on Sunday</span>", while month data should look like "<span class="code">06-Oct-2009
|
|
15:20</span>" </p>
|
|
<p>It also allows the formatting to be set for almanac times: </p>
|
|
<pre>
|
|
ephem_day = %H:%M
|
|
ephem_year = %d-%b-%Y %H:%M</pre>
|
|
<p>The first of these, <span class="code">ephem_day</span>, is used for almanac
|
|
times within the day, such as sunrise or sunset. The second,
|
|
<span class="code">ephem_year</span>, is used for almanac times within the year,
|
|
such as the next equinox or full moon. </p>
|
|
<h3 class="config_section">[[DegreeDays]]</h3>
|
|
<p class="config_important">heating_base <br />
|
|
cooling_base </p>
|
|
<p>Set to the base temperature for calculating heating and cooling degree-days,
|
|
along with the unit to be used. Examples:</p>
|
|
<pre>
|
|
heating_base = 65.0, degree_F
|
|
cooling_base = 20.0, degree_C</pre>
|
|
<h3 id="[[Trend]]" class="config_section">[[Trend]]</h3>
|
|
<p class="config_option">time_delta</p>
|
|
<p>Set to the time difference over which you want trends to be calculated. The
|
|
default is 3 hours.</p>
|
|
<h2 class="config_section">[Labels]</h2>
|
|
<p>This section sets the various labels to use. </p>
|
|
<p class="config_option">hemispheres </p>
|
|
<p>Comma separated list for the labels to be used for the four hemispheres.
|
|
The default is "<span class="code">N, S, E, W</span>". </p>
|
|
<h3 class="config_section">[[Generic]]</h3>
|
|
<p>This sub-sections specifies default labels to be used for each SQL type.
|
|
For example, options </p>
|
|
<pre>
|
|
inTemp = Temperature inside the house
|
|
outTemp = Outside Temperature</pre>
|
|
<p>would cause the given labels to be used for plots involving SQL types
|
|
<span class="code">inTemp </span>and <span class="code">outTemp</span>. </p>
|
|
<h2 class="config_section">[Almanac]</h2>
|
|
<p>This section controls what text to use for the almanac. It consists of only
|
|
one entry </p>
|
|
<p class="config_option">moon_phases </p>
|
|
<p>This option is a comma separated list of labels to be used for the eight
|
|
phases of the moon. Default is "<span class="code">New, Waxing crescent,
|
|
First quarter, Waxing gibbous, Full, Waning gibbous, Last quarter, Waning crescent</span>".
|
|
</p>
|
|
<h2 class="config_section">[FileGenerator]</h2>
|
|
<p>This section is used by generator <span class="code">weewx.reportengine.FileGenerator</span>
|
|
and controls text generation from templates, specifically which files are to
|
|
be produced from which template. </p>
|
|
<h3>Overview of file generation</h3>
|
|
<p>Customization of file generation consists of playing with the various options
|
|
offered below and, failing that, modifying the template files that come with
|
|
the distribution. </p>
|
|
<p>Each template file is named something like <span class="code"><em>D/F.E.tmpl</em></span>,
|
|
where <span class="code">D</span> is the subdirectory the template sits in and
|
|
will also be the subdirectory the results will be put in, and
|
|
<span class="code">F.E</span> is the generated file name. So, given a template
|
|
file with name <span class="code">Acme/index.html.tmpl</span>, the results will
|
|
be put in <span class="code"><em>$HTML_ROOT</em>/Acme/index.html</span>. </p>
|
|
<p>The skin that comes with the standard distribution of <span class="code">
|
|
weewx</span> contains three different kinds of generated output: </p>
|
|
<ol>
|
|
<li>Summary by month. In addition to the naming rules above, if the template
|
|
file has the letters <span class="code">YYYY</span> and
|
|
<span class="code">MM</span> in its name, these will be substituted for
|
|
the year and month, respectively. So, a template with the name
|
|
<span class="code">summary-YYYY-MM.html.tmpl</span> would have name
|
|
<span class="code">summary-2010-03.html</span> for the month of March, 2010.
|
|
The default distribution has been set up to produce NOAA monthly summaries,
|
|
one for each month, as a simple text file (no HTML). </li>
|
|
<li>Summary by year. In addition to the naming rules above, if the
|
|
template file has the letters <span class="code">YYYY</span> in its name,
|
|
the year will be substituted. The default distribution has been set up to
|
|
produce NOAA yearly summaries, one for each year, as a simple text file
|
|
(no HTML). </li>
|
|
<li>Summary "To Date". The default distribution has been set up
|
|
to produce reports for the day, week, month, and year-to-date observations.
|
|
These four files are all HTML files. The first, the daily summary (output
|
|
file i<span class="code">ndex.html</span>), includes a drop-down list that
|
|
allows the NOAA month and yearly summaries to be displayed. </li>
|
|
</ol>
|
|
<h3>General</h3>
|
|
<p class="config_option">encoding </p>
|
|
<p>This option controls which encoding is to be used for the generated output.
|
|
There are 3 possible choices: </p>
|
|
<table class="center" style="width: 60%">
|
|
<tr>
|
|
<td class="text_highlight">Encoding</td>
|
|
<td><strong>ComComments</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">html_entities</td>
|
|
<td>Non 7-bit characters will be represented as HTML entities (<em>e.g.</em>
|
|
the degree sign will be represented as <span class="code">&#176;</span>)</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">utf8</td>
|
|
<td>Non 7-bit characters will be represented in UTF-8.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">strict_ascii</td>
|
|
<td>Non 7-bit characters will be ignored.</td>
|
|
</tr>
|
|
</table>
|
|
<p>By default, the encoding <span class="code">html_entities</span> is used
|
|
for HTML files, <span class="code">strict_ascii</span> for the NOAA template
|
|
files. </p>
|
|
<h3 class="config_section">[[SummaryByMonth]]</h3>
|
|
<p>This section controls which summaries-by-month are generated. For each such
|
|
summary, it should have its own sub-subsection, with option
|
|
<span class="code">template</span> listing the template to be used. The default
|
|
configuration generates NOAA-by-month summaries and is summarized below as an
|
|
example. Additional "by month" summaries can be added easily by following
|
|
the same pattern. </p>
|
|
<h4 class="config_section">[[[NOAA_month]]]</h4>
|
|
<p class="config_option">encoding </p>
|
|
<p>Set to <span class="code">strict_ascii</span> for the NOAA monthly summary.
|
|
</p>
|
|
<p class="config_option">template </p>
|
|
<p>This option is set to the source template for the NOAA monthly summary,
|
|
<span class="code">NOAA/NOAA-YYYY-MM.txt.tmpl</span>. </p>
|
|
<h3 class="config_section">[[SummaryByYear]]</h3>
|
|
<p>This section controls which summaries-by-year are generated. For each such
|
|
summary, it should have its own sub-subsection, with option
|
|
<span class="code">template</span> listing the template to be used. The default
|
|
configuration generates NOAA-by-year summaries and is summarized below as an
|
|
example. Additional "by year" summaries can be added easily by following
|
|
the pattern. </p>
|
|
<h4 class="config_section">[[[NOAA_year]]]</h4>
|
|
<p class="config_option">encoding </p>
|
|
<p>Set to <span class="code">strict_ascii</span> for the NOAA year summary.
|
|
</p>
|
|
<p class="config_option">template </p>
|
|
<p>This option is set to the source template for the NOAA yearly summary,
|
|
<span class="code">NOAA/NOAA-YYYY.txt.tmpl</span>. </p>
|
|
<h3 class="config_section">[[ToDate]]</h3>
|
|
<p>This section controls which observations-to-date are generated. The default
|
|
configuration generates four files: one for day, week, month, and year. Although
|
|
the sub-subsections below have names such as 'week' or 'month',
|
|
this is not used in their generation. Output is set by the template
|
|
<em>content</em>, not the name of the sub-subsection — the names below could
|
|
as easily have been'Fred', 'Mary', 'Peter', and 'George'
|
|
and had the same output. </p>
|
|
<p>Additional observations-to-date pages can be created easily by adding a new
|
|
sub-subsection and giving it a unique name ("Jill"?), then giving
|
|
the path to its template as option <span class="code">template</span>. </p>
|
|
<h4 class="config_section">[[[day]]]</h4>
|
|
<p class="config_option">template </p>
|
|
<p>Set to <span class="code">index.html.tmpl</span>, which contains the template
|
|
for the day summary. </p>
|
|
<h4 class="config_section">[[[week]]]</h4>
|
|
<p class="config_option">template </p>
|
|
<p>Set to <span class="code">week.html.tmpl</span>, which contains the template
|
|
for the week summary. </p>
|
|
<h4 class="config_section">[[[month]]]</h4>
|
|
<p class="config_option">template </p>
|
|
<p>Set to <span class="code">month.html.tmpl</span>, which contains the template
|
|
for the month summary. </p>
|
|
<h4 class="config_section">[[[year]]]</h4>
|
|
<p class="config_option">template </p>
|
|
<p>Set to <span class="code">year.html.tmpl</span>, which contains the template
|
|
for the year summary. </p>
|
|
<h4 class="config_section">[[[RSS]]]</h4>
|
|
<p class="config_option">template </p>
|
|
<p>Set to <span class="code">RSS/weewx_rss.xml.tmpl</span>, which contains a
|
|
template for an RSS feed. </p>
|
|
<h4 class="config_section">[[[Mobile]]]</h4>
|
|
<p class="config_option">template </p>
|
|
<p>Set to <span class="code">mobile.html.tmpl</span>, which contains a template
|
|
for a page formatted for mobile phones. </p>
|
|
<h2 class="config_section">[CopyGenerator]</h2>
|
|
<p>This section is used by generator <span class="code">weewx.reportengine.CopyGenerator</span>
|
|
and controls which files are to be copied over from the skin subdirectory to
|
|
the destination directory. Think of it as "file generation," except
|
|
that rather than going through the template engine, the files are simply copied
|
|
over. </p>
|
|
<p class="config_option">copy_once </p>
|
|
<p>This option controls which files get copied over on the first invocation
|
|
of the report engine service. Typically, this is things such as style sheets
|
|
or background GIFs. Wildcards can be used. </p>
|
|
<p class="config_option">copy_always </p>
|
|
<p>This is a list of files that should be copied on every invocation. Wildcards
|
|
can be used. </p>
|
|
<h2 class="config_section">[ImageGenerator]</h2>
|
|
<p>This section is used by generator <span class="code">weewx.reportengine.ImageGenerator</span>
|
|
and controls which images (plots) get generated and with which options. While
|
|
complicated, it is extremely flexible and powerful. </p>
|
|
<h3>Time periods</h3>
|
|
<p>The section consists of one or more sub-sections, one for each time period
|
|
(day, week, month, and year). These sub-sections define the nature of aggregation
|
|
and plot types for the time period. For example, here's a typical set of
|
|
options for sub-section <span class="code">[[month_images]]</span>, controlling
|
|
how images that cover a month period are generated: </p>
|
|
<pre>
|
|
[[month_images]]
|
|
x_label_format = %d
|
|
bottom_label_format = %m/%d/%y %H:%M
|
|
time_length = 2592000 # == 30 days
|
|
aggregate_type = avg
|
|
aggregate_interval = 10800 # == 3 hours</pre>
|
|
<p>The option <span class="code">x_label_format</span> gives a
|
|
<a href="http://docs.python.org/library/datetime.html#strftime-behavior">strftime()</a>
|
|
type format for the x-axis. In this example, it will only show days (format
|
|
option "<span class="code">%d</span>"). The <span class="code">bottom_label_format</span>
|
|
is the format used to time stamp the image at the bottom. In this example, it
|
|
will show the time as <span class="code">10/25/09 15:35</span>. A plot will
|
|
cover a nominal 30 days, and all items included in it will use an aggregate
|
|
type of averaging over 3 hours. </p>
|
|
<h3>Image files</h3>
|
|
<p>Within each sub-section is another nesting, one for each image to be generated.
|
|
The title of each sub-sub-section is the filename to be used for the image.
|
|
Finally, at one additional nesting level (!) are the logical names of all the
|
|
line types to be drawn in the image. Values specified in the level above
|
|
can be overridden. For example, here's a typical set of options for sub-sub-section
|
|
<span class="code">[[[monthrain]]]</span>: </p>
|
|
<pre>
|
|
[[[monthrain]]]
|
|
plot_type = bar
|
|
yscale = None, None, 0.02
|
|
[[[[rain]]]]
|
|
aggregate_type = sum
|
|
aggregate_interval = 86400
|
|
label = Rain (daily avg)</pre>
|
|
<p>This will generate an image file with name <span class="code">monthrain.png</span>.
|
|
It will be a bar plot. Option <span class="code">yscale</span> controls the
|
|
y-axis scaling — if left out, the scale will automatically be chosen. However,
|
|
in this example we are choosing to exercise some degree of control by specifying
|
|
values explicitly. The option takes a 3-way tuple (<span class="code">ylow</span>,
|
|
<span class="code">yhigh</span>, <span class="code">min_interval</span>), where
|
|
<span class="code">ylow</span> and <span class="code">yhigh</span> are the minimum
|
|
and maximum y-axis values, respectively, and <span class="code">min_interval</span>
|
|
is the minimum tick interval. If set to '<span class="code">None</span>',
|
|
the corresponding value will be automatically chosen. So, in this example, the
|
|
setting</p>
|
|
<p class="tty">yscale = None, None, 0.02</p>
|
|
<p>will cause <span class="code">weewx</span> to pick sensible y minimum and
|
|
maximum values, but require that the tick increment (<span class="code">min_interval</span>)
|
|
be at least 0.02. </p>
|
|
<p>Continuing on with the example above, there will be only one plot "line"
|
|
(it will actually be a series of bars) and it will have logical name "<span class="code">rain</span>".
|
|
Because we haven't said otherwise, the SQL data type to be used for this
|
|
line will be the same as its logical name, that is, <span class="code">rain</span>,
|
|
but this can be overridden (see below). The aggregation type will be summing
|
|
(overriding the averaging specified in sub-section <span class="code">[[month_images]]</span>),
|
|
so you get the total rain over the aggregate period (rather than the average)
|
|
over an aggregation interval of 86,400 seconds (one day). The plot line will
|
|
be titled with the indicated label ('<span class="code">Rain (daily avg)</span>')
|
|
</p>
|
|
<p>If there is a time gap in the data, the options <span class="code">line_gap_fraction</span> and
|
|
<span class="code">bar_gap_fraction</span>
|
|
control how it will be drawn. The former, <span class="code">line_gap_fraction</span>, is used for line
|
|
graphs, the latter, <span class="code">bar_gap_fraction</span>, for bar graphs. Here's what the resultant
|
|
plots look like without and with this option being specified:</p>
|
|
<table class="center">
|
|
<tr>
|
|
<td>
|
|
<div class="image">
|
|
<img alt="Gap not shown" height="197" src="day-gap-not-shown.png" width="334" /></div>
|
|
<div class="caption">
|
|
With no <span class="code">line_gap_fraction</span> specified</div>
|
|
</td>
|
|
<td>
|
|
<div class="image">
|
|
<img alt="Gap showing" height="197" src="day-gap-showing.png" width="334" />
|
|
</div>
|
|
<div class="caption">
|
|
With <span class="code">line_gap_fraction=0.01</span></div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<h3>Including more than one SQL type in a plot</h3>
|
|
<p>More than one SQL type can be included in a plot. For example, here's
|
|
how to generate a plot with the week's outside temperature as well as dewpoint:
|
|
</p>
|
|
<pre>
|
|
[[[monthtempdew]]]
|
|
[[[[outTemp]]]]
|
|
[[[[dewpoint]]]]</pre>
|
|
<p>This would create an image in file <span class="code">monthtempdew.png</span>
|
|
that includes a line plot of both outside temperature and dewpoint. </p>
|
|
<h3>Including the same SQL type more than once in a plot</h3>
|
|
<p>Another example. Say you want a plot of the day's temperature, overlaid
|
|
with hourly averages. Here, you are using the same data type ('<span class="code">outTemp</span>')
|
|
for both plot lines, the first with averages, the second without. If you do
|
|
the obvious it won't work: </p>
|
|
<pre>
|
|
## WRONG ##
|
|
[[[daytemp_with_avg]]]
|
|
[[[[outTemp]]]]
|
|
aggregate_type = avg
|
|
aggregate_interval = 3600
|
|
[[[[outTemp]]]] # OOPS! The same section name appears more than once!</pre>
|
|
<p>The option parser does not allow the same section name ('<span class="code">outTemp</span>'
|
|
in this case) to appear more than once at a given level in the configuration
|
|
file, so an error will be declared (technical reason: formally, the sections
|
|
are an unordered dictionary). If you wish for the same SQL type to appear more
|
|
than once in a plot then there is a trick you must know: use option
|
|
<span class="code">data_type</span>. This will override the default action that
|
|
the logical line name is used for the SQL type. So, our example would look like
|
|
this: </p>
|
|
<pre>
|
|
[[[daytemp_with_avg]]]
|
|
[[[[a_logical_name]]]]
|
|
data_type = outTemp
|
|
aggregate_type = avg
|
|
aggregate_interval = 3600
|
|
label = Avg. Temp.
|
|
[[[[outTemp]]]]</pre>
|
|
<p>Here, the first logical line has been given the name "<span class="code">a_logical_name</span>"
|
|
to distinguish it from the second line "<span class="code">outTemp</span>".
|
|
We have specified that the first line will use data type <span class="code">
|
|
outTemp</span> and that it will use averaging over a one hour period. The second
|
|
also uses <span class="code">outTemp</span>, but will not use averaging. </p>
|
|
<p>The result is a nice plot of the day's temperature, overlaid with a 3-hour
|
|
smoothed average: </p>
|
|
<p class="center">
|
|
<img alt="Daytime temperature with running average" height="180" src="daytemp_with_avg.png" width="300" />
|
|
</p>
|
|
<p>One more example. This one shows daily high and low temperatures for a year:</p>
|
|
<p class="tty">
|
|
[[year_images]]<br />
|
|
...<br />
|
|
[[[yearhilow]]]<br />
|
|
[[[[hi]]]]<br />
|
|
data_type = outTemp<br />
|
|
aggregate_type = max<br />
|
|
label = High<br />
|
|
[[[[low]]]]<br />
|
|
date_type = outTemp<br />
|
|
aggregate_type = min<br />
|
|
label = Low Temperature</p>
|
|
<p>This results in the plot <span class="code">yearhilow.png</span>:</p>
|
|
<p class="center"><img alt="Daily highs and lows" src="yearhilow.png" /> </p>
|
|
<h3>Progressive vector plots</h3>
|
|
<p><span class="code">Weewx</span> can produce progressive vector plots as well
|
|
as the more conventional x-y plots. To produce these, use plot type '<span class="code">vector</span>'.
|
|
You need a vector type to produce this kind of plot. There are two: '<span class="code">windvec</span>',
|
|
and '<span class="code">windgustvec</span>'. While they don't actually
|
|
appear in the SQL database, <span class="code">weewx</span> understands that
|
|
they represent special vector-types. The first, '<span class="code">windvec</span>',
|
|
represents the average wind in an archive period, the second, '<span class="code">windgustvec</span>'
|
|
the max wind in an archive period. Here's how to produce a progressive vector
|
|
for one week that shows the hourly biggest wind gusts, along with hourly averages:
|
|
</p>
|
|
<pre>
|
|
[[[weekgustoverlay]]]
|
|
aggregate_interval = 3600
|
|
[[[[windvec]]]]
|
|
label = Hourly Wind
|
|
plot_type = vector
|
|
aggregate_type = avg
|
|
[[[[windgustvec]]]]
|
|
label = Gust Wind
|
|
plot_type = vector
|
|
aggregate_type = max</pre>
|
|
<p>This will produce an image file with name <span class="code">weekgustoverlay.png</span>.
|
|
It will consist of two progressive vector plots, both using hourly aggregation
|
|
(3,600 seconds). For the first set of vectors, the hourly average will be used.
|
|
In the second, the max of the gusts will be used: </p>
|
|
<p class="center">
|
|
<img alt="hourly average wind vector overlaid with gust vectors" height="180" src="weekgustoverlay.png" width="300" />
|
|
</p>
|
|
<p>By default, the sticks in the progressive wind plots point towards the wind
|
|
source. That is, the stick for a wind from the west will point left. If you
|
|
have a chronic wind direction (as I do), you may want to rotate the default
|
|
direction so that all the vectors don't line up over the x-axis, overlaying
|
|
each other. Do this by using option <span class="code">vector_rotate</span>.
|
|
For example, with my chronic westerlies, I set <span class="code">vector_rotate</span>
|
|
to 90.0 for the plot above, so winds out of the west point straight up. </p>
|
|
<p>If you use this kind of plot (the out-of-the-box version of
|
|
<span class="code">weewx</span> includes daily, weekly, monthly, and yearly
|
|
progressive wind plots), a small compass rose will be put in the lower-left
|
|
corner of the image to show the orientation of North. </p>
|
|
<h3>Overriding values</h3>
|
|
<p>Remember that values at any level can override values specified at a higher
|
|
level. For example, say you want to generate the standard plots, but for a few
|
|
key observation types such as barometer, you want to also generate some oversized
|
|
plots to give you extra detail, perhaps for an HTML popup. The standard
|
|
<span class="code">weewx.conf</span> file specifies plot size of 300x180 pixels,
|
|
which will be used for all plots unless overridden: </p>
|
|
<pre>
|
|
[Images]
|
|
...
|
|
image_width=300
|
|
image_height = 180</pre>
|
|
<p>The standard plot of barometric pressure will appear in
|
|
<span class="code">daybarometer.png</span>: </p>
|
|
<pre>
|
|
[[[daybarometer]]]
|
|
[[[[barometer]]]] </pre>
|
|
<p>We now add our special plot of barometric pressure, but specify a larger
|
|
image size. This image will be put in file an class="code" daybarometer_big.png.
|
|
</p>
|
|
<pre>
|
|
[[[daybarometer_big]]]
|
|
image_width = 600
|
|
image_height = 360
|
|
[[[[barometer]]]]</pre>
|
|
<h2 class="config_section">[Generators]</h2>
|
|
<p class="config_option">generator_list </p>
|
|
<p>This option controls which generators get run for this skin. It is a comma
|
|
separated list. The generators will be run in this order. </p>
|
|
<h1 id="Customizing_the_weewx_service_engine">Customizing the
|
|
<span class="code">weewx</span> service engine</h1>
|
|
<p>This is an advance topic intended for those who wish to try their hand at
|
|
extending the internal engine in weewx. You should have a passing familiarity
|
|
with Python or, at least, be willing to learn it. </p>
|
|
<p><em>Please note that the service engine is likely to change in future versions!
|
|
</em></p>
|
|
<p>At a high level, <span class="code">weewx</span> consists of an <em>engine</em>
|
|
that is responsible for managing a set of <em>services</em>. A service consists
|
|
of a Python class which binds its member functions to various <em>events</em>.
|
|
The engine arranges to have the bound member function called when a specific
|
|
event happens, such as a new LOOP packet arriving. </p>
|
|
<p>To customize, you can </p>
|
|
<ul>
|
|
<li>Customize a service </li>
|
|
<li>Add a service </li>
|
|
</ul>
|
|
<p>The default install of <span class="code">weewx</span> includes the following
|
|
services, shown in the order they are normally run:</p>
|
|
<table class="center" style="width: 60%">
|
|
<tr>
|
|
<td class="text_highlight"><strong>Service</strong></td>
|
|
<td><strong>Function</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdConvert</td>
|
|
<td>Converts the units of the input to a target unit system (such as
|
|
US or Metric).</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdCalibrate</td>
|
|
<td>Adjust new LOOP and archive packets using calibration expressions.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdQC</td>
|
|
<td>Check that observation values fall within a specified range.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdArchive</td>
|
|
<td>Archive any new data to the SQL databases.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdTimeSynch</td>
|
|
<td>Arrange to have the clock on the console synchronized at regular
|
|
intervals.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdPrint</td>
|
|
<td>Print out new LOOP and archive packets on the console.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdRESTful</td>
|
|
<td>Start a thread to manage
|
|
<a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">
|
|
RESTful</a> (simple stateless client-server protocols) connections;
|
|
such as those used by the Weather Underground or PWSweather.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">weewx.wxengine.StdReport</td>
|
|
<td>Launch a new thread to do report processing after a new archive
|
|
record arrives. Reports do things such as generate HTML files, generate
|
|
images, or FTP/rsync files to a web server. New reports can be added
|
|
easily by the user.</td>
|
|
</tr>
|
|
</table>
|
|
<h2 id="Preserving_your_changes_across_an_upgrade">Preserving your changes across
|
|
an upgrade</h2>
|
|
<p>Generally, if you change the code in <span class="code">weewx</span> you
|
|
will have to cut-and-paste any changes you have made to the new code. However,
|
|
if you put the changes in the special directory <span class="code"><em>$WEEWX_ROOT</em>/bin/user</span>
|
|
(usually, <span class="code">/home/weewx/bin/user</span>) the setup routines
|
|
arranges for the changes to be preserved across an upgrade. </p>
|
|
<h2 id="Customizing_a_service">Customizing a Service</h2>
|
|
<p>The service <span class="code">weewx.wxengine.StdPrint</span> prints out
|
|
new LOOP and archive packets to the console when they arrive. By default, it
|
|
prints out the entire record, which generally includes a lot of possibly distracting
|
|
information and can be rather messy. Suppose you don't like this, and want
|
|
it to print out only the time, barometer reading, and the outside temperature
|
|
whenever a new LOOP packet arrives. This could be done by subclassing the default
|
|
print service <span class="code">StdPrint</span> and overriding member function
|
|
<span class="code">new_loop_packet()</span>. </p>
|
|
<p>In file <span class="code">bin/user/myprint.py</span>: </p>
|
|
<pre>
|
|
from weewx.wxengine import StdPrint
|
|
from weeutil.weeutil import timestamp_to_string
|
|
|
|
class MyPrint(StdPrint):
|
|
|
|
# Override the default new_loop_packet member function:
|
|
def new_loop_packet(self, event):
|
|
packet = event.packet
|
|
print "LOOP: ", timestamp_to_string(packet['dateTime']),
|
|
"BAR=", packet.get('barometer', 'N/A'),
|
|
"TEMP=", packet.get('outTemp', 'N/A')</pre>
|
|
<p>This service substitutes a new implementation for the member function
|
|
<span class="code">new_loop_packet</span>. This implementation prints out the
|
|
time, then the barometer reading (or '<span class="code">N/A</span>' if it is
|
|
not available) and the outside temperature (or '<span class="code">N/A</span>').</p>
|
|
<p>You then need to specify that your print service class should be loaded instead
|
|
of the default <span class="code">StdPrint</span> service. This is done by substituting
|
|
your service name for <span class="code">StdPrint</span> in
|
|
<span class="code">service_list</span>, located in <span class="code">[Engines][[WxEngine]]</span>:
|
|
</p>
|
|
<pre>
|
|
[Engines]
|
|
[[WxEngine]]
|
|
service_list = weewx.wxengine.StdConvert, weewx.wxengine.StdCalibrate, weewx.wxengine.StdQC, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, user.myprint.MyPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReport</pre>
|
|
<p>(Note that this list must be all on one line. Unfortunately, the parser
|
|
<span class="code">ConfigObj</span> does not allow options to be continued on
|
|
to following lines.) </p>
|
|
<h2 id="Adding_a_Service">Adding a Service</h2>
|
|
<p>Suppose there is no service that can be easily customized for your needs.
|
|
In this case, a new one can easily be created by subclassing off the abstract
|
|
base class <span class="code">StdService</span>, and then adding the functionality
|
|
you need. Here's an example that implements an alarm that sends off an email
|
|
when an arbitrary expression evaluates <span class="code">True</span>. This
|
|
example is included in the standard distribution in subdirectory "<span class="code">bin/examples</span>".
|
|
</p>
|
|
<p>File <span class="code">examples/alarm.py</span>: </p>
|
|
<pre class="tty">
|
|
import time
|
|
import smtplib
|
|
from email.mime.text import MIMEText
|
|
import threading
|
|
import syslog
|
|
|
|
import weewx
|
|
from weewx.wxengine import StdService
|
|
from weeutil.weeutil import timestamp_to_string, option_as_list
|
|
|
|
# Inherit from the base class StdService:
|
|
class MyAlarm(StdService):
|
|
"""Custom service that sounds an alarm if an arbitrary expression evaluates true"""
|
|
|
|
def __init__(self, engine, config_dict):
|
|
# Pass the initialization information on to my superclass:
|
|
super(MyAlarm, self).__init__(engine, config_dict)
|
|
|
|
# This will hold the time when the last alarm message went out:
|
|
self.last_msg_ts = 0
|
|
|
|
try:
|
|
# Dig the needed options out of the configuration dictionary.
|
|
# If a critical option is missing, an exception will be thrown and
|
|
# the alarm will not be set.
|
|
self.expression = config_dict['Alarm']['expression']
|
|
self.time_wait = int(config_dict['Alarm'].get('time_wait', 3600))
|
|
self.smtp_host = config_dict['Alarm']['smtp_host']
|
|
self.smtp_user = config_dict['Alarm'].get('smtp_user')
|
|
self.smtp_password = config_dict['Alarm'].get('smtp_password')
|
|
self.SUBJECT = config_dict['Alarm'].get('subject', "Alarm message from weewx")
|
|
self.FROM = config_dict['Alarm'].get('from', 'alarm@weewx.com')
|
|
self.TO = option_as_list(config_dict['Alarm']['mailto'])
|
|
syslog.syslog(syslog.LOG_INFO, "alarm: Alarm set for expression: \"%s\"" % self.expression)
|
|
|
|
# If we got this far, it's ok to start intercepting events:
|
|
self.bind(weewx.NEW_ARCHIVE_RECORD, self.newArchiveRecord) # NOTE 1
|
|
|
|
except Exception, e:
|
|
syslog.syslog(syslog.LOG_INFO, "alarm: No alarm set. %s" % e)
|
|
|
|
def newArchiveRecord(self, event):
|
|
"""Gets called on a new archive record event."""
|
|
|
|
# To avoid a flood of nearly identical emails, this will do
|
|
# the check only if we have never sent an email, or if we haven't
|
|
# sent one in the last self.time_wait seconds:
|
|
if not self.last_msg_ts or abs(time.time() - self.last_msg_ts) >= self.time_wait :
|
|
# Get the new archive record:
|
|
record = event.record
|
|
# Evaluate the expression in the context of the event archive record.
|
|
# Sound the alarm if it evaluates true:
|
|
if eval(self.expression, None, record): # NOTE 2
|
|
# Sound the alarm!
|
|
# Launch in a separate thread so it doesn't block the main LOOP thread:
|
|
t = threading.Thread(target = MyAlarm.soundTheAlarm, args=(self, record))
|
|
t.start()
|
|
# Record when the message went out:
|
|
self.last_msg_ts = time.time()
|
|
|
|
def soundTheAlarm(self, rec):
|
|
"""This function is called when the given expression evaluates True."""
|
|
|
|
# Get the time and convert to a string:
|
|
t_str = timestamp_to_string(rec['dateTime'])
|
|
|
|
# Log it in the system log:
|
|
syslog.syslog(syslog.LOG_INFO, "alarm: Alarm expression \"%s\" evaluated True at %s" % (self.expression, t_str))
|
|
|
|
# Form the message text:
|
|
msg_text = "Alarm expression \"%s\" evaluated True at %s\nRecord:\n%s" % (self.expression, t_str, str(rec))
|
|
# Convert to MIME:
|
|
msg = MIMEText(msg_text)
|
|
|
|
# Fill in MIME headers:
|
|
msg['Subject'] = self.SUBJECT
|
|
msg['From'] = self.FROM
|
|
msg['To'] = ','.join(self.TO)
|
|
|
|
# Create an instance of class SMTP for the given SMTP host:
|
|
s = smtplib.SMTP(self.smtp_host)
|
|
try:
|
|
# Some servers (eg, gmail) require encrypted transport.
|
|
# Be prepared to catch an exception if the server
|
|
# doesn't support it.
|
|
s.ehlo()
|
|
s.starttls()
|
|
s.ehlo()
|
|
syslog.syslog(syslog.LOG_DEBUG, " **** using encrypted transport")
|
|
except smtplib.SMTPException:
|
|
syslog.syslog(syslog.LOG_DEBUG, " **** using unencrypted transport")
|
|
|
|
try:
|
|
# If a username has been given, assume that login is required for this host:
|
|
if self.smtp_user:
|
|
s.login(self.smtp_user, self.smtp_password)
|
|
syslog.syslog(syslog.LOG_DEBUG, " **** logged in with user name %s" % (self.smtp_user,))
|
|
|
|
# Send the email:
|
|
s.sendmail(msg['From'], self.TO, msg.as_string())
|
|
# Log out of the server:
|
|
s.quit()
|
|
except Exception, e:
|
|
syslog.syslog(syslog.LOG_ERR, "alarm: SMTP mailer refused message with error %s" % (e,))
|
|
raise
|
|
|
|
# Log sending the email:
|
|
syslog.syslog(syslog.LOG_INFO, " **** email sent to: %s" % self.TO) </pre>
|
|
<p>This service expects all the information it needs to be in the configuration
|
|
file <span class="code">weewx.conf</span> in a new section called
|
|
<span class="code">[Alarm]</span>. So, add the following lines to your configuration
|
|
file: </p>
|
|
<pre class="tty">
|
|
[Alarm]
|
|
expression = "outTemp < 40.0"
|
|
time_wait = 3600
|
|
smtp_host = smtp.mymailserver.com
|
|
smtp_user = myusername
|
|
smtp_password = mypassword
|
|
mailto = auser@adomain.com, anotheruser@someplace.com
|
|
from = me@mydomain.com
|
|
subject = "Alarm message from weewx!"</pre>
|
|
<p>There are two important points to be noted in this example, each marked with
|
|
a "<span class="code">NOTE</span>" flag in the code.</p>
|
|
<ol>
|
|
<li>Here is where the binding happens between an event, weewx.NEW_ARCHIVE_RECORD
|
|
in this example, and a member function, self.newArchiveRecord. There are
|
|
other events that can be interecepted. Look in the file ./bin/weewx/__init__.py.</li>
|
|
<li>This is where the test is done of whether or not to sound the alarm.
|
|
The <span class="code">[Alarm]</span> configuration options specify that
|
|
the alarm be sounded when "<span class="code">outTemp < 40.0</span>"
|
|
evaluates <span class="code">True</span>, that is when the outside temperature
|
|
is below 40.0 degrees. Any valid Python expression can be used, although
|
|
the only variables available are those in the current archive record.</li>
|
|
</ol>
|
|
<p>Another example expression could be: </p>
|
|
<pre>
|
|
expression = "outTemp < 32.0 and windSpeed > 10.0"</pre>
|
|
<p>In this case, the alarm is sounded if the outside temperature drops below
|
|
freezing and the wind speed is greater than 10.0. </p>
|
|
<p>Option <span class="code">time_wait</span> is used to avoid a flood of nearly
|
|
identical emails. The new service will wait this long before sending another
|
|
email out. </p>
|
|
<p>Email will be sent through the SMTP host specified by option
|
|
<span class="code">smtp_host</span>. The recipient(s) are specified by the comma
|
|
separated option <span class="code">mailto</span>. </p>
|
|
<p>Many SMTP hosts require user login. If this is the case, the user and password
|
|
are specified with options <span class="code">smtp_user</span> and
|
|
<span class="code">smtp_password</span>, respectively. </p>
|
|
<p>The last two options, "<span class="code">from</span>" and "<span class="code">subject</span>"
|
|
are optional. If not supplied, <span class="code">weewx</span> will supply something
|
|
sensible. Note, however, that some mailers require a valid "from"
|
|
email address and the one <span class="code">weewx</span> supplies may not satisfy
|
|
its requirements. </p>
|
|
<p>To make this all work, you must tell the engine to load this new service.
|
|
This is done by adding your service name to the list <span class="code">service_list</span>,
|
|
located in <span class="code">[Engines][[WxEngine]]</span>: </p>
|
|
<pre>
|
|
[Engines]
|
|
[[WxEngine]]
|
|
service_list = weewx.wxengine.StdConvert, weewx.wxengine.StdCalibrate, weewx.wxengine.StdQC, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReport, examples.alarm.MyAlarm</pre>
|
|
<p>(Note that this list must be all on one line. Unfortunately, the parser
|
|
<span class="code">ConfigObj</span> does not allow options to be continued on
|
|
to following lines.) </p>
|
|
<p>In addition to the example above, the distribution also includes a low-battery
|
|
alarm (<span class="code">lowBattery.py</span>), which is very similar, except
|
|
that it intercepts LOOP events (instead of archiving events). </p>
|
|
<h1>Customizing the archive database</h1>
|
|
<p>For most users the default database will work just fine. It has the added
|
|
advantage of being compatible with the wview database. Nevertheless, there may
|
|
be occasions where you may want to add a SQL type to your database, or change
|
|
its unit system. This section shows you how to do this, using the utility
|
|
<span class="code">./bin/config_database.py</span>.</p>
|
|
<p>Before starting, it's worth running the utility with the
|
|
<span class="code">--help</span> flag to see how it is used:</p>
|
|
<p class="tty">cd /home/weewx<br />
|
|
./bin/config_database.py --help</p>
|
|
<h2>Adding a new observation type</h2>
|
|
<p>Suppose you have installed an electric meter at your house and you wish to
|
|
correlate electrical usage with the weather. The meter has some sort of connection
|
|
to your computer, allowing you to download the consumption. At the end of every
|
|
archive interval you want to sample the meter for the electricity consumed during
|
|
the interval, then store the results in the archive database, along with the
|
|
weather data. How would you do this?</p>
|
|
<p>First, you would write a custom service that retrieves the electrical consumption
|
|
data and adds it to the archive record. See the section
|
|
<a href="#Customizing_the_weewx_service_engine">Customizing the weewx service
|
|
engine</a> for details on how to write a custom service. However, when you are
|
|
done it will look something like this:</p>
|
|
<p class="tty">from weewx.wxengine import StdService<br />
|
|
<br />
|
|
class AddElectricity(StdService):<br />
|
|
<br />
|
|
def new_archive_packet(self, event):<br />
|
|
<br />
|
|
(code that downloads the consumption data from the connection
|
|
to the meter)<br />
|
|
<br />
|
|
event.record['electricity'] = retrieved_value</p>
|
|
<p>This adds a new key '<span class="code">electricity</span>' to the record
|
|
dictionary and sets it equal to some value. As an aside, if you do something
|
|
like this, you would want to make sure that the code to retrieve the current
|
|
electrical consumption does not delay very long so it does not slow down the
|
|
main loop. If it's going to cause a delay of more than a couple seconds you
|
|
might want to put it in a separate thread and feed the results to
|
|
<span class="code">AddElectricity</span> through a queue.</p>
|
|
<p>As usual, you would add your new service to the option <span class="code">
|
|
service_list</span> in <span class="code">weewx.conf</span>, making sure it
|
|
appears before <span class="code">StdArchive</span> so your new value is inserted
|
|
into the record <em>before</em> the data is archived.</p>
|
|
<h3><a id="Adding_a_new_type_to_the_archive_database">Adding a new type to the
|
|
archive database</a></h3>
|
|
<p>So, now you have created a new observation type, '<span class="code">electricity</span>'.
|
|
Trouble is, there is no corresponding type in the schema of the SQL database
|
|
and, therefore, it won't be stored there. How would you add such a type?</p>
|
|
<p>Here's our general strategy:</p>
|
|
<ol>
|
|
<li>Add a new type to the database schema.</li>
|
|
<li>Make sure you have the necessary permissions to create the new database.</li>
|
|
<li>Populate it with data from the old database.</li>
|
|
<li>Shuffle databases around so <span class="code">weewx</span> will use
|
|
the new database.</li>
|
|
<li>Modify the stats database so it includes the new type as well (Optional).</li>
|
|
</ol>
|
|
<p>1. <strong>Adding a new type to the schema.</strong> When creating a database
|
|
the schema is obtained from file <span class="code">./bin/user/schemas.py</span>.
|
|
Take a look at it now. You will see a list called <span class="code">defaultArchiveSchema</span>
|
|
that holds all the observation names and their SQL types. It looks something
|
|
like:</p>
|
|
<pre class="tty">defaultArchiveSchema = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
|
('usUnits', 'INTEGER NOT NULL'),
|
|
('interval', 'INTEGER NOT NULL'),
|
|
('barometer', 'REAL'),
|
|
('pressure', 'REAL'),
|
|
('altimeter', 'REAL'),
|
|
('inTemp', 'REAL'),
|
|
('outTemp', 'REAL'),
|
|
...
|
|
('inTempBatteryStatus', 'REAL')]</pre>
|
|
<p>Let's modify it to add our new type, '<span class="code">electricity</span>'.
|
|
Now it looks like this:</p>
|
|
<pre class="tty">defaultArchiveSchema = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
|
('usUnits', 'INTEGER NOT NULL'),
|
|
('interval', 'INTEGER NOT NULL'),
|
|
('barometer', 'REAL'),
|
|
('pressure', 'REAL'),
|
|
('altimeter', 'REAL'),
|
|
('inTemp', 'REAL'),
|
|
('outTemp', 'REAL'),
|
|
...
|
|
<span class="highlight"> ('electricity', 'REAL'),</span>
|
|
('inTempBatteryStatus', 'REAL')]</pre>
|
|
<p>The new line has been <span class="highlight">highlighted</span>.</p>
|
|
<p>2. <strong>Check permissions.</strong> The reconfiguration utility will create
|
|
a new database with the same name as the old, except with the suffix '<span class="code">_new</span>'
|
|
attached to the end. Make sure you have the necessary permissions to do this.
|
|
In particular, if you are using MySQL, you will need '<span class="code">CREATE</span>'
|
|
privileges.</p>
|
|
<p>3. <strong>Run <span class="code">config_database.py</span>.</strong> Now
|
|
run the utility <span class="code">config_database.py</span> with the
|
|
<span class="code">--reconfigure</span> option and the path to the configuration
|
|
file:</p>
|
|
<p class="tty">prompt: <strong>cd /home/weewx<br />
|
|
</strong>prompt: <strong>./bin/config_database.py --reconfigure ./weewx.conf</strong></p>
|
|
<p>This will create a new database (nominally, <span class="code">weewx.sdb_new</span>
|
|
if you are using sqlite, <span class="code">weewx_new</span> if you are using
|
|
MySQL) using the new schema and populate it with data from the old database.
|
|
</p>
|
|
<p>4. <strong><a name="Shuffle_the_databases">Shuffle the databases</a>.</strong>
|
|
Now arrange things so <span class="code">weewx</span> can find the new database.
|
|
You can either shuffle the databases around so the new database has the same
|
|
name as the old database, or edit <span class="code">weewx.conf</span> to use
|
|
the new database name. To do the former:</p>
|
|
<p><em>First do a backup!</em></p>
|
|
<p>For sqlite:</p>
|
|
<p class="tty">prompt: <strong>cd /home/weewx/archive<br />
|
|
</strong>prompt: <strong>mv weewx.sdb_new weewx.sdb</strong></p>
|
|
<p>For MySQL:</p>
|
|
<p class="tty">prompt: <strong>mysql -u <username> --password=<mypassword><br />
|
|
</strong>mysql> <strong>DROP DATABASE weewx; # Drops the old
|
|
database<br />
|
|
</strong>mysql> <strong>CREATE DATABASE weewx; # Create a new one with the
|
|
same name<br />
|
|
</strong>mysql> <strong>RENAME TABLE weewx_new.archive TO weewx.archive;
|
|
# Rename to the nominal name</strong></p>
|
|
<p>5. <strong>Modify the stats database.</strong> At this point, you can use
|
|
the new observation type in the plots. However, if you wish to use it in the
|
|
statistical summaries, you will also have to add it to the stats database.
|
|
To do this, add the type to the Python list <span class="code">stats_types</span>,
|
|
which can be found in <span class="code">bin/user/schemas.py</span>, so it reads something like this:</p>
|
|
<p class="tty">stats_types = ['barometer', 'inTemp', 'outTemp',
|
|
'inHumidity', 'outHumidity', <br />
|
|
|
|
'rainRate', 'rain', 'dewpoint', 'windchill', 'heatindex', 'ET', <br />
|
|
|
|
'radiation', 'UV', 'extraTemp1', 'rxCheckPercent', 'wind',
|
|
<span class="highlight">'electricity'</span>] </p>
|
|
<p>Now delete the stats database (nominally <span class="code">stats.sdb</span>
|
|
for sqlite, <span class="code">stats</span> for MySQL). Weewx will automatically
|
|
rebuild it, including your new type.</p>
|
|
<h3>Using the new type</h3>
|
|
<p>Now you've added a new type. How do you use it? </p>
|
|
<p>Pretty much like any other type. For example, to do a plot of the month's
|
|
electric consumption, totaled by day, add this section to the
|
|
<span class="code">[[month_images]]</span> section of <span class="code">skin.conf</span>:</p>
|
|
<p class="tty">[[[monthelectric]]]<br />
|
|
[[[[electricity]]]]<br />
|
|
aggregate_type = sum<br />
|
|
aggregate_interval = 86400<br />
|
|
label = Electric consumption (daily total)</p>
|
|
<p>This will cause the generation of an image <span class="code">monthelectric.png</span>,
|
|
showing a plot of each day's consumption for the past month.</p>
|
|
<p>If you wish to use the new type in the templates, it will be available using
|
|
the same syntax as any other type. Here are some other tags that might be useful:</p>
|
|
<table style="width: 70%">
|
|
<tr>
|
|
<td class="text_highlight"><strong>Tag</strong></td>
|
|
<td><strong>Meaning</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$day.electricity.sum</td>
|
|
<td>Total consumption since midnight</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$year.electricity.sum</td>
|
|
<td>Total consumption since the first of the year</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$year.electricity.max</td>
|
|
<td>The most consumed during any archive period</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$year.electricity.maxsum</td>
|
|
<td>The most consumed during a day</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$year.electricity.maxsumtime</td>
|
|
<td>The day it happened.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fixed_highlight">$year.electricity.sum_ge(5.0)</td>
|
|
<td>The number of days where more than 5.0 kWH of energy was consumed.</td>
|
|
</tr>
|
|
</table>
|
|
<h2 id="Changing_the_unit_system">Changing the unit system</h2>
|
|
<p>Normally, data is stored in the databases using US Customary units and, normally,
|
|
you don't care --- data can always be displayed using any units you choose.
|
|
It's an "implementation detail." Nevertheless, there may be special situations
|
|
where you wish to store the data in Metric units. For example, you may need
|
|
to allow direct programmatic access to the databases from another piece of software
|
|
that expects metric units. </p>
|
|
<p>Weewx does not allow you to change the database unit system midstream. You
|
|
can't start with one unit system then, in the middle of the database, switch
|
|
to another. See the section <span class="code">
|
|
<a href="usersguide.htm#[StdConvert]">[StdConvert]</a></span> in the Weewx User's
|
|
Guide. However, you can reconfigure the database by coping it to a new database,
|
|
performing the unit conversion along the way. You then use this new database.</p>
|
|
<p>The steps are pretty much the same as
|
|
<a href="#Adding_a_new_type_to_the_archive_database">Adding a New Type to the
|
|
ArchiveDatabase</a>, described above.</p>
|
|
<ol>
|
|
<li>Modify <span class="code">weewx.conf</span> to reflect your choice of
|
|
the new unit system to use.</li>
|
|
<li>Make sure you have the necessary permissions to create the new database.</li>
|
|
<li>Populate it with data from the old database.</li>
|
|
<li>Shuffle databases around so <span class="code">weewx</span> will use
|
|
the new database.</li>
|
|
<li>Rebuild the stats database to use the new unit system.</li>
|
|
</ol>
|
|
<p>1. <strong>Modify <span class="code">weewx.conf</span>.</strong> Edit the
|
|
configuration file to change option <span class="code">target_unit</span> in
|
|
section <span class="code"><a href="usersguide.htm#[StdConvert]">[StdConvert]</a></span>
|
|
to reflect your choice. If you are switching to metric units, the option will
|
|
look like</p>
|
|
<p class="tty">[StdConvert]<br />
|
|
target_unit = METRIC</p>
|
|
<p>2. <strong>Check permissions.</strong> The reconfiguration utility will create
|
|
a new database with the same name as the old, except with the suffix '<span class="code">_new</span>'
|
|
attached to the end. Make sure you have the necessary permissions to do this.
|
|
In particular, if you are using MySQL, you will need '<span class="code">CREATE</span>'
|
|
privileges.</p>
|
|
<p>3. <strong>Run <span class="code">config_database.py</span>.</strong> Now
|
|
run the utility <span class="code">config_database.py</span> with the
|
|
<span class="code">--reconfigure</span> option:</p>
|
|
<p class="tty">prompt: <strong>cd /home/weewx<br />
|
|
</strong>prompt: <strong>./bin/config_database.py --reconfigure ./weewx.conf</strong></p>
|
|
<p>This will create a new database (nominally, <span class="code">weewx.sdb_new</span>
|
|
if you are using sqlite, <span class="code">weewx_new</span> if you are using
|
|
MySQL), using the schema found in <span class="code">./bin/user/schemas.py</span>,
|
|
and populate it with data from the old database, while performing the unit conversion.</p>
|
|
<p>4. <strong>Shuffle the databases.</strong> This is identical to the description
|
|
<a href="#Shuffle_the_databases">above</a>.</p>
|
|
<p>5. <strong>Recreate the stats database.</strong> Delete the stats database,
|
|
then let <span class="code">weewx</span> regenerate it. It will use the new
|
|
unit system.</p>
|
|
<h1>Porting to new weather station hardware</h1>
|
|
<p>Naturally, this is an advanced topic but, nevertheless, I'd really like to
|
|
encourage any Python wizards out there to give it a try. Of course, I have selfish
|
|
reasons for encouraging you: I don't want to have to go out and buy every type
|
|
of hardware there is! It's expensive and my roof would look like a weather station
|
|
farm.</p>
|
|
<p>Here's the general strategy for doing a port:</p>
|
|
<p>Inherit from the abstract base class <span class="code">weewx.abstractstation.AbstractStation</span>.
|
|
Try to implement as many of its methods as you can. At the very minimum, you
|
|
must implement the following two: </p>
|
|
<p><span class="code">hardware_name</span>: Return a string with a short nickname
|
|
for the hardware, such as "<span class="code">ACME X90</span>"</p>
|
|
<p><span class="code">genLoopPackets</span>: This should be a generator
|
|
function that yields loop packets, one after another. Don't worry about stopping
|
|
it: the engine will do this when an archive record is due. A loop packet is
|
|
a dictionary. At the very minimum it must contain keys</p>
|
|
<table style="width: 50%; margin-left: 10%;">
|
|
<tr>
|
|
<td class="code">dateTime</td>
|
|
<td>The time of the observation in unix epoch time.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">usUnits</td>
|
|
<td>The unit system used. <span class="code">weewx.US</span> for US
|
|
customary, <span class="code">weewx.METRIC</span> for metric. See the
|
|
file <span class="code">bin/weewx/units.py</span>, dictionaries
|
|
<span class="code">USUnits</span> and <span class="code">MetricUnits</span>
|
|
for the exact definition of each.</td>
|
|
</tr>
|
|
</table>
|
|
<p>Then include any observation types you have in the dictionary. Every packet
|
|
need not contain the same set of observation types. Different packets can use
|
|
different unit systems, but all observations within a packet must use the same
|
|
unit system. If your hardware has an error and you don't have a value, you can
|
|
either leave it out of the dictionary or (preferred) set its value to
|
|
<span class="code">None</span>.</p>
|
|
<p>If your hardware does not have an archive record logger, then
|
|
<span class="code">weewx</span> can do the record generation for you. It will
|
|
automatically collect all the types it sees in your loop packets then emit a
|
|
record with the averages (in some cases the sum or max value) of all those types.
|
|
If it doesn't see a type, then it won't appear in the emitted record. If your
|
|
hardware does have a logger, then you should implement method
|
|
<span class="code">genArchiveRecords</span> as well. It should be a generator
|
|
function that returns all the records since a given time. </p>
|
|
<p>A couple of observation types are tricky. In particular, rain. Generally,
|
|
<span class="code">weewx</span> expects to see a packet with the amount of rain
|
|
that fell in that packet period included as observation '<span class="code">rain</span>'.
|
|
It then sums up all the values to get the total rainfall and emits that in the
|
|
archive record. If your hardware does not provide this value, you might have
|
|
to infer it from changes in whatever value it provides, for example changes
|
|
in the daily or monthly rainfall. I know this is not the best solution, but
|
|
it is the most general solution. Any alternatives are welcome!</p>
|
|
<p>Wind is another tricky one. It is actually broken up into four different
|
|
observations: '<span class="code">windSpeed</span>', '<span class="code">windDir</span>',
|
|
'<span class="code">windGust</span>', and '<span class="code">windGustDir</span>'.
|
|
Supply as many as you can. The directions should be compass directions in degrees
|
|
(0=North, 90=East, etc.).</p>
|
|
<p>To load your driver, you should also include a function called '<span class="code">loader</span>'.
|
|
It is a factory function that will return an instance of your driver. Its only
|
|
argument is the configuration dictionary. </p>
|
|
<p>You then include a new section in the configuration file
|
|
<span class="code">weewx.conf</span> that includes any options your driver needs.
|
|
It should also include an entry '<span class="code">driver</span>' that points
|
|
to where your driver can be found. Set option <span class="code">station_type</span>
|
|
to your new section type and your driver will be loaded.</p>
|
|
<p>Take a look at the simulator code in <span class="code">bin/weewx/simulator.py</span>
|
|
for a dirt simple example of a driver. The next most complicated is the driver
|
|
for the WMR-USB series, located in <span class="code">bin/weewx/wmrx.py</span>.
|
|
The driver for the Vantage series is by far the most complicated.</p>
|
|
<p>Naturally, there are a lot of subtleties that I've glossed over in this high-level
|
|
description. If you're game, give it a try — I'm happy to help you out!</p>
|
|
<h1 id="Archive_types">Appendix A: Archive types</h1>
|
|
<p><em>Archive types</em> are weather observations that have come from your
|
|
instrument and been stored in the <em>archive database, </em> a SQL database.
|
|
They represent the <em>current conditions</em> as of some time. They are available
|
|
to be used in two places: </p>
|
|
<ul>
|
|
<li>In your template files as a tag with period <span class="code">$current</span>.
|
|
Hence, the tag <span class="code">$current.outTemp</span> represents the
|
|
latest current outside temperature. There is no aggregation involved (see
|
|
<a href="#Statistical_types">statistical types</a> for aggregation).
|
|
</li>
|
|
<li>In your plot graphs. Here, a line in the graph represents the set of
|
|
current observations over a time period. While each plot point in a graph
|
|
may represent an aggregation, do not confuse this aggregation with the statistical
|
|
aggregation. The former is done with the archive database, the latter with
|
|
the statistical database. </li>
|
|
</ul>
|
|
<p>The following table shows all the possible archive types and whether they
|
|
can be used in tag <span class="code">$current</span> or in a plot. Note that
|
|
just because a type appears in the table does not necessarily mean that it is
|
|
available for <em>your</em> station setup. That would depend on whether your
|
|
instrument supports the type. </p>
|
|
<table class="center" style="width: 80%">
|
|
<tr>
|
|
<td><strong>Archive Type</strong></td>
|
|
<td style="width: 200px"><strong>SQL Type</strong> <br />
|
|
<span class="xxsmall">(appears in archive database)</span></td>
|
|
<td><strong>Can be used <br />
|
|
in plots</strong></td>
|
|
<td><strong>Can be used <br />
|
|
in tag <span class="code">$current</span></strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">altimeter</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">barometer</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">consBatteryVoltage</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">dateTime</td>
|
|
<td>X</td>
|
|
<td></td>
|
|
<td>X (represents current time)</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">dewpoint</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">ET</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">extraHumid1</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">extraHumid2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">extraTemp1</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">extraTemp2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">extraTemp3</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">hail</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">hailRate</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">heatindex</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">heatingTemp</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">heatingVoltage</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">inHumidity</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">inTemp</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">inTempBatteryStatus</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">interval</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">leafTemp2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">leafWet2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">outHumidity</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">outTemp</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">outTempBatteryStatus</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">pressure</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">radiation</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">rain</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">rainBatteryStatus</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">rainRate</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">referenceVoltage</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">rxCheckPercent</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilMoist1</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilMoist2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code" style="height: 33px">soilMoist3</td>
|
|
<td style="height: 33px">X</td>
|
|
<td style="height: 33px">X</td>
|
|
<td style="height: 33px">X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilMoist4</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilTemp1</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilTemp2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilTemp3</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilTemp4</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">supplyVoltage</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">txBatteryStatus</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">usUnits</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">UV</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windvec</td>
|
|
<td> </td>
|
|
<td>X (special vector type)</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windBatteryStatus</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windDir</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windGust</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windGustDir</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windSpeed</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windchill</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
</table>
|
|
<h1 id="Units">Appendix B: Units</h1>
|
|
<p>The table below lists all the unit groups, their members, and which units
|
|
are options for the group. </p>
|
|
<table class="center" style="width: 60%">
|
|
<tr>
|
|
<td><strong>Group</strong></td>
|
|
<td><strong>Members</strong></td>
|
|
<td><strong>Unit options</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">group_altitude</td>
|
|
<td class="code">altitude</td>
|
|
<td class="code">foot <br />
|
|
meter</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_degree_day</td>
|
|
<td>cooldeg<br />
|
|
heatdeg</td>
|
|
<td>degree_F_day<br />
|
|
degree_C_day</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_direction</td>
|
|
<td>gustdir <br />
|
|
vecdir <br />
|
|
windDir <br />
|
|
windGustDir</td>
|
|
<td>degree_compass</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_interval</td>
|
|
<td>interval</td>
|
|
<td>minute</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_moisture</td>
|
|
<td>soilMoist1 <br />
|
|
soilMoist2 <br />
|
|
soilMoist3 <br />
|
|
soilMoist4</td>
|
|
<td>centibar</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_percent</td>
|
|
<td>extraHumid1 <br />
|
|
extraHumid2 <br />
|
|
inHumidity <br />
|
|
outHumidity <br />
|
|
rxCheckPercent</td>
|
|
<td>percent</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_pressure</td>
|
|
<td>barometer <br />
|
|
altimeter <br />
|
|
pressure</td>
|
|
<td>inHg <br />
|
|
mbar <br />
|
|
hPa</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_radiation</td>
|
|
<td>UV <br />
|
|
radiation</td>
|
|
<td>watt_per_meter_squared</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_rain</td>
|
|
<td>rain <br />
|
|
ET <br />
|
|
hail</td>
|
|
<td>in <br />
|
|
cm <br />
|
|
mm</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_rainrate</td>
|
|
<td>rainRate <br />
|
|
hailRate</td>
|
|
<td>in_per_hour <br />
|
|
cm_per_hour <br />
|
|
mm_per_hour</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_speed</td>
|
|
<td>wind <br />
|
|
windGust <br />
|
|
windSpeed <br />
|
|
windgustvec <br />
|
|
windvec</td>
|
|
<td>mile_per_hour <br />
|
|
km_per_hour <br />
|
|
knot <br />
|
|
meter_per_second</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_speed2</td>
|
|
<td>rms <br />
|
|
vecavg</td>
|
|
<td>mile_per_hour2 <br />
|
|
km_per_hour2 <br />
|
|
knot2 <br />
|
|
meter_per_second2</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_temperature</td>
|
|
<td>dewpoint <br />
|
|
extraTemp1 <br />
|
|
extraTemp2 <br />
|
|
extraTemp3 <br />
|
|
heatindex <br />
|
|
heatingTemp <br />
|
|
inTemp <br />
|
|
leafTemp1 <br />
|
|
leafTemp2 <br />
|
|
outTemp <br />
|
|
soilTemp1 <br />
|
|
soilTemp2 <br />
|
|
soilTemp3 <br />
|
|
soilTemp4 <br />
|
|
windchill</td>
|
|
<td>degree_F <br />
|
|
degree_C</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_time</td>
|
|
<td>dateTime</td>
|
|
<td>unix_epoch</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_uv</td>
|
|
<td>UV</td>
|
|
<td>uv_index</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_volt</td>
|
|
<td>consBatteryVoltage <br />
|
|
heatingVoltage <br />
|
|
referenceVoltage <br />
|
|
supplyVoltage</td>
|
|
<td>volt</td>
|
|
</tr>
|
|
<tr class="code">
|
|
<td>group_NONE</td>
|
|
<td>NONE</td>
|
|
<td>NONE</td>
|
|
</tr>
|
|
</table>
|
|
<h1 id="Statistical_types">Appendix C: Statistical types</h1>
|
|
<p>Most of the templates are devoted to reporting <em>statistical types</em>,
|
|
such as temperature, wind, or rainfall, using various <em>aggregates</em>, such
|
|
as min, max, or sum. These are called <em>aggregations</em>, because they are
|
|
a summary of lots of underlying data. However, only certain aggregates make
|
|
sense for certain statistical types. For example, heat degree days is defined
|
|
on a daily basis, so while the day's average temperature is meaningful,
|
|
the day's heating degree days do not. </p>
|
|
<p>The following table defines which aggregates are available to be used in
|
|
your template for which statistical types (assuming your station supports them
|
|
and you have specified that it be stored in your stats database. See section
|
|
<span class="code"><a href="usersguide.htm#[Stats]">[Stats]</a></span> in the
|
|
<span class="code">weewx.conf</span> configuration file). </p>
|
|
<table style="width: 100%">
|
|
<tr>
|
|
<td><em>Stats Type</em></td>
|
|
<td class="code">min</td>
|
|
<td class="code">mintime</td>
|
|
<td class="code">max</td>
|
|
<td class="code">maxtime</td>
|
|
<td class="code">avg</td>
|
|
<td class="code">sum</td>
|
|
<td class="code">rms</td>
|
|
<td class="code">vecavg</td>
|
|
<td class="code">vecdir</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">barometer</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">inTemp</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">outTemp</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">inHumidity</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">outHumidity</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">wind</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">rain</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">dewpoint</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windchill</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">heatindex</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">heatdeg</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">cooldeg</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">ET</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">radiation</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">UV</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">extraTemp1 <br />
|
|
extraTemp2 <br />
|
|
extraTemp3</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilTemp1 <br />
|
|
soilTemp2 <br />
|
|
soilTemp3</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">leafTemp1 <br />
|
|
leafTemp2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">extraHumid1 <br />
|
|
extraHumid2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">soilMoist1 <br />
|
|
soilMoist2 <br />
|
|
soilMoist3 <br />
|
|
soilMoist4</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">leafWet1 <br />
|
|
leafWet2</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">rxCheckPercent</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
<td> </td>
|
|
</tr>
|
|
</table>
|
|
<p> </p>
|
|
<h1 id="Packet_types">Appendix D: Packet types</h1>
|
|
<p><em>Packets</em> are the raw data coming off the instrument (as opposed to
|
|
<em>records</em>, which are stored on the database). The observation types available
|
|
in a packet are useful when setting <em><a href="usersguide.htm#QC">quality
|
|
control rules</a></em> and when doing <em>
|
|
<a href="usersguide.htm#Calibrate">calibrations</a></em>. </p>
|
|
<p>They may also be useful if you are writing your own custom service. In particular,
|
|
for subclasses of <span class="code">StdService</span>, member function
|
|
<span class="code">newLoopPacket</span> is called when new LOOP packets arrive,
|
|
and member function <span class="code">newArchivePacket</span> is called when
|
|
new archive packets arrive. For both functions, the only argument (besides
|
|
<span class="code">self</span>) is a dictionary, where the key is the type listed
|
|
below, and the value is the observation value. </p>
|
|
<p>See the guide from <em>
|
|
<a href="http://www.davisnet.com/support/weather/download/VantageSerialProtocolDocs_v250.pdf">
|
|
Vantage Pro and Pro2 Serial Communications Reference</a></em> (available on
|
|
the Davis website) for more information about these types. </p>
|
|
<table class="center" style="width: 50%">
|
|
<tr>
|
|
<td><strong><em>Type</em></strong></td>
|
|
<td><strong>Loop packet</strong></td>
|
|
<td><strong>Archive Packet</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">barometer</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">consBatteryVoltage</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">dateTime</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">dayET</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">dayRain</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">dewpoint</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">ET</span> (hourly)</td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraAlarm1</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraAlarm2</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraAlarm3</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraAlarm4</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraAlarm5</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraAlarm6</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraAlarm7</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraAlarm8</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraHumid1</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraHumid2</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraHumid3</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraHumid4</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraHumid5</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraHumid6</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraHumid7</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraTemp1</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraTemp2</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraTemp3</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraTemp4</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraTemp5</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraTemp6</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">extraTemp7</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">forecastIcon</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">forecastRule</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">heatIndex</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">highOutTemp</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">highRadiation</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">highUV</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">inHumidity</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">inTemp</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">interval</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">insideAlarm</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">leafTemp1</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">leafTemp2</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">leafTemp3</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">leafTemp4</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">leafWet1</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">leafWet2</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">leafWet3</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">leafWet4</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">lowOutTemp</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">monthET</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">monthRain</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">outHumidity</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">outTemp</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">outsideAlarm1</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">outsideAlarm2</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">radiation</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">rain</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">rainAlarm</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">rainRate</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">rxCheckPercent</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilLeafAlarm1</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilLeafAlarm2</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilLeafAlarm3</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilLeafAlarm4</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilMoist1</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilMoist2</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilMoist3</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilMoist4</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilTemp1</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilTemp2</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilTemp3</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">soilTemp4</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">stormRain</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">stormStart</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">sunrise</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">sunset</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">txBatteryStatus</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">usUnits</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">UV</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">windChill</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">windDir</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">windGust</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">windGustDir</span></td>
|
|
<td> </td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">windSpeed10</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">windSpeed</span></td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">yearET</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">yearRain</span></td>
|
|
<td>X</td>
|
|
<td> </td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<script type="text/javascript">
|
|
samaxesJS.toc({
|
|
exclude : 'h4, h5, h6',
|
|
autoId : true,
|
|
context : 'technical_content'
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|