Git Product home page Git Product logo

weewx-aqi's Introduction

weewx-aqi

Copyright 2018 - 2021 -- Jonathan Koren [email protected]

What is it?

weewx-aqi is not an air quality monitor. Instead, it calculates an air quality index from various pollutants. Air quality indices are single numbers that are meant to succinctly describe how safe the air is. weeex-aqi can calculate the following indices:

  • Australia's Air Quality Index
  • Australia's Interim Web Reporting Particulate Index (February 2020)
  • Canada's Air Quality Health Index
  • European Union's European Air Quality Index
  • European Union's Common Air Quality Hourly Index
  • India's National Air Quality Index
  • Mexico's Índice Metropolitano de la Calidad del Aire
  • United Kingdom's Daily Air Quality Index
  • United States's Air Quality Index
  • United States's NowCast Air Quality Index

Prerequisites

A source for air quality data, such as weewx-purpleair .

Installation

  1. run the installer (from the git directory):

    wee_extension --install .

  2. restart weewx:

    sudo /etc/init.d/weewx stop sudo /etc/init.d/weewx start

This will install the extension into the weewx/user/ directory.

By default, the install script configures weewx-aqi for use with weewx-purpleair and calculates a United States's NowCast AQI. If you are not using weewx-purpleair, or wish to use a different air quality index, you will need to modify your weewx.conf.

When configuring a different air quality sensor, you need to set the data_binding of sensor readings, and provide a schema of columns to pollutants. along with a column storing the reading's timestamp in epoch seconds UTC, and a column with the semantics of WeeWx's usUnits. Optional columns for temperature, and atmospheric pressure are helpful, but not required.

The configurable schema columns are:

  • dateTime: required Timestamp of the reading in epoch seconds UTC.
  • usUnits: required Unit system the readings are stored in.
  • temp: optional Temperature at the sensor.
  • pressure: optional Atmospheric at the sensor.
  • pm2_5: optional Particulate matter smaller than 2.5 micrometers
  • pm10_0: optional Particulate matter smaller than 10 micrometers
  • co: optional Carbon monoxide
  • no2: optional Nitrogen dioxide
  • so2: optional Sulfur dioxide
  • o3: optional Ozone
  • nh3: optional Ammonia
  • pb: optional Lead

All air quality indices, with the exception of Canada's, can be calculated for a single pollutant. Additionally, all air quality indices can also calculate composite index. However, this index will only be calculated if readings are available for all of the requisite components.

After installation, you will need to modify your weewx.conf. Mainly, you will need to connect weewx-aqi to the data binding for the air sensor. Assuming you're using weewx-purpleair, you will need to add the following to your weewx.conf.

The default weewx.conf block is:

[AqiService]
    [[air_sensor]]
        pm2_5 = pm2_5_atm
        temp = purple_temperature
        data_binding = purpleair_binding
        dateTime = dateTime
        pressure = purple_pressure
        pm10_0 = pm10_0_atm
        usUnits = usUnits
    [[standard]]
        data_binding = aqi_binding
        standard = user.aqi.us.NowCast

Display the data

To make use of the plugin you will need to modify the templates in /etc/weewx/skins/*.tmpl to include references to the new data found in the aqi.sdb file.

Examples:

The Current Value

$latest($data_binding='aqi_binding').aqi_pm2_5

Maximum Value Today

$day($data_binding='aqi_binding').aqi_pm2_5.max

Time Today When The Maximum Value Occurred

$day($data_binding='aqi_binding').aqi_pm2_5.maxtime

Colors and Categories

AQIs have categorical labels associated with the AQI values. The index of the current category is available via $latest($data_binding='aqi_binding').aqi_pm2_5_category. The AQI color and category can be found using wrapping the index with the$aqi Cheetah template. Add to your skin.conf:

[CheetahGenerator]
    search_list_extensions = user.aqi.service.AqiSearchList

And then in your template (e.g. index.html.tmpl), you can add something similar to this example <DIV>, that illustrates display the AQI value, category, and color:

<div style="text-align: center; background-color: #$aqi($current($data_binding='aqi_binding').aqi_pm2_5_category).color;" >
    $current($data_binding='aqi_binding').aqi_pm2_5 <br/>
    $aqi($current($data_binding='aqi_binding').aqi_pm2_5_category).category
</div>

Units

AQIs are dimensionless.

You can also graph these values by adding the appropriate configuration to your skin.conf file:

    [[[dayaqi]]]
        data_binding = aqi_binding
        [[[[aqi_pm2_5]]]]

The values stored in the database are:

aqi_composite,
aqi_composite_category,
aqi_pm2_5,
aqi_pm2_5_category,
aqi_pm10_0,
aqi_pm10_0_category,
aqi_co,
aqi_co_category,
aqi_no2,
aqi_no2_category,
aqi_so2,
aqi_so2_category,
aqi_o3,
aqi_o3_category,
aqi_nh3,
aqi_nh3_category,
aqi_pb,
aqi_pb_category,

Additional utilities

aqi_backfill is a utility that allows you to backfill aqi.sdb according to the current weewx.conf.

Development Testing

cd weewx-aqi
python3 -m unittest

weewx-aqi's People

Contributors

duckrising avatar jonathankoren avatar jpbion avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

weewx-aqi's Issues

custom PM sensor

Hello Jonathan,

I have installed your plugin on WeeWX 4.2.0 with extended database - pm10_0 and pm2_5 values are stored in main weewx.sdb database.
I dont have weewx-purpleair sensor, but custom sensor, which fills out the database through FilePile. So I modified the weewx.conf to:

# Options for extension 'aqi'
[AqiService]
    [[standard]]
        data_binding = aqi_binding
        standard = user.aqi.us.NowCast
    [[air_sensor]]
        data_binding = wx_binding
        usUnits = usUnits
        dateTime = dateTime
#        temp = extraTemp1
#        pressure = pressure
        pm2_5 = pm2_5
        pm10_0 = pm10_0

but I got these errors:

Dec 15 23:07:06 WeeWX /weewxd: AqiService: ValueError AQI calculation for pm2_5 on 1608069960 failed: NowCast AQI could not be calculated for the observations. Too many missing. Missing 2, which meets or exceeding the limit of 1
Dec 15 23:07:06 WeeWX /weewxd: AqiService: ValueError AQI calculation for pm10_0 on 1608069960 failed: NowCast AQI could not be calculated for the observations. Too many missing. Missing 2, which meets or exceeding the limit of 1
Dec 15 23:07:06 WeeWX /weewxd: AqiService: not storing record for dateTime 1608069960

what I have done wrong?

Thanks,
Michal, Slovakia

Schema Columns

In reading the install instructions it seems that the extension assumes there are observation values for pm2_5 and pm10_0, for example.

My weewx uses a custom weather controller, but my driver supplies the preconfigured observation values so I haven't had to modify the database schema. My controller can provide values for PM2.5 and PM10. To extend the schema is this as simple as using "wee_database --add-column" and then make my driver provide the values? Or is there some other configuration I need to do to extend the schema?

Error on startup with the updated version

Hi,
Firstly, thanks for this extension. I am attempting to set it up to use the SDS011 particle sensor in conjunction with the weewx-sds011 driver.

Does this version have backward compatibility or is it purely Python3x? The reason I ask is that it is throwing the following error at startup: -

sudo tail -f /var/log/syslog
May 10 09:25:29 raspberrypi weewx[15155]: **** self.service_obj.append(weeutil.weeutil._get_object(svc)(self, config_dict))
May 10 09:25:29 raspberrypi weewx[15155]: **** File "/home/weewx/bin/weeutil/weeutil.py", line 1107, in _get_object
May 10 09:25:29 raspberrypi weewx[15155]: **** mod = import(module)
May 10 09:25:29 raspberrypi weewx[15155]: **** File "/home/weewx/bin/user/aqi/service.py", line 15, in
May 10 09:25:29 raspberrypi weewx[15155]: **** from . import calculators
May 10 09:25:29 raspberrypi weewx[15155]: **** File "/home/weewx/bin/user/aqi/calculators.py", line 80
May 10 09:25:29 raspberrypi weewx[15155]: **** class AqiCalculator(metaclass=ABCMeta):
May 10 09:25:29 raspberrypi weewx[15155]: **** ^
May 10 09:25:29 raspberrypi weewx[15155]: **** SyntaxError: invalid syntax
May 10 09:25:29 raspberrypi weewx[15155]: **** Exiting.

aqi-service fails and crashes weewx when no data is available

I had a sensor issue and so had no data for an extended period of time. After not finding any data, the AQI service fails and crashes weewx.
Jun 4 05:40:19 weewx weewx[20685] INFO weewx.engine: Main loop exiting. Shutting engine down.
Jun 4 05:40:19 weewx weewx[20685] INFO weewx.engine: Shutting down StdReport thread
Jun 4 05:40:19 weewx weewx[20685] INFO user.sdr: shutdown process rtl_433 -M utc -F json
Jun 4 05:40:19 weewx weewx[20685] INFO user.MQTTSubscribe: (Service) Disconnected with result code 0
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: Caught unrecoverable exception:
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** list index out of range
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** Traceback (most recent call last):
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 214, in run
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** self.dispatchEvent(weewx.Event(weewx.CHECK_LOOP, packet=packet))
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 245, in dispatchEvent
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** callback(event)
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 634, in check_loop
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** raise BreakLoop
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** weewx.engine.BreakLoop
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: ****
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** During handling of the above exception, another exception occurred:
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: ****
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** Traceback (most recent call last):
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 650, in post_loop
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** self._catchup(self.engine.console.genArchiveRecords)
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 697, in _catchup
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** for record in generator(lastgood_ts):
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/drivers/init.py", line 30, in genArchiveRecords
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** raise NotImplementedError("Method 'genArchiveRecords' not implemented")
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** NotImplementedError: Method 'genArchiveRecords' not implemented
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: ****
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** During handling of the above exception, another exception occurred:
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: ****
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** Traceback (most recent call last):
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewxd", line 153, in main
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** engine.run()
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 221, in run
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 245, in dispatchEvent
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** callback(event)
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 652, in post_loop
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** self._software_catchup()
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 715, in _software_catchup
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** self.engine.dispatchEvent(weewx.Event(weewx.NEW_ARCHIVE_RECORD,
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 245, in dispatchEvent
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** callback(event)
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/user/aqi/service.py", line 355, in new_archive_record
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** self.aqi_standard.calculate_aqi(pollutant, required_unit, joined)
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/user/aqi/standards.py", line 57, in calculate_aqi
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** return self.calculators[pollutant].calculate(pollutant, observation_unit, observations)
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/user/aqi/calculators.py", line 172, in calculate
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** last_valid_index = get_last_valid_index(observations, self.duration_in_secs)
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** File "/home/weewx/bin/user/aqi/calculators.py", line 38, in get_last_valid_index
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** first_invalid_timestamp = observations[0][0] - duration_in_secs
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** IndexError: list index out of range
Jun 4 05:40:23 weewx weewx[20685] CRITICAL main: **** Exiting.

United States EPA has updated their AQI ranges for PM2.5

Hello,

As of May 6, 2024 the US EPA has updated their calculations for PM2.5 to make the range for 'good' to be much smaller. The notice (which is currently available on their website https://www.airnow.gov/) states:

"2024-05-06
AirNow products now reflect the updated Air Quality Index for fine particle pollution."

And they have provided a link to a pdf with more details including the new ranges (https://www.epa.gov/system/files/documents/2024-02/pm-naaqs-air-quality-index-fact-sheet.pdf)

In short, instead of good being calculated off of a range of 0.0 to 12.0 micrograms per cubic meter, it is now based on 0.0 to 9.0. The moderate range has changed accordingly from 12.1 to 35.4 to 9.1 to 35.4. All other categories have the same ranges as before.

With the older settings being present in this plugin the values don't match well with what the EPA and others are publishing. On the other hand, if a change is made to the plugin there will cause a continuity issue as the values calculated with the new standards won't be an apples to apples comparison with historical data.

As I am just integrating an air quality sensor (Ecowitt WH41) I went ahead and modified the /etc/weewx/bin/user/aqi/us.py to reflect the new values and it seems to be working well. For reference please find the diff output below. Perhaps having a us.py and a us_legacy.py would be a good way to move forward?

root@weewx:/etc/weewx/bin/user/aqi# diff us.py.orig us.py
38,39c38,39
<             .add_breakpoint(  0,  50,   0.0,  12.0) \
<             .add_breakpoint( 51, 100,  12.1,  35.4) \
---
>             .add_breakpoint(  0,  50,   0.0,   9.0) \
>             .add_breakpoint( 51, 100,   9.1,  35.4) \

aqi service fails in case sensor meassure very high amount of particles

Aug 19 19:10:19 new-weather-machine journal: weewx[26377] INFO weewx.manager: Added record 2022-08-19 19:09:34 CEST (1660928974) to database 'purpleair.sdb'
Aug 19 19:10:19 new-weather-machine journal: weewx[26377] INFO weewx.manager: Added record 2022-08-19 19:09:34 CEST (1660928974) to daily summary in 'purpleair.sdb'
Aug 19 19:10:19 new-weather-machine journal: weewx[26377] INFO weewx.engine: Main loop exiting. Shutting engine down.
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] INFO user.interceptor: shutting down server thread
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__: Caught unrecoverable exception:
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  AQI can not be calculated from this table
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  Traceback (most recent call last):
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 214, in run
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      self.dispatchEvent(weewx.Event(weewx.CHECK_LOOP, packet=packet))
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      callback(event)
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 634, in check_loop
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      raise BreakLoop
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  weewx.engine.BreakLoop
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  During handling of the above exception, another exception occurred:
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  Traceback (most recent call last):
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 650, in post_loop
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      self._catchup(self.engine.console.genArchiveRecords)
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 697, in _catchup
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      for record in generator(lastgood_ts):
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/drivers/__init__.py", line 30, in genArchiveRecords
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      raise NotImplementedError("Method 'genArchiveRecords' not implemented")
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  NotImplementedError: Method 'genArchiveRecords' not implemented
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  During handling of the above exception, another exception occurred:
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  Traceback (most recent call last):
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewxd", line 153, in main
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      engine.run()
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 221, in run
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      callback(event)
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 652, in post_loop
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      self._software_catchup()
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 717, in _software_catchup
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      origin='software'))
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      callback(event)
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/user/aqi/service.py", line 342, in new_archive_record
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      self.aqi_standard.calculate_aqi(pollutant, required_unit, joined)
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/user/aqi/standards.py", line 57, in calculate_aqi
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      return self.calculators[pollutant].calculate(pollutant, observation_unit, observations)
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/user/aqi/calculators.py", line 182, in calculate
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      return self._calculate_index_from_mean(obs_mean)
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****    File "/usr/share/weewx/user/aqi/calculators.py", line 282, in _calculate_index_from_mean
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****      raise IndexError('AQI can not be calculated from this table')
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  IndexError: AQI can not be calculated from this table
Aug 19 19:10:20 new-weather-machine journal: weewx[26377] CRITICAL __main__:     ****  Exiting.

Support NowCast 2019 O3 Calculations

In 2019, the EPA changed the way NowCast calculates O3 now using a complicated system that can turn into using a partial least squares model to predict the 8 hour average centered on the current time. (i.e. Predict what the 8 hour average would be if you calculated it using 4 hours of the past, and 4 hours in the future.)

This is a rather involved calculation to say the least.

See https://github.com/USEPA/O3-Nowcast for a definition.

I assume that you're supposed to take this 8 hour prediction and feed that into the 8 hour O3 table, along with plugging the 1 hour trailing average into the 1 hour table, and then taking the maximum AQI.

WeeWX crashing

Hello,
could you help me with the issue - weewx-aqi crashing the weewx?

Dec 28 09:46:54 WeeWX weewx[28536] WARNING weewx.qc: 2022-12-28 09:46:00 CET (1672217160) Archive value 'extraTemp1' 196.088 outside limi                                                    ts (-40.0, 120.0)
Dec 28 09:46:54 WeeWX weewx[28536] WARNING weewx.qc: 2022-12-28 09:46:00 CET (1672217160) Archive value 'pm10_0' -0.5 outside limits (0.0                                                    , 500.0)
Dec 28 09:46:54 WeeWX weewx[28536] WARNING weewx.qc: 2022-12-28 09:46:00 CET (1672217160) Archive value 'pm2_5' 98966.41 outside limits (                                                    0.0, 500.0)
Dec 28 09:46:54 WeeWX weewx[28536] INFO weewx.engine: Main loop exiting. Shutting engine down.
Dec 28 09:46:54 WeeWX weewx[28536] INFO user.interceptor: shutting down server thread
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__: Caught unrecoverable exception:
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  list index out of range
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  Traceback (most recent call last):
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 214, in run
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      self.dispatchEvent(weewx.Event(weewx.CHECK_LOOP, packet=packet))
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      callback(event)
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 634, in check_loop
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      raise BreakLoop
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  weewx.engine.BreakLoop
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  During handling of the above exception, another exception occurred:
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  Traceback (most recent call last):
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 650, in post_loop
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      self._catchup(self.engine.console.genArchiveRecords)
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 697, in _catchup
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      for record in generator(lastgood_ts):
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/drivers/__init__.py", line 30, in genArchi                                                    veRecords
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      raise NotImplementedError("Method 'genArchiveRecords' not implemented                                                    ")
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  NotImplementedError: Method 'genArchiveRecords' not implemented
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  During handling of the above exception, another exception occurred:
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  Traceback (most recent call last):
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewxd", line 154, in main
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      engine.run()
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 221, in run
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      callback(event)
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 652, in post_loop
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      self._software_catchup()
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 715, in _software_catchup
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      self.engine.dispatchEvent(weewx.Event(weewx.NEW_ARCHIVE_RECORD,
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      callback(event)
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/user/aqi/service.py", line 355, in new_archive_r                                                    ecord
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      self.aqi_standard.calculate_aqi(pollutant, required_unit, joined)
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/user/aqi/standards.py", line 57, in calculate_aq                                                    i
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      return self.calculators[pollutant].calculate(pollutant, observation_u                                                    nit, observations)
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/user/aqi/calculators.py", line 172, in calculate
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      last_valid_index = get_last_valid_index(observations, self.duration_i                                                    n_secs)
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****    File "/usr/share/weewx/user/aqi/calculators.py", line 38, in get_last_v                                                    alid_index
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****      first_invalid_timestamp = observations[0][0] - duration_in_secs
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  IndexError: list index out of range
Dec 28 09:46:54 WeeWX weewx[28536] CRITICAL __main__:     ****  Exiting.

I have the latest Master branch installed.
thank you,
Michal

weewx crashing

we have the latest version of weewx-aqi 1.4.1 but weewx still crash when sensor measure very high amount of particles.

weewx log:

Jan 24 16:40:24 piWx weewx[581] CRITICAL main: Caught unrecoverable exception:
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** AQI can not be calculated from this table
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** Traceback (most recent call last):
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 214, in run
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** self.dispatchEvent(weewx.Event(weewx.CHECK_LOOP, packet=packet))
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** callback(event)
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 634, in check_loop
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** raise BreakLoop
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** weewx.engine.BreakLoop
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: ****
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** During handling of the above exception, another exception occurred:
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: ****
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** Traceback (most recent call last):
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 650, in post_loop
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** self._catchup(self.engine.console.genArchiveRecords)
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 697, in _catchup
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** for record in generator(lastgood_ts):
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/drivers/init.py", line 30, in genArchiveRecords
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** raise NotImplementedError("Method 'genArchiveRecords' not implemented")
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** NotImplementedError: Method 'genArchiveRecords' not implemented
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: ****
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** During handling of the above exception, another exception occurred:
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: ****
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** Traceback (most recent call last):
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewxd", line 154, in main
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** engine.run()
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 221, in run
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** callback(event)
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 652, in post_loop
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** self._software_catchup()
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 715, in _software_catchup
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** self.engine.dispatchEvent(weewx.Event(weewx.NEW_ARCHIVE_RECORD,
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/weewx/engine.py", line 245, in dispatchEvent
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** callback(event)
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/user/aqi/service.py", line 355, in new_archive_record
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** self.aqi_standard.calculate_aqi(pollutant, required_unit, joined)
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/user/aqi/standards.py", line 57, in calculate_aqi
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** return self.calculators[pollutant].calculate(pollutant, observation_unit, observations)
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/user/aqi/calculators.py", line 186, in calculate
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** return self._calculate_index_from_mean(obs_mean)
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** File "/usr/share/weewx/user/aqi/calculators.py", line 286, in _calculate_index_from_mean
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** raise IndexError('AQI can not be calculated from this table')
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** IndexError: AQI can not be calculated from this table
Jan 24 16:40:24 piWx weewx[581] CRITICAL main: **** Exiting.

how to fix this issue?
thnks

UK DAQI aqi.sdb

A question. I am using the UK DAQI. I notice that the category columns are all populated in the aqi.sdb database with zero. Is this correct? I am still getting a background colour but as the readings are at index 1 at the moment have yet to see if this will change when index increases. Am I correct in thinking the category is linked to colour or is it different for DAQI.

I am using a SDS011 particle sensor which measures PM2.5 and PM10 only with the weewx-sds011 driver.
Screenshot from 2020-05-12 09 44 51

Thanks
Ian

weewx-aqi v1.4.1 calculation fail

when the sensor measure a sudden high reading the weewx-aqi calculation fail and crash weewx.
it will never run until the reading of the sensor comes down to within the limits.

is it possible to have max level filtering within the code of weewx-aqi so the error " IndexError: AQI can not be calculated from this table" can be avoided and have smooth weewx run.

Two Sensors Support

I have outdoor and indoor air quality sensors but weewx-aqi support only one sensor. can we get support for the other sensor

Weewx Died This Morning

I am not sure what is happening, but this morning, it seems Weewx stopped working. I can reboot and it works for a little bit, then stops working. Here is the log excerpt.

This is the log after a reboot.

Sep 30 14:48:14 weewx-pi systemd[1]: Finished Update UTMP about System Runlevel Changes.
Sep 30 14:48:15 weewx-pi cloud-init[1985]: Cloud-init v. 21.2-3-g899bfaa9-0ubuntu220.04.1 running 'modules:final' at Thu, 30 Sep 2021 20:48:15 +0000. Up 56.14 seconds.
Sep 30 14:48:15 weewx-pi cloud-init[1985]: Cloud-init v. 21.2-3-g899bfaa9-0ubuntu2
20.04.1 finished at Thu, 30 Sep 2021 20:48:15 +0000. Datasource DataSourceNone. Up 56.49 seconds
Sep 30 14:48:15 weewx-pi cloud-init[1985]: 2021-09-30 20:48:15,466 - cc_final_message.py[WARNING]: Used fallback datasource
Sep 30 14:48:15 weewx-pi systemd[1]: Finished Execute cloud user/final scripts.
Sep 30 14:48:15 weewx-pi systemd[1]: Reached target Cloud-init target.
Sep 30 14:48:15 weewx-pi systemd[1]: Startup finished in 9.642s (kernel) + 46.957s (userspace) = 56.599s.
Sep 30 14:48:23 weewx-pi weewx[867] DEBUG user.gw1000: Next update in 20 seconds
Sep 30 14:48:23 weewx-pi weewx[867] DEBUG weewx.restx: Wunderground-RF: wait interval (20 < 80) has not passed for record 2021-09-30 14:48:23 MDT (1633034903)
Sep 30 14:48:23 weewx-pi weewx[867] INFO weewx.restx: MQTT: Published record 2021-09-30 14:48:23 MDT (1633034903)
Sep 30 14:48:43 weewx-pi weewx[867] DEBUG user.gw1000: Next update in 20 seconds
Sep 30 14:48:43 weewx-pi weewx[867] DEBUG weewx.restx: Wunderground-RF: wait interval (40 < 80) has not passed for record 2021-09-30 14:48:43 MDT (1633034923)
Sep 30 14:48:43 weewx-pi weewx[867] INFO weewx.restx: MQTT: Published record 2021-09-30 14:48:43 MDT (1633034923)
Sep 30 14:49:03 weewx-pi weewx[867] DEBUG user.gw1000: Next update in 20 seconds
Sep 30 14:49:03 weewx-pi weewx[867] DEBUG weewx.restx: Wunderground-RF: wait interval (60 < 80) has not passed for record 2021-09-30 14:49:03 MDT (1633034943)
Sep 30 14:49:03 weewx-pi weewx[867] INFO weewx.restx: MQTT: Published record 2021-09-30 14:49:03 MDT (1633034943)
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG user.gw1000: Next update in 20 seconds
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG user.aqixtypes: UsEpaAqiXTypes.get_scalar(aqi_pm2_51_24h_avg,,)
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG user.aqixtypes: UsEpaAqiXTypes.get_scalar(aqi_pm2_52_24h_avg,,)
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG user.aqixtypes: UsEpaAqiXTypes.get_scalar 'pm2_52_24h_avg' not in record
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.wxservices: Unknown extensible type 'aqi_pm2_52_24h_avg'
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG user.aqixtypes: UsEpaAqiXTypes.get_scalar(aqi_pm2_51_instant,,)
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG user.aqixtypes: UsEpaAqiXTypes.get_scalar(aqi_pm2_52_instant,,)
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG user.aqixtypes: UsEpaAqiXTypes.get_scalar 'pm2_52' not in record
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.wxservices: Unknown extensible type 'aqi_pm2_52_instant'
Sep 30 14:49:23 weewx-pi weewx[867] INFO weewx.engine: Main loop exiting. Shutting engine down.
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.restx: Shut down WeatherCloud thread.
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.restx: Shut down OWM thread.
Sep 30 14:49:23 weewx-pi weewx[867] INFO weewx.restx: MQTT: Published record 2021-09-30 14:49:23 MDT (1633034963)
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.restx: Shut down MQTT thread.
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.restx: Shut down AWEKAS thread.
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.restx: Shut down WOW thread.
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.restx: Shut down CWOP thread.
Sep 30 14:49:23 weewx-pi weewx[867] DEBUG weewx.restx: Shut down PWSWeather thread.
Sep 30 14:49:24 weewx-pi weewx[867] INFO weewx.restx: Wunderground-RF: Published record 2021-09-30 14:49:23 MDT (1633034963)
Sep 30 14:49:24 weewx-pi weewx[867] DEBUG weewx.restx: Shut down Wunderground-RF thread.
Sep 30 14:49:24 weewx-pi weewx[867] DEBUG weewx.restx: Shut down StationRegistry thread.
Sep 30 14:49:24 weewx-pi weewx[867] INFO user.gw1000: Gw1000Collector thread has been terminated
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: Caught unrecoverable exception:
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** unsupported operand type(s) for -: 'NoneType' and 'float'
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** Traceback (most recent call last):
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 214, in run
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** self.dispatchEvent(weewx.Event(weewx.CHECK_LOOP, packet=packet))
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 245, in dispatchEvent
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** callback(event)
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 624, in check_loop
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** raise BreakLoop
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** weewx.engine.BreakLoop
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: ****
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** During handling of the above exception, another exception occurred:
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: ****
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** Traceback (most recent call last):
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 640, in post_loop
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** self._catchup(self.engine.console.genArchiveRecords)
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 687, in _catchup
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** for record in generator(lastgood_ts):
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/drivers/init.py", line 30, in genArchiveRecords
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** raise NotImplementedError("Method 'genArchiveRecords' not implemented")
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** NotImplementedError: Method 'genArchiveRecords' not implemented
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: ****
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** During handling of the above exception, another exception occurred:
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: ****
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** Traceback (most recent call last):
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewxd", line 157, in main
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** engine.run()
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 221, in run
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 245, in dispatchEvent
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** callback(event)
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 642, in post_loop
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** self._software_catchup()
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 705, in _software_catchup
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** self.engine.dispatchEvent(weewx.Event(weewx.NEW_ARCHIVE_RECORD,
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/engine.py", line 245, in dispatchEvent
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** callback(event)
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/user/aqi/service.py", line 311, in new_archive_record
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** temp_kelvin = weewx.units.CtoK(weewx.units.FtoC(row['outTemp']))
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** File "/home/weewx/bin/weewx/units.py", line 44, in FtoC
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** return (x - 32.0) * 5.0 / 9.0
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** TypeError: unsupported operand type(s) for -: 'NoneType' and 'float'
Sep 30 14:49:24 weewx-pi weewx[867] CRITICAL main: **** Exiting.
Sep 30 15:02:21 weewx-pi systemd[1]: Starting Cleanup of Temporary Directories...
Sep 30 15:02:22 weewx-pi systemd[1]: systemd-tmpfiles-clean.service: Succeeded.
Sep 30 15:02:22 weewx-pi systemd[1]: Finished Cleanup of Temporary Directories.
^C

Explicitly Support Unbounded Indicies

Currently we put a very large upper bound instead of having unbounded indicies. This should be changed to more clearly support unbounded indicies.

Additionally, we should support out of table range data as well.

Not enough observations

I am trying to get weewx-aqi working with my custom weather station. My weather station has an air quality sensor that emits sensor readings every 2 seconds. These readings are used to generate loop packets in my driver. The air quality readings are not stored anywhere. I've configured weeewx-aqi to use the weewx archive records as the sensor database (data_binding = wx_binding). The weewx-aqi extension runs just fine but I get "Not enough observations" errors and nothing is written to the aqi database. My guess is that this is caused by the fact that the sensor store in my case is just the weewx archive records and there is clearly not enough data to satisfy the weewx-aqi extension. My idea to fix this is to create a real AQI sensor store that my weather station driver would write into. I would then configure weewx-aqi to to this. This seems like it would make this work. Does this sound like a correct analysis?

Aug 22 15:14:14 weewx-test /weewxd: AqiService: ValueError AQI calculation for pm2_5 on 1629645240 failed: Not enough observations wanted 540, but got 16
Aug 22 15:14:14 weewx-test /weewxd: AqiService: ValueError AQI calculation for pm10_0 on 1629645240 failed: Not enough observations wanted 540, but got 16
Aug 22 15:14:14 weewx-test /weewxd: AqiService: not storing record for dateTime 1629645240

AQI is slow to drop after spike

If my PM2.5 sensor has a spike for whatever reason, the AQI is slow to respond and spike too, and then it takes forever to return to normal even after normal readings have resumed. Here is a graph of it happening. It is annoying.

image

units.py: KeyError: 'parts_per_billion'

Hello and sorry for my bad english. I am using your extension and I noticed that the units are used differently.

units.py with part_per_xxxx
part_per_million/part_per_billion

in us.py/ca.py with part(s)_per_xxxx
parts_per_million,parts_per_million

For example, if I use o3, then the conversion should be from obs unit microgram_per_meter_cubed to required_unit parts_per_billion.

The error then occurs in units.py:
KeyError: 'parts_per_billion'

Regards
Henry

Calculate EU AQI

Hello, would it be possible to add the calculation for European AQI?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.