From 6032ea2671008f9cabdbcd9431c46ea443bdb795 Mon Sep 17 00:00:00 2001 From: Tom Keffer Date: Sun, 10 Nov 2013 15:56:43 +0000 Subject: [PATCH] Reformatted. --- docs/customizing.htm | 4424 +++++++++++++++++++++++------------------- 1 file changed, 2457 insertions(+), 1967 deletions(-) diff --git a/docs/customizing.htm b/docs/customizing.htm index 08818ae3..fa7ddcf6 100644 --- a/docs/customizing.htm +++ b/docs/customizing.htm @@ -1,51 +1,67 @@ - + - - - - - weewx: Customization Guide - - - - - - -

Customizing weewx
- - Version: 2.5.0 - + + + + + + +weewx: Customization Guide + + + + + + +

+ Customizing weewx
Version: + 2.5.0

Table of Contents

Introduction

-

This document covers the customization of weewx. - It assumes that you have read and are reasonably familiar with the - Users Guide.

-

It starts with an overview of the architecture of weewx. If you are - only interested in customizing the generated reports you can probably skip - the overview and proceed directly to the section - The Standard skin configuration file. 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.

-

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.

-

Most of the guide will cover any weather hardware, but the exact data - types are specific to the Davis Vantage series. Unless you are using an - unusual type you are unlikely to run into trouble.

-

Warning!
- weewx is still an experimental system and, as - such, its internal design is subject to change. Be prepared to do updates - to any code or customization you do!

+

+ This document covers the customization of weewx. + It assumes that you have read and are reasonably familiar with + the Users Guide. +

+

+ It starts with an overview of the architecture of weewx. If you + are only interested in customizing the generated reports you can + probably skip the overview and proceed directly to the section + The Standard skin configuration + file + . 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. +

+

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.

+

Most of the guide will cover any weather hardware, but the + exact data types are specific to the Davis Vantage series. + Unless you are using an unusual type you are unlikely to run + into trouble.

+

+ Warning!
weewx + is still an experimental system and, as such, its internal + design is subject to change. Be prepared to do updates to any + code or customization you do! +

Overview of the weewx architecture

-

At a high-level, weewx consists of an engine - class called StdEngine. It is responsible for - loading "services", then arranging for them to be called when key - events occur, such as the arrival of LOOP data. The default install of - weewx includes the following services:

- +

+ At a high-level, weewx consists of an + engine class called StdEngine. It is + responsible for loading "services", then arranging for + them to be called when key events occur, such as the arrival of + LOOP data. The default install of + weewx includes the following services: +

+
@@ -53,18 +69,18 @@ - + - + - + @@ -72,47 +88,64 @@ - + - + - + - +
Service
weewx.wxengine.StdConvertConverts the units of the input to a target unit system (such as - US or Metric).Converts the units of the input to a target unit + system (such as US or Metric).
weewx.wxengine.StdCalibrateAdjust new LOOP and archive packets using calibration - expressions.Adjust new LOOP and archive packets using + calibration expressions.
weewx.wxengine.StdQCCheck quality of incoming data, making sure values fall within a - specified range.Check quality of incoming data, making sure values + fall within a specified range.
weewx.wxengine.StdArchive
weewx.wxengine.StdTimeSynchArrange to have the clock on the station synchronized at regular - intervals.Arrange to have the clock on the station + synchronized at regular intervals.
weewx.wxengine.StdPrintPrint out new LOOP and archive packets on the console.Print out new LOOP and archive packets on the + console.
weewx.wxengine.StdRESTfulStart a thread to manage - RESTful (simple stateless client-server protocols) - connections; such as those used by the Weather Underground or CWOP.Start a thread to manage + RESTful (simple stateless client-server protocols) + connections; such as those used by the Weather Underground + or CWOP. +
weewx.wxengine.StdReportLaunch a new thread to do report processing after a new archive - record arrives. Reports do things such as generate HTML files, - generate images, or FTP/rsync files to a web server. New reports can - be added easily by the user.Launch a new thread to do report processing after a + new archive record arrives. Reports do things such as + generate HTML files, generate images, or FTP/rsync files + to a web server. New reports can be added easily by the + user.
-

It is easy to extend old services or to add new ones. The source - distribution includes an example new service called "MyAlarm," - which sends an email when an arbitrary expression evaluates - True. These advanced topics are covered later in the section - Customizing the weewx service engine.

-

The standard reporting service, StdReport

-

For the moment, let us focus on the last service, - weewx.wxengine.StdReport, the standard service for creating - reports. This will be what most users will want to customize even if it - means changing just a few options.

-

Reports

-

The Standard Report Service runs zero or more Reports. The - specific reports which get run are set in the configuration file weewx.conf, in section - [StdReport]. +

+ It is easy to extend old services or to add new ones. The source + distribution includes an example new service called "MyAlarm," which sends an email when an + arbitrary expression evaluates True. + These advanced topics are covered later in the section Customizing the weewx service + engine.

-

The default distribution of weewx includes - three reports:

- +

+ The standard reporting service, StdReport +

+

+ For the moment, let us focus on the last service, weewx.wxengine.StdReport, the standard + service for creating reports. This will be what most users will + want to customize even if it means changing just a few options. +

+

Reports

+

+ The Standard Report Service runs zero or more Reports. + The specific reports which get run are set in the configuration + file weewx.conf, in section [StdReport]. +

+

+ The default distribution of weewx + includes three reports: +

+
@@ -120,52 +153,63 @@ - + - + - +
Report
StandardReportGenerates 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. 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.
FTPArranges to upload everything in the - $HTML_ROOT - directory up to a remote webserver.Arranges to upload everything in the $HTML_ROOT directory up to a + remote webserver. +
RSYNCLike FTP, but uses rsync for transferring files to a remote - webserver.Like FTP, but uses rsync for transferring files to + a remote webserver.
-

Note that the FTP and RSYNC "reports" are a funny kind of report in - that it they do not actually generate anything. Instead, they use the - reporting service engine to arrange for things to be transferred to a - remote server.

+

Note that the FTP and RSYNC "reports" are a funny kind of + report in that it they do not actually generate anything. + Instead, they use the reporting service engine to arrange for + things to be transferred to a remote server.

Skins

-

Each report has a Skin 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 skin configuration file, - skin.conf. If you will, the skin controls the look and feel - 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 weewx.conf or the skin - configuration file skin.conf.

-

Like all reports, the FTP and RSYNC "Reports" also use a skin, and - include a skin configuration file, although they are quite minimal.

-

Skins live in their own directory located in - $SKIN_ROOT. +

+ Each report has a Skin 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 skin configuration file, + skin.conf. If you will, the skin + controls the look and feel 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 weewx.conf or the skin configuration file + skin.conf. +

+

Like all reports, the FTP and RSYNC "Reports" also use a + skin, and include a skin configuration file, although they are + quite minimal.

+

+ Skins live in their own directory located in $SKIN_ROOT.

Generators

-

To create their output, skins rely on one or more Generators, - code that actually create useful things such as HTML files or plot images. - Generators can also copy files around or FTP/rsync them to remote - locations. The default install of weewx includes - the following generators:

- +

+ To create their output, skins rely on one or more Generators, + code that actually create useful things such as HTML files or + plot images. Generators can also copy files around or FTP/rsync + them to remote locations. The default install of weewx includes the following generators: +

+
@@ -173,8 +217,8 @@ - + @@ -194,90 +238,121 @@
Generator
weewx.cheetahgenerator.CheetahGeneratorGenerates files from templates, using the Cheetah template - engine. Used to generate HTML and text files.Generates files from templates, using the Cheetah + template engine. Used to generate HTML and text files.
weewx.imagegenerator.ImageGenerator
-

Note that the three generators FtpGenerator, +

+ Note that the three generators FtpGenerator, RsyncGenerator, and - CopyGenerator - do not actually generate anything having to do with the presentation - layer. Instead, they just move files around.

-

Which generators are to be run for a given skin is specified in the - skin's configuration file skin.conf, in section - [Generators].

+ CopyGenerator do not actually generate anything having to do + with the presentation layer. Instead, they just move files + around. +

+

+ Which generators are to be run for a given skin is specified in + the skin's configuration file skin.conf, + in section + [Generators]. +

Databases

-

There are two databases used by weewx, which - can be implemented either by using - SQLITE3, an open-source, lightweight SQL database, or - MySQL, an open-source, full-featured database server, or some - combination of the two of them.

+

+ There are two databases used by weewx, + which can be implemented either by using SQLITE3, an open-source, + lightweight SQL database, or + MySQL, an open-source, full-featured database server, or some + combination of the two of them. +

-

How these abstract databases are bound to the real database is covered - in the Weewx User's Guide, in section '[StdArchive]'.

-

The important thing to remember is that the archive database contains a - record for every archive interval and, as such, represents the current - conditions at the time of the observation. By contrast, the - statistical database represents the aggregation of conditions over a - day. 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.

-

The archive database is used for both generating plot data and in - template generation (where it appears as tag $current). - The statistical database is used only in template generation (where it - appears as tags $day, $week, - $month, $year, and - $rainyear, depending on the aggregation time - period).

+

+ How these abstract databases are bound to the real database is + covered in the Weewx User's Guide, + in section '[StdArchive]'. +

+

+ The important thing to remember is that the archive database + contains a record for every archive interval and, as such, + represents the current conditions at the time of the + observation. By contrast, the statistical database represents + the aggregation of conditions over a day. 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. +

+

+ The archive database is used for both generating plot data and + in template generation (where it appears as tag $current). The statistical database is + used only in template generation (where it appears as tags $day, $week, $month, $year, + and $rainyear, depending on the + aggregation time period). +

Where to put customizations

-

For configuration changes, simply modify the - weewx configuration file - weewx.conf, and possibly modify the skin - configuration file skin.conf as described later - in this document. These files will be preserved when you upgrade.

-

Other customizations require new Python code or modifications of - example code. Where should you put the code? If you simply modify the - examples in place, then your changes will be overwritten the next time you - do an upgrade.

-

A better idea is to put the code in the - $BIN_ROOT/user, - directory. For example, copy example code from the - examples directory to the - user directory, then modify it there. If your - modification does not contain much code, consider putting it in the - extensions.py file in the user - directory. The user directory is preserved - through upgrades, so you won't have to redo any changes you might have - made.

+

+ For configuration changes, simply modify the weewx + configuration file weewx.conf, and + possibly modify the skin configuration file skin.conf + as described later in this document. These files will be + preserved when you upgrade. +

+

Other customizations require new Python code or + modifications of example code. Where should you put the code? If + you simply modify the examples in place, then your changes will + be overwritten the next time you do an upgrade.

+

+ A better idea is to put the code in the $BIN_ROOT/user, directory. For example, copy + example code from the examples + directory to the user directory, then + modify it there. If your modification does not contain much + code, consider putting it in the extensions.py file in the user directory. The user + directory is preserved through upgrades, so you won't have to + redo any changes you might have made. +

Customizing reports

-

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.

+

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.

Changing options

-

Changing an option means either modifying the main configuration file weewx.conf, or the skin configuration file for the - standard skin that comes with the distribution (nominally, file - $SKIN_ROOT/Standard/skin.conf).

-

Changing options in skin.conf

-

With this approach, the user edits the skin configuration file for the - standard skin that comes with weewx, located in - $SKIN_ROOT/Standard/skin.conf, using a - text editor. For example, suppose you wish to use metric units in the - presentation layer, instead of the default US Customary Units. The section - that controls units is [Units][[Groups]]. It - looks like this:

+

+ Changing an option means either modifying the main configuration + file weewx.conf, or the skin + configuration file for the standard skin that comes with the + distribution (nominally, file + $SKIN_ROOT/Standard/skin.conf). +

+

+ Changing options in skin.conf +

+

+ With this approach, the user edits the skin configuration file + for the standard skin that comes with weewx, + located in $SKIN_ROOT/Standard/skin.conf, using a text editor. + For example, suppose you wish to use metric units in the + presentation layer, instead of the default US Customary Units. + The section that controls units is [Units][[Groups]]. + It looks like this: +

[Units]
     [[Groups]]
         group_altitude    = foot
@@ -294,7 +369,7 @@
         group_temperature = degree_F
         group_uv          = uv_index 
         group_volt        = volt
-

To use metric units, you would edit this section to read:

+

To use metric units, you would edit this section to read:

[Units]
     [[Groups]]
         group_altitude    = meter
@@ -311,49 +386,63 @@
         group_temperature = degree_C
         group_uv          = uv_index 
         group_volt        = volt
-

The options that were changed have been -  highlighted . Details of the various unit options are given in - Appendix B: Units.

-

Other options are available, such as changing the text label for - various observation types. For example, suppose your weather console is - actually located in a barn, not indoors, and you want the plot for the - temperature at the console to be labeled "Barn Temperature," rather than - the default "Inside Temperature." This can be done by changing the "inTemp" option located in section - [Labels][[Generic]] - from the default

+

+ The options that were changed have been +  highlighted . Details of the various unit options + are given in Appendix B: Units. +

+

+ Other options are available, such as changing the text label for + various observation types. For example, suppose your weather + console is actually located in a barn, not indoors, and you want + the plot for the temperature at the console to be labeled "Barn + Temperature," rather than the default "Inside Temperature." This + can be done by changing the "inTemp" + option located in section + [Labels][[Generic]] from the default +

[Units]
     [[Generic]]
         inTemp  = Inside Temperature
         outTemp = Outside Temperature
         ...
-

to:

+

to:

[Units]
     [[Generic]]
         inTemp  = Barn Temperature
         outTemp = Outside Temperature
         ...
-

Overriding options in skin.conf from weewx.conf

-

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, weewx.conf. The advantage of - this approach is that you can use the same skin to produce several - different output, each with separate options.

-

Revisiting our example, suppose you want two reports, one in US - Customary, the other in Metric. The former will go in the directory $HTML_ROOT, the latter in a directory, $HTML_ROOT/metric. - If you just simply modify skin.conf, 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 directory then - editing the new skin.conf. The trouble with this - approach is that you would then have two skins you would have to - maintain. If you change something, you have to remember to change it in - both places.

-

But, there's a better approach: reuse the same skin, but override some - of its options. Here is what your [StdReport] - section in weewx.conf would look like:

+

+ Overriding options in skin.conf from weewx.conf +

+

+ 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, weewx.conf. + The advantage of this approach is that you can use the same skin + to produce several different output, each with separate options. +

+

+ Revisiting our example, suppose you want two reports, one in US + Customary, the other in Metric. The former will go in the + directory $HTML_ROOT, the latter + in a directory, $HTML_ROOT/metric. If you just simply modify skin.conf, 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 directory then + editing the new skin.conf. The trouble + with this approach is that you would then have two + skins you would have to maintain. If you change something, you + have to remember to change it in both places. +

+

+ But, there's a better approach: reuse the same skin, but + override some of its options. Here is what your [StdReport] section in weewx.conf + would look like: +

[StdReport]
     #
     # This section specifies what reports, using which skins, are to be generated.
@@ -391,38 +480,45 @@
     [[FTP]]
     ...
     ... (as before) 
-

We have done two things different from the stock reports. First (1), we - have renamed the first report from StandardReport - to - USReport for clarity; and (2) we have - introduced a new report MetricReport, just like - the first, except it puts its results in a different spot and uses - different units. Both use the same skin, the Standard - skin.

+

+ We have done two things different from the stock reports. First + (1), we have renamed the first report from StandardReport + to USReport for clarity; and (2) we + have introduced a new report MetricReport, + just like the first, except it puts its results in a different + spot and uses different units. Both use the same skin, the Standard skin. +

Customizing templates

-

If you cannot achieve the results you need by changing a configuration - option, you may have to modify the templates that come with - weewx, or write your own.

-

Template modifications are preserved across upgrades (indeed, - everything in the ./skins directory is - preserved), so you don't have to worry about losing changes.

-

Template generation is done using the - Cheetah - 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, weewx adopts a very small subset of - its power.

+

+ If you cannot achieve the results you need by changing a + configuration option, you may have to modify the templates that + come with weewx, or write your own. +

+

+ Template modifications are preserved across upgrades (indeed, + everything in the ./skins directory is + preserved), so you don't have to worry about losing changes. +

+

+ Template generation is done using the Cheetah 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, weewx + adopts a very small subset of its power. +

The dot code

-

The key construct is a 'dot' code, specifying what value you want. For - example:

+

The key construct is a 'dot' code, specifying what value + you want. For example:

$month.outTemp.max
 $month.outTemp.maxtime
 $current.outTemp
-

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

+

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

<html>
     <head>
         <title>Current conditions</title>
@@ -432,197 +528,256 @@ $current.outTemp
<p>Max for the month is $month.outTemp.max, which occurred at $month.outTemp.maxtime</p> </body> </html> -

would be all you need for a very simple HTML page that would display - the text (assuming that the unit group for temperature is - degree_F): -

-

Current temperature = 51.0°F
- Max for the month is 68.8°F, which occurred at 07-Oct-2009 15:15

-

The format that was used to format the temperature (51.0) - is specified in section - [Units][[StringFormat]]. The unit label °F - is from section [Units][[Labels]], while the time - format is from - [Units][[TimeFormats]]. +

+ would be all you need for a very simple HTML page that would + display the text (assuming that the unit group for temperature + is degree_F):

-

As we saw above, the dot codes can be very simple:

+

+ Current temperature = 51.0°F
Max for the month is + 68.8°F, which occurred at 07-Oct-2009 15:15 +

+

+ The format that was used to format the temperature (51.0) is specified in section + [Units][[StringFormat]]. The unit label °F + is from section [Units][[Labels]], while the time + format is from [Units][[TimeFormats]]. +

+

As we saw above, the dot codes can be very simple:

## Output max outside temperature using an appropriate format and label:
 $month.outTemp.max
-

Most of the time, the dot code will "do the right thing" and is all you - will need. However, weewx 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.

-

There are two different versions of the dot code, depending on whether - the data is "current", or an aggregation over time. However, both versions - are similar.

+

+ Most of the time, the dot code will "do the right thing" and is + all you will need. However, weewx + 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. +

+

There are two different versions of the dot code, depending + on whether the data is "current", or an aggregation over time. + However, both versions are similar.

-

Time period $current

-

Time period $current represents a current - observation. An example would be the current barometric pressure: +

+ Time period $current +

+

+ Time period $current represents a current + observation. An example would be the current barometric + pressure:

$current.barometer
-

The dot code for a current observation looks like:

+

The dot code for a current observation looks like:

$current.obstype[.optional_unit_conversion][.optional_formatting]
-

Where:

-

obstype is an - observation type, such as barometer. See - Appendix A, Archive Types for a - table of observation types valid for time period - current. +

Where:

+

+ obstype is an observation + type, such as barometer. See + Appendix A, Archive Types + for a table of observation types valid for time period current. +

+

+ optional_unit_conversion is an + optional unit conversion tag. If provided, the results will be + converted into the specified units, otherwise the default units + specified in the skin configuration file (in section [Units][[Groups]]) will be used. See the + section Unit + Conversion Options below. +

+

+ optional_formatting is an + optional formatting tag that controls how the value will appear. + See the section Formatting + Options below.

-

optional_unit_conversion is an - optional unit conversion tag. If provided, the results will be converted - into the specified units, otherwise the default units specified in the - skin configuration file (in section [Units][[Groups]]) - will be used. See the section Unit - Conversion Options below.

-

optional_formatting - is an optional formatting tag that controls how the value will appear. - See the section Formatting Options - below.

-

Aggregation periods $day, - $week, $month, - $year, $rainyear +

+ Aggregation periods $day, $week, $month, $year, $rainyear

-

The other time periods represent an aggregation over time. In - addition to the time period over which the aggregation will occur, they - also require an aggregation type. An example would be the week's - total precipitation (where the aggregation type is - sum): -

+

+ The other time periods represent an aggregation over + time. In addition to the time period over which the + aggregation will occur, they also require an aggregation + type. An example would be the week's total precipitation + (where the aggregation type is + sum): +

$week.rain.sum
-

The dot code for an aggregation over time looks like:

+

The dot code for an aggregation over time looks like:

$period.statstype.aggregation[.optional_unit_conversion][.optional_formatting]
-

Where:

-

period is the time - period over which the aggregation is to be done. Possible choices are day, week, - month, - year, rainyear.

-

statstype is a - statistical type. See Appendix C, - Statistical Types, for a table of statistical types.

-

aggregation is an - aggregation type. This is something like 'min', - 'sum', 'mintime'. If - you ask for $month.outTemp.avg you are asking - for the average outside temperature for the month. The table - Appendix C: Statistical Types - shows what aggregation types are available for which types.

-

optional_unit_conversion is an - optional unit conversion tag. If provided, the results will be converted - into the specified units, otherwise the default units specified in the - skin configuration file (in section [Units][[Groups]]) - will be used. See the section Unit - Conversion Options below.

-

optional_formatting - is an optional formatting tag that controls how the value will appear. - See the section Formatting Options - below.

+

Where:

+

+ period is the time period + over which the aggregation is to be done. Possible choices are day, week, month, year, rainyear. +

+

+ statstype is a statistical + type. See Appendix C, + Statistical Types, for a table of statistical types. +

+

+ aggregation is an aggregation + type. This is something like 'min', 'sum', 'mintime'. + If you ask for $month.outTemp.avg you + are asking for the average outside temperature for the + month. The table Appendix + C: Statistical Types shows what aggregation types are + available for which types. +

+

+ optional_unit_conversion is an + optional unit conversion tag. If provided, the results will be + converted into the specified units, otherwise the default units + specified in the skin configuration file (in section [Units][[Groups]]) will be used. See the + section Unit + Conversion Options below. +

+

+ optional_formatting is an + optional formatting tag that controls how the value will appear. + See the section Formatting + Options below. +

Unit conversion options

-

The tag optional_unit_conversion - can be used with either current observations or aggregations. If - supplied, the results will be converted to the specified units. For - example, if you have set group_pressure to - inches of mercury (inHg), then the tag

+

+ The tag optional_unit_conversion + can be used with either current observations or aggregations. If + supplied, the results will be converted to the specified units. + For example, if you have set group_pressure + to inches of mercury (inHg), then the + tag +

Today's average pressure=$day.barometer.avg 
-

would normally give a result such as

-

Today's average pressure=30.05 inHg

-

However, if you add "mbar" to the end,

+

would normally give a result such as

+

Today's average pressure=30.05 inHg +

+

+ However, if you add "mbar" to the end, +

$day.barometer.avg.mbar 
-

then the results will be in millibars:

-

Today's average pressure=1017.5 mbar

+

then the results will be in millibars:

+

Today's average pressure=1017.5 mbar +

Wind ordinals

-

Using this method, you can output compass ordinals for wind direction. - For example, the template

+

Using this method, you can output compass ordinals for wind + direction. For example, the template

Current wind direction is $current.windDir ($current.windDir.ordinal_compass)

would result in:

-

Current wind direction is 138° (SW)

-

The ordinal abbreviations that are used are set by option - directions - in the skin configuration file skin.conf.

-

Illegal conversions

-

If an inappropriate conversion is asked for, e.g.,

-
Today's average pressure=$day.barometer.degree_C 
-

then the offending tag will be put in the output:

-

Today's average pressure=$day.barometer.degree_C +

Current wind direction is 138° (SW)

+

+ The ordinal abbreviations that are used are set by option directions in the skin configuration file + skin.conf.

+

Illegal conversions

+

+ If an inappropriate conversion is asked for, e.g., +

+
Today's average pressure=$day.barometer.degree_C 
+

then the offending tag will be put in the output:

+

Today's average + pressure=$day.barometer.degree_C

Formatting options

-

The tag optional_formatting can be - used with either current observations or aggregations. It can be one of: +

+ The tag optional_formatting + can be used with either current observations or aggregations. It + can be one of:

- +
- - + + - - + + - + - - + + - + - - + +
Optional Formatting Tag Comment
(no tag) Value is returned as a string, formatted using an appropriate - string format from skin.conf. A unit label - from skin.conf is also attached at the - end. (no tag)Value is returned as a string, formatted using an + appropriate string format from skin.conf. + A unit label from skin.conf is + also attached at the end. +
.string(NONE_string)Value is returned as a string, formatted using an appropriate - string format from skin.conf. If the value - is None, the string - NONE_string - will be substituted if given, otherwise the value for - NONE - in - [Units][[StringFormats]] - will be used. A unit label from - skin.conf - will be attached at the end. .string(NONE_string) + Value is returned as a string, formatted using an + appropriate string format from skin.conf. + If the value is None, the string + NONE_string will be substituted + if given, otherwise the value for + NONE in + [Units][[StringFormats]] + will be used. A unit label from + skin.conf will be attached at the end. +
.formattedValue is returned as a string, formatted using an appropriate - string format and None value from skin.conf. No label.Value is returned as a string, formatted using an + appropriate string format and None + value from skin.conf. No label. +
.format(string_format, NONE_string)Value is returned as a string, using the string format specified - with string_format. If the value is None, - the string NONE_string will be substituted - if given, otherwise the value for NONE - in - [Units][[StringFormats]] - will be used. A unit label from - skin.conf - will be attached at the end. .format(string_format, NONE_string) + Value is returned as a string, using the string + format specified with string_format. If the value + is None, the string NONE_string will be substituted if + given, otherwise the value for NONE + in + [Units][[StringFormats]] + will be used. A unit label from + skin.conf will be attached at the end. +
.nolabel(string_format, NONE_string)Value is returned as a string, using the string format specified - with string_format. If the value is None, - the string NONE_string will be substituted - if given, otherwise the value for NONE - in - [Units][[StringFormats]] - will be used. No label will be attached at the end.Value is returned as a string, using the string + format specified with string_format. If the value + is None, the string NONE_string will be substituted if + given, otherwise the value for NONE + in + [Units][[StringFormats]] + will be used. No label will be attached at the end. +
.raw Value is returned "as is" without being converted to a string - and without any formatting applied. You must be prepared to deal - with a None value unless the value is - converted directly to a string. In this case, it will be converted - to the empty string ('').rawValue is returned "as is" without being converted + to a string and without any formatting applied. You must + be prepared to deal with a None + value unless the value is converted directly to a string. + In this case, it will be converted to the empty string ('') +
-

Summary:

- +

Summary:

+
@@ -675,8 +830,9 @@ $month.outTemp.max
Formatting Tag
-

Here are some examples with the expected results:

- +

Here are some examples with the expected results:

+
@@ -684,63 +840,71 @@ $month.outTemp.max - - + + - + - + - + - + - + - - - + + + - + - + - + - + @@ -748,88 +912,110 @@ $month.outTemp.max - - + + - + - + - + - + - + - + - + - + - +
Tag Comment
$current.outTemp 45.2°F $current.outTemp45.2°F String formatting and label from skin.conf
$current.outTemp.string45.2°F45.2°F String formatting and label from skin.conf
$current.UV.string N/AThis example assumes that the instrument has no UV sensor, - resulting in a None value. The string - specified by NONE in - [Units][[StringFormats]] - is substituted.This example assumes that the instrument has no UV + sensor, resulting in a None + value. The string specified by NONE + in [Units][[StringFormats]] + is substituted. +
$current.UV.string("No UV") No UVThis example assumes that the instrument has no UV sensor, - resulting in a None value. The string - supplied by the user is substituted.This example assumes that the instrument has no UV + sensor, resulting in a None + value. The string supplied by the user is substituted. +
$current.outTemp.formatted $current.outTemp.formatted 45.2String formatting from skin.conf; no - labelString formatting from skin.conf; + no label +
$current.outTemp.format("%.3f") 45.200°FSpecified string format used; label from - skin.conf.$current.outTemp.format("%.3f")45.200°FSpecified string format used; label from skin.conf. +
$current.dateTime02-Apr-2010 16:2502-Apr-2010 16:25 Time formatting and label from skin.conf
$current.dateTime.format("%H:%M") 16:25Specified time format used; label from - skin.conf.Specified time format used; label from skin.conf. +
$current.dateTime.raw 1270250700Unix epoch time, converted to string by template engine.Unix epoch time, converted to string by template + engine.
$current.outTemp.raw 45.2Float returned, converted to string by template engine.Float returned, converted to string by template + engine.
$month.dateTime Time formatting and label from skin.conf
$month.outTemp.avg 40.8°F$month.outTemp.avg40.8°F String formatting and label from skin.conf
$month.outTemp.avg.string40.8°F40.8°F Time formatting and label from skin.conf
$month.UV.avg.string N/AThis example assumes that the instrument has no UV sensor, - resulting in a None value. The string - specified by NONE in - [Units][[StringFormats]] - is substituted.This example assumes that the instrument has no UV + sensor, resulting in a None + value. The string specified by NONE + in [Units][[StringFormats]] + is substituted. +
$month.UV.avg.string("No UV") No UVThis example assumes that the instrument has no UV sensor, - resulting in a None value. The string - supplied by the user is substituted.This example assumes that the instrument has no UV + sensor, resulting in a None + value. The string supplied by the user is substituted. +
$month.outTemp.avg.formatted $month.outTemp.avg.formatted 40.8String formatting from skin.conf; no - labelString formatting from skin.conf; + no label +
$month.outTemp.avg.format("%.3f")40.759°F40.759°F Specified string format used; no label
$month.outTemp.avg.raw $month.outTemp.avg.raw 40.7589690722Float returned, converted to string by template engineFloat returned, converted to string by template + engine
$month.UV.avg.raw (empty)None value converted to empty string - by template engine.None value converted to + empty string by template engine.
-

Note:

+

Note:

-

Type dateTime

-

While not an observation type, in many ways the time of an observation, - dateTime, can be treated as one. A tag such as - $current.dateTime represents the current - time (more properly, the time as of the end of the last archive - interval). Similarly, a tag such as $month.dateTime - represents the start time of the month. Like true observation types, - explicit formats can be specified, except that they require a - strftime() time format, rather than a string format:

+

+ Type dateTime +

+

+ While not an observation type, in many ways the time of an + observation, dateTime, can be treated + as one. A tag such as $current.dateTime + represents the current time (more properly, the time as + of the end of the last archive interval). Similarly, a tag such + as $month.dateTime represents the + start time of the month. Like true observation types, explicit + formats can be specified, except that they require a + strftime() time format + , rather than a string format: +

$month.dateTime.format("%B %Y)
-

produces

+

produces

January 2010
-

The returned string value will always be in local time.

-

The raw value of dateTime is Unix Epoch Time - (number of seconds since 00:00:00 UTC 1 Jan 1970, i.e., a large - number), which you must convert yourself to local time. It is guaranteed - to never be None, so you don't worry have to - worry about handling a None - value.

-

Tag $trend

-

The tag $trend is available for time trends, - such as barometer trends. Here are some examples:

- +

+ The returned string value will always be in local time. +

+

+ The raw value of dateTime is Unix + Epoch Time (number of seconds since 00:00:00 UTC 1 Jan 1970, i.e., + a large number), which you must convert yourself to local time. + It is guaranteed to never be None, so + you don't worry have to worry about handling a None value. +

+

+ Tag $trend +

+

+ The tag $trend is available for time + trends, such as barometer trends. Here are some examples: +

+
@@ -841,7 +1027,7 @@ $month.outTemp.max - + @@ -853,17 +1039,23 @@ $month.outTemp.max
Tag
$trend.outTemp1.1 °C1.1°C
$trend.time_delta
-

Note that the time delta over which the trend is calculated is also - available. This time delta is set by an option in the skin configuration - file, time_delta.

+

+ Note that the time delta over which the trend is calculated is + also available. This time delta is set by an option in the skin + configuration file, time_delta. +

As a summary, the template expression

<p>The barometer trend over $trend.time_delta.hour is $trend.barometer.format("%+.2f").</p>

would result in

-

The barometer trend over 3 hrs is +.02 inHg.

-

Tag $unit

-

The unit type, label, and string formats are also available, allowing - you to do highly customized labels:

- +

The barometer trend over 3 hrs is + +.02 inHg.

+

+ Tag $unit +

+

The unit type, label, and string formats are also + available, allowing you to do highly customized labels:

+
@@ -875,7 +1067,7 @@ $month.outTemp.max - + @@ -883,24 +1075,30 @@ $month.outTemp.max
Tag
$unit.label.outTemp°C°C
$unit.format.outTemp
-

As a summary, the tag

+

As a summary, the tag

$day.outTemp.max.formatted$unit.label.outTemp
-

would result in

-
21.2°C
-

(assuming metric values have been specified for - group_temperature), essentially reproducing the results of the - simpler tag $day.outTemp.max. +

would result in

+
21.2°C
+

+ (assuming metric values have been specified for group_temperature), essentially + reproducing the results of the simpler tag $day.outTemp.max.

Iteration

-

For dot codes using an aggregation (e.g., - $day, - $week, $month, $year, $rainyear, then - the aggregation period can be iterated over by day or month. These are the - only two iteration periods available as of this version.

-

This example uses a Cheetah 'for' loop to - iterate over all months in a year, printing out each month's min and max - temperature (the iteration loop is  highlighted ):

+

+ For dot codes using an aggregation (e.g., $day, $week, $month, $year, $rainyear, then the aggregation period can + be iterated over by day or month. These are the only two + iteration periods available as of this version. +

+

+ This example uses a Cheetah 'for' loop + to iterate over all months in a year, printing out each month's + min and max temperature (the iteration loop is  highlighted ): +

<html>
     <head>
         <title>Year stats by month</title>
@@ -912,12 +1110,12 @@ $month.outTemp.max
#end for </body> </html> -

Produces results:

+

Produces results:

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
+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
@@ -926,16 +1124,21 @@ 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
-

See the NOAA template files NOAA/NOAA-YYYY.txt.tmpl - and NOAA/NOAA-YYYY-MM.txt.tmpl for examples - using iteration, as well as explicit formatting.

+

+ See the NOAA template files NOAA/NOAA-YYYY.txt.tmpl + and NOAA/NOAA-YYYY-MM.txt.tmpl for + examples using iteration, as well as explicit formatting. +

Almanac

-

If module pyephem has been - installed, then weewx can generate extensive - almanac information for the Sun, Moon, Venus, Mars, Jupiter, and other - heavenly bodies, including their rise, transit and set times, as well as - their azimuth and altitude. Other information is also available.

-

Here is a small sampling:

+

+ If module pyephem + has been installed, then weewx can + generate extensive almanac information for the Sun, Moon, Venus, + Mars, Jupiter, and other heavenly bodies, including their rise, + transit and set times, as well as their azimuth and altitude. + Other information is also available. +

+

Here is a small sampling:

<html>
     <head>
         <title>Almanac data</title>
@@ -954,7 +1157,8 @@ December: Min, max temperatures: N/A N/A
#end if </body> </html> -

If your installation has pyephem installed this would result in:

+

If your installation has pyephem installed this would + result in:

Current time is 29-Mar-2011 09:20
 Sunrise, transit, sunset: 06:51 13:11 19:30
 Moonrise, transit, moonset: 04:33 09:44 15:04
@@ -962,12 +1166,13 @@ Mars rise, transit, set: 06:35 12:30 18:26
 Azimuth, altitude of mars: 124.354959275 26.4808431952
 Next new, full moon: 03-Apr-2011 07:32 17-Apr-2011 19:43
 Next summer, winter solstice: 21-Jun-2011 10:16 21-Dec-2011 21:29
-

Otherwise, a fallback position is used, resulting in

+

Otherwise, a fallback position is used, resulting in

Current time is 29-Mar-2011 09:20
 Sunrise, sunset: 06:51 19:30
-

As shown in the example, you can test whether this extended almanac - information is available with the value - $almanac.hasExtras. +

+ As shown in the example, you can test whether this extended + almanac information is available with the value $almanac.hasExtras.

The almanac information falls in two categories:

We will cover each of these separately.

Calendar events

-

"Calendar events" do not require a heavenly body. They cover things - such as "next_solstice", or "next_first_quarter_moon". - The syntax here is

+

+ "Calendar events" do not require a heavenly body. They cover + things such as "next_solstice", or "next_first_quarter_moon". The syntax here + is +

$almanac.next_solstice
-

or

+

or

$almanac.next_first_quarter_moon
-

Here is a table of the information that falls into this category:

+

Here is a table of the information that falls into this + category:

@@ -1018,39 +1227,50 @@ Sunrise, sunset: 06:51 19:30

Heavenly bodies

-

The second category does require a heavenly body. This covers queries - such as, "When does Jupiter rise?" or, "When does the sun transit?" - Examples are

+

The second category does require a heavenly body. This + covers queries such as, "When does Jupiter rise?" or, "When does + the sun transit?" Examples are

$almanac.jupiter.rise

or

$almanac.sun.transit
-

To accurately calculate these times, weewx - automatically uses the present temperature and pressure to calculate - refraction effects. However, you can override these values, which will be - necessary if you wish to match the almanac times published by the Naval - Observatory as - explained in the pyephem documentation. For example, to match the - sunrise time as published by the Observatory, instead of

+

+ To accurately calculate these times, weewx + automatically uses the present temperature and pressure to + calculate refraction effects. However, you can override these + values, which will be necessary if you wish to match the almanac + times published by the Naval Observatory as + explained in the pyephem documentation. For example, to match + the sunrise time as published by the Observatory, instead of +

$almanac.sun.rise

use

$almanac(pressure=0, horizon=-34.0/60.0).sun.rise
-

By setting pressure to zero we are bypassing the refraction - calculations and manually setting the horizon to be 34 arcminutes lower - than the normal horizon. This is what the Navy uses.

-

If you wish to calculate the start of civil twilight, you can set the - horizon to -6 degrees, and also tell weewx to - use the center of the sun (instead of the upper limb, which it normally - uses) to do the calcuation:

+

By setting pressure to zero we are bypassing the refraction + calculations and manually setting the horizon to be 34 + arcminutes lower than the normal horizon. This is what the Navy + uses.

+

+ If you wish to calculate the start of civil twilight, you can + set the horizon to -6 degrees, and also tell weewx + to use the center of the sun (instead of the upper limb, which + it normally uses) to do the calcuation: +

$almanac(pressure=0, horizon=-6).sun(use_center=1).rise

The general syntax is:

$almanac(pressure=pressure, horizon=horizon,
          temperature=temperature_C).heavenly_body(use_center=[01]).attribute
-

As you can see, in addition to the horizon angle, you can also override - atmospheric pressure and temperature (degrees Celsius).

-

PyEphem offers an extensive list of objects that can be used for the heavenly_body tag. All the planets and - many stars are in the list.

-

The attribute tag can be one of

+

As you can see, in addition to the horizon angle, you can + also override atmospheric pressure and temperature (degrees + Celsius).

+

+ PyEphem offers an extensive list of objects that can be used for + the heavenly_body tag. All + the planets and many stars are in the list. +

+

+ The attribute tag can be one of +

@@ -1098,56 +1318,72 @@ Sunrise, sunset: 06:51 19:30

Defining new tags

- In the section on Customizing templates, - we have seen how you can change a template and make use of the various - tags available such as $day.outTemp.max for - the maximum outside temperature for the day. But, what if you want to - introduce some new data for which no tag is available? -

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 [Extras] in the skin configuration file. - More information on how to do this can be found there.

-

But, what if you wish to introduce a more dynamic tag, one that - requires some calculation, or perhaps uses the database? Simply putting it - in the [Extras] section won't do, because then - it cannot change.

-

The answer is to write a search list extension.

+ In the section on Customizing + templates, we have seen how you can change a template and make + use of the various tags available such as $day.outTemp.max + for the maximum outside temperature for the day. But, what if you + want to introduce some new data for which no tag is available? +

+ 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 [Extras] in the skin + configuration file. More information on how to do this can be + found there. +

+

+ But, what if you wish to introduce a more dynamic tag, one that + requires some calculation, or perhaps uses the database? Simply + putting it in the [Extras] section + won't do, because then it cannot change. +

+

+ The answer is to write a search list extension. +

Search list

-

The Cheetah template engine (which weewx - uses) finds tags by scanning a search list, a Python list of - objects. For example, for a tag $foo, the engine - will scan down the list, trying each object obj - in turn. First it tries using foo as an - attribute, that is, - obj.foo. If that raises an exception - AttributeError, then it will try - foo as a key, that is - obj[key]. If that raises a - KeyError, then it moves on to the next item in - the list. The first match that does not raise an exception is returned. If - no match is found, it raises a NameMapper.NotFound - exception.

-

- Extending the list

-

Weewx comes with a number of objects already in the search list, but - you can extend it. To do so, you should have some familiarity with Python, - in particular, how to write new classes and member functions for them.

-

Let's look at an example. The regular version of - weewx - offers statistical summaries by day, week, month, and year. Suppose we - would like to add two more:

+

+ The Cheetah template engine (which weewx + uses) finds tags by scanning a search list, a + Python list of objects. For example, for a tag $foo, the engine will scan down the list, + trying each object obj in turn. First + it tries using foo as an attribute, + that is, obj.foo. If that raises an + exception AttributeError, then it + will try foo as a key, that is obj[key]. If that raises a KeyError, then it moves on to the next + item in the list. The first match that does not raise an + exception is returned. If no match is found, it raises a NameMapper.NotFound exception. +

+

Extending the list

+

Weewx comes with a number of objects already in the search + list, but you can extend it. To do so, you should have some + familiarity with Python, in particular, how to write new classes + and member functions for them.

+

+ Let's look at an example. The regular version of weewx offers statistical summaries by + day, week, month, and year. Suppose we would like to add two + more: +

-

This example is included in the distribution as - $BIN_ROOT/examples/xsearch.py:

-
import datetime
+      

+ This example is included in the distribution as $BIN_ROOT/examples/xsearch.py: +

+
import datetime
 import time
 
 from weewx.cheetahgenerator import SearchList
@@ -1186,87 +1422,102 @@ class MyXSearch(SearchList):                                #1
                                  'seven_day' : seven_day_stats}               # 8
         
         return search_list_extension 
-

Going through the example, line by line:

+

Going through the example, line by line:

    -
  1. Create a new class called MyXSearch, which - will inherit from class SearchList. All search - list extensions inherit from this class.
  2. -
  3. Create an initializer for our new class. In this case, the initializer - does nothing except pass its only parameter, - generator, a reference to the calling generator, - to its superclass, SearchList. The superclass will - store it in self.
  4. -
  5. Override member function get_extension(). - This function will be called when the generator is ready to accept your - new search list extension. The parameters that will be passed in are: +
  6. Create a new class called MyXSearch, + which will inherit from class SearchList. + All search list extensions inherit from this class. +
  7. +
  8. Create an initializer for our new class. In this case, + the initializer does nothing except pass its only parameter, generator, a reference to the calling + generator, to its superclass, SearchList. + The superclass will store it in self. +
  9. +
  10. Override member function get_extension(). + This function will be called when the generator is ready to + accept your new search list extension. The parameters that + will be passed in are:
      -
    • self Python's way of indicating the - instance we are working with;
    • -
    • valid_timespan An instance of the - utility class TimeSpan. This will contain - the valid start and ending times used by the template. Normally, - this is all valid times;
    • +
    • self Python's way of + indicating the instance we are working with;
    • +
    • valid_timespan An + instance of the utility class TimeSpan. + This will contain the valid start and ending times used by + the template. Normally, this is all valid times;
    • archivedb An instance of - weewx.archive.Archive, holding the - archive database;
    • -
    • statsdb An instance of - weewx.stats.StatsDb, holding the - statistical database.
    • + weewx.archive.Archive, holding + the archive database; +
    • statsdb An instance of weewx.stats.StatsDb, holding the + statistical database.
  11. -
  12. The class TimeSpanStats represents a - statistical calculation over a time period. In our case, we will set it - up to represent the statistics over all possible times. The class takes - 4 parameters. +
  13. The class TimeSpanStats + represents a statistical calculation over a time period. In + our case, we will set it up to represent the statistics over + all possible times. The class takes 4 parameters.
      -
    • The first is the timespan over which the calculation is to be - done. Here, we have a lucky coincidence: the variable - valid_timespan - already holds a TimeSpan object - representing the domain of all valid timespans, so we simply pass it - in.
    • -
    • The second is the statistical database the calculation is to be - run against. We simply pass in - statsdb.
    • -
    • The third should be an instance of class - weewx.units.Formatter, which contains - information about how the results should be formatted. We just pass - in the formatter set up by the generator, - self.generator.formatter.
    • -
    • The fourth should be an instance of - weewx.units.Converter, which contains - information about the target units (e.g., "degree_C") - that are to be used. Again, we just pass in the instance set up by - the generator, - self.generator.converter.
    • +
    • The first is the timespan over which the + calculation is to be done. Here, we have a lucky + coincidence: the variable valid_timespan + already holds a TimeSpan object + representing the domain of all valid timespans, so we + simply pass it in. +
    • +
    • The second is the statistical database the + calculation is to be run against. We simply pass in statsdb. +
    • +
    • The third should be an instance of class weewx.units.Formatter, which contains + information about how the results should be formatted. We + just pass in the formatter set up by the generator, self.generator.formatter. +
    • +
    • The fourth should be an instance of weewx.units.Converter, which contains + information about the target units (e.g., "degree_C") that are to be used. Again, + we just pass in the instance set up by the generator, self.generator.converter. +
-

That one was relatively easy because we already had an instance of - TimeSpan, - valid_timespan, that represented the time over - which we wanted to do the calculations. Setting up an instance that will - work for the last seven days is a bit trickier. Continuing our example...

+

+ That one was relatively easy because we already had an instance + of TimeSpan, valid_timespan, + that represented the time over which we wanted to do the + calculations. Setting up an instance that will work for the last + seven days is a bit trickier. Continuing our example... +

    -
  1. The object valid_timespan holds the domain - of all valid times, but in order to calculate statistics for the last - seven days, we need not the earliest valid time, but the time at - midnight seven days ago. So, we do a little Python date arithmetic to - calculate this. The object - week_dt will be an instance of - datetime.date.
  2. +
  3. The object valid_timespan + holds the domain of all valid times, but in order to calculate + statistics for the last seven days, we need not the earliest + valid time, but the time at midnight seven days ago. So, we do + a little Python date arithmetic to calculate this. The object + week_dt will be an instance of datetime.date. +
  4. We convert it to unix epoch time.
  5. -
  6. Now we are ready to initialize an appropriate - TimeSpanStats object. It's the same as in - step #4, except we use our new timespan object.
  7. -
  8. Create a small dictionary with two keys, 'alltime', - and 'seven_day' and return it.
  9. +
  10. Now we are ready to initialize an appropriate TimeSpanStats object. It's the same as in + step #4, except we use our new timespan object. +
  11. +
  12. Create a small dictionary with two keys, 'alltime', and 'seven_day' + and return it. +
-

The last step is to tell the template engine where to find our - extension. You do that by going into the skin configuration file, - skin.conf, and adding the option - search_list_extensions with our new extension. - When you're done, it will look something like this:

+

+ The last step is to tell the template engine where to find our + extension. You do that by going into the skin configuration + file, skin.conf, and adding the option + search_list_extensions with our new + extension. When you're done, it will look something like this: +

[CheetahGenerator]
     # This section is used by the generator CheetahGenerator, and specifies
     # which files are to be generated from which template.
@@ -1279,19 +1530,23 @@ class MyXSearch(SearchList):                                #1
     [[SummaryByMonth]]
     ...
 
-

Our addition has been  highlighted . - Note that it is in the section - [CheetahGenerator]. (This section was called - [FileGenerator] in earlier versions of weewx, - a name which will still work.)

-

Now, if the Cheetah engine encounters the tag - $alltime, it will scan the search list, looking for an attribute or - key that matches alltime. When it gets to the - little dictionary we provided, it will find a matching key, allowing it to - retrieve the appropriate - TimeSpanStats object.

-

With this approach, you can now include "all time" or "seven day" - statistics in your HTML templates:

+

+ Our addition has been  highlighted . + Note that it is in the section [CheetahGenerator]. + (This section was called + [FileGenerator] in earlier versions of weewx, + a name which will still work.) +

+

+ Now, if the Cheetah engine encounters the tag + $alltime, it will scan the search list, looking for an + attribute or key that matches alltime. + When it gets to the little dictionary we provided, it will find + a matching key, allowing it to retrieve the appropriate TimeSpanStats object. +

+

With this approach, you can now include "all time" or + "seven day" statistics in your HTML templates:

...
 <table>
     <tr>
@@ -1307,304 +1562,402 @@ class MyXSearch(SearchList):                                #1
         <td>$seven_day.rain.sum
     </tr>
     ... (more table entries)
-

If you place a custom generator somewhere other than the - $BIN_ROOT hierarchy where - weewxd resides, you may have to specify its - location in the environment variable - PYTHONPATH +

+ If you place a custom generator somewhere other than the $BIN_ROOT hierarchy where weewxd resides, you may have to specify + its location in the environment variable PYTHONPATH in the shell where you start weewx:

-
export PYTHONPATH=/home/me/secret_location
+
export PYTHONPATH=/home/me/secret_location

Customizing skins: the Standard skin

-

This section is a reference to the options appearing in the Standard - skin configuration file, found in - $SKIN_ROOT/Standard/skin.conf.

-

It is worth noting that, like the main configuration file - weewx.conf, UTF-8 is used throughout. The most - important options are up near the top of the file. The truly important - ones, the ones you are likely to have to customize for your station, are - highlighted. +

+ This section is a reference to the options appearing in the + Standard skin configuration file, found in $SKIN_ROOT/Standard/skin.conf. +

+

+ It is worth noting that, like the main configuration file weewx.conf, UTF-8 is used throughout. The + most important options are up near the top of the file. The + truly important ones, the ones you are likely to have to + customize for your station, are + highlighted.

[Extras]

-

This section is available to you to add any static tags that you might - want to be available in the templates.

+

This section is available to you to add any static tags + that you might want to be available in the templates.

An Example: the Standard skin

-

As an example, the Standard skin.conf - file includes two options: radar_url, which is - available as tag $Extras.radar_url, and - googleAnalyticsId, available as tag - $Extras.googleAnalyticsId. If you take a look - at the template - index.html.tmpl you will see examples of - testing for these tags (search the file for the string - radar_url or - googleAnalyticsId to find them).

-

radar_url

-

If set, the NOAA radar image will be displayed. If commented out, no - image will be displayed.

-

googleAnalyticsId

-

If you have a Google - Analytics ID, 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.

+

+ As an example, the Standard skin.conf + file includes two options: radar_url, + which is available as tag $Extras.radar_url, + and googleAnalyticsId, available as + tag $Extras.googleAnalyticsId. If you + take a look at the template index.html.tmpl + you will see examples of testing for these tags (search the file + for the string radar_url or googleAnalyticsId to find them). +

+

radar_url

+

If set, the NOAA radar image will be displayed. If + commented out, no image will be displayed.

+

googleAnalyticsId

+

+ If you have a Google + Analytics ID, 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. +

-

Extending [Extras]

-

Other tags can be added in a similar manner, including sub-sections. - 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 sub-section.

+

+ Extending [Extras] +

+

Other tags can be added in a similar manner, including + sub-sections. 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 sub-section.

[Extras]
     [[video]]
         still = video_capture.jpg
         hyperlink = http://www.eatatjoes.com/video.html
-

Then in your template you could refer to these as:

+

Then in your template you could refer to these as:

<a href="$Extras.video.hyperlink">
     <img src="$Extras.video.still" alt="Video capture"/>
 </a>

[Units]

-

This section deals with Units and their formatting.

+

This section deals with Units and their formatting.

[[Groups]]

-

This sub-section lists all the Unit Groups and specifies which - unit system is to be used for each one of them.

-

As there are many different observational measurement types (such as 'outTemp', 'barometer', - etc.) used in weewx (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. Weewx has taken a middle route and - divided all the different observation types into 12 different "unit - groups." A unit group is something like "group_temperature." It represents the measurement - system to be used by all observation types that are measured in - temperature, such as inside temperature (type 'inTemp'), - outside temperature ('outTemp'), dewpoint ('dewpoint'), wind chill ('windchill'), - and so on. If you decide that you want unit group - group_temperature - to be measured in "degree_C" then you are - saying all members of its group will be reported in degrees - Celsius.

-

Note that the unit system is always specified in the singular. That is, - specify "degree_C" or "foot", - not "degrees_C" or "feet". - See the Appendix Units for more - information, including a concise summary of the groups, their members, and - which options can be used for each group.

-

- group_altitude +

+ This sub-section lists all the Unit Groups and + specifies which unit system is to be used for each one of them.

-

Which measurement unit to be used for altitude. Possible options are 'foot' or 'meter'.

-

group_direction

-

Which measurement unit to be used for direction. The only option is "degree_compass".

-

group_moisture

-

The measurement unit to be used for soil moisture. The only option is "centibar."

-

group_percent

-

The measurement unit to be used for percentages. The only option is "percent".

-

group_pressure

-

The measurement unit to be used for pressure. Possible options are one - of "inHg" (inches of mercury), "mbar", - or "hPa."

-

group_radiation

-

The measurement unit to be used for radiation. The only option is "watt_per_meter_squared."

-

group_rain

-

The measurement unit to be used for precipitation. Options are "inch", - "cm," or "mm."

-

group_rainrate

-

The measurement unit to be used for rate of precipitation. Possible - options are one of "inch_per_hour", "cm_per_hour", - or "mm_per_hour".

-

group_speed

-

The measurement unit to be used for wind speeds. Possible options are - one of "mile_per_hour", "km_per_hour", - "knot", or "meter_per_second." -

-

group_speed2

-

This group is similar to group_speed, but is - used for calculated wind speeds which typically have a slightly higher - resolution. Possible options are one "mile_per_hour2", - "km_per_hour2", "knot2", - or "meter_per_second2".

-

group_temperature +

+ As there are many different observational measurement types + (such as 'outTemp', 'barometer', etc.) used in weewx (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. Weewx + has taken a middle route and divided all the different + observation types into 12 different "unit groups." A + unit group is something like "group_temperature." + It represents the measurement system to be used by all + observation types that are measured in temperature, such as + inside temperature (type 'inTemp'), + outside temperature ('outTemp'), + dewpoint ('dewpoint'), wind chill ('windchill'), and so on. If you decide that + you want unit group group_temperature + to be measured in "degree_C" then you + are saying all members of its group will be reported in + degrees Celsius. +

+

+ Note that the unit system is always specified in the singular. + That is, specify "degree_C" or "foot", not "degrees_C" + or "feet". See the Appendix + Units + for more information, including a concise summary of the + groups, their members, and which options can be used for each + group. +

+

+ group_altitude +

+

+ Which measurement unit to be used for altitude. Possible options + are 'foot' or 'meter'. +

+

group_direction

+

+ Which measurement unit to be used for direction. The only option + is "degree_compass". +

+

group_moisture

+

+ The measurement unit to be used for soil moisture. The only + option is "centibar." +

+

group_percent

+

+ The measurement unit to be used for percentages. The only option + is "percent". +

+

group_pressure

+

+ The measurement unit to be used for pressure. Possible options + are one of "inHg" (inches of mercury), + "mbar", or "hPa." +

+

group_radiation

+

+ The measurement unit to be used for radiation. The only option + is "watt_per_meter_squared." +

+

group_rain

+

+ The measurement unit to be used for precipitation. Options are "inch", "cm," or + "mm." +

+

group_rainrate

+

+ The measurement unit to be used for rate of precipitation. + Possible options are one of "inch_per_hour", + "cm_per_hour", or "mm_per_hour". +

+

group_speed

+

+ The measurement unit to be used for wind speeds. Possible + options are one of "mile_per_hour", "km_per_hour", "knot", + or "meter_per_second." +

+

group_speed2

+

+ This group is similar to group_speed, + but is used for calculated wind speeds which typically have a + slightly higher resolution. Possible options are one "mile_per_hour2", "km_per_hour2", + "knot2", or "meter_per_second2". +

+

+ group_temperature +

+

+ The measurement unit to be used for temperatures. Options are "degree_F" or "degree_C." +

+

group_volt

+

+ The measurement unit to be used for voltages. The only option is + "volt."

-

The measurement unit to be used for temperatures. Options are "degree_F" - or "degree_C."

-

group_volt

-

The measurement unit to be used for voltages. The only option is "volt."

[[StringFormats]]

-

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

+

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

degree_C = %.1f
 inch     = %.2f
-

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 - formatting codes are those used by Python, a, and are very similar - to C's sprintf() codes.

-

You can also specify what string to use for an invalid or unavailable - measurement (value 'None'). For example,

+

+ 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 + formatting codes are those used by Python, a, and are very + similar to C's sprintf() codes. +

+

+ You can also specify what string to use for an invalid or + unavailable measurement (value 'None'). + For example, +

NONE = " N/A "

[[Labels]]

-

This sub-section specifies what label is to be used for each - measurement unit type. For example, the options

-
degree_F = °F
+      

This sub-section specifies what label is to be used for + each measurement unit type. For example, the options

+
degree_F = °F
 inch     = ' in'
-

would cause all temperatures to have unit labels °F - 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).

+

+ would cause all temperatures to have unit labels °F 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). +

[[TimeFormats]]

-

This sub-section is used for date and time labels, using - strftime() - formats. The values that come with the default - skin.conf will work for most locales, - provided you set the environment - variable LANG before running weewx.

-

While they give acceptable results in all locales, the defaults are - not the most attractive. For example, the format used for the month - summary is

-
month = %x %X
-

which (in the U.S. locale) results in something that looks like

-

11/09/09 05:20:00 PM

-

You may wish to do something fancier. For example, try this one

+

+ This sub-section is used for date and time labels, using + strftime() formats. The values that come with the default skin.conf will work for most locales, provided you set the + environment variable LANG before running weewx. +

+

While they give acceptable results in all locales, the + defaults are not the most attractive. For example, the format + used for the month summary is

+
month = %x %X
+

which (in the U.S. locale) results in something that looks + like

+

11/09/09 05:20:00 PM

+

You may wish to do something fancier. For example, try this + one

month = %d-%b-%Y %H:%M

which results in a lable that looks like:

-

06-Oct-2009 15:20

-

Section [[TimeFormats]] also allows the - formatting to be set for almanac times:

+

06-Oct-2009 15:20

+

+ Section [[TimeFormats]] also allows + the formatting to be set for almanac times: +

ephem_day  = %X
 ephem_year = %x %X
-

The first of these, ephem_day, is used for - almanac times within the day, such as sunrise or sunset. The second, ephem_year, is used for almanac times within the - year, such as the next equinox or full moon.

+

+ The first of these, ephem_day, is used + for almanac times within the day, such as sunrise or sunset. The + second, ephem_year, is used for + almanac times within the year, such as the next equinox or full + moon. +

[[Ordinates]]

directions

-

Set to the abbreviations to be used for ordinal directions. By default, - this is N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, - WSW, W, WNW, NW, NNW, N.

+

+ Set to the abbreviations to be used for ordinal directions. By + default, this is N, NNE, NE, ENE, E, + ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW, N. +

[[DegreeDays]]

-

heating_base
- cooling_base

-

Set to the base temperature for calculating heating and cooling - degree-days, along with the unit to be used. Examples:

+

+ heating_base
cooling_base +

+

Set to the base temperature for calculating heating and + cooling degree-days, along with the unit to be used. Examples:

heating_base = 65.0, degree_F
 cooling_base = 20.0, degree_C

[[Trend]]

time_delta

-

Set to the time difference over which you want trends to be calculated. - The default is 3 hours.

+

Set to the time difference over which you want trends to be + calculated. The default is 3 hours.

time_grace

-

When searching for a previous record to be used in calculating a trend, - a record within this amount of time_delta - will be accepted. Default is 300 seconds.

+

+ When searching for a previous record to be used in calculating a + trend, a record within this amount of time_delta + will be accepted. Default is 300 seconds. +

[Labels]

-

This section sets the various labels to use.

-

hemispheres

-

Comma separated list for the labels to be used for the four - hemispheres. The default is "N, S, E, W".

-

latlon_formats

-

Comma separated list for the formatting to be used when converting - latitude and longitude to strings. There should be three elements:

-
    -
  1. The format to be used for whole degrees of latitude
  2. -
  3. The format to be used for whole degrees of longitude
  4. -
  5. The format to be used for minutes.
  6. -
-

This allows you to decide whether or not you want leading zeroes. The - default includes leading zeroes and is "%02d", "%03d", "%05.2f"

+

This section sets the various labels to use.

+

hemispheres

+

+ Comma separated list for the labels to be used for the four + hemispheres. The default is "N, S, E, + W". +

+

latlon_formats

+

Comma separated list for the formatting to be used when + converting latitude and longitude to strings. There should be + three elements:

+
    +
  1. The format to be used for whole degrees of latitude
  2. +
  3. The format to be used for whole degrees of longitude
  4. +
  5. The format to be used for minutes.
  6. +
+

This allows you to decide whether or not you want leading + zeroes. The default includes leading zeroes and is "%02d", + "%03d", "%05.2f"

[[Generic]]

-

This sub-section specifies default labels to be used for each SQL type. - For example, options

+

This sub-section specifies default labels to be used for + each SQL type. For example, options

inTemp = Temperature inside the house
 outTemp = Outside Temperature
-

would cause the given labels to be used for plots involving SQL types inTemp and outTemp.

+

+ would cause the given labels to be used for plots involving SQL + types inTemp and outTemp. +

[Almanac]

-

This section controls what text to use for the almanac. It consists of - only one entry

-

moon_phases

-

This option is a comma separated list of labels to be used for the - eight phases of the moon. Default is "New, Waxing - crescent, First quarter, Waxing gibbous, Full, Waning gibbous, Last - quarter, Waning crescent".

+

This section controls what text to use for the almanac. It + consists of only one entry

+

moon_phases

+

+ This option is a comma separated list of labels to be used for + the eight phases of the moon. Default is "New, + Waxing crescent, First quarter, Waxing gibbous, Full, Waning + gibbous, Last quarter, Waning crescent". +

[CheetahGenerator]

-

This section is used by generator - weewx.cheetahgenerator.CheetahGenerator - and controls text generation from templates, specifically which files - are to be produced from which template.

-

Before V2.5, this section was called - [FileGenerator]. Older versions and names are - 100% backwards compatible.

+

+ This section is used by generator weewx.cheetahgenerator.CheetahGenerator + and controls text generation from templates, specifically which + files are to be produced from which template. +

+

+ Before V2.5, this section was called [FileGenerator]. + Older versions and names are 100% backwards compatible. +

Overview of file generation

-

Files are generated from templates, and each template is identified by - the template parameter.

-

Each template file is named something like - D/F.E.tmpl, where - D is the (optional) directory the template - sits in and will also be the directory the results will be put in, and - F.E is the generated file name. So, given a template file with name - Acme/index.html.tmpl, the results will be put in - $HTML_ROOT/Acme/index.html.

-

The configuration for a group of templates will look something like - this:

-
[CheetahGenerator]
+      

+ Files are generated from templates, and each template is + identified by the template + parameter. +

+

+ Each template file is named something like D/F.E.tmpl, + where D is the (optional) directory + the template sits in and will also be the directory the results + will be put in, and F.E is the + generated file name. So, given a template file with name Acme/index.html.tmpl, the results will be + put in $HTML_ROOT/Acme/index.html. +

+

The configuration for a group of templates will look + something like this:

+
[CheetahGenerator]
     [[index]]
         template = index.html.tmpl
     [[textfile]]
         template = filename.txt.tmpl
     [[xmlfile]]
         template = filename.xml.tmpl
-

There can be only one template in - each block. In most cases, the block name does not matter - it is used - only to isolate each template. However, there are two block names that - have speacial meaning: SummaryByMonth and SummaryByYear. These are - described below.

-

The file generator runs on each new archive record. In a default weewx - installation, that would be every 5 minutes.

-

Cheetah processes each template to generate a file. Cheetah follows any - logic defined by directives such as for - or if ... else, and it replaces variables such - as $Extras.radar_url or - $current.outTemp.max.

-

Variables are defined by objects in weewx. Some variables are static, - others are linked to data in databases. The list of variables can be - extended.

+

+ There can be only one template + in each block. In most cases, the block name does not matter - + it is used only to isolate each template. However, there are two + block names that have speacial meaning: SummaryByMonth and + SummaryByYear. These are described below. +

+

The file generator runs on each new archive record. In a + default weewx installation, that would be every 5 minutes.

+

+ Cheetah processes each template to generate a file. Cheetah + follows any logic defined by directives such as for or if ... + else, and it replaces variables such as $Extras.radar_url + or $current.outTemp.max. +

+

Variables are defined by objects in weewx. Some variables + are static, others are linked to data in databases. The list of + variables can be extended.

File generation options

search_list

-

This is the list of search list objects that will be scanned by the - template engine, looking for tags. See the section - Defining new tags and the - - Cheetah documentation for details on search lists. If no - search_list - is specified, a default list will be used. The default list is:

+

+ This is the list of search list objects that will be scanned by + the template engine, looking for tags. See the section + Defining new tags + and the + Cheetah documentation for details on search lists. If no search_list is specified, a + default list will be used. The default list is: +

search_list = weewx.cheetahgenerator.Almanac, weewx.cheetahgenerator.Station, weewx.cheetahgenerator.Stats, weewx.cheetahgenerator.UnitInfo, weewx.cheetahgenerator.Extras, weewx.cheetahgenerator.Current

search_list_extensions

-

This defines one or more search list objects that will be appended to - the search_list. For example, the - following adds alltime and forecast variables to the search list.

+

+ This defines one or more search list objects that will be + appended to the search_list. + For example, the following adds alltime and forecast variables + to the search list. +

search_list_extensions = examples.xsearch.MyXSearch, user.forecast.ForecastVariables
-

encoding

-

This option controls which encoding is to be used for the generated - output. The encoding can be specified for individual files. There are 3 - possible choices:

+

encoding

+

This option controls which encoding is to be used for the + generated output. The encoding can be specified for individual + files. There are 3 possible choices:

@@ -1613,8 +1966,10 @@ outTemp = Outside Temperature - + @@ -1626,48 +1981,62 @@ outTemp = Outside Temperature
html_entitiesNon 7-bit characters will be represented as HTML entities (e.g., - the degree sign will be represented as &#176;)Non 7-bit characters will be represented as HTML + entities (e.g., the degree sign will be + represented as &#176;) +
utf8
-

The encoding html_entities is the default.

+

+ The encoding html_entities is the + default. +

template

-

The name of a template file. A template filename must end with - .tmpl. Filenames are case-sensitive. If the - template filename has the letters YYYY - or MM in its name, these will be substituted - for the year and month, respectively. So, a template with the name - summary-YYYY-MM.html.tmpl would have name - summary-2010-03.html for the month of March, - 2010.

+

+ The name of a template file. A template filename must end with .tmpl. Filenames are case-sensitive. If + the template filename has the letters YYYY + or MM in its name, these will be + substituted for the year and month, respectively. So, a template + with the name summary-YYYY-MM.html.tmpl + would have name summary-2010-03.html + for the month of March, 2010. +

stale_age

-

File staleness age, in seconds. If the file is older than this age it - will be generated from the template. If no stale_age is specified the file - will be generated each time the generator runs.

+

File staleness age, in seconds. If the file is older than + this age it will be generated from the template. If no stale_age + is specified the file will be generated each time the generator + runs.

[[SummaryByMonth]]

-

The SummaryByMonth section defines some - special behavior. Each template in this section will be used multiple - times, each time with a different per-month timespan. Be sure to include - YYYY and - MM in the filename of any template in this - section.

+

+ The SummaryByMonth section defines + some special behavior. Each template in this section will be + used multiple times, each time with a different per-month + timespan. Be sure to include YYYY and + MM in the filename of any template in + this section. +

[[SummaryByYear]]

-

The SummaryByYear section defines some - special behavior. Each template in this section will be used multiple - times, each time with a different per-year timespan. Be sure to include - YYYY in the filename of any template in this section.

+

+ The SummaryByYear section defines some + special behavior. Each template in this section will be used + multiple times, each time with a different per-year timespan. Be + sure to include YYYY in the filename + of any template in this section. +

Customizing file generation

-

The best way to customization file generation is to make a copy of a - working report/skin, then make incremental changes.

-

When there is an error during template generation, the error will show - up in the log file. Many errors are obvious - Cheetah will display a line - number and list the template file in which the error occurred. In some - cases the error reporting is rather obscure. So make small changes and - tests often. Use - wee_report - to test modifications to the generator configuration and/or the template - contents.

+

The best way to customization file generation is to make a + copy of a working report/skin, then make incremental changes.

+

+ When there is an error during template generation, the error + will show up in the log file. Many errors are obvious - Cheetah + will display a line number and list the template file in which + the error occurred. In some cases the error reporting is rather + obscure. So make small changes and tests often. Use wee_report to test modifications to the + generator configuration and/or the template contents. +

An Example: the Standard skin

-

Here is the [CheetahGenerator] section from - the Standard skin.conf

+

+ Here is the [CheetahGenerator] section + from the Standard skin.conf +

[CheetahGenerator]
     # This section is used by the generator CheetahGenerator, and specifies
@@ -1708,57 +2077,69 @@ outTemp = Outside Temperature
[[[Mobile]]] template = mobile.html.tmpl
-

The Standard skin contains three different kinds of generated output:

+

The Standard skin contains three different kinds of + generated output:

    -
  1. Summary by Month. The Standard skin uses - SummaryByMonth to produce NOAA summaries, - one for each month, as a simple text file.
  2. -
  3. Summary by Year. The Standard skin uses - SummaryByYear to produce NOAA summaries, one - for each year, as a simple text file.
  4. -
  5. Summary "To Date". The Standard skin produce reports for the day, - week, month, and year-to-date observations. These files are HTML. The - first, the daily summary (output filename is - index.html), includes a drop-down list that - displays the NOAA month and yearly summaries.
  6. +
  7. Summary by Month. The Standard skin uses SummaryByMonth to produce NOAA summaries, + one for each month, as a simple text file. +
  8. +
  9. Summary by Year. The Standard skin uses SummaryByYear to produce NOAA summaries, + one for each year, as a simple text file. +
  10. +
  11. Summary "To Date". The Standard skin produce reports + for the day, week, month, and year-to-date observations. These + files are HTML. The first, the daily summary (output filename + is index.html), includes a drop-down + list that displays the NOAA month and yearly summaries. +
-

The encoding for text files is strict_ansii, - whereas the encoding for html files is - html_entities. In the Standard skin this is - specified by declaring - encoding = html_entities at the top level of - [CheetahGenerator] then - encoding = strict_ansii for each text file. +

+ The encoding for text files is strict_ansii, + whereas the encoding for html files is html_entities. + In the Standard skin this is specified by declaring encoding = html_entities at the top level + of [CheetahGenerator] then encoding = strict_ansii for each text + file. +

+

+ Other than SummaryByMonth and SummaryByYear, the section names are + arbitrary. ToDate could just as well + have been called files_to_date, and + the sections day, week, + and month could just as well have been + called tom, dick, + and harry.

-

Other than SummaryByMonth and - SummaryByYear, the section names are - arbitrary. ToDate could just as well have been - called files_to_date, and the sections - day, week, and - month could just as well have been called - tom, dick, and - harry.

[CopyGenerator]

-

This section is used by generator - weewx.reportengine.CopyGenerator - and controls which files are to be copied over from the skin directory - 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.

+

+ This section is used by generator + weewx.reportengine.CopyGenerator and controls which files are + to be copied over from the skin directory 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. +

Copy generator options

-

copy_once

-

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.

-

copy_always

-

This is a list of files that should be copied on every invocation. - Wildcards can be used.

+

copy_once

+

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.

+

copy_always

+

This is a list of files that should be copied on every + invocation. Wildcards can be used.

An Example: the Standard skin

-

Here is the [CopyGenerator] section from the - Standard skin.conf

+

+ Here is the [CopyGenerator] section + from the Standard skin.conf +

[CopyGenerator]
     # This section is used by the generator CopyGenerator
 
@@ -1767,21 +2148,26 @@ outTemp = Outside Temperature
# List of files to be copied each time the generator runs # copy_always =
-

The Standard skin includes some background images, CSS files, and icons - that need to be copied once. There are no files that need to be copied - each time the generator runs.

+

The Standard skin includes some background images, CSS + files, and icons that need to be copied once. There are no files + that need to be copied each time the generator runs.

[ImageGenerator]

-

This section is used by generator - weewx.reportengine.ImageGenerator - and controls which images (plots) get generated and with which options. - While complicated, it is extremely flexible and powerful.

+

+ This section is used by generator + weewx.reportengine.ImageGenerator and controls which images + (plots) get generated and with which options. While complicated, + it is extremely flexible and powerful. +

Time periods

-

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 is a - typical set of options for sub-section [[month_images]], - controlling how images that cover a month period are generated:

+

+ 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 is a typical set of options for + sub-section [[month_images]], + controlling how images that cover a month period are generated: +

[[month_images]]
     x_label_format = %d
     bottom_label_format = %x %X
@@ -1789,32 +2175,43 @@ outTemp = Outside Temperature
aggregate_type = avg aggregate_interval = 10800 # == 3 hours

Here's a description of these options.

-

The option x_label_format gives a - strftime() - type format for the x-axis. In this example, it will only show the day - of the month (format option "%d").

-

The bottom_label_format is the format used - for the time stamp at the bottom of the image. In this example, it has - been specified as "%x %X", - which will use date and time formatting appropriate for your locale, - provided you set environment - variable LANG first. For example, in the U.S., it will show the time - as 10/25/09 05:20:00 PM, while - in Europe it might show 25/10/09 17:20:00.

-

The option time_length = 2592000 says that - the plot will cover a nominal 30 days.

-

The option aggregate_type = avg says that - each point in the plot will be the average over a time period. The - option aggregate_interval = 10800 says that - time period will be 3 hours.

+

+ The option x_label_format gives a + strftime() type format for the x-axis. In this example, it + will only show the day of the month (format option "%d"). +

+

+ The bottom_label_format is the format + used for the time stamp at the bottom of the image. In this + example, it has been specified as "%x %X", + which will use date and time formatting appropriate for your + locale, provided you + set environment variable LANG first. For example, in the U.S., + it will show the time as 10/25/09 05:20:00 PM, + while in Europe it might show 25/10/09 + 17:20:00. +

+

+ The option time_length = 2592000 + says that the plot will cover a nominal 30 days. +

+

+ The option aggregate_type = avg + says that each point in the plot will be the average over a time + period. The option aggregate_interval = 10800 + says that time period will be 3 hours. +

Image files

-

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 is a - typical set of options for sub-sub-section - [[[monthrain]]]: +

+ 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 is a typical set of options for + sub-sub-section [[[monthrain]]]:

[[[monthrain]]]
     plot_type = bar
@@ -1823,80 +2220,104 @@ outTemp = Outside Temperature
aggregate_type = sum aggregate_interval = 86400 label = Rain (daily avg) -

This will generate an image file with name - monthrain.png. It will be a bar plot. Option - yscale controls the y-axis scaling — if left out, the scale will - automatically be chosen. However, in this example we are choosing to - exercise some degree of control by specifying values explicitly. The - option takes a 3-way tuple (ylow, - yhigh, - min_interval), where ylow - and yhigh are the minimum and maximum y-axis - values, respectively, and min_interval is the - minimum tick interval. If set to 'None', the - corresponding value will be automatically chosen. So, in this example, the - setting

+

+ This will generate an image file with name + monthrain.png. It will be a bar plot. Option yscale controls the y-axis scaling — if + left out, the scale will automatically be chosen. However, in + this example we are choosing to exercise some degree of control + by specifying values explicitly. The option takes a 3-way tuple + (ylow, + yhigh, min_interval), where ylow and yhigh + are the minimum and maximum y-axis values, respectively, and min_interval is the minimum tick interval. + If set to 'None', the corresponding + value will be automatically chosen. So, in this example, the + setting +

yscale = None, None, 0.02
-

will cause weewx to pick sensible y minimum - and maximum values, but require that the tick increment (min_interval) - be at least 0.02.

-

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 "rain". Because we have not said otherwise, - the SQL data type to be used for this line will be the same as its logical - name, that is, rain, but this can be overridden - (see below). The aggregation type will be summing (overriding the - averaging specified in sub-section [[month_images]]), - 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 ('Rain - (daily avg)')

-

If there is a time gap in the data, the options - line_gap_fraction - and bar_gap_fraction control how it will be - drawn. The former, line_gap_fraction, is used - for line graphs, the latter, bar_gap_fraction, - for bar graphs. Here's what the resultant plots look like without and with - this option being specified:

-
-
+ will cause weewx to pick sensible y + minimum and maximum values, but require that the tick increment + (min_interval) be at least 0.02. +

+

+ 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 "rain". Because we + have not said otherwise, the SQL data type to be used for this + line will be the same as its logical name, that is, rain, but this can be overridden (see + below). The aggregation type will be summing (overriding the + averaging specified in sub-section [[month_images]]), + 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 ('Rain (daily avg)') +

+

+ If there is a time gap in the data, the options line_gap_fraction and bar_gap_fraction + control how it will be drawn. The former, line_gap_fraction, + is used for line graphs, the latter, bar_gap_fraction, + for bar graphs. Here's what the resultant plots look like + without and with this option being specified: +

+
+
+ Gap not shown -

No line_gap_fraction - specified

+

+ No line_gap_fraction specified +

-
Gap showing -

With line_gap_fraction=0.01

+
+ Gap showing +

+ With line_gap_fraction=0.01 +

-
+

Including more than one SQL type in a plot

-

More than one SQL type can be included in a plot. For example, here is - how to generate a plot with the week's outside temperature as well as - dewpoint:

+

More than one SQL type can be included in a plot. For + example, here is how to generate a plot with the week's outside + temperature as well as dewpoint:

[[[monthtempdew]]]
     [[[[outTemp]]]]
     [[[[dewpoint]]]]
-

This would create an image in file monthtempdew.png - that includes a line plot of both outside temperature and dewpoint.

+

+ This would create an image in file monthtempdew.png + that includes a line plot of both outside temperature and + dewpoint. +

Including the same SQL type more than once in a plot

-

Another example. Say you want a plot of the day's temperature, overlaid - with hourly averages. Here, you are using the same data type ('outTemp') - for both plot lines, the first with averages, the second without. If you - do the obvious it won't work:

+

+ Another example. Say you want a plot of the day's temperature, + overlaid with hourly averages. Here, you are using the same data + type ('outTemp') for both plot lines, + the first with averages, the second without. If you do the + obvious it won't work: +

## WRONG ##
 [[[daytemp_with_avg]]]
     [[[[outTemp]]]]
         aggregate_type = avg
         aggregate_interval = 3600
     [[[[outTemp]]]]  # OOPS! The same section name appears more than once!
-

The option parser does not allow the same section name ('outTemp' - 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 data_type. This will - override the default action that the logical line name is used for the SQL - type. So, our example would look like this:

+

+ The option parser does not allow the same section name ('outTemp' 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 data_type. This will + override the default action that the logical line name is used + for the SQL type. So, our example would look like this: +

[[[daytemp_with_avg]]]
     [[[[a_logical_name]]]]
         data_type = outTemp
@@ -1904,18 +2325,24 @@ outTemp = Outside Temperature
aggregate_interval = 3600 label = Avg. Temp. [[[[outTemp]]]] -

Here, the first logical line has been given the name "a_logical_name" - to distinguish it from the second line "outTemp". - We have specified that the first line will use data type - outTemp and that it will use averaging over a one hour period. - The second also uses outTemp, but will not use - averaging.

-

The result is a nice plot of the day's temperature, overlaid with a - 3-hour smoothed average:

-

Daytime temperature with running average

-

One more example. This one shows daily high and low temperatures for a - year:

+

+ Here, the first logical line has been given the name "a_logical_name" to distinguish it from the + second line "outTemp". We have + specified that the first line will use data type outTemp and that it will use averaging + over a one hour period. The second also uses outTemp, + but will not use averaging. +

+

The result is a nice plot of the day's temperature, + overlaid with a 3-hour smoothed average:

+

+ Daytime temperature with running average +

+

One more example. This one shows daily high and low + temperatures for a year:

[[year_images]]
     ...
     [[[yearhilow]]]
@@ -1927,20 +2354,29 @@ outTemp = Outside Temperature
date_type = outTemp aggregate_type = min label = Low Temperature -

This results in the plot yearhilow.png:

-

Daily highs and lows

+

+ This results in the plot yearhilow.png: +

+

+ Daily highs and lows +

Progressive vector plots

-

Weewx can produce progressive vector plots as - well as the more conventional x-y plots. To produce these, use plot type 'vector'. - You need a vector type to produce this kind of plot. There are two: 'windvec', - and 'windgustvec'. While they do not actually - appear in the SQL database, weewx understands - that they represent special vector-types. The first, 'windvec', - represents the average wind in an archive period, the second, 'windgustvec' - 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:

+

+ Weewx can produce progressive vector + plots as well as the more conventional x-y plots. To produce + these, use plot type 'vector'. You + need a vector type to produce this kind of plot. There are two: + 'windvec', and 'windgustvec'. + While they do not actually appear in the SQL database, weewx understands that they represent + special vector-types. The first, 'windvec', + represents the average wind in an archive period, the second, 'windgustvec' 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: +

[[[weekgustoverlay]]]
     aggregate_interval = 3600
     [[[[windvec]]]]
@@ -1951,48 +2387,61 @@ outTemp = Outside Temperature
label = Gust Wind plot_type = vector aggregate_type = max -

This will produce an image file with name - weekgustoverlay.png. 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: +

+ This will produce an image file with name + weekgustoverlay.png. 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:

-

hourly average wind vector overlaid with gust vectors

-

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 do not line up over the x-axis, - overlaying each other. Do this by using option - vector_rotate. For example, with my chronic westerlies, I set - vector_rotate - to 90.0 for the plot above, so winds out of the west point straight up. +

+ hourly average wind vector overlaid with gust vectors +

+

+ 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 do not line up over the x-axis, overlaying each + other. Do this by using option + vector_rotate. For example, with my chronic westerlies, I set + vector_rotate to 90.0 for the plot + above, so winds out of the west point straight up. +

+

+ If you use this kind of plot (the out-of-the-box version of weewx 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.

-

If you use this kind of plot (the out-of-the-box version of - weewx - 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.

Overriding values

-

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 weewx.conf file - specifies plot size of 300x180 pixels, which will be used for all plots - unless overridden:

+

+ 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 weewx.conf file specifies plot size of + 300x180 pixels, which will be used for all plots unless + overridden: +

[Images]
     ...
-    image_width=300
+    image_width  = 300
     image_height = 180
-

The standard plot of barometric pressure will appear in - daybarometer.png: +

+ The standard plot of barometric pressure will appear in daybarometer.png:

[[[daybarometer]]]
     [[[[barometer]]]] 
-

We now add our special plot of barometric pressure, but specify a - larger image size. This image will be put in file - daybarometer_big.png. +

+ We now add our special plot of barometric pressure, but specify + a larger image size. This image will be put in file daybarometer_big.png.

[[[daybarometer_big]]]
     image_width  = 600
@@ -2000,8 +2449,10 @@ outTemp = Outside Temperature
[[[[barometer]]]]

An Example: the Standard skin

-

Here is part of the [ImageGenerator] - section from the Standard skin.conf

+

+ Here is part of the [ImageGenerator] + section from the Standard skin.conf +

[ImageGenerator]
     image_width = 300
     image_height = 180
@@ -2071,45 +2522,57 @@ outTemp = Outside Temperature
... -

The Standard skin defines many different types of plots. Note that each - plot will be created only if there are data that match the definition. For - example, if a station does not produce radiation data, no radiation images - will be generated. This means that a single report can be used for many - different stations, even if the stations have different sensors or - capabilities.

+

The Standard skin defines many different types of plots. + Note that each plot will be created only if there are data that + match the definition. For example, if a station does not produce + radiation data, no radiation images will be generated. This + means that a single report can be used for many different + stations, even if the stations have different sensors or + capabilities.

[Generators]

-

This section defines the generators that should be run as well as - options for specific generators.

+

This section defines the generators that should be run as + well as options for specific generators.

Generator options

-

generator_list

-

This option controls which generators get run for this skin. It is a - comma separated list. The generators will be run in this order.

+

generator_list

+

This option controls which generators get run for this + skin. It is a comma separated list. The generators will be run + in this order.

An Example: the Standard skin

-

Here is the [Generators] section from the - Standard skin.conf

+

+ Here is the [Generators] section from + the Standard skin.conf +

[Generators]
     generator_list = weewx.cheetahgenerator.CheetahGenerator, weewx.imagegenerator.ImageGenerator, weewx.reportengine.CopyGenerator
-

The Standard skin uses three generators: CheetahGenerator, - ImageGenerator, and CopyGenerator.

+

The Standard skin uses three generators: CheetahGenerator, + ImageGenerator, and CopyGenerator.

Localization

-

Weewx has been designed to make localization fairly straightforward. - What follows is a guide to localizing to a non-English language and/or - locale.

+

Weewx has been designed to make localization fairly + straightforward. What follows is a guide to localizing to a + non-English language and/or locale.

Translate the templates

-

First, you will need to go through the templates and translate to your - target language. Obvious text strings such as "Current - Weather Conditions" will need to be translated.

+

+ First, you will need to go through the templates and translate + to your target language. Obvious text strings such as "Current Weather Conditions" will need to + be translated. +

Modify skin.conf to reflect local conventions

-

Next, you will need to go through skin.conf - and modify options to follow local conventions. This includes dates and - labels.

+

+ Next, you will need to go through skin.conf + and modify options to follow local conventions. This includes + dates and labels. +

Dates

-

The date and time formats used in the default distribution of - weewx are locale independent, so they should be OK.

+

+ The date and time formats used in the default distribution of weewx are locale independent, so they + should be OK. +

    [[TimeFormats]]
         #
         # This section sets the string format to be used for
@@ -2123,23 +2586,23 @@ outTemp = Outside Temperature
current = %x %X ephem_day = %X ephem_year = %x %X -

The specifiers "%X" and "%x" say to format the time and date, - respectively, in a way that is suitable for your locale.

-

The bottom label format used in plots should also be OK:

+

The specifiers "%X" and "%x" say to format the time and + date, respectively, in a way that is suitable for your locale.

+

The bottom label format used in plots should also be OK:

bottom_label_format = %x %X

Labels

-

There are several almanac labels that may need to be changed. These - include:

+

There are several almanac labels that may need to be + changed. These include:

hemisphere = N, S, E, W

and

moon_phases = New, Waxing crescent, First quarter, Waxing gibbous, Full, Waning gibbous, Last quarter, Waning crescent
-

Most of the unit labels either follow ISO conventions, or are unlikely - to be used outside English speaking countries (an example would be - "foot"). But, there are two exceptions:

-
hour           = " hrs"
+      

Most of the unit labels either follow ISO conventions, or + are unlikely to be used outside English speaking countries (an + example would be "foot"). But, there are two exceptions:

+
hour           = " hrs"
 second         = " secs"
-

You will also have to change the generic labels given to your weather - observations:

+

You will also have to change the generic labels given to + your weather observations:

barometer      = Barometer
 dewpoint       = Dew Point
 heatindex      = Heat Index
@@ -2159,35 +2622,50 @@ windchill      = Wind Chill
 windgustvec    = Gust Vector
 windvec        = Wind Vector
 extraTemp1     = Pond Temperature
-

Environment variable - LANG

-

Finally, you will need to set the environment variable - LANG - to reflect your locale. For example, assuming you set

+

+ Environment variable LANG +

+

+ Finally, you will need to set the environment variable LANG to reflect your locale. For example, + assuming you set +

$ export LANG=es_ES.UTF-8
-

before running weewx, then the local Spanish - names for days of the week and months of the year will be used. The - decimal point for numbers will also be modified appropriately.

-

Customizing the weewx - service engine

-

This is an advanced 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.

-

Please note that the service engine is likely to change in future - versions!

-

At a high level, weewx consists of an - engine - that is responsible for managing a set of services. A service - consists of a Python class which binds its member functions to various - events. The engine arranges to have the bound member function called - when a specific event happens, such as a new LOOP packet arriving.

-

To customize, you can

+

+ before running weewx, then the local + Spanish names for days of the week and months of the year will + be used. The decimal point for numbers will also be modified + appropriately. +

+

+ Customizing the weewx service engine +

+

This is an advanced 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.

+

+ Please note that the service engine is likely to change + in future versions! +

+

+ At a high level, weewx consists of an + engine that is responsible for managing a set of services. + A service consists of a Python class which binds its member + functions to various events. The engine arranges to + have the bound member function called when a specific event + happens, such as a new LOOP packet arriving. +

+

To customize, you can

    -
  • Customize a service
  • -
  • Add a service
  • +
  • Customize a service
  • +
  • Add a service
-

The default install of weewx includes the - following services, shown in the order they are normally run:

+

+ The default install of weewx includes + the following services, shown in the order they are normally + run: +

@@ -2196,17 +2674,18 @@ extraTemp1 = Pond Temperature - + - + - + @@ -2214,41 +2693,48 @@ extraTemp1 = Pond Temperature - + - + - + - +
weewx.wxengine.StdConvertConverts the units of the input to a target unit system (such as - US or Metric).Converts the units of the input to a target unit + system (such as US or Metric).
weewx.wxengine.StdCalibrateAdjust new LOOP and archive packets using calibration - expressions.Adjust new LOOP and archive packets using + calibration expressions.
weewx.wxengine.StdQCCheck that observation values fall within a specified range.Check that observation values fall within a + specified range.
weewx.wxengine.StdArchive
weewx.wxengine.StdTimeSynchArrange to have the clock on the console synchronized at regular - intervals.Arrange to have the clock on the console + synchronized at regular intervals.
weewx.wxengine.StdPrintPrint out new LOOP and archive packets on the console.Print out new LOOP and archive packets on the + console.
weewx.wxengine.StdRESTfulStart a thread to manage - RESTful (simple stateless client-server protocols) - connections; such as those used by the Weather Underground or - PWSweather.Start a thread to manage + RESTful (simple stateless client-server protocols) + connections; such as those used by the Weather Underground + or PWSweather. +
weewx.wxengine.StdReportLaunch a new thread to do report processing after a new archive - record arrives. Reports do things such as generate HTML files, - generate images, or FTP/rsync files to a web server. New reports can - be added easily by the user.Launch a new thread to do report processing after a + new archive record arrives. Reports do things such as + generate HTML files, generate images, or FTP/rsync files + to a web server. New reports can be added easily by the + user.

Customizing a Service

-

The service weewx.wxengine.StdPrint prints - out new LOOP and archive packets to the console when they arrive. By - default, it prints out the entire record, which generally includes a lot - of possibly distracting information and can be rather messy. Suppose you - do not like this, and want it to print out only the time, barometer - reading, and the outside temperature whenever a new LOOP packet arrives. - This could be done by subclassing the default print service - StdPrint - and overriding member function new_loop_packet(). +

+ The service weewx.wxengine.StdPrint + prints out new LOOP and archive packets to the console when they + arrive. By default, it prints out the entire record, which + generally includes a lot of possibly distracting information and + can be rather messy. Suppose you do not like this, and want it + to print out only the time, barometer reading, and the outside + temperature whenever a new LOOP packet arrives. This could be + done by subclassing the default print service + StdPrint and overriding member function new_loop_packet().

-

Create the file $BIN_ROOT/user/myprint.py: +

+ Create the file $BIN_ROOT/user/myprint.py:

from weewx.wxengine import StdPrint
 from weeutil.weeutil import timestamp_to_string
@@ -2261,32 +2747,44 @@ class MyPrint(StdPrint):
     print "LOOP: ", timestamp_to_string(packet['dateTime']),
         "BAR=",  packet.get('barometer', 'N/A'),
         "TEMP=", packet.get('outTemp', 'N/A')
-

This service substitutes a new implementation for the member function new_loop_packet. This implementation prints out - the time, then the barometer reading (or 'N/A' - if it is not available) and the outside temperature (or 'N/A').

-

You then need to specify that your print service class should be loaded - instead of the default StdPrint service. This is - done by substituting your service name for StdPrint - in service_list, located in - [Engines][[WxEngine]]: +

+ This service substitutes a new implementation for the member + function new_loop_packet. This + implementation prints out the time, then the barometer reading + (or 'N/A' if it is not available) and + the outside temperature (or 'N/A'). +

+

+ You then need to specify that your print service class should be + loaded instead of the default StdPrint + service. This is done by substituting your service name for StdPrint in service_list, + located in [Engines][[WxEngine]]:

[Engines]
     [[WxEngine]]
-        service_list = weewx.wxengine.StdConvert, weewx.wxengine.StdCalibrate, weewx.wxengine.StdQC, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, user.myprint.MyPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReport
-

Note that the service_list must be all on one - line. Unfortunately, the parser ConfigObj - does not allow options to be continued on to following lines.

+ service_list = weewx.wxengine.StdConvert, weewx.wxengine.StdCalibrate, weewx.wxengine.StdQC, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, user.myprint.MyPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReport
+

+ Note that the service_list must be all + on one line. Unfortunately, the parser ConfigObj + does not allow options to be continued on to following lines. +

Adding a Service

-

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 StdService, and then - adding the functionality you need. Here is 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 directory $BIN_ROOT/examples.

-

File examples/alarm.py:

+

+ 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 StdService, + and then adding the functionality you need. Here is 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 + directory $BIN_ROOT/examples. +

+

+ File examples/alarm.py: +

import time
 import smtplib
 from email.mime.text import MIMEText
@@ -2395,10 +2893,12 @@ class MyAlarm(StdService):
         
         # Log sending the email:
         syslog.syslog(syslog.LOG_INFO, "  **** email sent to: %s" % self.TO)    
-

This service expects all the information it needs to be in the - configuration file weewx.conf in a new section - called [Alarm]. So, add the following lines to - your configuration file:

+

+ This service expects all the information it needs to be in the + configuration file weewx.conf in a new + section called [Alarm]. So, add the + following lines to your configuration file: +

[Alarm]
     expression = "outTemp < 40.0"
     time_wait = 3600
@@ -2408,77 +2908,108 @@ class MyAlarm(StdService):
     mailto = auser@adomain.com, anotheruser@someplace.com
     from   = me@mydomain.com
     subject = "Alarm message from weewx!"
-

There are two important points to be noted in this example, each marked - with a "NOTE" flag in the code.

-
    -
  1. Here is where the binding happens between an event, - weewx.NEW_ARCHIVE_RECORD in this example, and a member function, - self.newArchiveRecord. There are other events that can be interecepted. - Look in the file $BIN_ROOT/weewx/__init__.py.
  2. -
  3. This is where the test is done of whether or not to sound the alarm. - The [Alarm] configuration options specify that - the alarm be sounded when "outTemp < 40.0" - 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.
  4. -
-

Another example expression could be:

-
expression = "outTemp < 32.0 and windSpeed > 10.0"
-

In this case, the alarm is sounded if the outside temperature drops - below freezing and the wind speed is greater than 10.0.

-

Option time_wait is used to avoid a flood of - nearly identical emails. The new service will wait this long before - sending another email out.

-

Email will be sent through the SMTP host specified by option - smtp_host. The recipient(s) are specified by the comma separated - option mailto. +

+ There are two important points to be noted in this example, each + marked with a "NOTE" flag in the code. +

+
    +
  1. Here is where the binding happens between an event, + weewx.NEW_ARCHIVE_RECORD in this example, and a member + function, self.newArchiveRecord. There are other events that + can be interecepted. Look in the file $BIN_ROOT/weewx/__init__.py. +
  2. +
  3. This is where the test is done of whether or not to + sound the alarm. The [Alarm] + configuration options specify that the alarm be sounded when "outTemp < 40.0" 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. +
  4. +
+

Another example expression could be:

+
expression = "outTemp < 32.0 and windSpeed > 10.0"
+

In this case, the alarm is sounded if the outside + temperature drops below freezing and the wind speed is greater + than 10.0.

+

+ Option time_wait is used to avoid a + flood of nearly identical emails. The new service will wait this + long before sending another email out. +

+

+ Email will be sent through the SMTP host specified by option smtp_host. The recipient(s) are specified + by the comma separated option mailto. +

+

+ Many SMTP hosts require user login. If this is the case, the + user and password are specified with options smtp_user + and smtp_password, respectively. +

+

+ The last two options, "from" and "subject" are optional. If not supplied, weewx will supply something sensible. + Note, however, that some mailers require a valid "from" email + address and the one weewx supplies may + not satisfy its requirements. +

+

+ 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 service_list, located in [Engines][[WxEngine]]:

-

Many SMTP hosts require user login. If this is the case, the user and - password are specified with options smtp_user - and smtp_password, respectively.

-

The last two options, "from" and "subject" - are optional. If not supplied, weewx will supply - something sensible. Note, however, that some mailers require a valid - "from" email address and the one weewx - supplies may not satisfy its requirements.

-

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 - service_list, located in [Engines][[WxEngine]]:

[Engines]
    [[WxEngine]]
-	service_list = weewx.wxengine.StdConvert, weewx.wxengine.StdCalibrate, weewx.wxengine.StdQC, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReport, examples.alarm.MyAlarm
-

Note that the service_list must be all on one - line. Unfortunately, the parser ConfigObj - does not allow options to be continued on to following lines.

-

In addition to the example above, the distribution also includes a - low-battery alarm (lowBattery.py), which is - similar, except that it intercepts LOOP events (instead of archiving - events).

-

Customizing the archive database

-

For most users the default database will work just fine. It has the - added advantage of being compatible with the wview database. Nevertheless, - there may be occasions where you may want to add a SQL type to your - database, or change its unit system. This section shows you how to do - this, using the utility $BIN_ROOT/wee_config_database.

-

Before starting, it's worth running the utility with the - --help - flag to see how it is used:

+ service_list = weewx.wxengine.StdConvert, weewx.wxengine.StdCalibrate, weewx.wxengine.StdQC, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReport, examples.alarm.MyAlarm + +

+ Note that the service_list must be all + on one line. Unfortunately, the parser ConfigObj + does not allow options to be continued on to following lines. +

+

+ In addition to the example above, the distribution also includes + a low-battery alarm (lowBattery.py), + which is similar, except that it intercepts LOOP events (instead + of archiving events). +

+

Customizing the archive database

+

+ For most users the default database will work just fine. It has + the added advantage of being compatible with the wview database. + Nevertheless, there may be occasions where you may want to add a + SQL type to your database, or change its unit system. This + section shows you how to do this, using the utility $BIN_ROOT/wee_config_database. +

+

+ Before starting, it's worth running the utility with the --help flag to see how it is used: +

$BIN_ROOT/wee_config_database --help

Adding a new observation type

-

Suppose you have installed an electric meter at your house and you wish - to correlate electrical usage with the weather. The meter has some sort of - connection to your computer, allowing you to download the consumption. At - the end of every archive interval you want to sample the meter for the - electricity consumed during the interval, then store the results in the - archive database, along with the weather data. How would you do this?

-

First, you would write a custom service that retrieves the electrical - consumption data and adds it to the archive record. See the section Customizing the weewx service engine for - details on how to write a custom service. However, when you are done it - will look something like this:

+

Suppose you have installed an electric meter at your house + and you wish to correlate electrical usage with the weather. The + meter has some sort of connection to your computer, allowing you + to download the consumption. At the end of every archive + interval you want to sample the meter for the electricity + consumed during the interval, then store the results in the + archive database, along with the weather data. How would you do + this?

+

+ First, you would write a custom service that retrieves the + electrical consumption data and adds it to the archive record. + See the section Customizing the + weewx service engine for details on how to write a custom + service. However, when you are done it will look something like + this: +

from weewx.wxengine import StdService
 	
 class AddElectricity(StdService):
@@ -2488,40 +3019,53 @@ class AddElectricity(StdService):
         (code that downloads the consumption data from the connection to the meter)
 
         event.record['electricity'] = retrieved_value
-

This adds a new key 'electricity' to the - record dictionary and sets it equal to some value. As an aside, if you do - something like this, you would want to make sure that the code to retrieve - the current electrical consumption does not delay very long so it does not - slow down the main loop. If it's going to cause a delay of more than a - couple seconds you might want to put it in a separate thread and feed the - results to AddElectricity - through a queue.

-

As usual, you would add your new service to the option - service_list in weewx.conf, making - sure it appears before StdArchive so your new - value is inserted into the record before the data is archived.

-

Adding a new type to the archive database

-

So, now you have created a new observation type, 'electricity'. - Trouble is, there is no corresponding type in the schema of the SQL - database and, therefore, it won't be stored there. How would you add such - a type?

+

+ This adds a new key 'electricity' to + the record dictionary and sets it equal to some value. As an + aside, if you do something like this, you would want to make + sure that the code to retrieve the current electrical + consumption does not delay very long so it does not slow down + the main loop. If it's going to cause a delay of more than a + couple seconds you might want to put it in a separate thread and + feed the results to AddElectricity + through a queue. +

+

+ As usual, you would add your new service to the option service_list in weewx.conf, + making sure it appears before StdArchive + so your new value is inserted into the record before + the data is archived. +

+

Adding a new type to the archive + database

+

+ So, now you have created a new observation type, 'electricity'. Trouble is, there is no + corresponding type in the schema of the SQL database and, + therefore, it won't be stored there. How would you add such a + type? +

Here's our general strategy:

  1. Add a new type to the database schema.
  2. -
  3. Make sure you have the necessary permissions to create the new - database.
  4. +
  5. Make sure you have the necessary permissions to create + the new database.
  6. Populate it with data from the old database.
  7. -
  8. Shuffle databases around so weewx will use - the new database.
  9. -
  10. Modify the stats database so it includes the new type as well - (Optional).
  11. +
  12. Shuffle databases around so weewx + will use the new database. +
  13. +
  14. Modify the stats database so it includes the new type + as well (Optional).
-

1. Adding a new type to the schema. When creating a - database the schema is obtained from file $BIN_ROOT/user/schemas.py. Take a look at it now. You will - see a list called defaultArchiveSchema that - holds all the observation names and their SQL types. It looks something - like:

+

+ 1. Adding a new type to the schema. When + creating a database the schema is obtained from file $BIN_ROOT/user/schemas.py. + Take a look at it now. You will see a list called defaultArchiveSchema that holds all the + observation names and their SQL types. It looks something like: +

defaultArchiveSchema = [('dateTime',             'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
         ('usUnits',              'INTEGER NOT NULL'),
         ('interval',             'INTEGER NOT NULL'),
@@ -2532,8 +3076,10 @@ class AddElectricity(StdService):
         ('outTemp',              'REAL'),
         ...
         ('inTempBatteryStatus',  'REAL')]
-

Let's modify it to add our new type, 'electricity'. - Now it looks like this:

+

+ Let's modify it to add our new type, 'electricity'. + Now it looks like this: +

defaultArchiveSchema = [('dateTime',             'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
         ('usUnits',              'INTEGER NOT NULL'),
         ('interval',             'INTEGER NOT NULL'),
@@ -2545,30 +3091,45 @@ class AddElectricity(StdService):
         ...
         ('electricity',          'REAL'),
         ('inTempBatteryStatus',  'REAL')]
-

The new line has been  highlighted .

-

2. Check permissions. The reconfiguration utility will - create a new database with the same name as the old, except with the - suffix '_new' attached to the end. Make sure you - have the necessary permissions to do this. In particular, if you are using - MySQL, you will need 'CREATE' privileges.

-

3. Run wee_config_database. - Now run the utility wee_config_database - with the --reconfigure option and the path to - the configuration file:

+

+ The new line has been  highlighted . +

+

+ 2. Check permissions. The reconfiguration + utility will create a new database with the same name as the + old, except with the suffix '_new' + attached to the end. Make sure you have the necessary + permissions to do this. In particular, if you are using MySQL, + you will need 'CREATE' privileges. +

+

+ 3. Run wee_config_database. + Now run the utility wee_config_database + with the --reconfigure option and the + path to the configuration file: +

$BIN_ROOT/wee_config_database --reconfigure $CONFIG_ROOT/weewx.conf
-

This will create a new database (nominally, - weewx.sdb_new - if you are using sqlite, weewx_new if you are - using MySQL) using the new schema and populate it with data from the old - database.

-

4. Shuffle the databases. Now arrange things so weewx can find the new database.

-

Warning!
- Make a backup of the data before doing any of the next steps!

-

You can either shuffle the databases around so the new database has - the same name as the old database, or edit weewx.conf - to use the new database name. To do the former:

+ class="symcode">$CONFIG_ROOT/weewx.conf +

+ This will create a new database (nominally, + weewx.sdb_new if you are using sqlite, weewx_new + if you are using MySQL) using the new schema and populate it + with data from the old database. +

+

+ 4. Shuffle the databases. Now arrange things so + weewx can find the new database. +

+

+ Warning!
Make a backup of the data + before doing any of the next steps! +

+

+ You can either shuffle the databases around so the new database + has the same name as the old database, or edit weewx.conf to use the new database name. + To do the former: +

For sqlite:

cd $SQLITE_ROOT
 mv weewx.sdb_new weewx.sdb
@@ -2577,37 +3138,47 @@ mv weewx.sdb_new weewx.sdb mysql> DROP DATABASE weewx;  # Drops the old database mysql> CREATE DATABASE weewx; # Create a new one with the same name mysql> RENAME TABLE weewx_new.archive TO weewx.archive;   # Rename to the nominal name -

5. Modify the stats database. At this point, you can - use the new observation type in the plots. However, if you wish to use it - in the statistical summaries, you will also have to add it to the stats - database. To do this, add the type to the Python list - stats_types, which can be found in $BIN_ROOT/user/schemas.py, - so it reads something like this:

+

+ 5. Modify the stats database. At this point, + you can use the new observation type in the plots. However, if + you wish to use it in the statistical summaries, you will also + have to add it to the stats database. To do this, add the type + to the Python list stats_types, which + can be found in $BIN_ROOT/user/schemas.py, so it reads something + like this: +

stats_types = ['barometer', 'inTemp', 'outTemp', 
     'inHumidity', 'outHumidity', 
     'rainRate', 'rain', 'dewpoint', 'windchill', 'heatindex', 'ET', 
     'radiation', 'UV', 'extraTemp1', 'rxCheckPercent', 'wind',
     'electricity']
-

Now delete the stats database (nominally stats.sdb - for sqlite, stats for MySQL). Weewx will - automatically rebuild it, including your new type.

+

+ Now delete the stats database (nominally stats.sdb + for sqlite, stats for MySQL). Weewx + will automatically rebuild it, including your new type. +

Using the new type

-

Now you've added a new type. How do you use it?

-

Pretty much like any other type. For example, to do a plot of the - month's electric consumption, totaled by day, add this section to the [[month_images]] section of - skin.conf:

+

Now you've added a new type. How do you use it?

+

+ Pretty much like any other type. For example, to do a plot of + the month's electric consumption, totaled by day, add this + section to the [[month_images]] + section of skin.conf: +

[[[monthelectric]]]
     [[[[electricity]]]]
         aggregate_type = sum
         aggregate_interval = 86400
         label = Electric consumption (daily total)
-

This will cause the generation of an image - monthelectric.png, showing a plot of each day's consumption for the - past month.

-

If you wish to use the new type in the templates, it will be available - using the same syntax as any other type. Here are some other tags that - might be useful:

+

+ This will cause the generation of an image + monthelectric.png, showing a plot of each day's consumption + for the past month. +

+

If you wish to use the new type in the templates, it will + be available using the same syntax as any other type. Here are + some other tags that might be useful:

@@ -2636,86 +3207,116 @@ mv weewx.sdb_new weewx.sdb - +
$year.electricity.sum_ge(5.0)The number of days where more than 5.0 kWH of energy was - consumed.The number of days where more than 5.0 kWH of + energy was consumed.

Changing the unit system

-

Normally, data is stored in the databases using US Customary units and, - normally, you don't care --- data can always be displayed using any units - you choose. It's an "implementation detail." Nevertheless, there may be - special situations where you wish to store the data in Metric units. For - example, you may need to allow direct programmatic access to the databases - from another piece of software that expects metric units. +

Normally, data is stored in the databases using US + Customary units and, normally, you don't care --- data can + always be displayed using any units you choose. It's an + "implementation detail." Nevertheless, there may be special + situations where you wish to store the data in Metric units. For + example, you may need to allow direct programmatic access to the + databases from another piece of software that expects metric + units.

+

+ Weewx does not allow you to change the database unit system + midstream. You can't start with one unit system then, in the + middle of the database, switch to another. See the section + [StdConvert] in the Weewx User's Guide. However, you can + reconfigure the database by coping it to a new database, + performing the unit conversion along the way. You then use this + new database. +

+

+ The steps are pretty much the same as Adding a New Type to the + ArchiveDatabase, described above.

-

Weewx does not allow you to change the database unit system midstream. - You can't start with one unit system then, in the middle of the database, - switch to another. See the section - [StdConvert] - in the Weewx User's Guide. However, you can reconfigure the database by - coping it to a new database, performing the unit conversion along the way. - You then use this new database.

-

The steps are pretty much the same as - Adding a New Type to the ArchiveDatabase, described above.

    -
  1. Modify weewx.conf to reflect your choice - of the new unit system to use.
  2. -
  3. Make sure you have the necessary permissions to create the new - database.
  4. +
  5. Modify weewx.conf to reflect + your choice of the new unit system to use. +
  6. +
  7. Make sure you have the necessary permissions to create + the new database.
  8. Populate it with data from the old database.
  9. -
  10. Shuffle databases around so weewx will use - the new database.
  11. +
  12. Shuffle databases around so weewx + will use the new database. +
  13. Rebuild the stats database to use the new unit system.
-

1. Modify weewx.conf. Edit - the configuration file to change option target_unit - in section - [StdConvert] - to reflect your choice. If you are switching to metric units, the option - will look like

+

+ 1. Modify weewx.conf. + Edit the configuration file to change option target_unit + in section [StdConvert] to reflect + your choice. If you are switching to metric units, the option + will look like +

[StdConvert]
     target_unit = METRIC
-

2. Check permissions. The reconfiguration utility will - create a new database with the same name as the old, except with the - suffix '_new' attached to the end. Make sure you - have the necessary permissions to do this. In particular, if you are using - MySQL, you will need 'CREATE' privileges.

-

3. Run wee_config_database. - Now run the utility wee_config_database with - the --reconfigure option:

+

+ 2. Check permissions. The reconfiguration + utility will create a new database with the same name as the + old, except with the suffix '_new' + attached to the end. Make sure you have the necessary + permissions to do this. In particular, if you are using MySQL, + you will need 'CREATE' privileges. +

+

+ 3. Run wee_config_database. + Now run the utility wee_config_database + with the --reconfigure option: +

$BIN_ROOT/wee_config_database --reconfigure $CONFIG_ROOT/weewx.conf
-

This will create a new database (nominally, - weewx.sdb_new - if you are using sqlite, weewx_new if you are - using MySQL), using the schema found in $BIN_ROOT/user/schemas.py, and populate it with data from - the old database, while performing the unit conversion.

-

4. Shuffle the databases. This is identical to the - description above.

-

5. Recreate the stats database. Delete the stats - database, then let weewx regenerate it. It will - use the new unit system.

+ class="symcode">$CONFIG_ROOT/weewx.conf +

+ This will create a new database (nominally, + weewx.sdb_new if you are using sqlite, weewx_new + if you are using MySQL), using the schema found in $BIN_ROOT/user/schemas.py, + and populate it with data from the old database, while + performing the unit conversion. +

+

+ 4. Shuffle the databases. This is identical to + the description above. +

+

+ 5. Recreate the stats database. Delete the + stats database, then let weewx + regenerate it. It will use the new unit system. +

Porting to new weather station hardware

-

Naturally, this is an advanced topic but, nevertheless, I'd really like - to encourage any Python wizards out there to give it a try. Of course, I - have selfish reasons for encouraging you: I don't want to have to go out - and buy every type of hardware there is! It's expensive and my roof would - look like a weather station farm.

+

Naturally, this is an advanced topic but, nevertheless, I'd + really like to encourage any Python wizards out there to give it + a try. Of course, I have selfish reasons for encouraging you: I + don't want to have to go out and buy every type of hardware + there is! It's expensive and my roof would look like a weather + station farm.

Here's the general strategy for doing a port.

Implement the driver

-

Inherit from the abstract base class - weewx.abstractstation.AbstractStation. Try to - implement as many of its methods as you can. At the very minimum, you must - implement hardware_name - and genLoopPackets.

-

hardware_name: Return a string with a short - nickname for the hardware, such as "ACME X90"

-

genLoopPackets: This should be a generator - function that yields loop packets, one after another. Don't worry about - stopping it: the engine will do this when an archive record is due. A loop - packet is a dictionary. At the very minimum it must contain keys

+

+ Inherit from the abstract base class weewx.abstractstation.AbstractStation. + Try to implement as many of its methods as you can. At the very + minimum, you must implement hardware_name + and genLoopPackets. +

+

+ hardware_name: Return a string with a + short nickname for the hardware, such as "ACME + X90" +

+

+ genLoopPackets: This should be a + generator function that yields loop packets, one after another. + Don't worry about stopping it: the engine will do this when an + archive record is due. A loop packet is a dictionary. At the + very minimum it must contain keys +

@@ -2724,133 +3325,173 @@ class="symcode">$CONFIG_ROOT/weewx.conf - +
usUnitsThe unit system used. weewx.US for US - customary, weewx.METRIC for metric. See - the file units.py, dictionaries USUnits and MetricUnits - for the exact definition of each.The unit system used. weewx.US + for US customary, weewx.METRIC + for metric. See the file units.py, + dictionaries USUnits and MetricUnits for the exact definition + of each. +
-

Then include any observation types you have in the dictionary. Every - packet need not contain the same set of observation types. Different - packets can use different unit systems, but all observations within a - packet must use the same unit system. If your hardware has an error and - you don't have a value, you can either leave it out of the dictionary or - (preferred) set its value to None.

-

A couple of observation types are tricky. In particular, rain. - Generally, weewx expects to see a packet with - the amount of rain that fell in that packet period included as observation - 'rain'. It then sums up all the values to get - the total rainfall and emits that in the archive record. If your hardware - does not provide this value, you might have to infer it from changes in - whatever value it provides, for example changes in the daily or monthly - rainfall. I know this is not the best solution, but it is the most general - solution. Any alternatives are welcome!

-

Wind is another tricky one. It is actually broken up into four - different observations: 'windSpeed', 'windDir', - 'windGust', and 'windGustDir'. - Supply as many as you can. The directions should be compass directions in - degrees (0=North, 90=East, etc.).

-

Be careful when reporting pressure. There are three observations - related to pressure. Some stations report only the station pressure, - others calculate and report sea level pressures.

+

+ Then include any observation types you have in the dictionary. + Every packet need not contain the same set of observation types. + Different packets can use different unit systems, but all + observations within a packet must use the same unit system. If + your hardware has an error and you don't have a value, you can + either leave it out of the dictionary or (preferred) set its + value to None. +

+

+ A couple of observation types are tricky. In particular, rain. + Generally, weewx expects to see a + packet with the amount of rain that fell in that packet period + included as observation 'rain'. It + then sums up all the values to get the total rainfall and emits + that in the archive record. If your hardware does not provide + this value, you might have to infer it from changes in whatever + value it provides, for example changes in the daily or monthly + rainfall. I know this is not the best solution, but it is the + most general solution. Any alternatives are welcome! +

+

+ Wind is another tricky one. It is actually broken up into four + different observations: 'windSpeed', 'windDir', 'windGust', + and 'windGustDir'. Supply as many as + you can. The directions should be compass directions in degrees + (0=North, 90=East, etc.). +

+

Be careful when reporting pressure. There are three + observations related to pressure. Some stations report only the + station pressure, others calculate and report sea level + pressures.

- + - + - +
pressureThe Station Pressure (SP), which is the raw, absolute - pressure measured by the station. This is the true barometric - pressure for the station.The Station Pressure (SP), which is the + raw, absolute pressure measured by the station. This is + the true barometric pressure for the station. +
barometerThe Sea Level Pressure (SLP) obtained by correcting the - Station Pressure for altitude and local temperature. This is - the pressure reading most commonly used by meteorologist to track - weather systems at the surface, and this is the pressure that is - uploaded to weather services by weewx. It - is the station pressure reduced to mean sea level using local - altitude and local temperature. The Sea Level Pressure (SLP) obtained by + correcting the Station Pressure for altitude and + local temperature. This is the pressure reading most + commonly used by meteorologist to track weather systems at + the surface, and this is the pressure that is uploaded to + weather services by weewx. It is + the station pressure reduced to mean sea level using local + altitude and local temperature. +
altimeterThe Altimeter Setting (AS) obtained by correcting the - Station Pressure for altitude. This is the pressure - reading most commonly heard in weather reports. It is not the true - barometric pressure of a station, but rather the station pressure - reduced to mean sea level using altitude and an assumed temperature - average.The Altimeter Setting (AS) obtained by + correcting the Station Pressure for altitude. + This is the pressure reading most commonly heard in + weather reports. It is not the true barometric pressure of + a station, but rather the station pressure reduced to mean + sea level using altitude and an assumed temperature + average. +

-

genArchiveRecords: If your hardware does not - have an archive record logger, then weewx can do - the record generation for you. It will automatically collect all the types - it sees in your loop packets then emit a record with the averages (in some - cases the sum or max value) of all those types. If it doesn't see a type, - then it won't appear in the emitted record. If your hardware does have a - logger, then you should implement method - genArchiveRecords - as well. It should be a generator function that returns all the records - since a given time.

-

closePort: If the driver needs to close a - serial port, terminate a thread, close a database, or perform any other - activity before the application terminates, do it in this method.

-

loader: This is a factory function that - returns an instance of your driver. It has two arguments: the - configuration dictionary, and a reference to the weewx engine.

+

+ genArchiveRecords: If your hardware + does not have an archive record logger, then weewx + can do the record generation for you. It will automatically + collect all the types it sees in your loop packets then emit a + record with the averages (in some cases the sum or max value) of + all those types. If it doesn't see a type, then it won't appear + in the emitted record. If your hardware does have a logger, then + you should implement method genArchiveRecords + as well. It should be a generator function that returns all the + records since a given time. +

+

+ closePort: If the driver needs to + close a serial port, terminate a thread, close a database, or + perform any other activity before the application terminates, do + it in this method. +

+

+ loader: This is a factory function + that returns an instance of your driver. It has two arguments: + the configuration dictionary, and a reference to the weewx + engine. +

Define the configuration

-

You then include a new section in the configuration file - weewx.conf - that includes any options your driver needs. It should also include an - entry 'driver' that points to where your driver - can be found. Set option station_type - to your new section type and your driver will be loaded.

+

+ You then include a new section in the configuration file weewx.conf that includes any options your + driver needs. It should also include an entry 'driver' that points to where your driver + can be found. Set option station_type + to your new section type and your driver will be loaded. +

Examples

-

Take a look at the simulator code in simulator.py - for a dirt simple example of a driver. The next most complicated is the - driver for the WMR100 series, located in wmr100.py. - The driver for the Vantage series is by far the most complicated. It - actually multi-inherits from not only AbstractStation, - but also StdService. That is, it also - participates in the engine as a service.

-

Naturally, there are a lot of subtleties that I've glossed over in this - high-level description. If you're game, give it a try — I'm happy to - help you out!

+

+ Take a look at the simulator code in simulator.py + for a dirt simple example of a driver. The next most complicated + is the driver for the WMR100 series, located in wmr100.py. The driver for the Vantage + series is by far the most complicated. It actually + multi-inherits from not only AbstractStation, + but also StdService. That is, it also + participates in the engine as a service. +

+

Naturally, there are a lot of subtleties that I've glossed + over in this high-level description. If you're game, give it a + try — I'm happy to help you out!

Appendix A: Archive Types

-

Archive types are weather observations that have come from - your instrument and been stored in the archive database, a SQL - database. They represent the current conditions as of some time. - They are available to be used in two places:

+

+ Archive types are weather observations that have come + from your instrument and been stored in the archive + database, a SQL database. They represent the current + conditions as of some time. They are available to be used in + two places: +

    -
  • In your template files as a tag with period - $current. Hence, the tag $current.outTemp - represents the latest current outside temperature. There is no - aggregation involved (see statistical types - for aggregation).
  • -
  • 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.
  • +
  • In your template files as a tag with period $current. Hence, the tag $current.outTemp represents the latest + current outside temperature. There is no aggregation involved + (see statistical types for + aggregation). +
  • +
  • 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.
-

The following table shows all the possible archive types and whether - they can be used in tag $current or in a plot. - Note that just because a type appears in the table does not necessarily - mean that it is available for your station setup. That would - depend on whether your instrument supports the type.

+

+ The following table shows all the possible archive types and + whether they can be used in tag $current + or in a plot. Note that just because a type appears in the table + does not necessarily mean that it is available for your + station setup. That would depend on whether your instrument + supports the type. +

- - + (appears in archive + database) + + @@ -2873,8 +3514,7 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + @@ -3162,8 +3802,8 @@ class="symcode">$CONFIG_ROOT/weewx.conf
Archive Type SQL Type
- (appears in archive database)
Can be used
- in plots
Can be used
- in tag $current
Can be used
in plots +
Can be used
in tag $current
altimeter
dateTime X
-

X (represents current time)

Appendix B: Units

-

The table below lists all the unit groups, their members, and which - units are options for the group.

+

The table below lists all the unit groups, their members, + and which units are options for the group.

@@ -3174,22 +3814,21 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + - - + + - + @@ -3199,99 +3838,78 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - + @@ -3300,10 +3918,9 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + @@ -3314,19 +3931,24 @@ class="symcode">$CONFIG_ROOT/weewx.conf
group_altitude altitudefoot
- meter
foot
meter +
group_degree_daycooldeg
- heatdeg
degree_F_day
- degree_C_day
cooldeg
heatdeg +
degree_F_day
degree_C_day +
group_directiongustdir
- vecdir
- windDir
- windGustDir
gustdir
vecdir
windDir
+ windGustDir +
degree_compass
group_moisturesoilMoist1
- soilMoist2
- soilMoist3
- soilMoist4
soilMoist1
soilMoist2
soilMoist3
+ soilMoist4 +
centibar
group_percentextraHumid1
- extraHumid2
- inHumidity
- outHumidity
- rxCheckPercent
extraHumid1
extraHumid2
inHumidity +
outHumidity
rxCheckPercent +
percent
group_pressurebarometer
- altimeter
- pressure
inHg
- mbar
- hPa
barometer
altimeter
pressure +
inHg
mbar
hPa +
group_radiationUV
- radiation
UV
radiation +
watt_per_meter_squared
group_rainrain
- ET
- hail
in
- cm
- mm
rain
ET
hail +
in
cm
mm +
group_rainraterainRate
- hailRate
in_per_hour
- cm_per_hour
- mm_per_hour
rainRate
hailRate +
in_per_hour
cm_per_hour
mm_per_hour +
group_speedwind
- windGust
- windSpeed
- windgustvec
- windvec
mile_per_hour
- km_per_hour
- knot
- meter_per_second
wind
windGust
windSpeed
+ windgustvec
windvec +
mile_per_hour
km_per_hour
knot
+ meter_per_second +
group_speed2rms
- vecavg
mile_per_hour2
- km_per_hour2
- knot2
- meter_per_second2
rms
vecavg +
mile_per_hour2
km_per_hour2
knot2
+ meter_per_second2 +
group_temperaturedewpoint
- extraTemp1
- extraTemp2
- extraTemp3
- heatindex
- heatingTemp
- inTemp
- leafTemp1
- leafTemp2
- outTemp
- soilTemp1
- soilTemp2
- soilTemp3
- soilTemp4
- windchill
degree_F
- degree_C
dewpoint
extraTemp1
extraTemp2
+ extraTemp3
heatindex
heatingTemp
+ inTemp
leafTemp1
leafTemp2
outTemp +
soilTemp1
soilTemp2
soilTemp3
+ soilTemp4
windchill +
degree_F
degree_C +
group_time dateTimeunix_epoch
- dublin_jd
unix_epoch
dublin_jd +
group_uv
group_voltconsBatteryVoltage
- heatingVoltage
- referenceVoltage
- supplyVoltage
consBatteryVoltage
heatingVoltage
+ referenceVoltage
supplyVoltage +
volt

Appendix C: Statistical Types

-

Most of the templates are devoted to reporting statistical types, - such as temperature, wind, or rainfall, using various aggregates, - such as min, max, or sum. These are called aggregations, 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.

-

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 - [Stats] - in the weewx.conf configuration file).

+

+ Most of the templates are devoted to reporting statistical + types, such as temperature, wind, or rainfall, using various aggregates, + such as min, max, or sum. These are called aggregations, + 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. +

+

+ 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 [Stats] in the weewx.conf configuration file). +

@@ -3522,9 +4144,9 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + @@ -3536,9 +4158,9 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + @@ -3550,8 +4172,8 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + @@ -3563,8 +4185,8 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + @@ -3576,10 +4198,9 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + @@ -3591,8 +4212,8 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + @@ -3618,22 +4239,31 @@ class="symcode">$CONFIG_ROOT/weewx.conf
 
extraTemp1
- extraTemp2
- extraTemp3
extraTemp1
extraTemp2
+ extraTemp3 +
X X X  
soilTemp1
- soilTemp2
- soilTemp3
soilTemp1
soilTemp2
+ soilTemp3 +
X X X  
leafTemp1
- leafTemp2
leafTemp1
leafTemp2 +
X X X  
extraHumid1
- extraHumid2
extraHumid1
extraHumid2 +
X X X  
soilMoist1
- soilMoist2
- soilMoist3
- soilMoist4
soilMoist1
soilMoist2
+ soilMoist3
soilMoist4 +
X X X  
leafWet1
- leafWet2
leafWet1
leafWet2 +
X X X

Appendix D: Packet Types

-

Packets are the raw data coming off the instrument (as opposed - to records, which are stored on the database). The observation - types available in a packet are useful when setting - quality control rules and when doing - calibrations. +

+ Packets are the raw data coming off the instrument (as + opposed to records, which are stored on the database). + The observation types available in a packet are useful when + setting quality + control rules and when doing calibrations.

-

They may also be useful if you are writing your own custom service. In - particular, for subclasses of StdService, member - function newLoopPacket is called when new LOOP - packets arrive, and member function newArchivePacket - is called when new archive packets arrive. For both functions, the only - argument (besides self) is a dictionary, where - the key is the type listed below, and the value is the observation value.

-

See the guide from +

+ They may also be useful if you are writing your own custom + service. In particular, for subclasses of StdService, + member function newLoopPacket is + called when new LOOP packets arrive, and member function newArchivePacket is called when new + archive packets arrive. For both functions, the only argument + (besides self) is a dictionary, where + the key is the type listed below, and the value is the + observation value. +

+

+ See the guide from Vantage Pro and Pro2 Serial Communications Reference - (available on the Davis website) for more information about these types. + (available on the Davis website) for more information about + these types.

@@ -3648,16 +4278,13 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - + + - + @@ -3665,26 +4292,20 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - + + - - - + + + - + @@ -3697,93 +4318,66 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -3802,40 +4396,35 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + - + - + - + - + @@ -3863,53 +4452,44 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + - + - + - + - - - + + + - - + + @@ -3920,52 +4500,42 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + - + - - + + - + - - + + - + - + - + @@ -3973,12 +4543,9 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - - + + + @@ -3997,16 +4564,14 @@ class="symcode">$CONFIG_ROOT/weewx.conf - + - + @@ -4014,44 +4579,33 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - + + - - + + - - - + + + - - - + + + - + @@ -4059,18 +4613,14 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - - + + + - + @@ -4091,36 +4641,27 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - - + + + - - - + + + - - + + - + @@ -4128,25 +4669,20 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - - + + + - + - + @@ -4154,42 +4690,30 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - - + + + - - - + + + - - - + + + - - - + + + @@ -4250,148 +4774,114 @@ class="symcode">$CONFIG_ROOT/weewx.conf - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - + - - + + - + - + - + - - + + - - - + + + - + - - - + + + - - + +
barometer X X
-

-


consBatteryVoltage X
-

volt volt
dateTime X X
-

-


dayET X
-

-

-



dayRain X
-

in cm
ET (hourly)
-

X
-

-


extraAlarm1 X
-

-

-



extraAlarm2 X
-

-

-



extraAlarm3 X
-

-

-



extraAlarm4 X
-

-

-



extraAlarm5 X
-

-

-



extraAlarm6 X
-

-

-



extraAlarm7 X
-

-

-



extraAlarm8 X
-

-

-



extraHumid1
extraHumid3 X
-

% %
extraHumid4 X
-

% %
extraHumid5 X
-

% %
extraHumid6 X
-

% %
extraHumid7 X
-

% %
extraTemp4 X
-

F C
extraTemp5 X
-

F C
extraTemp6 X
-

F C
extraTemp7 X
-

F C
forecastIcon X
-

-

-



forecastRule X X
-

-


heatIndex
highOutTemp
-

X F C
highRadiation
-

X
-

-


highUV
-

X
-

-


inHumidity X
-

% %
inTemp X
-

F C
interval
-

X minute minute
insideAlarm X
-

-

-



leafTemp1
leafTemp3 X
-

F C
leafTemp4 X
-

F C
leafWet1 X X
-

-


leafWet2 X X
-

-


leafWet3 X
-

-

-



leafWet4 X
-

-

-



lowOutTemp
-

X F C
monthET X
-

-

-



monthRain X
-

in cm
outsideAlarm1 X
-

-

-



outsideAlarm2 X
-

-

-



radiation X X
-

-


rain
-

X in cm
rainAlarm X
-

-

-



rainRate X
-

in/hr cm/hr
rxCheckPercent
-

X % %
soilLeafAlarm1 X
-

-

-



soilLeafAlarm2 X
-

-

-



soilLeafAlarm3 X
-

-

-



soilLeafAlarm4 X
-

-

-



soilMoist1
stormRain X
-

-

-



stormStart X
-

-

-



sunrise X
-

-

-



sunset X
-

-

-



txBatteryStatus X
-

-

-



usUnits X X
-

-


UV X X
-

-


windChill X X
-

C
windDir X X
-

-


windGust
-

X
-

km/h
windGustDir
-

X
-

-


windSpeed10 X
-

-

-



windSpeed X X
-

km/h
yearET X
-

-

-



yearRain X
-

-


cm
- + - +