Adding a DWD product
Each DWD product is one coordinator subclass in products.py. Adding one
touches a handful of places, in this order.
Checklist
- Subclass a base in
products.py:WholeFileProductfor one file per release, decoded whole (HymecNG, RADOLAN);RadvorProductfor a RADVOR tar archive (RS, RV);BaseProductUpdateCoordinatoritself only if neither fits.
- Set the class constants:
PRODUCT_KEY,PRODUCT_LABEL,RELEASE_INTERVAL,RELEASE_DELAY,RELEASE_OFFSETandOVERDUE_GRACE(spelled out even when it isDEFAULT_OVERDUE_GRACE; a test enforces it),COVERAGE_KEYS(the sub-keys that areNonewithout data for the cell; a test checks every product has them), andMAX_FAST_POLL_INTERVALif the default does not fit. See below. - Add the URL pattern to
radar/urls.py;_get_urlderives the URL fromPRODUCT_KEY.- A
WholeFileProductimplements the blocking_parse(content, ts); the base downloads the file and runs it in the executor. - A
RadvorProductimplements_fetch_and_parse. - Keep
_fetch_and_parsefree of side effects; anything else goes in_async_on_new_release.
- A
- The grid comes from each file's
/wheregroup (radar/grid.py), so a product on another polar-stereographic grid needs nothing more; one in another projection needs that projection ingrid.py. - Add sensor descriptions in
sensor.py(a new*_SENSORStuple). - Register the class in the
PRODUCT_CLASSEStuple of__init__.py. - Register the sensors in
async_setup_entryofsensor.py, and add eachtranslation_key's name totranslations/en.jsonandtranslations/de.json. The two files must keep identical keys; a test checks it. - Add it to
PRODUCTSinscripts/check_release_delay.py, so itsRELEASE_DELAYis checked against what DWD actually does. - Document it: an entity page in
website/docs/entities/and its German translation, and the tables in the introduction, the entity overview and Release timing.
Picking the release constants
RELEASE_INTERVALandRELEASE_OFFSETdescribe the nominal times: every 5 minutes at :00, :05, … is an interval of 5 minutes and no offset; hourly at :50 is an interval of 1 hour and an offset of 50 minutes.RELEASE_DELAYis how long after its nominal time a file is on Open Data. Measure it from theLast-Modifiedheaders of recent files (that is whatscripts/check_release_delay.pydoes) and take a value at or above the mean: fetching before DWD publishes costs a failed request and a retry every time.OVERDUE_GRACEis how long DWD is given to publish an overdue release before the sensors go stale. It must not be a whole multiple ofRELEASE_INTERVAL, or the deadline coincides with a fetch; a test enforces that per product.USE_LOCAL_TIMEis for a product whose nominal times are on local time, like the dailysf_2350.
Naming the entities
Follow the naming rules in CLAUDE.md and
ADR 0001: a window in
the name only when it is part of the value, last / next / calendar
periods, units that follow the product. Never give a new entity an id a
released version gave another one; tests/entity_ids.py records them.