USB Weather Station & Weewx using Docker
Summary
Use of a Low cost WH1080 USB Weather station, connected by USB to an intel NUC running docker (x86). The NUC is running Debian Buster as a base OS.
Weewx pushes data to a local MQTT server (on the same NUC) and also uses SFTP to push graphs and displays to my commercial webserver. At some stage I’ll get it to push data to wunderground.com also which I have found useful previously.
Current Weather Station Hardware
Current weather station model WH1080 (WA-1091-1, and it shows up in weewx as a WH2080)
https://www.aliexpress.com/item/801879857.html approx $200 incl shipping.
It was bought to replace my previous weather station model, a WH3081) The previous model tended to lock up regularly on the USB port, requiring it to be rebooted. This link shows some tips for the previous model: https://www.taverner-rich.com/fine-offset-wh3081-tips-tricks/ . Previously I was using a small Orange Pi zero to create a similar solution, but with the USB issues and a couple of SD card fails, I was looking for a more robust solution with less hardware. Oh, and any excuse to use docker.
Docker image
This was the image chosen, based on how recently it had been updated and how popular it was. It also had the MQTT plugin already which I needed.
https://hub.docker.com/r/felddy/weewx
It appears that this docker setup was not intended to produce any html/graphs directly but just use MQTT. The image was missing a couple of python modules that are used to produce graphs etc, so I needed a dockerfile to get them in there. Also, it needed to expose the html/images outside the docker container. Reviewing the logs and having a play inside the console of the docker image I worked out what was missing.
docker
This was the docker-compose file I ended up with:
version: "3.3"
volumes:
data:
services:
weewx:
#image: felddy/weewx
build: .
container_name: weewx
restart: unless-stopped
volumes:
- /dockervolumes/weewx/data:/data
- /dockervolumes/weewx/html:/home/weewx/public_html
environment:
- TZ=Pacific/Auckland
devices:
- /dev/bus/usb:/dev/bus/usb
dockerfile
Using “build: .” in the docker-compose file will look for a dockerfile in the local directory, rather than building an image directly. This allows the additional binaries to be installed.
FROM felddy/weewx
RUN pip install --upgrade pip
RUN pip install pillow
RUN pip install cheetah3
USB Subsystem access with Docker
The weather station uses the USB subsystem, not serial and it can be confusing looking at implementations of docker for other weatherstation setups. It does not appear to use a tty such as /dev/ttyUSB0, /dev/ttyACM0 etc or /dev/serial. It also does not show up in /dev/serial/by-id as some of my other USB devices do.
The docker-compose file above showed how I shared the entire USB bus with the docker container. That wasn’t the entire story though, as permissions were still an issue.
I plan to go back and tighten the permissions (assign the docker container tighter group access, and reduce perms to a 0660 mask should do it), but currently I have set UDEV rules so that the specific USB device has full read permissions to all, but this setup is working currently.
I also looked at just running the container in privileged mode as many pages suggest, i.e. “privileged: true” in docker-compose, but as well as being very insecure, I don’t think this works in debian buster
The process to find out the info for UDEV was to run #lsusb and see where the weatherstation appeared.
root@panda: /root# lsusb
Bus 001 Device 002: ID 8087:8000 Intel Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 004: ID 2548:1002 Pulse-Eight CEC Adapter
Bus 002 Device 003: ID 1941:8021 Dream Link WH1080 Weather Station / USB Missile Launcher
Bus 002 Device 002: ID 0451:16a8 Texas Instruments, Inc.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Yes, this is the WH1080 weather station on bus 2:3 (and the ID is also a USB missile launcher). Potentially you could just allow access to that particular USB port, but this is unreliable as the port ID could possibly change and we may want to plug the station into another port, or a USB hub in future.
The Vendor ID is 1941 and the product ID is 8021. You can find more about the device and the USB system it is plugged into by using:
# udevadm info -a -n /dev/bus/usb/002/003
Take this info and make a UDEV rule, I made it as /etc/udev/rules.d/99-weather-station.rules
root@panda:/root# cat /etc/udev/rules.d/99-weather-station.rules
# Weather Station
SUBSYSTEM=="usb", ATTRS{idVendor}=="1941", ATTRS{idProduct}=="8021", MODE="0666", GROUP="plugdev", SYMLINK+="weather-station"
This USB rule allows full access to the device from docker, and with the docker-compose as above, it won’t care which USB port it is plugged in to. Note there is a SYMLINK above too that I planned to map, but it appears Buster doesn’t like symlink devices in docker according to some of the info I read.
Weewx options
Finally, it was just left to set up weewx correctly. I added the following directories to store weewx config, the database and the hrml/graphs that weewx creates.
/dockervolumes/weewx/data /dockervolumes/weewx/html
Note as per the info at https://hub.docker.com/r/felddy/weewx shows if you run
# docker-compose run weewx
it will generate a default conf file for you by asking you a bunch of questions.
The config file at /dockervolumes/weewx/data/weewx.conf had some changes as below. (the whole config file isn’t shown here)
[FineOffsetUSB]
# This section is for the Fine Offset series of weather stations.
# The station model, e.g., WH1080, WS1090, WS2080, WH3081
model = WS2080
# How often to poll the station for data, in seconds
polling_interval = 60
# The driver to use:
driver = weewx.drivers.fousb
[[MQTT]]
server_url = mqtt://192.168.1.256:1883
topic = weewx
unit_system = METRIC
[[FTP]]
# FTP'ing the results to a webserver is treated as just another report,
# albeit one with an unusual report generator!
skin = Ftp
# If you wish to use FTP, set "enable" to "true", then
# fill out the next four lines.
# Use quotes around passwords to guard against parsing errors.
enable = true
user = weewx_user
password = 123456
server = mywebsite.example # The ftp server name, e.g, www.myserver.org
path = /web/weewxweather # The destination directory, e.g., /weather
# Set to True for an FTP over TLS (FTPS) connection. Not all servers
# support this.
secure_ftp = true
# To upload files from something other than what HTML_ROOT is set
# to above, specify a different HTML_ROOT here.
#HTML_ROOT = public_html
# Most FTP servers use port 21
port = 21
# Set to 1 to use passive mode, zero for active mode
passive = 1
Additional Links & Info
Weather Station info
Fine Offset Models info https://wiki.trixology.com/index.php?title=Fine_Offset
USB Docker & UDEV Links
https://www.losant.com/blog/how-to-access-serial-devices-in-docker
https://www.weather-watch.com/smf/index.php?topic=33564.15
https://stackoverflow.com/questions/24225647/docker-a-way-to-give-access-to-a-host-usb-or-serial-device
http://marc.merlins.org/perso/linux/post_2018-12-20_Accessing-USB-Devices-In-Docker-_ttyUSB0_-dev-bus-usb-_-for-fastboot_-adb_-without-using-privileged.html
Help with using dockerfiles via docker-compose
https://docs.docker.com/compose/gettingstarted/
Other Options
Local Webserver for weewx
This is a simple webserver setup for weewx if needed… I didn’t want a local http engine on the docker box. My weewx implementation just pushes the html and graphics to a commercial server by sftp.
https://hub.docker.com/r/mitct02/weewx
USB reset tips for previous model
https://groups.google.com/forum/#!topic/weewx-user/owhSpmklNlc
https://www.mail-archive.com/weewx-user@googlegroups.com/msg18376.html
My eventual USB Reset method using home automation
https://zorruno.com/2020/usb-weather-station-using-docker/
Eliminate the USB receiver/display for more reliability
Remove the USB Main display which may not be that reliable (hopefully my current model is more reliable than the last) and build a 433MHz receiver.
https://blog.mjwconsult.co.uk/wh1080-weatherstation-with-arduino-and-weewx/
My later method of getting data directly via 433MHz and an SDR
This is my setup for using an SDR and getting the data directly (I didn’t need both methods, and am happy with using WeeWX.
https://zorruno.com/2020/using-an-sdr-and-rtl_433-in-docker-with-mqtt/