A helper for setting up weather stations

Find out what your weather station is actually sending.

The server prepares a temporary subdomain under test-station.schizza.cz which you set as the upload target in your weather station for the next 30 minutes. Every request the station sends is captured – you see method, path, port, SSL/non-SSL route, the detected protocol (PWS/WU vs. WSLink) and the full payload. Nothing is written to disk – the data disappears as soon as the session expires.

Detailed guide ↓
What to enter into the weather station
In the station's custom upload settings (Custom Server / Customized Server)
fill in these fields. Replace values in <> with what you get
after clicking the button above.

  Server / Hostname:   <code>.test-station.schizza.cz
  Port:                80 (HTTP)  or  443 (HTTPS)
  Path:                keep the station's default
  Station ID, Password: anything – the server does not check them
  Interval:            the shortest available, so you see results quickly

Tip: try HTTP (port 80) first. If your station only sends over HTTPS,
the server will detect that and recommend the WSLink SSL proxy.
Your new test address

    
How the whole thing works

Three simple steps:

  1. Click the “Generate test address” button. The server will prepare a unique subdomain valid for 30 minutes – the actual address appears right after generation in the “Your new test address” box.
  2. In your weather station's settings (typically under “Custom Server”, “Weather Services” or “Customized”), enter that address as the upload target and save. A concrete field example is in the “What to enter into the weather station” card above.
  3. Open the “Results” link and wait for the first data (usually within one upload interval). The server will show what the station is really sending, which protocol it uses (PWS/WU vs. WSLink) and recommend the matching Home Assistant integration settings.
README and documentation
Show README

Test Station Server

A standalone lightweight web server for diagnosing requests from weather stations.

Rust-based, all-in-one web server.

Features

  • estimates which protocol the station is using: WSLink vs PWS/WU
  • distinguishes SSL and non-SSL routes based on proxy headers
  • temporarily stores query string, form body, relevant headers, and raw payload
  • keeps each session for 5 minutes and then destroys it
  • stores no cookies and writes no data to disk; all statistics are kept only in temporary memory and discarded after 5 minutes

Run

cd tools/test-station-server
cargo run

Docker Compose

cd tools/test-station-server
docker compose up --build -d

The service listens on port 8099 by default.

Optional environment variables:

TEST_STATION_BIND=0.0.0.0:8099
TEST_STATION_BASE_DOMAIN=test-station.schizza.cz
TEST_STATION_SESSION_TTL_SECS=300
TEST_STATION_MAX_BODY_BYTES=65536

Proxy Behind Traefik

The server does not handle TLS termination by itself. It assumes TLS is handled by Traefik or another reverse proxy, which forwards information about the original route in upstream headers.

The server reads these headers:

  • X-Forwarded-Proto
  • X-Forwarded-Port
  • X-Forwarded-Host
  • X-Forwarded-For
  • Forwarded
  • optionally X-Test-Station-Route-Security: ssl|non-ssl

X-Forwarded-Proto is usually enough. If you want to explicitly distinguish two Traefik routes, add a custom middleware that sets X-Test-Station-Route-Security.

An example dynamic configuration is available in examples/traefik-dynamic.yml.

Note for Traefik v3:

  • use HostRegexp(\[a-z0-9]+.test-station.your-domain.tld`)` for wildcard subdomains
  • the older syntax HostRegexp(\{code:[a-z0-9]+}.test-station.your-domain.tld`)` is tied to v2 syntax and in v3 often results in the router not matching the request at all
  • if the base domain opens but the subdomain returns 404 page not found, the problem is usually the HostRegexp match or a missing wildcard DNS record

Routing Model

  • GET / on the base domain shows the session generator
  • POST /api/sessions creates a new session
  • results are available only on the base domain via /results/<code>
  • session JSON is available only on the base domain via /api/sessions/<code>
  • requests sent to the session subdomain are stored as captured events

Notes

  • sessions are purely in-memory; they disappear after restart and expire after 5 minutes
  • after TTL expires, the data is deleted and the subdomain stops being valid
  • the PWS/WU vs WSLink heuristic is intentionally simple and mainly relies on known parameters such as ID/PASSWORD or wsid/wspw