diff --git a/bin/weewx/wxservices.py b/bin/weewx/wxservices.py index 5fad9a39..99543028 100644 --- a/bin/weewx/wxservices.py +++ b/bin/weewx/wxservices.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2009-2020 Tom Keffer +# Copyright (c) 2009-2021 Tom Keffer # # See the file LICENSE.txt for your full rights. # @@ -13,6 +13,7 @@ from __future__ import absolute_import import logging import weewx.engine +import weeutil.weeutil log = logging.getLogger(__name__) @@ -20,36 +21,55 @@ log = logging.getLogger(__name__) class StdWXCalculate(weewx.engine.StdService): def __init__(self, engine, config_dict): - """Initialize an instance of StdWXXTypes""" + """Initialize an instance of StdWXCalculate and determine the calculations to be done. + + Directives look like: + + obs_type = [prefer_hardware|hardware|software], [loop|archive] + + where: + + obs_type is an observation type to be calculated, such as 'heatindex' + + The choice [prefer_hardware|hardware|software] determines how the value is to be + calculated. Option "prefer_hardware" means that if the hardware supplies a value, it will + be used, otherwise the value will be calculated in software. + + The choice [loop|archive] indicates whether the calculation is to be done for only LOOP + packets, or only archive records. If left out, it will be done for both. + + Examples: + + cloudbase = software,loop + The derived type 'cloudbase' will always be calculated in software, but only for LOOP + packets + + cloudbase = software, record + The derived type 'cloudbase' will always be calculated in software, but only for archive + records. + + cloudbase = software + The derived type 'cloudbase' will always be calculated in software, for both LOOP packets + and archive records""" + super(StdWXCalculate, self).__init__(engine, config_dict) - # determine the calculations to be done and when - # - # create calc_dicts for LOOP and for ARCHIVE holding the calculations - # to be done at those times. the configuration indicates the bindings, - # and thus into which or both calc_dicts that each calculation should - # be placed. no bindings mentioned means 'loop' and 'archive' e.g. - # 'cloudbase = software' same as 'cloudbase = software,loop,archive' - # (backwards compatability with weewx 4.2 configuration files). - # TODO document in User and/or Customisation Guide - # - # Default to no calculations. - # - self.loop_calc_dict = dict() # map {obs->directive} for LOOP - self.archive_calc_dict = dict() # map {obs->directive} for ARCHIVE - for obs, rule in config_dict.get('StdWXCalculate', {}).get('Calculations', {}).items(): - # ensure we have a list, not a (possibly comma-separated) string - words = rule if isinstance(rule, list) else rule.split(',') - # canonicalise to trimmed lower case - words = [w.strip().lower() for w in words] + self.loop_calc_dict = dict() # map {obs->directive} for LOOP packets + self.archive_calc_dict = dict() # map {obs->directive} for archive records - # the first word is the directive, the rest are bindings (if any) - if len(words) == 1 or 'loop' in words: + for obs_type, rule in config_dict.get('StdWXCalculate', {}).get('Calculations', {}).items(): + # Ensure we have a list: + words = weeutil.weeutil.option_as_list(rule) + # Split the list up into a directive, and (optionally) which bindings it applies to + # (loop or archive). + directive = words[0].lower() + bindings = [w.lower() for w in words[1:]] + if not bindings or 'loop' in bindings: # no bindings mentioned, or 'loop' plus maybe others - self.loop_calc_dict[obs] = words[0] - if len(words) == 1 or 'archive' in words: + self.loop_calc_dict[obs_type] = directive + if not bindings or 'archive' in bindings: # no bindings mentioned, or 'archive' plus maybe others - self.archive_calc_dict[obs] = words[0] + self.archive_calc_dict[obs_type] = directive # Backwards compatibility for configuration files v4.1 or earlier: self.loop_calc_dict.setdefault('windDir', 'software') @@ -58,8 +78,8 @@ class StdWXCalculate(weewx.engine.StdService): self.archive_calc_dict.setdefault('windGustDir', 'software') if weewx.debug > 1: - log.debug(f"Calculations for LOOP: {self.loop_calc_dict}") - log.debug(f"Calculations for ARCHIVE: {self.archive_calc_dict}") + log.debug("Calculations for LOOP packets: %s", self.loop_calc_dict) + log.debug("Calculations for archive records: %s", self.archive_calc_dict) # Get the data binding. Default to 'wx_binding'. data_binding = config_dict.get('StdWXCalculate', diff --git a/docs/changes.txt b/docs/changes.txt index d005ae82..85ee339c 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -1,6 +1,12 @@ weewx change history -------------------- +4.4.0 MM/DD/YYYY + +StdWXCalculate can now do calculations for only LOOP packets, only archive +records, or both. PR #630. Thanks to user g-eddy! + + 4.3.0 01/04/2020 Version 4.2.0 had a bug, which caused the sums in the daily summary to be diff --git a/docs/usersguide.htm b/docs/usersguide.htm index 09bf4a76..456a909a 100644 --- a/docs/usersguide.htm +++ b/docs/usersguide.htm @@ -2601,7 +2601,7 @@ longitude = -77.0366

The service StdWXCalculate can be extended by the user to add new, derived types - using the XTypes system. See the wiki article Extensible types (XTypes) for how to do this.

@@ -2609,9 +2609,71 @@ longitude = -77.0366

[[Calculations]]

- This subsection specifies which strategy is to be used to provide values for derived variables. + This subsection specifies which strategy is to be used to provide values for derived variables. It consists + of zero or more options with the syntax: +

+
obs_type = directive[, optional_bindings]...
+ +

where

+ + + +

+ Example 1: if your weather station calculates windchill using the pre-2001 algorithm, and you prefer to + have WeeWX calculate it using a modern algorithm, specify the following: +

+ +
[StdWXCalculate]
+    [[Calculations]]
+      windchill = software
+

+ This will force WeeWX to always calculate a value for windchill, irregardless + of whether the hardware provides one. +

+ +

+ Example 2: suppose you want ET to be calculated, but only for archive records. The option would look like: +

+
[StdWXCalculate]
+    [[Calculations]]
+      ET = software, archive
+ +

Defaults

+ +

+ Note:
In the absence of a [[Calculations]] section, no values will be - calculated. However, the version of weewx.conf that comes with the WeeWX + calculated! +

+

+ However, the version of weewx.conf that comes with the WeeWX distribution comes with a version of [[Calculations]] that looks like this:

@@ -2632,38 +2694,6 @@ longitude = -77.0366 windchill = prefer_hardware windrun = prefer_hardware -

- The options for each quantity are hardware, software, or - prefer_hardware

- - - - - - - - - - - - - -
hardwareNever calculate the value.
softwareAlways calculate the value.
prefer_hardwareCalculate the value only if it is not provided by hardware.
- -

- For example, if your weather station calculates windchill using the pre-2001 algorithm, and you prefer to - have WeeWX calculate it using a current algorithm, specify the following: -

- -
[StdWXCalculate]
-    [[Calculations]]
-      windchill = software
- -

- This will force WeeWX to always calculate a value for windchill, irregardless - of whether the hardware provides one. -

-

[[WXXTypes]]