Version: 4.2
WeeWX Upgrade Guide

This document explains the three methods of upgrading:

- Upgrading using setup.py
- Upgrading using DEB package
- Upgrading using RPM package

The section Instructions for Specific Versions describes changes required from one version to the next. These changes apply to every upgrade method.

Warning!
You must use the same upgrade technique as your initial install! For example, if you used setup.py to install WeeWX, then you should use setup.py to upgrade. If you used a DEB or RPM package to install, then you should upgrade using the same package type.

# Upgrading using setup.py

Before upgrading WeeWX, check the section Instructions for Specific Versions to see if any specific actions are required.

If you are an old Python 2 version, and you plan on switching to Python 3, make sure you have installed whatever pre-requisites are required. You can find them in the guide Installation using setup.py.

Then follow the standard installation procedure:

Unpack the archive:

    tar xvfz weewx-X.Y.Z.tar.gz

Change directory into it:

    cd weewx-X.Y.Z

Build the distribution, using whatever version of Python you plan to use. For example, for Python 3:

    python3 ./setup.py build

Warning!
Before doing the next step, be sure that home in the file setup.cfg is set to the location of the previous WeeWX installation.

After checking setup.cfg, install your new version of WeeWX, again using the version of Python you plan on using:

    sudo python3 ./setup.py install

The install process will do the following:

- Install the new version in the bin directory, while preserving any user extensions in the bin/user directory
- Save a copy of the old weewx.conf as weewx.conf.YYYYMMDDHHMMSS
- Update your copy of weewx.conf, reflecting any changes required by the latest version of WeeWX. This updated version is then installed.
- Install a skins directory if one does not already exist.

Finally, restart WeeWX.

# Upgrading using DEB package

If you have specified the WeeWX apt repository in /etc/apt/sources.list.d/weewx.list, then upgrade to the latest version like this:

    sudo apt-get update
    sudo apt-get install weewx

Otherwise, download the latest X.Y.Z DEB package from the Download page on weewx.com, then upgrade like this:

    sudo dpkg -i weewx_X.Y.Z-R.deb

The upgrade process will not modify the WeeWX databases.

Unmodified files will be upgraded. If modifications have been made to the WeeWX configuration, you will be prompted as to whether you want to keep the existing configuration or accept the new configuration. Either way, a copy of the option you did not choose will be saved.

For example, if /etc/weewx/weewx.conf was modified, you will see a message something like this:

    Configuration file `/etc/weewx/weewx.conf'
      ==> Modified (by you or by a script) since installation.
      ==> Package distributor has shipped an updated version.
      What would you like to do about it ?  Your options are:
                Y or I  : install the package maintainer's version
                N or O  : keep your currently-installed version
                  D     : show the differences between the versions
                  Z     : start a shell to examine the situation
             The default action is to keep your current version.
      *** weewx.conf (Y/I/N/O/D/Z) [default=N] ?

Choosing I (install the new version) will place the previous configuration in /etc/weewx/weewx.conf.dpkg-old where it can be compared with the new version /etc/weewx/weewx.conf

Choosing O (keep the current version) will place the new configuration in /etc/weewx/weewx.conf.dpkg-new where it can be compared with the old version /etc/weewx/weewx.conf

# Upgrading using RPM package

If you have specified the WeeWX yum repository in /etc/yum.repos.d/weewx.repo, then upgrade to the latest version like this:

    sudo yum update weewx

Otherwise, download the latest X.Y.Z RPM package from the Download page on weewx.com, then upgrade like this:

    sudo rpm -U weewx-X.Y.Z-R.rpm

The upgrade process will not modify the WeeWX databases.

Unmodified files will be upgraded. If modifications have been made to the configuration, rpm will display a message about any differences between the changes and the new configuration. Any new changes from the upgrade will be noted as files with a .rpmnew extension and the modified files will be left untouched.

For example, if /etc/weewx/weewx.conf was modified, rpm will present a message something like this:

    warning: /etc/weewx/weewx.conf created as /etc/weewx/weewx.conf.rpmnew

# Instructions for specific versions

## From 4.1 or earlier

For the most part, V4.2 is backwards compatible with previous versions. There is one small exception.

### Type beaufort deprecated

The type beaufort has been deprecated, although there are no immediate plans to remove it — using it will put a warning in the log. Instead, it has become a new unit, which can be used as part of group_speed. Here's an example:

pre 4.1 | 4.2
    <p>
       The current wind speed is $current.windSpeed,
       which is $current.beaufort on the beaufort scale.
    </p>
    <p>
       The current wind speed is $current.windSpeed,
       which is $current.windSpeed.beaufort on the beaufort scale.
    </p>

## From V3.9 or earlier

For the most part, V4.0 is backwards compatible with previous versions.

### Python 2.5 and 2.6

Support for Python 2.5 and 2.6 has been dropped. It has now been well over 10 years since these versions were introduced, and 6+ years since they were supported by the Python Software Foundation. If you are using Python 2.5 or 2.6, then you should either upgrade your copy of Python, or stay with your old version of WeeWX.

### [StdWXCalculate]

In earlier versions of WeeWX, many derived types were calculated by default by the service StdWXCalculate. By contrast, in WeeWX V4, no derived types are calculated by default — all desired types must be explicitly listed in weewx.conf. For most users, this will not cause a problem because most types were already listed in weewx.conf. However if you deleted one of the following types in the clause [StdWXCalculate], and started to depend on the default calculations, then the type will no longer be calculated in V4.

pressure | barometer | altimeter
windchill | heatindex | dewpoint
inDewpoint | rainRate

In this case, you should add the type to [StdWXCalculate]. For example, if for some reason you deleted dewpoint, then you would need to add the following

    [StdWXCalculate]
      [[Calculations]]
        ...
        dewpoint = prefer_hardware

## From V3.8 or earlier

### New skins

Version 3.9 introduces and installs a new skin, Seasons, and promotes two old skins, Mobile and Smartphone, previously part of Standard, to first-class, independent, skins.

- If you are installing fresh (not an upgrade), then all four skins, Seasons, Standard, Mobile, and Smartphone will be installed, but only Seasons will be activated.
- If you are upgrading, then the three new skins, Seasons, Mobile, and Smartphone will be installed, but none will be activated. Your existing Standard will be left untouched and activated. For most people, your website will continue to look as expected (the exception is explained below in section Do you need to change anything?).

If you are upgrading, and you wish to try the new skin Seasons, then activate it, but be sure to deactivate Standard. Otherwise, both will get generated, and they will compete with each other for placement in your HTML directory.

### Skin defaults

Version 3.9 introduces a new section, [StdReport]/[[Defaults]] in weewx.conf. Options in this section apply to all reports. For example, if you set a unit group here, it will be applied everywhere. This makes it easy to set the units across all reports, or to ensure that the labels for observations are the same in every report.

It also adds a file defaults.py, in which the fallback values for every report parameter are specified. Although the defaults file is currently useful only to developers, in the future it may be extended to facilitate translations and localization.

### Do you need to change anything?

The introduction of the new section, [StdReport]/[[Defaults]] in weewx.conf, can change which units are applied to reports because it has a higher precedence than what is in skin.conf. See the section How options work for details of the ordering in which an option is considered.

Most users will be unaffected by these changes because they depend on specific report overrides. There is, however, one exception:

If your installation does not use overrides, and you changed to metric units in your skin.conf file, you will be affected.

Your reports will start appearing in U.S. Customary units. The reason is that the new section, [StdReport]/[[Defaults]] has higher priority than options in skin.conf, and thus will start asserting themselves.

The fix is simple: modify the [StdReport]/[[Defaults]] to suit your preferences.

However, users who specified what unit system to use as part of the automated install using a package installer or setup.py, will have an override section, and therefore will be unaffected. This is because the override section has the highest priority.

## From V3.6 or earlier

### Changes to daily summaries

Perhaps the most significant change in V3.7 is a fix for how daily summary values are calculated and stored.

Daily summaries were introduced in V3.0 (December, 2014), to speed up certain kinds of aggregation calculations. They were designed to "weight" values depending on the time length of the archive record that contributed them. For example, shorter intervals contributed less than longer intervals. This was intended to enable changes to the length of the archive interval.

Unfortunately, a bug caused the weightings to all be one (1), regardless of what the actual archive interval length might be. This means all archive records, long and short, contribute the same amount, instead of being weighted by their length. So, if the archive interval were to change, averages would be calculated incorrectly.

This bug will only affect you if you have changed the length of your archive interval, or if you plan to. If you have not changed your archive interval length, and have no plans to do so, then there is nothing you need to do.

Your archive may have interval values of different sizes if...
... you have imported data using wee_import.
... your hardware has a data logger, your configuration uses record_generation=software, and the archive_interval is different from that in the hardware.
... your archive contains data from more than one type of hardware.

The wee_database utility, with option --update, can fix this problem by recalculating the weights in the daily summary, on the basis of the actual archive interval lengths. On a Raspberry Pi 1, model B, it takes about 10 minutes to fix a database with 10 years of data. On faster machines, it takes much less time.

    wee_database /etc/weewx/weewx.conf --update

If you have multiple databases, consider recalculating the weights in each database. Interval weighting will only need to be applied to databases that have daily summaries, i.e., the binding uses

    manager = weewx.wxmanager.WXDaySummaryManager

To apply interval weighting to a database other than the default wx_binding, use the --binding=BINDING_NAME option in conjunction with the --update action.

    wee_database /etc/weewx/weewx.conf --update --binding=cmon_binding

### Recalculation of windSpeed maximum values

Version 3.7 changes how maximum windSpeed is calculated for aggregations of a day or more. Previously, if option use_hilo was set to True (the usual case), maximum windSpeed for a day was set to the maximum value seen in the LOOP packets for the day. In practice this is the same value as windGust. That is, these two tags would supply the same value:

    $day.windSpeed.max
    $day.windGust.max

In Version 3.7, this has been changed so the maximum windSpeed is now set to the maximum archive value seen during the day — usually a slightly smaller number. However, older daily max values will still contain the max LOOP packet values. If you wish to update your older values and have them use the max archive record value, use the utility wee_database, with option --update.

### Changes to wee_database

The wee_database utility has been revised. Whilst the v3.6 functionality has been retained, a number of the wee_database actions have been renamed and new options have been added to support the weighting of daily summaries and the recalculation of portions of the windSpeed daily summary table. The rebuilding of the daily summaries (formerly backfilling the daily summaries) now supports selective rebuilding. Full details on the revised wee_database utility can be found in the wee_database section in the Utilities Guide.

### Change in the name and locations of examples

In earlier versions, examples were located with the WeeWX code base, and packaged as a Python module. This is categorically and semantically incorrect.

The examples now live in their own directory, whose location is dependent on the installation method. If you use an example, you should copy it to the user subdirectory, modify it if necessary, then use it there. Your copy will be retained across version upgrades.

3.6 | 3.7
    examples.alarm.MyAlarm
    examples.lowBattery.MyAlarm
    examples.xsearch.MyXSearch
    user.alarm.MyAlarm
    user.lowBattery.BatteryAlarm
    user.stats.MyStats

Finally, note that the name of one example has been changed:

3.6 | 3.7
    xsearch.py
    stats.py

### Changes to sensor mapping

The mapping of sensors to database fields was formalized in Version 3.7, resulting in changes to the configuration for some of the drivers, including cc3000, te923, wmr100, wmr200, wmr300, and wmr9x8.

For the wmr200 driver, until Version 3.6, the fields extraTemp1 and extraHumid1 were not usable. Version 3.6.1 shifted the extraTemp and extraHumid mappings down one channel, so that extraTemp1 corresponded to channel 2, extraTemp2 corresponded to channel 3, and so on. The mappings can now be modified by a change to the configuration file, and the default mappings are as follows:

3.6 | 3.7
    ** hard-coded in the driver **

    outTemp = temperature_1
    # extraTemp1 is not usable
    extraTemp2 = temperature_2
    extraTemp3 = temperature_3
    extraTemp4 = temperature_4
    extraTemp5 = temperature_5
    extraTemp6 = temperature_6
    extraTemp7 = temperature_7
    extraTemp8 = temperature_8
    outHumidity = humidity_1
    # extraHumid1 is not usable
    extraHumid2 = humidity_2
    extraHumid3 = humidity_3
    extraHumid4 = humidity_4
    extraHumid5 = humidity_5
    extraHumid6 = humidity_6
    extraHumid7 = humidity_7
    extraHumid8 = humidity_8
    [WMR200]
        [[sensor_map]]
            altimeter = altimeter
            pressure = pressure
            windSpeed = wind_speed
            windDir = wind_dir
            windGust = wind_gust
            windBatteryStatus = battery_status_wind
            inTemp = temperature_0
            outTemp = temperature_1
            extraTemp1 = temperature_2
            extraTemp2 = temperature_3
            extraTemp3 = temperature_4
            extraTemp4 = temperature_5
            extraTemp5 = temperature_6
            extraTemp6 = temperature_7
            extraTemp7 = temperature_8
            inHumidity = humidity_0
            outHumidity = humidity_1
            extraHumid1 = humidity_2
            extraHumid2 = humidity_3
            extraHumid3 = humidity_4
            extraHumid4 = humidity_5
            extraHumid5 = humidity_6
            extraHumid6 = humidity_7
            extraHumid7 = humidity_8
            outTempBatteryStatus = battery_status_out
            rain = rain
            rainTotal = rain_total
            rainRate = rain_rate
            hourRain = rain_hour
            rain24 = rain_24
            rainBatteryStatus = battery_status_rain
            UV = uv
            uvBatteryStatus = battery_status_uv
            windchill = windchill
            heatindex = heatindex
            forecastIcon = forecast_icon
            outTempFault = out_fault
            windFault = wind_fault
            uvFault = uv_fault
            rainFault = rain_fault
            clockUnsynchronized = clock_unsynchronized

For the te923 driver:

3.6 | 3.7
    [TE923]
        [[map]]
            link_wind = windLinkStatus
            bat_wind = windBatteryStatus
            link_rain = rainLinkStatus
            bat_rain = rainBatteryStatus
            link_uv = uvLinkStatus
            bat_uv = uvBatteryStatus
            uv = UV
            t_in = inTemp
            h_in = inHumidity
            t_1 = outTemp
            h_1 = outHumidity
            bat_1 = outBatteryStatus
            link_1 = outLinkStatus
            t_2 = extraTemp1
            h_2 = extraHumid1
            bat_2 = extraBatteryStatus1
            link_2 = extraLinkStatus1
            t_3 = extraTemp2
            h_3 = extraHumid3
            bat_3 = extraBatteryStatus2
            link_3 = extraLinkStatus2
            t_4 = extraTemp3
            h_4 = extraHumid3
            bat_4 = extraBatteryStatus3
            link_4 = extraLinkStatus3
            t_5 = extraTemp4
            h_5 = extraHumid4
            bat_5 = extraBatteryStatus4
            link_5 = extraLinkStatus4
    [TE923]
        [[sensor_map]]
            windLinkStatus = link_wind
            windBatteryStatus = bat_wind
            rainLinkStatus = link_rain
            rainBatteryStatus = bat_rain
            uvLinkStatus = link_uv
            uvBatteryStatus = bat_uv
            inTemp = t_in
            inHumidity = h_in
            outTemp = t_1
            outHumidity = h_1
            outTempBatteryStatus = bat_1
            outLinkStatus = link_1
            extraTemp1 = t_2
            extraHumid1 = h_2
            extraBatteryStatus1 = bat_2
            extraLinkStatus1 = link_2
            extraTemp2 = t_3
            extraHumid2 = h_3
            extraBatteryStatus2 = bat_3
            extraLinkStatus2 = link_3
            extraTemp3 = t_4
            extraHumid3 = h_4
            extraBatteryStatus3 = bat_4
            extraLinkStatus3 = link_4
            extraTemp4 = t_5
            extraHumid4 = h_5
            extraBatteryStatus4 = bat_5
            extraLinkStatus4 = link_5

## From V3.5 or earlier

### Changes to weewx.conf

In Version 3.6, the list of options that describe how derived variables are to be calculated have been moved to a new subsection called [[Calculations]]. The upgrade process will automatically make this change for you.

3.5 | 3.6
    [StdWXCalculate]
        pressure = prefer_hardware
        barometer = prefer_hardware
        altimeter = prefer_hardware
        windchill = prefer_hardware
        heatindex = prefer_hardware
        dewpoint = prefer_hardware
        inDewpoint = prefer_hardware
        rainRate = prefer_hardware
    [StdWXCalculate]
        [[Calculations]]
            pressure = prefer_hardware
            barometer = prefer_hardware
            altimeter = prefer_hardware
            windchill = prefer_hardware
            heatindex = prefer_hardware
            dewpoint = prefer_hardware
            inDewpoint = prefer_hardware
            rainRate = prefer_hardware

## From V3.1 or earlier

### New utilities

Version 3.2 includes new utilities to facilitate configuration.

3.2 | 3.1 and earlier |
wee_config |  | Change driver or other station parameters
wee_extension | setup.py or wee_setup | Install, list, and remove extensions
wee_database | wee_config_database | Manipulate the database
wee_device | wee_config_device | Get and set parameters on the hardware
wee_reports | wee_reports | Run reports

### Changes to weewx.conf

Release 3.2 introduces a new section [DatabaseTypes]. This section defines the default settings for each type of database. For example, the host, user, and password for MySQL databases can be specified once in the DatabaseTypes section instead of repeating in each Database section. The defaults in DatabaseTypes can be overridden in each Database section as needed.

3.1 | 3.2
    [DataBindings]
        [[wx_binding]]
            database = archive_sqlite
            manager = weewx.wxmanager.WXDaySummaryManager
            table_name = archive
            schema = schemas.wview.schema
    [Databases]
        [[archive_sqlite]]
            root = %(WEEWX_ROOT)s
            database = archive/weewx.sdb
            driver = weedb.sqlite
        [[archive_mysql]]
            host = localhost
            user = weewx
            password = weewx
            database = weewx
            driver = weedb.mysql
    [DataBindings]
        [[wx_binding]]
            database = archive_sqlite
            manager = weewx.wxmanager.WXDaySummaryManager
            table_name = archive
            schema = schemas.wview.schema
    [Databases]
        [[archive_sqlite]]
            database_name = weewx.sdb
            database_type = SQLite

        [[archive_mysql]]
            database_name = weewx
            database_type = MySQL

    [DatabaseTypes]
        [[SQLite]]
            driver = weedb.sqlite
            SQLITE_ROOT = %(WEEWX_ROOT)s/archive
        [[MySQL]]
            driver = weedb.mysql
            host = localhost
            user = weewx
            password = weewx

## From V2.7 or earlier

### Overview

While a lot has changed with Version 3, the upgrade process should take care of most changes for most users. However, if you have installed an extension or, especially, if you have written a custom service, search list extension, or uploader, you will have to make some changes.

### Database contents

With Version 3, there is no longer a separate "stats" database. Instead, "daily summaries" have been included in the same database as the archive data — everything is under one name. For example, if you are using sqlite, both the archive data and the daily summaries will be inside file weewx.sdb. With MySQL, everything is inside the database weewx. This makes it easier to keep all data together when working with multiple databases.

This change in database structure should be transparent to you. On startup, WeeWX will automatically backfill the new internal daily summaries from the archive data. Your old "stats" database will no longer be used and may safely set aside or even deleted.

### Pressure calibration

Since the new StdWXCalculate service is applied after the StdCalibrate services, the pressure_offset parameter is no longer necessary; pressure calibration can be applied just like any other calibration. If your pressure was calibrated using the pressure_offset parameter, move the calibration to the [StdCalibrate] section. This applies only to CC3000, FineOffsetUSB, Ultimeter, WS1, WS23xx, and WS28xx hardware.

### weewx.conf

A version 2.X weewx.conf file is not compatible with Version 3.X. However, the upgrade process should automatically update the file. Nevertheless, the changes are documented below:

2.7 | 3.0
    [StdReport]
        data_binding = wx_binding
    [StdArchive]
        archive_database = archive_sqlite
        stats_database = stats_sqlite
        archive_schema = user.schemas.defaultArchiveSchema
        stats_schema = user.schemas.defaultStatsSchema
    [StdArchive]
        data_binding = wx_binding
    [DataBindings]
        [[wx_binding]]
            database = archive_sqlite
            manager = weewx.wxmanager.WXDaySummaryManager
            table_name = archive
            schema = schemas.wview.schema
    [Databases]
        [[archive_sqlite]]
            root = %(WEEWX_ROOT)s
            database = archive/weewx.sdb
            driver = weedb.sqlite
        [[stats_sqlite]]
            root = %(WEEWX_ROOT)s
            database = archive/stats.sdb
            driver = weedb.sqlite
        [[archive_mysql]]
            host = localhost
            user = weewx
            password = weewx
            database = weewx
            driver = weedb.mysql
        [[stats_mysql]]
            host = localhost
            user = weewx
            password = weewx
            database = stats
            driver = weedb.mysql
    [Databases]
        [[archive_sqlite]]
            root = %(WEEWX_ROOT)s
            database_name = archive/weewx.sdb
            driver = weedb.sqlite

        [[archive_mysql]]
            host = localhost
            user = weewx
            password = weewx
            database_name = weewx
            driver = weedb.mysql
    [Engines]
        [[WxEngine]]
            prep_services = \
        weewx.wxengine.StdTimeSynch
            process_services = \
        weewx.wxengine.StdConvert, \
        weewx.wxengine.StdCalibrate, \
        weewx.wxengine.StdQC

            archive_services = \
        weewx.wxengine.StdArchive
            restful_services = \
        weewx.restx.StdStationRegistry, \
        weewx.restx.StdWunderground, \
        weewx.restx.StdPWSweather, \
        weewx.restx.StdCWOP, \
        weewx.restx.StdWOW, \
        weewx.restx.StdAWEKAS
            report_services = \
        weewx.wxengine.StdPrint, \
        weewx.wxengine.StdReport
    [Engine]
        [[Services]]
            prep_services = \
        weewx.engine.StdTimeSynch
            process_services = \
        weewx.engine.StdConvert, \
        weewx.engine.StdCalibrate, \
        weewx.engine.StdQC, \
        weewx.wxservices.StdWXCalculate
            archive_services = \
        weewx.engine.StdArchive
            restful_services = \
        weewx.restx.StdStationRegistry, \
        weewx.restx.StdWunderground, \
        weewx.restx.StdPWSweather, \
        weewx.restx.StdCWOP, \
        weewx.restx.StdWOW, \
        weewx.restx.StdAWEKAS
            report_services = \
        weewx.engine.StdPrint, \
        weewx.engine.StdReport

### Custom data sources in skins

The mechanism for specifying non-default data sources in skins has changed. If you modified the Standard skin, or created or used other skins that draw data from a database other than the weather database, you must change how the other sources are specified.

For example, in the cmon extension:

2.7 | 3.0
    [ImageGenerator]
        ...
        [[day_images]]
            ...
            [[[daycpu]]]
                archive_database = cmon_sqlite
                [[[cpu_user]]]
                [[[cpu_idle]]]
                [[[cpu_system]]]
    [ImageGenerator]
        ...
        [[day_images]]
            ...
            [[[daycpu]]]
                data_binding = cmon_binding
                [[[cpu_user]]]
                [[[cpu_idle]]]
                [[[cpu_system]]]

### Extensions

Many skins will work in v3 with no modification required. However, every search list extension will have to be upgraded, every restful extension must be upgraded, and some other services must be upgraded.

There is no automated upgrade system for extensions; if an extension must be upgraded, you must do it manually. If the extension has any python code, this will mean replacing any v2-compatible code with v3-compatible code. In some cases parts of the configuration file weewx.conf must be modified.

For example, to update the pmon extension, replace bin/user/pmon.py with the v3-compatible pmon.py and modify weewx.conf as shown in this table:

2.7 | 3.0
    [ProcessMonitor]
        database = pmon_sqlite
    [ProcessMonitor]
        data_binding = pmon_binding
    [DataBindings]
        [[pmon_binding]]
            database = pmon_sqlite
            manager = weewx.manager.DaySummaryManager
            table_name = archive
            schema = user.pmon.schema
    [Databases]
        [[pmon_sqlite]]
            root = %(WEEWX_ROOT)s
            database = archive/pmon.sdb
            driver = weedb.sqlite
    [Databases]
        [[pmon_sqlite]]
            root = %(WEEWX_ROOT)s
            database_name = archive/pmon.sdb
            driver = weedb.sqlite

For other extensions, see the extension's documentation or contact the author of the extension.

### Search list extensions

The introduction of data bindings has meant a change in the calling signature of search list extensions. By way of example, here's the example from the section Extending the list in the Customizing Guide, with the differences highlighted.

2.7 | 3.0
    def get_extension(self, timespan, archivedb, statsdb):

        all_stats = TimeSpanStats(
            timespan,
            statsdb,
            formatter=self.generator.formatter,
            converter=self.generator.converter)
        week_dt = datetime.date.fromtimestamp(timespan.stop) - \
                  datetime.timedelta(weeks=1)
        week_ts = time.mktime(week_dt.timetuple())
        seven_day_stats = TimeSpanStats(
            TimeSpan(week_ts, timespan.stop),
            statsdb,
            formatter=self.generator.formatter,
            converter=self.generator.converter)

        search_list_extension = {'alltime'   : all_stats,
                                 'seven_day' : seven_day_stats}

        return search_list_extension
    def get_extension_list(self, timespan, db_lookup):

        all_stats = TimespanBinder(
            timespan,
            db_lookup,
            formatter=self.generator.formatter,
            converter=self.generator.converter)
        week_dt = datetime.date.fromtimestamp(timespan.stop) - \
            datetime.timedelta(weeks=1)
        week_ts = time.mktime(week_dt.timetuple())
        seven_day_stats = TimespanBinder(
            TimeSpan(week_ts, timespan.stop),
            db_lookup,
            formatter=self.generator.formatter,
            converter=self.generator.converter)

        search_list_extension = {'alltime'   : all_stats,
                                 'seven_day' : seven_day_stats}

        return [search_list_extension]

A few things to note:

- The name of the extension function has changed from get_extension to get_extension_list.
- The calling signature has changed. Instead of an archive database and a stats database being passed in, a single database lookup function is passed in.
- The name of the top-level class in the tag chain has changed from TimeSpanStats to TimespanBinder. See the Customizing Guide for details.
- Instead of returning a single search list extension, the function should now return a Python list of extensions. The list will be searched in order.

### Derived quantities

Some calculations that were done in drivers or in hardware are now done consistently by the new StdWXCalculate service. Drivers should no longer calculate derived quantities such as windchill, heatindex, dewpoint, or rain rate.

### Driver APIs

The base class for drivers has been renamed, and new, optional, methods have been defined to provide hooks for configuring hardware and producing default and upgraded configuration stanzas.

These changes affect only those who have written custom drivers.

2.7 | 3.0
    import weewx.abstractstation

    class ACME960(weewx.abstractstation.AbstractStation):
        ...
    import weewx.drivers

    class ACME960(weewx.drivers.AbstractDevice):
        ...

### Service APIs

The base class for services has moved.

This affects only those who have written custom services.

2.7 | 3.0
    import weewx.wxengine

    class BetterMousetrapService(weewx.wxengine.StdService):
        ...
    import weewx.engine

    class BetterMousetrapService(weewx.engine.StdService):
        ...

### RESTful APIs

Some of the methods internal to RESTful services have changed, specifically those that relate to getting configuration options from weewx.conf and configuring databases.

This affects only those who have written custom RESTful services.

Here is an example of obtaining the database dictionary for use in the RESTful service thread.

2.7 | 3.0
    site_dict = weewx.restx.get_dict(config_dict, 'Uploader')
    db_name = config_dict['StdArchive']['archive_database']
    db_dict = config_dict['Databases'][db_name]
    site_dict.setdefault('database_dict', db_dict)
    site_dict = config_dict['StdRESTful']['Uploader']
    site_dict = accumulateLeaves(site_dict, max_level=1)
    manager_dict = weewx.manager.open_manager_with_config(
        config_dict, 'wx_binding')

### Database APIs

The methods for obtaining, opening, and querying databases have changed. This affects only those who have written code that accesses databases.

The class Manager and its subclasses have replaced the old Archive class. The table name is no longer hard-coded, so developers should use the table name from the database binding. There is no longer a separate StatsDb class, its functions having been subsumed into the Manager class and its subclasses.

A new class DBBinder is the preferred way of getting a Manager class, as it will automatically take care of instantiating the right class, as well as caching instances of Manager. An instance of DBBinder is held by the engine as attribute db_binder. Here's an example of making a simple query.

2.7 | 3.0
    db = config_dict['StdArchive']['archive_database']
    self.database_dict = config_dict['Databases'][db]
    with weewx.archive.Archive.open(self.database_dict) as archive:
        val = archive.getSql("SELECT AVG(windSpeed) FROM archive"
                             " WHERE dateTime>? AND dateTime<=?",
                             (start_ts, end_ts))
    with self.engine.db_binder.get_manager('wx_binding') as mgr:
        val = mgr.getSql("SELECT AVG(windSpeed) FROM %s"
                         " WHERE dateTime>? AND dateTime<=?" %
                         mgr.table_name, (start_ts, end_ts))

### Generator APIs

The base class for report generators has changed. The old class CachedReportGenerator no longer exists; its functionality has been replaced by an instance of DBBinder, held by the generator superclass. This affects only those who have written customer generators.

Here's an example:

2.7 | 3.0
    class GaugeGenerator(weewx.reportengine.CachedReportGenerator)
        def run(self):
            archive_name = self.config_dict['GaugeGenerator']['archive_name']
            archive = self._getArchive(archive_name)
            results = archive.getSql(...)
    class GaugeGenerator(weewx.reportengine.ReportGenerator)
        def run(self):
            mgr = self.generator.db_binder.get_manager()
            results = mgr.getSql(...)

### Extension installer

The setup.py utility is now included in the installation; it is no longer necessary to keep a copy of the WeeWX source tree just for the setup.py utility.

For .deb and .rpm installations, the command wee_setup is a symlink to setup.py.

The options for installing extensions changed slightly to be more consistent with the rest of the options to setup.py.

2.7 | 3.0
    setup.py --extension --install extensions/basic
    setup.py --extension --install basic.tar.gz
    setup.py --extension --uninstall basic
    setup.py --extension --list
    setup.py --extension --install basic.tar.gz --dryrun
    setup.py install --extension extensions/basic
    setup.py install --extension basic.tar.gz
    setup.py uninstall --extension basic
    setup.py list-extensions
    setup.py install --extension basic.tar.gz --dry-run

## From V2.6 or earlier

Version 2.7 is backwards compatible with earlier versions with one minor exception.

It now includes the ability to localize the WeeWX and server uptimes. Previously, the labels days, hours, and minutes were hardcoded in a Python utility. There was no way of changing them. Now, like any other labels, they are taken from the skin configuration file, skin.conf, section [[Labels]]. Older configuration files had a definition for hour, but none for day, and minute. Also, the old definition for hour used an abbreviation hrs instead of hours.

If you do nothing, your WeeWX and station uptimes will look like:

    Weewx uptime:  1 day, 1 hrs, 41 minutes
    Server uptime: 2 days, 10 hrs, 22 minutes

Note how the label for hours is abbreviated and always uses the plural. If you want the previous behavior, or if you want to localize the labels, you should update your skin configuration file. Remove the old entries for hour and second and replace them with:

    day               = " day",    " days"
    hour              = " hour",   " hours"
    minute            = " minute", " minutes"
    second            = " second", " seconds"

The first item is the singular spelling, the second the plural. This will result in the desired

    Weewx uptime:  1 day, 1 hour, 41 minutes
    Server uptime: 2 days, 10 hours, 22 minutes

## From V2.5 or earlier

Version 2.6 is backwards compatible with earlier versions, with a couple of small exceptions.

- If you have written a custom WeeWX service, the install routine will try to insert its name into an appropriate place in one of the five new lists of services to be run. You should check section [Engines][[WxEngine]] to make sure it made a reasonable guess.
- If you have written a custom RESTful service, the architecture for these services has completely changed. They are now first class services, and are treated like any other WeeWX service. There are some guides to writing RESTful services using the new architecture at the top of the file bin/weewx/restx.py. I can also help you with the transition.
- Option interval in the CWOP configuration section has become option post_interval. This change should be done automatically by the install routine.
- The mechanism for specifying RESTful services has changed. To activate a RESTful service, put the driver in the restful_services list in [Engines][[WxEngine]]. The driver parameter is no longer necessary in the RESTful service's configuration stanza. These changes should be done automatically by the install routine.

## From V2.3 or earlier

The option time_length will now be the exact length of the resultant plot. Before, a plot with time_length equal to 24 hours would result in a plot of 27 hours, now it's 24 hours. If you want the old behavior, set it equal to 27 hours. To do this, change your section in skin.conf from

    [[day_images]]
        x_label_format = %H:%M
        bottom_label_format = %m/%d/%y %H:%M
        time_length = 86400 # == 24 hours

to

    [[day_images]]
        x_label_format = %H:%M
        bottom_label_format = %m/%d/%y %H:%M
        time_length = 97200 # == 27 hours

The service StdTimeSync now synchronizes the console's onboard clock on startup. This is nice because if the clock failed, perhaps because the battery was taken out, the time is corrected first before data is downloaded from the logger's memory. To take advantage of this, you can move service StdTimeSync to the front of the list of services to be run. For example:

    [[WxEngine]]
        # The list of services the main weewx engine should run:
        service_list = weewx.wxengine.StdTimeSynch, weewx.wxengine.StdConvert,
        weewx.wxengine.StdCalibrate, weewx.wxengine.StdQC, weewx.wxengine.StdArchive, weewx.wxengine.StdPrint,
        weewx.wxengine.StdRESTful, weewx.wxengine.StdReport

## From V2.2 or earlier

The signature of the function "loader", used to return an instance of the station device driver, has changed slightly. It has changed from

    loader(config_dict)

to

    loader(config_dict, engine)

That is, a second parameter, engine, has been added. This is a reference to the WeeWX engine.

This change will affect only those who have written their own device driver.

## From V2.1 or earlier

Version 2.2 introduces a schema, found in bin/user/schemas.py, for the stats database. This schema is used only when initially creating the database. If you have a specialized stats database, that is, one that saves types other than the default that comes with WeeWX, you should edit this file to reflect your changes before attempting to rebuild the database.

## From V1.14 or earlier

Version 2.0 introduces many new features, including a revamped internal engine. There are two changes that are not backwards compatible:

- The configuration file, weewx.conf. When upgrading from V1.X, the setup utility will install a new, fresh copy of weewx.conf, which you will then have to edit by hand. Thereafter, V2.X upgrades should be automatic.
- Custom services. If you have written a custom service, it will have to be updated to use the new engine. The overall architecture is very similar, except that functions must be bound to events, rather than get called implicitly. See the sections Customizing a Service and Adding a Service in the Customizing Guide for details on how to do this.

All skins should be completely backwards compatible, so you should not have to change your templates or skin configuration file, skin.conf.

If you have written a custom report generator it should also be backwards compatible.

## From V1.13 or earlier

Version 1.14 introduces some new webpages that have been expressly formatted for the smartphone by using jQuery.

The skins shipped with the distribution take advantage of these features. If you do nothing, your old skins will continue to work, but you will not be taking advantage of these new webpages.

If you want them, then you have two choices:

1. Rename your old skin directory (call it "skins.old") then do the install. This will install the new skin distribution. You can then modify it to reflect any changes you have made, referring to skins.old for guidance. If you have not changed many things, this approach will be the easiest.
2. Alternatively, change the contents of your existing skin directory to include the new webpages. If you take this approach, you will need to copy over the contents of the subdirectory skins/Standard/smartphone from the distribution into your skins/Standard directory. You will then need to modify your skin.conf.

   After the section that looks like

       [[[Mobile]]]
           template = mobile.html.tmpl

   add the following directives:

       [[[MobileSmartphone]]]
           template = smartphone/index.html.tmpl
       [[[MobileTempOutside]]]
           template = smartphone/temp_outside.html.tmpl
       [[[MobileRain]]]
           template = smartphone/rain.html.tmpl
       [[[MobileBarometer]]]
           template = smartphone/barometer.html.tmpl
       [[[MobileWind]]]
           template = smartphone/wind.html.tmpl
       [[[MobileRadar]]]
           template = smartphone/radar.html.tmpl

   Then modify section [CopyGenerator] to add the highlighted files:

       [CopyGenerator]
           #
           # This section is used by the generator CopyGenerator
           #

           # List of files that are to be copied at the first invocation of the generator only
           copy_once = backgrounds/*, weewx.css, mobile.css, favicon.ico, smartphone/icons/*, smartphone/custom.js

Whichever approach you chose, the generated files will appear in public_html/smartphone. The start of the document root will be at public_html/smartphone/index.html. You may want to add a link to this in the template for your main index page skins/Standard/index.html.tmpl.

## From V1.12 or earlier

Version 1.13 changed the way binding happens to the databases used in reports so that it happens much later. The upshot is that the signature of a few functions changed. Most you are unlikely to encounter. The exception is if you have written custom template search lists, as described in the Customizing weewx guide. This section has been updated to reflect the new function signatures. As a side effect, the illustrated example actually has become much simpler!

No changes to skins.

## From V1.9 or earlier

Version 1.10 introduced several new features.

### New almanac features, icon, and mobile template

Version 1.10 introduces some extra almanac features, such as the azimuth and elevation of the sun and moon, or when the next solstice will be. It also includes a template formatted for smartphones, as well as an icon ("favicon.ico") that displays in your browser toolbar. The skins shipped with the distribution take advantage of these features. If you do nothing, your old skins will continue to work, but you will not take advantage of these new features.

If you want these new features then you have two choices:

1. Rename your old skin directory (call it "skin.old") then do the install. This will install the new skin distribution. You can modify it to reflect any changes you have made, referring to skin.old for guidance.
2. Alternatively, change the contents of your existing skin directory to take advantage of the new features. If you take this approach, you will need to copy over files favicon.ico, mobile.css, and mobile.html.tmpl from the distribution into your skin/Standard directory. Modify skins/Standard/index.html.tmpl to take advantage of the new almanac features, using the version shipped with the distribution for guidance. You will then need to modify your skin.conf.

   Add a new [[[Mobile]]] section:

       [FileGenerator]
           ...
           [[ToDate]]
               ...
           [[[Mobile]]]
               template = mobile.html.tmpl

   Then add mobile.css and favicon.ico to the list of files to be copied on report generation:

       [CopyGenerator]
           copy_once = backgrounds/*, weewx.css, mobile.css, favicon.ico

Which approach you should take will depend on how extensively you have modified the stock skin distribution. If the modifications are slight, approach #1 will be easier, otherwise use approach #2.

### Backwards compatibility

With the introduction of explicit control of output units in the templates such as

    $day.outTemp.max.degree_C

the calling signature of the following two Python classes was changed

- weewx.stats.TaggedStats
- weewx.stats.TimeSpanStats

The example of writing a custom generator MyFileGenerator (which produced "all time" statistics) has been changed to reflect the new signatures.

This will only affect you if you have written a custom generator.

## From V1.7.0 or earlier

With the introduction of a standard archiving service, StdArchive, the names of some events have changed. This will not affect you unless you have written a custom service.

## From V.1.5.0 or earlier

V1.7 introduces skins. The skins live in subdirectory skins. They are not compatible with the old template subdirectory --- you can't simply rename templates to skins.

The part of the configuration file dealing with the presentation layer has been split off into a separate file skin.conf. Hence, once again, the installation script setup.py will NOT merge your old weewx.conf configuration file into the new one. You will have to re-edit weewx.conf to put in your customizations. You may also have to edit skin.conf for whatever skin you choose (right now, only one skin, Standard, comes with the distribution).

However, a reinstall of V1.7 will merge your changes for weewx.conf. It will also merge any changes you have made to skin.conf as well.

Please check the following:

- Option "altitude" in section [Station] now takes a unit. Hence, it should look something like:

      altitude = 120, meter

- In a similar manner, options heating_base and cooling_base in skin.conf also take units:

      heating_base = 65, degree_F
      cooling_base = 65, degree_F

The directory 'templates' is no longer used; it has been replaced with directory 'skins'. You may delete it if you wish:

    rm -r templates

## From V1.4.0 or earlier

Because the configuration file weewx.conf changed significantly going from V1.4 to V1.5, the installation script setup.py will NOT merge your old configuration file into the new one. You will have to re-edit weewx.conf to put in your customizations.

## From V1.2.0 or earlier

Option clock_check, previously found in the [VantagePro] section, is now found in the [Station] section. The install program will put a default value in the new place, but it will not delete nor move your old value over. If you have changed this value or if you cannot stand the thought of clock_check appearing in two different places, you should delete the old one found under [VantagePro] and make sure the new value, found under [Station] is correct.

Two Python files are no longer used, so they may be deleted from your installation if you wish:

    rm bin/weewx/processdata.py
    rm bin/weewx/mainloop.py

In addition, file readme.htm has been moved to subdirectory docs, so the old one can be deleted:

    rm readme.htm