mirror of
https://github.com/weewx/weewx.git
synced 2026-04-18 08:36:54 -04:00
2564 lines
103 KiB
HTML
2564 lines
103 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$ -->
|
|
|
|
<head>
|
|
<meta content="en-us" http-equiv="Content-Language" />
|
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
|
<title>Customizing weewx</title>
|
|
<style type="text/css">
|
|
body {
|
|
font: 11pt Verdana,arial,sans-serif;
|
|
color: black;
|
|
}
|
|
p {
|
|
font: 11pt Verdana,arial,sans-serif;
|
|
color: black;
|
|
}
|
|
ol {
|
|
font: 11pt Verdana,arial,sans-serif;
|
|
color: black;
|
|
}
|
|
ul {
|
|
font: 11pt Verdana,arial,sans-serif;
|
|
color: black;
|
|
}
|
|
li {
|
|
font: 11pt Verdana,arial,sans-serif;
|
|
color: black;
|
|
}
|
|
dl {
|
|
font: 11pt Verdana,arial,sans-serif;
|
|
color: black;
|
|
}
|
|
dt {
|
|
font: 11pt Verdana,arial,sans-serif;
|
|
color: black;
|
|
}
|
|
dd {
|
|
font: 11pt Verdana,arial,sans-serif;
|
|
color: black;
|
|
}
|
|
h1 {
|
|
font: bold xx-large Verdana, arial, sans-serif;
|
|
color: #FFFFFF;
|
|
border: 1px solid black;
|
|
border-bottom: 2px solid black;
|
|
border-right: 2px solid black;
|
|
background-color: #008080;
|
|
padding-left: .5em;
|
|
padding-right: .5em;
|
|
margin-top: 60pt;
|
|
border-right-width: medium;
|
|
border-bottom-width: medium;
|
|
}
|
|
h2 {
|
|
font: bold x-large Verdana, arial, sans-serif;
|
|
color: teal;
|
|
border: 1px solid black;
|
|
background-color: #e8e8e8;
|
|
padding-left: .5em;
|
|
padding-right: .5em;
|
|
margin-top: 30pt;
|
|
}
|
|
h3 {
|
|
font: bold medium Verdana, arial, sans-serif;
|
|
color: teal;
|
|
border: 1px solid black;
|
|
background-color: #e8e8e8;
|
|
padding-left: .5em;
|
|
padding-right: .5em;
|
|
}
|
|
h4 {
|
|
font: bold medium Verdana, arial, sans-serif;
|
|
color: black;
|
|
}
|
|
.code {
|
|
font-family: "Courier New", Courier, monospace;
|
|
}
|
|
table {
|
|
border-style: solid;
|
|
border-width: 1px;
|
|
border-collapse: collapse;
|
|
}
|
|
td {
|
|
border-style: solid;
|
|
border-width: 1px;
|
|
padding: 5px;
|
|
}
|
|
.indent {
|
|
margin-left: 40px;
|
|
}
|
|
.tty, pre {
|
|
font-family: "Courier New", Courier, monospace;
|
|
margin-left: 40px;
|
|
margin-top: 0px;
|
|
margin-bottom: 0px;
|
|
background-color: #FFFFCC;
|
|
}
|
|
.title {
|
|
text-align: center;
|
|
margin-top: 0px;
|
|
}
|
|
.config_option {
|
|
font-family: "Courier New", Courier, monospace;
|
|
font-weight: normal;
|
|
}
|
|
.config_section {
|
|
font-family: "Courier New", Courier, monospace;
|
|
}
|
|
.config_important {
|
|
font-family: "Courier New", Courier, monospace;
|
|
font-weight: bold;
|
|
color: #0000FF;
|
|
}
|
|
.bold_n_blue {
|
|
color: #0000FF;
|
|
}
|
|
.xxsmall {
|
|
font-size: xx-small;
|
|
}
|
|
.highlight {
|
|
background-color: #FFFF66;
|
|
}
|
|
.center {
|
|
text-align: center;
|
|
}
|
|
.Example_output {
|
|
padding: 10px;
|
|
border: thin #000000 dotted;
|
|
font-family: "Times New Roman", Times, serif;
|
|
margin-left: 40px;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1 class="title">Customizing <span class="code">weewx</span><br />
|
|
Version 1.7</h1>
|
|
<h1>Table of contents</h1>
|
|
<ol>
|
|
<li><a href="#Introduction">Introduction</a></li>
|
|
<li><a href="#Opportunities_for_customizing_reports">Opportunities for customizing
|
|
reports</a></li>
|
|
<li><a href="#Reference:_The_Standard_skin_configuration_file">Reference: The
|
|
Standard skin configuration file</a></li>
|
|
<li><a href="#Customizing_the_weewx_service_engine">Customizing the
|
|
<span class="code">weewx</span> service engine</a></li>
|
|
<li><a href="#Types">Appendix A: Types</a></li>
|
|
<li><a href="#Units">Appendix B: Units</a></li>
|
|
<li><a href="#Statistical_types">Appendix C: Statistical aggregations</a></li>
|
|
</ol>
|
|
<h1>1. <a name="Introduction">Introduction</a></h1>
|
|
<p>This document covers the customization of weewx. It assumes that you have read
|
|
and are reasonably familiar with the <a href="readme.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 skin reports you can probably skip that section and
|
|
just have a look at the options available for the Standard skin configuration file,
|
|
described in the section <em>
|
|
<a href="#Reference:_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>
|
|
<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 any "<em>services</em>"
|
|
that are to be run and 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 align="center" style="width: 60%">
|
|
<tr>
|
|
<td><strong>Service</strong></td>
|
|
<td><strong>Function</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdRESTful</span></td>
|
|
<td>Starts 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><span class="code">weewx.wxengine.StdCatchUp</span></td>
|
|
<td>Any data found on the weather station memory but not yet in the archive,
|
|
is retrieved and put in the archive.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdTimeSynch</span></td>
|
|
<td>Arranges to have the clock on the station synchronized at regular intervals.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdPrint</span></td>
|
|
<td>Prints out new LOOP and archive packets on the console.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdReportService</span></td>
|
|
<td>Launches 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 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>.
|
|
It is also possible to extend the internal engine. 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><a name="The_standard_reporting_service,_StdReportService">The standard reporting
|
|
service, <span class="code">StdReportService</span></a></h3>
|
|
<p>For the moment, we focus on the last service, <span class="code">weewx.wxengine.StdReportService</span>,
|
|
the standard service for creating reports. This will be what most users want to
|
|
customize even if it means just changing a few options.</p>
|
|
<h4>Reports</h4>
|
|
<p>The Standard Report Service runs zero or more <em>Reports.</em> Which ones are
|
|
set in the weewx configuration file <span class="code">weewx.conf</span>, in section
|
|
<span class="code">[Reports]</span>.</p>
|
|
<p>The default distribution of weewx includes two reports:</p>
|
|
<table align="center" style="width: 60%">
|
|
<tr>
|
|
<td><strong>Report</strong></td>
|
|
<td><strong>Default functionality</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">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="code">FTP</td>
|
|
<td>Arranges to upload everything in the <span class="code">public_html</span>
|
|
subdirectory up to a remote webserver.</td>
|
|
</tr>
|
|
</table>
|
|
<p>Note that the FTP "report" is kind of a funny report in that it doesn't actually
|
|
generate anything. Instead, it uses the reporting service engine to arrange for
|
|
things to be FTP'd to a remote server.</p>
|
|
<h4>Skins<br />
|
|
</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 "Report" also uses a skin, and includes a skin configuration
|
|
file, although it is 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. They can also copy
|
|
files around or FTP them to remote locations. The default install of
|
|
<span class="code">weewx </span>includes the following generators:</p>
|
|
<table align="center" style="width: 60%">
|
|
<tr>
|
|
<td><strong>Generator</strong></td>
|
|
<td><strong>Function</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">weewx.filegenerator.FileGenerator</td>
|
|
<td>Generates files from templates. Used to generate HTML and text
|
|
files.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">weewx.imagegenerator.ImageGenerator</td>
|
|
<td>Generates graph plots.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.reportengine.FtpGenerator</span></td>
|
|
<td>Uploads data to a remote server using FTP.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.reportengine.CopyGenerator</span></td>
|
|
<td>Copies files locally.</td>
|
|
</tr>
|
|
</table>
|
|
<p>Note that the two generators <span class="code">FtpGenerator </span>and
|
|
<span class="code">CopyGenerator </span>don't actually generate anything 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>.</p>
|
|
<h2><a name="Databases">Databases</a></h2>
|
|
<p>There are two databases used in weewx, both <a href="http://www.sqlite.org/">SQLITE3</a>
|
|
databases:</p>
|
|
<ul>
|
|
<li>The <em>archive database</em>, nominally located at <span class="code">
|
|
<em>$WEEWX_ROOT</em>/archive/weewx.sdb</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>, nominally located at
|
|
<span class="code"><em>$WEEWX_ROOT</em>/archive/stats.sdb</span>. It
|
|
consists of a separate table for each type, one record per day, keyed by the
|
|
start time of the day. </li>
|
|
</ul>
|
|
<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>2. <a name="Opportunities_for_customizing_reports">Opportunities for customizing
|
|
reports</a></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 going into either <span class="code">weewx.conf</span> or the
|
|
<span class="code">skin.conf</span> that comes
|
|
with the standard distribution and changing a value.</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. Then, you would edit section <span class="code">[Units][[Groups]]</span>
|
|
to read:</p>
|
|
<pre>[Units]</pre>
|
|
<pre> [[Groups]]</pre>
|
|
<pre class="highlight"> group_altitude = meter</pre>
|
|
<pre class="highlight"> group_degree_day = degree_C_day </pre>
|
|
<pre> group_direction = degree_compass</pre>
|
|
<pre> group_moisture = centibar</pre>
|
|
<pre> group_percent = percent</pre>
|
|
<pre class="highlight"> group_pressure = mbar</pre>
|
|
<pre> group_radiation = watt_per_meter_squared</pre>
|
|
<pre class="highlight"> group_rain = mm</pre>
|
|
<pre class="highlight"> group_rainrate = mm_per_hour</pre>
|
|
<pre class="highlight"> group_speed = meter_per_second</pre>
|
|
<pre class="highlight"> group_speed2 = meter_per_second2</pre>
|
|
<pre class="highlight"> group_temperature = degree_C</pre>
|
|
<pre> 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. Suppose your weather instrument 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 "inTemp" option located
|
|
in section [Labels][[Generic]] from </p>
|
|
<pre>[Units]</pre>
|
|
<pre> [[Generic]]</pre>
|
|
<pre> inTemp = Inside Temperature</pre>
|
|
<pre> outTemp = Outside Temperature</pre>
|
|
<pre> ...</pre>
|
|
<p>so that it reads</p>
|
|
<pre>[Units]</pre>
|
|
<pre> [[Generic]]</pre>
|
|
<pre class="highlight"> inTemp = Barn Temperature</pre>
|
|
<pre> outTemp = Outside Temperature</pre>
|
|
<pre> ...</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 overriding some options.
|
|
Here's what your <span class="code">[Report]</span> section in
|
|
<span class="code">weewx.conf</span> would look like:</p>
|
|
<pre>[Reports]</pre>
|
|
<pre>#
|
|
# This section specifies what reports, using which skins, are to be generated.
|
|
#</pre>
|
|
<pre> </pre>
|
|
<pre># Where the skins reside, relative to WEEWX_ROOT:
|
|
SKIN_ROOT = skins
|
|
</pre>
|
|
<pre># Where the generated reports should go, relative to WEEWX_ROOT:
|
|
HTML_ROOT = public_html </pre>
|
|
<pre> </pre>
|
|
<pre> # This report will use US Customary Units</pre>
|
|
<pre class="highlight"> [[USReport]]</pre>
|
|
<pre> # It's based on the Standard skin
|
|
skin = Standard</pre>
|
|
<pre> </pre>
|
|
<pre class="highlight"> # 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</pre>
|
|
<pre> </pre>
|
|
<pre> [[FTP]]</pre>
|
|
<pre> ...</pre>
|
|
<pre> ... (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><a name="Customizing_templates">Customizing templates</a></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 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>$month.outTemp.max</pre>
|
|
<pre>$month.outTemp.maxtime</pre>
|
|
<pre>$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><html></pre>
|
|
<pre> <head></pre>
|
|
<pre> <title>Current conditions</title></pre>
|
|
<pre> </head></pre>
|
|
<pre> <body></pre>
|
|
<pre> <p>Current temperature = $current.outTemp</p></pre>
|
|
<pre> <p>Max for the month is $month.outTemp.max, which occurred at $month.outTemp.maxtime</p></pre>
|
|
<pre> </body></pre>
|
|
<pre></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>## Output max outside temperature using an appropriate format and label:
|
|
$month.outTemp.max</pre>
|
|
<p>Most of the time, this is all you will be using. 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, 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>. Its dot code looks like:</p>
|
|
<pre><em>$current.obstype[.optional_formatting]</em></pre>
|
|
<p>Where:</p>
|
|
<p class="indent"><span class="code"><em>obstype</em></span> is an observation
|
|
type. See <em><a href="#Archive_types">Appendix A,
|
|
Archive Types</a></em> for a table of observation types valid for <span class="code">current.</span></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>.
|
|
The dot code
|
|
looks like:</p>
|
|
<pre><em>$period.statstype.aggregation.[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"><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><a name="Formatting_options">Formatting options</a></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 align="center" style="width: 80%">
|
|
<tr>
|
|
<td>
|
|
<p><strong>Optional formatting tag</strong></p>
|
|
</td>
|
|
<td>
|
|
<p><strong>Comment</strong></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<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>
|
|
<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][[Formats]]</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>
|
|
<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>
|
|
<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][[Formats]]</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="code">
|
|
.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][[Formats]]</a></span>
|
|
will be used. No label will be attached at the end.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<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 align="center" style="width: 80%">
|
|
<tr>
|
|
<td><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><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="code">.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="code">.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="code">.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="code">.nolabel</td>
|
|
<td>User-supplied</td>
|
|
<td>No label</td>
|
|
<td>Optional user-supplied</td>
|
|
<td>string</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">.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 align="center">
|
|
<tr>
|
|
<td><strong>Tag</strong></td>
|
|
<td><strong>Result</strong></td>
|
|
<td><strong>Comment</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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][[Formats]]</a></span> is
|
|
substituted.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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="code">
|
|
$current.dateTime.raw</td>
|
|
<td class="code">
|
|
1270250700</td>
|
|
<td>
|
|
Unix epoch time, converted to string by template engine.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">
|
|
$current.outTemp.raw</td>
|
|
<td class="code">
|
|
45.2</td>
|
|
<td>
|
|
Float returned, converted to string by template engine.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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][[Formats]]</a></span> is
|
|
substituted.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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="code">
|
|
$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><a name="Type_dateTime">Type <span class="code">dateTime</span></a></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), 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-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>
|
|
<p> </p>
|
|
<h3>Unit tags</h3>
|
|
<p>The unit type, label, and string formats are also available,
|
|
allowing you to do highly customized labels:</p>
|
|
<table style="width: 40%" align="center">
|
|
<tr>
|
|
<td><strong>Tag</strong></td>
|
|
<td><strong>Results</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">$unit.unit_type.outTemp</td>
|
|
<td class="code">degree_C</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">$unit.label.outTemp</td>
|
|
<td class="code">°C</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">$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.
|
|
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:</p>
|
|
<pre><html></pre>
|
|
<pre> <head></pre>
|
|
<pre> <title>Year stats by month</title></pre>
|
|
<pre> </head></pre>
|
|
<pre> <body></pre>
|
|
<pre> <p>Min, max temperatures by month:</p></pre>
|
|
<pre> #for $month in $year.months</pre>
|
|
<pre> <p>$month.dateTime.format("%B"): Min, max temperatures: $month.outTemp.min $month.outTemp.max</p></pre>
|
|
<pre> #end for </pre>
|
|
<pre> </body></pre>
|
|
<pre></html></pre>
|
|
<p>Produces results:</p>
|
|
<pre>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>
|
|
<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>Extending an existing 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? 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 stock <span class="code">weewx</span> reports
|
|
offers statistical summaries by day, week, month, and year. Suppose we would like to add
|
|
one more: all-time statistics. This would allow us to display statistics such as
|
|
the all-time high or low temperature seen at your station. </p>
|
|
<p>This example is included in the distribution as <span class="code">examples/mygenerator.py</span>:</p>
|
|
<pre>from weewx.filegenerator import FileGenerator
|
|
from weewx.stats import TimeSpanStats
|
|
from weeutil.weeutil import TimeSpan
|
|
|
|
class MyFileGenerator(FileGenerator): # 1
|
|
|
|
def getToDateSearchList(self, currentRec, stop_ts): # 2
|
|
|
|
# Get a TimeSpan object that represents all time up to the stop time:
|
|
all_time = TimeSpan(self.start_ts, stop_ts) # 3
|
|
|
|
# Get a TimeSpanStats object :
|
|
all_stats = TimeSpanStats(self.statsdb,
|
|
all_time,
|
|
unit_info=self.unit_info) # 4
|
|
|
|
# Get the superclass's search list:
|
|
search_list = FileGenerator.getToDateSearchList(self, currentRec, stop_ts) #5
|
|
|
|
# Now tack on my addition as a small dictionary with key 'alltime':
|
|
search_list += [ {'alltime' : all_stats} ] # 6
|
|
|
|
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 are <span class="code">self</span> (Python's way of
|
|
indicating the instance we are working with), <span class="code">currentRec</span>
|
|
(a dictionary with the current conditions), and <span class="code">stop_ts</span>
|
|
(the ending time for the "to date" summary, in Unix epoch time).</li>
|
|
<li>Attribute <span class="code">self.start_ts</span> is available as the
|
|
earliest time seen in the main archive database. The class <span class="code">TimeSpan</span>
|
|
is a utility class that represents an interval of time. Here, we are
|
|
creating an instance of <span class="code">TimeSpan</span> that represents
|
|
all time preceeding <span class="code">stop_ts</span>.</li>
|
|
<li>Class <span class="code">TimeSpanStats</span> represents a statistical calculation
|
|
over a time period. It takes 3 parameters. The first,
|
|
<span class="code">self.statsdb</span> is the statistical database the
|
|
calculation is to be run against; the second is the timespan over which the
|
|
calculation is to be done; and the third, <span class="code">self.unit_info</span>,
|
|
is an instance of class <span class="code">weewx.units.UnitInfo</span>,
|
|
which contains information about the target units the results are to be
|
|
returned in as well as formatting and labeling information. </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 a single key, '<span class="code">alltime</span>', with value an instance of
|
|
<span class="code">TimeSpanStats</span>.</li>
|
|
</ol>
|
|
<p>With this approach, you can now include "all time" statistics in
|
|
your HTML templates:</p>
|
|
<pre>...</pre>
|
|
<pre>...
|
|
<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>
|
|
... (more table entries)</pre>
|
|
<pre class="tty"> </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">PYTHON_PATH</span>:</p>
|
|
<pre>export PYTHON_PATH=/home/me/secret_location</pre>
|
|
<h1>3. <a name="Reference:_The_Standard_skin_configuration_file">Reference: The Standard
|
|
skin configuration file</a></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>, U, UTF-8 is used throughout. Also, like the weewx.conf, 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 class="config_section"><a name="[Extras]">[Extras]</a></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>
|
|
<h4 class="config_option">radar_url</h4>
|
|
<p>If set, the NOAA radar image will be displayed. If commented out, no image will
|
|
be displayed.</p>
|
|
<h4 class="config_option">googleAnalyticsId</h4>
|
|
<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]</pre>
|
|
<pre> [[video]]</pre>
|
|
<pre> still = video_capture.jpg</pre>
|
|
<pre> 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>
|
|
<h4 class="config_important"><a name="group_altitude">group_altitude</a></h4>
|
|
<p>Which measurement unit to be used for altitude. Possible options are '<span class="code">foot</span>'
|
|
or '<span class="code">meter</span>'.</p>
|
|
<h4 class="config_option">group_direction</h4>
|
|
<p>Which measurement unit to be used for direction. The only option is "<span class="code">degree_compass</span>".</p>
|
|
<h4 class="config_option">group_moisture</h4>
|
|
<p>The measurement unit to be used for soil moisture. The only option is "<span class="code">centibar</span>."</p>
|
|
<h4 class="config_option">group_percent</h4>
|
|
<p>The measurement unit to be used for percentages. The only option is "<span class="code">percent</span>".</p>
|
|
<h4 class="config_important">group_pressure</h4>
|
|
<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>
|
|
<h4 class="config_option">group_radiation</h4>
|
|
<p>The measurement unit to be used for radiation. The only option is "<span class="code">watt_per_meter_squared</span>."</p>
|
|
<h4 class="config_important">group_rain</h4>
|
|
<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>
|
|
<h4 class="config_important">group_rainrate</h4>
|
|
<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>
|
|
<h4 class="config_important">group_speed</h4>
|
|
<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>
|
|
<h4 class="config_important">group_speed2</h4>
|
|
<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>
|
|
<h4 class="config_important"><a name="group_temperature">group_temperature</a></h4>
|
|
<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>
|
|
<h4 class="config_option">group_volt</h4>
|
|
<p>The measurement unit to be used for voltages. The only option is "<span class="code">volt</span>."</p>
|
|
<h3 class="config_section"><a name="Units_StringFormats">[[StringFormats]]</a></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</pre>
|
|
<pre>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 class="config_section"><a name="[[Labels]]">[[Labels]]</a></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</pre>
|
|
<pre>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 class="config_section"><a name="TimeFormats">[[TimeFormats]]</a></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</pre>
|
|
<pre>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>
|
|
<h3 class="config_section">[[DegreeDays]] </h3>
|
|
<h4 class="config_option"><span class="config_important">heating_base<br />
|
|
cooling_base</span></h4>
|
|
<p>Set to the base temperature for calculating heating and cooling degree-days,
|
|
along with the unit to be used:</p>
|
|
<pre>heating_base = 65.0, degree_F
|
|
cooling_base = 65.0, degree_C</pre>
|
|
<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</pre>
|
|
<pre>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>
|
|
<h4 class="config_option">encoding</h4>
|
|
<p>This option controls which encoding is to be used for the generated output. There
|
|
are 3 possible choices:</p>
|
|
<table align="center" style="width: 60%">
|
|
<tr>
|
|
<td><strong>Encoding</strong></td>
|
|
<td><strong>ComComments</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">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="code">utf8</td>
|
|
<td>Non 7-bit characters will be represented in UTF-8.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">strict_ascii</td>
|
|
<td>Non 7-bit characters will be ignoredd> </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>Set to <span class="code">RSS/weewx_rss.xml.tmpl</span>, which contains a
|
|
template for an RSS feed.</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]]</pre>
|
|
<pre> x_label_format = %d</pre>
|
|
<pre> bottom_label_format = %m/%d/%y %H:%M</pre>
|
|
<pre> time_length = 2592000 # == 30 days</pre>
|
|
<pre> aggregate_type = avg</pre>
|
|
<pre> 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> class="tty">[[[[[[monthrain]]]</p>
|
|
<pre> plot_type = bar</pre>
|
|
<pre> yscale = None, None, 0.02</pre>
|
|
<pre> [[[[rain]]]]</pre>
|
|
<pre> aggregate_type = sum</pre>
|
|
<pre> aggregate_interval = 86400</pre>
|
|
<pre> 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. It is a 3-way tuple (<span class="code">ylow</span>,
|
|
<span class="code">yhigh</span>, <span class="code">min_interval</span>), where
|
|
<span class="code">ymin</span> and <span class="code">ymax</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, we are letting
|
|
<span class="code">weewx</span> pick sensible y minimum and maximum values, but
|
|
we are requiring 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>, b, 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>
|
|
<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>
|
|
<p class="tty">[[[monthtempdew]]]</p>
|
|
<p class="tty"> [[[[outTemp]]]]</p>
|
|
<p class="tty"> [[[[dewpoint]]]]</p>
|
|
<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 ##</pre>
|
|
<pre>[[[[[[daytemp_with_avg]]]</pre>
|
|
<pre> [[[[outTemp]]]]</pre>
|
|
<pre> aggregate_type = avg</pre>
|
|
<pre> aggregate_interval = 3600</pre>
|
|
<pre> [[[[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]]]</pre>
|
|
<pre> [[[[a_logical_name]]]]</pre>
|
|
<pre> data_type = outTemp</pre>
|
|
<pre> aggregate_type = avg</pre>
|
|
<pre> aggregate_interval = 3600</pre>
|
|
<pre> label = Avg. Temp. </pre>
|
|
<pre> [[[[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>
|
|
<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]]]</pre>
|
|
<pre> aggregate_interval = 3600</pre>
|
|
<pre> [[[[windvec]]]]</pre>
|
|
<pre> label = Hourly Wind </pre>
|
|
<pre> plot_type = vector</pre>
|
|
<pre> aggregate_type = avg</pre>
|
|
<pre> [[[[windgustvec]]]]</pre>
|
|
<pre> label = Gust Wind </pre>
|
|
<pre> plot_type = vector</pre>
|
|
<pre> 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]</pre>
|
|
<pre> ...</pre>
|
|
<pre> image_width=300</pre>
|
|
<pre> image_height = 180</pre>
|
|
<p>The standard plot of barometric pressure will appear in <span class="code">daybarometer.png</span>:</p>
|
|
<p class="tty"> [[[daybarometer]]]</p>
|
|
<p class="tty"> [[[[barometer]]]] </p>
|
|
<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>
|
|
<p class="tty"> [[[daybarometer_big]]]</p>
|
|
<p class="tty"> image_width = 600</p>
|
|
<p class="tty"> image_height = 360</p>
|
|
<p class="tty"> [[[[barometer]]]]</p>
|
|
<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>
|
|
<h2 class="config_section"> </h2>
|
|
<h1>4. <a name="Customizing_the_weewx_service_engine">Customizing the
|
|
<span class="code">weewx</span> service engine</a></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>At a high level, weewx consists of an <em>engine</em> that is responsible for
|
|
managing a set of <em>services</em>. A service consists of a Python class with a
|
|
set of member functions. The engine arranges to have appropriate member functions
|
|
called when specific events happen. For example, when a new LOOP packet arrives,
|
|
member function <span class="code">processLoopPacket()</span> of all services is
|
|
called.</p>
|
|
<p>To customize, you can</p>
|
|
<ul>
|
|
<li>Customize a service</li>
|
|
<li>Add a service</li>
|
|
<li>Customize the engine</li>
|
|
</ul>
|
|
<p>This section describes how to do all three.</p>
|
|
<p>The default install of <span class="code">weewx</span> includes the following
|
|
services:</p>
|
|
<table style="width: 100%">
|
|
<tr>
|
|
<td><strong>Service</strong></td>
|
|
<td><strong>Function</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdRESTful</span></td>
|
|
<td>Starts thread to manage
|
|
<a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">
|
|
RESTful</a> (simple client-server stateless protocols) connections; adds
|
|
new data to a Queue monitored by the thread. The thread then consumes
|
|
the new data, sending it to sites such as the Weather Underground or
|
|
PWSweather.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdCatchUp</span></td>
|
|
<td>Any data found on the weather station memory but not yet in the archive,
|
|
is retrieved and put in the archive.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdTimeSynch</span></td>
|
|
<td>Arranges to have the clock on the station synchronized at regular intervals.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdPrint</span></td>
|
|
<td>Prints out new LOOP and archive packets on the console.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.wxengine.StdReportService</span></td>
|
|
<td>Launches a new thread to do processing after a new archive record arrives.
|
|
The thread loads zero or more reports and processes them in order. Reports
|
|
do things such as generate HTML files, generate images, or FTP files to
|
|
a web server. New reports can be added easily by the user.</td>
|
|
</tr>
|
|
</table>
|
|
<h2>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 time, barometer, outside temperature, wind speed, and wind direction. Suppose
|
|
you don't like this, and want to print out humidity as well when a new LOOP packet
|
|
arrives, but leave the printing of archive packets alone. This could be done by
|
|
subclassing the default print service <span class="code">StdPrint</span> and overriding
|
|
member function <span class="code">processLoopPacket()</span>. </p>
|
|
<p>In file <span class="code">myprint.py</span>:</p>
|
|
<pre>from weewx.wxengine import StdPrint
|
|
from weeutil.weeutil import timestamp_to_string
|
|
|
|
class MyPrint(StdPrint):
|
|
|
|
# Override the default processLoopPacket:
|
|
def processLoopPacket(self, physicalPacket):
|
|
print "LOOP: ", timestamp_to_string(physicalPacket['dateTime']),\
|
|
physicalPacket['barometer'],\
|
|
physicalPacket['outTemp'],\
|
|
physicalPacket['outHumidity'],\
|
|
physicalPacket['windSpeed'],\
|
|
physicalPacket['windDir']</pre>
|
|
<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 the standard print service name in the option
|
|
<span class="code">service_list</span>, located in <span class="code">[Engines][[WxEngine]]</span>:</p>
|
|
<pre>[Engines]
|
|
[[WxEngine]]
|
|
service_list = weewx.wxengine.StdRESTful, weewx.wxengine.StdCatchUp, weewx.wxengine.StdTimeSynch, myprint.MyPrint, weewx.wxengine.StdReportService</pre>
|
|
<p>(Note that this list must be all on one line. The parser <span class="code">ConfigObj</span>
|
|
does not allow options to be continued on to following lines.)</p>
|
|
<h2>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 True. This example is included in the standard distribution
|
|
in subdirectory "<span class="code">examples</span>".</p>
|
|
<p>File <span class="code">examples/alarm.py</span>:</p>
|
|
<pre>import time
|
|
import smtplib
|
|
from email.mime.text import MIMEText
|
|
import threading
|
|
import syslog
|
|
|
|
from weewx.wxengine import StdService
|
|
from weeutil.weeutil import timestamp_to_string
|
|
|
|
# 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):
|
|
# Pass the initialization information on to my superclass:
|
|
StdService.__init__(self, engine)
|
|
|
|
# This will hold the time when the last alarm message went out:
|
|
self.last_msg_ts = None
|
|
self.expression = None
|
|
|
|
def setup(self):
|
|
|
|
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 = self.engine.config_dict['Alarm']['expression']
|
|
self.time_wait = int(self.engine.config_dict['Alarm'].get('time_wait', 3600))
|
|
self.smtp_host = self.engine.config_dict['Alarm']['smtp_host']
|
|
self.smtp_user = self.engine.config_dict['Alarm'].get('smtp_user')
|
|
self.smtp_password = self.engine.config_dict['Alarm'].get('smtp_password')
|
|
self.TO = self.engine.config_dict['Alarm']['mailto']
|
|
syslog.syslog(syslog.LOG_INFO, "alarm: Alarm set for expression: \"%s\"" % self.expression)
|
|
except:
|
|
self.expression = None
|
|
self.time_wait = None
|
|
|
|
def postArchiveData(self, rec):
|
|
# Let the super class see the record first:
|
|
StdService.postArchiveData(self, rec)
|
|
|
|
# See if the alarm has been set:
|
|
if self.expression:
|
|
# 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 :
|
|
|
|
# Evaluate the expression in the context of 'rec'.
|
|
# Sound the alarm if it evaluates true:
|
|
if eval(self.expression, None, rec): # NOTE 1
|
|
# 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, rec))
|
|
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'])
|
|
# 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'] = "Alarm message from weewx"
|
|
msg['From'] = "weewx"
|
|
msg['To'] = 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()
|
|
except smtplib.SMTPException:
|
|
pass
|
|
# 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)
|
|
# Send the email:
|
|
s.sendmail(msg['From'], [self.TO], msg.as_string())
|
|
# Log out of the server:
|
|
s.quit()
|
|
# Log it in the system log:
|
|
syslog.syslog(syslog.LOG_INFO, "alarm: Alarm sounded for expression: \"%s\"" % self.expression)
|
|
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>[Alarm]
|
|
expression = "outTemp < 40.0"
|
|
time_wait = 3600
|
|
smtp_host = smtp.mymailserver.com
|
|
smtp_user = myusername
|
|
smtp_password = mypassword
|
|
mailto = auser@adomain.com</pre>
|
|
<p>These options specify that the alarm is to be sounded when "<span class="code">outTemp
|
|
< 40.0</span>" evaluates True, 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. (The place in the code where the expression
|
|
is evaluated is marked with "<span class="code">NOTE 1</span>".)</p>
|
|
<p>Another example expression could be:</p>
|
|
<p class="tty"> expression = "outTemp < 32.0 and windSpeed > 10.0"</p>
|
|
<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 is specified in 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>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.StdRESTful, weewx.wxengine.StdCatchUp, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, weewx.wxengine.StdReportService, examples.alarm.MyAlarm</pre>
|
|
<p>(Again, the list must be all on one line.)</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>
|
|
<h2>Customizing the Engine</h2>
|
|
<p>In this section, we look at how to install a custom Engine. In general, this
|
|
is the least desirable way to proceed, but in some cases it may be the only way
|
|
to get what you want.</p>
|
|
<p>For example, suppose you want to define a new event for when the first archive
|
|
of a day arrives. This can be done by extending the the standard engine. </p>
|
|
<p>This example is in file <span class="code">example/daily.py</span>:</p>
|
|
<pre>from weewx.wxengine import StdEngine, StdService
|
|
from weeutil.weeutil import startOfArchiveDay
|
|
|
|
class MyEngine(StdEngine):
|
|
"""A customized weewx engine."""
|
|
|
|
def __init__(self, *args, **vargs):
|
|
# Pass on the initialization data to my superclass:
|
|
StdEngine.__init__(self, *args, **vargs)
|
|
|
|
# This will record the timestamp of the old day
|
|
self.old_day = None
|
|
|
|
def postArchiveData(self, rec):
|
|
# First let my superclass process it:
|
|
StdEngine.postArchiveData(self, rec)
|
|
|
|
# Get the timestamp of the start of the day using
|
|
# the utility function startOfArchiveDay
|
|
dayStart_ts = startOfArchiveDay(rec['dateTime'])
|
|
|
|
# Call the function firstArchiveOfDay if either this is
|
|
# the first archive since startup, or if a new day has started
|
|
if not self.old_day or self.old_day != dayStart_ts:
|
|
self.old_day = dayStart_ts
|
|
self.newDay(rec) # NOTE 1
|
|
|
|
def newDay(self, rec):
|
|
"""Called when the first archive record of a day arrives."""
|
|
|
|
# Go through the list of service objects. This
|
|
# list is actually in my superclass StdEngine.
|
|
for svc_obj in self.service_obj:
|
|
# Because this is a new event, not all services will
|
|
# be prepared to accept it. Be prepared for an AttributeError
|
|
# exception:
|
|
try: # NOTE 2
|
|
svc_obj.firstArchiveOfDay(rec)
|
|
except AttributeError:
|
|
pass</pre>
|
|
<p>This customized engine works by monitoring the arrival of archive records, and
|
|
checking their time stamp (<span class="code">rec['dateTime']</span>. It calculates
|
|
the time stamp for the start of the day, and if it changes, calls member function
|
|
<span class="code">newDay()</span> (NOTE 1). </p>
|
|
<p>The member function <span class="code">newDay()</span> then goes through the
|
|
list of services (attribute <span class="code">self.service_obj</span>). Because
|
|
this engine is defining a new event (first archive of the day), the existing
|
|
services may not be prepared to accept it. So, be prepared to catch an exception
|
|
<span class="code">AttributeError</span> if the service does not define it (NOTE
|
|
2).</p>
|
|
<p>To use this engine, go into file <span class="code">weewxd.py</span> and change
|
|
the line</p>
|
|
<p class="tty">weewx.wxengine.main()</p>
|
|
<p>so that it uses your new engine:</p>
|
|
<pre>from examples.daily import MyEngine
|
|
|
|
# Specify that my specialized engine should be used instead
|
|
# of the default:
|
|
weewx.wxengine.main(EngineClass = MyEngine)</pre>
|
|
<p>We now have a new engine that defines a new event ("<span class="code">firstArchiveOfDay</span>"),
|
|
but there is no service to take advantage of it. We define a new service:</p>
|
|
<pre># Define a new service to take advantage of the new event
|
|
class DailyService(StdService):
|
|
"""This service can do something when the first archive record of
|
|
a day arrives."""
|
|
|
|
def firstArchiveOfDay(self, rec):
|
|
"""Called when the first archive record of a day arrives."""
|
|
|
|
print "The first archive of the day has arrived!"
|
|
print rec
|
|
|
|
# You might want to do something here like run a cron job</pre>
|
|
<p>This service will simply print out a notice and then print out the new record.
|
|
However, if there is some daily processing you want to do, perhaps a backup, or
|
|
running utility <a href="http://www.weewx.com/wunderfixer">wunderfixer</a>, this
|
|
would be the place to do it.</p>
|
|
<p>The final step is to go into your configuration file and specify that this new
|
|
service be loaded, by adding its class name to option <span class="code">service_list</span>:</p>
|
|
<pre>[Engines]
|
|
|
|
[[WxEngine]]
|
|
# The list of services the main weewx engine should run:
|
|
service_list = weewx.wxengine.StdRESTful, weewx.wxengine.StdCatchUp, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, weewx.wxengine.StdReportService, examples.daily.DailyService</pre>
|
|
<p>(Again, the list must be all on one line.)</p>
|
|
<h1>Appendix A: <a name="Archive_types">Archive types</a></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 align="center" style="width: 80%">
|
|
<tr>
|
|
<td><strong>Name</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">soilMoist3</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>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>Appendix B: <a name="Units">Units</a></h1>
|
|
<p>The table below lists all the unit groups, their members, and which units are
|
|
options for the group.</p>
|
|
<table align="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_direction</td>
|
|
<td>gustdir<br />
|
|
vecdir<br />
|
|
windDir<br />
|
|
windGustDir</td>
|
|
<td>degree_compass</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_degree_day</td>
|
|
<td>heatdef<br />
|
|
cooldeg</td>
|
|
<td>degree_F_day<br />
|
|
degree_C_day</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>Appendix C: <a name="Statistical_types">Statistical types</a></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="readme.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>
|
|
|
|
</body>
|
|
|
|
</html>
|