# Customization Guide This document covers the customization of WeeWX. It assumes that you have read, and are reasonably familiar with, the [_Users Guide_](../../usersguide/introduction). The introduction contains an overview of the architecture. If you are only interested in customizing the generated reports you can probably skip the introduction and proceed directly to the section [_Customizing reports_](../custom-reports). With this approach you can easily add new plot images, change the titles of images, change the units used in the reports, and so on. However, if your goal is a specialized application, such as adding alarms, RSS feeds, _etc._, then it would be worth your while to read about the internal architecture. Most of the guide applies to any hardware, but the exact data types are hardware-specific. See the [_WeeWX Hardware Guide_](../../hardware/drivers) for details of how different observation types are handled by different types hardware. !!! Warning WeeWX is still an experimental system and, as such, its internal design is subject to change. Future upgrades may break any customizations you have done, particularly if they involve the API (skin customizations tend to be more stable). ## Overall system architecture Below is a brief overview of the WeeWX system architecture, which is covered in much more detail in the rest of this document. |  | |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| | A typical WeeWX pipeline. The actual pipeline depends on what extensions are in use. Data, in the form of LOOP packets and archive records, flows from top to bottom. | * A WeeWX process normally handles the monitoring of one station — _e.g._ a weather station. The process is configured using options in a configuration file, typically called `weewx.conf`. * A WeeWX process has at most one "driver" to communicate with the station hardware and receive "high resolution" (_i.e._ every few seconds) measurement data in the form of LOOP packets. The driver is single-threaded and blocking, so no more than one driver can run in a WeeWX process. * LOOP packets may contain arbitrary data from the station/driver in the form of a Python dictionary. Each LOOP packet must contain a time stamp and a unit system, in addition to any number of observations, such as temperature or humidity. For extensive types, such as rain, the packet contains the total amount of rain that fell during the observation period. * WeeWX then compiles these LOOP packets into regularly spaced "archive records". For most types, the archive record contains the average value seen in all of the LOOP packets over the archive interval (typically 5 minutes). For extensive types, such as rain, it is the sum of all values over the archive interval. * Internally, the WeeWX engine uses a _pipeline_ architecture, consisting of many _services_. Services bind to events of interest, such as new LOOP packets, or new archive records. Events are then run down the pipeline in order — services at the top of the pipeline act on the data before services farther down the pipe. * Services can do things such as check the data quality, apply corrections, or save data to a database. Users can easily add new services. * WeeWX includes an ability to customize behavior by installing _extensions_. Extensions may consist of one or more drivers, services, and/or skins, all in an easy-to-install package. ## Data architecture WeeWX is data-driven. When the sensors spit out some data, WeeWX does something. The "something" might be to print out the data, or to generate an HTML report, or to use FTP to copy a report to a web server, or to perform some calculations using the data. A driver is Python code that communicates with the hardware. The driver reads data from a serial port or a device on the USB or a network interface. It handles any decoding of raw bits and bytes, and puts the resulting data into LOOP packets. The drivers for some kinds of hardware (most notably, Davis Vantage) are capable of emitting archive records as well. In addition to the primary observation types such as temperature, humidity, or solar radiation, there are also many useful dependent types, such as wind chill, heat index, or ET, which are calculated from the primary data. The firmware in some weather stations are capable of doing many of these calculations on their own. For the rest, should you choose to do so, the WeeWX service [StdWXCalculate](../../reference/weewx-options/stdwxcalculate) can fill in the gaps. Sometimes the firmware simply does it wrong, and you may choose to have WeeWX do the calculation, despite the type's presence in LOOP packets. ## LOOP packets _vs._ archive records Generally, there are two types of data that flow through WeeWX: LOOP packets, and archive records. Both are represented as Python dictionaries. ### LOOP packets LOOP packets are the raw data generated by the device driver. They get their name from the Davis Instruments documentation. For some devices they are generated at rigid intervals, such as every 2 seconds for the Davis Vantage series, for others, irregularly, every 20 or 30 seconds or so. LOOP packets may or may not contain all the data types an instrument is capable of measuring. For example, a packet may contain only temperature data, another only barometric data, _etc_. These kinds of packet are called _partial record packets_. By contrast, other types of hardware (notably the Vantage series) include every data type in every LOOP packet. In summary, LOOP packets can be highly irregular in time and in what they contain, but they come in frequently. ### Archive records By contrast, archive records are highly regular. They are generated at regular intervals (typically every 5 to 30 minutes), and all contain the same data types. They represent an _aggregation_ of the LOOP packets over the archive interval. The exact kind of aggregation depends on the data type. For example, for temperature, it's generally the average temperature over the interval. For rain, it's the sum of rain over the interval. For battery status it's the last value in the interval. Some hardware is capable of generating their own archive records (the Davis Vantage and Oregon Scientific WMR200, for example), but for hardware that cannot, WeeWX generates them. It is the archive data that is put in the SQL database, although, occasionally, the LOOP packets can be useful (such as for the Weather Underground's "Rapidfire" mode). ## What to customize For configuration changes, such as which skins to use, or enabling posts to the Weather Underground, simply modify the WeeWX configuration file, nominally `weewx.conf`. Any changes you make will be preserved during an upgrade. Customization of reports may require changes to a skin configuration file `skin.conf` or template files ending in `.tmpl` or `.inc`. Anything in the `skins` subdirectory is also preserved across upgrades. You may choose to install one of the many [third-party extensions](https://github.com/weewx/weewx/wiki#extensions-to-weewx) that are available for WeeWX. These are typically installed in either the skins or user subdirectories, both of which are preserved across upgrades. More advanced customizations may require new Python code or modifications of example code. These should be placed in the `user` directory, where they will be preserved across upgrades. For example, if you wish to modify one of the examples that comes with WeeWX, copy it from the examples directory to the user directory, then modify it there. This way, your modifications will not be touched if you upgrade. For code that must run before anything else in WeeWX runs (for example, to set up an environment), put it in the file `extensions.py` in the user directory. It is always run before the WeeWX engine starts up. Because it is in the `user` subdirectory, it is preserved between upgrades. ## Do I need to restart WeeWX? If you make a change in `weewx.conf`, you will need to restart `weewxd`. If you modify Python code in the `user` directory or elsewhere, you will need to restart `weewxd`. If you install an extension, you will need to restart `weewxd`. If you make a change to a template or to a `skin.conf` file, then you do not need to restart `weewxd`. The change will be adopted at the next reporting cycle, typically at the end of an archive interval. ## The utility `wee_reports` If you make changes, how do you know what the results will look like? You could just run `weewxd` and wait until the next reporting cycle kicks off but, depending on your archive interval, that could be a 30-minute wait or more. The utility `wee_reports` allows you to run a report whenever you like. To use it, just run it from a command line, with the location of your configuration file `weewx.conf` as the first argument. Optionally, you can tell it what to use as the "Current" time, using either option `--epoch`, or some combination of `--date` and `--time`. For more information about `wee_reports`, see the [Utilities Guide](../../utilities/wee_reports) ## The WeeWX service architecture At a high-level, WeeWX consists of an engine class called `StdEngine`. It is responsible for loading _services_, then arranging for them to be called when key events occur, such as the arrival of LOOP or archive data. The default install of WeeWX includes the following services:
| Service | Function |
| weewx.engine.StdTimeSynch | Arrange to have the clock on the station synchronized at regular intervals. |
| weewx.engine.StdConvert | Converts the units of the input to a target unit system (such as US or Metric). |
| weewx.engine.StdCalibrate | Adjust new LOOP and archive packets using calibration expressions. |
| weewx.engine.StdQC | Check quality of incoming data, making sure values fall within a specified range. |
| weewx.wxservices.StdWXCalculate | Decide which derived observation types need to be calculated. |
| weewx.wxxtypes.StdWXXTypes weewx.wxxtypes.StdPressureCooker weewx.wxxtypes.StdRainRater weewx.wxxtypes.StdDelta |
Calculate derived variables, such as ET, dewpoint, or rainRate. |
| weewx.engine.StdArchive | Archive any new data to the SQL databases. |
| weewx.restx.StdStationRegistry weewx.restx.StdWunderground weewx.restx.StdPWSweather weewx.restx.StdCWOP weewx.restx.StdWOW weewx.restx.StdAWEKAS |
Various RESTful services (simple stateless client-server protocols), such as the Weather Underground, CWOP, etc. Each launches its own, independent thread, which manages the post. |
| weewx.engine.StdPrint | Print out new LOOP and archive packets on the console. |
| weewx.engine.StdReport | Launch a new thread to do report processing after a new archive record arrives. Reports do things such as generate HTML or CSV files, generate images, or transfer files using FTP/rsync. |
| Report | Default functionality |
| SeasonsReport | Introduced with WeeWX V3.9, this report generates a single HTML file with day, week, month and year "to-date" summaries, as well as the plot images to go along with them. Buttons select which time scale the user wants. It also generates HTML files with more details on celestial bodies and statistics. Also generates NOAA monthly and yearly summaries. |
| SmartphoneReport | A simple report that generates an HTML file, which allows "drill down" to show more detail about observations. Suitable for smaller devices, such as smartphones. |
| MobileReport | A super simple HTML file that just shows the basics. Suitable for low-powere d or bandwidth-constrained devices. |
| StandardReport | This is an older report that has been used for many years in WeeWX. It generates day, week, month and year "to-date" summaries in HTML, as well as the plot images to go along with them. Also generates NOAA monthly and yearly summaries. It typically loads faster than the SeasonsReport. |
| FTP | Transfer everything in the HTML_ROOT directory to a remote server using ftp. |
| RSYNC | Transfer everything in the HTML_ROOT directory to a remote server using the utility rsync. |
| Generator | Function |
| weewx.cheetahgenerator.CheetahGenerator | Generates files from templates, using the Cheetah template engine. Used to generate HTML and text files. |
| weewx.imagegenerator.ImageGenerator | Generates graph plots. |
| weewx.reportengine.FtpGenerator | Uploads data to a remote server using FTP. |
| weewx.reportengine.RsyncGenerator | Uploads data to a remote server using rsync. |
| weewx.reportengine.CopyGenerator | Copies files locally. |
| dateTime | usUnits | interval | barometer | pressure | altimeter | inTemp | outTemp | ... |
| 1413937800 | 1 | 5 | 29.938 | null | null | 71.2 | 56.0 | ... |
| 1413938100 | 1 | 5 | 29.941 | null | null | 71.2 | 55.9 | ... |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| Name | Meaning |
| dateTime | The time at the end of the archive interval in unix epoch time. This is the primary key in the database. It must be unique, and it cannot be null. |
| usUnits | The unit system the record is in. It cannot be null. See the Units for how these systems are encoded. |
| interval | The length of the archive interval in minutes. It cannot be null. |