~derf

You have reached the personal homepage of an entity commonly known as derf / derfnull / Birte Friesel. Hi! 👋

If you are looking for the more professional side of me, you may take a look at my Publications (see below) or head directly to my work homepage: Dr. Birte Kristina Friesel @ Universität Osnabrück

Resources

Contact

You can reach me by E-Mail (d​erf@fina​lr​ewind.org) and on IRC (derf0 @ OFTC, hackint). My PGP key for E-Mail encryption is 64FE6EC0 55560F9E F13A3044 19E6E524 EBB177BA. I occasionally post stuff on the Fediverse (@derf@social.skyshaper.org).

The remainder of this page duplicates a curated sub-set of projects and the latest blog entries.

Projects

> dbris 'Eichlinghofen H-Bahn, Dortmund' 'Dortmund Hbf'

19.01. 16:51  (00:21)  17:12   .  Bus  S

Bus 440 → Oespel S-Bahnhof, Dortmund
16:51 (+1)  ab  Eichlinghofen H-Bahn, Dortmund
16:56 (+1)  an  Oespel S-Bahnhof, Dortmund

Fußweg 46m  (≈ 3 min.)
S 1 → Dortmund Hbf   .
17:01 (+5)  ab  Dortmund-Oespel  2
17:12 (+2)  an  Dortmund Hbf  7
> hafas 'Eichlinghofen H-Bahn, Dortmund' 'Dortmund Hbf'

00:15        Schw-B HB5  (0:03)  S 1

Schw-B HB5 → Universität S-Bahnhof, Dortmund
21:51  ab  Eichlinghofen H-Bahn, Dortmund
21:55  an  Universität S-Bahnhof, Dortmund

Walk 37m  (approx. 3 minutes)
S 1 → Dortmund Hbf
21:58  ab  Dortmund Universität: 2
22:06  an  Dortmund Hbf: 4
> efa Essen Martinstr Düsseldorf Hbf
14:34 ab  Essen Martinstr.: Bstg. 1      Straßenbahn 108      Essen Altenessen Bf Schleife
14:38 an  Essen Hauptbahnhof: Bstg. 1

14:47 ab  Essen Hauptbahnhof: 2          R-Bahn RE11 (RRX)    Düsseldorf Hbf
15:24 an  Düsseldorf Hbf: 10
> dbris-m 'Bochum Hbf'
06:39  ( +7)   ICE 843                             Berlin Hbf  5
06:39  ( +7)   ICE 853                             Berlin Hbf  5
06:51  (+19)       S 1                              Essen Hbf  7
06:37  ( +1)   ICE 527                            München Hbf  3
Zug fährt abweichend mit nur einem Zugteil. Die Wagen 31 - 39 entfallen.
> hafas-m 'Hamburg Dammtor'
13:49  ( +1)  RE 7     Flensburg                  3
13:49  ( +1)  RE 7     Kiel Hbf                   3
13:49         S 5      Buxtehude                  2
13:50  ( +4)  Bus 5    Nedderfeld, Hamburg
13:50         U 1      Ohlstedt, Hamburg
> efa-m -s VVO Dresden Hbf
13:40 ( -2)  5      66           Lockwitz
13:41        3      3         .  Wilder Mann
13:44        4      3         .  Coschütz
13:44        6      66           Freital-Deuben
13:46 ( +4)  6      360          Kurort Altenberg Bahnhof
13:46        5      360          Dresden Ammonstraße / Budapester Straße
13:48 ( +1)  1      7         *  Weixdorf
13:51        1      10        .  Tolkewitz
13:52        Gl.10  RE3          Hof Hbf

News

Travel-Status-DE-HAFAS-6.24.tar.gz (signature)

  • station: Fix result->station->{eva} key

Travel-Status-DE-VRR-3.18.tar.gz (signature)

I'm a sucker for colourful Grafana graphs (and not-necessarily-useful data logging in general), so naturally, I also had to see if I could get some hardware stats from my Steam Deck in there. Turns out: thanks to Deck's Linux foundation, this is quite easy. All you need to do is enable SSH access (or work directly on the device) and set up a systemd user timer with whatever kind of data logging you want. In my case, I did the following:

  • Switch to desktop mode
  • Open konsole (i.e., the terminal app)
  • Run passwd to set a password for the deck user
  • ssh deck@steamdeck from my workstation
  • Install a script for InfluxDB logging in ~/bin
  • Install a user service and associated timer in ~/.config/systemd/user to run this script every few minutes
  • Enable the timer

My script looks as follows:

#!/bin/sh

HOST=steamdeck

exec curl -s -XPOST 'https://[…]/influxdb/write?db=hosts' \
--data "
memory,type=embedded,host=${HOST} $(free -b | awk '($1 == "Mem:") { printf "used_bytes=%d,used_percent=%f", $2 - $7, ($2 - $7) * 100 / $2 }')
$(awk '($1 ~ /^(.*):$/) { gsub(/:/, "", $1); printf "interface,type=embedded,host='${HOST}',name=%s rx_bytes=%d,rx_drop_count=%d,tx_bytes=%d,tx_drop_count=%d\n", $1, $2, $5, $10, $13 }' /proc/net/dev)
$(df -B1 | awk '($1 != "Filesystem") { gsub(/%/, "", $5); printf "filesystem,type=embedded,host='${HOST}',device=\"%s\",mountpoint=\"%s\" total_bytes=%d,used_bytes=%d,available_bytes=%d,used_percent=%d\n", $1, $6, $2, $3, $4, $5 }')
load,type=embedded,host=${HOST} $(awk '{print "avg1=" $1 ",avg5=" $2 ",avg15=" $3}' /proc/loadavg)
users,type=embedded,host=${HOST} $(who | awk '($5 !~ /tmux/) {logins++} END { printf "login_count=%d,session_count=%d", logins, NR }')
battery,type=embedded,host=${HOST},id=1 capacity_percent=$(cat /sys/class/power_supply/BAT1/capacity),cycle_count=$(cat /sys/class/power_supply/BAT1/cycle_count),voltage_uv=$(cat /sys/class/power_supply/BAT1/voltage_now)
$(for i in /sys/class/thermal/thermal_zone*; do test -r $i/type && test -r $i/temp && echo "sensor,type=embedded,host=${HOST},name=$(cat $i/type) mdegc=$(cat $i/temp)"; done)
"

This gives me stats about memory and disk (SSD + µSD) usage, load, and current battery charge and voltage. Unfortunately, power readings do not seem to be available.

For instance, the following screenshots show an evening DOOM session, followed by leaving the Deck idle to finish some downloads.

They allow for insights such as:

  • The Steam Deck typically reaches 80°C when running hardware-intensive games
  • Battery drain really depends a lot on what kind of game you're playing
  • The Lenovo USB-C Slim Travel Dock I'm using for working at home works just fine with the Steam Deck, but fails to negotiate proper power delivery, so the battery slowly drains when playing.

Recently, I managed to drop my Canon EOS M50 while changing lenses. The fall wasn't that high (maybe 20cm, give or take), but exerted enough force on the body to dislodge the viewfinder's eyecup. This caused the viewfinder's proximity sensor to always detect something (namely, the eyecup's plastic), which, in turn, meant that the camera would no longer operate its 3" LCD – after all, someone was using the viewfinder, so better turn it off in order to save power.

Trying to shove the eyecup back into place did not work at all, and the fact that Canon does not treat it as user-serviceable or -replaceable did not bode too well. After a few weeks' worth of hesitation, I decided to try disassembling the camera up to the eyecup and repair / re-align it myself. It was long out of warranty, so at least I culd not void anything by trying my luck. There was just the risk of “verschlimmbessern” (making something worse by trying to improve), i.e., breaking the camera entirely when trying to repair it.

So, as usual: only do this if you know what you're doing, and don't blame me if something breaks.

Disassembly

Getting to the eyecup requires removal of nine (black, plastic?) PH0 screws and two parts of the camera's plastic shell. I did not check the screw types thoroughly – they all seemed quite similar, but I still made sure to re-apply each screw to the correct hole just to be on the safe side.

First, remove the microphone and NFC cover on the left. It is held in place by three screws, and can be carefully lifted out once they are loose. There are no plastic clips or anything, so you should not need to apply force.

Then, flip out the 3" LCD so that it is out of the way and reveals two screws below the viewfinder. Remove these, the two screws at the tripod mount, and the two screws on the right side. The plastic part that you can now remove holds control button and is connected to the camera with a flat flex cable right below the control buttons. So, carefully fold out the plastic back (including the control buttons), and tilt it to the right to avoid stressing said cable. You only need to rotate it by about 90° in order to expose the final (tenth) screw securing the eyecup. You can choose between disconnecting it and storing it somewhere safe, or leaving it connected and being extra careful not to break it.

Repair

Now, remove the metal screw holding the eyecup. In my case, once the screw was out, I could easily move the eyecup back into place (without having to exert force) and was already done with the repair. I expect that you can also replace the entire eyecup at this point, but I did not try that.

Re-Assembly

  • Secure the eyecup with the metal screw
  • Reconnect the flat flex cable leading to the control buttons on the back cover
  • Snap the back cover back into place. Do not secure it yet.
  • Turn on the camera and verify that eyecup / viewfinder, 3" LCD, and the control buttons on the back (next to the LCD) are working
  • Turn the camera off
  • Secure the back cover with its six black screws
  • Snap the side cover back into place
  • Secure the side cover with its thre black screws

In my case, I did not verify that the control buttons are working before re-applying all screws. While I had not unplugged the flat flex cable, I had still managed to loosen its connector, so I had to go back and re-connected it in order to have a working camera again. Before proceeding with the re-assembly, the connector should look roughly like this:

Apart from that, this was a pleasantly straightforward repair, and definitely better than just not using the LCD anymore.

Travel-Status-DE-DBRIS-0.18.tar.gz (signature)

  • dbris-m: Show trip number changes along the route, if any
  • Journey: Fix ->operator and ->train_no accessors
  • Journey: New accessors: trip_numbers, trip_no_at
  • Location: New accessor: trip_no

Travel-Status-DE-DBRIS-0.17.tar.gz (signature)

  • Journey: New accessors: admin_id, admin_ids, operator, operators
  • New build dependencies: File::Slurp, JSON

Travel-Status-DE-DBRIS-0.16.tar.gz (signature)

  • Formation::Group: Add ICE L and LINT 41; fix CFL KISS detection

Travel-Status-DE-DBRIS-0.15.tar.gz (signature)

  • DBRIS: Add optional failure_cache key to new / new_p. This causes the module to cache failed requests, thus decreasing the risk of running into rate limits when, e.g., requesting carriage formation data that is not available upstream.
  • Formation::Group: Update carriage name list (patch by Lili Chelsea Urban)

Travel-Status-DE-VRR-3.17.tar.gz (signature)

  • New dependency: URI::Escape
  • URL-Escape umlauts in name/place parameters sent to EFA backends. This fixes umlaut-related issues in LinzAG and VVO requests.
  • EFA: Detect "invalid stop" backend errors.
  • EFA(3pm): Remove efa_encoding, which has been unsupported for a long time already.

Travel-Status-DE-VRR-3.16.tar.gz (signature)

  • Add AVV ("AVV Augsburg", not Aachen) service definition

Travel-Status-DE-DBRIS-0.14.tar.gz (signature)

  • dbris-m: Do not break --json/--raw-json if the requested stop name is not an exact match
  • Location: Set is_additional for additional stops based on text remarks

Travel-Status-DE-IRIS-2.00.tar.gz (signature)

  • Update station database
  • db-iris and Travel::Status::DE::IRIS are still deprecated, but as the backend service is still available, we might as well make the most of it
  • The major release is mandated by Perl's standard versioning scheme. There are no backwards-incompatible changes.

On the fourth and final full day of our vacation in the Giant Mountains, we decided to go for a change of scenery: take the train to Szklarska Poreba (Schreiberhau), walk up to Pramen Labe (Elbquelle / spring of the Elbe river), and then, depending on time of day and our appetite for more, either take the train back to Karpacz or walk back there across the peaks of the Giant Mountains. Unsurprisingly, we ended up walking the 20km or so from Pramen Labe back to Karpacz, and I can only say that that was the best decision we could have made.

  • KD D62 Karpacz (09:00) → Jelenia Góra (09:18)
  • KD D6 Jelenia Góra (09:24) → Szklarska Poreba Górna (10:15)

Pramen Labe

Szklarska Poreba is a comfortable little town, and seems like less of a tourist attraction than Karpacz. Only downside: it's located in a valley, with the train station where we got off sitting on the hills on one side and the Giant Mountains on the other. So, we first had to lose some precious elevation only to climb back up again on the other side. Apart from that, the way up went as usual: it started out relatively smooth and even, and then got steep and stony. There were some more stone formations and water streams, but nothing out of the ordinary.

Pramen Labe was pretty crowded, so we didn't stay for too long (13:30 to 14:00 or so). The spring itself is your typical ordinary spring, augmented with a nice list of some of the towns and cities it passes before it finally flows into the North Sea. It's located on a relatively large plateau, so from the spring itself, you don't have that much of a view into the surrounding mountain- or countryside.

The Ridge

The first peak we passed was Violik / Łabski Szczyt (Veilchenstein / violet peak). Apparently, its granite rock is slowly ground down by freezing water, leading to its slightly unnatural look as if someone had used a large shovel to pile up a heap of stones. It was also home to some prime specimen of some kind of moss, possibly Trentepohlia iolithus (Veilchenmoos) or Psilolechia lucida (Schwefelflechte).

Up next were Vysoká pláň (high plain), a small peak located on a wide plateau that sits at about 1,400 metres above sea level, and the neighbouring Śnieżne Kotły (Schneegruben / snow pits). Vysoká pláň features the former Schronisko „Nad Śnieżnymi Kotłami” (Schneegrubenbaude / shelter “above the snow pits”), which used to offer rest to hikers and mountain climbers. These days, it is instead used as a radio tower: Radiowo-telewizyjny Ośrodek Nadawczy Śnieżne Kotły. Śnieżne Kotły tend to be a repository for not-yet-molten snow late into spring, but were absolutely devoid of it when we passed them in early August. In any case, the view from the upper side of the cliff was quite spectacular. We spent a few minutes admiring the views, and continued at about 15:00.

We continued around Vysoké kolo (Hohes Rad / high wheel), whose peak consists entirely of broken granite, towards Špindlerova bouda (Spindlerbaude / Špindler's hut), a former shelter that now serves as a hotel.

The peak of vysoké kolo really is quite impressive – I only have pictures of the hiking path around it; see the Wikipedia links for more. Some of the rocks on the path are loose and there are no handrails or anything – do be careful where you step.

The remainder of the way towards Špindlerova bouda provided more granite heaps, mountain pines, and other kinds of rock formations. Also, Špindlerova bouda itself actually features a bus stop, located at convenient 1,198 metres above sea level.

Descent

From here on, continuing the path along the peaks would have taken us to Słonecznik, which we had already visited two days ago. Instead, we descended to the north. We had actually planned to make our descent before Špindlerova bouda, however, it turned out that that path was closed to hikers.

At this point, the clock was reading 17:00, we still had quite a few kilometres left to go, and the shadows were already growing longer. We had the sun at our backs and got some nice views across the Polish lowlands, plus the usual selection of rocks, more or less forested areas, and marsh lands. We reached Polana - Kotki (Katzenschlosslichtung / cat castle glade) at 18:45, and got back to Karpacz at around 20:15.

See lib.finalrewind.org/Pramen Labe for more pictures.

This is the third of four posts about our 2025 vacation in the Giant Mountains (Krkonoše / Karkonosze), see Vacation in the Giant Mountaints for an introduction.

We wanted to have a change from the typical Polish food in the evening, and, thus, decided to climb up to Horní Malá Úpa on the Czech side of the Giant Mountains, have lunch there, walk a bit along the ridge, and return to Karpacz.

Ascent, Part 1

We started at around 10:30 from the very West of Karpacz, specifically its Osiedle Skalne suburb. From there, we took a path along (and, as often as not, across) the Malina stream (Langwasserbach). Some crossings came with bridges, others with broken bridges, and some with just a few strategically placed rocks. The latter parts of the path are helpfully marked with exclamation marks, likely indicating precisely these challenges. Anyhow, we enjoyed the quiet we had in this part of the forest, and made it through all fords without surprise baths.

Budniki

At 12:00, about a third of the way up, we reached former Budniki (Forstbauden / Forstlangwasser). We weren't aware of this site when planning the trip, so that was a pleasant surprise. Essentially, Budniki is a former settlement that, due to its location very close to the peaks of the Giant Mountains, had the peculiarity of not receiving any direct sunlight for 110 days a year. Apparently, it was abandoned around 1950 due to preparations / explorations for uranium mining operations. We also learnt about Wołogór, which doesn't seem to have an English or German Wikipedia page that I can link. Furries, they're everywhere!

We also found out that the bread we had brought along was not a proper dark bread, but simply wheat with activated charcoal. That's the kind of surprises you can get when you aren't fluent in Polish.

Ascent, Part 2

From Budniki on, the remaining 400-or-so metres of elevation got quite challenging, with uneven and pretty steep terrain that just kept going on and on. When we finally reached a more even path close to the ridge line, we were greeted with the usual occasional flooding, lush green, and (at about 14:00) a sign welcoming us to Česká Republika.

Horní Malá Úpa

For English speakers, the jokes related to the name of Horní Malá Úpa (Ober-Kleinaupa / upper Malá Úpa) write themselves. So naturally, we had to pose for the obligatory photos near the entrance sign. Apart from that, the municipality is unspectacular. There's some border stones that still bear markings of the former ČSSR (Tschechoslowakei), some skiing infrastructure, and buses that are specifically outfitted for taking on bikes (or, possibly, skis). We had lunch at Pivovar Trautenberk, which I can recommend. Also, the nice part about Česká is that if you order lemonade, there's a high likelihood that you'll be served kofola 😋.

Tabule

After some exploration and our lunch break, we left Horní Malá Úpa for the final climb up the nearest peak at around 15:30. We started out in a dense forest, and then, as the vegetation grew thinner, got some views towards other parts of the Giant Mountains.

We reached Tabule (Tafelstein / table peak) at about 17:00, and took in some more scenery. Once again, we could spot Sněžka in the distance, and also a little bit of Karpacz and the Polish lowlands.

Descent

The descent took us slightly west of the path we used for the ascent, and was just as steep. It also really drove home just how much its height (and, likely, other factors) affect the vegetation – we got everything from low bushes to coniferous and birch forests.

We passed Budniki once more, and then followed the Skałka stream for a bit. Here, we were faced with another surprise: a (possibly carbonated) spring that not even OpenStreetMap knew about.

We got back to Karpacz at about 19:00. As usual, more photos are available at lib.finalrewind.org/Tabule 2025.

Travel-Status-DE-HAFAS-6.23.tar.gz (signature)

  • Update URL for NAHSH service