Saturday, December 21, 2024

A Wee Bit of Weather

So a while back I got a hand-me-down weather station from Tyler.

It's been dutifully recording the temperature, observing the lack of wind, and overcounting the rainfall for a few years up here now. But it was also never really great.

There was a fan inside it that buzzed and rattled, the rain gauge, as it turned out, was 150% inaccurate, and finally the straw that broke the camel's back was when the temperature sensor started reporting completely absurd readings. It was time to fix it.

And by fix it I mean replace it.

This cheerful little box arrived at my door straight from China, via a quick detour through the House of Bezos. It does the usual temperature, humidity, wind and rain sensing, as well as measuring total insolation and also UV, which is pretty keen.

It comes with all the bits and bobs needed to set it up, except of course for the pole to stick it onto. Luckily I had a scrap of redwood kicking around that I could use.

It's technically supposed to be round but whatever, square will do fine too.

Back up on the roof I clamped it temporarily to the piece of cedar fence board that I had used to mount the old weather station. Conveniently it's aligned north-south, so I didn't have to worry about rotating the weather station on the square pole to get the wind direction readings to be correct.

And a few screws will hold it in place just fine.

And you know, while I'm up here I should probably fix this section of gutter.

Every time the downspout gets plugged, this section collapses and I get a waterfall pouring off the roof, thanks to this hanger here being shittily installed.

Not only is it way at the end, leaving a huge gap to the next hanger, but it's also bent out of the way and not actually catching the lip of the gutter at all.

But thankfully both those problems have a solution.

Anyway, where was I? Oh yes, the weather station.

Getting the display hooked up and running was pretty straightforward. A touch screen might have been nice, but the buttons along the bottom worked well enough.

But only having the weather report in this one specific spot isn't especially convenient, when I might be yards away from it. I clearly needed to take advantage of the wifi features to upload the weather data into my own little local cloud.

To collect and process the data, I decided to use WeeWX in a Docker container, using this project.

First things first, I'd need a user for the container to run under, because running containers as root is so 2023. Thankfully this is as simple as running adduser --system weewx. Of course I'd need to make sure to add the appropriate entries to /etc/subuid and /etc/subgid so that the container could allocate UIDs and GIDs inside its namespace.

Then I needed a Docker compose file which specified the correct image to use, along with opening a port for the base station to send its readings to:

name: "weewx"


volumes:

  data:


services:

  weewx:

    image: felddy/weewx:release-5.0.2

    # devices:

    #   - "/dev/ttyUSB0:/dev/ttyUSB0"

    volumes:

      - type: bind

        source: ./data

        target: /data

    ports:

      - "8383:8383/tcp"

    environment:

      - TZ=PST8PDT

I prepared a directory at /var/local/weewx to hold this container's files, adding a data subdirectory, and set that as the home directory for the user. About the only special step I needed to take at this point was making sure that the data subdirectory was temporarily world-writeable until I figured out what UID and GID the container user would get assigned, after which I removed the world-write permission and chowned the directory.

Running the container for the first time is what populates the directory, and doing so is as simple as calling sudo -u weewx podman compose run weewx as root.

I next needed to install the WeeWX Interceptor plugin, which is what would actually be listening for the weather data being sent by the base station. With the WeeWX 5.1 container this is one simple line, just sudo -u weewx podman compose run --rm weewx extension install --yes https://github.com/matthewwall/weewx-interceptor/archive/master.zip. Then I followed that up with sudo -u weewx podman compose run --rm weewx station reconfigure --driver=user.interceptor --no-prompt to update the configuration file.

After a bit of tweaking, the file now had a section like this:

[Interceptor]

    # This section is for the network traffic interceptor driver.

    

    # The driver to use:

    driver = user.interceptor

    

    # Specify the hardware device to capture. Options include:

    #   acurite-bridge - acurite internet bridge, smarthub, or access

    #   observer - fine offset WH2600/HP1000/HP1003, ambient WS2902

    #   lw30x - oregon scientific LW301/LW302

    #   lacrosse-bridge - lacrosse GW1000U/C84612 internet bridge

    #   ecowitt-client - any hardware that uses the ecowitt protocol

    #   wu-client - any hardware that uses the weather underground protocol

    device_type = observer

    port = 8383

And of course in the Station section the type was set via the line station_type = Interceptor.

To start the container for real this time, we use sudo -u weewx podman compose up --detach. However, we're not done yet, as there's still some configuration to do on the base station.

Now obviously some of these values will depend on your network set up, but the values you'll need to substitute should be fairly obvious. Here's what mine looks like:

One important thing to pay attention to here is the Path line. By default it's set to /data/report/ and the WeeWX interceptor largely ignores it, only looking for the query portion of the URL after the question mark. Except that the HTTP request it actually assembles looks like this: GET /data/report/&PASSKEY=DA76...

There's two things wrong with this. First, there's no question mark before the query parameters, which trips up the interceptor plugin. It tries to parse the URL by grabbing everything after the question mark, so having it missing means that nothing is grabbed. Second, the parameters start with an ampersand, meaning that there's effectively an empty parameter at the start of the string, which also confuses the interceptor plugin.

Thankfully since we can modify the path, we can splice in a value that will fix both of these issues, changing it to /data/report/?ID=id. The ID=id part is arbitrary, I just chose it because the interceptor plugin is coded specifically to ignore that parameter (amongst a few others). It just needs to be there so that the query string doesn't start with ?&.

And with all that done, I finally have the weather station reporting correctly into WeeWX, and all that's left to do is to write a systemd script to make the container start on boot, and then tweak the configuration for WeeWX to fix the units to be more metric.

It was quite an adventure, but it worked out in the end.