--- title: Upgrade my weatherstation to WeeWX 5 summary: > Another big move for the weatherstation. The station also moved off the Raspberry Pi 4 and I'm using the SQLite database again (instead of a local or remote MySQL server). The new environment is a virtual machine running on my homeserver. date: 2024-06-30T21:48:50+0200 # lastmod: coverCaption: Ecowitt WS69 categories: - amateur-radio - computerstuff tags: - Archlinux - WeeWX - WX --- I moved the weatherstation software again to another computer, this time a virtual one -- that means one Raspberry Pi less on the windowsill. The installation process is also [covered in the 5.0 docs](https://weewx.com/docs/5.0/quickstarts/pip/). ## Creating the virtual environment ~~~console $ sudo pacman -S python-pip ~~~ ~~~console $ python -m venv ~/weewx-venv $ source ~/weewx-venv/bin/activate $ python -m pip install weewx ~~~ The installation is complete, let's create the station. I like doing upgrades "from scratch" because I can use an up-to-date configuration file -- although it is more work to add the old changes to the new file. ## Create the new station ~~~console $ weectl station create took 8s via 🐍 v3.12.3 weewx-venv ~~~ Follow the instructions on the command line. Edit the freshly created configuration file. ~~~console $ nvim ~/weewx-data/weewx.conf ~~~ Including my old settings and add the GW1000 configuration for the plugin that I will soon install. ## Installing the extensions Do this **within the virtual environment**! Install the GW1000 driver: ~~~console $ weectl extension install https://github.com/gjr80/weewx-gw1000/releases/latest/download/gw1000.zip ~~~ Install the WDC theme: ~~~console $ wget -O "/tmp/weewx-wdc.zip" https://github.com/Daveiano/weewx-wdc/releases/download/v3.5.1/weewx-wdc-v3.5.1.zip $ mkdir /tmp/weewx-wdc/ $ unzip /tmp/weewx-wdc.zip -d /tmp/weewx-wdc/ $ weectl extension install -y /tmp/weewx-wdc/ ~~~ Install the XAGGS extension: ~~~console $ weectl extension install https://github.com/tkeffer/weewx-xaggs/archive/master.zip ~~~ Install forecast plugin: ~~~console $ wget https://github.com/chaunceygardiner/weewx-forecast/releases/download/v3.4.0b12/weewx-forecast-3.4.0b12.zip $ weectl extension install weewx-forecast-3.4.0b12.zip ~~~ Install the OpenWeatherMap extension: ~~~console $ wget -O weewx-owm.zip https://github.com/matthewwall/weewx-owm/archive/master.zip $ weectl extension install weewx-owm.zip ~~~ ## Install Systemd and udev files ~~~console $ sudo sh ~/weewx-data/scripts/setup-daemon.sh ~~~ My installation died everyday at 5 AM and so I modified the systemd files at the `[Service]` section: ~~~patch --- weewx.service 2024-06-13 21:13:50.115021718 +0200 +++ /etc/systemd/system/weewx.service 2024-06-11 05:22:43.224222604 +0200 @@ -12,6 +12,8 @@ ExecStart=/home/dominic/weewx-venv/bin/python /home/dominic/weewx-venv/lib/python3.12/site-packages/weewxd.py /home/dominic/weewx-data/weewx.conf StandardOutput=null StandardError=journal+console +RestartSec=60 +Restart=on-failure User=dominic Group=dominic ~~~ ## Adopt the configuration files Again, to include the latest changes and themes. ~~~console $ nvim ~/weewx-data/weewx.conf $ nvim ~/weewx-data/skins/weewx-wdc/skin.conf ~~~ Start WeeWX and test the configuration: ~~~console $ weewxd ~~~ If everything runs without problems we can now enable and start the Systemd service. ~~~console $ sudo systemctl enable weewx.service ~~~ I like to test it with a full reboot, if you just want to start the daemon right away you can also run `sudo systemctl enable --now weewx.service` instead. ## Register the station on OpenWeatherMap After creating an API key (which I already have because of the forecast plugin that I use already) we can register our new station on the command line with `curl`. ~~~console $ curl --header "Content-Type: application/json" --request POST \ --data '{"external_id": "LGFD_OE7DRT","name": "OE7DRT-13, Laengenfeld, Tirol, Austria","latitude": 47.07321210625363, "longitude": 10.974540559888204, "altitude": 1202}' \ "http://api.openweathermap.org/data/3.0/stations?appid={APIKEY}" ~~~ That should give you something like this (probably without linebreaks!): ~~~json { "ID": "${STATION_ID}", "updated_at": "2024-06-23T07:40:47.276754274Z", "created_at": "2024-06-23T07:40:47.276754093Z", "user_id": "${USERID}", "external_id": "LGFD_OE7DRT", "name": "OE7DRT-13, Laengenfeld, Tirol, Austria", "latitude": 47.07321210625363, "longitude": 10.974540559888204, "altitude": 1202, "rank": 10, "source_type": 5 } ~~~ I haven't found any information about the format of `altitude` so I currently used 1202, which represents my stations height in **meters**. To change a stations information I'd then send another request like: ~~~console $ curl --header "Content-Type: application/json" --request PUT \ --data '{"external_id": LGFD_OE7DRT, "name": "OE7DRT-13, Längenfeld, Tirol, Austria"}' \ "http://api.openweathermap.org/data/3.0/stations/${STATION_ID}?appid=${APIKEY}" ~~~ ## Send the URL as the stations status text Create another virtual environment: ~~~console $ python -m venv ~/aprs-venv $ python -m pip install aprslib ~~~ Create systemd files for the user: ~~~console $ mkdir -p .config/systemd/user ~~~ Create these two files in the directory above: `aprs-sendstatus.timer`: ~~~systemd [Unit] Description="Send APRS status package to APRS-IS for the Weatherstation" [Timer] OnBootSec=2min OnUnitInactiveSec=30min Unit=aprs-sendstatus.service [Install] WantedBy=default.target ~~~ `aprs-sendstatus.service`: ~~~systemd [Unit] Description="Send APRS status package to APRS-IS for the Weatherstation" After=network.target [Service] Type=oneshot ExecStart=/home/dominic/aprs-venv/bin/python /home/dominic/bin/aprs_sendstatus.py [Install] WantedBy=default.target ~~~ Enable the timer: ~~~console $ systemctl --user daemon-reload $ systemctl --user enable --now aprs-sendstatus.timer ~~~ Check if the timer is listed: ~~~console $ systemctl --user list-timers NEXT LEFT LAST PASSED UNIT ACTIVATES Sun 2024-06-30 21:54:20 CEST 25min Sun 2024-06-30 21:24:19 CEST 4min 18s ago aprs-sendstatus.timer aprs-sendstatus.service 1 timers listed. Pass --all to see loaded but inactive timers, too. ~~~