- This document covers the customization of WeeWX. - It assumes that you have read, and are reasonably familiar with, - the Users Guide. -
- -Introduction
- -- This document 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.conf - . 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.
- -Most of the guide applies to any hardware, but the exact - data types are hardware-specific. Many examples use types - specific to the Davis Vantage series. Unless you are using an - unusual type you are unlikely to run into trouble.
- -
- Warning!
WeeWX
- is still an experimental system and, as such, its internal
- design is subject to change. Future upgrades may break any
- customizations you have done, particularly if they involve the
- API (skin customizations tend to be more stable).
-
Where to put customizations
- -- For configuration changes, simply modify the WeeWX - configuration file weewx.conf. - Customization of reports may require changes to a skin - configuration file skin.conf or - template files ending in .tmpl. The weewx.conf configuration file and the skin.conf configuration and template files - in the skins directory will be - preserved when you upgrade. -
- -Other customizations require new Python code or - modifications of example code. Where should you put the code? If - you simply modify the examples in place, then your changes will - be overwritten the next time you do an upgrade.
- -- A better idea is to put the code in the user, - directory. For example, copy example code from the examples directory to the user directory, then modify it there. If - your modification does not contain much code, consider putting - it in the file extensions.py in the user directory. Because the user directory is preserved through - upgrades, you won't have to redo any changes you might have - made. -
- -Data architecture
- -- WeeWX is data-driven. When the sensors spit out some data, WeeWX - does something. The 'something' - might be to print out the data, or to generate an HTML report, - or to use FTP to copy a report to a web server, or to perform - some calculations using the data. These actions are called - services. -
- -- A driver is Python code that communicates with the hardware. The - driver reads data from a serial port or a device on the USB or a - network interface. It handles any decoding of raw bits and - bytes, and puts the resulting data into LOOP packets and archive - RECORDs. Whenever possible, WeeWX - should work "out of the box" with minimal configuration. - However, in some cases the driver may include code to configure - and test the hardware, typically via the wee_device - utility. -
- -- In many cases there are useful dependent variables that use the - primary variables emitted by the driver. For example, rain rate, - windchill, heatindex, humidex, apptemp, ET are all dependent - quantities — they require primary observations such as - wind speed, temperature, solar radiation. The firmware for some - hardware calculates dependent quantities. The WeeWX - service StdWXCalculate fills in the - gaps and determines whether to use a value from firmware or a - calculation from WeeWX. Sometimes the - firmware simply does it wrong. -
- -- LOOP packets vs. archive records -
- -Generally, there are two types of data that flow through - WeeWX: LOOP packets, and archive records.
- -LOOP packets
-- LOOP packets are the raw data generated by the device driver. - They get their name from the Davis Instruments documentation. - For some devices they are generated at rigid intervals, such as - every 2 seconds for the Davis Vantage series, for others, - irregularly, every 20 or 30 seconds or so. LOOP packets may or - may not contain all the data types. For example, a packet may - contain only temperature data, another only barometric data, etc. - These kinds of packet are called partial record packets. - By contrast, other types of hardware (notably the Vantage - series), every LOOP packet contains every data type. -
- -In summary, LOOP packets can be highly irregular, but they - come in frequently.
- -Archive records
- -- By contrast, archive records are highly regular. They are - generated at regular intervals (generally every 5 to 30 - minutes), and all contain the same data types. They represent an - aggregation of the LOOP packets over the archive - interval. The exact kind of aggregation depends on the data - type. For example, for temperature, it's generally the average - temperature over the interval. For rain, it's the sum of rain - over the interval. For battery status it's the last value in the - interval. -
- -Some hardware is capable of generating its own archive - records (the Davis Vantage and Oregon Scientific WMR200, for - example), but for hardware that does not archive data, WeeWX - generates them.
- -It is the archive data that is put in the SQL database, - although, occasionally, the LOOP packets can be useful (such as - for the Weather Underground's "Rapidfire" mode).
- -The WeeWX service architecture
- -- At a high-level, WeeWX consists of an - engine class called StdEngine. It is - responsible for loading services, then arranging for - them to be called when key events occur, such as the arrival of - LOOP or archive data. The default install of WeeWX - includes the following services: -
-| Service | -Function | -
| weewx.engine.StdTimeSynch | -Arrange to have the clock on the station - synchronized at regular intervals. - | -
| weewx.engine.StdConvert | -Converts the units of the input to a target unit - system (such as US or Metric). - | -
| weewx.engine.StdCalibrate | -Adjust new LOOP and archive packets using - calibration expressions. - | -
| weewx.engine.StdQC | -Check quality of incoming data, making sure values - fall within a specified range. - | -
| weewx.wxservices.StdWXCalculate | -Calculate any missing, derived weather observation - types, such a dewpoint, windchill, or altimeter-corrected - pressure. - | -
| weewx.engine.StdArchive | -Archive any new data to the SQL databases. | -
| weewx.restx.StdStationRegistry - weewx.restx.StdWunderground - weewx.restx.StdPWSweather weewx.restx.StdCWOP - weewx.restx.StdWOW weewx.restx.StdAWEKAS - |
- Various - RESTful services (simple stateless client-server - protocols), such as the Weather Underground, CWOP, etc. - Each launches its own, independent thread, which manages - the post. - | -
| weewx.engine.StdPrint | -Print out new LOOP and archive packets on the - console. - | -
| weewx.engine.StdReport | -Launch a new thread to do report processing after a - new archive record arrives. Reports do things such as - generate HTML or CSV files, generate images, or FTP/rsync - files to a web server. - | -
- It is easy to extend old services or to add new ones. The source - distribution includes an example new service called MyAlarm, which sends an email when an - arbitrary expression evaluates True. - These advanced topics are covered later in the section Customizing the WeeWX service - engine. -
- - -- The standard reporting service, StdReport -
- -- For the moment, let us focus on the last service, weewx.engine.StdReport, the standard - service for creating reports. This will be what most users will - want to customize, even if it means just changing a few options. -
- -Reports
- -- The standard reporting service, StdReport, - runs zero or more reports. The specific reports which - get run are set in the configuration file - weewx.conf, - in section [StdReport]. -
- -- The default distribution of WeeWX includes three reports: -
-| Report | -Default functionality | -
| StandardReport | -Generates day, week, month and year "to-date" - summaries in HTML, as well as the plot images to go along - with them. Also generates NOAA monthly and yearly - summaries. - | -
| FTP | -Arranges to upload everything in the HTML_ROOT directory up to a remote - webserver. - | -
| RSYNC | -Like FTP, but uses rsync for transferring files to - a remote webserver. - | -
Note that the FTP and RSYNC "reports" are a funny kind of - report in that it they do not actually generate anything. - Instead, they use the reporting service engine to arrange for - things to be transferred to a remote server.
- -Skins
- -- Each report has a skin associated with it. For most - reports, the relationship with the skin is an obvious one: it - contains the templates, any auxiliary files such as background - GIFs or CSS style sheets, and a skin configuration file, - skin.conf. If you will, the skin - controls the look and feel of the report. Note that - more than one report can use the same skin. For example, you - might want to run a report that uses US Customary units, then - run another report against the same skin, but using metric units - and put the results in a different place. All this is possible - by either overriding configuration options in the WeeWX configuration - file weewx.conf or the skin configuration - file skin.conf. -
- -Like all reports, the FTP and RSYNC "reports" also use a - skin, and include a skin configuration file, although they are - quite minimal.
- -- Skins live in their own directory called skins, - whose location is referred to as SKIN_ROOT. - -
-SKIN_ROOT
- The symbol SKIN_ROOT is a symbolic - name to the location of the directory where your skins are - located. It is not to be taken literally. Consult the directory - layout table in the User's Guide for its exact location, - dependent on how you installed WeeWX and what operating - system you are using + This document covers the customization of WeeWX. It assumes that you have read, and are reasonably familiar + with, the Users Guide.
-Generators
+Introduction
-- To create their output, skins rely on one or more generators, - which are what do the actual work, such as creating HTML files - or plot images. Generators can also copy files around or - FTP/rsync them to remote locations. The default install of WeeWX - includes the following generators: -
-| Generator | -Function | -
| weewx.cheetahgenerator.CheetahGenerator | -Generates files from templates, using the Cheetah - template engine. Used to generate HTML and text files. - | -
| weewx.imagegenerator.ImageGenerator | -Generates graph plots. | -
| weewx.reportengine.FtpGenerator | -Uploads data to a remote server using FTP. | -
| weewx.reportengine.RsyncGenerator | -Uploads data to a remote server using rsync. | -
| weewx.reportengine.CopyGenerator | -Copies files locally. | -
- Note that the three generators FtpGenerator, - RsyncGenerator, and CopyGenerator - do not actually generate anything having to do with the - presentation layer. Instead, they just move files around. -
++ This document 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.conf . 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. +
-- Which generators are to be run for a given skin is specified in - the skin's configuration file skin.conf, - in section [Generators]. -
+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. +
-Templates
+Most of the guide applies to any hardware, but the exact data types are hardware-specific. Many examples use + types specific to the Davis Vantage series. Unless you are using an unusual type you are unlikely to run + into trouble. +
-- A template is a text file that is processed by a template - engine to create a new file. WeeWX - uses the Cheetah - template engine. The generator weewx.cheetahgenerator.CheetahGenerator - is responsible for running Cheetah at appropriate times. -
+
+ Warning!
WeeWX is still an experimental system and, as such, its internal design is
+ subject to change. Future upgrades may break any customizations you have done, particularly if they involve
+ the API (skin customizations tend to be more stable).
+
A template may be used to generate HTML, XML, CSV, - Javascript, or any other type of text file. A template typically - contains variables that are replaced when creating the new file. - Templates may also contain simple programming logic.
+Where to put customizations
-- Each template file lives in the skin directory of the skin that - uses it. By convention, a template file ends with the .tmpl extension. -
++ For configuration changes, simply modify the WeeWX configuration file weewx.conf. + Customization of reports may require changes to a skin configuration file skin.conf or template files ending in .tmpl. The weewx.conf configuration file and the skin.conf configuration + and template files in the skins directory will be preserved when you upgrade. +
-- The utility wee_reports -
+Other customizations require new Python code or modifications of example code. Where should you put the code? + If you simply modify the examples in place, then your changes will be overwritten the next time you do an + upgrade. +
-If you make changes, how do you know what the results will - look like? You could just run WeeWX and wait until the next - reporting cycle kicks off but, depending on your archive - interval, that could be a 30 minute wait or more.
++ A better idea is to put the code in the user, directory. For example, copy example + code from the examples directory to the user directory, + then modify it there. If your modification does not contain much code, consider putting it in the file extensions.py in the user directory. Because the user directory is preserved through upgrades, you won't have to redo any changes you + might have made. +
-- The utility wee_reports allows you to - run a report whenever you like. To use it, just run it from a - command line, with the location of your configuration file weewx.conf as the first argument. - Optionally, if you include a unix epoch timestamp as a second - argument, then the report will use that as the "Current" time; - otherwise, the time of the last record in the archive database - will be used. Here is an example, using 1 May 2014 00:00 PDT as - the "Current" time. -
-wee_reports weewx.conf 1398927600
+ Data architecture
-- For more information about wee_reports, - see the Utilities - Guide -
++ WeeWX is data-driven. When the sensors spit out some data, WeeWX does something. The 'something' might be to + print out the data, or to generate an HTML report, or to use FTP to copy a report to a web server, or to + perform some calculations using the data. These actions are called services. +
-The database
++ A driver is Python code that communicates with the hardware. The driver reads data from a serial port or a + device on the USB or a network interface. It handles any decoding of raw bits and bytes, and puts the + resulting data into LOOP packets and archive RECORDs. Whenever possible, WeeWX should work "out of the box" + with minimal configuration. However, in some cases the driver may include code to configure and test the + hardware, typically via the wee_device utility. +
-- WeeWX uses a single database to store - and retrieve the records it needs. It can be implemented by - using either SQLITE3, an - open-source, lightweight SQL database, or MySQL, an open-source, - full-featured database server. -
++ In many cases there are useful dependent variables that use the primary variables emitted by the driver. For + example, rain rate, windchill, heatindex, humidex, apptemp, ET are all dependent quantities — they + require primary observations such as wind speed, temperature, solar radiation. The firmware for some + hardware calculates dependent quantities. The WeeWX service StdWXCalculate fills + in the gaps and determines whether to use a value from firmware or a calculation from WeeWX. Sometimes the + firmware simply does it wrong. +
-Structure
++ LOOP packets vs. archive records
-- Inside this database are several tables. The most important is - the archive table, a big flat table, holding one record - for each archive interval, keyed by dateTime, - the time at the end of the archive interval. It looks something - like this: -
+Generally, there are two types of data that flow through WeeWX: LOOP packets, and archive records.
-| dateTime | -usUnits | -interval | -barometer | -pressure | -altimeter | -inTemp | -outTemp | -... | -
| 1413937800 | -1 | -5 | -29.938 | -null | -null | -71.2 | -56.0 | -... | -
| 1413938100 | -1 | -5 | -29.941 | -null | -null | -71.2 | -55.9 | -... | -
| ... | -... | -... | -... | -... | -... | -... | -... | -... | -
In summary, LOOP packets can be highly irregular, but they come in frequently.
-- The first three columns are required. Here's what they - mean: -
-| Name | -Meaning | -
| dateTime | -The time at the end of the archive interval in unix epoch - time. This is the primary key in the database. It - must be unique, and it cannot be null. - | -
| usUnits | -The unit system the record is in. It cannot be null. - See the Appendix: Units for - how these systems are encoded. - | -
| interval | -The length of the archive interval in minutes. - It cannot be null. - | -
Archive records
-- In addition to the main archive table, there are a number of - smaller tables inside the database, one for each observation - type, that hold daily summaries of the type. For - example, the minimum and maximum value seen during the day, and - at what time. These tables have names such as archive_day_outTemp - or archive_day_barometer. Their - existence is generally transparent to the user. -
++ By contrast, archive records are highly regular. They are generated at regular intervals (generally every 5 + to 30 minutes), and all contain the same data types. They represent an aggregation of the LOOP + packets over the archive interval. The exact kind of aggregation depends on the data type. For example, for + temperature, it's generally the average temperature over the interval. For rain, it's the sum of rain over + the interval. For battery status it's the last value in the interval. +
-Binding names
+Some hardware is capable of generating its own archive records (the Davis Vantage and Oregon Scientific + WMR200, for example), but for hardware that does not archive data, WeeWX generates them. +
-- While most users will only need the one weather database that - comes with WeeWX, the reporting engine - allows you to use multiple databases in the same report. For - example, if you have installed the cmon computer monitoring package, which - uses its own database, you may want to include some statistics - or graphs about your server in your reports, using that - database. -
+It is the archive data that is put in the SQL database, although, occasionally, the LOOP packets can be + useful (such as for the Weather Underground's "Rapidfire" mode). +
-- An additional complication is that WeeWX - can use more than one database implementation: SQLite or MySQL. - Making users specify in the templates not only which database to - use, but also which implementation, would be unreasonable. -
+The WeeWX service architecture
-- The solution, like so many other problems in computer science, - is to introduce another level of indirection, a database - binding. Rather than specify which database to use, you - specify which binding to use. Bindings do not change - with the database implementation, so, for example, you know that - wx_binding will always point to the - weather database, no matter if its implementation is a sqlite - database or a MySQL database. Bindings are listed in section [DataBindings] - in weewx.conf. -
++ At a high-level, WeeWX consists of an engine class called StdEngine. It is + responsible for loading services, then arranging for them to be called when key events occur, such + as the arrival of LOOP or archive data. The default install of WeeWX includes the following services: +
+| Service | +Function | +
| weewx.engine.StdTimeSynch | +Arrange to have the clock on the station synchronized at regular intervals. + | +
| weewx.engine.StdConvert | +Converts the units of the input to a target unit system (such as US or Metric). + | +
| weewx.engine.StdCalibrate | +Adjust new LOOP and archive packets using calibration expressions. + | +
| weewx.engine.StdQC | +Check quality of incoming data, making sure values fall within a specified range. + | +
| weewx.wxservices.StdWXCalculate | +Calculate any missing, derived weather observation types, such a dewpoint, windchill, or + altimeter-corrected pressure. + | +
| weewx.engine.StdArchive | +Archive any new data to the SQL databases. | +
| weewx.restx.StdStationRegistry weewx.restx.StdWunderground + weewx.restx.StdPWSweather weewx.restx.StdCWOP weewx.restx.StdWOW weewx.restx.StdAWEKAS + |
+ Various RESTful services + (simple stateless client-server protocols), such as the Weather Underground, CWOP, etc. Each + launches its own, independent thread, which manages the post. + | +
| weewx.engine.StdPrint | +Print out new LOOP and archive packets on the console. + | +
| weewx.engine.StdReport | +Launch a new thread to do report processing after a new archive record arrives. Reports do things + such as generate HTML or CSV files, generate images, or FTP/rsync files to a web server. + | +
+ 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 weather database binding that WeeWX - uses is wx_binding. This is the - binding that you will be using most of the time and, indeed, it - is the default. You rarely have to specify it explicitly. -
-Programming interface
++ The standard reporting service, StdReport +
-- WeeWX includes a module called weedb that provides a single interface for - many of the differences between database implementations such as - SQLite and MySQL. However, it is not uncommon to make direct SQL - queries within services or search list extensions. In such - cases, the SQL should be generic so that it will work with every - type of database. -
++ For the moment, let us focus on the last service, weewx.engine.StdReport, the + standard service for creating reports. This will be what most users will want to customize, even if it means + just changing a few options. +
-The database manager class provides methods to create, - open, and query a database. These are the canonical forms for - obtaining a database manager.
+Reports
-If you are opening a database from within a WeeWX service:
-db_manager = self.engine.db_binder.get_manager(data_binding='name_of_binding', initialize=True) ++ The standard reporting service, StdReport, runs zero or more reports. The + specific reports which get run are set in the configuration file weewx.conf, in + section [StdReport]. +
+ ++ The default distribution of WeeWX includes three reports: +
+
| Report | +Default functionality | +
| StandardReport | +Generates day, week, month and year "to-date" summaries in HTML, as well as the plot images to go + along with them. Also generates NOAA monthly and yearly summaries. + | +
| FTP | +Arranges to upload everything in the HTML_ROOT directory up to a remote + webserver. + | +
| RSYNC | +Like FTP, but uses rsync for transferring files to a remote webserver. + | +
Note that the FTP and RSYNC "reports" are a funny kind of report in that it they do not actually generate + anything. Instead, they use the reporting service engine to arrange for things to be transferred to a remote + server. +
+ +Skins
+ ++ Each report has a skin associated with it. For most reports, the relationship with the skin is an + obvious one: it contains the templates, any auxiliary files such as background GIFs or CSS style sheets, and + a skin configuration file, skin.conf. If you will, the skin controls the + look and feel of the report. Note that more than one report can use the same skin. For example, you + might want to run a report that uses US Customary units, then run another report against the same skin, but + using metric units and put the results in a different place. All this is possible by either overriding + configuration options in the WeeWX configuration file weewx.conf or the skin + configuration file skin.conf. +
+ +Like all reports, the FTP and RSYNC "reports" also use a skin, and include a skin configuration file, + although they are quite minimal. +
+ ++ Skins live in their own directory called skins, whose location is referred to as + SKIN_ROOT. + +
+SKIN_ROOT
++ The symbol SKIN_ROOT is a symbolic name to the location of the directory + where your skins are located. It is not to be taken literally. Consult the directory layout table in the User's Guide for its exact + location, dependent on how you installed WeeWX and what operating system you are using +
+Generators
+ ++ To create their output, skins rely on one or more generators, which are what do the actual work, + such as creating HTML files or plot images. Generators can also copy files around or FTP/rsync them to + remote locations. The default install of WeeWX includes the following generators: +
+| Generator | +Function | +
| weewx.cheetahgenerator.CheetahGenerator | +Generates files from templates, using the Cheetah template engine. Used to generate HTML and text + files. + | +
| weewx.imagegenerator.ImageGenerator | +Generates graph plots. | +
| weewx.reportengine.FtpGenerator | +Uploads data to a remote server using FTP. | +
| weewx.reportengine.RsyncGenerator | +Uploads data to a remote server using rsync. | +
| weewx.reportengine.CopyGenerator | +Copies files locally. | +
+ Note that the three generators FtpGenerator, RsyncGenerator, and CopyGenerator do not actually generate + anything having to do with the presentation layer. Instead, they just move files around. +
+ ++ Which generators are to be run for a given skin is specified in the skin's configuration file skin.conf, in section [Generators]. +
+ +Templates
+ ++ A template is a text file that is processed by a template engine to create a new file. WeeWX uses + the Cheetah template engine. The generator weewx.cheetahgenerator.CheetahGenerator is responsible for running Cheetah at + appropriate times. +
+ +A template may be used to generate HTML, XML, CSV, Javascript, or any other type of text file. A template + typically contains variables that are replaced when creating the new file. Templates may also contain simple + programming logic. +
+ ++ Each template file lives in the skin directory of the skin that uses it. By convention, a template file ends + with the .tmpl extension. +
+ ++ The utility wee_reports +
+ +If you make changes, how do you know what the results will look like? You could just run WeeWX and wait until + the next reporting cycle kicks off but, depending on your archive interval, that could be a 30 minute wait + or more. +
+ ++ The utility wee_reports allows you to run a report whenever you like. To use it, + just run it from a command line, with the location of your configuration file weewx.conf as the first argument. Optionally, if you include a unix epoch timestamp as a + second argument, then the report will use that as the "Current" time; otherwise, the time of the last record + in the archive database will be used. Here is an example, using 1 May 2014 00:00 PDT as the "Current" time. +
+wee_reports weewx.conf 1398927600
+
+ + For more information about wee_reports, see the Utilities Guide +
+ +The database
+ ++ WeeWX uses a single database to store and retrieve the records it needs. It can be implemented by using + either SQLITE3, an open-source, lightweight SQL database, or MySQL, an open-source, full-featured database server. +
+ +Structure
+ ++ Inside this database are several tables. The most important is the archive table, a big flat table, + holding one record for each archive interval, keyed by dateTime, the time at the + end of the archive interval. It looks something like this: +
+ +| dateTime | +usUnits | +interval | +barometer | +pressure | +altimeter | +inTemp | +outTemp | +... | +
| 1413937800 | +1 | +5 | +29.938 | +null | +null | +71.2 | +56.0 | +... | +
| 1413938100 | +1 | +5 | +29.941 | +null | +null | +71.2 | +55.9 | +... | +
| ... | +... | +... | +... | +... | +... | +... | +... | +... | +
+ The first three columns are required. Here's what they mean: +
+| Name | +Meaning | +
| dateTime | +The time at the end of the archive interval in unix + epoch time. This is the primary key in the database. It must be unique, and it cannot + be null. + | +
| usUnits | +The unit system the record is in. It cannot be null. See the Appendix: + Units for how these systems are encoded. + | +
| interval | +The length of the archive interval in minutes. It cannot be null. + | +
+ In addition to the main archive table, there are a number of smaller tables inside the database, one for + each observation type, that hold daily summaries of the type. For example, the minimum and maximum + value seen during the day, and at what time. These tables have names such as archive_day_outTemp + or archive_day_barometer. Their existence is generally transparent to the user. +
+ +Binding names
+ ++ While most users will only need the one weather database that comes with WeeWX, the reporting engine allows + you to use multiple databases in the same report. For example, if you have installed the cmon computer monitoring + package, which uses its own database, you may want to include some statistics or graphs about your server in + your reports, using that database. +
+ ++ An additional complication is that WeeWX can use more than one database implementation: SQLite or MySQL. + Making users specify in the templates not only which database to use, but also which implementation, would + be unreasonable. +
+ ++ The solution, like so many other problems in computer science, is to introduce another level of indirection, + a database binding. Rather than specify which database to use, you specify which binding + to use. Bindings do not change with the database implementation, so, for example, you know that wx_binding will always point to the weather database, no matter if its implementation is + a sqlite database or a MySQL database. Bindings are listed in section [DataBindings] in weewx.conf. +
+ ++ The standard weather database binding that WeeWX uses is wx_binding. This is the + binding that you will be using most of the time and, indeed, it is the default. You rarely have to specify + it explicitly. +
+ +Programming interface
+ ++ WeeWX includes a module called weedb that provides a single interface for many of + the differences between database implementations such as SQLite and MySQL. However, it is not uncommon to + make direct SQL queries within services or search list extensions. In such cases, the SQL should be generic + so that it will work with every type of database. +
+ +The database manager class provides methods to create, open, and query a database. These are the canonical + forms for obtaining a database manager. +
+ +If you are opening a database from within a WeeWX service:
+db_manager = self.engine.db_binder.get_manager(data_binding='name_of_binding', initialize=True)
# Sample query:
db_manager.getSql("SELECT SUM(rain) FROM %s "\
"WHERE dateTime>? AND dateTime<=?" % db_manager.table_name, (start_ts, stop_ts))
- - If you are opening a database from within a WeeWX search list - extension, you will be passed in a function db_lookup() - as a parameter, which can be used to bind to a database. By - default, it returns a manager bound to wx_binding: -
-wx_manager = db_lookup() # Get default binding ++ If you are opening a database from within a WeeWX search list extension, you will be passed in a function + db_lookup() as a parameter, which can be used to bind to a database. By default, + it returns a manager bound to wx_binding: +
+wx_manager = db_lookup() # Get default binding other_manager = db_lookup(data_binding='some_other_binding') # Get an explicit binding # Sample queries: @@ -687,116 +575,95 @@ wx_manager.getSql("SELECT SUM(rain) FROM %s "\ "WHERE dateTime>? AND dateTime<=?" % wx_manager.table_name, (start_ts, stop_ts)) other_manager.getSql("SELECT SUM(power) FROM %s"\ "WHERE dateTime>? AND dateTime<=?" % other_manager.table_name, (start_ts, stop_ts))-- If opening a database from somewhere other than a service, and - there is no DBBinder available: -
-db_manager = weewx.manager.open_manager_with_config(config_dict, data_binding='name_of_binding') ++ If opening a database from somewhere other than a service, and there is no DBBinder available: +
+db_manager = weewx.manager.open_manager_with_config(config_dict, data_binding='name_of_binding') # Sample query: db_manager.getSql("SELECT SUM(rain) FROM %s "\ "WHERE dateTime>? AND dateTime<=?" % db_manager.table_name, (start_ts, stop_ts))-- The DBBinder caches managers, and thus - database connections. It cannot be shared between threads. -
++ The DBBinder caches managers, and thus database connections. It cannot be shared + between threads. +
-Units
+Units
-- The unit architecture in WeeWX is - designed to make basic unit conversions and display of units - easy. It is not designed to provide dimensional analysis, - arbitrary conversions, and indications of compatibility. -
++ The unit architecture in WeeWX is designed to make basic unit conversions and display of units easy. It is + not designed to provide dimensional analysis, arbitrary conversions, and indications of compatibility. +
-- The driver reads observations from an instrument and - converts them, as necessary, into a standard set of units. The - actual units used by each instrument vary widely; some - instruments use Metric units, others use US Customary units, and - many use a mixture. The driver ensures that the units are - consistent for storage in the WeeWX - database. By default, and to maintain compatibility with wview, the default database units are US - Customary, although this can be changed. -
++ The driver reads observations from an instrument and converts them, as necessary, into a standard + set of units. The actual units used by each instrument vary widely; some instruments use Metric units, + others use US Customary units, and many use a mixture. The driver ensures that the units are consistent for + storage in the WeeWX database. By default, and to maintain compatibility with wview, the default database units are US Customary, although this can be changed. +
-- Note that whatever unit system is used in the database, data can - be displayed using any unit system. So, in practice, it - does not matter what unit system is used in the database. -
++ Note that whatever unit system is used in the database, data can be displayed using any unit + system. So, in practice, it does not matter what unit system is used in the database. +
-- Each observation type, such as outTemp - or pressure, is associated with a unit - group such as group_temperature or group_pressure. Each unit group is - associated with a unit type such as degree_F - or mbar. The template system uses this - architecture to display the names of units and to convert - observations from one unit to another. -
++ Each observation type, such as outTemp or pressure, is associated with a unit group such as group_temperature + or group_pressure. Each unit group is associated with a unit type such as + degree_F or mbar. The template + system uses this architecture to display the names of units and to convert observations from one unit to + another. +
-With this architecture one can easily create reports with, - say, wind measured in knots, rain measured in mm, and - temperatures in degree Celsius. Or one can create a single set - of templates, but display data in different unit systems with - only a few stanzas in a configuration file.
+With this architecture one can easily create reports with, say, wind measured in knots, rain measured in mm, + and temperatures in degree Celsius. Or one can create a single set of templates, but display data in + different unit systems with only a few stanzas in a configuration file. +
-Customizing reports
+Customizing reports
-This section discusses the two general strategies for - customizing reports: by changing options in one or more - configuration file, or by changing the template files. The - former is generally easier, but occasionally the latter is - necessary.
+This section discusses the two general strategies for customizing reports: by changing options in one or more + configuration file, or by changing the template files. The former is generally easier, but occasionally the + latter is necessary. +
-Changing options
+Changing options
-- Changing an option means either modifying the main configuration - file weewx.conf, or the skin - configuration file skin.conf. -
++ Changing an option means either modifying the main configuration file weewx.conf, + or the skin configuration file skin.conf. +
-- Each skin will have a skin.conf that - defines its default configuration. The examples in this guide - refer to the standard skin that comes with the distribution. -
++ Each skin will have a skin.conf that defines its default configuration. The + examples in this guide refer to the standard skin that comes with the distribution. +
-- Changing options in skin.conf -
++ Changing options in skin.conf +
-- With this approach, edit the skin configuration file with a text - editor. Changes made in this way will be used by WeeWX - the next time it generates reports, - which is typically the next archive interval; there is no need - to restart WeeWX to see the results of - the changes. -
++ With this approach, edit the skin configuration file with a text editor. Changes made in this way will be + used by WeeWX the next time it generates reports, which is typically the next archive interval; there is no + need to restart WeeWX to see the results of the changes. +
-- For the standard skin that comes with WeeWX, - the file is skins/Standard/skin.conf. - It includes many, many options that can be changed. For a - complete list, see the section below, The skin configuration file skin.conf. -
++ For the standard skin that comes with WeeWX, the file is skins/Standard/skin.conf. + It includes many, many options that can be changed. For a complete list, see the section below, The skin configuration file skin.conf. +
-- For example, suppose you wish to use metric units in the - presentation layer, instead of the default US Customary Units. - The section in skin.conf that controls - units is [Units][[Groups]]. It looks - like this: -
-[Units] ++ For example, suppose you wish to use metric units in the presentation layer, instead of the default US + Customary Units. The section in skin.conf that controls units is [Units][[Groups]]. It looks like this: +
+[Units] [[Groups]] group_altitude = foot group_degree_day = degree_F_day @@ -812,8 +679,8 @@ db_manager.getSql("SELECT SUM(rain) FROM %s "\ group_temperature = degree_F group_uv = uv_index group_volt = volt-To use metric units, you would edit this section to read:
-[Units] +To use metric units, you would edit this section to read:
+[Units] [[Groups]] group_altitude = meter group_degree_day = degree_C_day @@ -829,74 +696,59 @@ db_manager.getSql("SELECT SUM(rain) FROM %s "\ group_temperature = degree_C group_uv = uv_index group_volt = volt-- The options that were changed have been highlighted . - Details of the various unit options are given in the Appendix: Units. -
++ The options that were changed have been highlighted . Details of + the various unit options are given in the Appendix: 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] ++ 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] +to:
+[Units] [[Generic]] inTemp = Barn Temperature outTemp = Outside Temperature ...-- Overriding options in skin.conf from weewx.conf -
++ Overriding options in skin.conf from weewx.conf +
-- This approach is very similar, except that instead of changing - the skin configuration file, skin.conf, - 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. -
++ This approach is very similar, except that instead of changing the skin configuration file, skin.conf, 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. +
-- With this approach, you must restart WeeWX - to see the effects of any changes. -
++ With this approach, you must restart WeeWX to see the effects of any changes. +
-- Revisiting our example, suppose you want two reports, one in US - Customary, the other in Metric. The former will go in the - directory HTML_ROOT, the latter in - a directory, HTML_ROOT/metric. If you just simply modify skin.conf, you can get one, but not both - at the same time. Alternatively, you could create a whole new - skin by copying all the files to a new skin directory then - editing the new skin.conf. The trouble - with this approach is that you would then have two - skins you would have to maintain. If you change something, you - have to remember to change it in both places. -
++ Revisiting our example, suppose you want two reports, one in US Customary, the other in Metric. The former + will go in the directory HTML_ROOT, the latter in a directory, HTML_ROOT/metric. If you just simply modify skin.conf, you can get one, but not both at the same time. Alternatively, you could + create a whole new skin by copying all the files to a new skin directory then editing the new skin.conf. The trouble with this approach is that you would then have two skins + you would have to maintain. If you change something, you have to remember to change it in both places. +
-- But, there's a better approach: reuse the same skin, but - override some of its options. Here is what your [StdReport] section in weewx.conf - would look like: -
-[StdReport] ++ But, there's a better approach: reuse the same skin, but override some of its options. Here is what your + [StdReport] section in weewx.conf would look like: +
+[StdReport] # # This section specifies what reports, using which skins, are to be generated. # @@ -930,54 +782,44 @@ db_manager.getSql("SELECT SUM(rain) FROM %s "\ group_speed2 = meter_per_second2 group_temperature = degree_C-- We have done two things different from the stock reports. First - (1), we have renamed the first report from StandardReport - to USReport for clarity; and second - (2), we have introduced a new report MetricReport, - just like the first, except it puts its results in a different - spot and uses different units. Both use the same skin, the Standard skin. -
++ We have done two things different from the stock reports. First (1), we have renamed the first report from + StandardReport to USReport for clarity; and second (2), + we have introduced a new report MetricReport, just like the first, except it puts + its results in a different spot and uses different units. Both use the same skin, the Standard + skin. +
-Customizing templates
+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. -
++ If you cannot achieve the results you need by changing a configuration option, you may have to modify the + templates that come with WeeWX, or write your own. +
-- Template modifications are preserved across upgrades (indeed, - everything in the skins directory is - preserved), so you don't have to worry about losing changes - after an upgrade. -
++ Template modifications are preserved across upgrades (indeed, everything in the skins directory is preserved), so you don't have to worry about losing changes after an + upgrade. +
-- 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. -
++ 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. +
-Tags
+Tags
-The key construct is a 'tag', specifying what value you - want. For example:
-$current.outTemp +The key construct is a 'tag', specifying what value you want. For example:
+$current.outTemp $month.outTemp.max $month.outTemp.maxtime-would code the current outside temperature, the maximum - outside temperature for the month, and the time that maximum - temperature occurred, respectively. So a template file that - contains:
-<html> +-would code the current outside temperature, the maximum outside temperature for the month, and the time that + maximum temperature occurred, respectively. So a template file that contains: +
+<html> <head> <title>Current conditions</title> </head> @@ -986,963 +828,867 @@ $month.outTemp.maxtime<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): -
++ 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 -+ Current temperature = 51.0°F
-
Max for the month is 68.8°F, which occurred at 07-Oct-2009 15:15 +- The format that was used to format the temperature (51.0) is specified in section [Units][[StringFormat]]. - The unit label °F is from section [Units][[Labels]], - while the time format is from [Units][[TimeFormats]]. -
++ The format that was used to format the temperature (51.0) is specified in section + [Units][[StringFormat]]. The unit label °F is from section [Units][[Labels]], while the time format is from [Units][[TimeFormats]]. +
-As we saw above, the tags can be very simple:
-## Output max outside temperature using an appropriate format and label: +As we saw above, the tags can be very simple:
+## Output max outside temperature using an appropriate format and label: $month.outTemp.max-- Most of the time, tags will "do the right thing" and are all you - will need. However, WeeWX offers - extensive customization of the generated 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. -
++ Most of the time, tags will "do the right thing" and are all you will need. However, WeeWX offers extensive + customization of the generated 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 tags, depending on - whether the data is "current", or an aggregation over time. - However, both versions are similar.
+There are two different versions of the tags, depending on whether the data is "current", or an aggregation + over time. However, both versions are similar. +
-- Time period $current -
++ Time period $current +
-- Time period $current represents a current - observation. An example would be the current barometric - pressure: -
-$current.barometer++ Time period $current represents a current observation. An example would + be the current barometric pressure: +
+$current.barometer-- Formally, WeeWX first looks for the observation type in the - record emitted by the NEW_ARCHIVE_RECORD - event. This is generally the data emitted by the station - console, augmented by any derived variables (e.g.wind - chill) that you might have specified. If the observation type - cannot be found there, the most recent record in the database - will be searched. -
-The most general tag for a "current" observation looks - like:
-$current($data_binding=binding_name).obstype[.optional_unit_conversion][.optional_formatting]-Where:
++ Formally, WeeWX first looks for the observation type in the record emitted by the NEW_ARCHIVE_RECORD + event. This is generally the data emitted by the station console, augmented by any derived variables (e.g.wind + chill) that you might have specified. If the observation type cannot be found there, the most recent record + in the database will be searched. +
+The most general tag for a "current" observation looks like:
+$current($data_binding=binding_name).obstype[.optional_unit_conversion][.optional_formatting]+Where:
-- binding_name is a binding - name to a database. An example would be wx_binding. - See the section Binding - names for more details. -
++ binding_name is a binding name to a database. An example would be wx_binding. See the section Binding names for more + details. +
-- obstype is an observation type, such - as barometer. See Appendix: Archive Types for a table - of observation types valid for time period current. -
++ obstype is an observation type, such as barometer. See + Appendix: 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. -
++ 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. +
-- optional_formatting is a set of optional - formatting tags, which control how the value will appear. See the - section Formatting - Options below. -
++ optional_formatting is a set of optional formatting tags, which control how the + value will appear. See the section Formatting Options below. +
-- Time period $latest -
++ Time period $latest +
-- Time period $latest is very similar to - $current, except that it uses the last - available timestamp in a database. Usually, $current - and $latest are the same, but if a - data binding points to a remote database, they may not be. See - the section Using multiple - bindings for an example where this happened. -
++ Time period $latest is very similar to $current, except + that it uses the last available timestamp in a database. Usually, $current and + $latest are the same, but if a data binding points to a remote database, they may + not be. See the section Using multiple bindings for an example where + this happened. +
-Aggregation periods
+Aggregation periods
-Aggregation periods is the other kind of tag. For example,
-$week.rain.sum-- represents an aggregation over time, using a certain aggregation - type. In this example, the aggregation time is a week, and the - aggregation type is summation. So, this tag represents the total - rainfall over a week. -
+Aggregation periods is the other kind of tag. For example,
+$week.rain.sum++ represents an aggregation over time, using a certain aggregation type. In this example, + the aggregation time is a week, and the aggregation type is summation. So, this tag represents the total + rainfall over a week. +
-The most general tag for an aggregation over time looks - like:
-$period($data_binding=binding_name, $optional_ago=delta).statstype.aggregation[.optional_unit_conversion][.optional_formatting]-Where:
+The most general tag for an aggregation over time looks like:
+$period($data_binding=binding_name, $optional_ago=delta).statstype.aggregation[.optional_unit_conversion][.optional_formatting]+Where:
-- period is the time period over which - the aggregation is to be done. Possible choices are listed in a - table below. -
++ period is the time period over which the aggregation is to be done. Possible + choices are listed in a table below. +
-- binding_name is a binding - name to a database. An example would be wx_binding. - See the section Binding - names for more details. -
++ binding_name is a binding name to a database. An example would be wx_binding. See the section Binding names for more + details. +
-- optional_ago is a keyword - that depends on the aggregation period. For example, for week, it would be weeks_ago, - for day, it would be days_ago, etc. -
++ optional_ago is a keyword that depends on the aggregation period. For + example, for week, it would be weeks_ago, for day, it would be days_ago, etc. +
-- delta is an integer indicating which - aggregation period is desired. For example $week($weeks_ago=1) - indicates last week, $day($days_ago=2) - would be the day-before-yesterday, etc. The default is - zero: that is, this aggregation period. -
++ delta is an integer indicating which aggregation period is desired. For example + $week($weeks_ago=1) indicates last week, $day($days_ago=2) would be the day-before-yesterday, etc. The default is zero: + that is, this aggregation period. +
-- statstype is a statistical - type. This is generally any observation type that appears in - the database, as well as a few synthetic types (such as heating - and cooling degree-days). Not all aggregations are supported for - all types. -
++ statstype is a statistical type. This is generally any observation type + that appears in the database, as well as a few synthetic types (such as heating and cooling degree-days). + Not all aggregations are supported for all types. +
-- aggregation is an aggregation - type. If you ask for $month.outTemp.avg - you are asking for the average outside temperature for - the month. Possible aggregation types are given in Appendix: Aggregation types. -
++ aggregation is an aggregation type. If you ask for $month.outTemp.avg + you are asking for the average outside temperature for the month. Possible aggregation types are + given in Appendix: Aggregation 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. -
++ 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. +
-- optional_formatting is a set of optional - formatting tags, which control how the value will appear. See the - section Formatting - Options below. -
++ optional_formatting is a set of optional formatting tags, which control how the + value will appear. See the section Formatting Options below. +
-- There are several different aggregation periods that - can be used: -
-
| Aggregation period | -Meaning | -Example | -Meaning of example | -
| $hour | -This hour. | -$hour.outTemp.maxtime | -The time of the max temperature this hour. | -
| $day | -Today (since midnight). | -$day.outTemp.max | -The max temperature since midnight | -
| $yesterday | -Yesterday. Synonym for $day($days_ago=1). - | -$yesterday.outTemp.maxtime | -The time of the max temperature yesterday. | -
| $week | -This week. The start of the week is set by option week_start. - | -$week.outTemp.max | -The max temperature this week. | -
| $month | -This month. | -$month.outTemp.min | -The minimum temperature this month. | -
| $year | -This year. | -$year.outTemp.max | -The max temperature since the start of the year. | -
| $rainyear | -This rain year. The start of the rain year is set - by option rain_year_start. - | -$rainyear.rain.sum | -The total rainfall for this rain year. The start of - the rain year is set by option rain_year_start. - | -
| Aggregation period | +Meaning | +Example | +Meaning of example | +
| $hour | +This hour. | +$hour.outTemp.maxtime | +The time of the max temperature this hour. | +
| $day | +Today (since midnight). | +$day.outTemp.max | +The max temperature since midnight | +
| $yesterday | +Yesterday. Synonym for $day($days_ago=1). + | +$yesterday.outTemp.maxtime | +The time of the max temperature yesterday. | +
| $week | +This week. The start of the week is set by option week_start. + | +$week.outTemp.max | +The max temperature this week. | +
| $month | +This month. | +$month.outTemp.min | +The minimum temperature this month. | +
| $year | +This year. | +$year.outTemp.max | +The max temperature since the start of the year. | +
| $rainyear | +This rain year. The start of the rain year is set by option rain_year_start. + | +$rainyear.rain.sum | +The total rainfall for this rain year. The start of the rain year is set by option rain_year_start. + | +
- The $optional_ago parameters can be useful for - statistics farther in the past. Here are some examples: -
++ The $optional_ago parameters can be useful for statistics farther in the past. Here are some + examples: +
-| Aggregation period | -Example | -Meaning | -
| $hour($hours_ago=h) - | -$hour($hours_ago=1).outTemp.avg | -The average temperature last hour (1 hour ago). | -
| $day($days_ago=d) - | -$day($days_ago=2).outTemp.avg | -The average temperature day before yesterday (2 days - ago). - | -
| $week($weeks_ago=d) - | -$week($weeks_ago=1).outTemp.max | -The maximum temperature last week. | -
| $month($months_ago=m) - | -$month($months_ago=1).outTemp.max | -The maximum temperature last month. | -
| $year($years_ago=m) - | -$year($years_ago=1).outTemp.max | -The maximum temperature last year. | -
| Aggregation period | +Example | +Meaning | +
| $hour($hours_ago=h) + | +$hour($hours_ago=1).outTemp.avg | +The average temperature last hour (1 hour ago). | +
| $day($days_ago=d) + | +$day($days_ago=2).outTemp.avg | +The average temperature day before yesterday (2 days ago). + | +
| $week($weeks_ago=d) + | +$week($weeks_ago=1).outTemp.max | +The maximum temperature last week. | +
| $month($months_ago=m) + | +$month($months_ago=1).outTemp.max | +The maximum temperature last month. | +
| $year($years_ago=m) + | +$year($years_ago=1).outTemp.max | +The maximum temperature last year. | +
Unit conversion options
+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
++ 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 -
+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:
++ 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 -
+Today's average pressure=1017.5 mbar +
-Illegal conversions
+Illegal conversions
-- If an inappropriate or nonsense conversion is asked for, e.g., -
-Today's minimum pressure in mbars: $day.barometer.min.mbar ++ If an inappropriate or nonsense conversion is asked for, e.g., +
+Today's minimum pressure in mbars: $day.barometer.min.mbar or in degrees C: $day.barometer.min.degree_C or in foobar units: $day.barometer.min.foobar-then the offending tag(s) will be put in the output:
+then the offending tag(s) will be put in the output:
-- Today's minimum pressure in mbars: 1015.3
+
or in degrees - C: $day.barometer.min.degree_C
or in foobar units: - $day.barometer.min.foobar -+ Today's minimum pressure in mbars: 1015.3
-
or in degrees C: $day.barometer.min.degree_C
or in + foobar units: $day.barometer.min.foobar +Formatting options
+Formatting options
-- A variety of tags and arguments are available to you to customize the formatting of the final observation - value. This table lists the tags: -
-
| Optional formatting tag | -Comment | -
| .format(args) | -Format the string according to a set of optional args (see below). | -
| .ordinal_compass | -Output compass ordinals for wind direction (e.g."SW"). - The ordinal abbreviations are set by option directions - in the skin configuration file skin.conf. - | -
| .raw | -Value is returned "as is" without being converted - to a string and without any formatting applied. This can - be useful for doing arithmetic directly within the - templates. You must be prepared to deal with a potential None value. - | -
+ A variety of tags and arguments are available to you to customize the formatting of the final observation + value. This table lists the tags: +
+| Optional formatting tag | +Comment | +
| .format(args) | +Format the string according to a set of optional args (see below). | +
| .ordinal_compass | +Output compass ordinals for wind direction (e.g."SW"). The ordinal abbreviations are set by + option directions in the skin configuration file skin.conf. + | +
| .raw | +Value is returned "as is" without being converted to a string and without any formatting applied. + This can be useful for doing arithmetic directly within the templates. You must be prepared to deal + with a potential None value. + | +
The first of these tags has the formal structure:
-.format(format_string=None, None_string=None, add_label=True, localize=True)+
The first of these tags has the formal structure:
+.format(format_string=None, None_string=None, add_label=True, localize=True)-
Here is the meaning of each of the optional arguments:
+Here is the meaning of each of the optional arguments:
-| Optional argument | -Comment | -||||||||||
| format_string | -Use the optional string to format the value. If set to None, - then an appropriate string format from skin.conf will be used. - | -||||||||||
| None_string | -Should the observation value be NONE, then use the supplied
- string (typically, something like "N/A"). If None_string is
- set to None, then the value for NONE
- in [Units][[StringFormats]]
+
|
+ ||||||||||
| add_label | +If set to True (the default), then a unit label (e.g., °F) from + skin.conf will be attached to the end. Otherwise, it will be left out. + | +||||||||||
| localize | +If set to True (the default), then localize the results. Otherwise, do + not. + | +
If you're willing to honor the ordering of the arguments, the argument name can be omitted.
+If you're willing to honor the ordering of the arguments, the argument name can be omitted.
-Formatting examples
+Formatting examples
-This section gives a number of example tags, and their expected output. The following values are assumed:
+This section gives a number of example tags, and their expected output. The following values are assumed:
-| Observation | -Value | -
| - outTemp - | -45.2°F | -
| - UV - | -- None - | -
| - windDir - | -138° | -
| - dateTime - | -1270250700 | -
| Observation | +Value | +
| + outTemp + | +45.2°F | +
| + UV + | ++ None + | +
| + windDir + | +138° | +
| + dateTime + | +1270250700 | +
Here are the examples:
-| Tag | -Result | -Comment | -
| $current.outTemp | -45.2°F | -String formatting from [Units][[StringFormats]]. - Label from [Units][[Labels]] in - skin.conf | -
| $current.outTemp.format | -45.2°F | -Same as the $current.outTemp. | -
| $current.outTemp.format() | -45.2°F | -Same as the $current.outTemp. | -
| $current.outTemp.format(format_string="%.3f") | -45.200°F | -Specified string format used; - label from [Units][[Labels]] in - skin.conf. - | -
| $current.outTemp.format("%.3f") | -45.200°F | -As above, except a positional argument, instead of the named argument, is being used. - | -
| $current.outTemp.format(add_label=False) | -45.2 | -No label. The string formatting is from - [Units][[StringFormats]] in - skin.conf | -
| $current.UV | -N/A | -The string specified by option NONE - in [Units][[StringFormats]] in skin.conf - is used. - | -
| $current.UV.format(None_string="No UV") | -No UV | -Specified None_string is used. - | -
| $current.windDir | -138° | -Formatting is from option degree_compass in - [Units][[StringFormats]] in skin.conf. - | -
| $current.windDir.ordinal_compass | -SW | -Ordinal direction from section - [Units][[Ordinates]] in - skin.conf is being substituted. - | -
| $current.dateTime | -02-Apr-2010 16:25 | -Time formatting from - [Units][[TimeFormats]] in - skin.conf is being used. | -
| $current.dateTime.format(format_string="%H:%M") | -16:25 | -Specified time format used. | -
| $current.dateTime.format("%H:%M") | -16:25 | -As above, except a positional argument, instead of the named argument, is being used. | -
| $current.dateTime.raw | -1270250700 | -Raw Unix epoch time (which is converted to a string by the template - engine). - | -
| $current.outTemp.raw | -45.2 | -Raw float value (which is converted to a string by the template engine). - | -
Here are the examples:
+| Tag | +Result | +Comment | +
| $current.outTemp | +45.2°F | +String formatting from [Units][[StringFormats]]. Label from [Units][[Labels]] in skin.conf | +
| $current.outTemp.format | +45.2°F | +Same as the $current.outTemp. | +
| $current.outTemp.format() | +45.2°F | +Same as the $current.outTemp. | +
| $current.outTemp.format(format_string="%.3f") | +45.200°F | +Specified string format used; label from [Units][[Labels]] + in skin.conf. + | +
| $current.outTemp.format("%.3f") | +45.200°F | +As above, except a positional argument, instead of the named argument, is being used. + | +
| $current.outTemp.format(add_label=False) | +45.2 | +No label. The string formatting is from [Units][[StringFormats]] + in skin.conf | +
| $current.UV | +N/A | +The string specified by option NONE in [Units][[StringFormats]] in skin.conf is used. + | +
| $current.UV.format(None_string="No UV") | +No UV | +Specified None_string is used. + | +
| $current.windDir | +138° | +Formatting is from option degree_compass in [Units][[StringFormats]] in skin.conf. + | +
| $current.windDir.ordinal_compass | +SW | +Ordinal direction from section [Units][[Ordinates]] in skin.conf is + being substituted. + | +
| $current.dateTime | +02-Apr-2010 16:25 | +Time formatting from [Units][[TimeFormats]] in skin.conf + is being used. + | +
| $current.dateTime.format(format_string="%H:%M") | +16:25 | +Specified time format used. | +
| $current.dateTime.format("%H:%M") | +16:25 | +As above, except a positional argument, instead of the named argument, is being used. | +
| $current.dateTime.raw | +1270250700 | +Raw Unix epoch time (which is converted to a string by the template engine). + | +
| $current.outTemp.raw | +45.2 | +Raw float value (which is converted to a string by the template engine). + | +
Note that the same formatting conventions can be used for aggregation periods, - such as $month, as well as $current.
+Note that the same formatting conventions can be used for aggregation periods, such as $month, + as well as $current. +
-- Start, end, and dateTime -
++ Start, end, and 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) and would produce - something like -
-01/09/2010 12:30:00-
- Like true observation types, explicit formats can be specified, - except that they require a - strftime() time format - , rather than a string format. -
++ 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) + and would produce something like +
+01/09/2010 12:30:00+
+ Like true observation types, explicit formats can be specified, except that they require a strftime() time + format , rather than a string format. +
-For example, adding a format descriptor like this:
-$current.dateTime.format("%d-%b-%Y %H:%M")
- produces
+For example, adding a format descriptor like this:
+$current.dateTime.format("%d-%b-%Y %H:%M")
+ produces
-09-Jan-2010 12:30
+09-Jan-2010 12:30
-- For aggregation periods, such as $month, - you can request the start or end of the - period, by using suffixes .start or .end, respectively. For example, -
-The current month runs from $month.start to $month.end.-
results in
-The current month runs from 01/01/2010 12:00:00 AM to 02/01/2017 12:00:00 AM.+
+ For aggregation periods, such as $month, you can request the + start or end of the period, by using suffixes .start or .end, respectively. For example, +
+The current month runs from $month.start to $month.end.+
results in
+The current month runs from 01/01/2010 12:00:00 AM to 02/01/2017 12:00:00 AM.-
- In addition to the suffixes .start and - .end, the suffix .dateTime - is provided for backwards compatibility. Like .start, - it refers to the start of the interval. -
++ In addition to the suffixes .start and .end, the suffix + .dateTime is provided for backwards compatibility. Like .start, it refers to the start of the interval. +
-- The returned string values will always be in local time. - However, if you ask for the raw value -
-$current.dateTime.raw+
+ The returned string values will always be in local time. However, if you ask for the raw value +
+$current.dateTime.raw-
- the returned value will be in Unix Epoch Time (number of seconds - since 00:00:00 UTC 1 Jan 1970, i.e., a large number), - which you must convert yourself. It is guaranteed to never be None, so you don't worry have to worry - about handling a None value. -
++ the returned value will be in Unix Epoch Time (number of seconds since 00:00:00 UTC 1 Jan 1970, + i.e., a large number), which you must convert yourself. It is guaranteed to never be None, so you don't worry have to worry about handling a None + value. +
-- Tag $trend -
++ Tag $trend +
-- The tag $trend is available for time - trends, such as changes in barometric pressure. Here are some - examples: -
-| Tag | -Results | -
| $trend.barometer | --.05 inHg | -
| $trend($time_delta=3600).barometer | --.02 inHg | -
| $trend.outTemp | -1.1 °C | -
| $trend.time_delta | -10800 secs | -
| $trend.time_delta.hour | -3 hrs | -
- Note how you can explicitly specify a value in the tag itself - (2nd example above). If you do not specify a value, then a - default time interval, set by option time_delta in the skin configuration file, - will be used. This value can be retrieved by using the syntax $trend.time_delta (3rd example above). -
++ The tag $trend is available for time trends, such as changes in barometric + pressure. Here are some examples: +
+| Tag | +Results | +
| $trend.barometer | +-.05 inHg | +
| $trend($time_delta=3600).barometer | +-.02 inHg | +
| $trend.outTemp | +1.1 °C | +
| $trend.time_delta | +10800 secs | +
| $trend.time_delta.hour | +3 hrs | +
+ Note how you can explicitly specify a value in the tag itself (2nd example above). If you do not specify a + value, then a default time interval, set by option time_delta + in the skin configuration file, will be used. This value can be retrieved by using the syntax $trend.time_delta (3rd example above). +
-For example, the template expression
-The barometer trend over $trend.time_delta.hour is $trend.barometer.format("%+.2f")
- would result in
+For example, the template expression
+The barometer trend over $trend.time_delta.hour is $trend.barometer.format("%+.2f")
+ would result in
-The barometer trend over 3 hrs is - +.03 inHg.
+The barometer trend over 3 hrs is +.03 inHg.
-- Tag $span -
++ Tag $span +
-- The tag $span allows aggregation over - a user defined period up to and including the current time. Its - most general form looks like: -
++ The tag $span allows aggregation over a user defined period up to and including + the current time. Its most general form looks like: +
-$span([$data_binding=binding_name][,$optional_delta=delta]).obstype.aggregation[.optional_unit_conversion][.optional_formatting]+
$span([$data_binding=binding_name][,$optional_delta=delta]).obstype.aggregation[.optional_unit_conversion][.optional_formatting]-
Where:
-- binding_name is a binding - name to a database. An example would be wx_binding. - See the section Binding - names for more details. -
+Where:
++ binding_name is a binding name to a database. An example would be wx_binding. See the section Binding names for more + details. +
-- $optional_delta=delta - is one or more comma separated delta settings from the table - below. If more than one delta setting is included then the - period used for the aggregate is the sum of the individual delta - settings. If no delta setting is included, or all included delta - settings are zero, the returned aggregate is based on the - current obstype only. -
++ $optional_delta=delta is one or more comma separated delta + settings from the table below. If more than one delta setting is included then the period used for the + aggregate is the sum of the individual delta settings. If no delta setting is included, or all included + delta settings are zero, the returned aggregate is based on the current obstype + only. +
-- obstype is a observation type, such as - outTemp, that is supported by the $current tag. See Appendix: Archive Types for a table - of observation types supported by the $current - tag. -
++ obstype is a observation type, such as outTemp, that is + supported by the $current tag. See Appendix: Archive + Types for a table of observation types supported by the $current tag. +
-- aggregation is an aggregation - type. Possible aggregation types are given in Appendix: Aggregation types. -
++ aggregation is an aggregation type. Possible aggregation types are given + in Appendix: Aggregation types. +
-- optional_unit_conversion is an - optional unit conversion tag. See the section Unit Conversion Options. -
++ optional_unit_conversion is an optional unit conversion tag. See the section + Unit Conversion Options. +
-- optional_formatting is an optional - formatting tag that controls how the value will appear. See the - section Formatting - Options. -
-There are several different delta settings that can be - used:
-| Delta Setting | -Example | -Meaning | -
| $time_delta=seconds | -$span($time_delta=1800).outTemp.avg | -The average temperature over the last immediate 30 - minutes (1800 seconds). - | -
| $hour_delta=hours | -$span($hour_delta=6).outTemp.avg | -The average temperature over the last immediate 6 - hours. - | -
| $day_delta=days | -$span($day_delta=1).rain.sum | -The total rainfall over the last immediate 24 - hours. - | -
| $week_delta=weeks | -$span($week_delta=2).barometer.max | -The maximum barometric pressure over the last - immediate 2 weeks. - | -
| $month_delta=months | -$span($month_delta=3).outTemp.min | -The minimum temperture over the last immediate 3 - months (90 days). - | -
| $year_delta=years | -$span($year_delta=1).windchill.min | -The minimum wind chill over the last immediate 1 - year (365 days). - | -
+ optional_formatting is an optional formatting tag that controls how the value will + appear. See the section Formatting Options. +
+There are several different delta settings that can be used:
+| Delta Setting | +Example | +Meaning | +
| $time_delta=seconds | +$span($time_delta=1800).outTemp.avg | +The average temperature over the last immediate 30 minutes (1800 seconds). + | +
| $hour_delta=hours | +$span($hour_delta=6).outTemp.avg | +The average temperature over the last immediate 6 hours. + | +
| $day_delta=days | +$span($day_delta=1).rain.sum | +The total rainfall over the last immediate 24 hours. + | +
| $week_delta=weeks | +$span($week_delta=2).barometer.max | +The maximum barometric pressure over the last immediate 2 weeks. + | +
| $month_delta=months | +$span($month_delta=3).outTemp.min | +The minimum temperture over the last immediate 3 months (90 days). + | +
| $year_delta=years | +$span($year_delta=1).windchill.min | +The minimum wind chill over the last immediate 1 year (365 days). + | +
For example, the template expressions
-The total rainfall over the last 30 hours is $span($hour_delta=30).rain.sum-
and
-The total rainfall over the last 30 hours is $span($hour_delta=6, $day_delta=1).rain.sum-
would both result in
+For example, the template expressions
+The total rainfall over the last 30 hours is $span($hour_delta=30).rain.sum+
and
+The total rainfall over the last 30 hours is $span($hour_delta=6, $day_delta=1).rain.sum+
would both result in
-The total rainfall over the last 30 - hours is 1.24 in
+The total rainfall over the last 30 hours is 1.24 in
-- Tag $unit -
++ Tag $unit +
-The type, label, and string formats for all units are also - available, allowing you to do highly customized labels:
-| Tag | -Results | -
| $unit.unit_type.outTemp | -degree_C | -
| $unit.label.outTemp | -°C | -
| $unit.format.outTemp | -%.1f | -
For example, the tag
-$day.outTemp.max.format(add_label=False)$unit.label.outTemp-
would result in
+The type, label, and string formats for all units are also available, allowing you to do highly customized + labels: +
+| Tag | +Results | +
| $unit.unit_type.outTemp | +degree_C | +
| $unit.label.outTemp | +°C | +
| $unit.format.outTemp | +%.1f | +
For example, the tag
+$day.outTemp.max.format(add_label=False)$unit.label.outTemp+
would result in
-21.2°C
+21.2°C
-- (assuming metric values have been specified for group_temperature), essentially - reproducing the results of the simpler tag $day.outTemp.max. -
++ (assuming metric values have been specified for group_temperature), essentially + reproducing the results of the simpler tag $day.outTemp.max. +
-- Tag $obs -
++ Tag $obs +
-- The labels used for the various observation types are available - using tag $obs. These are basically - the values given in the skin dictionary, section [Labels][[Generic]]. -
-| Tag | -Results | -
| $obs.label.outTemp | -Outside Temperature | -
| $obs.label.UV | -UV Index | -
+ The labels used for the various observation types are available using tag $obs. + These are basically the values given in the skin dictionary, section [Labels][[Generic]]. +
+| Tag | +Results | +
| $obs.label.outTemp | +Outside Temperature | +
| $obs.label.UV | +UV Index | +
Iteration
+Iteration
-It is possible to iterate over the following:
+It is possible to iterate over the following:
-| Tag suffix | -Results | -
| .records | -Iterate over every record | -
| .hours | -Iterate by hours | -
| .days | -Iterate by days | -
| .months | -Iterate by months | -
| .years | -Iterate by years | -
| .spans(interval=seconds) - | -Iterate by custom length spans. The default - interval is 10800 seconds (3 hours). The spans will align - to local time boundaries. - | -
| Tag suffix | +Results | +
| .records | +Iterate over every record | +
| .hours | +Iterate by hours | +
| .days | +Iterate by days | +
| .months | +Iterate by months | +
| .years | +Iterate by years | +
| .spans(interval=seconds) + | +Iterate by custom length spans. The default interval is 10800 seconds (3 hours). The spans will + align to local time boundaries. + | +
- The following template 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 . -
-Min, max temperatures by month ++ The following template 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 . +
+Min, max temperatures by month #for $month in $year.months $month.dateTime.format("%B"): Min, max temperatures: $month.outTemp.min $month.outTemp.max #end for-The result is:
+The result is:
-- Min, max temperatures by month:
+
January: Min, max - temperatures: 30.1°F 51.5°F
February: Min, max - temperatures: 24.4°F 58.6°F
March: Min, max temperatures: - 27.3°F 64.1°F
April: Min, max temperatures: 33.2°F 52.5°F
- May: Min, max temperatures: N/A N/A
June: Min, max - temperatures: N/A N/A
July: Min, max temperatures: N/A - N/A
August: Min, max temperatures: N/A N/A
- September: Min, max temperatures: N/A N/A
October: Min, - max temperatures: N/A N/A
November: Min, max - temperatures: N/A N/A
December: Min, max temperatures: - N/A N/A -+ Min, max temperatures by month:
-
January: Min, max temperatures: 30.1°F 51.5°F
February: Min, max + temperatures: 24.4°F 58.6°F
March: Min, max temperatures: 27.3°F 64.1°F
April: Min, max + temperatures: 33.2°F 52.5°F
May: Min, max temperatures: N/A N/A
June: Min, max temperatures: N/A + N/A
July: Min, max temperatures: N/A N/A
August: Min, max temperatures: N/A N/A
September: + Min, max temperatures: N/A N/A
October: Min, max temperatures: N/A N/A
November: Min, max + temperatures: N/A N/A
December: Min, max temperatures: N/A N/A +- The following template again uses a Cheetah for - loop, this time to iterate over 3-hour spans over the last 24 hours, - displaying the averages in each span. The iteration loop is highlighted . -
-<p>3 hour averages over the last 24 hours</p> ++ The following template again uses a Cheetah for loop, this time to iterate over + 3-hour spans over the last 24 hours, displaying the averages in each span. The iteration loop is highlighted . +
+<p>3 hour averages over the last 24 hours</p> <table> <tr> <td>Date/time</td><td>outTemp</td><td>outHumidity</td> @@ -1954,74 +1700,72 @@ $month.dateTime.format("%B"): Min, max temperatures: $month.outTemp.min $month.o #end for </table>-The result is:
+The result is:
---3 hour averages over the last 24 hours
--
+- -Date/time -outTemp -outHumidity -- -21/01 18:50 -33.4°F -95% -- -21/01 21:50 -32.8°F -96% -- -22/01 00:50 -33.2°F -96% -- -22/01 03:50 -33.2°F -96% -- -22/01 06:50 -33.8°F -96% -- -22/01 09:50 -36.8°F -95% -- -22/01 12:50 -39.4°F -91% -- -22/01 15:50 -35.4°F -93% -++3 hour averages over the last 24 hours
++
-+ +Date/time +outTemp +outHumidity ++ +21/01 18:50 +33.4°F +95% ++ +21/01 21:50 +32.8°F +96% ++ +22/01 00:50 +33.2°F +96% ++ +22/01 03:50 +33.2°F +96% ++ +22/01 06:50 +33.8°F +96% ++ +22/01 09:50 +36.8°F +95% ++ +22/01 12:50 +39.4°F +91% ++ +22/01 15:50 +35.4°F +93% +- See the NOAA template files NOAA/NOAA-YYYY.txt.tmpl - and NOAA/NOAA-YYYY-MM.txt.tmpl for - other examples using iteration, as well as explicit formatting. -
++ See the NOAA template files NOAA/NOAA-YYYY.txt.tmpl and NOAA/NOAA-YYYY-MM.txt.tmpl + for other examples using iteration, as well as explicit formatting. +
-Comprehensive example
-- This example is designed to put together a lot of the elements - above, including iteration, aggregation period starts and ends, - formatting, and overriding units. -
+Comprehensive example
++ This example is designed to put together a lot of the elements above, including iteration, aggregation + period starts and ends, formatting, and overriding units. +
-+<html> <head> <style> @@ -2053,22 +1797,20 @@ $month.dateTime.format("%B"): Min, max temperatures: $month.outTemp.min $month.o </body> </html>-Click here for the results.
+Click here for the results.
-Almanac
+Almanac
-- If module pyephem - has been installed, then WeeWX can - generate extensive almanac information for the Sun, Moon, Venus, - Mars, Jupiter, and other heavenly bodies, including their rise, - transit and set times, as well as their azimuth and altitude. - Other information is also available. -
++ If module pyephem has been installed, then WeeWX can generate + extensive almanac information for the Sun, Moon, Venus, Mars, Jupiter, and other heavenly bodies, including + their rise, transit and set times, as well as their azimuth and altitude. Other information is also + available. +
-Here is an example template:
+Here is an example template:
-Current time is $current.dateTime +Current time is $current.dateTime #if $almanac.hasExtras Sunrise, transit, sunset: $almanac.sun.rise $almanac.sun.transit $almanac.sun.set Moonrise, transit, moonset: $almanac.moon.rise $almanac.moon.transit $almanac.moon.set @@ -2080,574 +1822,484 @@ Next summer, winter solstice: $almanac.next_summer_solstice $almanac.next_winter Sunrise, sunset: $almanac.sunrise $almanac.sunset #end if-If pyephem is installed this would result in:
+If pyephem is installed this would result in:
-- Current time is 29-Mar-2011 09:20
+
Sunrise, transit, - sunset: 06:51 13:11 19:30
Moonrise, transit, moonset: - 04:33 09:44 15:04
Mars rise, transit, set: 06:35 12:30 - 18:26
Azimuth, altitude of mars: 124.354959275 - 26.4808431952
Next new, full moon: 03-Apr-2011 07:32 - 17-Apr-2011 19:43
Next summer, winter solstice: - 21-Jun-2011 10:16 21-Dec-2011 21:29 -+ Current time is 29-Mar-2011 09:20
-
Sunrise, transit, sunset: 06:51 13:11 19:30
Moonrise, transit, + moonset: 04:33 09:44 15:04
Mars rise, transit, set: 06:35 12:30 18:26
Azimuth, altitude of mars: + 124.354959275 26.4808431952
Next new, full moon: 03-Apr-2011 07:32 17-Apr-2011 19:43
Next summer, + winter solstice: 21-Jun-2011 10:16 21-Dec-2011 21:29 +Otherwise, a fallback of basic calculations is used, - resulting in:
+Otherwise, a fallback of basic calculations is used, resulting in:
-- Current time is 29-Mar-2011 09:20
+
Sunrise, sunset: 06:51 - 19:30 -+ Current time is 29-Mar-2011 09:20
-
Sunrise, sunset: 06:51 19:30 +- As shown in the example, you can test whether this extended - almanac information is available with the value $almanac.hasExtras. -
++ As shown in the example, you can test whether this extended almanac information is available with the value + $almanac.hasExtras. +
-The almanac information falls into three categories:
-
-
-
- Calendar events -
- Heavenly bodies -
- Functions -
We will cover each of these separately.
-Calendar events
+The almanac information falls into three categories:
+-
+
- Calendar events +
- Heavenly bodies +
- Functions +
We will cover each of these separately.
+Calendar events
-- "Calendar events" do not require a heavenly body. They cover - things such as next_solstice, or next_first_quarter_moon. The syntax here - is -
-$almanac.next_solstice-
or
-$almanac.next_first_quarter_moon-
Here is a table of the information that falls into this - category:
-| previous_equinox | -next_equinox | -previous_solstice | -next_solstice | -
| previous_autumnal_equinox | -next_autumnal_equinox | -previous_vernal_equinox | -next_vernal_equinox | -
| previous_winter_solstice | -next_winter_solstice | -previous_summer_solstice | -next_summer_solstice | -
| previous_new_moon | -next_new_moon | -previous_first_quarter_moon | -next_first_quarter_moon | -
| previous_full_moon | -next_full_moon | -previous_last_quarter_moon | -next_last_quarter_moon | -
Heavenly bodies
++ "Calendar events" do not require a heavenly body. They cover things such as next_solstice, or next_first_quarter_moon. The syntax here is +
+$almanac.next_solstice+
or
+$almanac.next_first_quarter_moon+
Here is a table of the information that falls into this category:
+| previous_equinox | +next_equinox | +previous_solstice | +next_solstice | +
| previous_autumnal_equinox | +next_autumnal_equinox | +previous_vernal_equinox | +next_vernal_equinox | +
| previous_winter_solstice | +next_winter_solstice | +previous_summer_solstice | +next_summer_solstice | +
| previous_new_moon | +next_new_moon | +previous_first_quarter_moon | +next_first_quarter_moon | +
| previous_full_moon | +next_full_moon | +previous_last_quarter_moon | +next_last_quarter_moon | +
Heavenly bodies
-The second category does require a heavenly body. This - covers queries such as, "When does Jupiter rise?" or, "When does - the sun transit?" Examples are
-$almanac.jupiter.rise-
or
-$almanac.sun.transit-
- To accurately calculate these times, WeeWX - automatically uses the present temperature and pressure to - calculate refraction effects. However, you can override these - values, which will be necessary if you wish to match the almanac - times published by the Naval Observatory as - explained in the pyephem documentation. For example, to match - the sunrise time as published by the Observatory, instead of -
-$almanac.sun.rise-
use
-$almanac(pressure=0, horizon=-34.0/60.0).sun.rise-
By setting pressure to zero we are bypassing the refraction - calculations and manually setting the horizon to be 34 - arcminutes lower than the normal horizon. This is what the Navy - uses.
+The second category does require a heavenly body. This covers queries such as, "When does Jupiter rise?" or, + "When does the sun transit?" Examples are +
+$almanac.jupiter.rise+
or
+$almanac.sun.transit+
+ To accurately calculate these times, WeeWX automatically uses the present temperature and pressure to + calculate refraction effects. However, you can override these values, which will be necessary if you wish to + match the almanac times published by the Naval Observatory as explained in the pyephem documentation. For + example, to match the sunrise time as published by the Observatory, instead of +
+$almanac.sun.rise+
use
+$almanac(pressure=0, horizon=-34.0/60.0).sun.rise+
By setting pressure to zero we are bypassing the refraction calculations and manually setting the horizon to + be 34 arcminutes lower than the normal horizon. This is what the Navy uses. +
-- If you wish to calculate the start of civil twilight, you can - set the horizon to -6 degrees, and also tell WeeWX - to use the center of the sun (instead of the upper limb, which - it normally uses) to do the calcuation: -
-$almanac(pressure=0, horizon=-6).sun(use_center=1).rise-
The general syntax is:
-$almanac(pressure=pressure, horizon=horizon, ++ If you wish to calculate the start of civil twilight, you can set the horizon to -6 degrees, and also tell + WeeWX to use the center of the sun (instead of the upper limb, which it normally uses) to do the calcuation: +
+$almanac(pressure=0, horizon=-6).sun(use_center=1).rise+The general syntax is:
+$almanac(pressure=pressure, horizon=horizon, temperature=temperature_C).heavenly_body(use_center=[01]).attribute-As you can see, in addition to the horizon angle, you can - also override atmospheric pressure and temperature (degrees - Celsius).
+As you can see, in addition to the horizon angle, you can also override atmospheric pressure and temperature + (degrees Celsius). +
-- PyEphem offers an extensive list of objects that can be used for - the heavenly_body tag. All - the planets and many stars are in the list. -
++ PyEphem offers an extensive list of objects that can be used for the heavenly_body tag. All the planets and many stars are in the list. +
-- The possible values for the attribute - tag are listed in the following table: -
-
| az | -alt | -a_ra | -a_dec | -
| g_ra | -ra | -g_dec | -dec | -
| elong | -radius | -hlong | -hlat | -
| sublat | -sublong | -next_rising | -next_setting | -
| next_transit | -next_antitransit | -previous_rising | -previous_setting | -
| previous_transit | -previous_antitransit | -rise | -set | -
| transit | -- | - | - |
+ The possible values for the attribute tag are listed in the following table: +
+| az | +alt | +a_ra | +a_dec | +
| g_ra | +ra | +g_dec | +dec | +
| elong | +radius | +hlong | +hlat | +
| sublat | +sublong | +next_rising | +next_setting | +
| next_transit | +next_antitransit | +previous_rising | +previous_setting | +
| previous_transit | +previous_antitransit | +rise | +set | +
| transit | ++ | + | + |
Functions
-There is actually one one function in this category: separation. - It returns the angular separation between two heavenly bodies. For example, to calculate - the angular separation between Venus and Mars you would use:
-+Functions
+There is actually one one function in this category: separation. It returns the + angular separation between two heavenly bodies. For example, to calculate the angular separation between + Venus and Mars you would use: +
+<p>The separation between Venus and Mars is $almanac.separation(($almanac.venus.alt,$almanac.venus.az), ($almanac.mars.alt,$almanac.mars.az))</p>-This would result in:
-The separation between Venus and Mars is 55:55:31.8
+This would result in:
+The separation between Venus and Mars is 55:55:31.8
-Wind
+Wind
-- Wind deserves a few comments because it is stored in the - database in two different ways: as a set of scalars, and as a vector - of speed and direction. Here are the four wind-related scalars - stored in the main archive database: -
-
| Archive type | -Meaning | -Valid contexts | -
| windSpeed | -The average wind speed seen during the archive - period. - | -- $current, $latest, $day, $week, $month, $year, $rainyear - | -
| windDir | -If software record generation is used, this is the - vector average over the archive period. If hardware record - generation is used, the value is hardware dependent. - | -|
| windGust | -The maximum (gust) wind speed seen during the - archive period. - | -|
| windGustDir | -The direction of the wind when the gust was observed. | -
+ Wind deserves a few comments because it is stored in the database in two different ways: as a set of + scalars, and as a vector of speed and direction. Here are the four wind-related scalars stored in + the main archive database: +
+| Archive type | +Meaning | +Valid contexts | +
| windSpeed | +The average wind speed seen during the archive period. + | ++ $current, $latest, $day, $week, $month, $year, $rainyear + | +
| windDir | +If software record generation is used, this is the vector average over the archive period. If + hardware record generation is used, the value is hardware dependent. + | +|
| windGust | +The maximum (gust) wind speed seen during the archive period. + | +|
| windGustDir | +The direction of the wind when the gust was observed. | +
In addition, a wind vector is stored in the daily - summaries.
-| Daily summary type | -Meaning | -Valid contexts | -
| wind | -A vector composite of the wind. It includes - information such as the direction of the maximum gust, and - the x- and y-vector wind run. - | -$day, $week, $month, $year, $rainyear | -
- Note
The vector is only stored in the daily summaries,
- so unlike the scalar tags such as windSpeed
- or windGust, the tag wind can only be used in aggregations such
- as $day, $month,
- etc.
-
In addition, a wind vector is stored in the daily summaries.
+| Daily summary type | +Meaning | +Valid contexts | +
| wind | +A vector composite of the wind. It includes information such as the direction of the maximum gust, + and the x- and y-vector wind run. + | +$day, $week, $month, $year, $rainyear | +
+ Note
The vector is only stored in the daily summaries, so unlike the scalar tags such as
+ windSpeed or windGust, the tag wind can only be used in aggregations such as $day, $month, etc.
+
Any of these can be used in your tags. Here are some - examples:
+Any of these can be used in your tags. Here are some examples:
-| Tag | -Meaning | -
| $current.windSpeed | -The average wind speed over the most recent archive - interval. - | -
| $current.windDir | -If software record generation is used, this is the - vector average over the archive interval. If hardware - record generation is used, the value is hardware - dependent. - | -
| $current.windGust | -The maximum wind speed (gust) over the most recent - archive interval. - | -
| $current.windGustDir | -The direction of the gust. | -
| $day.wind.avg | -The average wind speed since midnight. If the wind - blows east at 5 m/s for 2 hours, then west at 5 m/s for 2 - hours, the average wind speed is 5 m/s. - | -
| $day.wind.vecavg | -The vector average wind speed since - midnight. If the wind blows east at 5 m/s for 2 hours, - then west at 5 m/s for 2 hours, the vector average wind - speed is zero. - | -
| $day.wind.vecdir | -The direction of the vector averaged wind speed. If - the wind blows northwest for two hours, then southwest for - two hours, the vector averaged direction is west. - | -
| $day.wind.max | -The maximum wind gust since midnight. | -
| $day.wind.gustdir | -The direction of the maximum wind gust. | -
| $day.wind.maxtime | -The time of the maximum wind gust. | -
| $day.windSpeed.max | -The max average wind speed. The wind is averaged - over each of the archive intervals. Then the maximum of - these values is taken. Note that this is not the - same as the maximum wind gust. - | -
| $day.windDir.avg | -Not a very useful quantity. This is the strict, - arithmetic average of all the compass wind direction. - Probably not what you want. - | -
| Tag | +Meaning | +
| $current.windSpeed | +The average wind speed over the most recent archive interval. + | +
| $current.windDir | +If software record generation is used, this is the vector average over the archive interval. If + hardware record generation is used, the value is hardware dependent. + | +
| $current.windGust | +The maximum wind speed (gust) over the most recent archive interval. + | +
| $current.windGustDir | +The direction of the gust. | +
| $day.wind.avg | +The average wind speed since midnight. If the wind blows east at 5 m/s for 2 hours, then west at 5 + m/s for 2 hours, the average wind speed is 5 m/s. + | +
| $day.wind.vecavg | +The vector average wind speed since midnight. If the wind blows east at 5 m/s for 2 hours, + then west at 5 m/s for 2 hours, the vector average wind speed is zero. + | +
| $day.wind.vecdir | +The direction of the vector averaged wind speed. If the wind blows northwest for two hours, then + southwest for two hours, the vector averaged direction is west. + | +
| $day.wind.max | +The maximum wind gust since midnight. | +
| $day.wind.gustdir | +The direction of the maximum wind gust. | +
| $day.wind.maxtime | +The time of the maximum wind gust. | +
| $day.windSpeed.max | +The max average wind speed. The wind is averaged over each of the archive intervals. Then the + maximum of these values is taken. Note that this is not the same as the maximum wind gust. + | +
| $day.windDir.avg | +Not a very useful quantity. This is the strict, arithmetic average of all the compass wind + direction. Probably not what you want. + | +
Defining new tags
+Defining new tags
-- 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? -
++ 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. -
++ If you wish to introduce a static tag, that is, one that will not change with time (such as a Google + analytics Tracker ID, or your name), then this is very easy: simply put it in section [Extras] in the skin configuration file. More information on how to do this can be + found there. +
-- But, what if you wish to introduce a more dynamic tag, one that - requires some calculation, or perhaps uses the database? Simply - putting it in the [Extras] section - won't do, because then it cannot change. -
++ But, what if you wish to introduce a more dynamic tag, one that requires some calculation, or perhaps uses + the database? Simply putting it in the [Extras] section won't do, because then it + cannot change. +
-- The answer is to write a search list extension. -
++ The answer is to write a search list extension. +
-How the search list works
+How the search list works
-- Let's start by taking a look at how the Cheetah search - list works. -
++ Let's start by taking a look at how the Cheetah search list works. +
-- The Cheetah template engine finds tags by scanning a search - list, a Python list of objects. For example, for a tag $foo, the engine will scan down the list, - trying each object in the list in turn. For each object, it will - first try using foo as an attribute, - that is, it will try evaluating obj.foo. - If that raises an AttributeError - exception, then it will try foo as a - key, that is obj[key]. If that - raises a KeyError exception, then it - moves on to the next item in the list. The first match that does - not raise an exception is used. If no match is found, Cheetah - raises a NameMapper.NotFound - exception. -
++ The Cheetah template engine finds tags by scanning a search list, a Python list of objects. For example, for + a tag $foo, the engine will scan down the list, trying each object in the list in + turn. For each object, it will first try using foo as an attribute, that is, it + will try evaluating obj.foo. If that raises an AttributeError + exception, then it will try foo as a key, that is obj[key]. + If that raises a KeyError exception, then it moves on to the next item in the + list. The first match that does not raise an exception is used. If no match is found, Cheetah raises a NameMapper.NotFound exception. +
-How tags work
+How tags work
-- Now let's take a look at how the search list interacts with - WeeWX tags. Let's start by looking at a simple example: station - altitude, available as the tag -
-++ Now let's take a look at how the search list interacts with WeeWX tags. Let's start by looking at a simple + example: station altitude, available as the tag +
+$station.altitude-- As we saw in the previous section, Cheetah will run down the - search list, looking for an object with a key or attribute station. In the default search list, - WeeWX includes one such object, an instance of the class - weewx.cheetahgenerator.Station, - which has an attribute station, so it - gets a hit on this object. -
++ As we saw in the previous section, Cheetah will run down the search list, looking for an object with a key + or attribute station. In the default search list, WeeWX includes one such object, + an instance of the class weewx.cheetahgenerator.Station, which has an attribute + station, so it gets a hit on this object. +
-- Cheetah will then try to evaluate the attribute altitude on this object. Class Station has such an attribute, so Cheetah - evaluates it. -
++ Cheetah will then try to evaluate the attribute altitude on this object. Class + Station has such an attribute, so Cheetah evaluates it. +
-- What this attribute returns is not a raw value, say 700, nor even a string. Instead, it - returns an instance of the class ValueHelper, - a special class defined in module weewx.units. - Internally, it holds not only the raw value, but also references - to the formats, labels, and conversion targets you specified in - your configuration file. Its job is to make sure that the final - output reflects these preferences. Cheetah doesn't know anything - about this class. What it needs, when it has finished evaluating - the expression $station.altitude, is a - string. In order to convert the ValueHelper - it has in hand into a string, it does what every other Python - object does when faced with this problem: it calls the special - method __str__. - Class ValueHelper has a definition for - this method. Evaluating this function triggers the final steps - in this process. Any necessary unit conversions are done, then - formatting occurs and, finally, a label is attached. The result - is a string something like -
++ What this attribute returns is not a raw value, say 700, nor even a string. + Instead, it returns an instance of the class ValueHelper, a special class defined + in module weewx.units. Internally, it holds not only the raw value, but also + references to the formats, labels, and conversion targets you specified in your configuration file. Its job + is to make sure that the final output reflects these preferences. Cheetah doesn't know anything about this + class. What it needs, when it has finished evaluating the expression $station.altitude, is a string. In order to convert the ValueHelper + it has in hand into a string, it does what every other Python object does when faced with this problem: it + calls the special method __str__. + Class ValueHelper has a definition for this method. Evaluating this function + triggers the final steps in this process. Any necessary unit conversions are done, then formatting occurs + and, finally, a label is attached. The result is a string something like +
-700 feet
+700 feet
-- which is what Cheetah actually puts in the generated HTML file. - This is a good example of lazy evaluation. The tags - gather all the information they need, but don't do the final - evaluation until the last final moment, when the most context is - understood. WeeWX uses this technique extensively. -
++ which is what Cheetah actually puts in the generated HTML file. This is a good example of lazy + evaluation. The tags gather all the information they need, but don't do the final evaluation until the + last final moment, when the most context is understood. WeeWX uses this technique extensively. +
-Now let's look at a more complicated example, say the - maximum temperature since midnight:
-$day.outTemp.max-- When this is evaluated by Cheetah, it actually produces a chain - of objects. At the top of this chain is class weewx.tags.TimeBinder, - an instance of which is included in the default search list. - Internally, this instance stores the time of the desired report - (usually the time of the last archive record), a cache to the - databases, a default data binding, as well as references to the - formatting and labelling options you have chosen. -
+Now let's look at a more complicated example, say the maximum temperature since midnight:
+$day.outTemp.max++ When this is evaluated by Cheetah, it actually produces a chain of objects. At the top of this chain is + class weewx.tags.TimeBinder, an instance of which is included in the default + search list. Internally, this instance stores the time of the desired report (usually the time of the last + archive record), a cache to the databases, a default data binding, as well as references to the formatting + and labelling options you have chosen. +
-- This instance is examined by Cheetah to see if it has an - attribute day. It does and, when it is - evaluated, it returns the next class in the chain, an instance - of weewx.tags.TimespanBinder. In - addition to all the other things contained in its parent TimeBinder, class TimespanBinder - adds the desired time period, that is, the time span from - midnight to the current time. -
++ This instance is examined by Cheetah to see if it has an attribute day. It does + and, when it is evaluated, it returns the next class in the chain, an instance of weewx.tags.TimespanBinder. + In addition to all the other things contained in its parent TimeBinder, class + TimespanBinder adds the desired time period, that is, the time span from midnight + to the current time. +
-- Cheetah then continues on down the chain and tries to find the - next attribute, outTemp. There is no - such hard coded attribute (hard coding all the conceivable - different observation types would be impossible!). Instead, - class TimespanBinder defines the - Python special method __getattr__. - If Python cannot find a hard coded version of an attribute, and - the method __getattr__ exists, it will - try it. The definition provided by TimespanBinder - returns an instance of the next class in the chain, weewx.tags.ObservationBinder, which not - only remembers all the previous stuff, but also adds the - observation type, outTemp. -
++ Cheetah then continues on down the chain and tries to find the next attribute, outTemp. There is no such hard coded attribute (hard coding all the conceivable + different observation types would be impossible!). Instead, class TimespanBinder + defines the Python special method __getattr__. + If Python cannot find a hard coded version of an attribute, and the method __getattr__ exists, it will try it. The definition provided by TimespanBinder + returns an instance of the next class in the chain, weewx.tags.ObservationBinder, + which not only remembers all the previous stuff, but also adds the observation type, outTemp. +
-- Cheetah then tries to evaluate an attribute max - of this class. Now, finally, the chain ends. The attribute max triggers the actual calculation of the - value, using all the known parameters: the database binding to - be hit, the time span of interest, the observation type, and the - type of aggregation, querying the database as necessary. The - database is not actually hit until the last possible moment, - after everything needed to do the evalation is known. -
++ Cheetah then tries to evaluate an attribute max of this class. Now, finally, the + chain ends. The attribute max triggers the actual calculation of the value, using + all the known parameters: the database binding to be hit, the time span of interest, the observation type, + and the type of aggregation, querying the database as necessary. The database is not actually hit until the + last possible moment, after everything needed to do the evalation is known. +
-- Like our previous example, the results of the evaluation are - then packaged up in an instance of ValueHelper, - which does the final conversion to the desired units, formats - the string, then adds a label. The results, something like -
++ Like our previous example, the results of the evaluation are then packaged up in an instance of ValueHelper, which does the final conversion to the desired units, formats the string, + then adds a label. The results, something like +
-12°C
+12°C
-- are put in the generated HTML file. As you can see, a lot of - machinery is hidden behind the deceptively simple expression $day.outTemp.max! -
++ are put in the generated HTML file. As you can see, a lot of machinery is hidden behind the deceptively + simple expression $day.outTemp.max! +
-Extending the list
+Extending the list
-- As mentioned, WeeWX comes with a - number of objects already in the search list, but you can extend - it. To do so, you should have some familiarity with Python, in - particular, how to write new classes and member functions for - them. -
++ As mentioned, WeeWX comes with a number of objects already in the search list, but you can extend it. To do + so, you should have some familiarity with Python, in particular, how to write new classes and member + functions for them. +
-- Let's look at an example. The regular version of WeeWX - offers statistical summaries by day, - week, month, and year. Suppose we would like to add two more: -
-
-
-
- All-time statistics. This would allow us to display - statistics such as the all-time high or low temperature seen - at your station; - -
- Seven days statistics. While WeeWX - offers the tag $week, this is - statistics since Sunday at midnight. We would like to - have statistics for a full week, that is since midnight seven - days ago. - -
- This example is included in the distribution as examples/stats.py. If you wish to use or modify it, - first copy it over to user/stats.py - then modify it there. -
-import datetime ++ Let's look at an example. The regular version of WeeWX offers statistical summaries by day, week, month, and + year. Suppose we would like to add two more: +
+
-
+
- All-time statistics. This would allow us to display statistics such as the all-time high or low + temperature seen at your station; + +
- Seven days statistics. While WeeWX offers the tag $week, this is statistics + since Sunday at midnight. We would like to have statistics for a full week, that is since + midnight seven days ago. + +
+ This example is included in the distribution as examples/stats.py. If you wish to + use or modify it, first copy it over to user/stats.py then modify it there. +
+import datetime
import time
from weewx.cheetahgenerator import SearchList
@@ -2704,121 +2356,89 @@ class MyStats(SearchList): # 1
# Finally, return our extension as a list:
return [search_list_extension] # 9
- Going through the example, line by line:
--
-
- Create a new class called MyStats, - which will inherit from class SearchList. - All search list extensions inherit from this class. - -
- Create an initializer for our new class. In this case, - the initializer is not really necessary and does nothing - except pass its only parameter, generator, - a reference to the calling generator, on to its superclass, SearchList. The superclass will store it - in self. - -
- Override member function get_extension_list().
- This function will be called when the generator is ready to
- accept your new search list extension. The parameters that
- will be passed in are:
-
-
-
- self Python's way of - indicating the instance we are working with; - -
- timespan An instance of - the utility class TimeSpan. This - will contain the valid start and ending times used by the - template. Normally, this is all valid times; - -
- db_lookup This is a - function supplied by the generator. It takes a single - argument, a name of a binding. When called, it will return - an instance of the database manager class for that - binding. The default for the function is whatever binding - you set with the option data_binding - for this report, usually wx_binding. - -
- - The class TimespanBinding
- represents a statistical calculation over a time period. We
- have already met it in the introduction How tags work. In our case, we
- will set it up to represent the statistics over all possible
- times. The class takes 5 parameters.
-
-
-
- The first, timespan, - is the timespan over which the - calculation is to be done. Here, we have a lucky - coincidence: the variable timespan - already holds a TimeSpan object - representing the domain of all valid timespans, so we - simply pass it in. - -
- The second, db_lookup, - is the database lookup function to be - used. We simply pass in db_lookup. - -
- The third, formatter, - should be an instance of class weewx.units.Formatter, which contains - information about how the results should be formatted. We - just pass in the formatter set up by the generator, self.generator.formatter. - -
- The fourth, converter, - should be an instance of weewx.units.Converter, which contains - information about the target units (e.g., degree_C) that are to be used. Again, - we just pass in the instance set up by the generator, self.generator.converter. - -
- The fifth, skin_dict, - is an instance of configobj.ConfigObj, - and contains the contents of the skin configuration file. - We pass it on in order to allow aggregations that need information - from the file, such as heating and cooling degree-days. - -
-
- That one was relatively easy because we already had an instance - of TimeSpan, that is, timespan, which represented the time over - which we wanted to do the calculations. Setting up an instance - that will work for the last seven days is a bit trickier. - Continuing our example... -
--
-
- The object timespan holds the - domain of all valid times, but in order to calculate - statistics for the last seven days, we need not the earliest - valid time, but the time at midnight seven days ago. So, we do - a little Python date arithmetic to calculate this. The object - week_dt will be an instance of datetime.date. - -
- We convert it to unix epoch time. -
- Now we are ready to initialize an appropriate TimespanBinder object. It's the same as in - step #4, except we use our new timespan object. - -
- Create a small dictionary with two keys, alltime, and seven_day. - -
- Return the dictionary in a list -
- The final step that we need to do is to tell the template engine - where to find our extension. You do that by going into the skin - configuration file, skin.conf, and - adding the option search_list_extensions - with our new extension. When you're done, it will look something - like this: -
-[CheetahGenerator] +Going through the example, line by line:
++
+- Create a new class called MyStats, which will inherit from class SearchList. All search list extensions inherit from this class. +
+- Create an initializer for our new class. In this case, the initializer is not really necessary and does + nothing except pass its only parameter, generator, a reference to the calling + generator, on to its superclass, SearchList. The superclass will store it in + self. +
+- Override member function get_extension_list(). This function will be called + when the generator is ready to accept your new search list extension. The parameters that will be passed + in are: +
++
+- self Python's way of indicating the instance we are working with; +
+- timespan An instance of the utility class TimeSpan. This will contain the valid start and ending times used by the + template. Normally, this is all valid times; +
+- db_lookup This is a function supplied by the generator. It takes a + single argument, a name of a binding. When called, it will return an instance of the database + manager class for that binding. The default for the function is whatever binding you set with + the option data_binding for this report, usually wx_binding. +
+- The class TimespanBinding represents a statistical calculation over a time + period. We have already met it in the introduction How tags work. + In our case, we will set it up to represent the statistics over all possible times. The class takes 5 + parameters. +
++
+- The first, timespan, is the timespan over which the calculation is to + be done. Here, we have a lucky coincidence: the variable timespan + already holds a TimeSpan object representing the domain of all valid + timespans, so we simply pass it in. +
+- The second, db_lookup, is the database lookup function to be used. We + simply pass in db_lookup. +
+- The third, formatter, should be an instance of class weewx.units.Formatter, which contains information about how the results + should be formatted. We just pass in the formatter set up by the generator, self.generator.formatter. +
+- The fourth, converter, should be an instance of weewx.units.Converter, + which contains information about the target units (e.g., degree_C) that are to be used. Again, we just pass in the instance set + up by the generator, self.generator.converter. +
+- The fifth, skin_dict, is an instance of configobj.ConfigObj, + and contains the contents of the skin configuration file. We pass it on in order to allow + aggregations that need information from the file, such as heating and cooling degree-days. +
++ That one was relatively easy because we already had an instance of TimeSpan, that + is, timespan, which represented the time over which we wanted to do the + calculations. Setting up an instance that will work for the last seven days is a bit trickier. Continuing + our example... +
++
+- The object timespan holds the domain of all valid times, but in order to + calculate statistics for the last seven days, we need not the earliest valid time, but the time at + midnight seven days ago. So, we do a little Python date arithmetic to calculate this. The object week_dt will be an instance of datetime.date. +
+- We convert it to unix epoch time.
+- Now we are ready to initialize an appropriate TimespanBinder object. It's the + same as in step #4, except we use our new timespan object. +
+- Create a small dictionary with two keys, alltime, and seven_day. +
+- Return the dictionary in a list
++ The final step that we need to do is to tell the template engine where to find our extension. You do that by + going into the skin configuration file, skin.conf, and adding the option search_list_extensions with our new extension. When you're done, it will look something + like this: +
+[CheetahGenerator] # This section is used by the generator CheetahGenerator, and specifies # which files are to be generated from which template. @@ -2829,23 +2449,20 @@ class MyStats(SearchList): # 1 [[SummaryByMonth]] ...-- Our addition has been highlighted. - Note that it is in the section [CheetahGenerator]. -
++ Our addition has been highlighted. Note that it is in the section [CheetahGenerator]. +
-- Now, if the Cheetah engine encounters the tag - $alltime, it will scan the search list, looking for an - attribute or key that matches alltime. - When it gets to the little dictionary we provided, it will find - a matching key, allowing it to retrieve the appropriate TimespanBinding object. -
++ Now, if the Cheetah engine encounters the tag + $alltime, it will scan the search list, looking for an attribute or key that matches alltime. When it gets to the little dictionary we provided, it will find a matching key, + allowing it to retrieve the appropriate TimespanBinding object. +
-With this approach, you can now include "all time" or - "seven day" statistics in your HTML templates:
-+With this approach, you can now include "all time" or "seven day" statistics in your HTML templates:
+<table> <tr> <td>Maximum temperature to date: </td> @@ -2860,35 +2477,31 @@ class MyStats(SearchList): # 1 <td>$seven_day.rain.sum </tr> </table>-- We put our addition in the file user/stats.py, - which means it will be in the directory hierarchy - where weewxd resides. Python will search - this hierarchy by default, so it will find our addition. However, if - you put it somewhere else, may will have to specify its location with - the environment variable PYTHONPATH when you start WeeWX: -
-export PYTHONPATH=/home/me/secret_location++ We put our addition in the file user/stats.py, which means it will be in the + directory hierarchy where weewxd resides. Python will search this hierarchy by + default, so it will find our addition. However, if you put it somewhere else, may will have to specify its + location with the environment variable PYTHONPATH when you start WeeWX: +
+export PYTHONPATH=/home/me/secret_location-Customizing images
+Customizing images
-- The installed version of WeeWX is - configured to generate a set of useful plots. But, what if you - don't like how they look, or you want to generate different - plots, perhaps with different aggregation types? This section - covers how to do this. -
++ The installed version of WeeWX is configured to generate a set of useful plots. But, what if you don't like + how they look, or you want to generate different plots, perhaps with different aggregation types? This + section covers how to do this. +
-- Image generation is controlled by the section [ImageGenerator] - in the skin configuration file skin.conf. - Let's take a look at the beginning part of this section. It - looks like this: -
-[ImageGenerator] ++ Image generation is controlled by the section [ImageGenerator] in the skin + configuration file skin.conf. Let's take a look at the beginning part of this + section. It looks like this: +
+[ImageGenerator] ... image_width = 300 image_height = 180 @@ -2897,31 +2510,25 @@ class MyStats(SearchList): # 1 chart_background_color = 0xd8d8d8 chart_gridline_color = 0xa0a0a0 ...-- The options right under the section name [ImageGenerator] - will apply to all plots, unless overridden in - subsections. So, unless otherwise changed, all plots will be 300 - pixels in width, 180 pixels in height, and will have an RGB - background color of 0xf5f5f5, a very light gray (HTML color - "WhiteSmoke"). The chart itself will have a background color of - 0xd8d8d8 (a little darker gray), and the gridlines will be - 0xa0a0a0 (still darker). The other options farther down (not - shown) will also apply to all plots. -
++ The options right under the section name [ImageGenerator] will apply to + all plots, unless overridden in subsections. So, unless otherwise changed, all plots will be 300 + pixels in width, 180 pixels in height, and will have an RGB background color of 0xf5f5f5, a very light gray + (HTML color "WhiteSmoke"). The chart itself will have a background color of 0xd8d8d8 (a little darker gray), + and the gridlines will be 0xa0a0a0 (still darker). The other options farther down (not shown) will also + apply to all plots. +
-Time periods
+Time periods
-- After the "global" options at the top of section [ImageGenerator], comes a set of - sub-sections, one for each time period (day, week, month, and - year). These sub-sections define the nature of aggregation and - plot types for that time period. For example, here is a typical - set of options for sub-section [[month_images]]. - It controls which "monthly" images will get generated, and what - they will look like: -
-[[month_images]] ++ After the "global" options at the top of section [ImageGenerator], comes a set of + sub-sections, one for each time period (day, week, month, and year). These sub-sections define the nature of + aggregation and plot types for that time period. For example, here is a typical set of options for + sub-section [[month_images]]. It controls which "monthly" images will get + generated, and what they will look like: +
+[[month_images]] x_label_format = %d bottom_label_format = %m/%d/%y %H:%M time_length = 2592000 # == 30 days @@ -2929,179 +2536,144 @@ class MyStats(SearchList): # 1 aggregate_interval = 10800 # == 3 hours show_daynight = false-- 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 something like 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. Finally, by setting option show_daynight - to false, we are requesting that - day-night, shaded bands not be shown. -
++ 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 something like 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. Finally, by setting option show_daynight to false, we are requesting that day-night, shaded bands not be shown. +
-Image files
+Image files
-- Within each time period 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. Like elsewhere, the values - specified in the level above can be overridden. For example, - here is a typical set of options for sub-sub-section [[[monthrain]]]: -
-[[[monthrain]]] ++ Within each time period 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. Like elsewhere, the values specified + in the level above can be overridden. For example, here is a typical set of options for sub-sub-section + [[[monthrain]]]: +
+[[[monthrain]]] plot_type = bar yscale = None, None, 0.02 [[[[rain]]]] aggregate_type = sum aggregate_interval = 86400 label = Rain (daily total)-- This will generate an image file with name monthrain.png. - It will be a bar plot. Option yscale - controls the y-axis scaling — if left out, the scale will - automatically be chosen. However, in this example we are - choosing to exercise some degree of control by specifying values - explicitly. The option is a 3-way tuple (ylow, - yhigh, min_interval), - where ylow and yhigh - are the minimum and maximum y-axis values, respectively, and min_interval is the minimum tick interval. - If set to None, the corresponding - value will be automatically chosen. So, in this example, the - setting -
-yscale = None, None, 0.02-- will cause WeeWX to pick sensible y - minimum and maximum values, but require that the tick increment - (min_interval) be at least 0.02. -
++ This will generate an image file with name monthrain.png. It will be a bar plot. + Option yscale controls the y-axis scaling — if left out, the scale will + automatically be chosen. However, in this example we are choosing to exercise some degree of control by + specifying values explicitly. The option is a 3-way tuple (ylow, yhigh, min_interval), where ylow and + yhigh are the minimum and maximum y-axis values, respectively, and min_interval is the minimum tick interval. If set to None, the + corresponding value will be automatically chosen. So, in this example, the setting +
+yscale = None, None, 0.02++ will cause WeeWX to pick sensible y minimum and maximum values, but require that the tick increment (min_interval) be at least 0.02. +
-- Continuing on with the example above, there will be only one - plot "line" (it will actually be a series of bars) and it will - have logical name rain. Because we - have not said otherwise, the SQL data type to be used for this - line will be the same as its logical name, that is, rain, but this can be overridden. 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 of - 'Rain (daily total)'. The result of all this is the following - plot: -
++ Continuing on with the example above, there will be only one plot "line" (it will actually be a series of + bars) and it will have logical name rain. Because we have not said otherwise, the + SQL data type to be used for this line will be the same as its logical name, that is, rain, + but this can be overridden. 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 of 'Rain (daily total)'. The result of all this is the following plot: +
--
+-
+
-+
Line gaps
+Line gaps
-- If there is a time gap in the data, the option line_gap_fraction controls how line plots - will be drawn. Here's what a plot looks like without and with - this option being specified: -
++ If there is a time gap in the data, the option line_gap_fraction controls how line + plots will be drawn. Here's what a plot looks like without and with this option being specified: +
---- -+
+-+--
- No line_gap_fraction specified +++ No line_gap_fraction specified ++++ +
+ With line_gap_fraction=0.01 ++--+ +
Including more than one SQL type in a plot
-- With line_gap_fraction=0.01 --Including more than one SQL type in a plot
- -More than one SQL type can be included in a plot. For - example, here is how to generate a plot with the week's outside - temperature as well as dewpoint:
-[[[monthtempdew]]] +More than one SQL type can be included in a plot. For example, here is how to generate a plot with the week's + outside temperature as well as dewpoint: +
+[[[monthtempdew]]] [[[[outTemp]]]] [[[[dewpoint]]]]-- This would create an image in file monthtempdew.png - that includes a line plot of both outside temperature and - dewpoint. -
++ This would create an image in file monthtempdew.png that includes a line plot of + both outside temperature and dewpoint. +
-Including the same SQL - type more than once in a plot
+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 ## ++ 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]]] [[[[avgTemp]]]] data_type = outTemp aggregate_type = avg aggregate_interval = 3600 label = Avg. Temp. [[[[outTemp]]]]-- Here, the first plot line has been given the name avgTemp to distinguish it from the second - line outTemp. Any name will do — - it just has to be different. 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. -
++ Here, the first plot line has been given the name avgTemp to distinguish it from + the second line outTemp. Any name will do — it just has to be different. 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 one hour smoothed average:
+The result is a nice plot of the day's temperature, overlaid with a one hour smoothed average:
--
+-
+
-+
One more example. This one shows daily high and low - temperatures for a year:
-[[year_images]] +One more example. This one shows daily high and low temperatures for a year:
+[[year_images]] [[[yearhilow]]] [[[[hi]]]] data_type = outTemp @@ -3111,33 +2683,26 @@ class MyStats(SearchList): # 1 data_type = outTemp aggregate_type = min label = Low Temperature-- This results in the plot yearhilow.png: -
++ This results in the plot yearhilow.png: +
--
+-
+
-+
Progressive vector plots
+Progressive vector plots
-- WeeWX can produce progressive vector - plots as well as the more conventional x-y plots. To produce - these, use plot type vector. You need - a vector type to produce this kind of plot. There are two: windvec, and windgustvec. - While they do not actually appear in the SQL database, - WeeWX understands that they represent - special vector-types. The first, windvec, - represents the average wind in an archive period, the second, windgustvec the max wind in an archive - period. Here's how to produce a progressive vector for one week - that shows the hourly biggest wind gusts, along with hourly - averages: -
-[[[weekgustoverlay]]] ++ WeeWX can produce progressive vector plots as well as the more conventional x-y plots. To produce these, use + plot type vector. You need a vector type to produce this kind of plot. There are + two: windvec, and windgustvec. While they do not + actually appear in the SQL database, WeeWX understands that they represent special vector-types. The first, + windvec, represents the average wind in an archive period, the second, windgustvec the max wind in an archive period. Here's how to produce a progressive + vector for one week that shows the hourly biggest wind gusts, along with hourly averages: +
+[[[weekgustoverlay]]] aggregate_interval = 3600 [[[[windvec]]]] label = Hourly Wind @@ -3147,92 +2712,75 @@ class MyStats(SearchList): # 1 label = Gust Wind plot_type = vector aggregate_type = max-- This will produce an image file with name weekgustoverlay.png. - It will consist of two progressive vector plots, both using - hourly aggregation (3,600 seconds). For the first set of - vectors, the hourly average will be used. In the second, the max - of the gusts will be used: -
++ This will produce an image file with name weekgustoverlay.png. It will consist of + two progressive vector plots, both using hourly aggregation (3,600 seconds). For the first set of vectors, + the hourly average will be used. In the second, the max of the gusts will be used: +
--
+-
+
-+
- By default, the sticks in the progressive wind plots point - towards the wind source. That is, the stick for a wind from the - west will point left. If you have a chronic wind direction (as I - do), you may want to rotate the default direction so that all - the vectors do not line up over the x-axis, overlaying each - other. Do this by using option vector_rotate. - For example, with my chronic westerlies, I set vector_rotate to 90.0 for the plot above, - so winds out of the west point straight up. -
++ By default, the sticks in the progressive wind plots point towards the wind source. That is, the stick for a + wind from the west will point left. If you have a chronic wind direction (as I do), you may want to rotate + the default direction so that all the vectors do not line up over the x-axis, overlaying each other. Do this + by using option vector_rotate. For example, with my chronic westerlies, I set + vector_rotate to 90.0 for the plot above, so winds out of the west point straight + up. +
-- If you use this kind of plot (the out-of-the-box version of - WeeWX includes daily, weekly, monthly, and - yearly progressive wind plots), a small compass rose will be put - in the lower-left corner of the image to show the orientation of - North. -
++ If you use this kind of plot (the out-of-the-box version of WeeWX includes daily, weekly, monthly, and + yearly progressive wind plots), a small compass rose will be put in the lower-left corner of the image to + show the orientation of North. +
-Overriding values
+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: -
-[ImageGenerator] ++ 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: +
+[ImageGenerator] ... 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 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 daybarometer_big.png. +
+[[[daybarometer_big]]] image_width = 600 image_height = 360 [[[[barometer]]]]-Using multiple bindings
+Using multiple bindings
-- It's easy to use more than one database in your reports. Here's - an example. In my office I have two consoles: a VantagePro2 - connected to a Dell Optiplex, and a WMR100N, connected to a - Raspberry Pi. Each is running WeeWX. - The Dell is using SQLite, the RPi, MySQL. -
++ It's easy to use more than one database in your reports. Here's an example. In my office I have two + consoles: a VantagePro2 connected to a Dell Optiplex, and a WMR100N, connected to a Raspberry Pi. Each is + running WeeWX. The Dell is using SQLite, the RPi, MySQL. +
-Suppose I wish to compare the inside temperatures of the - two consoles. How would I do that?
+Suppose I wish to compare the inside temperatures of the two consoles. How would I do that?
-- It's easier to access MySQL across a network than SQLite, so - let's run the reports on the Dell, but access the RPi's MySQL - database remotely. Here's how the bindings and database sections - of weewx.conf would look on the Dell: -
-[DataBindings] ++ It's easier to access MySQL across a network than SQLite, so let's run the reports on the Dell, but access + the RPi's MySQL database remotely. Here's how the bindings and database sections of weewx.conf + would look on the Dell: +
+[DataBindings] # This section binds a data store to an actual database [[wx_binding]] @@ -3285,32 +2833,28 @@ class MyStats(SearchList): # 1 password = weewx-- The two additions have been highlighted. - The first, [[wmr100_binding]], adds a - new binding called wmr10_binding. It - links ("binds") to the new database, called rpi_mysql, - through the option database. It also - defines some characteristics of the binding, such as which - manager is to be used and what its schema looks like. -
++ The two additions have been highlighted. The first, [[wmr100_binding]], + adds a new binding called wmr10_binding. It links ("binds") to the new database, + called rpi_mysql, through the option database. It also + defines some characteristics of the binding, such as which manager is to be used and what its schema looks + like. +
-- The second addition, [[rpi-mysql]] - defines the new database. Option database_type - is set to MySQL, indicating that it is - a MySQL database. Defaults for MySQL databases are defined in - the section [[MySQL]]. The new - database accepts all of them, except for host, - which as been set to the remote host rpi-bug, - the name of my Raspberry Pi. -
++ The second addition, [[rpi-mysql]] defines the new database. Option database_type is set to MySQL, indicating that it is a MySQL + database. Defaults for MySQL databases are defined in the section [[MySQL]]. The + new database accepts all of them, except for host, which as been set to the remote + host rpi-bug, the name of my Raspberry Pi. +
-Explicit binding in tags
+Explicit binding in tags
-How do we use this new binding? First, let's do a text - comparison, using tags. Here's what our template looks like:
-<table> +How do we use this new binding? First, let's do a text comparison, using tags. Here's what our template looks + like: +
+<table> <tr> <td class="stats_label">Inside Temperature, Vantage</td> <td class="stats_data">$current.inTemp</td> @@ -3321,41 +2865,38 @@ class MyStats(SearchList): # 1 </tr> </table>-- The explicit binding to wmr100_binding - is highlighted. This tells the reporting engine to override the - default binding specifed in [StdReport], - generally wx_binding, and use wmr100_binding instead. -
++ The explicit binding to wmr100_binding is highlighted. This tells the reporting + engine to override the default binding specifed in [StdReport], generally wx_binding, and use wmr100_binding instead. +
-This results in an HTML output that looks like:
+This results in an HTML output that looks like:
--+--- -
-- -Inside Temperature, Vantage -68.7°F -- - -Inside Temperature, WMR100 -68.9°F -+-+++ +
++ +Inside Temperature, Vantage +68.7°F ++ + +Inside Temperature, WMR100 +68.9°F +Explicit binding in images
+Explicit binding in images
-- How would we produce a graph of the two different temperatures? - Here's what the relevant section of the skin.conf - file would look like. -
-[[[daycompare]]] ++ How would we produce a graph of the two different temperatures? Here's what the relevant section of the + skin.conf file would look like. +
+[[[daycompare]]] [[[[inTemp]]]] label = Vantage inTemp [[[[WMR100Temp]]]] @@ -3363,157 +2904,126 @@ class MyStats(SearchList): # 1 data_binding = wmr100_binding label = WMR100 inTemp-- This will produce an image with name daycompare.png, - with two plot lines. The first will be of the temperature from - the Vantage. It uses the default binding, wx_binding, - and will be labeled Vantage inTemp. - The second explicitly uses the wmr100_binding. - Because it uses the same variable name (inTemp) - as the first line, we had to explicitly specify it using option - data_type, in order to avoid using the - same sub-section name twice (see the section Including the same SQL - type more than once in a plot for details). It will be - labeled WMR100 inTemp. The results - look like this: -
-+
+ This will produce an image with name daycompare.png, with two plot lines. The + first will be of the temperature from the Vantage. It uses the default binding, wx_binding, + and will be labeled Vantage inTemp. The second explicitly uses the wmr100_binding. Because it uses the same variable name (inTemp) + as the first line, we had to explicitly specify it using option data_type, in + order to avoid using the same sub-section name twice (see the section Including the same SQL type more than once in a plot for + details). It will be labeled WMR100 inTemp. The results look like this: +
+-
Stupid detail
+Stupid detail
-- At first, I could not get this example to work. The problem - turned out to be that the RPi was processing things just a beat - behind the Dell, so the temperature for the "current" time - wasn't ready when the Dell needed it. I kept getting N/A. To avoid this, I introduced the tag $latest, which uses the last available - timestamp in the binding, which may or may not be the same as - what $current uses. That's why the - example above uses $latest instead of - $current. -
++ At first, I could not get this example to work. The problem turned out to be that the RPi was processing + things just a beat behind the Dell, so the temperature for the "current" time wasn't ready when the Dell + needed it. I kept getting N/A. To avoid this, I introduced the tag $latest, which uses the last available timestamp in the binding, which may or may not be + the same as what $current uses. That's why the example above uses $latest instead of $current. +
-Customizing the report - generation time
+Customizing the report generation time
-- Normal WeeWX operation is to run each report - defined in weewx.conf every archive period. Whilst - this may suit most situations, there may be occasions when it is desirable - to run a report less frequently than every archive period. For example, the - archive interval might be 5 minutes, but you only want to FTP files every - 30 minutes, once per day or at a set time each day. Weewx has two mechanisms - that provide the ability to control when files are generated. The - stale_age - option allows control over the age of a file before it is regenerated and - the report_timing option allows precise control - over when individual reports are run. -
++ Normal WeeWX operation is to run each report defined in weewx.conf every archive period. Whilst this may suit most situations, there may be + occasions when it is desirable to run a report less frequently than every archive period. For example, the + archive interval might be 5 minutes, but you only want to FTP files every 30 minutes, once per day or at a + set time each day. Weewx has two mechanisms that provide the ability to control when files are generated. + The stale_age option allows control over the age + of a file before it is regenerated and the report_timing option allows precise + control over when individual reports are run. +
-- Note
+
Whilst the report_timing - option allows the user to specify when a given report is generated, it - should be noted that the generation of reports is still controlled by - the WeeWX report cycle and as such the report_timing - option does not allow reports to be generated more frequently than once - every archive period. -+ Note
-
Whilst the report_timing option allows the user to + specify when a given report is generated, it should be noted that the generation of reports is still + controlled by the WeeWX report cycle and as such the report_timing option does not + allow reports to be generated more frequently than once every archive period. +- The report_timing option -
++ The report_timing option
-- The report_timing option uses a - CRON-like format to control when a report is to be run. Whilst a - CRON-like format is used, the control of WeeWX - report generation using the report_timing - option is confined completely to WeeWX - and has no interraction with the system CRON service. -
++ The report_timing option uses a CRON-like format to control when a report is to be + run. Whilst a CRON-like format is used, the control of WeeWX report generation using the report_timing + option is confined completely to WeeWX and has no interraction with the system CRON service. +
-- The report_timing option consists of - five, space separated parameters as follows: -
++ The report_timing option consists of five, space separated parameters as follows: +
-report_timing = minutes hours day_of_month months day_of_week+report_timing = minutes hours day_of_month months day_of_week-- The report_timing parameters are - summarised in the following table: -
++ The report_timing parameters are summarised in the following table: +
-- -
+- -Parameter -Function -Allowable values -- -minutes -Specifies the minutes of the hour when the report - will be run - -*, or -
numbers in the range 0..59 inclusive -- -hours -Specifies the hours of the day when the report will - be run - -*, or -
numbers in the range 0..23 inclusive -- -day_of_month -Specifies the days of the month when the report - will be run - -*, or -
numbers in the range 1..31 inclusive -- -months -Specifies the months of the year when the report - will be run - -*, or -
numbers in the range 1..12 inclusive, - or
abbreviated names in the range jan..dec inclusive -- - -day_of_week -Specifies the days of the week when the report will - be run - -*, or -
numbers in the range 0..7 inclusive - (0,7 = Sunday, 1 = Monday etc), or
abbreviated names - in the range sun..sat inclusive -+ +
-+ +Parameter +Function +Allowable values ++ +minutes +Specifies the minutes of the hour when the report will be run + +*, or +
numbers in the range 0..59 inclusive ++ +hours +Specifies the hours of the day when the report will be run + +*, or +
numbers in the range 0..23 inclusive ++ +day_of_month +Specifies the days of the month when the report will be run + +*, or +
numbers in the range 1..31 inclusive ++ +months +Specifies the months of the year when the report will be run + +*, or +
numbers in the range 1..12 inclusive, or
abbreviated names in the range jan..dec + inclusive ++ + +day_of_week +Specifies the days of the week when the report will be run + +*, or +
numbers in the range 0..7 inclusive (0,7 = Sunday, 1 = Monday etc), or
abbreviated + names in the range sun..sat inclusive +- The report_timing option may only be - used in weewx.conf. When set in the [StdReport] section of weewx.conf - the option will apply to all reports listed under [StdReport]. When specified within a - report section, the option will override any setting in [StdReport] for that report. In this - manner it is possible to have different reports run at different - times. The following sample weewx.conf - excerpt illustrates this: -
++ The report_timing option may only be used in weewx.conf. + When set in the [StdReport] section of weewx.conf the + option will apply to all reports listed under [StdReport]. When specified within a + report section, the option will override any setting in [StdReport] for that + report. In this manner it is possible to have different reports run at different times. The following sample + weewx.conf excerpt illustrates this: +
-+[StdReport] # Where the skins reside, relative to WEEWX_ROOT @@ -3537,650 +3047,560 @@ class MyStats(SearchList): # 1 skin = SomeOtherSkin report_timing = */10 * * * *-- In the above case, the [[AReport]] - report would be run under under control of the 0 * * * * setting (on the hour) under [StdReport] and the [[AnotherReport]] - report would be run under control of the */10 * * * * setting (every 10 minutes) - which has overriden the [StdReport] - setting. -
++ In the above case, the [[AReport]] report would be run under under control of the + 0 * * * * setting (on the hour) under [StdReport] and + the [[AnotherReport]] report would be run under control of the */10 * * * * + setting (every 10 minutes) which has overriden the [StdReport] setting. +
-- How report_timing controls reporting -
++ How report_timing controls reporting
-- The syntax and interpretation of the report_timing - parameters are largely the same as those of the CRON service in - many Unix and Unix-like operating systems. The syntax and - interpretation are outlined below. -
++ The syntax and interpretation of the report_timing parameters are largely the same + as those of the CRON service in many Unix and Unix-like operating systems. The syntax and interpretation are + outlined below. +
-- When the report_timing option is in - use WeeWX will run a report when the - minute, hour and month of year parameters match the report time, - and at least one of the two day parameters (day of month or day - of week) match the report time. This means that non-existent - times, such as "missing hours" during daylight savings - changeover, will never match, causing reports scheduled during - the "missing times" not to be run. Similarly, times that occur - more than once (again, during daylight savings changeover) will - cause matching reports to be run more than once. -
++ When the report_timing option is in use WeeWX will run a report when the minute, + hour and month of year parameters match the report time, and at least one of the two day parameters (day of + month or day of week) match the report time. This means that non-existent times, such as "missing hours" + during daylight savings changeover, will never match, causing reports scheduled during the "missing times" + not to be run. Similarly, times that occur more than once (again, during daylight savings changeover) will + cause matching reports to be run more than once. +
-- Note
+
Report time does not refer to the time at - which the report is run, but rather the date and time of the - latest data the report is based upon. If you like, it is the - effective date and time of the report. For normal WeeWX - operation, the report time aligns - with the dateTime of the most recent - archive record. When reports are run using the wee_reports utility, the report time is - either the dateTime of the most recent - archive record (the default) or the optional timestamp command - line argument. -+ Note
-
Report time does not refer to the time at which the report is run, but rather the + date and time of the latest data the report is based upon. If you like, it is the effective date and time of + the report. For normal WeeWX operation, the report time aligns with the dateTime + of the most recent archive record. When reports are run using the wee_reports + utility, the report time is either the dateTime of the most recent archive record + (the default) or the optional timestamp command line argument. +- Note
+
The day a report is to be run can be specified - by two parameters; day of month and/or day of week. If both - parameters are restricted (i.e., not an asterisk), the report - will be run when either field matches the current time. For - example,
report_timing = 30 4 - 1,15 * 5
would cause the report to be run at 4:30am on - the 1st and 15th of each month as well as 4:30am every Friday. -+ Note
-
The day a report is to be run can be specified by two parameters; day of month + and/or day of week. If both parameters are restricted (i.e., not an asterisk), the report will be run when + either field matches the current time. For example,
report_timing = 30 4 + 1,15 * 5
would cause the report to be run at 4:30am on the 1st and 15th of each month as well as + 4:30am every Friday. +- The relationship between report_timing - and archive period -
++ The relationship between report_timing and archive period
-- A traditional CRON service has a resolution of one minute, meaning that - the CRON service checks each minute as to whether to execute any - commands. On the other hand, the WeeWX report system checks which - reports are to be run once per archive period, where the archive period - may be one minute, five minutes or some other user defined period. - Consequently, the report_timing option may - specify a report to be run at some time that does not align with the - WeeWX archive period. In such cases cases the - report_timing option does not cause a report - to be run outside of the normal WeeWX report cycle, rather it will - cause the report to be run during the next report cycle. At the start - of each report cycle, and provided a report_timing - option is set, WeeWX will check each minute boundary from the current - report time back until the report time of the previous report cycle. If - a match is found on any of these one minute boundaries the - report will be run during the report cycle. This may be best described - through some examples: -
++ A traditional CRON service has a resolution of one minute, meaning that the CRON service checks each minute + as to whether to execute any commands. On the other hand, the WeeWX report system checks which reports are + to be run once per archive period, where the archive period may be one minute, five minutes or some other + user defined period. Consequently, the report_timing option may specify a report + to be run at some time that does not align with the WeeWX archive period. In such cases cases the report_timing option does not cause a report to be run outside of the normal WeeWX + report cycle, rather it will cause the report to be run during the next report cycle. At the start of each + report cycle, and provided a report_timing option is set, WeeWX will check each + minute boundary from the current report time back until the report time of the previous report cycle. If a + match is found on any of these one minute boundaries the report will be run during the + report cycle. This may be best described through some examples: +
-- -
+- -report_timing -Archive period -When the report will be run -- -0 * * * * -5 minutes -The report will be run only during the report cycle commencing on the hour. -- -5 * * * * -5 minutes -The report will be run only during the report cycle commencing at 5 minutes past the hour. -- -3 * * * * -5 minutes -The report will be run only during the report cycle commencing at 5 minutes past the hour. -- -10 * * * * -15 minutes -The report will be run only during the report cycle commencing at 15 minutes past the hour -- -10,40 * * * * -15 minutes -The report will be run only during the report cycles commencing at 15 minutes past the hour and 45 minutes - past the hour. - -- - -5,10 * * * * -15 minutes -The report will be run once only during the report cycle commencing at 15 minutes past the hour. -+ +
-+ +report_timing +Archive period +When the report will be run ++ +0 * * * * +5 minutes +The report will be run only during the report cycle commencing on the hour. ++ +5 * * * * +5 minutes +The report will be run only during the report cycle commencing at 5 minutes past the hour. ++ +3 * * * * +5 minutes +The report will be run only during the report cycle commencing at 5 minutes past the hour. ++ +10 * * * * +15 minutes +The report will be run only during the report cycle commencing at 15 minutes past the hour ++ +10,40 * * * * +15 minutes +The report will be run only during the report cycles commencing at 15 minutes past the hour and 45 + minutes past the hour. + ++ + +5,10 * * * * +15 minutes +The report will be run once only during the report cycle commencing at 15 minutes past the hour. + +Lists, ranges and steps
+Lists, ranges and steps
-- The report_timing option supports - lists, ranges and steps for all parameters. Lists, ranges and - steps may be used as follows: -
++ The report_timing option supports lists, ranges and steps for all parameters. + Lists, ranges and steps may be used as follows: +
--
-- Lists. A list is a set of numbers (or ranges) separated - by commas, for example 1,2,5,9 or 0-4,8-12. A match with any - of the elements of the list will result in a match for that - particular parameter. If the examples were applied to the - minutes parameter, and subject to other parameters in the report_timing option, the report would be - run at minutes 1,2,5 and 9 and 0,1,2,3,4,8,9,10,11 and 12 - respectively. Abbreviated month and day names cannot be used - in a list. -
++
+- Lists. A list is a set of numbers (or ranges) separated by commas, for example 1,2,5,9 or 0-4,8-12. A + match with any of the elements of the list will result in a match for that particular parameter. If the + examples were applied to the minutes parameter, and subject to other parameters in the report_timing option, the report would be run at minutes 1,2,5 and 9 and + 0,1,2,3,4,8,9,10,11 and 12 respectively. Abbreviated month and day names cannot be used in a list. +
-- Ranges. Ranges are two numbers separated with a hyphen, - for example 8-11. The specified range is inclusive. A match - with any of the values included in the range will result in a - match for that particular parameter. If the example was - applied to the hours parameter, and subject to other - parameters in the report_timing - option, the report would be run at hours 8,9,10 and 11. A - range may be included as an element of a list. Abbreviated - month and day names cannot be used in a range. -
+- Ranges. Ranges are two numbers separated with a hyphen, for example 8-11. The specified range is + inclusive. A match with any of the values included in the range will result in a match for that + particular parameter. If the example was applied to the hours parameter, and subject to other parameters + in the report_timing option, the report would be run at hours 8,9,10 and 11. A + range may be included as an element of a list. Abbreviated month and day names cannot be used in a + range. +
-- Steps. A step can be used in conjunction with a range - or asterisk and are denoted by a '/' followed by a number. - Following a range with a step specifies skips of the step - number's value through the range. For example, 0-12/2 used in - the hours parameter would, subject to other parameter in the report_timing option, run the report at - hours 0,2,4,6,8,12. Steps are also permitted after an asterisk - in which case the skips of the step number's value occur - through the all possible values of the parameter. For example, - */3 can be used in the hours parameter to, subject to other - parameter in the report_timing - option, run the report at hours 0,3,6,9,12,15,18 and 21. -
-- Steps. A step can be used in conjunction with a range or asterisk and are denoted by a '/' followed by a + number. Following a range with a step specifies skips of the step number's value through the range. For + example, 0-12/2 used in the hours parameter would, subject to other parameter in the report_timing + option, run the report at hours 0,2,4,6,8,12. Steps are also permitted after an asterisk in which case + the skips of the step number's value occur through the all possible values of the parameter. For + example, */3 can be used in the hours parameter to, subject to other parameter in the report_timing option, run the report at hours 0,3,6,9,12,15,18 and 21. +
+Nicknames
+Nicknames
-- The report_timing option supports a - number of time specification 'nicknames'. These nicknames are - prefixed by the '@' character and replace the five parameters in - the report_timing option. The - nicknames supported are: -
++ The report_timing option supports a number of time specification 'nicknames'. + These nicknames are prefixed by the '@' character and replace the five parameters in the report_timing + option. The nicknames supported are: +
-- -
+- -Nickname -Equivalent setting - -When the report will be run -- -@yearly -
@annually -0 0 1 1 * -Once per year at midnight on 1 January. -- -@monthly -0 0 1 * * -Monthly at midnight on the 1st of the month. -- -@weekly -0 0 * * 0 -Every week at midnight on Sunday. -- -@daily -0 0 * * * -Every day at midnight. -- - -@hourly -0 * * * * -Every hour on the hour. -+ +
-+ +Nickname +Equivalent setting + +When the report will be run ++ +@yearly +
@annually +0 0 1 1 * +Once per year at midnight on 1 January. ++ +@monthly +0 0 1 * * +Monthly at midnight on the 1st of the month. ++ +@weekly +0 0 * * 0 +Every week at midnight on Sunday. ++ +@daily +0 0 * * * +Every day at midnight. ++ + +@hourly +0 * * * * +Every hour on the hour. +- report_timing option examples -
++ report_timing option examples
-- Numeric settings for report_timing can - be at times difficult to understand due to the complex - combinations of parameters. The following table shows a number - of example report_timing options and - the corresponding times when the report would be run. -
++ Numeric settings for report_timing can be at times difficult to understand due to + the complex combinations of parameters. The following table shows a number of example report_timing + options and the corresponding times when the report would be run. +
-- -
+- -report_timing -When the report will be run -- -* * * * * -Every archive period. This setting is effectively - the default WeeWX method of operation. - -- -25 * * * * -25 minutes past every hour. -- -0 * * * * -Every hour on the hour. -- -5 0 * * * -00:05 daily. -- -25 16 * * * -16:25 daily. -- -25 16 1 * * -16:25 on the 1st of each month. -- -25 16 1 2 * -16:25 on the 1st of February. -- -25 16 * * 0 -16:25 each Sunday. -- -*/10 * * * * -On the hour and 10, 20, 30, 40 and 50 mnutes past - the hour. - -- -*/9 * * * * -On the hour and 9, 18, 27, 36, 45 and 54 minutes - past the hour. - -- -*/10 */2 * * * -0, 10, 20, 30, 40 and 50 minutes after the even - hour. - -- -* 6-17 * * * -Every archive period from 06:00 (inclusive) up - until, but excluding, 18:00. - -- -* 1,4,14 * * * -Every archive period in the hour starting 01:00 to - 01:59, 04:00 to 04:59 amd 14:00 to 14:59 (Note excludes - report times at 02:00, 05:00 and 15:00). - -- -0 * 1 * 0,3 -On the hour on the first of the month and on the - hour every Sunday and Wednesday. - -- -* * 21,1-10/3 6 * -Every archive period on the 1st, 4th, 7th, 10th and - 21st of June. - -- - -@monthly -Midnight on the 1st of the month. -+ +
-+ +report_timing +When the report will be run ++ +* * * * * +Every archive period. This setting is effectively the default WeeWX method of operation. + ++ +25 * * * * +25 minutes past every hour. ++ +0 * * * * +Every hour on the hour. ++ +5 0 * * * +00:05 daily. ++ +25 16 * * * +16:25 daily. ++ +25 16 1 * * +16:25 on the 1st of each month. ++ +25 16 1 2 * +16:25 on the 1st of February. ++ +25 16 * * 0 +16:25 each Sunday. ++ +*/10 * * * * +On the hour and 10, 20, 30, 40 and 50 mnutes past the hour. + ++ +*/9 * * * * +On the hour and 9, 18, 27, 36, 45 and 54 minutes past the hour. + ++ +*/10 */2 * * * +0, 10, 20, 30, 40 and 50 minutes after the even hour. + ++ +* 6-17 * * * +Every archive period from 06:00 (inclusive) up until, but excluding, 18:00. + ++ +* 1,4,14 * * * +Every archive period in the hour starting 01:00 to 01:59, 04:00 to 04:59 amd 14:00 to 14:59 (Note + excludes report times at 02:00, 05:00 and 15:00). + ++ +0 * 1 * 0,3 +On the hour on the first of the month and on the hour every Sunday and Wednesday. + ++ +* * 21,1-10/3 6 * +Every archive period on the 1st, 4th, 7th, 10th and 21st of June. + ++ + +@monthly +Midnight on the 1st of the month. +- The wee_reports utility and the report_timing option -
++ The wee_reports utility and the report_timing option +
-- The report_timing option is ignored - when using the wee_reports utility. -
++ The report_timing option is ignored when using the wee_reports + utility. +
-- The skin configuration file skin.conf -
++ The skin configuration file skin.conf +
-- This section is a reference to the options appearing in the skin - configuration file, skin.conf. For - a given skin, it is located in its skin directory. For example, for the skin Seasons, - it is located in SKIN_ROOT/Seasons/skin.conf. -
++ This section is a reference to the options appearing in the skin configuration file, skin.conf. + For a given skin, it is located in its skin directory. For example, for the skin Seasons, it is + located in SKIN_ROOT/Seasons/skin.conf. +
-- The most important options, the ones you are likely to have to - customize, are highlighted. -
++ The most important options, the ones you are likely to have to customize, are highlighted. +
-- It is worth noting that, like the main configuration file weewx.conf, UTF-8 is used throughout. -
++ It is worth noting that, like the main configuration file weewx.conf, UTF-8 is + used throughout. +
-[Extras]
+[Extras]
-This section is available to add any static tags you might - want to use in your templates.
+This section is available to add any static tags you might want to use in your templates.
-Example
+Example
-- As an example, the Standard skin.conf - file includes three options: -
--
-- -Skin option -Template tag -- -radar_img -$Extras.radar_img -- -radar_url -$Extras.radar_url -- -googleAnalyticsId -$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_img to find - them). -
++ As an example, the Standard skin.conf file includes three options: +
++
++ +Skin option +Template tag ++ +radar_img +$Extras.radar_img ++ +radar_url +$Extras.radar_url ++ +googleAnalyticsId +$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_img to find them). +
-radar_img
+radar_img
-Set to an URL to show a local radar image for you.
+Set to an URL to show a local radar image for you.
-radar_url
+radar_url
-If the above radar image is clicked, the browser will go to - this URL. This is usually used to show a more detailed, - close-up, radar picture.
+If the above radar image is clicked, the browser will go to this URL. This is usually used to show a more + detailed, close-up, radar picture. +
-For me in Oregon, setting the above two options to:
-+For me in Oregon, setting the above two options to:
+[Extras] radar_img = http://radar.weather.gov/ridge/lite/N0R/RTX_loop.gif radar_url = http://radar.weather.gov/ridge/radar.php?product=NCR&rid=RTX&loop=yes-- results in a nice image of a radar centered on Portland, Oregon. - When you click on it, it gives you a detailed, animated view. If - you live in the USA, take a look at the NOAA radar website to - find a nice one that will work for you. In other countries, you - will have to consult your local weather service. -
++ results in a nice image of a radar centered on Portland, Oregon. When you click on it, it gives you a + detailed, animated view. If you live in the USA, take a look at the NOAA + radar website to find a nice one that will work for you. In other countries, you will have to consult + your local weather service. +
-googleAnalyticsId
+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. -
++ 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] -
++ Extending [Extras] +
-Other tags can be added in a similar manner, including - sub-sections. For example, say you have added a video camera and - you would like to add a still image with a hyperlink to a page - with the video. You want all of these options to be neatly - contained in a sub-section.
-[Extras] +Other tags can be added in a similar manner, including sub-sections. For example, say you have added a video + camera and you would like to add a still image with a hyperlink to a page with the video. You want all of + these options to be neatly contained in a sub-section. +
+[Extras] [[video]] still = video_capture.jpg hyperlink = http://www.eatatjoes.com/video.html-Then in your template you could refer to these as:
-<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]
+[Units]
-This section deals with Units and their formatting.
+This section deals with Units and their formatting.
-[[Groups]]
+[[Groups]]
-- This sub-section lists all the Unit Groups and - specifies which unit system is to be used for each one of them. -
++ This sub-section lists all the Unit Groups and specifies which unit system is to be used for each + one of them. +
-- As there are many different observational measurement types - (such as outTemp, barometer, - etc.) used in WeeWX (more than 50 at - last count), it would be tedious, not to say possibly - inconsistent, to specify a different measurement system for each - one of them. At the other extreme, requiring all of them to be - "U.S. Customary" or "Metric" seems overly restrictive. WeeWX - has taken a middle route and divided - all the different observation types into 12 different unit - groups. A unit group is something like group_temperature. - It represents the measurement system to be used by all - observation types that are measured in temperature, such as - inside temperature (type inTemp), - outside temperature (outTemp), - dewpoint (dewpoint), wind chill (windchill), and so on. If you decide that - you want unit group group_temperature - to be measured in degree_C then you - are saying all members of its group will be reported in - degrees Celsius. -
++ 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. -
++ 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 -
++ group_altitude +
-- Which measurement unit to be used for altitude. Possible options - are foot or meter. -
++ Which measurement unit to be used for altitude. Possible options are foot or meter. +
-group_direction
+group_direction
-- Which measurement unit to be used for direction. The only option - is degree_compass. -
++ Which measurement unit to be used for direction. The only option is degree_compass. +
-group_moisture
+group_moisture
-- The measurement unit to be used for soil moisture. The only - option is centibar. -
++ The measurement unit to be used for soil moisture. The only option is centibar. +
-group_percent
+group_percent
-- The measurement unit to be used for percentages. The only option - is percent. -
++ The measurement unit to be used for percentages. The only option is percent. +
-group_pressure
+group_pressure
-- The measurement unit to be used for pressure. Possible options - are one of inHg (inches of mercury), mbar, or hPa. -
++ The measurement unit to be used for pressure. Possible options are one of inHg + (inches of mercury), mbar, or hPa. +
-group_radiation
+group_radiation
-- The measurement unit to be used for radiation. The only option - is watt_per_meter_squared. -
++ The measurement unit to be used for radiation. The only option is watt_per_meter_squared. +
-group_rain
+group_rain
-- The measurement unit to be used for precipitation. Options are inch, cm, or mm. -
++ The measurement unit to be used for precipitation. Options are inch, cm, or mm. +
-group_rainrate
+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. -
++ 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
+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. -
++ 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
+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. -
++ 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. +
- + -- The measurement unit to be used for temperatures. Options are degree_F or degree_C. -
++ The measurement unit to be used for temperatures. Options are degree_F or degree_C. +
-group_volt
+group_volt
-- The measurement unit to be used for voltages. The only option is - volt. -
++ The measurement unit to be used for voltages. The only option is volt. +
-[[StringFormats]]
+[[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 +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, and are very - similar to C's sprintf() codes. -
++ 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, 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 "++ You can also specify what string to use for an invalid or unavailable measurement (value None). + For example, +
+NONE = " N/A "-[[Labels]]
+[[Labels]]
-This sub-section specifies what label is to be used for - each measurement unit type. For example, the options
-degree_F = °F +This sub-section specifies what label is to be used for each measurement unit type. For example, the + options +
+degree_F = °F inch = ' in'-- would cause all temperatures to have unit labels °F and all precipitation to have labels in. If any special symbols are to be used - (such as the degree sign above) they should be encoded in UTF-8. - This is generally what most text editors use if you - cut-and-paste from a character map. -
++ 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. +
-If the label includes two values, then the first is assumed - to be the singular form, the second the plural form. For - example,
-foot = " foot", " feet" +If the label includes two values, then the first is assumed to be the singular form, the second the plural + form. For example, +
+foot = " foot", " feet" ... day = " day", " days" hour = " hour", " hours" minute = " minute", " minutes" second = " second", " seconds"-- This is particularly useful when localizing - the WeeWX and server uptimes. -
++ This is particularly useful when localizing the WeeWX and server uptimes. +
-[[TimeFormats]]
+[[TimeFormats]]
-- This sub-section is used for time labels. It uses strftime() - formats. The default looks like this: -
-+-+ This sub-section is used for time labels. It uses strftime() formats. The default + looks like this: +
+[[TimeFormats]] # This section sets the string format to be used for each time scale. # The values below will work in every locale, but may not look @@ -4195,18 +3615,15 @@ second = " second", " seconds"ephem_day = %X ephem_year = %x %X- The specifiers %x, %X, - and %A code locale dependent date, - time, and weekday names, respectively. Hence, if you set an - appropriate environment variable LANG, - then the date and times should follow local conventions (see - section Environment - variable LANG for details on how to do this). However, they - will not look particularly pretty and you may want to change - them. For example, I use this in the U.S.: -
-+-+ The specifiers %x, %X, and %A + code locale dependent date, time, and weekday names, respectively. Hence, if you set an appropriate + environment variable LANG, then the date and times should follow local conventions + (see section Environment variable LANG for details on how to do + this). However, they will not look particularly pretty and you may want to change them. For example, I use + this in the U.S.: +
+[[TimeFormats]] # # More attractive formats that work in most Western countries. @@ -4220,300 +3637,264 @@ second = " second", " seconds"ephem_day = %H:%M ephem_year = %d-%b-%Y %H:%M- The last two formats, ephem_day and ephem_year allow the formatting to be set - for almanac times The first, ephem_day, - is used for almanac times within the day, such as sunrise or - sunset. The second, ephem_year, is - used for almanac times within the year, such as the next equinox - or full moon. -
++ The last two formats, ephem_day and ephem_year allow the + formatting to be set for almanac times The first, ephem_day, is used for almanac + times within the day, such as sunrise or sunset. The second, ephem_year, is used + for almanac times within the year, such as the next equinox or full moon. +
-[[Ordinates]]
+[[Ordinates]]
-directions
+directions
-- Set to the abbreviations to be used for ordinal directions. By - default, this is N, NNE, NE, ENE, E, +
-+ Set to the abbreviations to be used for ordinal directions. By default, this is N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW, N. -
+[[DegreeDays]]
+[[DegreeDays]]
-- heating_base
+
cooling_base -+ heating_base
-
cooling_base +Set to the base temperature for calculating heating and - cooling degree-days, along with the unit to be used. Examples:
-heating_base = 65.0, degree_F +Set to the base temperature for calculating heating and cooling degree-days, along with the unit to be used. + Examples: +
+heating_base = 65.0, degree_F cooling_base = 20.0, degree_C-[[Trend]]
+[[Trend]]
-time_delta
+time_delta
-Set to the time difference over which you want trends to be - calculated. The default is 3 hours.
+Set to the time difference over which you want trends to be calculated. The default is 3 hours.
-time_grace
+time_grace
-- When searching for a previous record to be used in calculating a - trend, a record within this amount of time_delta - will be accepted. Default is 300 seconds. -
++ When searching for a previous record to be used in calculating a trend, a record within this amount of time_delta will be accepted. Default is 300 seconds. +
-[Labels]
+[Labels]
-This section sets the various labels to use.
+This section sets the various labels to use.
-hemispheres
+hemispheres
-- Comma separated list for the labels to be used for the four - hemispheres. The default is N, S, E, W. -
++ Comma separated list for the labels to be used for the four hemispheres. The default is N, S, E, W. +
-latlon_formats
+latlon_formats
-Comma separated list for the formatting to be used when - converting latitude and longitude to strings. There should be - three elements:
--
-- The format to be used for whole degrees of latitude
-- The format to be used for whole degrees of longitude
-- The format to be used for minutes.
-This allows you to decide whether or not you want leading - zeroes. The default includes leading zeroes and is - "%02d", "%03d", "%05.2f"
+Comma separated list for the formatting to be used when converting latitude and longitude to strings. There + should be three elements: +
++
+- The format to be used for whole degrees of latitude
+- The format to be used for whole degrees of longitude
+- The format to be used for minutes.
+This allows you to decide whether or not you want leading zeroes. The default includes leading zeroes and is + "%02d", "%03d", "%05.2f" +
-[[Generic]]
+[[Generic]]
-This sub-section specifies default labels to be used for - each observation type. For example, options
-inTemp = Temperature inside the house +This sub-section specifies default labels to be used for each observation type. For example, options
+inTemp = Temperature inside the house outTemp = Outside Temperature UV = UV Index-- would cause the given labels to be used for plots of inTemp and outTemp. - If no option is given, then the observation type itself will be - used (e.g., outTemp). -
++ would cause the given labels to be used for plots of inTemp and outTemp. If no option is given, then the observation type itself will be used + (e.g., outTemp). +
-[Almanac]
+[Almanac]
-This section controls what text to use for the almanac. It - consists of only one entry
+This section controls what text to use for the almanac. It consists of only one entry
-moon_phases
+moon_phases
-- This option is a comma separated list of labels to be used for - the eight phases of the moon. Default is New, +
-+ This option is a comma separated list of labels to be used for the eight phases of the moon. Default is + New, Waxing crescent, First quarter, Waxing gibbous, Full, Waning gibbous, Last quarter, Waning crescent. -
+[CheetahGenerator]
+[CheetahGenerator]
-- This section is used by generator weewx.cheetahgenerator.CheetahGenerator - and controls text generation from templates, specifically which - files are to be produced from which template. -
++ This section is used by generator weewx.cheetahgenerator.CheetahGenerator and + controls text generation from templates, specifically which files are to be produced from which template. +
-Overview of file generation
+Overview of file generation
-- Files are generated from templates, and each template is - identified by the template - parameter. -
++ Files are generated from templates, and each template is identified by the template + parameter. +
-- Each template file is named something like D/F.E.tmpl, - where D is the (optional) directory - the template sits in and will also be the directory the results - will be put in, and F.E is the - generated file name. So, given a template file with name Acme/index.html.tmpl, the results will be - put in HTML_ROOT/Acme/index.html. -
++ Each template file is named something like D/F.E.tmpl, where D is the (optional) directory the template sits in and will also be the directory the + results will be put in, and F.E is the generated file name. So, given a template + file with name Acme/index.html.tmpl, the results will be put in HTML_ROOT/Acme/index.html. +
-The configuration for a group of templates will look - something like this:
-[CheetahGenerator] +The configuration for a group of templates will look something like this:
+[CheetahGenerator] [[index]] template = index.html.tmpl [[textfile]] template = filename.txt.tmpl [[xmlfile]] template = filename.xml.tmpl-- There can be only one template - in each block. In most cases, the block name does not matter - — it is used only to isolate each template. However, there - are three block names that have special meaning: SummaryByMonth, SummaryByYear, - and ToDate. They are described below. -
++ There can be only one template in each block. In most cases, the block + name does not matter — it is used only to isolate each template. However, there are three block names + that have special meaning: SummaryByMonth, SummaryByYear, + and ToDate. They are described below. +
-The file generator runs on each new archive record. In a - default WeeWX installation, that would be every 5 minutes.
+The file generator runs on each new archive record. In a default WeeWX installation, that would be every 5 + minutes. +
-- Cheetah processes each template to generate a file. Cheetah - follows any logic defined by directives such as for or if ... - else, and it replaces variables such as $Extras.radar_url - or $current.outTemp.max. -
++ Cheetah processes each template to generate a file. Cheetah follows any logic defined by directives such as + for or if ... + else, and it replaces variables such as $Extras.radar_url or $current.outTemp.max. +
-Variables are defined by objects in WeeWX. Some variables - are static, others are linked to data in databases. The list of - variables can be extended.
+Variables are defined by objects in WeeWX. Some variables are static, others are linked to data in databases. + The list of variables can be extended. +
-File generation options
+File generation options
-search_list
+search_list
-- This is the list of search list objects that will be scanned by - the template engine, looking for tags. See the section Defining new tags and the Cheetah - documentation for details on search lists. If no search_list is specified, a - default list will be used. The default list is: -
-search_list = weewx.cheetahgenerator.Almanac, weewx.cheetahgenerator.Station, weewx.cheetahgenerator.Stats, weewx.cheetahgenerator.UnitInfo, weewx.cheetahgenerator.Extras-search_list_extensions
++ This is the list of search list objects that will be scanned by the template engine, looking for tags. See + the section Defining new tags and the Cheetah documentation for details on search lists. If + no search_list is specified, a default list will be used. The default + list is: +
+search_list = weewx.cheetahgenerator.Almanac, weewx.cheetahgenerator.Station, weewx.cheetahgenerator.Stats, weewx.cheetahgenerator.UnitInfo, weewx.cheetahgenerator.Extras+search_list_extensions
-- This defines one or more search list objects that will be - appended to the search_list. - For example, the following adds alltime and forecast variables - to the search list. -
-search_list_extensions = user.stats.MyStats, user.forecast.ForecastVariables-encoding
++ This defines one or more search list objects that will be appended to the search_list. + For example, the following adds alltime and forecast variables to the search list. +
+search_list_extensions = user.stats.MyStats, user.forecast.ForecastVariables+encoding
-- As Cheetah goes through the template, it substitutes strings for all tag values. - This option controls which encoding to use for the new strings. The encoding - can be chosen on a per file basis. There are 3 possible choices: -
-- -
-- -Encoding -Comments -- -html_entities -Non 7-bit characters will be represented as HTML - entities (e.g., the degree sign will be - represented as °) - -- -utf8 -Non 7-bit characters will be represented in UTF-8. -- - -strict_ascii -Non 7-bit characters will be ignored. -- The encoding html_entities is the - default. -
++ As Cheetah goes through the template, it substitutes strings for all tag values. This option controls which + encoding to use for the new strings. The encoding can be chosen on a per file basis. There are 3 possible + choices: +
++ +
++ +Encoding +Comments ++ +html_entities +Non 7-bit characters will be represented as HTML entities (e.g., the degree sign will be + represented as °) + ++ +utf8 +Non 7-bit characters will be represented in UTF-8. ++ + +strict_ascii +Non 7-bit characters will be ignored. ++ The encoding html_entities is the default. +
-template
+template
-- The name of a template file. A template filename must end with .tmpl. Filenames are case-sensitive. If - the template filename has the letters YYYY, - MM, WW or - DD in its name, these will be - substituted for the year, month, week and day of month, respectively. - So, a template with the name - summary-YYYY-MM.html.tmpl would have name - summary-2010-03.html for the month of - March, 2010. -
++ The name of a template file. A template filename must end with .tmpl. Filenames + are case-sensitive. If the template filename has the letters YYYY, MM, WW or DD in its name, these will + be substituted for the year, month, week and day of month, respectively. So, a template with the name summary-YYYY-MM.html.tmpl would have name summary-2010-03.html + for the month of March, 2010. +
-stale_age
+stale_age
-- File staleness age, in seconds. If the file is older than this - age it will be generated from the template. If no stale_age is specified, then the file will - be generated every time the generator runs. -
++ File staleness age, in seconds. If the file is older than this age it will be generated from the template. + If no stale_age is specified, then the file will be generated every time the + generator runs. +
-- Note
+
Precise control over when a - report is run is available through - use of the report_timing option in - weewx.conf. The report_timing - option uses a CRON-like setting to control precisely when a report is run. - See the Customizing the report generation time - section for details on the report_timing option. -+ Note
-
Precise control over when a report + is run is available through use of the report_timing option in weewx.conf. + The report_timing option uses a CRON-like setting to control precisely when a + report is run. See the Customizing the report generation time + section for details on the report_timing option. +[[SummaryByMonth]]
+[[SummaryByMonth]]
-- The SummaryByMonth section defines - some special behavior. Each template in this section will be - used multiple times, each time with a different per-month - timespan. Be sure to include YYYY and - MM in the filename of any template in - this section. -
++ The SummaryByMonth section defines some special behavior. Each template in this + section will be used multiple times, each time with a different per-month timespan. Be sure to include YYYY and MM in the filename of any template in this section. +
-[[SummaryByYear]]
+[[SummaryByYear]]
-- The SummaryByYear section defines some - special behavior. Each template in this section will be used - multiple times, each time with a different per-year timespan. Be - sure to include YYYY in the filename - of any template in this section. -
++ The SummaryByYear section defines some special behavior. Each template in this + section will be used multiple times, each time with a different per-year timespan. Be sure to include YYYY in the filename of any template in this section. +
-Customizing file generation
+Customizing file generation
-The best way to customize file generation is to make a copy - of a working report/skin, then make incremental changes.
+The best way to customize file generation is to make a copy of a working report/skin, then make incremental + changes. +
-- When there is an error during template generation, the error - will show up in the log file. Many errors are obvious — - Cheetah will display a line number and list the template file in - which the error occurred. In some cases the error reporting is - rather obscure. So make small changes and test often. Use the - utility wee_reports - to test modifications to the generator configuration and/or the - template contents. -
++ When there is an error during template generation, the error will show up in the log file. Many errors are + obvious — Cheetah will display a line number and list the template file in which the error occurred. + In some cases the error reporting is rather obscure. So make small changes and test often. Use the utility + wee_reports to test modifications to the generator + configuration and/or the template contents. +
-The Seasons skin templates
+The Seasons skin templates
-- By way of example, here is the [CheetahGenerator] section - from the skin.conf for the skin Seasons. -
++ By way of example, here is the [CheetahGenerator] section from the skin.conf for the skin Seasons. +
-[CheetahGenerator] +-[CheetahGenerator] # The CheetahGenerator creates files from templates. This section # specifies which files will be generated from which template. @@ -4551,537 +3932,467 @@ UV = UV Indextemplate = rss.xml.tmplThe skin contains three different kinds of generated output:
--
-- Summary by Month. The Seasons skin uses SummaryByMonth to produce NOAA summaries, - one for each month, as a simple text file. -
-- Summary by Year. The skin uses SummaryByYear to produce NOAA summaries, - one for each year, as a simple text file. -
-- Summary "To Date". The Seasons skin produces an HTML index.html page, - as well as HTML files for detailed statistics, telemetry, and celestial information. It also - includes a master page (tabular.html) in which NOAA information is - displayed. All these files are HTML. -
-- The encoding for text files is strict_ascii, - whereas the encoding for html files is html_entities. - This was specified by declaring encoding = html_entities at the top level - of [CheetahGenerator] then encoding = strict_ascii for each text - file. -
+The skin contains three different kinds of generated output:
++
+- Summary by Month. The Seasons skin uses SummaryByMonth to produce + NOAA summaries, one for each month, as a simple text file. +
+- Summary by Year. The skin uses SummaryByYear to produce NOAA summaries, one + for each year, as a simple text file. +
+- Summary "To Date". The Seasons skin produces an HTML index.html page, + as well as HTML files for detailed statistics, telemetry, and celestial information. It also includes a + master page (tabular.html) in which NOAA information is displayed. All these + files are HTML. +
++ The encoding for text files is strict_ascii, whereas the encoding for html files + is html_entities. This was specified by declaring encoding = html_entities + at the top level of [CheetahGenerator] then encoding = strict_ascii + for each text file. +
-- Other than SummaryByMonth and SummaryByYear, the section names are - arbitrary. ToDate could just as well - have been called files_to_date, and - the sections day, week, - and month could just as well have been - called tom, dick, - and harry. -
++ Other than SummaryByMonth and SummaryByYear, the section + names are arbitrary. ToDate could just as well have been called files_to_date, and the sections day, week, and month could just as well have been called tom, dick, and harry. +
-[ImageGenerator]
+[ImageGenerator]
-This section describes the various options available to the - image generator.
+This section describes the various options available to the image generator.
--+ - ++
+- - --
Part names in a WeeWX image-Overall options
- -These are options that affect the overall image.
- -- image_width
- -
image_height -The width and height of the image in pixels. Optional. - Default is 300 x 180 pixels.
- -image_background_color
- -- The background color of the whole image. Optional. Default is 0xf5f5f5 ("SmokeGray") -
- -chart_background_color
- -- The background color of the chart itself. Optional. Default is 0xd8d8d8. -
- -chart_gridline_color
- -- The color of the chart grid lines. Optional. Default is 0xa0a0a0 -
- --- +--- -
- A GIF showing the same image with anti_alias=1, - 2, and 4. +-Part names in a WeeWX image---
Example of day/night bands in - a one week image + +-Overall options
+ +These are options that affect the overall image.
+ ++ image_width
+ +
image_height +The width and height of the image in pixels. Optional. Default is 300 x 180 pixels.
+ +image_background_color
+ ++ The background color of the whole image. Optional. Default is 0xf5f5f5 + ("SmokeGray") +
+ +chart_background_color
+ ++ The background color of the chart itself. Optional. Default is 0xd8d8d8. +
+ +chart_gridline_color
+ ++ The color of the chart grid lines. Optional. Default is 0xa0a0a0 +
+ ++-+++ +
+ A GIF showing the same image with anti_alias=1, 2, and 4. ++++ +
Example of day/night bands in a one week image ++anti_alias
+anti_alias
-- Setting to 2 or more might give a sharper image, with fewer - jagged edges. Experimentation is in order. Default is 1. -
++ Setting to 2 or more might give a sharper image, with fewer jagged edges. Experimentation is in order. + Default is 1. +
-show_daynight
+show_daynight
-- Set to true to show day/night bands in - an image. Otherwise, set to false. This only looks good with day - or week plots. Optional. Default is false. -
++ Set to true to show day/night bands in an image. Otherwise, set to false. This + only looks good with day or week plots. Optional. Default is false. +
-daynight_day_color
+daynight_day_color
-- The color to be used for the daylight band. Optional. Default is - 0xffffff. -
++ The color to be used for the daylight band. Optional. Default is 0xffffff. +
-daynight_night_color
+daynight_night_color
-- The color to be used for the nighttime band. Optional. Default - is 0xf0f0f0, a dark gray. -
++ The color to be used for the nighttime band. Optional. Default is 0xf0f0f0, a dark + gray. +
-daynight_edge_color
+daynight_edge_color
-- The color to be used in the transition zone between night and - day. Optional. Default is 0xefefef, a - mid-gray. -
++ The color to be used in the transition zone between night and day. Optional. Default is 0xefefef, + a mid-gray. +
-Various label options
+Various label options
-These are options for the various labels used in the image.
+These are options for the various labels used in the image.
-top_label_font_path
+top_label_font_path
-- The path to the font to be use for the top label. Optional. If - not given, or if WeeWX cannot find the - font, then the default PIL font will be used. -
++ The path to the font to be use for the top label. Optional. If not given, or if WeeWX cannot find the font, + then the default PIL font will be used. +
-top_label_font_size
+top_label_font_size
-- The size of the top label in pixels. Optional. The default is 10. -
++ The size of the top label in pixels. Optional. The default is 10. +
-unit_label_font_path
+unit_label_font_path
-- The path to the font to be use for the unit label. Optional. If - not given, or if WeeWX cannot find the - font, then the default PIL font will be used. -
++ The path to the font to be use for the unit label. Optional. If not given, or if WeeWX cannot find the font, + then the default PIL font will be used. +
-unit_label_font_size
+unit_label_font_size
-- The size of the unit label in pixels. Optional. The default is 10. -
++ The size of the unit label in pixels. Optional. The default is 10. +
-unit_label_font_color
+unit_label_font_color
-- The color of the unit label font. Optional. Default is black. -
++ The color of the unit label font. Optional. Default is black. +
-bottom_label_font_path
+bottom_label_font_path
-- The path to the font to be use for the bottom label. Optional. - If not given, or if WeeWX cannot find - the font, then the default PIL font will be used. -
++ The path to the font to be use for the bottom label. Optional. If not given, or if WeeWX cannot find the + font, then the default PIL font will be used. +
-bottom_label_font_size
+bottom_label_font_size
-- The size of the bottom label in pixels. Optional. The default is - 10. -
++ The size of the bottom label in pixels. Optional. The default is 10. +
-bottom_label_font_color
+bottom_label_font_color
-- The color of the bottom label font. Optional. Default is black. -
++ The color of the bottom label font. Optional. Default is black. +
-bottom_label_format
+bottom_label_format
-- The format to be used for the bottom label. It should be a - strftime format. Optional. Default is '%m/%d/%y +
-+ The format to be used for the bottom label. It should be a strftime format. + Optional. Default is '%m/%d/%y %H:%M'. -
+bottom_label_offset
+bottom_label_offset
-The margin of the bottom label from the bottom of the plot. - Default is 3.
+The margin of the bottom label from the bottom of the plot. Default is 3.
-axis_label_font_path
+axis_label_font_path
-- The path to the font to be use for the x- and y-axis labels. - Optional. If not given, or if WeeWX - cannot find the font, then the default PIL font will be used. -
++ The path to the font to be use for the x- and y-axis labels. Optional. If not given, or if WeeWX cannot find + the font, then the default PIL font will be used. +
-axis_label_font_size
+axis_label_font_size
-- The size of the x- and y-axis labels in pixels. Optional. The - default is 10. -
++ The size of the x- and y-axis labels in pixels. Optional. The default is 10. +
-axis_label_font_color
+axis_label_font_color
-- The color of the x- and y-axis label font. Optional. Default is - black. -
++ The color of the x- and y-axis label font. Optional. Default is black. +
-x_label_format
+x_label_format
-- The format to be used for the time labels on the x-axis. It - should be a - strftime format. Optional. If not given, a sensible format - will be chosen automatically. -
++ The format to be used for the time labels on the x-axis. It should be a strftime format. + Optional. If not given, a sensible format will be chosen automatically. +
-x_interval
+x_interval
-- The time interval in seconds between x-axis tick marks. Optional. - If not given, a suitable default will be chosen. -
++ The time interval in seconds between x-axis tick marks. Optional. If not given, a suitable default will be + chosen. +
-x_label_spacing
+x_label_spacing
-- Specifies the ordinal increment between labels on the x-axis: - For example, 3 means a label every 3rd tick mark. - Optional. The default is 2. -
++ Specifies the ordinal increment between labels on the x-axis: For example, 3 means a label every 3rd tick + mark. Optional. The default is 2. +
-y_label_spacing
+y_label_spacing
-- Specifies the ordinal increment between labels on the y-axis: - For example, 3 means a label every 3rd tick mark. - Optional. The default is 2. -
++ Specifies the ordinal increment between labels on the y-axis: For example, 3 means a label every 3rd tick + mark. Optional. The default is 2. +
-y_nticks
+y_nticks
-- The nominal number of ticks along the y-axis. The default is 10. -
++ The nominal number of ticks along the y-axis. The default is 10. +
-stale_age
+stale_age
-- Image file staleness age, in seconds. If the image file is older than - this age it will be generated. If no stale_age - is specified, then the image file will be generated every time the - generator runs. -
++ Image file staleness age, in seconds. If the image file is older than this age it will be generated. If no + stale_age is specified, then the image file will be generated every time the + generator runs. +
-Plot scaling options
+Plot scaling options
-time_length
+time_length
-- The nominal length of the time period to be covered in seconds. - The exact length of the x-axis is chosen by the plotting engine - to cover this period. Optional. Default is 86400 - (one day). -
++ The nominal length of the time period to be covered in seconds. The exact length of the x-axis is chosen by + the plotting engine to cover this period. Optional. Default is 86400 (one day). +
-yscale
+yscale
-- A 3-way tuple (ylow, yhigh, min_interval), - where ylow and yhigh - are the minimum and maximum y-axis values, respectively, and min_interval is the minimum tick interval. - If set to None, the corresponding - value will be automatically chosen. Optional. Default is None, None, None. (Choose the y-axis - minimum, maximum, and minimum increment automatically.) -
++ A 3-way tuple (ylow, yhigh, min_interval), + where ylow and yhigh are the minimum and maximum y-axis + values, respectively, and min_interval is the minimum tick interval. If set to + None, the corresponding value will be automatically chosen. Optional. Default is + None, None, None. (Choose the y-axis minimum, maximum, and minimum increment + automatically.) +
-Compass rose options
+Compass rose options
---+
++-
Example of a vector plot with a - compass rose in the lower-left --Example of a vector plot with a compass rose in the lower-left ++rose_label
+rose_label
-- The label to be used in the compass rose to indicate due North. - Optional. Default is N. -
++ The label to be used in the compass rose to indicate due North. Optional. Default is N. +
-rose_label_font_path
+rose_label_font_path
-- The path to the font to be use for the rose label (the letter - "N," indicating North). Optional. If not given, or if WeeWX - cannot find the font, then the default PIL font will be used. -
++ The path to the font to be use for the rose label (the letter "N," indicating North). Optional. If not + given, or if WeeWX cannot find the font, then the default PIL font will be used. +
-rose_label_font_size
+rose_label_font_size
-- The size of the compass rose label in pixels. Optional. The - default is 10. -
++ The size of the compass rose label in pixels. Optional. The default is 10. +
-rose_label_font_color
+rose_label_font_color
-The color of the compass rose label. Optional. Default is - the same color as the rose itself.
+The color of the compass rose label. Optional. Default is the same color as the rose itself.
-vector_rotate
+vector_rotate
-- Causes the vectors to be rotated by this many degrees. Positive - is clockwise. If westerly winds dominate at your location (as - they do at mine), then you may want to specify +90 for this option. This will cause the - average vector to point straight up, rather than lie flat - against the x-axis. Optional. The default is 0. -
++ Causes the vectors to be rotated by this many degrees. Positive is clockwise. If westerly winds dominate at + your location (as they do at mine), then you may want to specify +90 for this + option. This will cause the average vector to point straight up, rather than lie flat against the x-axis. + Optional. The default is 0. +
-Shared plot line options
+Shared plot line options
-These are options shared by all the plot lines.
+These are options shared by all the plot lines.
-chart_line_colors
+chart_line_colors
-- Each chart line is drawn in a different color. This option is a - list of those colors. If the number of lines exceeds the length - of the list, then the colors wrap around to the beginning of the - list. NB: individual line color can be overridden by using - option color. Optional. In the case of - bar charts, this is the color of the outline of the bar. Default - is 0xff0000, 0x00ff00, 0x0000ff. -
++ Each chart line is drawn in a different color. This option is a list of those colors. If the number of lines + exceeds the length of the list, then the colors wrap around to the beginning of the list. NB: individual + line color can be overridden by using option color. Optional. In the case of bar + charts, this is the color of the outline of the bar. Default is 0xff0000, 0x00ff00, 0x0000ff. +
-chart_fill_colors
+chart_fill_colors
-- A list of the color to be used as the fill of the bar charts. - Optional. The default is to use the same color as the outline - color (option chart_line_colors) - above. -
++ A list of the color to be used as the fill of the bar charts. Optional. The default is to use the same color + as the outline color (option chart_line_colors) above. +
-chart_line_width
+chart_line_width
-- Each chart line can be drawn using a different line width. This - option is a list of these widths. If the number of lines exceeds - the length of the list, then the widths wrap around to the - beginning of the list. NB: individual line widths can be - overridden by using option width. - Optional. Default is 1, 1, 1. -
++ Each chart line can be drawn using a different line width. This option is a list of these widths. If the + number of lines exceeds the length of the list, then the widths wrap around to the beginning of the list. + NB: individual line widths can be overridden by using option width. Optional. + Default is 1, 1, 1. +
-Individual line options
+Individual line options
-These are options that are set for individual lines.
+These are options that are set for individual lines.
-aggregate_type
+aggregate_type
-- The default is to plot every data point, but this is probably - not a good idea for any plot longer than a day. By setting this - option, you can aggregate data by a set time interval. - Available aggregation types include avg, - sum, max, min, count, - last, and cumulative. -
++ The default is to plot every data point, but this is probably not a good idea for any plot longer than a + day. By setting this option, you can aggregate data by a set time interval. Available aggregation + types include avg, sum, max, + min, count, last, and cumulative. +
-aggregate_interval
+aggregate_interval
-- The time period over which the data should be aggregated. - Required if aggregate_type has been - set. -
++ The time period over which the data should be aggregated. Required if aggregate_type has been set. +
-plot_type
+plot_type
-- The type of plot for this line. Choices are line, - bar, or vector. - Optional. Default is line. -
++ The type of plot for this line. Choices are line, bar, + or vector. Optional. Default is line. +
-color
+color
-- This option is to override the color for an individual line. - Optional. Default is to use the color in chart_line_colors. -
++ This option is to override the color for an individual line. Optional. Default is to use the color in chart_line_colors. +
-fill_color
+fill_color
-- This option is to override the fill color for a bar chart. - Optional. Default is to use the color in chart_fill_colors. -
++ This option is to override the fill color for a bar chart. Optional. Default is to use the color in chart_fill_colors. +
-line_type
+line_type
-- The type of line to be used. Choices are solid - or none. Optional. Default is solid. -
++ The type of line to be used. Choices are solid or none. + Optional. Default is solid. +
-marker_type
+marker_type
-- The type of marker to be used to marke each data point. Choices - are cross, x, - circle, box, - or none. Optional. Default is none. -
++ The type of marker to be used to marke each data point. Choices are cross, x, circle, box, or none. Optional. Default is none. +
-marker_size
+marker_size
-- The size of the marker. Optional. Default is 8. -
- -line_gap_fraction
++ The size of the marker. Optional. Default is 8. +
-- If there is a gap between data points bigger than this - fractional amount of the x-axis, then a gap will be drawn, - rather than a connecting line. See Section Line gaps. Optional. The default is to - always draw the line. -
+line_gap_fraction
-width
++ If there is a gap between data points bigger than this fractional amount of the x-axis, then a gap will be + drawn, rather than a connecting line. See Section Line gaps. Optional. The + default is to always draw the line. +
-- This option is to override the line widthfor an individual line. - Optional. Default is to use the width in chart_line_width. -
+width
-label
++ This option is to override the line widthfor an individual line. Optional. Default is to use the width in + chart_line_width. +
-The label to be used for this plot line in the top label. - Optional. The default is to use the SQL variable name.
+label
-data_type
+The label to be used for this plot line in the top label. Optional. The default is to use the SQL variable + name. +
-- The SQL data type to be used for this plot line. For more - information, see the section Including the same SQL - type more than once in a plot. Optional. The default is to - use the section name. -
+data_type
++ The SQL data type to be used for this plot line. For more information, see the section Including the same SQL type more than once in a plot. Optional. + The default is to use the section name. +
-[CopyGenerator]
-- This section is used by generator weewx.reportengine.CopyGenerator - and controls which files are to be copied over from the skin - directory to the destination directory. Think of it as "file - generation," except that rather than going through the template - engine, the files are simply copied over. -
+[CopyGenerator]
-copy_once
++ This section is used by generator weewx.reportengine.CopyGenerator and controls + which files are to be copied over from the skin directory to the destination directory. Think of it as "file + generation," except that rather than going through the template engine, the files are simply copied over. +
-This 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_once
-copy_always
+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. +
-This is a list of files that should be copied on every - invocation. Wildcards can be used.
+copy_always
-- Here is the [CopyGenerator] section - from the Standard skin.conf -
-[CopyGenerator] +-This is a list of files that should be copied on every invocation. Wildcards can be used.
+ ++ Here is the [CopyGenerator] section from the Standard skin.conf +
+[CopyGenerator] # This section is used by the generator CopyGenerator # List of files to be copied only the first time the generator runs @@ -5089,58 +4400,51 @@ UV = UV Index# List of files to be copied each time the generator runs # copy_always =The Standard skin includes some background images, CSS - files, and icons that need to be copied once. There are no files - that need to be copied every time the generator runs.
+The Standard skin includes some background images, CSS files, and icons that need to be copied once. There + are no files that need to be copied every time the generator runs. +
-[Generators]
+[Generators]
-This section defines the list of generators that should be - run.
+This section defines the list of generators that should be run.
-generator_list
+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.
+This option controls which generators get run for this skin. It is a comma separated list. The generators + will be run in this order. +
-- Here is the [Generators] section from - the Standard skin.conf -
-[Generators] ++ Here is the [Generators] section from the Standard skin.conf +
+[Generators] generator_list = weewx.cheetahgenerator.CheetahGenerator, weewx.imagegenerator.ImageGenerator, weewx.reportengine.CopyGenerator-The Standard skin uses three generators: CheetahGenerator, - ImageGenerator, and CopyGenerator.
+The Standard skin uses three generators: CheetahGenerator, ImageGenerator, and CopyGenerator.
-Localization
+Localization
-What follows is a guide to localizing to a non-English - language and/or locale. There are two parts: translating to - different languages and modifying to reflect local conventions - for displaying data.
+What follows is a guide to localizing to a non-English language and/or locale. There are two parts: + translating to different languages and modifying to reflect local conventions for displaying data. +
-Translate the templates
+Translate the templates
-- First, you will need to go through the templates and translate - to your target language. Obvious text strings such as "Current Weather Conditions" will need to - be translated. -
++ First, you will need to go through the templates and translate to your target language. Obvious text strings + such as "Current Weather Conditions" will need to be translated. +
-Modify the skin configuration
+Modify the skin configuration
-- Next, you will need to go through skin.conf - to translate labels and modify formats to follow local - conventions. -
++ Next, you will need to go through skin.conf to translate labels and modify formats + to follow local conventions. +
-You will probably want to change the generic labels used - for the observation types:
-[Labels] +-You will probably want to change the generic labels used for the observation types:
+[Labels] ... [[Generic]] barometer = Barometer @@ -5161,27 +4465,25 @@ UV = UV Indexwindchill = Wind Chill windgustvec = Gust Vector windvec = Wind VectorThe hemisphere abbreviations may have to be changed:
-[Labels] +The hemisphere abbreviations may have to be changed:
+[Labels] hemispheres = N, S, E, W-The wind ordinal directions may have to be changed:
-[Units] +The wind ordinal directions may have to be changed:
+[Units] ... [[Ordinates]] # The ordinal directions. The last one should be for no wind direction directions = N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW, N/A-Don't forget the moon phases:
-[Almanac] +Don't forget the moon phases:
+[Almanac] moon_phases = New, Waxing crescent, First quarter, Waxing gibbous, Full, Waning gibbous, Last quarter, Waning crescent-- Most of the unit labels either follow ISO conventions, or are - unlikely to be used outside English speaking countries (an - example would be "foot"). But, there are a few - exceptions, used to label the WeeWX and server - "uptimes", which can be found in sub-section [Units][[Labels]] -
-[Units] +-+ Most of the unit labels either follow ISO conventions, or are unlikely to be used outside English speaking + countries (an example would be "foot"). But, there are a few exceptions, used to label the WeeWX + and server "uptimes", which can be found in sub-section [Units][[Labels]] +
+[Units] ... [[Labels]] ... @@ -5189,13 +4491,11 @@ UV = UV Indexhour = " hour", " hours" minute = " minute", " minutes" second = " second", " seconds"- By default, the time formats will use the local convention - specified by the LANG environment variable. These can be - modified individually in the [Units][[TimeFormats]] - section. -
-[Units] +-+ By default, the time formats will use the local convention specified by the LANG environment variable. These + can be modified individually in the [Units][[TimeFormats]] section. +
+[Units] [[TimeFormats]] day = %X week = %X (%A) @@ -5206,29 +4506,27 @@ UV = UV Indexephem_day = %X ephem_year = %x %XEncodings
-You may have to specify the encoding used
--
+- by a template;
-- in any strings substituted by Cheetah.
-Encodings
+You may have to specify the encoding used
++
-- by a template;
+- in any strings substituted by Cheetah.
+Encoding used in a template
-- If you use an encoding other than ASCII in a template, then you must - include a #encoding - directive at the top of the file, informing Cheetah of your choice. - If your template includes other templates (by using the #include - directive), and those templates use an encoding, then they must include their - own #encoding directive as well. -
+Encoding used in a template
++ If you use an encoding other than ASCII in a template, then you must include a #encoding directive at the top of the file, informing Cheetah of your choice. If your + template includes other templates (by using the #include directive), and those + templates use an encoding, then they must include their own #encoding directive as + well. +
-- For example, if you use UTF-8 - (the default used by all the standard WeeWX templates), then the top of - your template should look something like this: -
-#errorCatcher Echo +-+ For example, if you use UTF-8 (the default used by all the standard WeeWX + templates), then the top of your template should look something like this: +
+#errorCatcher Echo ## ## Specifying an encoding of UTF-8 is usually safe, but if your text is ## actually in Latin-1, then you should replace the string "UTF-8" with "latin-1" @@ -5237,81 +4535,69 @@ UV = UV Index<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">Encoding used in substituted strings
-- The other place where encoding matters is in the strings substituted by Cheetah. - The encoding for these is specified by the - encoding option - in the skin configuration file, skin.conf. -
+Encoding used in substituted strings
++ The other place where encoding matters is in the strings substituted by Cheetah. The encoding for these is + specified by the encoding option in the skin + configuration file, skin.conf. +
-- Environment variable LANG -
++ Environment variable LANG +
-- Finally, you will need to set the environment variable LANG to reflect your locale. For example, - assuming you set -
-$ export LANG=es_ES.UTF-8-- before running WeeWX, then the local - Spanish names for days of the week and months of the year will - be used. The decimal point for numbers will also be modified - appropriately. -
++ Finally, you will need to set the environment variable LANG to reflect your + locale. For example, assuming you set +
+$ export LANG=es_ES.UTF-8++ before running WeeWX, then the local Spanish names for days of the week and months of the year will be used. + The decimal point for numbers will also be modified appropriately. +
-- Customizing the WeeWX service engine -
++ Customizing the WeeWX service engine
-This is an advanced topic intended for those who wish to - try their hand at extending the internal engine in WeeWX. Before - attempting these examples, you should be reasonably proficient - with Python.
+This is an advanced topic intended for those who wish to try their hand at extending the internal engine in + WeeWX. Before attempting these examples, you should be reasonably proficient with Python. +
-Please note that the API to the service - engine may change in future versions!
+Please note that the API to the service engine may change in future versions!
-- At a high level, WeeWX consists of an - engine that is responsible for managing a set of services. - A service consists of a Python class which binds its member - functions to various events. The engine arranges to - have the bound member function called when a specific event - happens, such as a new LOOP packet arriving. -
++ At a high level, WeeWX consists of an engine that is responsible for managing a set of + services. A service consists of a Python class which binds its member functions to various events. + The engine arranges to have the bound member function called when a specific event happens, such as a new + LOOP packet arriving. +
-To customize, you can
--
-- Modify an existing service
-- Create a new service
-- See the table Default services - above for a list of the services that are normally run. -
+To customize, you can
++
+- Modify an existing service
+- Create a new service
++ See the table Default services above for a list of the services that are + normally run. +
-Modifying an existing service
+Modifying an existing service
-- The service weewx.engine.StdPrint - prints out new LOOP and archive packets to the console when they - arrive. By default, it prints out the entire record, which - generally includes a lot of possibly distracting information and - can be rather messy. Suppose you do not like this, and want it - to print out only the time, barometer reading, and the outside - temperature whenever a new LOOP packet arrives. This could be - done by subclassing the default print service StdPrint - and overriding member function new_loop_packet(). -
++ The service weewx.engine.StdPrint prints out new LOOP and archive packets to the + console when they arrive. By default, it prints out the entire record, which generally includes a lot of + possibly distracting information and can be rather messy. Suppose you do not like this, and want it to print + out only the time, barometer reading, and the outside temperature whenever a new LOOP packet arrives. This + could be done by subclassing the default print service StdPrint and overriding + member function new_loop_packet(). +
-- Create the file user/myprint.py: -
-from weewx.engine import StdPrint ++ Create the file user/myprint.py: +
+from weewx.engine import StdPrint from weeutil.weeutil import timestamp_to_string class MyPrint(StdPrint): @@ -5322,49 +4608,42 @@ class MyPrint(StdPrint): print "LOOP: ", timestamp_to_string(packet['dateTime']), "BAR=", packet.get('barometer', 'N/A'), "TEMP=", packet.get('outTemp', 'N/A')-- This service substitutes a new implementation for the member - function new_loop_packet. This - implementation prints out the time, then the barometer reading - (or N/A if it is not available) and - the outside temperature (or N/A). -
++ This service substitutes a new implementation for the member function new_loop_packet. This implementation prints out the time, then the barometer reading (or + N/A if it is not available) and the outside temperature (or N/A). +
-- You then need to specify that your print service class should be - loaded instead of the default StdPrint - service. This is done by substituting your service name for StdPrint in service_list, - located in [Engine][[Services]]: -
-[Engine] ++ You then need to specify that your print service class should be loaded instead of the default StdPrint service. This is done by substituting your service name for StdPrint + in service_list, located in [Engine][[Services]]: +
+[Engine] [[Services]] ... report_services = user.myprint.MyPrint, weewx.engine.StdReport-- Note that the report_services must be - all on one line. Unfortunately, the parser ConfigObj - does not allow options to be continued on to following lines. -
++ Note that the report_services must be all on one line. Unfortunately, the parser + ConfigObj does not allow options to be continued on to following lines. +
-Creating a new service
+Creating a new service
-- Suppose there is no service that can be easily customized for - your needs. In this case, a new one can easily be created by - subclassing off the abstract base class StdService, - and then adding the functionality you need. Here is an example - that implements an alarm, which sends off an email when an - arbitrary expression evaluates True. -
++ Suppose there is no service that can be easily customized for your needs. In this case, a new one can easily + be created by subclassing off the abstract base class StdService, and then adding + the functionality you need. Here is an example that implements an alarm, which sends off an email when an + arbitrary expression evaluates True. +
-- This example is included in the standard distribution as examples/alarm.py: -
++ This example is included in the standard distribution as examples/alarm.py: +
-import time +import time import smtplib from email.mime.text import MIMEText import threading @@ -5480,13 +4759,12 @@ class MyAlarm(StdService): syslog.syslog(syslog.LOG_INFO, "alarm: 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.example.com @@ -5495,142 +4773,116 @@ class MyAlarm(StdService): mailto = auser@example.com, anotheruser@example.com from = me@example.com subject = "Alarm message from WeeWX!"-- There are three important points to be noted in this example, - each marked with a NOTE flag in the - code. -
--
-- Here is where the binding happens between an event, weewx.NEW_ARCHIVE_RECORD in this example, - and a member function, self.newArchiveRecord. - When the event NEW_ARCHIVE_RECORD - occurs, the function self.newArchiveRecord - will be called. There are many other events that can be - intercepted. Look in the file weewx/__init__.py. -
-- Some hardware does not emit all possible observation - types in every record. So, it's possible that a record may be - missing some types that are used in the expression. This try - block will catch the NameError - exception that would be raised should this occur. -
-- This is where the test is done for whether or not to - sound the alarm. The [Alarm] - configuration options specify that the alarm be sounded when outTemp < 40.0 evaluates True, that is when the outside temperature - is below 40.0 degrees. Any valid Python expression can be - used, although the only variables available are those in the - current archive record. -
-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.
++ There are three important points to be noted in this example, each marked with a NOTE flag in the code. +
++
+- Here is where the binding happens between an event, weewx.NEW_ARCHIVE_RECORD + in this example, and a member function, self.newArchiveRecord. When the event + NEW_ARCHIVE_RECORD occurs, the function self.newArchiveRecord + will be called. There are many other events that can be intercepted. Look in the file weewx/__init__.py. +
+- Some hardware does not emit all possible observation types in every record. So, it's possible that a + record may be missing some types that are used in the expression. This try block will catch the NameError exception that would be raised should this occur. +
+- This is where the test is done for whether or not to sound the alarm. The [Alarm] configuration options specify that the alarm be sounded when outTemp < 40.0 evaluates True, that is when the outside + temperature is below 40.0 degrees. Any valid Python expression can be used, although the only variables + available are those in the current archive record. +
+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. +
-- Note that units must be the same as whatever is being used in - your database. That is, the same as what you specified in option - target_unit. -
++ Note that units must be the same as whatever is being used in your database. That is, the same as what you + specified in option target_unit. +
-- 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. -
++ Option time_wait is used to avoid a flood of nearly identical emails. The new + service will wait this long before sending another email out. +
-- Email will be sent through the SMTP host specified by option smtp_host. The recipient(s) are specified - by the comma separated option mailto. -
++ Email will be sent through the SMTP host specified by option smtp_host. The + recipient(s) are specified by the comma separated option mailto. +
-- Many SMTP hosts require user login. If this is the case, the - user and password are specified with options smtp_user - and smtp_password, respectively. -
++ Many SMTP hosts require user login. If this is the case, the user and password are specified with options + smtp_user and smtp_password, respectively. +
-- The last two options, from and subject are optional. If not supplied, - WeeWX will supply something sensible. - Note, however, that some mailers require a valid "from" email - address and the one WeeWX supplies may - not satisfy its requirements. -
++ The last two options, from and subject are optional. If + not supplied, WeeWX will supply something sensible. Note, however, that some mailers require a valid "from" + email address and the one WeeWX supplies may not satisfy its requirements. +
-- To make this all work, you must first copy the alarm.py file to the user - directory. Then tell the engine to load this new service by - adding the service name to the list report_services, - located in [Engine][[Services]]: -
-[Engine] +++ To make this all work, you must first copy the alarm.py file to the user directory. Then tell the engine to load this new service by adding the service name + to the list report_services, located in [Engine][[Services]]: +
+[Engine] [[Services]] report_services = weewx.engine.StdPrint, weewx.engine.StdReport, user.alarm.MyAlarm-- Again, note that the option report_services - must be all on one line — the parser ConfigObj - does not allow options to be continued on to following lines. -
+ class="highlight">, user.alarm.MyAlarm+ Again, note that the option report_services must be all on one line — the + parser ConfigObj does not allow options to be continued on to following lines. +
-- In addition to the example above, the distribution also includes - a low-battery alarm (lowBattery.py), - which is similar, except that it intercepts LOOP events (instead - of archiving events). -
++ In addition to the example above, the distribution also includes a low-battery alarm (lowBattery.py), + which is similar, except that it intercepts LOOP events (instead of archiving events). +
-Adding a second data source
+Adding a second data source
-A very common problem is wanting to augment the data from - your weather station with data from some other device. - Generally, you have two approaches for how to handle this:
--
+- Run two instances of WeeWX, each using its own - database and weewx.conf - configuration file. The results are then combined in a final report, - using WeeWX's ability to - use more than one database. See the Wiki entry - - How to run multiple instances of WeeWX for details - on how to do this. -
-- Run one instance, but use a custom WeeWX service to - augment the records coming from your weather station with data - from the other device. -
-A very common problem is wanting to augment the data from your weather station with data from some other + device. Generally, you have two approaches for how to handle this: +
++
-- Run two instances of WeeWX, each using its own database and weewx.conf + configuration file. The results are then combined in a final report, using WeeWX's ability to use more than one database. See the Wiki entry How to run multiple instances of + WeeWX for details on how to do this. +
+- Run one instance, but use a custom WeeWX service to augment the records coming from your weather station + with data from the other device. +
+This section covers the latter approach.
+This section covers the latter approach.
-Suppose you have installed an electric meter at your house - and you wish to correlate electrical usage with the weather. The - meter has some sort of connection to your computer, allowing you - to download the total power consumed. At the end of every archive interval - you want to calculate the amount of power consumed during the interval, - then add the results to the record coming off your - weather station. How would you do this?
+Suppose you have installed an electric meter at your house and you wish to correlate electrical usage with + the weather. The meter has some sort of connection to your computer, allowing you to download the total + power consumed. At the end of every archive interval you want to calculate the amount of power consumed + during the interval, then add the results to the record coming off your weather station. How would you do + this? +
-Here is the outline of a service that retrieves the - electrical consumption data and adds it to the archive record. It - assumes that you already have a function - download_total_power() that, somehow, downloads - the amount of power consumed since time zero.
+Here is the outline of a service that retrieves the electrical consumption data and adds it to the archive + record. It assumes that you already have a function download_total_power() that, + somehow, downloads the amount of power consumed since time zero. +
-- File user/electricity.py -
-import weewx ++ File user/electricity.py +
+import weewx from weewx.engine import StdService class AddElectricity(StdService): @@ -5654,89 +4906,75 @@ class AddElectricity(StdService): event.record['electricity'] = net_consumed self.last_total = total_power-- This adds a new key electricity to the - record dictionary and sets it equal to the difference between - the amount of power currently consumed and the amount consumed - at the last archive record. Hence, it will be the amount - of power consumed over the archive interval. The unit should - be Watt-hours. -
++ This adds a new key electricity to the record dictionary and sets it equal to the + difference between the amount of power currently consumed and the amount consumed at the last archive + record. Hence, it will be the amount of power consumed over the archive interval. The unit should be + Watt-hours. +
-- As an aside, it is important that the function - download_total_power() does not - delay very long because it will sit right in the main loop of - the WeeWX engine. If it's - going to cause a delay of more than a couple seconds you might - want to put it in a separate thread and feed the results to AddElectricity through a queue. -
++ As an aside, it is important that the function download_total_power() does not + delay very long because it will sit right in the main loop of the WeeWX engine. If it's going to cause a + delay of more than a couple seconds you might want to put it in a separate thread and feed the results to + AddElectricity through a queue. +
-- To make sure your service gets run, you need to add it to one of - the service lists in weewx.conf, - section [Engine], subsection [[Services]]. This subsection lists all - the services to be run, broken up into different service - lists. Here's a description of them: -
++ To make sure your service gets run, you need to add it to one of the service lists in weewx.conf, + section [Engine], subsection [[Services]]. This + subsection lists all the services to be run, broken up into different service lists. Here's a + description of them: +
-- -
+- -Service list -Function -- -prep_services -Perform any actions before the main loop is run. -- -data_services -Augment data, before it is processed. -- -process_services -Process, filter, and massage the data. -- -archive_services -Record the data in a database. -- -restful_services -Upload processed data to an external RESTful - service. - -- - -report_services -Run any reports. -+ +
-+ +Service list +Function ++ +prep_services +Perform any actions before the main loop is run. ++ +data_services +Augment data, before it is processed. ++ +process_services +Process, filter, and massage the data. ++ +archive_services +Record the data in a database. ++ +restful_services +Upload processed data to an external RESTful service. + ++ + +report_services +Run any reports. +- These lists are designed to orchestrate the data as it flows - through the WeeWX engine. For example, you want to make sure - data has been processed by, for example, running it through the - quality control service, StdQC, before - putting them in the database. Similarly, the reporting system - must come after the archiving service. These groups - insure that things happen in the proper sequence. -
++ These lists are designed to orchestrate the data as it flows through the WeeWX engine. For example, you want + to make sure data has been processed by, for example, running it through the quality control service, StdQC, before putting them in the database. Similarly, the reporting system must come + after the archiving service. These groups insure that things happen in the proper sequence. +
-- In our case, the obvious place for our new service is in data_services. When you're done, your - section [Engine] will look something - like this: -
-++ In our case, the obvious place for our new service is in data_services. When + you're done, your section [Engine] will look something like this: +
+# This section configures the internal WeeWX engine. [Engine] @@ -5753,381 +4991,317 @@ class AddElectricity(StdService): report_services = weewx.engine.StdPrint, weewx.engine.StdReport-Customizing the database
+Customizing the database
-For most users the default database will work just fine. It - has the added advantage of being compatible with the wview - database. Nevertheless, there may be occasions where you may - want to add a new SQL type to your database, or change its unit - system. This section shows you how to do this.
- -Add a new type to the database
- -- It is not unusual to have observation types that exist in the loop - packets and/or archive records, but are not in the database schema. - An example is the new observation type electricity, - from the example above, Adding a second data source. - If a type is not in the database schema, then it will be a second class citizen in WeeWX's world: - it cannot be used in a plot, nor for most statistics. - So how would you add such a type to the database schema? -
- -- The utility wee_database - can do this. It will create a new database that is - similar to the old database, except it will have the new type - in its schema. -
- -- Note
- -
It is possible to observe all of the observation types - included in the loop packets and archive records, whether or not they are stored - in the database, by - running WeeWX directly. -Here's our general strategy:
--
-- Extend the existing schema with the new type. -
-- Modify the wx_binding to use - the new schema instead of the old. -
-- Make sure you have the necessary permissions to create - a new database. -
-- Use the utility wee_database - to create the new database and populate it with data from the - old database. -
-- Shuffle databases around so WeeWX - will use the new database. -
-Here is the recipe that follows that strategy:
--
- -- -
-- Extend the existing schema with the new type. The schema - that comes with WeeWX is the same as what wview uses. It's located - in the file schemas/wview.py — take - a look at it now. We could just modify it in situ, but that - would run the risk of confusing the two versions. Alternatively, we - could copy the file over to a new location, and then modify that. - But, because our change is just a simple addition, we're going to - import the wview schema and just add on our new type.
-For this example, - we are going to add the new type electricity. - Add the following code to the bottom of a file: +
For most users the default database will work just fine. It has the added advantage of being compatible with + the wview database. Nevertheless, there may be occasions where you may want to add a new SQL type to your + database, or change its unit system. This section shows you how to do this.
-import schemas.wview -schema_with_electricity = schemas.wview.schema + [('electricity', 'REAL')]+ +Add a new type to the database
+- This creates a new schema with the name - user.electricity.schema_with_electricity, - that is just like the old one, except it has a new type - electricity tacked on to the end. + It is not unusual to have observation types that exist in the loop packets and/or archive records, but are + not in the database schema. An example is the new observation type electricity, + from the example above, Adding a second data source. If a type is + not in the database schema, then it will be a second class citizen in WeeWX's world: it cannot be used in a + plot, nor for most statistics. So how would you add such a type to the database schema?
-Now, where do we put this bit of code? Really, it can be put in any file that - is guaranteed to run before we try and store our new type. With this in mind, there - are two obvious choices:
--
+ + +- Add it to the bottom of user/extensions.py. This is a - special file, provided by WeeWX, which is guaranteed to run before the engine's main loop. - It's a good place to add types that already exist in the - archive records (an example would be humidex), - but don't yet exist in the database schema. -
-- If you've been following the example above, Adding a second - data source, then you can just simply add the code to the bottom of the file - you already have, user/electricity.py. This way, it will - run before any use of the new type. It has the added advantage that it keeps all - "electricity" related modifications in one place, making it easy to package up your changes - as a new WeeWX extension. -
+ ++ The utility wee_database can do + this. It will create a new database that is similar to the old database, except it will have the new type in + its schema. +
+ ++ Note
+ +
It is possible to observe all of the observation types included in the loop + packets and archive records, whether or not they are stored in the database, by running WeeWX directly. +Here's our general strategy:
++
-- Extend the existing schema with the new type. +
+- Modify the wx_binding to use the new schema instead of the old. +
+- Make sure you have the necessary permissions to create a new database. +
+- Use the utility wee_database to create the new database and populate it with + data from the old database. +
+- Shuffle databases around so WeeWX will use the new database. +
- -
-- Modify wx_binding. When - it creates the new, modified database, wee_database - needs to know to use your new schema instead of the old, wview - schema. You do this by changing the option schema - in section [DataBindings] in - weewx.conf.
-If you made the code additions in step 1 in - file user/extensions.py, then it - will look like this when you're done: -
+Here is the recipe that follows that strategy:
++
- +
+ Extend the existing schema with the new type. The schema that comes with WeeWX is + the same as what wview uses. It's located in the file schemas/wview.py + — take a look at it now. We could just modify it in situ, but that would run the risk + of confusing the two versions. Alternatively, we could copy the file over to a new location, and + then modify that. But, because our change is just a simple addition, we're going to import the wview + schema and just add on our new type. +
+For this example, we are going to add the new type electricity. Add the + following code to the bottom of a file: +
+import schemas.wview +schema_with_electricity = schemas.wview.schema + [('electricity', 'REAL')]++ This creates a new schema with the name user.electricity.schema_with_electricity, that is just like the old one, except + it has a new type electricity tacked on to the end. +
+Now, where do we put this bit of code? Really, it can be put in any file that is guaranteed to run + before we try and store our new type. With this in mind, there are two obvious choices: +
++
+- Add it to the bottom of user/extensions.py. This is a special file, + provided by WeeWX, which is guaranteed to run before the engine's main loop. It's a good place + to add types that already exist in the archive records (an example would be humidex), + but don't yet exist in the database schema. +
+- If you've been following the example above, Adding a second + data source, then you can just simply add the code to the bottom of the file you + already have, user/electricity.py. This way, it will run before any + use of the new type. It has the added advantage that it keeps all "electricity" related + modifications in one place, making it easy to package up your changes as a new WeeWX extension. +
+- +
++ Modify wx_binding. When it creates the new, modified + database, wee_database needs to know to use your new schema instead of the + old, wview schema. You do this by changing the option schema in section + [DataBindings] in weewx.conf. +
+If you made the code additions in step 1 in file user/extensions.py, then + it will look like this when you're done: +
-[DataBindings] +[DataBindings] [[wx_binding]] database = archive_sqlite table_name = archive manager = weewx.wxmanager.WXDaySummaryManager schema = user.extensions.schema_with_electricity-If you used user/electricity.py, then - it will look like this: -
+If you used user/electricity.py, then it will look like this: +
-[DataBindings] +[DataBindings] [[wx_binding]] database = archive_sqlite table_name = archive manager = weewx.wxmanager.WXDaySummaryManager schema = user.electricity.schema_with_electricity-- -
-- Check permissions. wee_database - will create a new database with the same name as the old, - except with the suffix _new - attached to the end. Make sure you have the necessary - permissions to create it. In particular, if you are using - MySQL, you will need CREATE - privileges: -
-mysql> GRANT select, update, create, delete, insert ON weewx_new.* TO weewx@localhost;-- -
- Create and populate the new database. Now - run the utility wee_database with - the --reconfigure option and the - path to the configuration file: -
+- +
++ Check permissions. wee_database will create a new + database with the same name as the old, except with the suffix _new + attached to the end. Make sure you have the necessary permissions to create it. In particular, if + you are using MySQL, you will need CREATE privileges: +
+mysql> GRANT select, update, create, delete, insert ON weewx_new.* TO weewx@localhost;+- +
-+ Create and populate the new database. Now run the utility wee_database + with the --reconfigure option and the path to the configuration file: +
-wee_database weewx.conf --reconfigure
+wee_database weewx.conf --reconfigure
-- This will create a new database (nominally, weewx.sdb_new if you are using SQLite, - weewx_new if you are using MySQL) - using the new schema and populate it with data from the old - database. -
-- -
+- Shuffle the databases. Now arrange things - so WeeWX can find the new - database. -
++ This will create a new database (nominally, weewx.sdb_new if you are using + SQLite, weewx_new if you are using MySQL) using the new schema and + populate it with data from the old database. +
+- +
-+ Shuffle the databases. Now arrange things so WeeWX can find the new database. +
-- Warning!
+
Make a backup of the data - before doing any of the next steps! -+ Warning!
-
Make a backup of the data before doing any of the next steps! +- You can either shuffle the databases around so the new - database has the same name as the old database, or edit weewx.conf to use the new database - name. To do the former: -
++ You can either shuffle the databases around so the new database has the same name as the old + database, or edit weewx.conf to use the new database name. To do the + former: +
-For SQLite:
-cd SQLITE_ROOT +For SQLite:
+cd SQLITE_ROOT mv weewx.sdb_new weewx.sdb-For MySQL:
-mysql -u <username> --password=<mypassword> +For MySQL:
+mysql -u <username> --password=<mypassword> mysql> DROP DATABASE weewx; # Delete the old database mysql> CREATE DATABASE weewx; # Create a new one with the same name mysql> RENAME TABLE weewx_new.archive TO weewx.archive; # Rename to the nominal name-- +
+- +
++ It's worth noting that there's actually a hidden, last step: rebuilding the daily summaries inside + the new database. This will be done automatically by WeeWX at the next startup. Alternatively, it + can be done manually using the wee_database + utility and the --rebuild-daily option: +
+wee_database weewx.conf --rebuild-daily+Changing the unit system
+- It's worth noting that there's actually a hidden, last step: - rebuilding the daily summaries inside the new database. This - will be done automatically by WeeWX - at the next startup. Alternatively, it can be done manually - using the wee_database utility and the --rebuild-daily option: + Normally, data are stored in the databases using US Customary units and, normally, you don't care; it is an + "implementation detail". Data can always be displayed using any units you want. The Customizing reports section explains how to do this. Nevertheless, there may + be special situations where you wish to store the data in Metric units. For example, you may need to allow + direct programmatic access to the databases from another piece of software that expects metric units.
-wee_database weewx.conf --rebuild-daily-Changing the unit system
- -- Normally, data are stored in the databases using US Customary - units and, normally, you don't care; it is an "implementation - detail". Data can always be displayed using any units you want. - The Customizing reports - section explains how to do this. Nevertheless, there may be - special situations where you wish to store the data in Metric - units. For example, you may need to allow direct programmatic - access to the databases from another piece of software that - expects metric units. -
- -- WeeWX does not allow you to change the database unit system - midstream. You can't start with one unit system then, in the - middle of the database, switch to another. See the section [StdConvert] - in the WeeWX User's Guide. However, you can reconfigure the - database by copying it to a new database, performing the unit - conversion along the way. You then use this new database. -
- -Here is the general strategy:
--
-- Modify weewx.conf to reflect - your choice of the new unit system to use. Your choices are US, METRIC, or METRICWX. See the Appendix: Units for the exact differences - between these three choices. -
-- Make sure you have the necessary permissions to create - the new database. -
-- Use the utility wee_database to create the new database - and populate it with data from the old database. -
-- Shuffle databases around so WeeWX - will use the new database. -
-Here is the recipe that follows that strategy:
--
-- -
- Modify weewx.conf. - Edit the configuration file to change option target_unit in section [StdConvert] - to reflect your choice. If you are switching to metric - units, the option will look like: + WeeWX does not allow you to change the database unit system midstream. You can't start with one unit system + then, in the middle of the database, switch to another. See the section [StdConvert] in the WeeWX User's Guide. However, you can + reconfigure the database by copying it to a new database, performing the unit conversion along the way. You + then use this new database.
-[StdConvert] + +Here is the general strategy:
++
+- Modify weewx.conf to reflect your choice of the new unit system to use. Your + choices are US, METRIC, or METRICWX. + See the Appendix: Units for the exact differences between these three + choices. +
+- Make sure you have the necessary permissions to create the new database. +
+- Use the utility wee_database + to create the new database and populate it with data from the old database. +
+- Shuffle databases around so WeeWX will use the new database. +
+Here is the recipe that follows that strategy:
++
+ +- +
-+ Modify weewx.conf. Edit the configuration file to change + option target_unit in section [StdConvert] to reflect your choice. If you are + switching to metric units, the option will look like: +
+[StdConvert] target_unit = METRICWX-- -
-- Check permissions. The reconfiguration - utility will create a new database with the same name as the - old, except with the suffix _new - attached to the end. Make sure you have the necessary - permissions to do this. In particular, if you are using - MySQL, you will need CREATE - privileges. -
-- -
-- Create and populate the new database. Now - run the utility wee_database with - the --reconfigure option: -
-wee_database weewx.conf --reconfigure-- This will create a new database (nominally, weewx.sdb_new if you are using SQLite, - weewx_new if you are using MySQL), - using the schema found in user/schemas.py, - and populate it with data from the old database, while - performing the unit conversion. -
-- -
+- Shuffle the databases. Now arrange things - so WeeWX can find the new database. -
+- +
++ Check permissions. The reconfiguration utility will create a new database with the + same name as the old, except with the suffix _new attached to the end. + Make sure you have the necessary permissions to do this. In particular, if you are using MySQL, you + will need CREATE privileges. +
+- +
++ Create and populate the new database. Now run the utility wee_database + with the --reconfigure option: +
+wee_database weewx.conf --reconfigure++ This will create a new database (nominally, weewx.sdb_new if you are using + SQLite, weewx_new if you are using MySQL), using the schema found in user/schemas.py, and populate it with data from the old database, while + performing the unit conversion. +
+- +
-+ Shuffle the databases. Now arrange things so WeeWX can find the new database. +
-- Warning!
+
Make a backup of the data - before doing any of the next steps! -+ Warning!
-
Make a backup of the data before doing any of the next steps! +- You can either shuffle the databases around so the new - database has the same name as the old database, or edit weewx.conf to use the new database - name. To do the former: -
++ You can either shuffle the databases around so the new database has the same name as the old + database, or edit weewx.conf to use the new database name. To do the + former: +
-For SQLite:
-cd SQLITE_ROOT +For SQLite:
+cd SQLITE_ROOT mv weewx.sdb_new weewx.sdb-For MySQL:
-mysql -u <username> --password=<mypassword> +For MySQL:
+mysql -u <username> --password=<mypassword> mysql> DROP DATABASE weewx; # Delete the old database mysql> CREATE DATABASE weewx; # Create a new one with the same name mysql> RENAME TABLE weewx_new.archive TO weewx.archive; # Rename to the nominal name-- +
+- +
++ It's worth noting that there's actually a hidden, last step: rebuilding the daily summaries inside + the new database. This will be done automatically by WeeWX at the next startup. Alternatively, it + can be done manually using the wee_database + utility and the --rebuild-daily option: +
+wee_database weewx.conf --rebuild-daily+Rebuilding the daily summaries
+- It's worth noting that there's actually a hidden, last step: - rebuilding the daily summaries inside the new database. This - will be done automatically by WeeWX - at the next startup. Alternatively, it can be done manually - using the wee_database utility and the --rebuild-daily option: + The wee_database utility can also be used to rebuild the daily summaries:
+wee_database weewx.conf --rebuild-daily-Rebuilding the daily summaries
+In most cases this will be sufficient; however, if anomalies remain in the daily summaries the daily summary + tables may be dropped first before rebuilding: +
-- The wee_database utility can also be - used to rebuild the daily summaries: -
+wee_database weewx.conf --drop-daily-wee_database weewx.conf --rebuild-daily++ The summaries will automatically be rebuilt the next time WeeWX starts, or they can be rebuilt with the + utility: +
-In most cases this will be sufficient; however, if - anomalies remain in the daily summaries the daily summary tables - may be dropped first before rebuilding:
- -wee_database weewx.conf --drop-daily- -- The summaries will automatically be rebuilt the next time - WeeWX starts, or they can be rebuilt with the utility: -
- -wee_database weewx.conf --rebuild-daily+wee_database weewx.conf --rebuild-daily-Customizing units and unit groups
+Customizing units and unit groups
-- Warning!
+
- This is an area that is rapidly changing in WeeWX. - Presently, new units and unit groups are added by manipulating - the internal dictionaries in WeeWX (as described below). In the future, - they may be specified in weewx.conf. -+ Warning!
-
This is an area that is rapidly changing in WeeWX. Presently, new units and + unit groups are added by manipulating the internal dictionaries in WeeWX (as described below). In the + future, they may be specified in weewx.conf. +Assigning a unit group
-- In the examples above, we created a new observation type, electricity, and added it to the database - schema. Now we would like to recognize that it is a member of - the unit group group_energy (which - already exists), so it can enjoy the labels and formats - already provided for this group. This is done by extending the dictionary weewx.units.obs_group_dict.
+Assigning a unit group
++ In the examples above, we created a new observation type, electricity, and added + it to the database schema. Now we would like to recognize that it is a member of the unit group group_energy (which already exists), so it can enjoy the labels and formats already + provided for this group. This is done by extending the dictionary weewx.units.obs_group_dict. +
-Add the following to our new services file - user/electricity.py, just after the last - import statement:
-import weewx +Add the following to our new services file user/electricity.py, just after the last + import statement: +
+import weewx from weewx.engine import StdService import weewx.units @@ -6137,509 +5311,426 @@ class AddElectricity(StdService): # [...]-When our new service gets loaded by the WeeWX engine, these few lines - will get run. They tell WeeWX that our new observation type, - electricity, is part of the unit group - group_energy. - Once the observation has been associated with a unit group, - the unit labels and other tag syntax will work for that - observation. So, now a tag like:
-$month.electricity.sum-will return the total amount of electricity consumed for - the month, in Watt-hours.
+When our new service gets loaded by the WeeWX engine, these few lines will get run. They tell WeeWX that our + new observation type, electricity, is part of the unit group group_energy. + Once the observation has been associated with a unit group, the unit labels and other tag syntax will work + for that observation. So, now a tag like: +
+$month.electricity.sum+will return the total amount of electricity consumed for the month, in Watt-hours.
-Creating a new unit group
-- That was an easy one, because there was already an existing - group, group_energy, that covered our new - observation type. But, what if we are measuring something entirely new, like - force with time? There is nothing in the existing system of - units that covers things like newtons or pounds. We will have to - define these new units, as well as the unit group they can - belong to. -
-- We assume we have a new observation type, force, - that we are measuring over time, for a service named - user/rocket.py. We will create a new unit group, - group_force, and new units, newton and pound. - Our new observation, force, will - belong to group_force, and will be - measured in units of newton or pound. -
--
+- As before, we start by specifying what group our new - observation type belongs to: -
++Creating a new unit group
++ That was an easy one, because there was already an existing group, group_energy, + that covered our new observation type. But, what if we are measuring something entirely new, like force with + time? There is nothing in the existing system of units that covers things like newtons or pounds. We will + have to define these new units, as well as the unit group they can belong to. +
++ We assume we have a new observation type, force, that we are measuring over time, + for a service named + user/rocket.py. We will create a new unit group, group_force, and new units, + newton and pound. Our new observation, force, will belong to group_force, and will be measured in + units of newton or pound. +
++
-- As before, we start by specifying what group our new observation type belongs to: +
-import weewx.units weewx.units.obs_group_dict['force'] = 'group_force'-- Next, we specify what unit is used to measure force in - the three standard unit systems used by weewx. -
++- Next, we specify what unit is used to measure force in the three standard unit systems used by weewx. +
-weewx.units.USUnits['group_force'] = 'pound' weewx.units.MetricUnits['group_force'] = 'newton' weewx.units.MetricWXUnits['group_force'] = 'newton'-- Then we specify what formats and labels to use for newton and pound: -
++- Then we specify what formats and labels to use for newton and pound: +
-weewx.units.default_unit_format_dict['newton'] = '%.1f' weewx.units.default_unit_format_dict['pound'] = '%.1f' weewx.units.default_unit_label_dict['newton'] = ' newton' weewx.units.default_unit_label_dict['pound'] = ' pound'-- Finally, we specify how to convert between them: -
++- Finally, we specify how to convert between them: +
-weewx.units.conversionDict['newton'] = {'pound': lambda x : x * 0.224809} weewx.units.conversionDict['pound'] = {'newton': lambda x : x * 4.44822}-As with the previous example of group_energy, - the last step is to extend the - weewx.units.obs_group_dict dictionary so that these new units can - be used by our service. We do this by adding the Python code from - steps 1 - 4 above into - our new services file user/rocket.py, at the - head of that file and just after the last import statement (as in the - previous example).
+As with the previous example of group_energy, the last step is to extend the + weewx.units.obs_group_dict dictionary so that these new units can be used by our service. We do this by + adding the Python code from steps 1 - 4 above into our new services file user/rocket.py, at the head of that file and just after the last import statement + (as in the previous example). +
-Use the new types
+Use the new types
-Now you've added a new type. How do you use it?
+Now you've added a new type. How do you use it?
-- Pretty much like any other type. For example, to do a plot of - the month's electric consumption, totaled by day, add this - section to the [[month_images]] - section of skin.conf: -
-[[[monthelectric]]] ++ Pretty much like any other type. For example, to do a plot of the month's electric consumption, totaled by + day, add this section to the [[month_images]] section of skin.conf: +
+[[[monthelectric]]] [[[[electricity]]]] aggregate_type = sum aggregate_interval = 86400 label = Electric consumption (daily total)-- This will cause the generation of an image monthelectric.png, - showing a plot of each day's consumption for the past month. -
++ This will cause the generation of an image monthelectric.png, showing a plot of + each day's consumption for the past month. +
-If you wish to use the new type in the templates, it will - be available using the same syntax as any other type. Here are - some other tags that might be useful:
-- -
+- -Tag -Meaning -- -$day.electricity.sum -Total consumption since midnight -- -$year.electricity.sum -Total consumption since the first of the year -- -$year.electricity.max -The most consumed during any archive period -- -$year.electricity.maxsum -The most consumed during a day -- -$year.electricity.maxsumtime -The day it happened. -- - -$year.electricity.sum_ge(5000.0) -The number of days of the year where more than 5.0 kWh of - energy was consumed. - -If you wish to use the new type in the templates, it will be available using the same syntax as any other + type. Here are some other tags that might be useful: +
++ +
-+ +Tag +Meaning ++ +$day.electricity.sum +Total consumption since midnight ++ +$year.electricity.sum +Total consumption since the first of the year ++ +$year.electricity.max +The most consumed during any archive period ++ +$year.electricity.maxsum +The most consumed during a day ++ +$year.electricity.maxsumtime +The day it happened. ++ + +$year.electricity.sum_ge(5000.0) +The number of days of the year where more than 5.0 kWh of energy was consumed. + +Porting to new hardware
+Porting to new hardware
-Naturally, this is an advanced topic but, nevertheless, I'd - like to encourage any Python wizards out there to give it a try. - Of course, I have selfish reasons for this: I don't want to have - to buy every weather station ever invented, and I don't want my - roof to look like a weather station farm!
+Naturally, this is an advanced topic but, nevertheless, I'd like to encourage any Python wizards out there to + give it a try. Of course, I have selfish reasons for this: I don't want to have to buy every weather station + ever invented, and I don't want my roof to look like a weather station farm! +
-General guidelines
+General guidelines
--
+- The driver should emit data as it receives it from the - hardware (no caching). -
-- The driver should emit only data it receives from the - hardware (no "filling in the gaps"). -
-- The driver should not modify the data unless the - modification is directly related to the hardware (e.g., - decoding a hardware-specific sensor value). -
-- If the hardware flags "bad data", then the driver - should emit a null value for that datum (Python None). -
-- The driver should not calculate any derived variables - (such as dewpoint). The service StdWXService - will do that. -
-- However, if the hardware emits a derived variable, then - the driver should emit it. -
-+
-- The driver should emit data as it receives it from the hardware (no caching). +
+- The driver should emit only data it receives from the hardware (no "filling in the gaps"). +
+- The driver should not modify the data unless the modification is directly related to the hardware (e.g., + decoding a hardware-specific sensor value). +
+- If the hardware flags "bad data", then the driver should emit a null value for that datum (Python None). +
+- The driver should not calculate any derived variables (such as dewpoint). The service StdWXService will do that. +
+- However, if the hardware emits a derived variable, then the driver should emit it. +
+Implement the driver
+Implement the driver
-- Create a file in the user directory, say mydriver.py. - This file will contain the driver class as well as any - hardware-specific code. Do not put it in the - weewx/drivers - directory or it will be deleted when you upgrade WeeWX. -
++ Create a file in the user directory, say mydriver.py. This file will contain the + driver class as well as any hardware-specific code. Do not put it in the weewx/drivers directory or it will be deleted when you upgrade WeeWX. +
-- Inherit from the abstract base class weewx.drivers.AbstractDevice. - Try to implement as many of its methods as you can. At the very - minimum, you must implement the first three methods, loader, hardware_name, - and genLoopPackets. -
++ Inherit from the abstract base class weewx.drivers.AbstractDevice. Try to + implement as many of its methods as you can. At the very minimum, you must implement the first three + methods, loader, hardware_name, and genLoopPackets. +
-- loader -
++ loader +
-This is a factory function that returns an instance of your - driver. It has two arguments: the configuration dictionary, and - a reference to the WeeWX engine.
+This is a factory function that returns an instance of your driver. It has two arguments: the configuration + dictionary, and a reference to the WeeWX engine. +
-- hardware_name -
++ hardware_name +
-- Return a string with a short nickname for the hardware, such as - "ACME X90" -
++ Return a string with a short nickname for the hardware, such as "ACME X90" +
-- genLoopPackets -
++ genLoopPackets +
-- This should be a generator - function that yields loop packets, one after another. Don't - worry about stopping it: the engine will do this when an archive - record is due. A "loop packet" is a dictionary. At the very - minimum it must contain keys for the observation time and for - the units used within the packet. -
--
-Required keys - -- -dateTime -The time of the observation in unix epoch time. -- - -usUnits -The unit system used. weewx.US - for US customary, weewx.METRICWX, - or weewx.METRIC for metric. See - the file units.py, dictionaries - USUnits, MetricWXUnits, - and MetricUnits for the exact - definition of each. - -- Then include any observation types you have in the dictionary. - Every packet need not contain the same set of observation types. - Different packets can use different unit systems, but all - observations within a packet must use the same unit system. If - your hardware is capable of measuing an observation type but, for - whatever reason, its value is bad (maybe a bad checksum?), then set its - value to None. If your hardware is incapable - of measuring an observation type, then leave it out of the dictionary. -
++ This should be a generator function that yields loop + packets, one after another. Don't worry about stopping it: the engine will do this when an archive record is + due. A "loop packet" is a dictionary. At the very minimum it must contain keys for the observation time and + for the units used within the packet. +
++
+Required keys + ++ +dateTime +The time of the observation in unix epoch time. ++ + +usUnits +The unit system used. weewx.US for US customary, weewx.METRICWX, + or weewx.METRIC for metric. See the file units.py, dictionaries USUnits, MetricWXUnits, and MetricUnits for the exact + definition of each. + ++ Then include any observation types you have in the dictionary. Every packet need not contain the same set of + observation types. Different packets can use different unit systems, but all observations within a packet + must use the same unit system. If your hardware is capable of measuing an observation type but, for whatever + reason, its value is bad (maybe a bad checksum?), then set its value to None. If + your hardware is incapable of measuring an observation type, then leave it out of the dictionary. +
-- A couple of observation types are tricky. In particular, rain. Generally, WeeWX - expects to see a packet with the amount of rain that fell in - that packet period included as observation rain. - It then sums up all the values to get the total rainfall and - emits that in the archive record. If your hardware does not - provide this value, you might have to infer it from changes in - whatever value it provides, for example changes in the daily or - monthly rainfall. I know this is not the best solution, but it - is the most general solution. Any alternatives are welcome! -
++ A couple of observation types are tricky. In particular, rain. Generally, WeeWX + expects to see a packet with the amount of rain that fell in that packet period included as observation + rain. It then sums up all the values to get the total rainfall and emits that in + the archive record. If your hardware does not provide this value, you might have to infer it from changes in + whatever value it provides, for example changes in the daily or monthly rainfall. I know this is not the + best solution, but it is the most general solution. Any alternatives are welcome! +
-- Wind is another tricky one. It is actually broken up into four - different observations: windSpeed, windDir, windGust, - and windGustDir. Supply as many as you - can. The directions should be compass directions in degrees - (0=North, 90=East, etc.). -
++ Wind is another tricky one. It is actually broken up into four different observations: windSpeed, + windDir, windGust, and windGustDir. Supply as many as you can. The directions should be compass directions in + degrees (0=North, 90=East, etc.). +
-Be careful when reporting pressure. There are three - observations related to pressure. Some stations report only the - station pressure, others calculate and report sea level - pressures.
--
+Pressure types - -- -pressure -The Station Pressure (SP), which is the - raw, absolute pressure measured by the station. This is - the true barometric pressure for the station. - -- -barometer -The Sea Level Pressure (SLP) obtained by - correcting the Station Pressure for altitude and - local temperature. This is the pressure reading most - commonly used by meteorologist to track weather systems at - the surface, and this is the pressure that is uploaded to - weather services by WeeWX. It is - the station pressure reduced to mean sea level using local - altitude and local temperature. - -- - -altimeter -The Altimeter Setting (AS) obtained by - correcting the Station Pressure for altitude. - This is the pressure reading most commonly heard in - weather reports. It is not the true barometric pressure of - a station, but rather the station pressure reduced to mean - sea level using altitude and an assumed temperature - average. - -Be careful when reporting pressure. There are three observations related to pressure. Some stations report + only the station pressure, others calculate and report sea level pressures. +
++
-Pressure types + ++ +pressure +The Station Pressure (SP), which is the raw, absolute pressure measured by the station. + This is the true barometric pressure for the station. + ++ +barometer +The Sea Level Pressure (SLP) obtained by correcting the Station Pressure for + altitude and local temperature. This is the pressure reading most commonly used by meteorologist to + track weather systems at the surface, and this is the pressure that is uploaded to weather services + by WeeWX. It is the station pressure reduced to mean sea level using local altitude and local + temperature. + ++ + +altimeter +The Altimeter Setting (AS) obtained by correcting the Station Pressure for + altitude. This is the pressure reading most commonly heard in weather reports. It is not the true + barometric pressure of a station, but rather the station pressure reduced to mean sea level using + altitude and an assumed temperature average. + +- genArchiveRecords() -
++ genArchiveRecords() +
-- If your hardware does not have an archive record logger, then - WeeWX can do the record generation for - you. It will automatically collect all the types it sees in your - loop packets then emit a record with the averages (in some cases - the sum or max value) of all those types. If it doesn't see a - type, then it won't appear in the emitted record. -
++ If your hardware does not have an archive record logger, then WeeWX can do the record generation for you. It + will automatically collect all the types it sees in your loop packets then emit a record with the averages + (in some cases the sum or max value) of all those types. If it doesn't see a type, then it won't appear in + the emitted record. +
-- However, if your hardware does have a logger, then you should - implement method genArchiveRecords() - as well. It should be a generator function that returns all the - records since a given time. -
++ However, if your hardware does have a logger, then you should implement method genArchiveRecords() + as well. It should be a generator function that returns all the records since a given time. +
-- archive_interval -
++ archive_interval +
-- If you implement function genArchiveRecords() - above, then you should also implement archive_interval - as either an attribute, or as a property - function. It should return the archive interval in seconds. -
++ If you implement function genArchiveRecords() above, then you should also + implement archive_interval as either an attribute, or as a property function. It should return the + archive interval in seconds. +
-- getTime() -
++ getTime() +
-If your hardware has an onboard clock and supports reading - the time from it, then you may want to implement this method. It - takes no argument. It should return the time in Unix Epoch Time. -
+If your hardware has an onboard clock and supports reading the time from it, then you may want to implement + this method. It takes no argument. It should return the time in Unix Epoch Time. +
-- setTime() -
++ setTime() +
-- If your hardware has an onboard clock and supports setting - it, then you may want to implement this method. It takes no - argument and does not need to return anything. -
++ If your hardware has an onboard clock and supports setting it, then you may want to implement this + method. It takes no argument and does not need to return anything. +
-- closePort() -
++ closePort() +
-- If the driver needs to close a serial port, terminate a thread, - close a database, or perform any other activity before the - application terminates, then you must supply this function. - WeeWX will call it if it needs to shut - down your console (usually in the case of an error). -
++ If the driver needs to close a serial port, terminate a thread, close a database, or perform any other + activity before the application terminates, then you must supply this function. WeeWX will call it if it + needs to shut down your console (usually in the case of an error). +
-Define the configuration
+Define the configuration
-- You then include a new section in the configuration file - weewx.conf that includes any options your - driver needs. It should also include an entry - driver - that points to where your driver can be found. Set option - station_type to your new section type and - your driver will be loaded. -
++ You then include a new section in the configuration file weewx.conf that includes + any options your driver needs. It should also include an entry driver that points + to where your driver can be found. Set option station_type to your new section + type and your driver will be loaded. +
-Examples
+Examples
-- The fileparse driver is perhaps the - simplest example of a WeeWX driver. - It reads name-value pairs from a file and uses the values as - sensor 'readings'. The code is actually packaged as an extension, located in - examples/fileparse, making it a good example - of not only writing a device driver, but also - of how to package an extension. The actual driver itself is in - examples/fileparse/bin/user/fileparse.py. -
++ The fileparse driver is perhaps the simplest example of a WeeWX driver. It reads + name-value pairs from a file and uses the values as sensor 'readings'. The code is actually packaged as an + extension, located in examples/fileparse, making it a good example of not only + writing a device driver, but also of how to package an extension. The actual driver itself is in examples/fileparse/bin/user/fileparse.py. +
-- Another good example is the simulator code - located in weewx/drivers/simulator.py. - It's dirt simple and you can easily play with it. Many people - have successfully used it as a starting point for writing their - own custom driver. -
++ Another good example is the simulator code located in weewx/drivers/simulator.py. + It's dirt simple and you can easily play with it. Many people have successfully used it as a starting point + for writing their own custom driver. +
-- The Ultimeter (ultimeter.py) and - WMR100 (wmr100.py) drivers illustrate - how to communicate with serial and USB hardware, respectively. - They also show different approaches for decoding data. - Nevertheless, they are pretty straightforward. -
++ The Ultimeter (ultimeter.py) and WMR100 (wmr100.py) + drivers illustrate how to communicate with serial and USB hardware, respectively. They also show different + approaches for decoding data. Nevertheless, they are pretty straightforward. +
-- The driver for the Vantage series is by far the most - complicated. It actually multi-inherits from not only AbstractDevice, but also StdService. That is, it also participates - in the engine as a service. -
++ The driver for the Vantage series is by far the most complicated. It actually multi-inherits from not only + AbstractDevice, but also StdService. That is, it also + participates in the engine as a service. +
-Naturally, there are a lot of subtleties that have been glossed - over in this high-level description. If you run into trouble, - look for help in the - weewx-development forum.
+Naturally, there are a lot of subtleties that have been glossed over in this high-level description. If you + run into trouble, look for help in the + weewx-development forum. +
-Extensions
+Extensions
-- A key feature of WeeWX is its ability - to be extended by installing 3rd party extensions. - Extensions are a way to package one or more customizations so - they can be installed and distributed as a functional group. -
++ A key feature of WeeWX is its ability to be extended by installing 3rd party extensions. Extensions + are a way to package one or more customizations so they can be installed and distributed as a functional + group. +
-Customizations typically fall into one of these categories:
--
+- search list extension
-- template
-- skin
-- service
-- generator
-- driver
-Customizations typically fall into one of these categories:
++
-- search list extension
+- template
+- skin
+- service
+- generator
+- driver
+- Take a look at the - WeeWX wiki - for a sampling of some of the extensions that are available. -
++ Take a look at the WeeWX wiki for a sampling of some of + the extensions that are available. +
- + -Creating an extension
+Creating an extension
-- Now that you have made some customizations, you might want to - share those changes with other WeeWX - users. Put your customizations into an extension to make - installation, removal, and distribution easier. -
++ Now that you have made some customizations, you might want to share those changes with other WeeWX users. + Put your customizations into an extension to make installation, removal, and distribution easier. +
-Here are a few guidelines for creating extensions:
--
+- Extensions should not modify or depend upon existing - skins. An extension should include its own, standalone skin to - illustrate any templates, search list extension, or generator - features. -
-- Extensions should not modify the database schemas. If - it requires data not found in the default databases, an - extension should provide its own database and schema. -
-Here are a few guidelines for creating extensions:
++
-- Extensions should not modify or depend upon existing skins. An extension should include its own, + standalone skin to illustrate any templates, search list extension, or generator features. +
+- Extensions should not modify the database schemas. If it requires data not found in the default + databases, an extension should provide its own database and schema. +
+How to package an extension
+How to package an extension
-- The structure of an extension mirrors that of WeeWX - itself. If the customizations include a skin, the extension will - have a skins directory. If the customizations include python - code, the extension will have a bin/user - directory. -
++ The structure of an extension mirrors that of WeeWX itself. If the customizations include a skin, the + extension will have a skins directory. If the customizations include python code, the extension will have a + bin/user directory. +
-Each extension should also include:
--
-- readme.txt - a summary of - what the extension does, list of pre-requisites (if any), and - instructions for installing the extension manually -
-- changelog - an enumeration of - changes in each release -
-- install.py - python code used - by the WeeWX ExtensionInstaller -
-- For example, here is the structure of a skin called basic: -
+Each extension should also include:
++
+- readme.txt - a summary of what the extension does, list of pre-requisites (if + any), and instructions for installing the extension manually +
+- changelog - an enumeration of changes in each release +
+- install.py - python code used by the WeeWX ExtensionInstaller +
++ For example, here is the structure of a skin called basic: +
-basic/ +basic/ basic/changelog basic/install.py basic/readme.txt @@ -6652,12 +5743,11 @@ basic/skins/basic/hilo.inc basic/skins/basic/index.html.tmpl basic/skins/basic/skin.conf-- Here is the structure of a search list extension called xstats: -
++ Here is the structure of a search list extension called xstats: +
-xstats/ +xstats/ xstats/changelog xstats/install.py xstats/readme.txt @@ -6665,831 +5755,792 @@ xstats/bin/ xstats/bin/user/ xstats/bin/user/xstats.py-- See the extensions directory of the - WeeWX source for examples. -
++ See the extensions directory of the WeeWX source for examples. +
-To distribute an extension, simply create a compressed - archive of the extension directory.
+To distribute an extension, simply create a compressed archive of the extension directory.
-- For example, create the compressed archive for the basic skin like this: -
++ For example, create the compressed archive for the basic skin like this: +
-tar cvfz basic.tar.gz basic
+tar cvfz basic.tar.gz basic
-Once an extension has been packaged, it can be installed using the - wee_extension - utility. -
+Once an extension has been packaged, it can be installed using the wee_extension utility. +
-Appendix: Archive Types
+Appendix: 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. -
-- 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 types - -- +Archive Type -SQL Type
(appears in archive ++ 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. +
+- 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 types + ++ -Archive Type +SQL Type -
(appears in archive database)Can be used -
in plots -Can be used -
in tag $current- -altimeter -X -X -X -- -barometer -X -X -X -- -consBatteryVoltage -X -X -X -- -dateTime -X -- X (represents current time) -- -dewpoint -X -X -X -- -ET -X -X -X -- -extraHumid1 -X -X -X -- -extraHumid2 -X -X -X -- -extraTemp1 -X -X -X -- -extraTemp2 -X -X -X -- -extraTemp3 -X -X -X -- -hail -X -X -X -- -hailRate -X -X -X -- -heatindex -X -X -X -- -heatingTemp -X -X -X -- -heatingVoltage -X -X -X -- -inHumidity -X -X -X -- -inTemp -X -X -X -- -inTempBatteryStatus -X -X -X -- -interval -X -X -X -- -leafTemp1 -X -X -X -- -leafTemp2 -X -X -X -- -leafWet1 -X -X -X -- -leafWet2 -X -X -X -- -outHumidity -X -X -X -- -outTemp -X -X -X -- -outTempBatteryStatus -X -X -X -- -pressure -X -X -X -- -radiation -X -X -X -- -rain -X -X -X -- -rainBatteryStatus -X -X -X -- -rainRate -X -X -X -- -referenceVoltage -X -X -X -- -rxCheckPercent -X -X -X -- -soilMoist1 -X -X -X -- -soilMoist2 -X -X -X -- -soilMoist3 -X -X -X -- -soilMoist4 -X -X -X -- -soilTemp1 -X -X -X -- -soilTemp2 -X -X -X -- -soilTemp3 -X -X -X -- -soilTemp4 -X -X -X -- -supplyVoltage -X -X -X -- -txBatteryStatus -X -X -X -- -usUnits -X -X -X -- -UV -X -X -X -- -windvec -- X (special vector type) -- - -windBatteryStatus -X -X -X -- -windDir -X -X -X -- -windGust -X -X -X -- -windGustDir -X -X -X -- -windSpeed -X -X -X -- - -windchill -X -X -X -Can be used +
in plots +Can be used +
in tag $current+ +altimeter +X +X +X ++ +barometer +X +X +X ++ +consBatteryVoltage +X +X +X ++ +dateTime +X ++ X (represents current time) ++ +dewpoint +X +X +X ++ +ET +X +X +X ++ +extraHumid1 +X +X +X ++ +extraHumid2 +X +X +X ++ +extraTemp1 +X +X +X ++ +extraTemp2 +X +X +X ++ +extraTemp3 +X +X +X ++ +hail +X +X +X ++ +hailRate +X +X +X ++ +heatindex +X +X +X ++ +heatingTemp +X +X +X ++ +heatingVoltage +X +X +X ++ +inHumidity +X +X +X ++ +inTemp +X +X +X ++ +inTempBatteryStatus +X +X +X ++ +interval +X +X +X ++ +leafTemp1 +X +X +X ++ +leafTemp2 +X +X +X ++ +leafWet1 +X +X +X ++ +leafWet2 +X +X +X ++ +outHumidity +X +X +X ++ +outTemp +X +X +X ++ +outTempBatteryStatus +X +X +X ++ +pressure +X +X +X ++ +radiation +X +X +X ++ +rain +X +X +X ++ +rainBatteryStatus +X +X +X ++ +rainRate +X +X +X ++ +referenceVoltage +X +X +X ++ +rxCheckPercent +X +X +X ++ +soilMoist1 +X +X +X ++ +soilMoist2 +X +X +X ++ +soilMoist3 +X +X +X ++ +soilMoist4 +X +X +X ++ +soilTemp1 +X +X +X ++ +soilTemp2 +X +X +X ++ +soilTemp3 +X +X +X ++ +soilTemp4 +X +X +X ++ +supplyVoltage +X +X +X ++ +txBatteryStatus +X +X +X ++ +usUnits +X +X +X ++ +UV +X +X +X ++ +windvec ++ X (special vector type) ++ + +windBatteryStatus +X +X +X ++ +windDir +X +X +X ++ +windGust +X +X +X ++ +windGustDir +X +X +X ++ +windSpeed +X +X +X ++ + +windchill +X +X +X +Appendix: Aggregation types
+Appendix: Aggregation types
--
+Aggregation types - -- -Aggregation type -Meaning -- -avg -The average value in the aggregation period. -- -sum -The sum of values in the aggregation period. -- -count -The number of non-null values in the aggregation - period. - -- -min -The minimum value in the aggregation period. -- -mintime -The time of the minimum value. -- -max -The maximum value in the aggregation period. -- -maxtime -The time of the maximum value. -- -maxmin -The maximum daily minimum in the aggregation - period. Aggregation period must be one day or longer. - -- -maxmintime -The time of the maximum daily minimum. -- -minmax -The minimum daily maximum in the aggregation - period. Aggregation period must be one day or longer. - -- -minmaxtime -The time of the minimum daily maximum. -- -maxsum -The maximum daily sum in the aggregation period. - Aggregation period must be one day or longer. - -- -maxsumtime -The time of the maximum daily sum. -- -meanmin -The average daily minimum in the aggregation - period. Aggregation period must be one day or longer. - -- -meanmax -The average daily maximum in the aggregation - period. Aggregation period must be one day or longer. - -- -gustdir -The direction of the max gust in the aggregation - period. - -- -last -The last value in the aggregation period. -- -lasttime -The time of the last value in the aggregation - period. - -- -max_ge(val) -The number of days where the maximum value is - greater than or equal to val. Aggregation period - must be one day or longer. - -- -max_le(val) -The number of days where the maximum value is less - than or equal to val. Aggregation period must be - one day or longer. - -- -min_ge(val) -The number of days where the minimum value is - greater than or equal to val. Aggregation period - must be one day or longer. - -- -min_le(val) -The number of days where the minimum value is less - than or equal to val. Aggregation period must be - one day or longer. - -- -sum_ge(val) -The number of days where the sum of value is - greater than or equal to val. Aggregation period - must be one day or longer. - -- -rms -The root mean square value in the aggregation - period. - -- -vecavg -The vector average speed in the aggregation period. -- - -vecdir -The vector averaged direction during the - aggregation period. - -+
-Aggregation types + ++ +Aggregation type +Meaning ++ +avg +The average value in the aggregation period. ++ +sum +The sum of values in the aggregation period. ++ +count +The number of non-null values in the aggregation period. + ++ +min +The minimum value in the aggregation period. ++ +mintime +The time of the minimum value. ++ +max +The maximum value in the aggregation period. ++ +maxtime +The time of the maximum value. ++ +maxmin +The maximum daily minimum in the aggregation period. Aggregation period must be one day or longer. + ++ +maxmintime +The time of the maximum daily minimum. ++ +minmax +The minimum daily maximum in the aggregation period. Aggregation period must be one day or longer. + ++ +minmaxtime +The time of the minimum daily maximum. ++ +maxsum +The maximum daily sum in the aggregation period. Aggregation period must be one day or longer. + ++ +maxsumtime +The time of the maximum daily sum. ++ +meanmin +The average daily minimum in the aggregation period. Aggregation period must be one day or longer. + ++ +meanmax +The average daily maximum in the aggregation period. Aggregation period must be one day or longer. + ++ +gustdir +The direction of the max gust in the aggregation period. + ++ +last +The last value in the aggregation period. ++ +lasttime +The time of the last value in the aggregation period. + ++ +max_ge(val) +The number of days where the maximum value is greater than or equal to val. Aggregation + period must be one day or longer. + ++ +max_le(val) +The number of days where the maximum value is less than or equal to val. Aggregation period + must be one day or longer. + ++ +min_ge(val) +The number of days where the minimum value is greater than or equal to val. Aggregation + period must be one day or longer. + ++ +min_le(val) +The number of days where the minimum value is less than or equal to val. Aggregation period + must be one day or longer. + ++ +sum_ge(val) +The number of days where the sum of value is greater than or equal to val. Aggregation + period must be one day or longer. + ++ +rms +The root mean square value in the aggregation period. + ++ +vecavg +The vector average speed in the aggregation period. ++ + +vecdir +The vector averaged direction during the aggregation period. + +Appendix: Units
+Appendix: Units
-- WeeWX offers three different unit systems: -
++ WeeWX offers three different unit systems: +
--
+The standard unit systems used within WeeWX -- -Name -Encoded value -Note -- -US -0x01 -U.S. Customary -- -METRICWX -0x11 -Metric, with rain related measurements in mm and speeds in m/s - -- -METRIC -0x10 -Metric, with rain related measurements in cm and speeds in km/hr - -+
-The standard unit systems used within WeeWX ++ +Name +Encoded value +Note ++ +US +0x01 +U.S. Customary ++ +METRICWX +0x11 +Metric, with rain related measurements in mm and speeds in m/s + ++ +METRIC +0x10 +Metric, with rain related measurements in cm and speeds in km/hr + +The table below lists all the unit groups, their members, - which units are options for the group, and what the defaults are - for each standard unit system.
--
+Unit groups, members and options - -- -Group -Members -Unit options -US -METRICWX -METRIC -- -group_altitude -altitude -
cloudbase -foot -
meter -foot -meter -meter -- -group_amp -- amp -amp -amp -amp -- -group_data -- byte -
bit -byte -byte -byte -- -group_degree_day -cooldeg -
heatdeg -degree_F_day -
degree_C_day -degree_F_day -degree_C_day -degree_C_day -- -group_direction -gustdir -
vecdir
windDir
- windGustDir -degree_compass -degree_compass -degree_compass -degree_compass -- -group_distance -windrun -mile -
km -mile -km -km -- -group_energy -- watt_hour -watt_hour -watt_hour -watt_hour -- -group_interval -interval -minute -minute -minute -minute -- -group_length -- inch -
cm -inch -cm -cm -- -group_moisture -soilMoist1 -
soilMoist2
soilMoist3
- soilMoist4 -centibar -centibar -centibar -centibar -- -group_percent -extraHumid1 -
extraHumid2
inHumidity -
outHumidity
rxCheckPercent -percent -percent -percent -percent -- -group_power -- watt -watt -watt -watt -- -group_pressure -barometer -
altimeter
pressure -inHg -
mbar
hPa -inHg -mbar -mbar -- -group_radiation -radiation -watt_per_meter_squared -watt_per_meter_squared -watt_per_meter_squared -watt_per_meter_squared -- -group_rain -rain -
ET
hail -inch -
cm
mm -inch -mm -cm -- -group_rainrate -rainRate -
hailRate -inch_per_hour -
cm_per_hour
- mm_per_hour -inch_per_hour -mm_per_hour -cm_per_hour -- -group_speed -wind -
windGust
windSpeed
- windgustvec
windvec -mile_per_hour -
km_per_hour
knot
- meter_per_second -mile_per_hour -meter_per_second -km_per_hour -- -group_speed2 -rms -
vecavg -mile_per_hour2 -
km_per_hour2
knot2
- meter_per_second2 -mile_per_hour2 -meter_per_second2 -km_per_hour2 -- -group_temperature -appTemp -
dewpoint
extraTemp1
- extraTemp2
extraTemp3
heatindex
- heatingTemp
humidex
inTemp
- leafTemp1
leafTemp2
outTemp
- soilTemp1
soilTemp2
soilTemp3
- soilTemp4
windchill -degree_F -
degree_C -degree_F -degree_C -degree_C -- -group_time -dateTime -unix_epoch -
dublin_jd -unix_epoch -unix_epoch -unix_epoch -- -group_uv -UV -uv_index -uv_index -uv_index -uv_index -- -group_volt -consBatteryVoltage -
heatingVoltage
- referenceVoltage
supplyVoltage -volt -volt -volt -volt -- -group_volume -- cubic_foot -
gallon
litre -gallon -litre -litre -- - -group_NONE -NONE -NONE -NONE -NONE -NONE -The table below lists all the unit groups, their members, which units are options for the group, and what the + defaults are for each standard unit system. +
++
-Unit groups, members and options + ++ +Group +Members +Unit options +US +METRICWX +METRIC ++ +group_altitude +altitude +
cloudbase +foot +
meter +foot +meter +meter ++ +group_amp ++ amp +amp +amp +amp ++ +group_data ++ byte +
bit +byte +byte +byte ++ +group_degree_day +cooldeg +
heatdeg +degree_F_day +
degree_C_day +degree_F_day +degree_C_day +degree_C_day ++ +group_direction +gustdir +
vecdir
windDir
windGustDir +degree_compass +degree_compass +degree_compass +degree_compass ++ +group_distance +windrun +mile +
km +mile +km +km ++ +group_energy ++ watt_hour +watt_hour +watt_hour +watt_hour ++ +group_interval +interval +minute +minute +minute +minute ++ +group_length ++ inch +
cm +inch +cm +cm ++ +group_moisture +soilMoist1 +
soilMoist2
soilMoist3
soilMoist4 +centibar +centibar +centibar +centibar ++ +group_percent +extraHumid1 +
extraHumid2
inHumidity
outHumidity
rxCheckPercent +percent +percent +percent +percent ++ +group_power ++ watt +watt +watt +watt ++ +group_pressure +barometer +
altimeter
pressure +inHg +
mbar
hPa +inHg +mbar +mbar ++ +group_radiation +radiation +watt_per_meter_squared +watt_per_meter_squared +watt_per_meter_squared +watt_per_meter_squared ++ +group_rain +rain +
ET
hail +inch +
cm
mm +inch +mm +cm ++ +group_rainrate +rainRate +
hailRate +inch_per_hour +
cm_per_hour
mm_per_hour +inch_per_hour +mm_per_hour +cm_per_hour ++ +group_speed +wind +
windGust
windSpeed
windgustvec
windvec +mile_per_hour +
km_per_hour
knot
meter_per_second +mile_per_hour +meter_per_second +km_per_hour ++ +group_speed2 +rms +
vecavg +mile_per_hour2 +
km_per_hour2
knot2
meter_per_second2 +mile_per_hour2 +meter_per_second2 +km_per_hour2 ++ +group_temperature +appTemp +
dewpoint
extraTemp1
extraTemp2
extraTemp3
heatindex
+ heatingTemp
humidex
inTemp
leafTemp1
leafTemp2
outTemp
soilTemp1 +
soilTemp2
soilTemp3
soilTemp4
windchill +degree_F +
degree_C +degree_F +degree_C +degree_C ++ +group_time +dateTime +unix_epoch +
dublin_jd +unix_epoch +unix_epoch +unix_epoch ++ +group_uv +UV +uv_index +uv_index +uv_index +uv_index ++ +group_volt +consBatteryVoltage +
heatingVoltage
referenceVoltage
supplyVoltage +volt +volt +volt +volt ++ +group_volume ++ cubic_foot +
gallon
litre +gallon +litre +litre ++ + +group_NONE +NONE +NONE +NONE +NONE +NONE +
-
-
+
+
+
-
-
-
+
+
-
-
-
+