diff --git a/docs/customizing.htm b/docs/customizing.htm index 223bf408..912c8ad6 100644 --- a/docs/customizing.htm +++ b/docs/customizing.htm @@ -9,136 +9,11 @@ Customizing weewx - + + + + + @@ -146,295 +21,291 @@ td {

Customizing weewx
Version 1.10

Table of contents

-
    -
  1. Introduction
  2. -
  3. Opportunities for customizing - reports
  4. -
  5. Reference: The - Standard skin configuration file
  6. -
  7. Customizing the - weewx service engine
  8. -
  9. Appendix A: Types
  10. -
  11. Appendix B: Units
  12. -
  13. Appendix C: Statistical aggregations
  14. -
-

1. 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.

-

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 any "services" -that are to be run and arranging for them to be called when key events occur, such -as the arrival of LOOP data. The default install of weewx -includes the following services:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ServiceFunction
weewx.wxengine.StdCalibrateAdjust new LOOP and archive packets using calibration expressions.
weewx.wxengine.StdQCCheck quality of incoming data, making sure values fall within a specified - range.
weewx.wxengine.StdArchiveArchive any new data to the SQL databases.
weewx.wxengine.StdTimeSynchArrange to have the clock on the station synchronized at regular intervals.
weewx.wxengine.StdPrintPrint 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.
weewx.wxengine.StdReportServiceLaunch a new thread to do report processing after a new archive record - arrives. Reports do things such as generate HTML files, generate images, - or FTP files to a web server. New reports can be added easily by the user.
-

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, StdReportService

-

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

-

Reports

-

The Standard Report Service runs zero or more Reports. Which reports -are to be run is set in the weewx configuration file weewx.conf, in section -[Reports].

-

The default distribution of weewx includes two reports:

- - - - - - - - - - - - - -
ReportDefault functionality
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.
FTPArranges to upload everything in the public_html - subdirectory up to a remote webserver.
-

Note that the FTP "report" is a funny kind of report in that it doesn't actually -generate anything. Instead, it uses the reporting service engine to arrange for -things to be FTP'd to a remote server.

-

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 "Report" also uses a skin, and includes a skin configuration -file, although it is quite minimal.

-

Skins live in their own subdirectory located in $HTML_ROOT/skins.

-

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 them to remote locations. The default install of -weewx includes the following generators:

- - - - - - - - - - - - - - - - - - - - - -
GeneratorFunction
weewx.filegenerator.FileGeneratorGenerates files from templates. Used to generate HTML and text files.
weewx.imagegenerator.ImageGeneratorGenerates graph plots.
weewx.reportengine.FtpGeneratorUploads data to a remote server using FTP.
weewx.reportengine.CopyGeneratorCopies files locally.
-

Note that the two generators FtpGenerator and -CopyGenerator don't actually generate anything 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.

-

Databases

-

There are two databases used in weewx, both using -SQLITE3, a light-weight SQL database:

- -

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).

-

2. Opportunities for 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.

-

Changing options

-

Changing an option means modifying either the main configuration file -weewx.conf, -or the skin configuration file for the standard skin that comes with the -distribution (nominally, file skins/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 -$WEEWX_ROOT/skins/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]] -and looks like this:

-
[Units]
-
  [[Groups]]
-
    group_altitude    = foot
-
    group_degree_day  = degree_F_day 
-
    group_direction   = degree_compass
-
    group_moisture    = centibar
-
    group_percent     = percent
-
    group_pressure    = inHg
-
    group_radiation   = watt_per_meter_squared
-
    group_rain        = inch
-
    group_rainrate    = inch_per_hour
-
    group_speed       = mile_per_second
-
    group_speed2      = mile_per_second2
-
    group_temperature = degree_F
-
   group_uv          = uv_index 
-
    group_volt        = volt
-

 

-

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

-
[Units]
-
  [[Groups]]
-
    group_altitude    = meter
-
    group_degree_day  = degree_C_day 
-
    group_direction   = degree_compass
-
    group_moisture    = centibar
-
    group_percent     = percent
-
    group_pressure    = mbar
-
    group_radiation   = watt_per_meter_squared
-
    group_rain        = mm
-
    group_rainrate    = mm_per_hour
-
    group_speed       = meter_per_second
-
    group_speed2      = meter_per_second2
-
    group_temperature = degree_C
-
    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

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

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 public_html, -the latter in a subdirectory, public_html/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 subdirectory 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 overriding some options. -Here's what your [Report] section in -weewx.conf would look like:

-
[Reports]
-
#
+
+
+
+

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.

+

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 any + "services" that are to be run and arranging for them to be called when + key events occur, such as the arrival of LOOP data. The default install of + weewx includes the following services:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ServiceFunction
weewx.wxengine.StdCalibrateAdjust new LOOP and archive packets using calibration expressions.
weewx.wxengine.StdQCCheck quality of incoming data, making sure values fall within a + specified range.
weewx.wxengine.StdArchiveArchive any new data to the SQL databases.
weewx.wxengine.StdTimeSynchArrange to have the clock on the station synchronized at regular + intervals.
weewx.wxengine.StdPrintPrint 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.
weewx.wxengine.StdReportServiceLaunch a new thread to do report processing after a new archive + record arrives. Reports do things such as generate HTML files, generate + images, or FTP files to a web server. New reports can be added easily + by the user.
+

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, StdReportService

+

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

+

Reports

+

The Standard Report Service runs zero or more Reports. Which reports + are to be run is set in the weewx configuration file weewx.conf, + in section [Reports].

+

The default distribution of weewx includes two reports:

+ + + + + + + + + + + + + +
ReportDefault functionality
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.
FTPArranges to upload everything in the public_html + subdirectory up to a remote webserver.
+

Note that the FTP "report" is a funny kind of report in that it doesn't actually + generate anything. Instead, it uses the reporting service engine to arrange + for things to be FTP'd to a remote server.

+

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 "Report" also uses a skin, and includes a skin + configuration file, although it is quite minimal.

+

Skins live in their own subdirectory located in $HTML_ROOT/skins.

+

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 them to remote locations. The default install + of weewx includes the following generators:

+ + + + + + + + + + + + + + + + + + + + + +
GeneratorFunction
weewx.filegenerator.FileGeneratorGenerates files from templates. Used to generate HTML and text files.
weewx.imagegenerator.ImageGeneratorGenerates graph plots.
weewx.reportengine.FtpGeneratorUploads data to a remote server using FTP.
weewx.reportengine.CopyGeneratorCopies files locally.
+

Note that the two generators FtpGenerator and + CopyGenerator don't actually generate anything 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.

+

Databases

+

There are two databases used in weewx, both using + SQLITE3, a light-weight SQL database:

+ +

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). +

+

Opportunities for 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.

+

Changing options

+

Changing an option means modifying either the main configuration file + weewx.conf, or the skin configuration file for the + standard skin that comes with the distribution (nominally, file + skins/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 + $WEEWX_ROOT/skins/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]] and looks like this:

+
[Units]
+
  [[Groups]]
+
    group_altitude    = foot
+
    group_degree_day  = degree_F_day 
+
    group_direction   = degree_compass
+
    group_moisture    = centibar
+
    group_percent     = percent
+
    group_pressure    = inHg
+
    group_radiation   = watt_per_meter_squared
+
    group_rain        = inch
+
    group_rainrate    = inch_per_hour
+
    group_speed       = mile_per_second
+
    group_speed2      = mile_per_second2
+
    group_temperature = degree_F
+
   group_uv          = uv_index 
+
    group_volt        = volt
+

 

+

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

+
[Units]
+
  [[Groups]]
+
    group_altitude    = meter
+
    group_degree_day  = degree_C_day 
+
    group_direction   = degree_compass
+
    group_moisture    = centibar
+
    group_percent     = percent
+
    group_pressure    = mbar
+
    group_radiation   = watt_per_meter_squared
+
    group_rain        = mm
+
    group_rainrate    = mm_per_hour
+
    group_speed       = meter_per_second
+
    group_speed2      = meter_per_second2
+
    group_temperature = degree_C
+
    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

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

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 + public_html, the latter in a subdirectory, public_html/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 subdirectory 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 overriding some + options. Here's what your [Report] section in + weewx.conf would look like:

+
[Reports]
+
#
 # This section specifies what reports, using which skins, are to be generated.
 #
-
 
-
# Where the skins reside, relative to WEEWX_ROOT:
+	
 
+
# Where the skins reside, relative to WEEWX_ROOT:
 SKIN_ROOT = skins
 
-
# Where the generated reports should go, relative to WEEWX_ROOT:
+	
# Where the generated reports should go, relative to WEEWX_ROOT:
 HTML_ROOT = public_html 
-
 
-
  # This report will use US Customary Units
-
  [[USReport]]
-
    # It's based on the Standard skin
+	
 
+
  # This report will use US Customary Units
+
  [[USReport]]
+
    # It's based on the Standard skin
     skin = Standard
-
 
-
  # This report will use metric units:
+	
 
+
  # This report will use metric units:
   [[MetricReport]]
     # It's also based on the Standard skin:
     skin = Standard 
@@ -451,33 +322,34 @@ HTML_ROOT = public_html 
group_speed = meter_per_second group_speed2 = meter_per_second2 group_temperature = degree_C
-
 
-
    [[FTP]]
-
      ...
-
      ... (as before) 
-

We have done two things different from the stock reports. First (1), we've renamed -the first report from StandardReport to -USReport for clarity; and (2) we've 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 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 key construct is a 'dot' code, specifying what value you want. For example:

-
$month.outTemp.max
+	
 
+
    [[FTP]]
+
      ...
+
      ... (as before) 
+

We have done two things different from the stock reports. First (1), we've + renamed the first report from StandardReport to + USReport for clarity; and (2) we've 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 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 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

-
<html>
+	

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>
   </head>
@@ -486,408 +358,412 @@ the current outside temperature, respectively. So, an HTML file that looks like<
   <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 -[Labels][[Time]].

-

The dot code

-

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

-
## Output max outside temperature using an appropriate format and label:
+	

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 [Labels][[Time]].

+

The dot code

+

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 very similar

-

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:

-
$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.

-

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

-

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:

-
$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.

-

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

-

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,

-

$day.barometer.avg.mbar

-

then the results will be in millibars:

-

Today's average pressure=1017.5 mbar

-

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:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

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.

-
.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][[Formats]] - 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.
.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][[Formats]] - 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][[Formats]] - 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 ('')
-

Summary:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Formatting tagFormat usedLabel UsedNONE stringReturned value
(no tag)From skin.confFrom skin.confFrom skin.confstring
.stringFrom skin.confFrom skin.confOptional user-suppliedstring
.formattedFrom skin.confNo labelFrom skin.confstring
.formatUser-suppliedFrom skin.confOptional user-suppliedstring
.nolabelUser-suppliedNo labelOptional user-suppliedstring
.rawNoneNo labelNonenative value
-

Here are some examples with the expected results:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TagResultComment
$current.outTemp 45.2°F String formatting and label from skin.conf
$current.outTemp.string45.2°FString formatting and label from skin.conf
$current.UV.stringN/AThis example assumes that the instrument has no UV sensor, resulting - in a None value. The string specified by - NONE in - [Units][[Formats]] 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.
$current.outTemp.formatted 45.2String formatting from skin.conf; no label
$current.outTemp.format("%.3f") 45.200°FSpecified string format used; label from skin.conf.
$current.dateTime02-Apr-2010 16:25Time formatting and label from skin.conf
$current.dateTime.format("%H:%M")16:25Specified time format used; label from skin.conf.
$current.dateTime.raw1270250700Unix epoch time, converted to string by template engine.
$current.outTemp.raw45.2Float returned, converted to string by template engine.
$month.dateTime01-Apr-2010 00:00Time formatting and label from skin.conf
$month.outTemp.avg 40.8°FString formatting and label from skin.conf
$month.outTemp.avg.string40.8°FTime formatting and label from skin.conf
$month.UV.avg.stringN/AThis example assumes that the instrument has no UV sensor, resulting - in a None value. The string specified by - NONE in - [Units][[Formats]] 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.
$month.outTemp.avg.formatted 40.8String formatting from skin.conf; no label
$month.outTemp.avg.format("%.3f")40.759°FSpecified string format used; no label
$month.outTemp.avg.raw 40.7589690722Float returned, converted to string by template engine
$month.UV.avg.raw(empty)None value converted to empty string by template - engine.
-

Note:

-
    -
  • Tags that take an argument (such as .string(NONE_string)) - do not require parenthesis if the argument is omitted.Thus, you can specify - either $month.outTemp.string() or - $month.outTemp.string, if you want the default value - of NONE_string. They produce the same results.
  • -
-

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

-
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.

-

 

-

Unit tags

-

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

- - - - - - - - - - - - - - - - - -
TagResults
$unit.unit_type.outTempdegree_C
$unit.label.outTemp°C
$unit.format.outTemp%.1f
-

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.

-

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):

-
<html>
-
  <head>
-
    <title>Year stats by month</title>
-
  </head>
-
  <body>
-
  <p>Min, max temperatures by month:</p>
-
  #for $month in $year.months
-
    <p>$month.dateTime.format("%B"): Min, max temperatures: $month.outTemp.min $month.outTemp.max</p>
-
  #end for 
-
  </body>
-
</html>
-

Produces results:

-
Min, max temperatures by month:
+	

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 very + similar

+

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:

+
$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.

+

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

+

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:

+
$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.

+

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

+

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,

+

$day.barometer.avg.mbar

+

then the results will be in millibars:

+

Today's average pressure=1017.5 mbar

+

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:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

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.

+
.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][[Formats]] 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.
.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][[Formats]] + 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][[Formats]] + 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 + ('')
+

Summary:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Formatting tagFormat usedLabel UsedNONE stringReturned value
(no tag)From skin.confFrom skin.confFrom skin.confstring
.stringFrom skin.confFrom skin.confOptional user-suppliedstring
.formattedFrom skin.confNo labelFrom skin.confstring
.formatUser-suppliedFrom skin.confOptional user-suppliedstring
.nolabelUser-suppliedNo labelOptional user-suppliedstring
.rawNoneNo labelNonenative value
+

Here are some examples with the expected results:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TagResultComment
$current.outTemp 45.2°F String formatting and label from skin.conf
$current.outTemp.string45.2°FString formatting and label from skin.conf
$current.UV.stringN/AThis example assumes that the instrument has no UV sensor, resulting + in a None value. The string specified by + NONE in + [Units][[Formats]] 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.
$current.outTemp.formatted 45.2String formatting from skin.conf; no label
$current.outTemp.format("%.3f") 45.200°FSpecified string format used; label from skin.conf.
$current.dateTime02-Apr-2010 16:25Time formatting and label from skin.conf
$current.dateTime.format("%H:%M")16:25Specified time format used; label from skin.conf.
$current.dateTime.raw1270250700Unix epoch time, converted to string by template engine.
$current.outTemp.raw45.2Float returned, converted to string by template engine.
$month.dateTime01-Apr-2010 00:00Time formatting and label from skin.conf
$month.outTemp.avg 40.8°FString formatting and label from skin.conf
$month.outTemp.avg.string40.8°FTime formatting and label from skin.conf
$month.UV.avg.stringN/AThis example assumes that the instrument has no UV sensor, resulting + in a None value. The string specified by + NONE in + [Units][[Formats]] 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.
$month.outTemp.avg.formatted 40.8String formatting from skin.conf; no label
$month.outTemp.avg.format("%.3f")40.759°FSpecified string format used; no label
$month.outTemp.avg.raw 40.7589690722Float returned, converted to string by template engine
$month.UV.avg.raw(empty)None value converted to empty string by + template engine.
+

Note:

+
    +
  • Tags that take an argument (such as .string(NONE_string)) + do not require parenthesis if the argument is omitted.Thus, you can specify + either $month.outTemp.string() or + $month.outTemp.string, if you want the default + value of NONE_string. They produce the same results.
  • +
+

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

+
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.

+

 

+

Unit tags

+

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

+ + + + + + + + + + + + + + + + + +
TagResults
$unit.unit_type.outTempdegree_C
$unit.label.outTemp°C
$unit.format.outTemp%.1f
+

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.

+

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):

+
<html>
+
  <head>
+
    <title>Year stats by month</title>
+
  </head>
+
  <body>
+
  <p>Min, max temperatures by month:</p>
+
  #for $month in $year.months
+
    <p>$month.dateTime.format("%B"): Min, max temperatures: $month.outTemp.min $month.outTemp.max</p>
+
  #end for 
+
  </body>
+
</html>
+

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
@@ -901,39 +777,39 @@ 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.

-

Writing a custom generator

-

To do more sophisticated customization it may be necessary to extend an existing -generator, or write your own.

-

Extending an existing generator

-

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? Simply putting it in the [Extras] section -won't do, because then it cannot change.

-

The answer is to extend the default file generator weewx.filegenerator.FileGenerator -by subclassing, then override the function that returns the search list. -The search list is a list of dictionaries that the template engine searches through, -trying all keys in each dictionary, looking for a match for your tag. For example, -for the "ToDate" generator, you would override function getToDateSearchList(), -and add a small dictionary with your tag as the key to the list returned by the -superclass.

-

Let's look at an example. The stock weewx reports offers -statistical summaries by day, week, month, and year. Suppose we would like to add -one more: all-time statistics. This would allow us to display statistics such as -the all-time high or low temperature seen at your station.

-

This example is included in the distribution as examples/mygenerator.py:

-
from weewx.filegenerator import FileGenerator
+	

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.

+

Writing a custom generator

+

To do more sophisticated customization it may be necessary to extend an existing + generator, or write your own.

+

Extending an existing generator

+

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? Simply putting it in the [Extras] + section won't do, because then it cannot change.

+

The answer is to extend the default file generator weewx.filegenerator.FileGenerator + by subclassing, then override the function that returns the search list. + The search list is a list of dictionaries that the template engine searches + through, trying all keys in each dictionary, looking for a match for your tag. + For example, for the "ToDate" generator, you would override function + getToDateSearchList(), and add a small dictionary + with your tag as the key to the list returned by the superclass.

+

Let's look at an example. The stock weewx reports + offers statistical summaries by day, week, month, and year. Suppose we would + like to add one more: all-time statistics. This would allow us to display statistics + such as the all-time high or low temperature seen at your station.

+

This example is included in the distribution as examples/mygenerator.py:

+
from weewx.filegenerator import FileGenerator
 from weewx.stats import TimeSpanStats
 from weeutil.weeutil import TimeSpan
 
@@ -958,36 +834,38 @@ class MyFileGenerator(FileGenerator):                    # 1
         return search_list
 
 
-

Going through the example, line by line:

-
    -
  1. Subclass from class FileGenerator. The new class - will be caled MyFileGenerator
  2. -
  3. Override member function getToDateSearchList(). - The parameters are self (Python's way of indicating - the instance we are working with), currentRec (a dictionary - with the current conditions), and stop_ts (the ending - time for the "to date" summary, in Unix epoch time).
  4. -
  5. Attribute self.start_ts is available as the earliest - time seen in the main archive database. The class TimeSpan - is a utility class that represents an interval of time. Here, we are creating - an instance of TimeSpan that represents all time preceeding - stop_ts.
  6. -
  7. Class TimeSpanStats represents a statistical calculation - over a time period. It takes 3 parameters. The first, self.statsdb - is the statistical database the calculation is to be run against; the second - is the timespan over which the calculation is to be done; and the third, - self.unit_info, is an instance of class - weewx.units.UnitInfo, which contains information about - the target units the results are to be returned in as well as formatting and - labeling information.
  8. -
  9. Get the search list from the superclass.
  10. -
  11. Tack on our addition and return the results. The search list will now consist - of a list of dictionaries, including a small one we added on the end that has - a single key, 'alltime', with value an instance of - TimeSpanStats.
  12. -
-

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

-
...
+	

Going through the example, line by line:

+
    +
  1. Subclass from class FileGenerator. The new + class will be caled MyFileGenerator
  2. +
  3. Override member function getToDateSearchList(). + The parameters are self (Python's way of indicating + the instance we are working with), currentRec + (a dictionary with the current conditions), and stop_ts + (the ending time for the "to date" summary, in Unix epoch time).
  4. +
  5. Attribute self.start_ts is available as the + earliest time seen in the main archive database. The class + TimeSpan is a utility class that represents an + interval of time. Here, we are creating an instance of + TimeSpan that represents all time preceeding + stop_ts.
  6. +
  7. Class TimeSpanStats represents a statistical + calculation over a time period. It takes 3 parameters. The first, + self.statsdb is the statistical database the calculation + is to be run against; the second is the timespan over which the calculation + is to be done; and the third, self.unit_info, + is an instance of class weewx.units.UnitInfo, + which contains information about the target units the results are to be + returned in as well as formatting and labeling information.
  8. +
  9. Get the search list from the superclass.
  10. +
  11. Tack on our addition and return the results. The search list will now + consist of a list of dictionaries, including a small one we added on the + end that has a single key, 'alltime', with value + an instance of TimeSpanStats.
  12. +
+

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

+
...
 ...
 <table>
   <tr>
@@ -999,422 +877,434 @@ class MyFileGenerator(FileGenerator):                    # 1
     <td>$alltime.outTemp.min
   </tr>
   ... (more table entries)
-
 
-

One additonal step is required: to tell the report service to run your generator -instead of the default generator. Modify option [Generators]generator_list -in the skin configuration file skin.conf to read:

-
generator_list = examples.mygenerator.MyFileGenerator, weewx.imagegenerator.ImageGenerator, weewx.reportengine.CopyGenerator
-

NB: If you create a custom generator some place other than where -weewxd.py resides, you may have to specify its location -in the environment variable PYTHON_PATH:

-
export PYTHON_PATH=/home/me/secret_location
-

Upgrades and user extensions

-

In the examples above, we subclassed weewx classes -to add functionality. Where should you put your new code? If you simply modify -the examples in place, then your changes will get overwritten the next time you -do an upgrade, forcing you to cut and paste any changes you have made.

-

A better idea is to copy over the examples to the subdirectory $WEEWX_ROOT/bin/user, then modify them there. -This subdirectory is preserved through upgrades, so you won't have to redo any -changes you might have made.

-

3. Reference: The -Standard skin configuration file

-

This section is a reference to the options appearing in the Standard skin configuration -file, found in $WEEWX_ROOT/skins/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 shown in -bold face and in blue.

-

[Extras]

-

This section is available to you to add any static tags that you might want to -be available in the templates. As an example, the stock 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 subsections. For example, -say you have added a video camera and you would like to add a still image with a -hyperlink to a page with the video. You want all of these options to be neatly contained -in a subsection.

-
[Extras]
+	
 
+

One additonal step is required: to tell the report service to run your generator + instead of the default generator. Modify option [Generators]generator_list + in the skin configuration file skin.conf to read:

+
generator_list = examples.mygenerator.MyFileGenerator, weewx.imagegenerator.ImageGenerator, weewx.reportengine.CopyGenerator
+

NB: If you create a custom generator some place other than where + weewxd.py resides, you may have to specify its location + in the environment variable PYTHON_PATH:

+
export PYTHON_PATH=/home/me/secret_location
+

Upgrades and user extensions

+

In the examples above, we subclassed weewx classes + to add functionality. Where should you put your new code? If you simply modify + the examples in place, then your changes will get overwritten the next time + you do an upgrade, forcing you to cut and paste any changes you have made. +

+

A better idea is to copy over the examples to the subdirectory + $WEEWX_ROOT/bin/user, then modify them there. + This subdirectory is preserved through upgrades, so you won't have to redo any + changes you might have made.

+

Reference: The + Standard skin configuration file

+

This section is a reference to the options appearing in the Standard skin + configuration file, found in $WEEWX_ROOT/skins/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 shown in + bold face and in blue.

+

[Extras]

+

This section is available to you to add any static tags that you might want + to be available in the templates. As an example, the stock + 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 subsections. For example, + say you have added a video camera and you would like to add a still image with + a hyperlink to a page with the video. You want all of these options to be neatly + contained in a subsection.

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

Then in your template you could refer to these as:

-
<a href="$Extras.video.hyperlink">
+	

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.

-

[[Groups]]

-

This subsection 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

-

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."

-

[[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

-
degree_C = %.1f
+	

[Units]

+

This section deals with Units and their formatting.

+

[[Groups]]

+

This subsection 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

+

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."

+

[[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

+
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,

-
NONE = " N/A "
-

[[Labels]]

-

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

-
degree_F = °F
+	

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 subsection 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).

-

[[TimeFormats]]

-

This sub-section is used for time labels. It uses -strftime() -formats. For example

-
week  = %H:%M on %A
+	

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 time labels. It uses + strftime() + formats. For example

+
week  = %H:%M on %A
 month = %d-%b-%Y %H:%M
-

would specify that week data should use a format such as "15:20 -on Sunday", while month data should look like "06-Oct-2009 -15:20"

-

[[DegreeDays]]

-

heating_base
-cooling_base

-

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

-
heating_base = 65.0, degree_F
+	

would specify that week data should use a format such as "15:20 + on Sunday", while month data should look like "06-Oct-2009 + 15:20"

+

[[DegreeDays]]

+

heating_base
+ cooling_base

+

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

+
heating_base = 65.0, degree_F
 cooling_base = 65.0, degree_C
-

[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".

-

[[Generic]]

-

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

-
inTemp = Temperature inside the house
+	

[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".

+

[[Generic]]

+

This sub-sections 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.

-

[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".

-

[FileGenerator]

-

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

-

Overview of file generation

-

Customization of file generation consists of playing with the various options -offered below and, failing that, modifying the template files that come with the -distribution.

-

Each template file is named something like D/F.E.tmpl, -where D is the subdirectory the template sits in and will -also be the subdirectory 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 skin that comes with the standard distribution of weewx -contains three different kinds of generated output:

-
    -
  1. Summary by month. In addition to the naming rules above, if the template - file has the letters YYYY and 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 default distribution has been set up to produce NOAA monthly - summaries, one for each month, as a simple text file (no HTML).
  2. -
  3. Summary by year.  In addition to the naming rules above, if the template - file has the letters YYYY in its name, the year will - be substituted. The default distribution has been set up to produce NOAA yearly - summaries, one for each year, as a simple text file (no HTML).
  4. -
  5. Summary "To Date". The default distribution has been set up to produce reports - for the day, week, month, and year-to-date observations. These four files are - all HTML files. The first, the daily summary (output file index.html), - includes a drop-down list that allows the NOAA month and yearly summaries to - be displayed.
  6. -
-

General

-

encoding

-

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

- - - - - - - - - - - - - - - - - -
EncodingComComments
html_entitiesNon 7-bit characters will be represented as HTML entities (e.g. - the degree sign will be represented as &#176;)
utf8Non 7-bit characters will be represented in UTF-8.
strict_asciiNon 7-bit characters will be ignored.
-

By default, the encoding html_entities is used for -HTML files, strict_ascii for the NOAA template files. -

-

[[SummaryByMonth]]

-

This section controls which summaries-by-month are generated. For each such summary, -it should have its own sub-subsection, with option template -listing the template to be used. The default configuration generates NOAA-by-month -summaries and is summarized below as an example. Additional "by month" summaries -can be added easily by following the same pattern.

-

[[[NOAA_month]]]

-

encoding

-

Set to strict_ascii for the NOAA monthly summary.

-

template

-

This option is set to the source template for the NOAA monthly summary, -NOAA/NOAA-YYYY-MM.txt.tmpl.

-

[[SummaryByYear]]

-

This section controls which summaries-by-year are generated. For each such summary, -it should have its own sub-subsection, with option template -listing the template to be used. The default configuration generates NOAA-by-year -summaries and is summarized below as an example. Additional "by year" summaries -can be added easily by following the pattern.

-

[[[NOAA_year]]]

-

encoding

-

Set to strict_ascii for the NOAA year summary.

-

template

-

This option is set to the source template for the NOAA yearly summary, -NOAA/NOAA-YYYY.txt.tmpl.

-

[[ToDate]]

-

This section controls which observations-to-date are generated. The default configuration -generates four files: one for day, week, month, and year. Although the sub-subsections -below have names such as 'week' or 'month', this is not used in their generation.  -Output is set by the template content, not the name of the sub-subsection -— the names below could as easily have been'Fred', 'Mary', 'Peter', and 'George' -and had the same output.

-

Additional observations-to-date pages can be created easily by adding a new sub-subsection -and giving it a unique name ("Jill"?), then giving the path to its template as option -template.

-

[[[day]]]

-

template

-

Set to index.html.tmpl, which contains the template -for the day summary.

-

[[[week]]]

-

template

-

Set to week.html.tmpl, which contains the template -for the week summary.

-

[[[month]]]

-

template

-

Set to month.html.tmpl, which contains the template -for the month summary.

-

[[[year]]]

-

template

-

Set to year.html.tmpl, which contains the template -for the year summary.

-

[[[RSS]]]

-

Set to RSS/weewx_rss.xml.tmpl, which contains a template -for an RSS feed.

-

[CopyGenerator]

-

This section is used by generator weewx.reportengine.CopyGenerator -and controls which files are to be copied over from the skin subdirectory to the -destination directory. Think of it as "file generation," except that rather than -going through the template engine, the files are simply copied over.

-

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.

-

[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.

-

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

-
[[month_images]]
+	

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".

+

[FileGenerator]

+

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

+

Overview of file generation

+

Customization of file generation consists of playing with the various options + offered below and, failing that, modifying the template files that come with + the distribution.

+

Each template file is named something like D/F.E.tmpl, + where D is the subdirectory the template sits in and + will also be the subdirectory 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 skin that comes with the standard distribution of + weewx contains three different kinds of generated output:

+
    +
  1. Summary by month. In addition to the naming rules above, if the template + file has the letters YYYY and + 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 default distribution has been set up to produce NOAA monthly summaries, + one for each month, as a simple text file (no HTML).
  2. +
  3. Summary by year.  In addition to the naming rules above, if the + template file has the letters YYYY in its name, + the year will be substituted. The default distribution has been set up to + produce NOAA yearly summaries, one for each year, as a simple text file + (no HTML).
  4. +
  5. Summary "To Date". The default distribution has been set up to produce + reports for the day, week, month, and year-to-date observations. These four + files are all HTML files. The first, the daily summary (output file index.html), + includes a drop-down list that allows the NOAA month and yearly summaries + to be displayed.
  6. +
+

General

+

encoding

+

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

+ + + + + + + + + + + + + + + + + +
EncodingComComments
html_entitiesNon 7-bit characters will be represented as HTML entities (e.g. + the degree sign will be represented as &#176;)
utf8Non 7-bit characters will be represented in UTF-8.
strict_asciiNon 7-bit characters will be ignored.
+

By default, the encoding html_entities is used + for HTML files, strict_ascii for the NOAA template + files.

+

[[SummaryByMonth]]

+

This section controls which summaries-by-month are generated. For each such + summary, it should have its own sub-subsection, with option + template listing the template to be used. The default + configuration generates NOAA-by-month summaries and is summarized below as an + example. Additional "by month" summaries can be added easily by following the + same pattern.

+

[[[NOAA_month]]]

+

encoding

+

Set to strict_ascii for the NOAA monthly summary.

+

template

+

This option is set to the source template for the NOAA monthly summary, + NOAA/NOAA-YYYY-MM.txt.tmpl.

+

[[SummaryByYear]]

+

This section controls which summaries-by-year are generated. For each such + summary, it should have its own sub-subsection, with option + template listing the template to be used. The default + configuration generates NOAA-by-year summaries and is summarized below as an + example. Additional "by year" summaries can be added easily by following the + pattern.

+

[[[NOAA_year]]]

+

encoding

+

Set to strict_ascii for the NOAA year summary.

+

template

+

This option is set to the source template for the NOAA yearly summary, + NOAA/NOAA-YYYY.txt.tmpl.

+

[[ToDate]]

+

This section controls which observations-to-date are generated. The default + configuration generates four files: one for day, week, month, and year. Although + the sub-subsections below have names such as 'week' or 'month', this is not + used in their generation.  Output is set by the template content, + not the name of the sub-subsection — the names below could as easily have been'Fred', + 'Mary', 'Peter', and 'George' and had the same output.

+

Additional observations-to-date pages can be created easily by adding a new + sub-subsection and giving it a unique name ("Jill"?), then giving the path to + its template as option template.

+

[[[day]]]

+

template

+

Set to index.html.tmpl, which contains the template + for the day summary.

+

[[[week]]]

+

template

+

Set to week.html.tmpl, which contains the template + for the week summary.

+

[[[month]]]

+

template

+

Set to month.html.tmpl, which contains the template + for the month summary.

+

[[[year]]]

+

template

+

Set to year.html.tmpl, which contains the template + for the year summary.

+

[[[RSS]]]

+

Set to RSS/weewx_rss.xml.tmpl, which contains a + template for an RSS feed.

+

[CopyGenerator]

+

This section is used by generator weewx.reportengine.CopyGenerator + and controls which files are to be copied over from the skin subdirectory to + the destination directory. Think of it as "file generation," except that rather + than going through the template engine, the files are simply copied over. +

+

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.

+

[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.

+

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's 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 = %m/%d/%y %H:%M
   time_length = 2592000 # == 30 days
   aggregate_type = avg
   aggregate_interval = 10800 # == 3 hours
-

The option x_label_format gives a -strftime() -type format for the x-axis. In this example, it will only show days (format option -"%d"). The bottom_label_format -is the format used to time stamp the image at the bottom. In this example, it will -show the time as 10/25/09 15:35. A plot will cover a nominal -30 days, and all items included in it will use an aggregate type of averaging over -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's a typical set of options for sub-sub-section -[[[monthrain]]]:

-
[[[monthrain]]]
+	

The option x_label_format gives a + strftime() + type format for the x-axis. In this example, it will only show days (format + option "%d"). The bottom_label_format + is the format used to time stamp the image at the bottom. In this example, it + will show the time as 10/25/09 15:35. A plot will + cover a nominal 30 days, and all items included in it will use an aggregate + type of averaging over 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's a typical set of options for sub-sub-section + [[[monthrain]]]:

+
[[[monthrain]]]
   plot_type = bar
   yscale = None, None, 0.02
   [[[[rain]]]]
     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. It is a 3-way tuple (ylow, -yhigh, min_interval), where -ymin and ymax 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, we are letting -weewx pick sensible y minimum and maximum values, but -we are requiring 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 haven't said otherwise, the SQL data type to be used for this line will -be the same as its logical name, that is, rain, b, 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)')

-

Including more than one SQL type in a plot

-

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

-
[[[monthtempdew]]]
+	

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. It is a 3-way tuple (ylow, + yhigh, min_interval), where + ymin and ymax 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, we are + letting weewx pick sensible y minimum and maximum + values, but we are requiring 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 haven't said otherwise, the SQL data type to be used for this line + will be the same as its logical name, that is, rain, + b, 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)')

+

Including more than one SQL type in a plot

+

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

+
[[[monthtempdew]]]
    [[[[outTemp]]]]
    [[[[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:

-
## WRONG ##
+	

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:

+
## 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:

-
[[[daytemp_with_avg]]]
+	

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
       aggregate_type = avg
       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

-

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 don't 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]]]
+	

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

+

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 don't 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]]]]
      label = Hourly Wind 
@@ -1424,124 +1314,126 @@ one week that shows the hourly biggest wind gusts, along with hourly averages:
-

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 don't 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.

-

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:

-
[Images]
+	

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 don't 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.

+

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:

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

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

-
    [[[daybarometer]]]
+	

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 an class="code" daybarometer_big.png.

-
     [[[daybarometer_big]]]
+	

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

+
     [[[daybarometer_big]]]
       image_width  = 600
       image_height = 360
       [[[[barometer]]]]
-

[Generators]

-

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.

-

 

-

4. Customizing the -weewx service engine

-

This is an advance topic intended for those who wish to try their hand at extending -the internal engine in weewx. You should have a passing familiarity with Python -or, at least, be willing to learn it.

-

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 with a -set of member functions. The engine arranges to have appropriate member functions -called when specific events happen. For example, when a new LOOP packet becomes -available, member function newLoopPacket() of all services -is called.

-

To customize, you can

-
    -
  • Customize a service
  • -
  • Add a service
  • -
  • Customize the engine
  • -
-

This section describes how to do all three.

-

The default install of weewx includes the following -services:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ServiceFunction
weewx.wxengine.StdCalibrateAdjust new LOOP and archive packets using calibration expressions.
weewx.wxengine.StdQCCheck that observation values fall within a specified range.
weewx.wxengine.StdArchiveArchive any new data to the SQL databases.
weewx.wxengine.StdTimeSynchArrange to have the clock on the station synchronized at regular intervals.
weewx.wxengine.StdPrintPrint 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.
weewx.wxengine.StdReportServiceLaunch a new thread to do report processing after a new archive record - arrives. Reports do things such as generate HTML files, generate images, - or FTP files to a web server. New reports can be added easily by the user.
-

Preserving your changes -across an upgrade

-

Generally, if you change the code in weewx you will -have to cut-and-paste any changes you have made to the new code. However, if you -put the changes in directory $WEEWX_ROOT/bin/user -(usually, /home/weewx/bin/user) the changes will be -preserved across an upgrade.

-

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 time, barometer, outside temperature, wind speed, and wind direction. Suppose -you don't like this, and want to print out humidity as well when a new LOOP packet -arrives. This could be done by subclassing the default print service -StdPrint and overriding member function -newLoopPacket().

-

In file bin/user/myprint.py:

-
from weewx.wxengine import StdPrint
+	

[Generators]

+

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.

+

Customizing the + weewx service engine

+

This is an advance topic intended for those who wish to try their hand at + extending the internal engine in weewx. You should have a passing familiarity + with Python or, at least, be willing to learn it.

+

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 with a set of member functions. The engine arranges to have + appropriate member functions called when specific events happen. For example, + when a new LOOP packet becomes available, member function + newLoopPacket() of all services is called.

+

To customize, you can

+
    +
  • Customize a service
  • +
  • Add a service
  • +
  • Customize the engine
  • +
+

This section describes how to do all three.

+

The default install of weewx includes the following + services:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ServiceFunction
weewx.wxengine.StdCalibrateAdjust new LOOP and archive packets using calibration expressions.
weewx.wxengine.StdQCCheck that observation values fall within a specified range.
weewx.wxengine.StdArchiveArchive any new data to the SQL databases.
weewx.wxengine.StdTimeSynchArrange to have the clock on the station synchronized at regular + intervals.
weewx.wxengine.StdPrintPrint 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.
weewx.wxengine.StdReportServiceLaunch a new thread to do report processing after a new archive + record arrives. Reports do things such as generate HTML files, generate + images, or FTP files to a web server. New reports can be added easily + by the user.
+

Preserving your changes + across an upgrade

+

Generally, if you change the code in weewx you + will have to cut-and-paste any changes you have made to the new code. However, + if you put the changes in directory $WEEWX_ROOT/bin/user + (usually, /home/weewx/bin/user) the changes will be + preserved across an upgrade.

+

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 time, barometer, outside temperature, wind speed, and wind direction. + Suppose you don't like this, and want to print out humidity as well when a new + LOOP packet arrives. This could be done by subclassing the default print service + StdPrint and overriding member function + newLoopPacket().

+

In file bin/user/myprint.py:

+
from weewx.wxengine import StdPrint
 from weeutil.weeutil import timestamp_to_string
 
 class MyPrint(StdPrint):
@@ -1554,24 +1446,26 @@ class MyPrint(StdPrint):
             loop_packet['outHumidity'],\
             loop_packet['windSpeed'],\
             loop_packet['windDir']
-

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 the standard print service name in the option -service_list, located in [Engines][[WxEngine]]:

-
[Engines]
+	

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 the standard print service name in the option + service_list, located in [Engines][[WxEngine]]:

+
[Engines]
     [[WxEngine]]
         service_list = weewx.wxengine.StdCalibrate, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, user.myprint.MyPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReportService
-

(Note that this 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's an example that implements an alarm that sends off an email when an -arbitrary expression evaluates True. This example is included in the standard distribution -in subdirectory "examples".

-

File examples/alarm.py:

-
import time
+	

(Note that this 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's an example that implements an alarm that sends off an email + when an arbitrary expression evaluates True. This example is included in the + standard distribution in subdirectory "examples". +

+

File examples/alarm.py:

+
import time
 import smtplib
 from email.mime.text import MIMEText
 import threading
@@ -1663,55 +1557,55 @@ class MyAlarm(StdService):
         # Log it in the system log:
         syslog.syslog(syslog.LOG_INFO, "alarm: Alarm sounded for expression: \"%s\"" % self.expression)
         syslog.syslog(syslog.LOG_INFO, "       *** email sent to: %s" % self.TO)
-

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]
+	

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
     smtp_host = smtp.mymailserver.com
     smtp_user = myusername
     smtp_password = mypassword
     mailto = auser@adomain.com
-

These options specify that the alarm is to 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. (The place -in the code where the expression is evaluated is marked with "NOTE -1".)

-

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 is specified in 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.

-

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]
+	

These options specify that the alarm is to 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. + (The place in the code where the expression is evaluated is marked with "NOTE + 1".)

+

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 is specified in 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.

+

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.StdCalibrate, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReportService, examples.alarm.MyAlarm
-

(Again, the list must be all on one line.)

-

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

-

Customizing the Engine

-

In this section, we look at how to install a custom Engine. In general, this -is the least desirable way to proceed, but in some cases it may be the only way -to get what you want.

-

For example, suppose you want to define a new event for when the first archive -of a day arrives. This can be done by extending the the standard engine.

-

This example is in file example/daily.py:

-
from weewx.wxengine import StdEngine, StdService
+	

(Again, the list must be all on one line.)

+

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

+

Customizing the Engine

+

In this section, we look at how to install a custom Engine. In general, this + is the least desirable way to proceed, but in some cases it may be the only + way to get what you want.

+

For example, suppose you want to define a new event for when the first archive + of a day arrives. This can be done by extending the the standard engine.

+

This example is in file example/daily.py:

+
from weewx.wxengine import StdEngine, StdService
 from weeutil.weeutil import startOfArchiveDay
 
 class MyEngine(StdEngine):
@@ -1751,28 +1645,28 @@ class MyEngine(StdEngine):
                 svc_obj.firstArchiveOfDay(rec)
             except AttributeError:
                 pass
-

This customized engine works by monitoring the arrival of archive records, and -checking their time stamp (rec['dateTime']. It calculates -the time stamp for the start of the day, and if it changes, calls member function -newDay() (NOTE 1).

-

The member function newDay() then goes through the -list of services (attribute self.service_obj). Because -this engine is defining a new event (first archive of the day), the existing services -may not be prepared to accept it. So, be prepared to catch an exception -AttributeError if the service does not define it (NOTE -2).

-

To use this engine, go into file weewxd.py and change -the line

-
weewx.wxengine.main()
-

so that it uses your new engine:

-
from examples.daily import MyEngine
+	

This customized engine works by monitoring the arrival of archive records, + and checking their time stamp (rec['dateTime']. It + calculates the time stamp for the start of the day, and if it changes, calls + member function newDay() (NOTE 1).

+

The member function newDay() then goes through + the list of services (attribute self.service_obj). + Because this engine is defining a new event (first archive of the day), the + existing services may not be prepared to accept it. So, be prepared to catch + an exception AttributeError if the service does not + define it (NOTE 2).

+

To use this engine, go into file weewxd.py and + change the line

+
weewx.wxengine.main()
+

so that it uses your new engine:

+
from examples.daily import MyEngine
  
 # Specify that my specialized engine should be used instead
 # of the default:
 weewx.wxengine.main(EngineClass = MyEngine)
-

We now have a new engine that defines a new event ("firstArchiveOfDay"), -but there is no service to take advantage of it. We define a new service:

-
# Define a new service to take advantage of the new event
+	

We now have a new engine that defines a new event ("firstArchiveOfDay"), + but there is no service to take advantage of it. We define a new service:

+
# Define a new service to take advantage of the new event
 class DailyService(StdService):
     """This service can do something when the first archive record of
     a day arrives."""
@@ -1784,1245 +1678,1247 @@ class DailyService(StdService):
         print rec
 
         # You might want to do something here like run a cron job
-

This service will simply print out a notice and then print out the new record. -However, if there is some daily processing you want to do, such as running a backup, -or running utility wunderfixer, this -would be the place to do it.

-

The final step is to go into your configuration file and specify that this new -service be loaded, by adding its class name to option service_list:

-
[Engines]
+	

This service will simply print out a notice and then print out the new record. + However, if there is some daily processing you want to do, such as running a + backup, or running utility wunderfixer, + this would be the place to do it.

+

The final step is to go into your configuration file and specify that this + new service be loaded, by adding its class name to option + service_list:

+
[Engines]
 
   [[WxEngine]]
     # The list of services the main weewx engine should run:
     service_list = weewx.wxengine.StdCalibrate, weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, weewx.wxengine.StdRESTful, weewx.wxengine.StdReportService, examples.daily.DailyService
-

(Again, the list must be all on one line.)

-

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:

-
    -
  • 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.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Archive TypeSQL Type
- (appears in archive database)
Can be used
- in plots
Can be used
- in tag $current
altimeterXXX
barometerXXX
consBatteryVoltageXXX
dateTimeXX (represents current time)
dewpointXXX
ETXXX
extraHumid1XXX
extraHumid2XXX
extraTemp1XXX
extraTemp2XXX
extraTemp3XXX
hailXXX
hailRateXXX
heatindexXXX
heatingTempXXX
heatingVoltageXXX
inHumidityXXX
inTempXXX
inTempBatteryStatusXXX
intervalXXX
leafTemp2XXX
leafWet2XXX
outHumidityXXX
outTempXXX
outTempBatteryStatusXXX
pressureXXX
radiationXXX
rainXXX
rainBatteryStatusXXX
rainRateXXX
referenceVoltageXXX
rxCheckPercentXXX
soilMoist1XXX
soilMoist2XXX
soilMoist3XXX
soilMoist4XXX
soilTemp1XXX
soilTemp2XXX
soilTemp3XXX
soilTemp4XXX
supplyVoltageXXX
txBatteryStatusXXX
usUnitsXXX
UVXXX
windvec X (special vector type) 
windBatteryStatusXXX
windDirXXX
windGustXXX
windGustDirXXX
windSpeedXXX
windchillXXX
-

Appendix B: Units

-

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

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GroupMembersUnit options
group_altitudealtitudefoot
- meter
group_directiongustdir
- vecdir
- windDir
- windGustDir
degree_compass
group_moisturesoilMoist1
- soilMoist2
- soilMoist3
- soilMoist4
centibar
group_percentextraHumid1
- extraHumid2
- inHumidity
- outHumidity
- rxCheckPercent
percent
group_pressurebarometer
- altimeter
- pressure
inHg
- mbar
- hPa
group_radiationUV
- radiation
watt_per_meter_squared
group_rainrain
- ET
- hail
in
- cm
- mm
group_rainraterainRate
- 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
group_speed2rms
- 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
group_degree_dayheatdef
- cooldeg
degree_F_day
- degree_C_day
group_voltconsBatteryVoltage
- heatingVoltage
- referenceVoltage
- supplyVoltage
volt
group_NONENONENONE
-

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).

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Stats Typeminmintimemaxmaxtimeavgsumrmsvecavgvecdir
barometerXXXXX    
inTempXXXXX    
outTempXXXXX    
inHumidityXXXXX    
outHumidityXXXXX    
windXXXXX XXX
rainXXXXXX   
dewpointXXXXX    
windchillXXXXX    
heatindexXXXXX    
heatdeg    XX   
cooldeg    XX   
ETXXXXX    
radiationXXXXX    
UVXXXXX    
extraTemp1
- extraTemp2
- extraTemp3
XXXXX    
soilTemp1
- soilTemp2
- soilTemp3
XXXXX    
leafTemp1
- leafTemp2
XXXXX    
extraHumid1
- extraHumid2
XXXXX    
soilMoist1
- soilMoist2
- soilMoist3
- soilMoist4
XXXXX    
leafWet1
- leafWet2
XXXXX    
rxCheckPercentXXXXX    
-

 

-

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.

-

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.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TypeLoop packetArchive Packet
barometerXX
consBatteryVoltageX 
dateTimeXX
dayETX 
dayRainX 
dewpointXX
ET (hourly) X
extraAlarm1X 
extraAlarm2X 
extraAlarm3X 
extraAlarm4X 
extraAlarm5X 
extraAlarm6X 
extraAlarm7X 
extraAlarm8X 
extraHumid1XX
extraHumid2XX
extraHumid3X 
extraHumid4X 
extraHumid5X 
extraHumid6X 
extraHumid7X 
extraTemp1XX
extraTemp2XX
extraTemp3XX
extraTemp4X 
extraTemp5X 
extraTemp6X 
extraTemp7X 
forecastIconX 
forecastRuleXX
heatIndexXX
highOutTemp X
highRadiation X
highUV X
inHumidityX 
inTempX 
interval X
insideAlarmX 
leafTemp1XX
leafTemp2XX
leafTemp3X 
leafTemp4X 
leafWet1XX
leafWet2XX
leafWet3X 
leafWet4X 
lowOutTemp X
monthETX 
monthRainX 
outHumidityXX
outTempXX
outsideAlarm1X 
outsideAlarm2X 
radiationXX
rain X
rainAlarmX 
rainRateX 
rxCheckPercent X
soilLeafAlarm1X 
soilLeafAlarm2X 
soilLeafAlarm3X 
soilLeafAlarm4X 
soilMoist1XX
soilMoist2XX
soilMoist3XX
soilMoist4XX
soilTemp1XX
soilTemp2XX
soilTemp3XX
soilTemp4XX
stormRainX 
stormStartX 
sunriseX 
sunsetX 
txBatteryStatusX 
usUnitsXX
UVXX
windChillXX
windDirXX
windGust X
windGustDir X
windSpeed10X 
windSpeedXX
yearETX 
yearRainX 
+

(Again, the list must be all on one line.)

+

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:

+
    +
  • 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.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Archive TypeSQL Type
+ (appears in archive database)
Can be used
+ in plots
Can be used
+ in tag $current
altimeterXXX
barometerXXX
consBatteryVoltageXXX
dateTimeXX (represents current time)
dewpointXXX
ETXXX
extraHumid1XXX
extraHumid2XXX
extraTemp1XXX
extraTemp2XXX
extraTemp3XXX
hailXXX
hailRateXXX
heatindexXXX
heatingTempXXX
heatingVoltageXXX
inHumidityXXX
inTempXXX
inTempBatteryStatusXXX
intervalXXX
leafTemp2XXX
leafWet2XXX
outHumidityXXX
outTempXXX
outTempBatteryStatusXXX
pressureXXX
radiationXXX
rainXXX
rainBatteryStatusXXX
rainRateXXX
referenceVoltageXXX
rxCheckPercentXXX
soilMoist1XXX
soilMoist2XXX
soilMoist3XXX
soilMoist4XXX
soilTemp1XXX
soilTemp2XXX
soilTemp3XXX
soilTemp4XXX
supplyVoltageXXX
txBatteryStatusXXX
usUnitsXXX
UVXXX
windvec X (special vector type) 
windBatteryStatusXXX
windDirXXX
windGustXXX
windGustDirXXX
windSpeedXXX
windchillXXX
+

Appendix B: Units

+

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

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GroupMembersUnit options
group_altitudealtitudefoot
+ meter
group_directiongustdir
+ vecdir
+ windDir
+ windGustDir
degree_compass
group_moisturesoilMoist1
+ soilMoist2
+ soilMoist3
+ soilMoist4
centibar
group_percentextraHumid1
+ extraHumid2
+ inHumidity
+ outHumidity
+ rxCheckPercent
percent
group_pressurebarometer
+ altimeter
+ pressure
inHg
+ mbar
+ hPa
group_radiationUV
+ radiation
watt_per_meter_squared
group_rainrain
+ ET
+ hail
in
+ cm
+ mm
group_rainraterainRate
+ 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
group_speed2rms
+ 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
group_degree_dayheatdef
+ cooldeg
degree_F_day
+ degree_C_day
group_voltconsBatteryVoltage
+ heatingVoltage
+ referenceVoltage
+ supplyVoltage
volt
group_NONENONENONE
+

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).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Stats Typeminmintimemaxmaxtimeavgsumrmsvecavgvecdir
barometerXXXXX    
inTempXXXXX    
outTempXXXXX    
inHumidityXXXXX    
outHumidityXXXXX    
windXXXXX XXX
rainXXXXXX   
dewpointXXXXX    
windchillXXXXX    
heatindexXXXXX    
heatdeg    XX   
cooldeg    XX   
ETXXXXX    
radiationXXXXX    
UVXXXXX    
extraTemp1
+ extraTemp2
+ extraTemp3
XXXXX    
soilTemp1
+ soilTemp2
+ soilTemp3
XXXXX    
leafTemp1
+ leafTemp2
XXXXX    
extraHumid1
+ extraHumid2
XXXXX    
soilMoist1
+ soilMoist2
+ soilMoist3
+ soilMoist4
XXXXX    
leafWet1
+ leafWet2
XXXXX    
rxCheckPercentXXXXX    
+

 

+

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.

+

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.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeLoop packetArchive Packet
barometerXX
consBatteryVoltageX 
dateTimeXX
dayETX 
dayRainX 
dewpointXX
ET (hourly) X
extraAlarm1X 
extraAlarm2X 
extraAlarm3X 
extraAlarm4X 
extraAlarm5X 
extraAlarm6X 
extraAlarm7X 
extraAlarm8X 
extraHumid1XX
extraHumid2XX
extraHumid3X 
extraHumid4X 
extraHumid5X 
extraHumid6X 
extraHumid7X 
extraTemp1XX
extraTemp2XX
extraTemp3XX
extraTemp4X 
extraTemp5X 
extraTemp6X 
extraTemp7X 
forecastIconX 
forecastRuleXX
heatIndexXX
highOutTemp X
highRadiation X
highUV X
inHumidityX 
inTempX 
interval X
insideAlarmX 
leafTemp1XX
leafTemp2XX
leafTemp3X 
leafTemp4X 
leafWet1XX
leafWet2XX
leafWet3X 
leafWet4X 
lowOutTemp X
monthETX 
monthRainX 
outHumidityXX
outTempXX
outsideAlarm1X 
outsideAlarm2X 
radiationXX
rain X
rainAlarmX 
rainRateX 
rxCheckPercent X
soilLeafAlarm1X 
soilLeafAlarm2X 
soilLeafAlarm3X 
soilLeafAlarm4X 
soilMoist1XX
soilMoist2XX
soilMoist3XX
soilMoist4XX
soilTemp1XX
soilTemp2XX
soilTemp3XX
soilTemp4XX
stormRainX 
stormStartX 
sunriseX 
sunsetX 
txBatteryStatusX 
usUnitsXX
UVXX
windChillXX
windDirXX
windGust X
windGustDir X
windSpeed10X 
windSpeedXX
yearETX 
yearRainX 
+
diff --git a/docs/readme.htm b/docs/readme.htm index f758c41c..f2caeaee 100644 --- a/docs/readme.htm +++ b/docs/readme.htm @@ -9,133 +9,11 @@ The Weewx weather system - + + + + + @@ -143,844 +21,850 @@ td {

The weewx weather system
Version 1.10

Table of Contents

-
    -
  1. Copyright
  2. -
  3. About weewx
  4. -
  5. Downloading weewx
  6. -
  7. Prerequisites
  8. -
  9. Installing weewx
  10. -
  11. Configuring weewx
  12. -
  13. Running weewx
  14. -
  15. Compatibility with wview
  16. -
  17. Monitoring weewx
  18. -
  19. Troubleshooting
  20. -
  21. Architectural notes
  22. -
-

For information on customizing weewx, see the separate -document Customizing weewx.

-

For instructions on upgrading from various versions, see the separate -document Upgrading weewx.

-

For instructions on porting to the SheevaPlug, see the separate document -Notes on porting weewx to the -SheevaPlug.

-

1. Copyright

-

(c) 2009, 2010 by Tom Keffer <tkeffer@gmail.com>

-

This program is free software: you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software Foundation, -either version 3 of the License, or (at your option) any later version.

-

This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details.

-

You should have received a copy of the GNU General Public License along with -this program. If not, see -http://www.gnu.org/licenses.

-

2. About weewx

-

weewx is a piece of software, written in -Python, that interacts with your weather station -to produce plots, reports, and HTML pages. It can optionally upload the reports -to a remote Web server as well as publish to the -WeatherUnderground or -PWSweather.com. It uses modern software -concepts, making it simple, robust, and easy to extend. For an example station see -Hood River West.

-

Key features:

- -

I wrote weewx over the winter of 2008-2009 for two -reasons: it was a wet and miserable winter here in Oregon with not much else to -do, so there was no good reason not to, and because I wanted a simple, easy-to-understand -server to run my Davis VantagePro2 weather station on a Linux box. I had been using -wview, which is a high-performance and -feature rich system authored by Mark Teel with lots of users. Written in C, it's -an efficient system that can run on underpowered boxes. In exchange, it's huge -(45,000+ lines of code), tightly integrated in with its companion library, radlib -(another 14,000+ lines), and very complex, making it difficult to understand and -reliably customize. I wanted something more modern and much simpler.

-

Having made a career in C++ and Java, I was also interested in some more modern -languages, so I thought I'd try either Python or Ruby (although, truth be told, -the roots of Python are nearly as old as C++!). I ended up picking Python because -its libraries are more mature and there are many mores choices for third party libraries.

-

Weewx weighs in at well under 5,000 lines of code. It also has another 2,900 -comment lines. Because it is pure Python, it requires no makefiles, no builds, -no special installs. It offers very powerful -configuration and templating options, as well as an internally extensible -engine, making it easy to customize. Its internal modular design and use of -modern exception handling make it very robust and difficult to crash. It is also -architecturally very simple and easy to understand. However, to be fair, at this -point it supports only the  -Davis -VantagePro2 weather station.

-

3. Downloading weewx

-

weewx can be downloaded from its -SourceForge page: -https://sourceforge.net/projects/weewx. -

-

4. Prerequisites

-

4.1 Python

-

Python V2.5 or V2.6 is required. The newer V3.0 distribution will not work.

-

4.2 Required packages

-

The following external packages are required to use weewx.

-
    -
  1. sqlite3 (Version 3.5 or greater) A - SQL database written in C, which weewx uses to store - data pulled from the weather station. Comes with Debian and many other Linux - distributions.
  2. -
  3. pysqlite (Version 2.5 - or greater) The Python interface to sqlite3.
  4. -
  5. configobj (Version - 4.5 or greater) Manages the configuration file weewx.conf.
  6. -
  7. pyserial (Version - 2.3 or greater) Manages the serial connection to the weather station.
  8. -
  9. Cheetah (Version 2.0 or greater) - The HTML templating engine.
  10. -
  11. Python Imaging Library (Version - 1.1.6 or greater) Also known as PIL, this is included in many Python distributions.
  12. -
-

There are two general strategies for installing these prerequisites:

-
    -
  1. Use operating system tools, such as apt-get (or - its graphical equivalent Synaptic Package Manager) for Debian/Ubuntu or - yast for SuSE; or
  2. -
  3. Use the Python tool - easy_install.
  4. -
-

Option #1 is easier, but if your Linux distribution does not come with such tools, -you may have to use easy_install. Brief instructions for -both approaches are given below.

-

Installation on Debian distributions (including Ubuntu) using -apt-get

-

The instructions that follow are for using the Debian tool -apt_get, but the same package names would be used should you chose to use -a graphical interface such as the Synaptic Package Manager.

-

sqlite3

-

My Ubuntu 8.10 system came with V3.5.9 of sqlite, which works just fine. However, -if you need to install:

-

sudo apt-get install sqlite3

-

pysqlite

-

Easily installed:

-

sudo apt-get install python-pysqlite2

-

configobj

-

Easily installed:

-

sudo apt-get install python-configobj

-

pyserial

-

Easily installed:

-

sudo apt-get install python-serial

-

Cheetah

-

Easily installed:

-

sudo apt-get install python-cheetah

-

Python Imaging Library (PIL)

-

My version of Python came with V1.1.6, which works great. However, some users -have reported having to install PIL. In this case

-

sudo apt-get install python-imaging

-

Installation on SuSE using yast

-

My SuSE 11.1 system came with some of the prerequisites installed, some available -through yast, and three that required -easy_install. To start, you will have to install the gcc -compiler:

-

sudo yast -i gcc

-

Then install easy_install:

-

sudo yast -i python-setuptools

-

On my system, some scripts wanted to install themselves into -/usr/local/lib/python2.6/site-packages, which didn't exist. -If this is the case, you may have to create these directories before running -easy_install:

-

sudo mkdir /usr/local/lib/python2.6

-

sudo mkdir /usr/local/lib/python2.6/site-packages

-

sqlite3

-

My SuSE 11.1 system came with V3.6.4, which works just fine. However, if you -need to install:

-

sudo yast -i sqlite3

-

pysqlite

-

Install using easy_install. See -comments below about installing pysqlite -using easy_install. On my SuSE 11.1 system, I had to install -the gcc compiler and the sqlite3 development environment first:

-

sudo yast -i gcc

-

sudo yast -i sqlite-devel

-

Then I was able to install pysqlite using easy_install. -However, because the hosting site for pysqlite had changed recently, I had to give -the URL explicitly:

-

sudo easy_install -http://pysqlite.googlecode.com/files/pysqlite-2.5.5.tar.gz

-

configobj

-

Install using easy_install:

-

sudo easy_install configobj

-

pyserial

-

Install using yast:

-

sudo yast-i python-serial

-

Cheetah

-

Install using easy_install (My system emitted a bunch -of, apparently, benign warnings):

-

sudo easy_install Cheetah

-

Python Imaging Library (PIL)

-

Install using yast

-

sudo yast -i python-imaging

-

Installation using easy_install

-

An alternative approach to installing the required packages is by using the Python -setup tool "easy_install", part of the -python-setuptools package. -Refer to their instructions on how to install this tool.

-

Once easy_install has been installed, installing the -rest of the packages is very easy.

-

sqlite3

-

My Ubuntu 8.10 system came with sqlite V3.5.9, which works just fine. If you -do not have sqlite3, refer to the sqlite webpage -for installation instructions.

-

pysqlite

-

While Version 2.3.X of pysqlite -is included with many versions of Python, the more recent 2.5.X or greater is required -in order to take advantage of transaction contexts. Hence, you may have to install -or upgrade. Because pysqlite builds a C library, you may have to install the Python -development environment first, if you have not already done so. Generally, this -means installing the gcc compiler. You may also have to install the sqlite3 development -environment as well.

-

With the development environment in place, you can easily build and install pysqlite:

-

easy_install pysqlite

-

If your system already has a version of pysqlite installed, but it is not a high -enough version (easy_install will tell you the version -you have), then you may have to force an upgrade:

-

easy_install --upgrade pysqlite

-

Note that at the time of this writing (24 Oct 2009), the hosting site for pysqlite -has changed to one on googlecode, and -easy_install could not find it. You may have to find and -give the URL explicitly to easy_install (adjust version -numbers as necessary):

-

easy_install http://pysqlite.googlecode.com/files/pysqlite-2.5.5.tar.gz

-

configobj

-

Easily installed:

-

easy_install configobj

-

pyserial

-

easy_install pyserial

-

Cheetah

-

easy_install Cheetah

-

Python Imaging Library (PIL)

-

My version of Python came with V1.1.6, which works great.

-

4.3 System requirements

-

I run weewx on a 500MHz system with an AMD Geode processor -and 512 MB of memory.  Configured this way, it consumes about 5% of the CPU -and about 40MB of total memory.

-

4.4 Weather station hardware requirements

-

At this point, only the -Davis VantagePro2 -is supported, and even then, only the "Revision B" version (firmware dated on or -after 22 April 2002). It would be very easy to port to a "Revision A" station or -even the original VantagePro, but I don't have access to the hardware to test it.

-

5. Installing weewx

-

Because weewx is "Pure Python", that is it is 100% -Python with no "C" modules to compile, installing it is very easy. Furthermore, -it uses the standard Python -distutils install method, which is very easy and flexible. Detailed instructions -follow.

-

5.1 Unpacking

-

Start by unpack the tar ball (substitute your version for X.Y.Z) into any convenient -directory where you have write permission

-

tar xvf weewx-X.Y.Z

-

Then change directory into it:

-

cd weewx-X.Y.Z

-

5.1 Choosing where to install weewx

-

Next step is figuring out where you want to install weewx. -If $WEEWX_INSTALL symbolizes the root -location of where the weewx directory will be -installed, then the nominal directory layout is:

- - - - - - - - - - - - - - - - - - - - - - - - - -
SubdirectoryContents
$WEEWX_INSTALL/binPython packages and scripts
$WEEWX_INSTALL/weewx.confConfiguration file
$WEEWX_INSTALL/skinsTemplate skins and their configuration files
$WEEWX_INSTALL/archivesqlite3 archive and statistical databases
$WEEWX_INSTALL/public_htmlGenerated HTML and .PNG images
-

By default, the location for WEEWX_INSTALL is -/home/weewx. However, it can be changed by editing the -file setup.cfg. If you wish to install someplace else, -open up setup.cfg and change the line

-

home = /home/weewx

-

to reflect your decision.

-

5.2 Build and install

-

Build the distribution

-

./setup.py build

-

(Because weewx is pure Python this doesn't actually -build anything, but it does arrange files for the final installation)

-

Then install it. If you have write permission in the directory where -weewx will go (i.e., -$WEEWX_INSTALL), -then type

-

./setup.py install

-

Otherwise, if you do not have write permission, you will have to use sudo:

-

sudo ./setup.py install

-

Upgrading

-

Before upgrading from a previous version of weewx, -check the upgrade notes, found in file upgrading.htm, -to see if there any specific actions you need to do.

-

You then generally follow the procedure above.

-

In particular, before starting, be sure to set -home in the file -setup.cfg.

-

The build and install process will do the following for you.

- -

5.3 Permissions

-

Strictly speaking it is not necessary to install or run weewx -with root privileges. You only need read/write access to the serial port for your -hardware. For example, if your hardware has a USB interface, on Ubuntu and SuSE:

-

sudo chmod a+rw /dev/ttyUSB0

-

Once done, if you edit setup.cfg to install into a -directory where you have write permissions, you can install and run -weewx without any root privileges at all.

-

5.4 Final note on installation

-

Because weewx is pure Python, it does not -actually have to be "built" and "installed" at all! You can just simply run it out of whatever -directory you unpack it into. However, it must still be told where to find the -skin templates and databases, as well as where to put the generated HTML files -and plot images. This is done by setting WEEWX_ROOT in weewx.conf -to reflect where your data files can be found (normally, the install process -does this for you):

-
> # Edit WEEWX_ROOT to reflect the location of your data hierarchy:
+
+
+
+

For information on customizing weewx, see the separate + document Customizing + weewx.

+

For instructions on upgrading from various versions, see the separate document + Upgrading weewx.

+

For instructions on porting to the SheevaPlug, see the separate document + Notes on porting weewx to + the SheevaPlug.

+

Copyright

+

(c) 2009, 2010, 2011 by Tom Keffer <tkeffer@gmail.com>

+

This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later version. +

+

This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +

+

You should have received a copy of the GNU General Public License along with + this program. If not, see + http://www.gnu.org/licenses.

+

About weewx

+

weewx is a piece of software, written in + Python, that interacts with your weather + station to produce plots, reports, and HTML pages. It can optionally upload + the reports to a remote Web server as well as publish to the + WeatherUnderground or + PWSweather.com. It uses modern software + concepts, making it simple, robust, and easy to extend. For an example station + see Hood River West.

+

Key features:

+
    +
  • An easy to understand, simple, extensible micro-kernel architecture;
  • +
  • Uploads to popular weather sites, such as Weather Underground and CWOP;
  • +
  • Uploads to your website using FTP;
  • +
  • Support for multiple skins;
  • +
  • Simple, but extensible templating system;
  • +
  • Support for multiple unit systems;
  • +
  • Calibration corrections;
  • +
  • Ability to extend weewx with new services + and reports.
  • +
+

I wrote weewx over the winter of 2008-2009 for + two reasons: it was a wet and miserable winter here in Oregon with not much + else to do, so there was no good reason not to, and because I wanted a simple, + easy-to-understand server to run my Davis VantagePro2 weather station on a Linux + box. I had been using wview, which + is a high-performance and feature rich system authored by Mark Teel with lots + of users. Written in C, it's an efficient system that can run on underpowered + boxes. In exchange, it's huge (45,000+ lines of code), tightly integrated in + with its companion library, radlib (another 14,000+ lines), and very complex, + making it difficult to understand and reliably customize. I wanted something + more modern and much simpler.

+

Having made a career in C++ and Java, I was also interested in some more + modern languages, so I thought I'd try either Python or Ruby (although, truth + be told, the roots of Python are nearly as old as C++!). I ended up picking + Python because its libraries are more mature and there are many mores choices + for third party libraries.

+

Weewx weighs in at well under 5,000 lines of code. + It also has another 2,900 comment lines. Because it is pure Python, it requires + no makefiles, no builds, no special installs. It offers very powerful configuration + and templating options, as well as an internally extensible engine, making it + easy to customize. Its internal modular design and use of modern exception handling + make it very robust and difficult to crash. It is also architecturally very + simple and easy to understand. However, to be fair, at this point it supports + only the  + Davis VantagePro2 + weather station.

+

Downloading weewx

+

weewx can be downloaded from its + SourceForge page: + https://sourceforge.net/projects/weewx. +

+

Prerequisites

+

Python

+

Python V2.5 or V2.6 is required. The newer V3.0 distribution will not work.

+

Required packages

+

The following external packages are required to use weewx.

+
    +
  1. sqlite3 (Version 3.5 or greater) + A SQL database written in C, which weewx uses + to store data pulled from the weather station. Comes with Debian and many + other Linux distributions.
  2. +
  3. pysqlite (Version + 2.5 or greater) The Python interface to sqlite3.
  4. +
  5. configobj (Version + 4.5 or greater) Manages the configuration file weewx.conf.
  6. +
  7. pyserial (Version + 2.3 or greater) Manages the serial connection to the weather station.
  8. +
  9. Cheetah (Version 2.0 or + greater) The HTML templating engine.
  10. +
  11. Python Imaging Library + (Version 1.1.6 or greater) Also known as PIL, this is included in many Python + distributions.
  12. +
+

There are two general strategies for installing these prerequisites:

+
    +
  1. Use operating system tools, such as apt-get + (or its graphical equivalent Synaptic Package Manager) for Debian/Ubuntu + or yast for SuSE; or
  2. +
  3. Use the Python tool + easy_install.
  4. +
+

Option #1 is easier, but if your Linux distribution does not come with such + tools, you may have to use easy_install. Brief instructions + for both approaches are given below.

+

Installation on Debian distributions (including Ubuntu) using + apt-get

+

The instructions that follow are for using the Debian tool + apt_get, but the same package names would be used + should you chose to use a graphical interface such as the Synaptic Package Manager.

+

sqlite3

+

My Ubuntu 8.10 system came with V3.5.9 of sqlite, which works just fine. + However, if you need to install:

+

sudo apt-get install sqlite3

+

pysqlite

+

Easily installed:

+

sudo apt-get install python-pysqlite2

+

configobj

+

Easily installed:

+

sudo apt-get install python-configobj

+

pyserial

+

Easily installed:

+

sudo apt-get install python-serial

+

Cheetah

+

Easily installed:

+

sudo apt-get install python-cheetah

+

Python Imaging Library (PIL)

+

My version of Python came with V1.1.6, which works great. However, some users + have reported having to install PIL. In this case

+

sudo apt-get install python-imaging

+

Installation on SuSE using yast

+

My SuSE 11.1 system came with some of the prerequisites installed, some available + through yast, and three that required + easy_install. To start, you will have to install the + gcc compiler:

+

sudo yast -i gcc

+

Then install easy_install:

+

sudo yast -i python-setuptools

+

On my system, some scripts wanted to install themselves into + /usr/local/lib/python2.6/site-packages, which didn't + exist. If this is the case, you may have to create these directories before + running easy_install:

+

sudo mkdir /usr/local/lib/python2.6

+

sudo mkdir /usr/local/lib/python2.6/site-packages

+

sqlite3

+

My SuSE 11.1 system came with V3.6.4, which works just fine. However, if + you need to install:

+

sudo yast -i sqlite3

+

pysqlite

+

Install using easy_install. See + comments below about installing pysqlite + using easy_install. On my SuSE 11.1 system, I had + to install the gcc compiler and the sqlite3 development environment first:

+

sudo yast -i gcc

+

sudo yast -i sqlite-devel

+

Then I was able to install pysqlite using easy_install. + However, because the hosting site for pysqlite had changed recently, I had to + give the URL explicitly:

+

sudo easy_install + http://pysqlite.googlecode.com/files/pysqlite-2.5.5.tar.gz

+

configobj

+

Install using easy_install:

+

sudo easy_install configobj

+

pyserial

+

Install using yast:

+

sudo yast-i python-serial

+

Cheetah

+

Install using easy_install (My system emitted a + bunch of, apparently, benign warnings):

+

sudo easy_install Cheetah

+

Python Imaging Library (PIL)

+

Install using yast

+

sudo yast -i python-imaging

+

Installation using easy_install

+

An alternative approach to installing the required packages is by using the + Python setup tool "easy_install", part of the + python-setuptools package. + Refer to their instructions on how to install this tool.

+

Once easy_install has been installed, installing + the rest of the packages is very easy.

+

sqlite3

+

My Ubuntu 8.10 system came with sqlite V3.5.9, which works just fine. If + you do not have sqlite3, refer to the sqlite + webpage for installation instructions.

+

pysqlite

+

While Version 2.3.X of pysqlite + is included with many versions of Python, the more recent 2.5.X or greater is + required in order to take advantage of transaction contexts. Hence, you may + have to install or upgrade. Because pysqlite builds a C library, you may have + to install the Python development environment first, if you have not already + done so. Generally, this means installing the gcc compiler. You may also have + to install the sqlite3 development environment as well.

+

With the development environment in place, you can easily build and install + pysqlite:

+

easy_install pysqlite

+

If your system already has a version of pysqlite installed, but it is not + a high enough version (easy_install will tell you + the version you have), then you may have to force an upgrade:

+

easy_install --upgrade pysqlite

+

Note that at the time of this writing (24 Oct 2009), the hosting site for + pysqlite has changed to one on googlecode, + and easy_install could not find it. You may have to + find and give the URL explicitly to easy_install (adjust + version numbers as necessary):

+

easy_install http://pysqlite.googlecode.com/files/pysqlite-2.5.5.tar.gz

+

configobj

+

Easily installed:

+

easy_install configobj

+

pyserial

+

easy_install pyserial

+

Cheetah

+

easy_install Cheetah

+

Python Imaging Library (PIL)

+

My version of Python came with V1.1.6, which works great.

+

System requirements

+

I run weewx on a 500MHz system with an AMD Geode + processor and 512 MB of memory.  Configured this way, it consumes about + 5% of the CPU and about 40MB of total memory.

+

Weather station hardware requirements

+

At this point, only the + Davis VantagePro2 + is supported, and even then, only the "Revision B" version (firmware dated on + or after 22 April 2002). It would be very easy to port to a "Revision A" station + or even the original VantagePro, but I don't have access to the hardware to + test it.

+

Installing weewx

+

Because weewx is "Pure Python", that is it is 100% + Python with no "C" modules to compile, installing it is very easy. Furthermore, + it uses the standard Python + distutils install method, + which is very easy and flexible. Detailed instructions follow.

+

Unpacking

+

Start by unpack the tar ball (substitute your version for X.Y.Z) into any + convenient directory where you have write permission

+

tar xvf weewx-X.Y.Z

+

Then change directory into it:

+

cd weewx-X.Y.Z

+

Choosing where to install weewx

+

Next step is figuring out where you want to install weewx. + If $WEEWX_INSTALL symbolizes the root location + of where the weewx directory will be installed, then + the nominal directory layout is:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
SubdirectoryContents
$WEEWX_INSTALL/binPython packages and scripts
$WEEWX_INSTALL/weewx.confConfiguration file
$WEEWX_INSTALL/skinsTemplate skins and their configuration files
$WEEWX_INSTALL/archivesqlite3 archive and statistical databases
$WEEWX_INSTALL/public_htmlGenerated HTML and .PNG images
+

By default, the location for WEEWX_INSTALL + is /home/weewx. However, it can be changed by editing + the file setup.cfg. If you wish to install someplace + else, open up setup.cfg and change the line

+

home = /home/weewx

+

to reflect your decision.

+

Build and install

+

Build the distribution

+

./setup.py build

+

(Because weewx is pure Python this doesn't actually + build anything, but it does arrange files for the final installation)

+

Then install it. If you have write permission in the directory where + weewx will go (i.e., + $WEEWX_INSTALL), then type

+

./setup.py install

+

Otherwise, if you do not have write permission, you will have to use sudo:

+

sudo ./setup.py install

+

Upgrading

+

Before upgrading from a previous version of weewx, + check the upgrade notes, found in file upgrading.htm, + to see if there any specific actions you need to do.

+

You then generally follow the procedure above.

+

In particular, before starting, be sure to set + home in the file + setup.cfg.

+

The build and install process will do the following for you.

+
    +
  • Save your old 'bin' subdirectory as + $WEEWX_INSTALL/bin.YYYYMMDDHHMMSS where + YYYYMMDDHHMMSS is a timestamp;
  • +
  • Save a copy of your old weewx.conf as + $WEEWX_INSTALL/weewx.conf.YYYYMMDDHHMMSS;
  • +
  • Merge any changes you've made to your old configuration file + weewx.conf into the new configuration file, then + install the merged copy (this effectively causes changes you've made to + override the values in the shipped version of weewx.conf);
  • +
  • Install a 'skins' subdirectory if one does + not already exist.
  • +
+

Permissions

+

Strictly speaking it is not necessary to install or run + weewx with root privileges. You only need read/write + access to the serial port for your hardware. For example, if your hardware has + a USB interface, on Ubuntu and SuSE:

+

sudo chmod a+rw /dev/ttyUSB0

+

Once done, if you edit setup.cfg to install into + a directory where you have write permissions, you can install and run + weewx without any root privileges at all.

+

Final note on installation

+

Because weewx is pure Python, it does not actually + have to be "built" and "installed" at all! You can just simply run it out of + whatever directory you unpack it into. However, it must still be told where + to find the skin templates and databases, as well as where to put the generated + HTML files and plot images. This is done by setting WEEWX_ROOT + in weewx.conf to reflect where your data files can + be found (normally, the install process does this for you):

+
> # Edit WEEWX_ROOT to reflect the location of your data hierarchy:
 > vi ./weewx-X.Y.Z/weewx.conf
 > # Now run weewxd.py out of the directory you unpacked weewx into:
 > ./weewx-X.Y.Z/bin/weewxd.py ./weewx-X.Y.Z/weewx.conf
-

6. Configuring weewx

-

This section covers configuring weewx, in -particular the configuration files -weewx.conf and skin.conf.

-

In the following, $WEEWX_ROOT refers to the -weewx data root directory, generally /home/weewx. -The subdirectories archive, skins, -and public_html are expected to be found here. -

-

6.1 Moving from wview

-

NOTE: This section is necessary only if you are moving from -wview to weewx -and wish to transfer your old data over. If you are starting afresh, you do not -need to follow this section — the two main databases are created and populated automatically -by weewx.

-

The main archive database can be just copied over because wview and weewx -use identical schemas:

-
mkdir $WEEWX_ROOT/archive
+	

Configuring weewx

+

This section covers configuring weewx, in particular + the configuration files weewx.conf and + skin.conf.

+

In the following, $WEEWX_ROOT refers to + the weewx data root directory, generally + /home/weewx. The subdirectories + archive, skins, and public_html + are expected to be found here.

+

Moving from wview

+

NOTE: This section is necessary only if you are moving from + wview to weewx + and wish to transfer your old data over. If you are starting afresh, you do + not need to follow this section — the two main databases are created and populated + automatically by weewx.

+

The main archive database can be just copied over because wview and + weewx use identical schemas:

+
mkdir $WEEWX_ROOT/archive
 cp /usr/local/var/wview/archive/wview-archive.sdb $WEEWX_ROOT/archive/weewx.sdb
-

The second database, the statistics, will then be automatically created and -backfilled on startup of weewx. If your existing database is large, backfilling could take some time. On my modest -500 MHz fit-PC -Slim with 512 MB of memory it took a little over 4 minutes for a year and a -half (25 MB) of data (while wview was running in the background).

-

6.2 Configuring your weather station

-

The only two variables weewx tries to manage on the -VantagePro are the time and the archive interval.

-

Time

-

The time on the VP is automatically synchronized with the -weewx server nominally every four hours (changeable by the user). You should -run a NTP daemon on your server to insure that -it is synchronized with the correct time. Doing so will greatly reduce errors, especially -if you send data to services such as the Weather Underground.

-

Archive interval

-

The archive interval is set in the main configuration file -$WEEWX_ROOT/weewx.conf. Look for the entry archive_interval -in the VantagePro section. Set it to the number of seconds. -Valid entries are 60, 300, 600, 900, 1800, 3600, and 7200. However, if you are ftp'ing -lots of files to a server, setting it to 60 seconds may not give enough time to -have them all uploaded before the next archive record is due. If this is the case, -you should pick an archive interval of at least 300 seconds, or trim the number -of files you are using.

-

I have found that a five minute (300 seconds) archive interval works well for -the VantagePro. Because of the large amount of onboard memory it carries, going -to a larger interval really does not have any advantages.

-

Choose your archiving interval carefully! Once chosen, it cannot be -changed without messing up your statistics (highs and lows will be OK, but -averages and rms wind speed will be wrong).

-

After setting the desired interval in the configuration file, run the configure.py -script to set it on the VantagePro. If it differs from the old archive interval, -the main memory log of the VantagePro will be cleared.

-

$WEEWX_ROOT/bin/configure.py --configure-VantagePro $WEEWX_ROOT/weewx.conf

-

6.3 Editing the configuration file weewx.conf

-

Station specific information is set in the configuration file -$WEEWX_ROOT/weewx.conf. There is another configuration -file skin.conf for presentation-specific options, which -is described in a separate document -Customizing weewx under section -Reference: -The standard skin configuration file.

-

Most of the important options are up near the top of the file. They are all documented -in this section, although you can safely ignore most of them. The truly important -ones, the ones you are likely to have to customize for your station, are shown in -bold face and in blue.

-

Default values are provided for many of them, meaning that if they are not listed -in the configuration file at all, weewx will -pick sensible values. When the documentation below gives a "default value" this -is what it means. However, all options have been given values in the configuration -file that ships with weewx, so you can see what they look -like. The value given in this shipped configuration file is not necessarily the -same as the "default value".

-

What follows is organized by the different sections of the configuration file.

-

General

-

The options declared at the top are not actually part of any section. There are -two:

-

debug

-

Set to 1 to have the program perform extra debug checks, as well as emit extra -information on the log file. Otherwise, set to 0. Default is 0 (no debug).

-

socket_timeout

-

Set to how long to wait before declaring a socket time out. This is used when -FTP'ing data to a web server or sending data to the Weather Underground. Twenty -(20) seconds is reasonable. Default is 20.

-

[Station]

-

This section covers options relating to the entire weather station setup.

-

WEEWX_ROOT

-

Set to the root directory of the weewx data file hierarchy -for this station, nominally '/home/weewx'. The -weewx data subdirectories skins, -archive, and public_html are expected to be -found here. This value -will be set automatically by the setup script setup.py -to reflect the choice you made in the configuration file setup.cfg. -Required. No default.

-

location

-

The station location should be a UTF-8 string that describes the geography of -where you weather station is located, such as 'Hood River, Oregon'. Required. No -default.

-

latitude
-longitude

-

The lat/lon should be set in decimal degrees, negative for southern and eastern -hemispheres, respectively. Required. No default.

-

altitude

-

Set to the altitude of the station and the unit used for the altitude. -Required. No default. Example:

-
altitude = 700, foot
-

rain_year_start

-

If your area uses a rain year that starts on something other than the first of -January, you may want to set this variable. For example, set to 10 if your rain -year starts in October (as mine does). Default is 1.

-

week_start

-

Start of the week. 0=Monday, 1= Tuesday, ... , 6 = Sunday. Default is 6 (Sunday)

-

clock_check

-

How often to check the station's onboard clock for drift, in seconds. Default -is 14400 (every 4 hours)

-

max_drift

-

The maximum amount of drift to tolerate, in seconds, in the onboard -clock, before resetting the clock. Default is 5.

-

cache_loop_data

-

Set to 1 (one) to cache LOOP data, otherwise, set to zero. Most users will not -want to change this unless you have a specialized application. Default is 1 (i.e., -cache LOOP data).

-

station_type

-

Set to the type of hardware you are using. For this version, only 'VantagePro' -is accepted. Required.

-

[VantagePro]

-

This section is for options relating to the VantagePro hardware.

-

port

-

Set to the port name used by your station. Example, /dev/ttyUSB0 -is a common location for USB ports under Debian, /dev/ttyS0 -for serial ports. Required. No default.

-

baudrate

-

Set to the baudrate of your station. The default is 19200.

-

archive_interval

-

Set to the desired archive interval of your station, in seconds. This variable -is only used when setting up your station. Otherwise, this value is read directly -from the station. Required if you configure your station. -No default.

-

iss_id

-

Set to the ID number of your Integrated Sensor Suite (ISS). This is used in the -formula to calculate reception quality for wireless stations. The default is 1.

-

archive_delay

-

How long to wait in seconds after the top of an archiving interval before fetching -new data off the station. For example, if your archive interval is 5 minutes and -archive_delay is set to 15, then the data will be fetched at 00:00:15, 00:05:15, -00:10:15, etc. This delay is to give the station a few seconds to archive the data -internally, and in case your server has any other tasks to do at the top of the -minute. Default is 15 seconds.

-

timeout

-

How many seconds  to wait for a response from the station before giving -up. Default is 5 seconds.

-

wait_before_retry

-

How many seconds to wait before retrying again. Unless you have a good reason -to change it, this value should be left at the default, as it is long enough for -the station to offer new data, but not so long as to go into a new loop packet (which -arrive every 2 seconds). Default is 1.2 seconds.

-

max_tries

-

How many times to try again before giving up. Default is 4.

-

unit_system

-

What unit system is in use on your weather station hardware. Possible values -are '1' (U.S. Customary) or '2' (Metric). As far as I know, all Davis instruments -support only U.S.. In any case, U.S. is the only system supported by -weewx at this time. Default is 1.

-

[RESTful]

-

This section is for configuring uploads to simple -RESTful -servers such as the Weather Underground, -PWSweather.com, or -CWOP.

-

[[Wunderground]]

-

Weewx can send your current data to the Weather Underground. -If you do not wish to do this, comment out the two options below.

-

station

-

Set to your Weather Underground station ID (e.g., KORHOODR3). -Required.

-

password

-

Set to your Weather Underground password. Required.

-

[[PWSweather]]

-

Weewx can send your current data to the -PWSweather.com service. -If you do not wish to do this, comment out the two options below.

-

station

-

Set to your PWSweather station ID. -Required.

-

password

-

Set to your PWSweather password. Required.

-

[[CWOP]]

-

Weewx can send your data to the Citizen Weather -Observer Program. If you do not wish to do this, comment out option "station" -below.

-

station

-

Set to your CWOP station ID (e.g., CW1234). -Required.

-

passcode

-

This is used for APRS (amateur radio) stations only. Set to the passcode -given to you by the CWOP operators. Otherwise, leave this option commented out -[Required for APRS stations; ignored for others]

-

server

-

A comma separated list of servers:ports to try. Unless you have a good reason -to change this, use the servers listed. [Required.]

-

interval

-

The interval in seconds between posts. Because CWOP is heavily used, the -operators discourage very frequent posts. Every 5 minutes (300 seconds) is fine, -but they prefer every 10 minutes (600 s) or even longer. Setting this value to -zero will cause every archive record to be posted. [Optional. Default is zero.]

-

stale

-

How old a record can be before it will not be used for a catch up. CWOP does -not use the timestamp on a posted record. Instead, they use the wall clock time -that it came in. This means that if your station is off the air for a long -period of time, then weewx attempts a catch up, old data could be interpreted as -the current conditions. [Optional. Default is 1800 seconds.]

-

[Archive]

-

This section is for configuring the sqlite3 database in which the station archive -data is stored.

-

archive_file

-

The path, relative to the WEEWX_ROOT directory, to -the database. Required

-

unit_system

-

What unit system to use inside the database. Required. The only one supported -right now is '1', the U.S. Customary system

-

[Stats]

-

This section is for configuring the sqlite3 database in which the station statistics -are stored.

-

stats_file

-

The path, relative to the WEEWX_ROOT directory to the -statistical database. Required.

-

stats_types

-

The list of types for which statistics will be kept. Types not listed will not -be available for generating HTML pages. Optional. The default is all types, resulting -in a possibly much bigger than necessary stats database (do you really have four -different soil moisture sensors?) The list that ships with the configuration file -will work for most stations and probably will not have to be modified.

-

[Reports]

-

This section controls which reports are to be generated. While it can be highly -customized for your individual situation, this documentation describes the section -as shipped in the standard distribution.

-

Each report is represented by a sub-section, marked with double brackets (e.g., -[[MyReport]]). Any options for the report should be placed -under it. The standard report service will go through the sections, running each -report in order. Hence, for the stock distribution, report [[StandardReport]] -will be run first, then report [[FTP]] (which actually -optionally uploads the results to a remote web server). Details for how to customize -reports are in the section -Opportunities for -customizing reports, in the document Customizing -weewx.

-

SKIN_ROOT

-

The directory relative to $WEEWX_ROOT where -the skins live. Default is skins.

-

HTML_ROOT

-

The target directory for the generated files, relative to -$WEEWX_ROOT. Generated files and images will be put here. Default -is public_html.

-

[[StandardReport]]

-

This is the standard report that will be run on every archiving interval. It -uses the skin "Standard", which generates four HTML pages -("day", "week", "month", and "year" observations), -plot graphs for same, an RSS feed, and NOAA -monthly and yearly reports. Unless changed otherwise, it uses US Customary Units -and puts the results in public_html and subdirectory -public_html/NOAA.

-

[[FTP]]

-

While this "report" doesn't actually generate anything, it uses the report machinery -to upload files from directory $HTML_ROOT to -a remote webserver. It does an incremental update, that is, it only FTPs any files -that have changed, saving the outgoing bandwidth of your Internet connection.

-

If you do not use such a server, comment out the first four options below.

-

user

-

Set to the username you use for your FTP connection to your web server. Required. -No default.

-

password

-

Set to the password you use for your FTP connection to your web server. Required. -No default.

-

server

-

Set to the name of your web server (e.g., -www.threefools.org, in my case). Required. No default

-

path

-

Set to the path where the weather data will be stored on your webserver (e.g., -'/weather'). NB: some FTP servers require a leading slash -('/'), some don't. Required. No default.

-

passive

-

Set to 1 if you wish to use the more modern, FTP passive mode, 0 if you wish -to use active mode. Passive mode generally works better through firewalls, but not -all FTP servers do a good job of supporting it. See -Active FTP vs. Passive FTP, a Definitive -Explanation for a good explanation of the difference. Default is 1 (passive -mode).

-

max_tries

-

Weewx will try up to this many times to FTP a file -up to your server before giving up. Default is 3.

-

[Calibrate]

-

One of the services that weewx can run is a calibration service -called StdCalibrate. -This service offers an opportunity to correct for any calibration errors in your -instruments. It is very general and flexible.

-

If you do not wish to apply any calibrations, you can leave it out of -service_list, the list of -services to be run, and it will not be loaded or run.

-

[[Corrections]]

-

In this section you list all correction expressions. For example, -say that you know your outside thermometer reads high by 0.2°F. You could -add the expression:

-
outTemp = outTemp - 0.2
-

Perhaps you need a linear correction around a reference temperature of 68°F:

-
outTemp = outTemp + (outTemp-68) * 0.02
-

It is even possible to do corrections involving more than one variable. -Suppose you have a temperature sensitive barometer:

-
barometer = barometer + (outTemp-32) * 0.0091
-

All correction expressions are run in the order given.

-

The units should be in the native units of the instrument, US -Customary in the case of the VantagePro.

-

Both LOOP data and archive data will be corrected. It is important that the -calibration service, StdCalibrate, be run before -the archiving service StdArchive, so that it is the -corrected data that is stored.

-

If all you require is a simple correction offset, this can also be done in -the Davis VantagePro hardware. See your manual for instructions.

-

[QC]

-

Another service that weewx can run is a quality control service -called StdQC. This service is very simple and only -checks that values are within a minimum and maximum range.

-

If you do not wish to use this service, you can leave it out of -service_list, the list of -services to be run, and it will not be loaded or run.

-

[[MinMax]]

-

In this section you list the observation types you wish to have checked, -along with their minimum and maximum values. The units should be in the native -units of the weather station hardware (e.g., US Customary in the case of the Davis -VantagePro2). For example,

-

[[MinMax]]
+

The second database, the statistics, will then be automatically created and + backfilled on startup of weewx. If your existing database is large, backfilling + could take some time. On my modest 500 MHz + fit-PC Slim + with 512 MB of memory it took a little over 4 minutes for a year and a half + (25 MB) of data (while wview was running in the background).

+

Configuring your weather station

+

The only two variables weewx tries to manage on + the VantagePro are the time and the archive interval.

+

Time

+

The time on the VP is automatically synchronized with the + weewx server nominally every four hours (changeable + by the user). You should run a NTP daemon + on your server to insure that it is synchronized with the correct time. Doing + so will greatly reduce errors, especially if you send data to services such + as the Weather Underground.

+

Archive interval

+

The archive interval is set in the main configuration file + $WEEWX_ROOT/weewx.conf. Look for the entry + archive_interval in the VantagePro + section. Set it to the number of seconds. Valid entries are 60, 300, 600, 900, + 1800, 3600, and 7200. However, if you are ftp'ing lots of files to a server, + setting it to 60 seconds may not give enough time to have them all uploaded + before the next archive record is due. If this is the case, you should pick + an archive interval of at least 300 seconds, or trim the number of files you + are using.

+

I have found that a five minute (300 seconds) archive interval works well + for the VantagePro. Because of the large amount of onboard memory it carries, + going to a larger interval really does not have any advantages.

+

Choose your archiving interval carefully! Once chosen, it cannot + be changed without messing up your statistics (highs and lows will be OK, but + averages and rms wind speed will be wrong).

+

After setting the desired interval in the configuration file, run the + configure.py script to set it on the VantagePro. If + it differs from the old archive interval, the main memory log of the VantagePro + will be cleared.

+

$WEEWX_ROOT/bin/configure.py --configure-VantagePro + $WEEWX_ROOT/weewx.conf

+

Editing the configuration file weewx.conf

+

Station specific information is set in the configuration file + $WEEWX_ROOT/weewx.conf. There is another + configuration file skin.conf for presentation-specific + options, which is described in a separate document + Customizing weewx + under section + Reference: + The standard skin configuration file.

+

Most of the important options are up near the top of the file. They are all + documented in this section, although you can safely ignore most of them. The + truly important ones, the ones you are likely to have to customize for your + station, are shown in bold face and in blue. +

+

Default values are provided for many of them, meaning that if they are not + listed in the configuration file at all, weewx + will pick sensible values. When the documentation below gives a "default value" + this is what it means. However, all options have been given values in the configuration + file that ships with weewx, so you can see what they + look like. The value given in this shipped configuration file is not necessarily + the same as the "default value".

+

What follows is organized by the different sections of the configuration + file.

+

General

+

The options declared at the top are not actually part of any section. There + are two:

+

debug

+

Set to 1 to have the program perform extra debug checks, as well as emit + extra information on the log file. Otherwise, set to 0. Default is 0 (no debug).

+

socket_timeout

+

Set to how long to wait before declaring a socket time out. This is used + when FTP'ing data to a web server or sending data to the Weather Underground. + Twenty (20) seconds is reasonable. Default is 20.

+

[Station]

+

This section covers options relating to the entire weather station setup. +

+

WEEWX_ROOT

+

Set to the root directory of the weewx data file + hierarchy for this station, nominally '/home/weewx'. + The weewx data subdirectories skins, + archive, and public_html + are expected to be found here. This value will be set automatically by the setup + script setup.py to reflect the choice you made in + the configuration file setup.cfg. Required. No default.

+

location

+

The station location should be a UTF-8 string that describes the geography + of where you weather station is located, such as 'Hood River, + Oregon'. Required. No default.

+

latitude
+ longitude

+

The lat/lon should be set in decimal degrees, negative for southern and eastern + hemispheres, respectively. Required. No default.

+

altitude

+

Set to the altitude of the station and the unit used for the altitude. Required. + No default. Example:

+
altitude = 700, foot
+

rain_year_start

+

If your area uses a rain year that starts on something other than the first + of January, you may want to set this variable. For example, set to 10 if your + rain year starts in October (as mine does). Default is 1.

+

week_start

+

Start of the week. 0=Monday, 1= Tuesday, ... , 6 = Sunday. Default is 6 (Sunday)

+

clock_check

+

How often to check the station's onboard clock for drift, in seconds. Default + is 14400 (every 4 hours)

+

max_drift

+

The maximum amount of drift to tolerate, in seconds, in the onboard clock, + before resetting the clock. Default is 5.

+

cache_loop_data

+

Set to 1 (one) to cache LOOP data, otherwise, set to zero. Most users will + not want to change this unless you have a specialized application. Default is + 1 (i.e., cache LOOP data).

+

station_type

+

Set to the type of hardware you are using. For this version, only 'VantagePro' + is accepted. Required.

+

[VantagePro]

+

This section is for options relating to the VantagePro hardware.

+

port

+

Set to the port name used by your station. Example, /dev/ttyUSB0 + is a common location for USB ports under Debian, /dev/ttyS0 + for serial ports. Required. No default.

+

baudrate

+

Set to the baudrate of your station. The default is 19200.

+

archive_interval

+

Set to the desired archive interval of your station, in seconds. This variable + is only used when setting up your station. Otherwise, this value is read directly + from the station. Required if you configure your + station. No default.

+

iss_id

+

Set to the ID number of your Integrated Sensor Suite (ISS). This is used + in the formula to calculate reception quality for wireless stations. The default + is 1.

+

archive_delay

+

How long to wait in seconds after the top of an archiving interval before + fetching new data off the station. For example, if your archive interval is + 5 minutes and archive_delay is set to 15, then the data will be fetched at 00:00:15, + 00:05:15, 00:10:15, etc. This delay is to give the station a few seconds to + archive the data internally, and in case your server has any other tasks to + do at the top of the minute. Default is 15 seconds.

+

timeout

+

How many seconds  to wait for a response from the station before giving + up. Default is 5 seconds.

+

wait_before_retry

+

How many seconds to wait before retrying again. Unless you have a good reason + to change it, this value should be left at the default, as it is long enough + for the station to offer new data, but not so long as to go into a new loop + packet (which arrive every 2 seconds). Default is 1.2 seconds.

+

max_tries

+

How many times to try again before giving up. Default is 4.

+

unit_system

+

What unit system is in use on your weather station hardware. Possible values + are '1' (U.S. Customary) or '2' (Metric). As far as I know, all Davis instruments + support only U.S.. In any case, U.S. is the only system supported by + weewx at this time. Default is 1.

+

[RESTful]

+

This section is for configuring uploads to simple + RESTful + servers such as the Weather Underground, + PWSweather.com, or + CWOP.

+

[[Wunderground]]

+

Weewx can send your current data to the Weather + Underground. If you do not wish to do this, comment out the two options below.

+

station

+

Set to your Weather Underground station ID (e.g., KORHOODR3). + Required.

+

password

+

Set to your Weather Underground password. Required.

+

[[PWSweather]]

+

Weewx can send your current data to the PWSweather.com + service. If you do not wish to do this, comment out the two options below.

+

station

+

Set to your PWSweather station ID. Required.

+

password

+

Set to your PWSweather password. Required.

+

[[CWOP]]

+

Weewx can send your data to the Citizen Weather + Observer Program. If you do not wish to do this, comment out option "station" + below.

+

station

+

Set to your CWOP station ID (e.g., CW1234). Required.

+

passcode

+

This is used for APRS (amateur radio) stations only. Set to the passcode + given to you by the CWOP operators. Otherwise, leave this option commented out + [Required for APRS stations; ignored for others]

+

server

+

A comma separated list of servers:ports to try. Unless you have a good reason + to change this, use the servers listed. [Required.]

+

interval

+

The interval in seconds between posts. Because CWOP is heavily used, the + operators discourage very frequent posts. Every 5 minutes (300 seconds) is fine, + but they prefer every 10 minutes (600 s) or even longer. Setting this value + to zero will cause every archive record to be posted. [Optional. Default is + zero.]

+

stale

+

How old a record can be before it will not be used for a catch up. CWOP does + not use the timestamp on a posted record. Instead, they use the wall clock time + that it came in. This means that if your station is off the air for a long period + of time, then weewx attempts a catch up, old data could be interpreted as the + current conditions. [Optional. Default is 1800 seconds.]

+

[Archive]

+

This section is for configuring the sqlite3 database in which the station + archive data is stored.

+

archive_file

+

The path, relative to the WEEWX_ROOT directory, + to the database. Required

+

unit_system

+

What unit system to use inside the database. Required. The only one supported + right now is '1', the U.S. Customary system

+

[Stats]

+

This section is for configuring the sqlite3 database in which the station + statistics are stored.

+

stats_file

+

The path, relative to the WEEWX_ROOT directory + to the statistical database. Required.

+

stats_types

+

The list of types for which statistics will be kept. Types not listed will + not be available for generating HTML pages. Optional. The default is all types, + resulting in a possibly much bigger than necessary stats database (do you really + have four different soil moisture sensors?) The list that ships with the configuration + file will work for most stations and probably will not have to be modified.

+

[Reports]

+

This section controls which reports are to be generated. While it can be + highly customized for your individual situation, this documentation describes + the section as shipped in the standard distribution.

+

Each report is represented by a sub-section, marked with double brackets + (e.g., [[MyReport]]). Any options for the + report should be placed under it. The standard report service will go through + the sections, running each report in order. Hence, for the stock distribution, + report [[StandardReport]] will be run first, then + report [[FTP]] (which actually optionally uploads + the results to a remote web server). Details for how to customize reports are + in the section + Opportunities + for customizing reports, in the document + Customizing weewx.

+

SKIN_ROOT

+

The directory relative to $WEEWX_ROOT + where the skins live. Default is skins.

+

HTML_ROOT

+

The target directory for the generated files, relative to + $WEEWX_ROOT. Generated files and images will + be put here. Default is public_html.

+

[[StandardReport]]

+

This is the standard report that will be run on every archiving interval. + It uses the skin "Standard", which generates four + HTML pages ("day", "week", "month", and "year" observations), plot graphs for + same, an RSS feed, and NOAA monthly and yearly reports. Unless changed otherwise, + it uses US Customary Units and puts the results in public_html + and subdirectory public_html/NOAA.

+

[[FTP]]

+

While this "report" doesn't actually generate anything, it uses the report + machinery to upload files from directory $HTML_ROOT + to a remote webserver. It does an incremental update, that is, it only FTPs + any files that have changed, saving the outgoing bandwidth of your Internet + connection.

+

If you do not use such a server, comment out the first four options below.

+

user

+

Set to the username you use for your FTP connection to your web server. Required. + No default.

+

password

+

Set to the password you use for your FTP connection to your web server. Required. + No default.

+

server

+

Set to the name of your web server (e.g., + www.threefools.org, in my case). Required. + No default

+

path

+

Set to the path where the weather data will be stored on your webserver (e.g., + '/weather'). NB: some FTP servers require a leading + slash ('/'), some don't. Required. No default.

+

passive

+

Set to 1 if you wish to use the more modern, FTP passive mode, 0 if you wish + to use active mode. Passive mode generally works better through firewalls, but + not all FTP servers do a good job of supporting it. See + Active FTP vs. Passive FTP, a + Definitive Explanation for a good explanation of the difference. Default + is 1 (passive mode).

+

max_tries

+

Weewx will try up to this many times to FTP a file + up to your server before giving up. Default is 3.

+

[Calibrate]

+

One of the services that weewx can run is a + calibration service called StdCalibrate. This + service offers an opportunity to correct for any calibration errors in your + instruments. It is very general and flexible.

+

If you do not wish to apply any calibrations, you can leave it out of + service_list, the list + of services to be run, and it will not be loaded or run.

+

[[Corrections]]

+

In this section you list all correction expressions. For example, + say that you know your outside thermometer reads high by 0.2°F. You could add + the expression:

+
outTemp = outTemp - 0.2
+

Perhaps you need a linear correction around a reference temperature of 68°F:

+
outTemp = outTemp + (outTemp-68) * 0.02
+

It is even possible to do corrections involving more than one variable. Suppose + you have a temperature sensitive barometer:

+
barometer = barometer + (outTemp-32) * 0.0091
+

All correction expressions are run in the order given.

+

The units should be in the native units of the instrument, US Customary + in the case of the VantagePro.

+

Both LOOP data and archive data will be corrected. It is important that the + calibration service, StdCalibrate, be run before + the archiving service StdArchive, so that it is the + corrected data that is stored.

+

If all you require is a simple correction offset, this can also be done in + the Davis VantagePro hardware. See your manual for instructions.

+

[QC]

+

Another service that weewx can run is a quality control service + called StdQC. This service is very simple and only + checks that values are within a minimum and maximum range.

+

If you do not wish to use this service, you can leave it out of + service_list, the list + of services to be run, and it will not be loaded or run.

+

[[MinMax]]

+

In this section you list the observation types you wish to have checked, + along with their minimum and maximum values. The units should be in the native + units of the weather station hardware (e.g., US Customary in the case + of the Davis VantagePro2). For example,

+

[[MinMax]]
  outTemp = -40, 120
  barometer = 28, 32.5
  outHumidity = 0, 100

-

In this example, if a temperature should fall outside of the inclusive range --40 °F through 120 °F, then it will be set to the null value, -None and ignored. In a similar manner, the acceptable -values for barometric pressure would be 28 through 32.5 inHg, for humidity 0 -through 100%.

-

Both LOOP and archive data will be checked. It is important that the quality -control service be run after the calibration service -StdCalibrate and before the archiving service -StdArchive, so that it is the calibrated data that is checked and then -stored.

-

Knowing the details of how your hardware encodes data helps to minimize the -number of observations that need to be checked. For example, the VP2 devotes -only one unsigned byte to storing wind speed, and even then -0xff is devoted to a bad value, so the only possible values that could -appear are 0 through 126 mph, a reasonable range. So, there is no real point in -checking wind speed for these instruments.

- -

[Engines]

-

This section is used to configure the internal service engine in weewx. It is -for advanced customization. Details on how to do this is found in the section - -Customizing the -weewx service engine in the document Customizing -weewx.

-

[[WxEngine]]

-

This section is for options used by the service engine.

-

service_list

-

This option is the list of services that are to be run by the service -engine. After each event (such as the arrival of LOOP data, etc.), they will be -run in the given order. The standard list of services run by weewx is:

-

service_list = weewx.wxengine.StdCalibrate, weewx.wxengine,StdQC, -weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, -weewx.wxengine.StdRESTful, weewx.wxengine.StdReportService

-

You can leave some of these services out if you do not need them. However, -this will only make a slight difference in execution speed.

-

7. Running weewx

-

Weewx can be run either from the command line (useful -for diagnostic purposes because it will print out a summary of every LOOP data), -or as a daemon. When first trying weewx, it's probably -best to run it from the command line because you will be able to see command line -diagnostics, as well as log messages.

-

7.1 Running from the command line

-

Weewx can easily be run from the command line. Start -by making sure you have appropriate permissions to the serial port your weather -station uses. For example, if you are using a plain old serial port:

-

sudo chmod 666 /dev/ttyS0

-

Then run the main loop program, weewxd.py, giving the -configuration file as its only parameter:

-

$WEEWX_ROOT/bin/weewxd.py $WEEWX_ROOT/weewx.conf

-

It should start by downloading any archive data from your weather station into -the database $WEEWX_ROOT/archive/weewx.sdb. As -the Davis VantagePro can store a couple thousand archive records internally, this -could take a minute or two. I've found this process particularly slow on SuSE for -some reason.

-

Weewx will then start monitoring LOOP data, printing -a short version of the received data on standard output, about once every two seconds.

-

You can tell a running instance of weewx to reread -its configuration file by sending it the HUP signal. First -run ps to find out the Process ID (PID) number of the -instance, then send it the HUP signal:

-

ps -a         # Note the -PID of the weewxd.py process

-

kill -HUP pid # Send it a HUP signal

-

7.2 Running as a daemon

-

For unattended operations it is best to have weewx -run as a daemon, started automatically when the server is rebooted. Start by selecting -the appropriate run script. They can be found under $WEEWX_ROOT/start_script. -

- - - - - - - - - -
SuSE:$WEEWX_ROOT/start_script/SuSE/weewx
Debian/Ubuntu:$WEEWX_ROOT/start_script/Debian/weewx
-

Check the chosen script to make sure the variable WEEWX_ROOT -inside has been set to the proper root directory for your weewx -installation (it should have been set to the correct value automatically by the -install process, but it's worth checking).

-

Copy it to the proper location for your system:

- - - - - - - - - -
SuSE:cp $WEEWX_ROOT/start_script/SuSE/weewx /etc/init.d
Debian/Ubuntu:cp $WEEWX_ROOT/start_script/Debian/weewx /etc/init.d
-

Make sure the script is executable:

- - - - - - - - -
SuSE:chmod +x /etc/init.d/weewx
Debian/Ubuntu:chmod +x /etc/init.d/weewx
-

Create symbolic links in the run level directories:

- - - - - - - - - -
SuSE:/usr/lib/lsb/install_initd /etc/init.d/weewx
Debian/Ubuntu:update-rc.d weewx defaults 98
-

Weewx will now start automatically whenever your system -is booted. You can also manually start, stop, and restart the -weewx daemon:

-

/etc/init.d/weewx start

-

/etc/init.d/weewx stop

-

/etc/init.d/weewx restart

-

By default, the scripts are designed to have weewx -run at run levels 2, 3, 4 and 5. Incidentally, a nice tool for setting run levels -with Debian (Ubuntu) systems is sysv-rc-conf. -It uses a curses interface to allow you to change easily which run level any of -your daemons runs at. There is a similar tool on SuSE. From the start menu run the -YAST Control Center, then look for Systems Services (Runlevel). Pick "Expert" mode -to see the run levels.

-

You can also tell weewx to reread its configuration -file without stopping by using the 'reload' option:

-

/etc/init.d/weewx reload

-

8. Compatibility with -wview

-

The sqlite3 archive database used by weewx (nominally, -weewx.sdb) is completely compatible with the database -used by wview (usually called -wview-archive.sdb), at least as of wview Version 5.2.X. -The schema and its semantics is identical. However, the statistical file -stats.sdb is different, and must be rebuilt. This will -be done automatically on startup by weewx.

-

9. Monitoring weewx

-

Weewx logs many events to the system log. On Debian -systems, this is /var/log/syslog, on SuSE, -/var/log/messages. Your system may use yet another place. -When troubleshooting the system, be sure to check it!

-

Setting the option debug in weewx.conf -to 1 (one) will generate many more checks and output and -can be useful for debugging.

-

10. Troubleshooting

-

If you get stuck, be sure to

-
    -
  • Set option debug in weewx.conf -to 1 (one)! It will put lots more information in the - log file, which can be very useful for troubleshooting and debugging!
  • -
  • Look at the log file. I am always happy - to take questions, but the first thing I will ask you is: "Did you look at - the log file?"
  • -
  • Run from the command line. Generally, weewx will catch and log any - unrecoverable exceptions. But if you are getting strange results, it is - worth running from the command line and looking for any clues.
  • -
-

10.1 Execution

-

configobj errors

-

These are errors in the configuration file. Two are very common. -Incidentally, these errors are far easier to diagnose when -weewx is run from the command line.

-

configobj.DuplicateError exception

-

This error is caused by using an identifier more than once in the -configuration file. For example, you may have inadvertently listed your FTP -server twice:

-
[Reports]
+	

In this example, if a temperature should fall outside of the inclusive range + -40 °F through 120 °F, then it will be set to the null value, + None and ignored. In a similar manner, the acceptable + values for barometric pressure would be 28 through 32.5 inHg, for humidity 0 + through 100%.

+

Both LOOP and archive data will be checked. It is important that the quality + control service be run after the calibration service + StdCalibrate and before the archiving service + StdArchive, so that it is the calibrated data that + is checked and then stored.

+

Knowing the details of how your hardware encodes data helps to minimize the + number of observations that need to be checked. For example, the VP2 devotes + only one unsigned byte to storing wind speed, and even then + 0xff is devoted to a bad value, so the only possible + values that could appear are 0 through 126 mph, a reasonable range. So, there + is no real point in checking wind speed for these instruments.

+

[Engines]

+

This section is used to configure the internal service engine in weewx. It + is for advanced customization. Details on how to do this is found in the section + + + Customizing the weewx service engine in the document + Customizing weewx.

+

[[WxEngine]]

+

This section is for options used by the service engine.

+

service_list

+

This option is the list of services that are to be run by the service + engine. After each event (such as the arrival of LOOP data, etc.), they will + be run in the given order. The standard list of services run by weewx is:

+

service_list = weewx.wxengine.StdCalibrate, weewx.wxengine,StdQC, + weewx.wxengine.StdArchive, weewx.wxengine.StdTimeSynch, weewx.wxengine.StdPrint, + weewx.wxengine.StdRESTful, weewx.wxengine.StdReportService

+

You can leave some of these services out if you do not need them. However, + this will only make a slight difference in execution speed.

+

Running weewx

+

Weewx can be run either from the command line (useful + for diagnostic purposes because it will print out a summary of every LOOP data), + or as a daemon. When first trying weewx, it's probably + best to run it from the command line because you will be able to see command + line diagnostics, as well as log messages.

+

Running from the command line

+

Weewx can easily be run from the command line. + Start by making sure you have appropriate permissions to the serial port your + weather station uses. For example, if you are using a plain old serial port:

+

sudo chmod 666 /dev/ttyS0

+

Then run the main loop program, weewxd.py, giving + the configuration file as its only parameter:

+

$WEEWX_ROOT/bin/weewxd.py $WEEWX_ROOT/weewx.conf

+

It should start by downloading any archive data from your weather station + into the database $WEEWX_ROOT/archive/weewx.sdb. + As the Davis VantagePro can store a couple thousand archive records internally, + this could take a minute or two. I've found this process particularly slow on + SuSE for some reason.

+

Weewx will then start monitoring LOOP data, printing + a short version of the received data on standard output, about once every two + seconds.

+

You can tell a running instance of weewx to reread + its configuration file by sending it the HUP signal. + First run ps to find out the Process ID (PID) number + of the instance, then send it the HUP signal:

+

ps -a         # Note + the PID of the weewxd.py process

+

kill -HUP pid # Send it a HUP signal

+

Running as a daemon

+

For unattended operations it is best to have weewx + run as a daemon, started automatically when the server is rebooted. Start by + selecting the appropriate run script. They can be found under + $WEEWX_ROOT/start_script.

+ + + + + + + + + +
SuSE:$WEEWX_ROOT/start_script/SuSE/weewx
Debian/Ubuntu:$WEEWX_ROOT/start_script/Debian/weewx
+

Check the chosen script to make sure the variable WEEWX_ROOT + inside has been set to the proper root directory for your + weewx installation (it should have been set to the correct value automatically + by the install process, but it's worth checking).

+

Copy it to the proper location for your system:

+ + + + + + + + + +
SuSE:cp $WEEWX_ROOT/start_script/SuSE/weewx /etc/init.d
Debian/Ubuntu:cp $WEEWX_ROOT/start_script/Debian/weewx /etc/init.d
+

Make sure the script is executable:

+ + + + + + + + + +
SuSE:chmod +x /etc/init.d/weewx
Debian/Ubuntu:chmod +x /etc/init.d/weewx
+

Create symbolic links in the run level directories:

+ + + + + + + + + +
SuSE:/usr/lib/lsb/install_initd /etc/init.d/weewx
Debian/Ubuntu:update-rc.d weewx defaults 98
+

Weewx will now start automatically whenever your + system is booted. You can also manually start, stop, and restart the + weewx daemon:

+

/etc/init.d/weewx start

+

/etc/init.d/weewx stop

+

/etc/init.d/weewx restart

+

By default, the scripts are designed to have weewx + run at run levels 2, 3, 4 and 5. Incidentally, a nice tool for setting run levels + with Debian (Ubuntu) systems is + sysv-rc-conf. It uses a curses + interface to allow you to change easily which run level any of your daemons + runs at. There is a similar tool on SuSE. From the start menu run the YAST Control + Center, then look for Systems Services (Runlevel). Pick "Expert" mode to see + the run levels.

+

You can also tell weewx to reread its configuration + file without stopping by using the 'reload' option:

+

/etc/init.d/weewx reload

+

Compatibility with + wview

+

The sqlite3 archive database used by weewx (nominally, + weewx.sdb) is completely compatible with the database + used by wview (usually called + wview-archive.sdb), at least as of wview Version 5.2.X. + The schema and its semantics is identical. However, the statistical file + stats.sdb is different, and must be rebuilt. This + will be done automatically on startup by weewx.

+

Monitoring weewx

+

Weewx logs many events to the system log. On Debian + systems, this is /var/log/syslog, on SuSE, + /var/log/messages. Your system may use yet another + place. When troubleshooting the system, be sure to check it!

+

Setting the option debug in + weewx.conf to 1 (one) will generate many more + checks and output and can be useful for debugging.

+

 Troubleshooting

+

If you get stuck, be sure to

+
    +
  • Set option debug in weewx.conf + to 1 (one)! It will put lots more information + in the log file, which can be very useful for troubleshooting and debugging!
  • +
  • Look at the log file. I am always happy + to take questions, but the first thing I will ask you is: "Did you look + at the log file?"
  • +
  • Run from the command line. Generally, weewx will catch and log any unrecoverable + exceptions. But if you are getting strange results, it is worth running + from the command line and looking for any clues.
  • +
+

 Execution

+

configobj errors

+

These are errors in the configuration file. Two are very common. Incidentally, + these errors are far easier to diagnose when weewx + is run from the command line.

+

configobj.DuplicateError exception

+

This error is caused by using an identifier more than once in the configuration + file. For example, you may have inadvertently listed your FTP server twice:

+
[Reports]
 	[[FTP]]
 		... (details elided)
 		user = fred
@@ -989,316 +873,323 @@ server twice:

server = ftp.myhost.com # OOPS! Listed it twice! path = /weather ...
-

Generally, if you encounter this error, the log file will give you the line -number it happened in:

-
Apr 24 12:09:15 raven weewx[11480]: wxengine: Error while parsing configuration file /home/weewx/weewx.conf
+	

Generally, if you encounter this error, the log file will give you the line + number it happened in:

+
Apr 24 12:09:15 raven weewx[11480]: wxengine: Error while parsing configuration file /home/weewx/weewx.conf
 Apr 24 12:09:15 raven weewx[11480]: wxengine: Unable to initialize main loop:
 Apr 24 12:09:15 raven weewx[11480]:     ****  Duplicate keyword name at line 254.
-Apr 24 12:09:15 raven weewx[11480]:     ****  Exiting. 
-

configobj.NestingError exception

-

This is a very similar error, and is caused by a misformed section nesting. -For example:

-
[Reports]
+Apr 24 12:09:15 raven weewx[11480]:     ****  Exiting. 
+

configobj.NestingError exception

+

This is a very similar error, and is caused by a misformed section nesting. + For example:

+
[Reports]
 	[[FTP]]]
 		... (details elided)
-

Note the extra closing bracket on the subsection FTP.

-

10.2 Hardware

-

Tips on a reliable system

-

If you are having problems keeping your weather station up for long periods -of time, here are some tips, in decreasing order of importance:

-
    -
  • Run on dedicated hardware. If you are using the server for other tasks, - particularly as your desktop machine, you will have reliability problems. If - you are using it as a print or network server, you will probably be OK.
  • -
  • Run headless. Modern graphical systems are extremely complex. As new - features are added, test suites don't always catch up. Your system will be - much more reliable if you run it without a windowing system (X Windows, in - the case of Linux).
  • -
  • Use an Uninterruptible Power Supply (UPS). The vast majority of power - glitches are very short lived — just a second or two — so you do not - need a big one. The 425 VA unit I use to protect my fit-PC cost me - $55 at Best Buy.
  • -
  • Use a VantagePro console with a serial connection, not a USB connection. See the - next section for details.
  • -
  • If you do use a USB connection, put a ferrite coil on each end of the - connection.
  • -
-

cp2101 converter problems

-

The USB converter used in the Davis VantagePro is known to have some "noise" -problems. The symptom is that the Linux kernel will disconnect from your old USB -port claiming "EMI noise", and reconnect to a new and different port, where -weewx can't find it. Here's -a typical log output:

-
Nov 29 10:40:21 hummingbird kernel: [6661624.786792] hub 2-0:1.0: port 3 disabled by hub (EMI?), re-enabling... 
+	

Note the extra closing bracket on the subsection FTP.

+

Hardware

+

Tips on a reliable system

+

If you are having problems keeping your weather station up for long periods + of time, here are some tips, in decreasing order of importance:

+
    +
  • Run on dedicated hardware. If you are using the server for other tasks, + particularly as your desktop machine, you will have reliability problems. + If you are using it as a print or network server, you will probably be OK.
  • +
  • Run headless. Modern graphical systems are extremely complex. As new + features are added, test suites don't always catch up. Your system will + be much more reliable if you run it without a windowing system (X Windows, + in the case of Linux).
  • +
  • Use an Uninterruptible Power Supply (UPS). The vast majority of power + glitches are very short lived — just a second or two — so you do not need + a big one. The 425 VA unit I use to protect my fit-PC cost me $55 at Best + Buy.
  • +
  • Use a VantagePro console with a serial connection, not a USB connection. + See the next section for details.
  • +
  • If you do use a USB connection, put a ferrite coil on each end of the + connection.
  • +
+

cp2101 converter problems

+

The USB converter used in the Davis VantagePro is known to have some "noise" + problems. The symptom is that the Linux kernel will disconnect from your old + USB port claiming "EMI noise", and reconnect to a new and different port, where + weewx can't find it. Here's a typical log output:

+
Nov 29 10:40:21 hummingbird kernel: [6661624.786792] hub 2-0:1.0: port 3 disabled by hub (EMI?), re-enabling... 
 Nov 29 10:40:21 hummingbird kernel: [6661624.786871] usb 2-3: USB disconnect, address 2 
 Nov 29 10:40:21 hummingbird kernel: [6661624.795778] cp2101 2-3:1.0: device disconnected 
 Nov 29 10:40:21 hummingbird weewx[25808]: VantagePro: Max retries exceeded while getting LOOP packets
-
 
-
... (messages elided)
-
 
-
Nov 29 10:40:22 hummingbird kernel: [6661625.352340] cp2101 2-3:1.0: cp2101 converter detected 
+	
 
+
... (messages elided)
+
 
+
Nov 29 10:40:22 hummingbird kernel: [6661625.352340] cp2101 2-3:1.0: cp2101 converter detected 
 Nov 29 10:40:22 hummingbird kernel: [6661625.528107] usb 2-3: reset full speed USB device using ohci_hcd and address 3 
 Nov 29 10:40:22 hummingbird kernel: [6661625.735497] usb 2-3: cp2101 converter now attached to ttyUSB1
-

In this example, the VantagePro was connected to -/dev/ttyUSB0, but then reconnected to /dev/ttyUSB1.

-

If you put ferrite coils on the USB connection, you will eliminate 90% of -this problem. I did this about 6 months ago, and have not had a problem since.

-

However, there is one final step you can take that will reallly harden up -your system: install a udev script that will create -a symbolic link to the VantagePro USB port, whatever it might be. With this -approach, if the port jumps from ttyUSB0 to -ttyUSB1, the symbolic link will move -as well. You just specify port /dev/vpro and be done with it. Here's how:

-

Installing a udev script

-

I have installed a file /etc/udev/rules.d/66-vpro.rules -on my fit-PC that looks like this:

-
# Automount the VantagePro2 to port /dev/vpro.
-
# Install in /etc/udev/rules.d/66-vpro.rules
-
#
-
ACTION=="add", ATTRS{interface}=="CP2102 USB to UART Bridge Controller", SYMLINK+="vpro"
-

What this rule says is that when the USB port is plugged in (action -add), and it has an attribute with name -interface that is equal to "CP2102 -USB to UART Bridge Controller", then add a symbolic link for its physical port -to /dev/vpro.

-

Your controller may have a different identifier!! I can recommend this -article, "Writing -udev rules," for how to find and write an -appropriate udev rule for your controller. (Note, -however, that this article uses the old udevinfo -command, rather than the newer udevadm command.) In -particular, run the command

-
# udevadm info --attribute-walk --path $(udevadm info --query=path --name=/dev/ttyUSB0) 
-

where /dev/ttyUSB0 is the port (substitute your -real USB port) the VP2 is attached to. It will print out various identifiers -that can be useful in identifying your VP2 to udev. -While the example script above used a rule that matched attribute -interface, others are possible. For example, you might -chose to match the attribute product.

-

Once you've installed your udev rule, you can then -set port=/dev/vpro in weewx.conf, -confident that it will always point to your VantagePro2, no matter which USB -port it is actually attached to!

-

I have tested this system many times. You can yank the USB port out of the -machine and then plug it back in while also pulling out the network connection -in the middle of an FTP upload: weewx will recover.

-

Or, at least, it should!

-

 

-

10.3 Templates

-

Cheetah.NameMapper.NotFound errors

-

If you get errors of the sort:

-
Apr 12 05:12:32 raven reportengine[3074]: filegenerator: Caught exception "<class 'NameMapper.NotFound'>" 
+	

In this example, the VantagePro was connected to /dev/ttyUSB0, + but then reconnected to /dev/ttyUSB1.

+

If you put ferrite coils on the USB connection, you will eliminate 90% of + this problem. I did this about 6 months ago, and have not had a problem since. +

+

However, there is one final step you can take that will reallly harden up + your system: install a udev script that will create + a symbolic link to the VantagePro USB port, whatever it might be. With this + approach, if the port jumps from ttyUSB0 to + ttyUSB1, the symbolic link will move as well. You + just specify port /dev/vpro and be done with it. Here's + how:

+

Installing a udev script

+

I have installed a file /etc/udev/rules.d/66-vpro.rules + on my fit-PC that looks like this:

+
# Automount the VantagePro2 to port /dev/vpro.
+
# Install in /etc/udev/rules.d/66-vpro.rules
+
#
+
ACTION=="add", ATTRS{interface}=="CP2102 USB to UART Bridge Controller", SYMLINK+="vpro"
+

What this rule says is that when the USB port is plugged in (action + add), and it has an attribute with name + interface that is equal to "CP2102 + USB to UART Bridge Controller", then add a symbolic link for its physical + port to /dev/vpro.

+

Your controller may have a different identifier!! I can recommend this article, + "Writing udev + rules," for how to find and write an appropriate + udev rule for your controller. (Note, however, that + this article uses the old udevinfo command, rather + than the newer udevadm command.) In particular, run + the command

+
# udevadm info --attribute-walk --path $(udevadm info --query=path --name=/dev/ttyUSB0) 
+

where /dev/ttyUSB0 is the port (substitute your + real USB port) the VP2 is attached to. It will print out various identifiers + that can be useful in identifying your VP2 to udev. + While the example script above used a rule that matched attribute + interface, others are possible. For example, you might + chose to match the attribute product.

+

Once you've installed your udev rule, you can then + set port=/dev/vpro in weewx.conf, + confident that it will always point to your VantagePro2, no matter which USB + port it is actually attached to!

+

I have tested this system many times. You can yank the USB port out of the + machine and then plug it back in while also pulling out the network connection + in the middle of an FTP upload: weewx will recover.

+

Or, at least, it should!

+

 

+

 Templates

+

Cheetah.NameMapper.NotFound errors

+

If you get errors of the sort:

+
Apr 12 05:12:32 raven reportengine[3074]: filegenerator: Caught exception "<class 'NameMapper.NotFound'>" 
 Apr 12 05:12:32 raven reportengine[3074]:          ****  Message: "cannot find 'fubar' in template /home/weewx/skins/Standard/index.html.tmpl"
 Apr 12 05:12:32 raven reportengine[3074]:          ****  Ignoring template and continuing.
-

you have a tag in your template that weewx -does not recognize (in this example, it's the tag $fubar -in the template /home/weewx/skins/Standard/index.html.tmpl.

-

11. Architectural notes

-

This section is not needed to get started.

-

11.1 Goals

-

The primary goals of weewx are:

-
    -
  • Architectural simplicity. No semaphores, no named pipes, no inter-process - communications, no complex multi-threading to manage.
  • -
  • "Fast enough." In any design decision, architectural simplicity - and elegance trumps speed. -
  • -
  • One code base. The same code base should be used for all platforms, all - weather stations, all reports, and any combination of features. Ample configuration - and customization options should be provided so the user doesn't feel tempted - to start hacking code. At worse, the user may have to subclass, which is much - easier to port to newer versions of the code base, than customizing the base - code.
  • -
  • Minimal reliance on external packages, so the user doesn't have to go chase - them down all over the Web before getting started.
  • -
  • Support only the Davis VantagePro2 initially (that's what I have), but make - no architectural decisions that lock out other stations.
  • -
  • As "pythonic" as I know how to make it. I'm a beginner Python programmer - with two decades of experience in C++. I tried hard to not make the code base - look like it was written by a C++ programmer who stumbled across a Python manual!
  • -
-

11.2 Strategies

-

To meet these goals, the following strategies were used:

-
    -
  • A "micro-kernel" design. The actual internal engine does very little. - It's main job is to load and run services at runtime, making it easy for users to add or subtract features.
  • -
  • A largely stateless design style. For example, many of the processing routines - read their own data from the database, rather than caching it and sharing with - other processing routines. While this means the same data may be read multiple - times, it also means the only point of possible cache incoherence is through - the database, where transactions are easily controlled. This greatly reduces - the chances of corrupting the data, making it much easier to understand and - modify the code base.
  • -
  • Isolate the data collection and archiving code in a single thread that - is simple enough that it is unlikely to crash. The report - processing is where most mistakes are likely to happen, so isolate that in a - separate thread. If it crashes, it will not affect the main data thread.
  • -
  • A powerful configuration parser, - ConfigObj, by - Michael Foord and Nicola Larosa, was chosen to read the configuration file. - This allows many options that might otherwise have to go in the code to go instead - in a configuration file.
  • -
  • A powerful templating engine, - Cheetah, was used. This allows many variables that I may not have thought - of to be accessed from within the HTML templates, without starting to modify - the code.
  • -
  • Pure Python. The code base is 100% Python — no underlying C libraries need - be built to install weewx. This also means no Makefiles - are needed.
  • -
-

While weewx is nowhere near as fast at generating images -and HTML as its predecessor, wview (this is partially -because it uses fancier fonts and a much more powerful templating engine), it is -'fast enough' for all platforms but the slowest. I run it regularly on a 500 MHz -machine where generating the 9 images used in the "Current Conditions" page takes -just under 2 seconds (compared with wview's 0.4 seconds). -

-

Unfortunately, the architectural goal of one code base is likely to be broken -with the arrival of Python V3.X. It has so many changes that are not backwards compatible -with V2.X, that a separate code base will most likely be needed. My intention is -to stick with the V2.5 and V2.6 versions until V3.X is so widespread it cannot be -ignored, then make a permanent switch. I doubt this will affect the average -weewx user.

-

All writes to the databases are protected by transactions. You can kill the program -at any time (either Control-C if run from the command line or "/etc/init.d/weewx -stop" if a daemon) without fear of corrupting the databases.

-

The code makes ample use of exceptions to insure graceful recovery from problems -such as network outages. It also monitors socket and console timeouts, restarting -whatever it was working on several times before giving up. In the case of an unrecoverable -console error (such as the console not responding at all), the program waits 60 -seconds then restarts the program from the top.

-

Any "hard" exceptions, that is those that do not involve network and console -timeouts and are most likely due to a logic error, are logged, reraised, and ultimately -cause thread termination. If this happens in the main thread (not likely due to -its simplicity), then this causes program termination. If it happens in the -report processing thread (much more likely), then only the generation of reports -will be affected — the main thread will continue downloading data off the -instrument and putting them in the database. You can fix the problem at your -leisure, without worrying about losing any data.

-

11.3 Terminology

-

This is a glossary of terminology used throughout the code.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
packetSomething obtained off the weather station. Frequently uses a complex - internal encoding, so it requires some processing to be useful.
recordSomething obtained off the SQL database.
archive packetA packet obtained off the store on the weather station. For example, - with a Davis VantagePro, it's obtained using their DMPAFT - command.
loop packetA packet with the current observations. For example, with a Davis VantagePro, - it's obtained using their LOOP command.
archive recordA record obtained off the SQL database
tuple-timeAn instance of the Python object time.struct_time. - This is a 9-wise tuple that represent a time. It could be in either local - time or UTC, though usually the former. See module time - for more information. They are useful because they are a little closer in - format to what the Davis VantagePro uses, although they still require a - bit of processing. Variables carrying tuple time usually have a suffix '_tt'.
epoch timeSometimes referred to as "unix time," or "unix epoch time." The number - of seconds since the epoch, which is 1 Jan 1970 00:00:00 UTC. Hence, it - always represents UTC (well.... after adding a few leap seconds. But, close - enough). This is the time used on the sqlite archive and appears as type - 'dateTime' in the SQL schema, perhaps an unfortunate - name because of the similarity to the Python type 'datetime'. Very easy - to manipulate, but it's an opaque big number.
time stampA variable in unix epoch time. Always in UTC. Variables carrying a time - stamp usually have a suffix '_ts'.
datetimeAn instance of the Python object datetime.datetime. - Variables of type datetime usually have a suffix '_dt'.
SQL typeA type that appears in the SQL database. This usually looks something - like 'outTemp', 'barometer', - 'extraTemp1', and so on.
observation typeA type that can be used in the presentations. This is generally all - of the SQL types, plus calculated data (such as rms - or vecavg).
value tupleA 3-way tuple. First element is a value, second element the unit - type the value is in, the third the unit group. An example would be (21.2, - 'degree_C', 'group_temperature').
-

11.4 Units

-

In general, there are three different areas where the unit system makes a difference.: -

-
    -
  1. On the weather station. As far as I know, the Davis VantagePro series supports - only U.S. Customary units internally.
  2. -
  3. In the database. The unit system of any individual record is indicated by - the "usUnits" field. The numerical value 1 indicates - U.S. Customary, 2 indicates Metric.
  4. -
  5. In the presentation (i.e., html and image files).
  6. -
-

The general strategy is that measurements are stored internally in the native -measurement system of the weather instrument. That is, the units used in #1 and -#2 are always the same. With Version 1.5, weewx supports translations between #2 -and #3, allowing any unit system to be used in the presentation layer.

-

It would be easy enough to support an instrument that uses metric units internally, -although this has not been done yet.

-

11.5 Value "None"

-

The Python special value 'None' is used throughout -to signal a missing data point. All functions expect it.

-

However, the time value must never be 'None'. This -is because it is used as the primary key in the SQL database.

-

11.6 Time

-

Weewx stores all data in UTC (roughly, "Greenwich" -or "Zulu") time. However, usually one is interested in weather events in local time -and want image and HTML generation to reflect that. Furthermore, most weather stations -are configured in local time. This requires that many data times be converted back -and forth between UTC and local time. To avoid tripping up over time zones and daylight -savings time, weewx generally uses Python routines to -do this conversion. Nowhere in the code base is there any explicit recognition of -DST. Instead, its presence is implicit in the conversions. At times, this can cause -the code to be relatively inefficient.

-

For example, if one wanted to plot something every 3 hours in UTC time, it would -be very simple: to get the next plot point, just add 10,800 to the epoch time:

-

next_ts = last_ts + 10800

-

But, if one wanted to plot something for every 3 hours in local time -(that is, at 0000, 0300, 0600, etc.), despite a possible DST change in the middle, -one could modify the above to recognize whether a DST transition occurs sometime -between last_ts and the next three hours and, if so, make -the necessary adjustments. This is generally what wview -does. Weewx takes a different approach and converts from -UTC to local, does the arithmetic, then converts back. This is inefficient, but -bulletproof against changes in DST algorithms, etc:

-

time_dt = datetime.datetime.fromtimestamp(last_ts)

-

delta = datetime.timedelta(seconds=10800)

-

next_dt = time_dt + delta

-

next_ts = int(time.mktime(next_dt.timetuple()))

-

Other time conversion problems are handled in a similar manner.

-

 

+

you have a tag in your template that weewx does + not recognize (in this example, it's the tag $fubar + in the template /home/weewx/skins/Standard/index.html.tmpl.

+

 Architectural notes

+

This section is not needed to get started.

+

Goals

+

The primary goals of weewx are:

+
    +
  • Architectural simplicity. No semaphores, no named pipes, no inter-process + communications, no complex multi-threading to manage.
  • +
  • "Fast enough." In any design decision, architectural simplicity and + elegance trumps speed.
  • +
  • One code base. The same code base should be used for all platforms, + all weather stations, all reports, and any combination of features. Ample + configuration and customization options should be provided so the user doesn't + feel tempted to start hacking code. At worse, the user may have to subclass, + which is much easier to port to newer versions of the code base, than customizing + the base code.
  • +
  • Minimal reliance on external packages, so the user doesn't have to go + chase them down all over the Web before getting started.
  • +
  • Support only the Davis VantagePro2 initially (that's what I have), but + make no architectural decisions that lock out other stations.
  • +
  • As "pythonic" as I know how to make it. I'm a beginner Python programmer + with two decades of experience in C++. I tried hard to not make the code + base look like it was written by a C++ programmer who stumbled across a + Python manual!
  • +
+

Strategies

+

To meet these goals, the following strategies were used:

+
    +
  • A "micro-kernel" design. The actual internal engine does very little. + It's main job is to load and run services at runtime, making it + easy for users to add or subtract features.
  • +
  • A largely stateless design style. For example, many of the processing + routines read their own data from the database, rather than caching it and + sharing with other processing routines. While this means the same data may + be read multiple times, it also means the only point of possible cache incoherence + is through the database, where transactions are easily controlled. This + greatly reduces the chances of corrupting the data, making it much easier + to understand and modify the code base.
  • +
  • Isolate the data collection and archiving code in a single thread that + is simple enough that it is unlikely to crash. The report processing is + where most mistakes are likely to happen, so isolate that in a separate + thread. If it crashes, it will not affect the main data thread.
  • +
  • A powerful configuration parser, + ConfigObj, + by Michael Foord and Nicola Larosa, was chosen to read the configuration + file. This allows many options that might otherwise have to go in the code + to go instead in a configuration file.
  • +
  • A powerful templating engine, + Cheetah, was used. This allows + many variables that I may not have thought of to be accessed from within + the HTML templates, without starting to modify the code.
  • +
  • Pure Python. The code base is 100% Python — no underlying C libraries + need be built to install weewx. This also means + no Makefiles are needed.
  • +
+

While weewx is nowhere near as fast at generating + images and HTML as its predecessor, wview (this is + partially because it uses fancier fonts and a much more powerful templating + engine), it is 'fast enough' for all platforms but the slowest. I run it regularly + on a 500 MHz machine where generating the 9 images used in the "Current Conditions" + page takes just under 2 seconds (compared with wview's + 0.4 seconds).

+

Unfortunately, the architectural goal of one code base is likely to be broken + with the arrival of Python V3.X. It has so many changes that are not backwards + compatible with V2.X, that a separate code base will most likely be needed. + My intention is to stick with the V2.5 and V2.6 versions until V3.X is so widespread + it cannot be ignored, then make a permanent switch. I doubt this will affect + the average weewx user.

+

All writes to the databases are protected by transactions. You can kill the + program at any time (either Control-C if run from the command line or "/etc/init.d/weewx + stop" if a daemon) without fear of corrupting the databases.

+

The code makes ample use of exceptions to insure graceful recovery from problems + such as network outages. It also monitors socket and console timeouts, restarting + whatever it was working on several times before giving up. In the case of an + unrecoverable console error (such as the console not responding at all), the + program waits 60 seconds then restarts the program from the top.

+

Any "hard" exceptions, that is those that do not involve network and console + timeouts and are most likely due to a logic error, are logged, reraised, and + ultimately cause thread termination. If this happens in the main thread (not + likely due to its simplicity), then this causes program termination. If it happens + in the report processing thread (much more likely), then only the generation + of reports will be affected — the main thread will continue downloading data + off the instrument and putting them in the database. You can fix the problem + at your leisure, without worrying about losing any data.

+

Terminology

+

This is a glossary of terminology used throughout the code.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
packetSomething obtained off the weather station. Frequently uses a complex + internal encoding, so it requires some processing to be useful.
recordSomething obtained off the SQL database.
archive packetA packet obtained off the store on the weather station. For example, + with a Davis VantagePro, it's obtained using their + DMPAFT command.
loop packetA packet with the current observations. For example, with a Davis + VantagePro, it's obtained using their LOOP + command.
archive recordA record obtained off the SQL database
tuple-timeAn instance of the Python object time.struct_time. + This is a 9-wise tuple that represent a time. It could be in either + local time or UTC, though usually the former. See module + time for more information. They are useful + because they are a little closer in format to what the Davis VantagePro + uses, although they still require a bit of processing. Variables carrying + tuple time usually have a suffix '_tt'.
epoch timeSometimes referred to as "unix time," or "unix epoch time." The + number of seconds since the epoch, which is 1 Jan 1970 00:00:00 UTC. + Hence, it always represents UTC (well.... after adding a few leap seconds. + But, close enough). This is the time used on the sqlite archive and + appears as type 'dateTime' in the SQL schema, + perhaps an unfortunate name because of the similarity to the Python + type 'datetime'. Very easy to manipulate, but it's an opaque big number. +
time stampA variable in unix epoch time. Always in UTC. Variables carrying + a time stamp usually have a suffix '_ts'.
datetimeAn instance of the Python object datetime.datetime. + Variables of type datetime usually have a suffix '_dt'.
SQL typeA type that appears in the SQL database. This usually looks something + like 'outTemp', 'barometer', + 'extraTemp1', and so on.
observation typeA type that can be used in the presentations. This is generally + all of the SQL types, plus calculated data (such as + rms or vecavg).
value tupleA 3-way tuple. First element is a value, second element the unit + type the value is in, the third the unit group. An example would be + (21.2, 'degree_C', 'group_temperature').
+

 Units

+

In general, there are three different areas where the unit system makes a + difference.:

+
    +
  1. On the weather station. As far as I know, the Davis VantagePro series + supports only U.S. Customary units internally.
  2. +
  3. In the database. The unit system of any individual record is indicated + by the "usUnits" field. The numerical value 1 + indicates U.S. Customary, 2 indicates Metric.
  4. +
  5. In the presentation (i.e., html and image files).
  6. +
+

The general strategy is that measurements are stored internally in the native + measurement system of the weather instrument. That is, the units used in #1 + and #2 are always the same. With Version 1.5, weewx supports translations between + #2 and #3, allowing any unit system to be used in the presentation layer.

+

It would be easy enough to support an instrument that uses metric units internally, + although this has not been done yet.

+

Value "None"

+

The Python special value 'None' is used throughout + to signal a missing data point. All functions expect it.

+

However, the time value must never be 'None'. This + is because it is used as the primary key in the SQL database.

+

Time

+

Weewx stores all data in UTC (roughly, "Greenwich" + or "Zulu") time. However, usually one is interested in weather events in local + time and want image and HTML generation to reflect that. Furthermore, most weather + stations are configured in local time. This requires that many data times be + converted back and forth between UTC and local time. To avoid tripping up over + time zones and daylight savings time, weewx generally + uses Python routines to do this conversion. Nowhere in the code base is there + any explicit recognition of DST. Instead, its presence is implicit in the conversions. + At times, this can cause the code to be relatively inefficient.

+

For example, if one wanted to plot something every 3 hours in UTC time, it + would be very simple: to get the next plot point, just add 10,800 to the epoch + time:

+

next_ts = last_ts + 10800

+

But, if one wanted to plot something for every 3 hours in local time + (that is, at 0000, 0300, 0600, etc.), despite a possible DST change in the middle, + one could modify the above to recognize whether a DST transition occurs sometime + between last_ts and the next three hours and, if so, + make the necessary adjustments. This is generally what wview + does. Weewx takes a different approach and converts + from UTC to local, does the arithmetic, then converts back. This is inefficient, + but bulletproof against changes in DST algorithms, etc:

+

time_dt = datetime.datetime.fromtimestamp(last_ts)

+

delta = datetime.timedelta(seconds=10800)

+

next_dt = time_dt + delta

+

next_ts = int(time.mktime(next_dt.timetuple()))

+

Other time conversion problems are handled in a similar manner.

+

 

+
diff --git a/docs/samaxesjs.toc-1.3.2.js b/docs/samaxesjs.toc-1.3.2.js new file mode 100644 index 00000000..207654a1 --- /dev/null +++ b/docs/samaxesjs.toc-1.3.2.js @@ -0,0 +1,256 @@ +/*! + * samaxesJS JavaScript Library + * http://code.google.com/p/samaxesjs/ + * + * Copyright (c) 2010 samaxes.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @projectDescription samaxesJS JavaScript Library. + * @author Samuel Santos + * @namespace samaxesJS + * @type {Object} + */ +var samaxesJS = { + /** + * Logging and debugging. + * @param {Object} obj The object to log. + */ + debug: function(obj) { + if (window.console && window.console.log) { + window.console.log(obj); + } + }, + /** + * Adds a load event handler to the target object. + * @param {Function} func Function to add a load event handler. + */ + addLoadEvent: function(func) { + var oldonload = window.onload; + if (typeof window.onload != 'function') { + window.onload = func; + } else { + window.onload = function() { + if (oldonload) { + oldonload(); + } + func(); + }; + } + }, + /** + * Used for trimming whitespace. + * @param {String} str The String to trim. + * @return {String} The trimmed string. + */ + trim: function(str) { + return (str || '').replace(/^(\s|\u00A0)+|(\s|\u00A0)+$/g, ''); + }, + /** + * Used for getting the size of an associative array. + * @param {Object} obj Associative array to check size. + * @return {Number} The size of the associative array. + */ + size: function(obj) { + var size = 0, key; + + for (key in obj) { + if (obj.hasOwnProperty(key)) { + size++; + } + } + + return size; + }, + /** + * Used for getting only the direct decendents of an element node by tag name. + * @param {Object} parent The parent node element. + * @param {String} node The node name. + * @return {Array} The direct decendents of an element node. + */ + getDirectElementsByTagName: function(parent, node) { + var directElementsByTagName = []; + var children = parent.childNodes; + var length = children.length; + + for (var i = 0; i < length; i++) { + // nodeType === 1 --> Node.ELEMENT_NODE + if (children[i].nodeType === 1 && children[i].nodeName.match(new RegExp(node, 'i'))) { + directElementsByTagName.push(children[i]); + } + } + + return directElementsByTagName; + } +}; + +/*! + * TOC JavaScript Library v1.3.2 + */ + +/** + * The TOC control dynamically builds a table of contents from the headings in + * a document and prepends legal-style section numbers to each of the headings. + * @namespace samaxesJS.toc + */ +samaxesJS.toc = function() { + var document = this.document; + + /** + * Creates a TOC element link. + * @private + * @param {String} nodeId The node id attribute. + * @param {String} innerHTML The node text. + * @return {HTMLElement} The element link. + */ + function createLink(nodeId, innerHTML) { + var a = document.createElement('a'); + if (nodeId !== '') { + a.setAttribute('href', '#' + nodeId); + } + a.innerHTML = innerHTML; + return a; + } + + /** + * Checks if the last node is a ul element. If not, a new one is created. + * @private + * @param {Number} header The heading counter. + * @param {Object} toc The container element. + */ + function checkContainer(header, toc) { + if (header === 0 && toc.getElementsByTagName('li').length > 0 && + !toc.getElementsByTagName('li')[toc.getElementsByTagName('li').length - 1].lastChild.nodeName.match(new RegExp('ul', 'i'))) { + toc.getElementsByTagName('li')[toc.getElementsByTagName('li').length - 1].appendChild(document.createElement('ul')); + } + } + + /** + * Updates headers numeration. + * @private + * @param {Object} headers The heading counters associative array. + * @param {String} header The heading element node name. + */ + function updateNumeration(headers, header) { + for (var i = 1; i <= samaxesJS.size(headers); i++) { + if ('h' + i === header) { + ++headers['h' + i]; + } else if ('h' + i > header) { + headers['h' + i] = 0; + } + } + } + + /** + * Generate an anchor id from a string by replacing unwanted characters. + * @private + * @param {String} text The original string. + * @return {String} The string without any unwanted characters. + */ + function generateId(text) { + return text.replace(/[ <#\/\\?&]/g, '_'); + } + + /** + * Prepends the numeration to a heading. + * @private + * @param {Object} headers The heading counters associative array. + * @param {String} header The heading element node name. + * @param {String} innerHTML The node text. + * @return {String} The heading element with section heading prepended. + */ + function addNumeration(headers, header, text) { + var numeration = ''; + + for (var i = 1; i <= samaxesJS.size(headers); i++) { + if ('h' + i <= header && headers['h' + i] > 0) { + numeration += headers['h' + i] + '.'; + } + } + + return numeration + ' ' + text; + } + + /** + * Appends a new node to the TOC. + * @private + * @param {Object} toc The container element. + * @param {Number} index The heading element index. + * @param {String} id The node id attribute. + * @param {String} text The node text. + */ + function appendToTOC(toc, index, id, text) { + var parent = toc; + + for (var i = 1; i < index; i++) { + if (samaxesJS.getDirectElementsByTagName(parent, 'li').length > 0) { + /*if (samaxesJS.getDirectElementsByTagName(samaxesJS.getDirectElementsByTagName(parent, 'li')[samaxesJS.getDirectElementsByTagName(parent, 'li').length - 1], 'ul').length === 0) { + parent.appendChild(document.createElement('li')).appendChild(document.createElement('ul')); + }*/ + parent = samaxesJS.getDirectElementsByTagName(parent, 'li')[samaxesJS.getDirectElementsByTagName(parent, 'li').length - 1].getElementsByTagName('ul')[0]; + } + } + + if (id == null) { + parent.appendChild(document.createElement('li')).innerHTML = text; + } else { + parent.appendChild(document.createElement('li')).appendChild(createLink(id, text)); + } + } + + return function(options) { + samaxesJS.addLoadEvent(function() { + var headers = []; + var context = (options && options.context) ? document.getElementById(options.context) : document.body; + var autoId = options && options.autoId; + var nodes = context.getElementsByTagName('*'); + var exclude = (!options || options.exclude === undefined) ? 'h1, h5, h6' : options.exclude; + for (var node in nodes) { + if (/h\d/i.test(nodes[node].nodeName) && !exclude.match(new RegExp(nodes[node].nodeName, 'i'))) { + headers.push(nodes[node]); + } + } + + if (headers.length > 0) { + var toc = document.getElementById((options && options.container) || 'toc').appendChild(document.createElement('ul')); + + var index = 0; + var headersNumber = {h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0}; + var indexes = {h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0}; + for (var i = 1; i <= 6; i++) { + indexes['h' + i] = (exclude.match(new RegExp('h' + i, 'i')) === null && document.getElementsByTagName('h' + i).length > 0) ? ++index : 0; + } + + for (var header in headers) { + try { + for (var i = 6; i >= 1; i--) { + if (headers[header].nodeName.match(new RegExp('h' + i, 'i'))) { + checkContainer(headersNumber['h' + i], toc); + updateNumeration(headersNumber, 'h' + i); + if (autoId && !headers[header].getAttribute('id')) { + headers[header].setAttribute('id', generateId(headers[header].innerHTML)); + } + headers[header].innerHTML = addNumeration(headersNumber, 'h' + i, headers[header].innerHTML); + appendToTOC(toc, indexes['h' + i], headers[header].getAttribute('id'), headers[header].innerHTML); + } + } + } catch (error) { + samaxesJS.debug('Error message: ' + error.message); + } + } + } + }); + }; +}(); diff --git a/docs/samaxesjs.toc-1.3.2.min.js b/docs/samaxesjs.toc-1.3.2.min.js new file mode 100644 index 00000000..7899c7cf --- /dev/null +++ b/docs/samaxesjs.toc-1.3.2.min.js @@ -0,0 +1,23 @@ +/* + * samaxesJS JavaScript Library + * http://code.google.com/p/samaxesjs/ + * + * Copyright (c) 2010 samaxes.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var samaxesJS={debug:function(a){if(window.console&&window.console.log){window.console.log(a)}},addLoadEvent:function(a){var b=window.onload;if(typeof window.onload!="function"){window.onload=a}else{window.onload=function(){if(b){b()}a()}}},trim:function(a){return(a||"").replace(/^(\s|\u00A0)+|(\s|\u00A0)+$/g,"")},size:function(c){var b=0,a;for(a in c){if(c.hasOwnProperty(a)){b++}}return b},getDirectElementsByTagName:function(c,e){var f=[];var b=c.childNodes;var d=b.length;for(var a=0;a0&&!h.getElementsByTagName("li")[h.getElementsByTagName("li").length-1].lastChild.nodeName.match(new RegExp("ul","i"))){h.getElementsByTagName("li")[h.getElementsByTagName("li").length-1].appendChild(a.createElement("ul"))}}function d(j,k){for(var h=1;h<=samaxesJS.size(j);h++){if("h"+h===k){++j["h"+h]}else{if("h"+h>k){j["h"+h]=0}}}}function b(h){return h.replace(/[ <#\/\\?&]/g,"_")}function g(l,m,k){var h="";for(var j=1;j<=samaxesJS.size(l);j++){if("h"+j<=m&&l["h"+j]>0){h+=l["h"+j]+"."}}return h+" "+k}function f(n,h,m,l){var k=n;for(var j=1;j0){k=samaxesJS.getDirectElementsByTagName(k,"li")[samaxesJS.getDirectElementsByTagName(k,"li").length-1].getElementsByTagName("ul")[0]}}if(m==null){k.appendChild(a.createElement("li")).innerHTML=l}else{k.appendChild(a.createElement("li")).appendChild(e(m,l))}}return function(h){samaxesJS.addLoadEvent(function(){var n=[];var k=(h&&h.context)?a.getElementById(h.context):a.body;var v=h&&h.autoId;var j=k.getElementsByTagName("*");var l=(!h||h.exclude===undefined)?"h1, h5, h6":h.exclude;for(var o in j){if(/h\d/i.test(j[o].nodeName)&&!l.match(new RegExp(j[o].nodeName,"i"))){n.push(j[o])}}if(n.length>0){var p=a.getElementById((h&&h.container)||"toc").appendChild(a.createElement("ul"));var t=0;var m={h1:0,h2:0,h3:0,h4:0,h5:0,h6:0};var s={h1:0,h2:0,h3:0,h4:0,h5:0,h6:0};for(var q=1;q<=6;q++){s["h"+q]=(l.match(new RegExp("h"+q,"i"))===null&&a.getElementsByTagName("h"+q).length>0)?++t:0}for(var r in n){try{for(var q=6;q>=1;q--){if(n[r].nodeName.match(new RegExp("h"+q,"i"))){c(m["h"+q],p);d(m,"h"+q);if(v&&!n[r].getAttribute("id")){n[r].setAttribute("id",b(n[r].innerHTML))}n[r].innerHTML=g(m,"h"+q,n[r].innerHTML);f(p,s["h"+q],n[r].getAttribute("id"),n[r].innerHTML)}}}catch(u){samaxesJS.debug("Error message: "+u.message)}}}})}}(); \ No newline at end of file diff --git a/docs/sheeva.htm b/docs/sheeva.htm index 5ff51300..c175a5e8 100644 --- a/docs/sheeva.htm +++ b/docs/sheeva.htm @@ -7,133 +7,8 @@ Porting to the SheevaPlug - + + diff --git a/docs/upgrading.htm b/docs/upgrading.htm index ac8da3be..be90db76 100644 --- a/docs/upgrading.htm +++ b/docs/upgrading.htm @@ -7,133 +7,8 @@ Upgrading weewx - + + diff --git a/docs/weewx_docs.css b/docs/weewx_docs.css new file mode 100644 index 00000000..ede30e42 --- /dev/null +++ b/docs/weewx_docs.css @@ -0,0 +1,144 @@ +/* + * $Revision$ + * $Author$ + * $Date$ + */ + +body { + font: 11pt Verdana,arial,sans-serif; + color: black; +} +p { + font: 11pt Verdana,arial,sans-serif; + color: black; +} +ol { + font: 11pt Verdana,arial,sans-serif; + color: black; +} +ul { + font: 11pt Verdana,arial,sans-serif; + color: black; +} +li { + font: 11pt Verdana,arial,sans-serif; + color: black; +} +dl { + font: 11pt Verdana,arial,sans-serif; + color: black; +} +dt { + font: 11pt Verdana,arial,sans-serif; + color: black; +} +dd { + font: 11pt Verdana,arial,sans-serif; + color: black; +} +h1 { + font: bold xx-large Verdana, arial, sans-serif; + color: #FFFFFF; + border: 1px solid black; + border-bottom: 2px solid black; + border-right: 2px solid black; + background-color: #008080; + padding-left: .5em; + padding-right: .5em; + margin-top: 60pt; + border-right-width: medium; + border-bottom-width: medium; +} +h2 { + font: bold x-large Verdana, arial, sans-serif; + color: teal; + border: 1px solid black; + background-color: #e8e8e8; + padding-left: .5em; + padding-right: .5em; + margin-top: 30pt; +} +h3 { + font: bold medium Verdana, arial, sans-serif; + color: teal; + border: 1px solid black; + background-color: #e8e8e8; + padding-left: .5em; + padding-right: .5em; +} +h4 { + font: bold medium Verdana, arial, sans-serif; + color: black; + text-decoration: underline; +} +.code { + font-family: "Courier New", Courier, monospace; +} +table { + border-style: solid; + border-width: 1px; + border-collapse: collapse; +} +td { + border-style: solid; + border-width: 1px; + padding: 5px; +} +.indent { + margin-left: 40px; +} +.tty, pre { + font-family: "Courier New", Courier, monospace; + margin-left: 40px; + margin-top: 0px; + margin-bottom: 0px; + background-color: #FFFFCC; +} +.title { + text-align: center; + margin-top: 0px; +} +.config_option { + font-family: "Courier New", Courier, monospace; + font-weight: bold; +} +.config_section { + font-family: "Courier New", Courier, monospace; + font-weight: bold; +} +.config_important { + font-family: "Courier New", Courier, monospace; + font-weight: bold; + color: #0000FF; +} +.bold_n_blue { + color: #0000FF; +} +.xxsmall { + font-size: xx-small; +} +.highlight { + background-color: #FFFF66; +} +.center { + text-align: center; +} +.Example_output { + padding: 10px; + border: thin #000000 dotted; + font-family: "Times New Roman", Times, serif; + margin-left: 40px; +} +.style1 { + border-style: solid; +} + +div#toc ul { + list-style: none; +} +div#toc ul li ul { + margin-bottom: 0.75em; +} +div#toc ul li ul li ul { + margin-bottom: 0.25em; +}