mirror of
https://github.com/weewx/weewx.git
synced 2026-06-09 09:35:19 -04:00
2022 lines
81 KiB
HTML
2022 lines
81 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 weewx v1.6</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_aggregations">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 Users Guide.</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.StdWunderground</span></td>
|
|
<td>Starts thread to manage WU connection; adds new data to a Queue to be
|
|
posted to the WU by the thread.</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>
|
|
<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 HTML files from templates. </td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">weewx.imagegenerator.ImageGenerator</td>
|
|
<td>Generates image plots</td>
|
|
</tr>
|
|
<tr>
|
|
<td><span class="code">weewx.reportengine.FtpGenerator</span></td>
|
|
<td>FTP uploads data</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>
|
|
<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>By changing options</h2>
|
|
<p>Changing an option means going into either weewx.conf or the skin.conf that comes
|
|
with the standard distribution and changing a value.</p>
|
|
<h3>By 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 weewx, 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> group_altitude = meter</pre>
|
|
<pre> group_direction = degree_compass</pre>
|
|
<pre> group_moisture = centibar</pre>
|
|
<pre> group_percent = percent</pre>
|
|
<pre> group_pressure = mbar</pre>
|
|
<pre> group_radiation = watt_per_meter_squared</pre>
|
|
<pre> group_rain = mm</pre>
|
|
<pre> group_rainrate = mm_per_hour</pre>
|
|
<pre> group_speed = meter_per_second</pre>
|
|
<pre> group_speed2 = meter_per_second2</pre>
|
|
<pre> group_temperature = degree_C</pre>
|
|
<pre> group_volt = volt</pre>
|
|
<p>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 label for various observation
|
|
types. Suppose your weather instrument console is actually located in a barn, not
|
|
indoors, and you want its plot 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> inTemp = Barn Temperature</pre>
|
|
<pre> outTemp = Outside Temperature</pre>
|
|
<pre> ...</pre>
|
|
<h3>By overriding options</h3>
|
|
<p>This approach is very similar, except that instead of changing the skin configuration,
|
|
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
|
|
[[USReport]]
|
|
# It's based on the Standard skin
|
|
skin = Standard</pre>
|
|
<pre> </pre>
|
|
<pre> # This report will use metric units: </pre>
|
|
<pre> [[MetricReport]]</pre>
|
|
<pre> # It's also based on the Standard skin:</pre>
|
|
<pre> skin = Standard </pre>
|
|
<pre> # However, override where the results will go and put them in a subdirectory:</pre>
|
|
<pre> HTML_ROOT = public_html/metric</pre>
|
|
<pre> </pre>
|
|
<pre> # And override the options that were not in metric units</pre>
|
|
<pre> [[[Units]]]
|
|
[[[[Groups]]]]
|
|
group_altitude = meter</pre>
|
|
<pre> group_pressure = mbar</pre>
|
|
<pre> group_rain = mm</pre>
|
|
<pre> group_rainrate = mm_per_hour</pre>
|
|
<pre> group_speed = meter_per_second</pre>
|
|
<pre> group_speed2 = meter_per_second2</pre>
|
|
<pre> 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>By <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>Generally, any value substituted by the engine is specified by using a 'dot'
|
|
code. 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="#Labels_Time">[Labels][[Time]]</a></span>.</p>
|
|
<p>The "dot" code has up to three parts. </p>
|
|
<ol>
|
|
<li>The first part is the time period, and can be one of <span class="code">
|
|
current</span>, <span class="code">day</span>, <span class="code">week</span>,
|
|
<span class="code">month</span>, <span class="code">year</span>, or
|
|
<span class="code">rainyear</span>.</li>
|
|
<li>The second part is the "statistical type". This is something like '<span class="code">outTemp</span>',
|
|
'<span class="code">rain</span>', '<span class="code">wind</span>', etc. The
|
|
statistical types are generally those that appear in the SQL databases with
|
|
three exceptions. First, type '<span class="code">wind</span>' is a special
|
|
hybrid type and does not appear in the SQL database. It brings together the
|
|
several different SQL types '<span class="code">windSpeed</span>', '<span class="code">windDir</span>',
|
|
<span class="code">windGust</span>', and '<span class="code">windGustDir</span>'
|
|
under one roof (all are still available, should you wish to use them for a specialized
|
|
application). Exceptions number two and three are '<span class="code">heatdeg</span>'
|
|
and '<span class="code">cooldeg</span>', heating and cooling degree-days, respectively,
|
|
which are synthesized from average outside temperature and do not appear directly
|
|
in the database. See <em><a href="#Types">Appendix A: Types</a></em> for a table
|
|
of statistical types.</li>
|
|
<li>The last position is the aggregation type, available for any time period
|
|
except for '<span class="code">current</span>'. The table
|
|
<a href="#Statistical_aggregations">Appendix C: Statistical aggregations</a>
|
|
shows what aggregation types are available for which types. </li>
|
|
</ol>
|
|
<p>In addition, if the first part of the dot code represents a time period longer
|
|
than a day (e.g., a week, month, year, or rainyear), then it can be iterated over.
|
|
This example uses a Cheetah 'for' 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> $month.outTemp.min $month.outTemp.max</pre>
|
|
<pre> # end for </pre>
|
|
<pre> </body></pre>
|
|
<pre></html></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>By 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? For example, suppose you want to use Google analytics, and you want to
|
|
make reference to the Google Tracker ID? You could modify a template and hardware
|
|
it in, but then you'd have to do that for every template. What you'd really like
|
|
to do is be able to obtain it through a tag:</p>
|
|
<pre class="tty">... (Google Analytics boilerplate)
|
|
<script type="text/javascript">
|
|
try {
|
|
var pageTracker = _gat._getTracker(<span class="highlight">$googleID</span>);
|
|
pageTracker._trackPageview();
|
|
} catch(err) {}
|
|
</script></pre>
|
|
<pre class="tty">... (More Google Analytics boilerplate)</pre>
|
|
<p>Here, the Google ID has been parameterized as a tag, <span class="code">$googleID</span>.
|
|
But, where does this value come from? How do I make it available inside my templates?</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 adding to the list of dictionaries a small dictionary with your tag as the key.
|
|
Here's an example: </p>
|
|
<p>File <span class="code">mygenerator.py</span>:</p>
|
|
<pre>from weewx.filegenerator import FileGenerator
|
|
|
|
class MyFileGenerator(FileGenerator):
|
|
|
|
def getToDateSearchList(self, currentRec, stop_ts):
|
|
|
|
# Call the superclass's version:
|
|
search_list = FileGenerator.getToDateSearchList(currentRec, stop_ts)
|
|
|
|
<span class="highlight">search_list += [ {'googleID' : 'UA-19281126-1'} ]</span>
|
|
|
|
return search_list</pre>
|
|
<p>Here, we first get the search list from the superclass, <span class="code">FileGenerator</span>,
|
|
and then (shown highlighted) add to it our simple dictionary with a single entry:
|
|
a key of "<span class="code">googleID</span>" and value of "<span class="code">UA-19281126-1</span>".
|
|
</p>
|
|
<p>Of course, this approach is not entirely satisfactory because you've hardwired
|
|
in the Google ID tag in your Python code. It would be much more desirable to get
|
|
it from the configuration file. One way to do this is to add a section to the weewx
|
|
configuration file with all your special options, including the Google tag:</p>
|
|
<p>File <span class="code">weewx.conf</span>:</p>
|
|
<pre>...</pre>
|
|
<pre>[MyOptions]</pre>
|
|
<pre> googleID = UA-19281126-1</pre>
|
|
<pre> myName = Mary</pre>
|
|
<pre> [[Video]]</pre>
|
|
<pre> video_capture = http://www.acme.com/videoimage.jpg</pre>
|
|
<pre>...</pre>
|
|
<p>The code for <span class="code">mygenerator.py</span> gets modified slightly
|
|
to inject the whole configuration section into the search list (shown highlighted
|
|
below):</p>
|
|
<pre>from weewx.filegenerator import FileGenerator
|
|
|
|
class MyFileGenerator(FileGenerator):
|
|
|
|
def getToDateSearchList(self, currentRec, stop_ts):
|
|
|
|
# Call the superclass's version:
|
|
search_list = FileGenerator.getToDateSearchList(currentRec, stop_ts)
|
|
|
|
search_list += [ self.config_dict['MyOptions'] ]
|
|
|
|
return search_list</pre>
|
|
<p>With this approach, you can now use all sorts of custom tags (highlighted) in
|
|
your HTML templates:</p>
|
|
<pre>...</pre>
|
|
<pre><img src="<span class="highlight">$Video.video_capture</span>" alt="Image of the house" /></pre>
|
|
<pre> </pre>
|
|
<pre><p>The operator's name is <span class="highlight">$myName</span>.</p></pre>
|
|
<pre> </pre>
|
|
<pre>... (Google Analytics boilerplate)
|
|
<script type="text/javascript">
|
|
try {
|
|
var pageTracker = _gat._getTracker(<span class="highlight">$googleID</span>);
|
|
pageTracker._trackPageview();
|
|
} catch(err) {}
|
|
</script></pre>
|
|
<pre>... (More Google Analytics boilerplate)</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">generator_list</span>
|
|
in the skin configuration file <span class="code">skin.conf</span> to read:</p>
|
|
<pre>generator_list = mygenerator.MyFileGenerator, weewx.imagegenerator.ImageGenerator, weewx.reportengine.CopyGenerator</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>
|
|
<h3>General</h3>
|
|
<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">[[Extras]]</h2>
|
|
<p>This section is available to you to add any tags that you might want to be available
|
|
in the templates. As an example, the stock <span class="code">skin.conf</span> file
|
|
includes option <span class="code">radar_url</span>, which is available as tag
|
|
<span class="code">$Extras.radar_url</span>. If you take a look at the template
|
|
<span class="code">index.html.tmpl</span> you will see an example of testing for
|
|
this tag (search the file for the string '<span class="code">radar</span>' to find
|
|
it).</p>
|
|
<p class="config_option">radar_url</p>
|
|
<p>If set, the NOAA radar image will be displayed. If commented out, no image will
|
|
be displayed.</p>
|
|
<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 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 "unit groups." 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">degrees_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">foot</span>" or "<span class="code">inch_per_hour</span>", not
|
|
"<span class="code">feet</span>" or "<span class="code">inches_per_hour</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>
|
|
<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 ' in'. 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>
|
|
<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>
|
|
<h3 class="config_section"><a name="Labels_Time">[[Time]]</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>
|
|
<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>EacEach 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.
|
|
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 index.html), 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 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 how summaries-by-month are generated. The default configuration
|
|
generates NOAA-by-month summaries. </p>
|
|
<h3 class="config_section">[[SummaryByYear]]</h3>
|
|
<p>This section controls how summaries-by-year are generated. The default configuration
|
|
generates NOAA-by-year summaries. </p>
|
|
<h3 class="config_section">[[ToDate]]</h3>
|
|
<p>This section controls how observations-to-date are generated. The default configuration
|
|
generates four files, one for day, week, month, and year-to-date.</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>
|
|
<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.StdWunderground</span></td>
|
|
<td>Starts thread to manage WU connection; adds new data to a Queue to be
|
|
posted to the WU by the thread.</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.StdWunderground, 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.StdWunderground, 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. Check first to see if the
|
|
# service has a member function "firstArchiveOfDay"
|
|
# before calling it:
|
|
if hasattr(svc_obj, "firstArchiveOfDay"): # NOTE 2
|
|
# The object does have the member function. Call it:
|
|
svc_obj.firstArchiveOfDay(rec)</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, the engine checks each one to make sure it
|
|
has a function <span class="code">firstArchiveOfDay</span> before calling 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.StdWunderground, 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: T<a name="Types">ypes</a></h1>
|
|
<p>The weather variables used in <span class="code">weewx</span> generally fall
|
|
into three different camps. They can be a "SQL type", meaning they appear in the
|
|
archive database, an "Observational type", meaning that they either appear in the
|
|
archive database or are a derived quantity thereof, or a "Statistical type," meaning
|
|
that they appear in the statistical database. Observational types can be used in
|
|
plots, statistical types can be aggregated and used in daily, weekly, monthly, and
|
|
yearly summaries. </p>
|
|
<p>The following table shows all the possible types and what categories they fall
|
|
into. 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, and whether or not you configured
|
|
<span class="code">weewx</span> to use that 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 style="width: 200px"><strong>Observation Type</strong><br />
|
|
<span class="xxsmall">(can be used in plots)</span></td>
|
|
<td style="width: 200px"><strong>Stats Type</strong><br />
|
|
<span class="xxsmall">(can be used in statistical aggregations)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">altimeter</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">altitude</td>
|
|
<td></td>
|
|
<td></td>
|
|
<td></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></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></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></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">UV</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">wind</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
<td>X</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="code">windvec</td>
|
|
<td> </td>
|
|
<td>X</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_volt</td>
|
|
<td>consBatteryVoltage<br />
|
|
heatingVoltage<br />
|
|
referenceVoltage<br />
|
|
supplyVoltage</td>
|
|
<td>volt</td>
|
|
</tr>
|
|
</table>
|
|
<h1>Appendix C: <a name="Statistical_aggregations">Statistical aggregations</a></h1>
|
|
<p>Most of the templates are devoted to reporting <em>statistical aggregates</em>,
|
|
such as monthly max temperature, or year-to-date rainfall. 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>
|