You may or may not find something useful here.

Browse the archive too see all entries.

no more nodm

Some time ago, I posted a recipe for running kodi-standalone in nodm.

Unfortunately, it is no longer viable, because nodm is deprecated and has two flaws:

  1. When the system is in shutdown, nodm will respawn itself after being killed by the system
  2. Since kodi 18.something, videos will freeze at the end and you can no longer see the kodi menus.

While the first one can be solved using a workaround in the systemd unit for nodm, the latter seems to be not fixable. Furthermore, nodm is no longer developed and also the developer suggest using lightdm and the autologin feature - which, by the way, solves both issues.

Posted Sat 21 Nov 2020 11:13:28 AM CET
recode samsung slowmo video

My Samsung S9 can produce nice slow-motion with 120fps. However, on the phone the videos are stored in 120fps, recoded to 29.99fps - so that you can view the slow-motion directly. But sometimes you also want the original video back. Here is a quick script to recode the video to normal speed:

ffmpeg -i "$FILENAME" -vn -acodec pcm_s16le -ar 44100 -ac 2 output.wav
sox output.wav fixed.wav speed 8.0
ffmpeg -i "$FILENAME" -vf setpts=1/8*PTS -an -r 30 -crf 18 output.mp4
ffmpeg -i output.mp4 -i fixed.wav -c:v copy -c:a aac realtime.mp4
rm output.wav output.mp4 fixed.wav

Unfortunately, you can not use ffmpeg for the audio too... But the trick using sox works fine!

Posted Mon 02 Nov 2020 11:30:27 AM CET
crack tip element in calculix

There is a special case of element, where the determinant of the Jacobian is "allowed" to be zero. This element is called the crack tip element, and is basically a quadratic quadrilateral element where two of the mid nodes are placed strategically in order to give a zero determinant at the corner node in between.

You can basically calculate the distance yourself, simply set up the trial function for the position, then differentiate to get the Jacobian and solve the determinant for zero at one of the corner nodes. It is actually a fun little exercise! If you calculate the length, you will note, that the resulting distance is 1/4 of the edge length - the undeformed element has the mid node at 1/2 the edge length.

But what does all this mean and can we do with this now? The determinant of the Jacobian effectively gives the volume (area) change for a given infitisimal point. That means, if det(J) equals 1, we have no change. If it is 2, we have an 100% increase. However, if it is zero, we produced a singularity, meaning we compressed everything into a point with no radius - even our infitisimal point gets even smaller. This zero determinant is the same concept of a division by zero. We can actually get a value from such a division, for example by looking at the limit at infinity. But back to our crack tip. The idea of the crack tip, as far as I understood it, is to model the emerging front of a crack where the material gets discontinuous. But as we can not really model discontinuity in the mesh, we use the singularity to model the stress concentrations at the point. By using an element where a single node gives a determinant of zero, allows us to model the diverging stress curve at that point, i.e. we can model a theoretical infinite stress.

Let us look at this example in more detail using calculix to calculate some numbers. First, we create a normal mesh using four CPS8 elements. We fix them on one side and apply a displacement at the two corner nodes the opposite side, effectively loading the elements in tension. We can probably already guess what will happen: The stress will be highest at the two corner nodes and gradually decrease towards the center from both sides. Indeed, we see the same in the output:

But, what happens if we introduce the crack at the middle between the two nodes? We apply the moved nodes and run the simulation again:

We can immediately see the stress concentration in the middle. If we plot the stress along the edge, we can see this more clearly:

But wait! Why is the stress not infinity, as proposed by the limit when we set the determinant to zero? The reason is the numerical model we use. First of all, we are solving the differntial equations here at the integration points and then transforming the result back onto the nodes. You can see what that means if you switch from CPS8 to CPS8R elements, which use only a single integration point. In that case, we do not even see the singularity that easily! In the end, our finite element model is just a model - which has obviously some drawbacks. If you look carefully at the element stress distribution, you can also see where the interpolation comes from - for example you can see some diagonal lines forming between the mid-nodes.

So we see, that we can use such elements to model stress concentrations without actually meshing the discontinuity, for example by inserting many many small elements at the crack tip. On the other hand this also gives a nice example, what happens if the mesh quality is bad and for some reason we introduce such distorted elements into our mesh! In such a case, we would see high stress concentrations at points where we do not have them in the real world.

If you want to play around with the two models, here are the input decks for download:

Posted Wed 29 Apr 2020 10:05:06 AM CEST
use nodm instead lightdm for kodi

The official kodi wiki suggests using lightdm with the autologin enabled in order to autostart kodi. But there is a problem with this approach: If kodi crashes (which it frequently does), you are greeted with the login screen instead of having kodi restart.

What you would need is a kiosk mode for lightdm - which is awefully heavy in configuration - at least in comparison with nodm:

  • Simply apt install nodm
  • then edit /etc/default/nodm and change NODM_USER=root for NODM_USER=kodi (or whatever kodi user you have)

Then, enable autostarting for the user:

$ mkdir -p ~/.config/autostart && ln -s /usr/bin/kodi ~/.config/autostart
Posted Mon 06 Jan 2020 12:05:57 PM CET
get local time via wifi

If you travel, you will probably have the problem that the time on your laptop is still the home time. On mobile phones, the time will automagically be retrieved from the mobile network time, but if you do not have a mobile connection on your laptop, this is quite hard. But there is a trick you can do, which requires the use of geoip-bin.

Just lookup your public wifi IP and compare it to the geoip database:

TZ=$(geoiplookup $(curl -s | cut -d " " -f 4 | tr -d ',') date

With a little bit of scripting, you can put this into a nice script, which will refresh the cache of the local timezone every hour.

# this script tries to get the local time by checking the public wifi IP

if ! [ -f ~/.cache/localtime.cache ] || [ $(($(date +%s) - $(stat --printf '%Y' ~/.cache/localtime.cache))) -gt 3600 ] ; then
    geoiplookup $(curl -s | cut -d " " -f 4 | tr -d ',' > ~/.cache/localtime.cache
    if [ $? -ne 0 ]; then
        exit 1

if [ -z "$1" ]; then

if [ -f ~/.cache/localtime.cache ]; then
    TZ=$(cat ~/.cache/localtime.cache) date +"$FMT"
    date +"$FMT"

Later I found out, that this script does only work, if the country you are in, is listed as an own timezone in /usr/share/zoneinfo. It is the case for GB but for example not for AT. There are some conversion lists, but you will obviously get problems when you are in the US or Russia, as those countries span multiple timezones. So yeah, this script kind of work in some cases only. But I hope you get the point and can adjust it to your needs!

Posted Thu 03 Oct 2019 10:03:31 AM CEST
building a proper gopro charger

Years ago, I bought some third party dual GoPro charger off amazon.

The first thing I did, was take it apart... It was very heavy and I was interested what I would find inside. To my surprise, most of the weight came from an steel piece, which was put inside the case. It looks like it was deliberatly put there to keep the charger from flying around or to give it a "proper feel". I don't know...

The charging circuit was also quite interesting. It only consists of the reference circuit to an UN8HX charger - which is a cheap 4.2V lithium charger IC with 500mA charging current, which was very easy to reverse engineer.

One funny thing though was that the two charging ports were connected in parallel to the charger. In my opinion this is not very good for LiPo batteries, especially if you try to charge to cells which have different charging levels.

At some day, the charger stopped working - I'm not sure why and I do not want to know... I bought some cheap LiPo charger circuits of amazon, in my case some boards which use a TC4056A (a 4.2V/1A lithium charger IC). After some sawing and glueing, I ended up with a much much smaller and better charger:

I also added a small spring on the side, as the charge pod size would not properly fit the batteries, hence they would fall out of the charger if used.

The charger works much faster than the original one (the original knock-off one). The biggest advantage though is the size: The old charger was quite clunky and much bigger than the GoPro itself.

(I know, the sawing is a little bit nasty and the thing does not look nice... I promise I'll 3d-print a proper case if I ever have time to do it ;))

Posted Tue 25 Jun 2019 09:15:44 PM CEST
Rant: Java versions in Debian

I need to run JabRef on my debian machine. But suddenly, it stopped working! After a little bit of searching, I found out that openjfx was lately upgraded to version 11+26-5. Nice! So finally it can be used with Java 11!

But wait... JabRef can only run with Java 8. But uhmmm that means I need the openjfx for Java 8 as well?!

Using confirmed that theory. Downgrading the packages of openjfx to 8u171-b11-2 made JabRef working again... Yeah, but then openjfx does not work with other versions than 11.

On the debian issue tracker you can find this bug: Debian bug #910407. There you can read:

openjdk-8 is still there because we haven't completed the transition to
Java 11 yet. It may remain in Buster but only as a build dependency,
there is no plan to support it at runtime. Java based applications in
Buster must run on Java 11 (it should soon become the default JRE).

For these reasons packaging openjfx-8 doesn't really make sense. That
would be a string preventing us from moving forward.

Uhmmmm, so that means Java 8 is basically out of order soon, but there are still very useful tools using it. Why is it so hard to create different versions of openjfx to work with each java version? What is even weirder about the openjfx package, is that it does not pin the versions of the dependand packages and also does not specify the required java version:

Package: openjfx
Version: 11+26-5
Priority: optional
Section: java
Maintainer: Debian Java Maintainers <>
Installed-Size: 30,7 kB
Depends: libopenjfx-java
Recommends: openjfx-source
Download-Size: 8.848 B
APT-Sources: testing/main amd64 Packages
Description: JavaFX/OpenJFX - Rich client application platform for Java
 JavaFX/OpenJFX is a set of graphics and media APIs that enables Java developers
 to design, create, test, debug, and deploy rich client applications that
 operate consistently across diverse platforms.

Package: openjfx
Version: 8u171-b11-2
Priority: optional
Section: java
Maintainer: Debian Java Maintainers <>
Installed-Size: 77,8 kB
Depends: libopenjfx-java, openjdk-8-jre
Download-Size: 35,8 kB
APT-Manual-Installed: yes
APT-Sources: unstable/main amd64 Packages
Description: JavaFX/OpenJFX 8 - Rich client application platform for Java
 JavaFX/OpenJFX is a set of graphics and media APIs that enables Java developers
 to design, create, test, debug, and deploy rich client applications that
 operate consistently across diverse platforms.

From that alone, I thought that openjfx 11 would work with the old versions just fine. But no, it does not.

That means I need to run JabRef in a VM soon, in order to make it work... Nice!

Posted Mon 19 Nov 2018 12:36:36 PM CET
the science of boiling eggs

There is a very interesting article in German on boiling eggs from one of the Science Busters Werner Gruber: Wie lange kocht man ein 3-Minuten Ei?.

This article gives an equation how long an egg must boil for a certain core temperature to reach:

t = 0.0016 \cdot d^2 \cdot \mathrm{ln}\left(\frac{2 \cdot(T_{\mathrm{water}} - T_{\mathrm{start}})}{T_{\mathrm{water}} - T_{\mathrm{inner}}}\right)

For a soft-boiled egg, the value of T_{\mathrm{inner}} should be above 61.5°C but below 65°C. The article specifies 62°C as the target but another page, which is citing this article gives 64°C as the target value. We use this higher value here.

As T_{\mathrm{water}} can be set to 100°C and T_{\mathrm{start}} can be assumed to be 4°C, if the egg comes from the freezer, the whole equation can also be written as:

t = 0.002678 \cdot d^2

A normal egg has a minor diameter of about 41mm (S) to 49mm (XL). Plotting the function between these values, we can see, that the curve is almost linear in this region. The linear function can be calculated as:

t \approx 0.24 \cdot d - 5.36

Thus, to have an "in the ballpark" figure for the boiling time, just take a quarter of the minor diameter and subtract 5 and a half minutes from the result and take the eggs out a little bit earlier ;)

Posted Tue 09 Oct 2018 03:50:32 PM CEST
fixing a hario scale

After a capuccino spill over a Hario VSTM-2000 scale, the timer was frozen and the buttons would not work anymore.

Also plugging in the USB would not work, the scale charged but did not reset. As the batteries are not removeable (at least not easily), I opened up the scale.

First you need to remove the rubber feet and remove the screws. There are also two more screews in the middle:

Now you open up the small lid, which has two more screews under it:

If you remove those two, the whole scale should come apart. You could have removed the scale plate before (I did not knew it was removeable), then it is much easier to separate the two halfes.

Here are a few impressions. First of all the load cell with it's four wire measurement:

Now the display and button module:

The USB charging module:

and the battery:

To reset the scale, I shorted the battery for a very short amount of time. It was enough to have the microcontroller reboot. I also cleaned the scale, as it had some milk in it. After that you can put everything back together. Make sure not to pinch the wires.

Posted Sat 14 Jul 2018 04:52:10 PM CEST
nexus5 charging

You ever wanted to monitor the charging of your Nexus 5 from the commandline? Here is how it works.

The Nexus 5 uses two chips to control the charging:

While the first chip controls the maximum current which is drawn from the USB, the second chip monitors the current charging current.

Both chips can be read over their I2C interface:

$ ls -al /sys/bus/i2c/drivers/max17048
total 0
drwxr-xr-x  2 root root    0 2018-06-27 21:03 .
drwxr-xr-x 17 root root    0 2018-06-27 20:58 ..
lrwxrwxrwx  1 root root    0 2018-06-27 21:03 84-0036 -> ../../../../devices/f9923000.i2c/i2c-84/84-0036
--w-------  1 root root 4096 2018-06-27 21:03 bind
--w-------  1 root root 4096 2018-06-27 21:03 uevent
--w-------  1 root root 4096 2018-06-27 21:03 unbind

$ ls -al /sys/bus/i2c/drivers/bq24192/
total 0
drwxr-xr-x  2 root root    0 2018-06-27 20:58 .
drwxr-xr-x 17 root root    0 2018-06-27 20:58 ..
lrwxrwxrwx  1 root root    0 2018-06-27 20:58 84-006b -> ../../../../devices/f9923000.i2c/i2c-84/84-006b
--w-------  1 root root 4096 2018-06-27 20:58 bind
--w-------  1 root root 4096 2018-06-27 20:58 uevent
--w-------  1 root root 4096 2018-06-27 20:58 unbind

To get the current current, you can do the following:

$ cat /sys/bus/i2c/drivers/max17048/84-0036/power_supply/battery/uevent

or while charging:

$ cat /sys/bus/i2c/drivers/max17048/84-0036/power_supply/battery/uevent
Posted Wed 27 Jun 2018 09:22:29 PM CEST