Skip to content

Enable Deep Sleep mode on Tuxedo Computers Pulse 15 Gen2

A while ago we bought new Pulse 15 laptops from Tuxedo Computers.

Installed Ubuntu on them, and for a while the sleep mode was nagging me, it does not really work. Today I found time to investigate this issue.

First let's find out which sleep mode is enabled:

cat /sys/power/mem_sleep

Something is wrong here. Not only can't I set the sleep mode to the desired "deep" mode, the "deep" mode is not even available. That explains why things are not working as expected.

After some research it turns out that this might be a BIOS problem. Prepare to reboot!

After the laptop powers up, press the "Del" key until the BIOS comes up. Then navigate to "Advanced Settings" -> "AMD PBS" -> "S3/Modern Standby Support".

The default is "Modern Standby Enable", but it turns out that this is the culprit. Changing this to "S3 Enable" and then reboot fixes the problem and "deep" now shows up in the available Linux Power States.

Then follow the description in this link, and permamently set the sleep mode to "deep".

cat /sys/power/mem_sleep
s2idle [deep]


Obsidian: Paste URL into selection

I have a few community plugins enabled in my Obsidian. One of them is "Paste URL into selection" - and it fits very well into the Markdown workflow. Also what you might know from other tools like Slack.

In Markdown, a link is created using square brackets and round brackets. The description text for the link goes into the square brackets, the URL into the round brackets:

[This is a link to the Obsidian website](

Now, usually I write the text first, and then later on add the link. Without this plugin, I have to add the square brackets manually, then add the round brackets and insert the link.
With the Paste URL into selection plugin, I copy the link, select the text in Obsidian and press Ctrl+V. The plugin creates the Markdown link automatically.

It's not much, but it's really useful when writing larger texts with many links!

Show me recent notes in my Obsidian Work Vault

In the previous Obsidian blog posting about managing tasks I showed a note which lists all open tasks in my Work vault. This gives me quick access to all open tasks.

In the same way I use another note quite often which shows me recently added and changed files in my Work vault.


Continue reading "Show me recent notes in my Obsidian Work Vault"

Show me all open Work tasks in Obsidian

My Obsidian vault is "all-in-one", personally I don't like switching between multiple vaults for work and private stuff, and I organize it in a way to keep things separated in one vault. Multiple templates I'm using automatically generate Tasks in my vault, therefore I need a convenient way to see open work tasks. This blog posting describes the approach I'm using.

In my vault I have a folder "Work", that's where all the work stuff lives, obviously. In this folder is a note named "Open Work Tasks". Here's the note, which is mostly DataView queries.

## Open Work Tasks

TABLE WITHOUT ID regexreplace(Tasks.text, "\[.*$", "") AS Task, choice(Tasks.completed, "🟒", "πŸ”΄") AS Status, AS "File"
FROM "Work"
FLATTEN file.tasks AS Tasks
WHERE file.tasks AND !Tasks.completed AND Tasks.text != ""

### Grouped list

FROM "Work"
WHERE !completed AND text != ""
GROUP BY section

### Dates for Tasks


- πŸ“… Due Date
- ⏳ Scheduled Date
- πŸ›« Start Date
- βž• Created Date
- βœ… Done Date

### Tasks with invalid dates

(created date is invalid) OR (done date is invalid) OR (due date is invalid) OR (scheduled date is invalid) OR (start date is invalid)

Let's go over this in detail:

Open Work Tasks

This DataView lists all open tasks, which have a text. Part of the templates is a "ready-to-go" task without text in the "Decisions" section, but such tasks are not listed here.

The query is limited to the "Work" folder, therefore excluding all other tasks somewhere else in the vault.

This list is flattened, which means that it shows all tasks, not grouped, no matter where in the vault under "Work". That's helpful to see where I still have work to do. At some point I may integrate this into Todoist, but so far it works well for me.

Grouped list

This list shows the same entries as the previous list, but groups the entries by source file. This gives me an idea if I have some "heavy work" open where multiple tasks require my attention for the same issue.

Dates for Tasks

This section is mostly documentation (for me). It helps me to quickly remember how to do all the different date forms the Task plugin can do.

Tasks with invalid dates

This last section is supposed to be empty at all times. It's simply a query which shows all Task entries (this time in the entire vault) which have invalid dates. The kind of mistakes which can happen when adding dates in free text form.


I try to work on open tasks as soon as possible, which means that I rarely have more than a few tasks open here - in contrary to my todo list in Todoist, which is quite large, but managed in a different way.

The two DataView queries provide me all the information I need to quickly find all remaining open Work tasks.


Photo by Glenn Carstens-Peters on Unsplash

Daily Notes in Obsidian

Obsidian is a note-taking software and knowledge base software, where the notes/files are written in Markdown. For quite a while I'm using it in my daily work.

One of the cool features it has is named "Daily Notes". As the name implies, there is a new note generated for every day. For me, this is used for writing down notes which do not deserve their own note. But also this is rather heavily used to share all kind of content from my mobile devides into the daily note in the first place. Content doesn't have to stay there, in fact most of it is either handled one way or another, or is moved to a different place. But it is a very nice collection point in the first place.

By default they are created in the main folder of the Obsidian vault - over time, these are hundreds of files, and no real structure. Which deserves to organize the Daily Notes in a better way.


Continue reading "Daily Notes in Obsidian"

KeepingYouAwake on Mac OS X

On my Mac, one of the annoying "features" is when the Mac screensaver comes on, the device eventually goes to sleep, and it disconnects the network. Which in turn timeouts services like Slack or Google, because these services keep a network connection open at all times. When waking up the device, I often have to login again into all the services, even though the device is just sitting in my working room on the desk all day and night. Very annoying.
I suppose it's one of these things where Apple thinks they know better how users want their device to behave.

KeepingYouAwake is a nice little tool which prevents all of this.

When it is running and activated, it prevents the Mac from going to sleep. Which in turn never deactivates the network. And never timeouts the online services.

What's not to love about it?

Picture made by Anton Atanasov

Extract better GPS coordinates from images using exiftool

Sometimes I have to extract Exif information from images, mostly the GPS coordinates. The coordinates coming raw from the images are not very helpful. Let's look at a picture I took today:

Bowl of ice cream

darktable shows the following coordinates:

latitude: N 52Β° 40,198'
longitude: E 013Β° 16,852'
elevation: 93,90 m above sea level

Now that is not very helpful, because neither OpenStreetMap nor Google recognize this format out of the box:

N 52Β° 40,198' E 013Β° 16,852'

Coordinates not working in OpenStreetMap

Coordinates not working in Google

Bummer. And I don't have the time or energy to fix that every time I need the coordinates. Luckily exiftool can output the coordinates in different formats, which is super helpful. For my use cases I choose the Degrees.MinutesSeconds format, also named "Decimal degrees", or DD. This format shows latitude and longitude geographic coordinates as decimal fractions of a degree.

exiftool -time:all -location:all -G -a -s -c "%.6f"

The explanation for the options used here:

  • -G: Print group name for each tag
  • -a: Allow duplicate tags to be extracted
  • -s: Short output format
  • -v: Print verbose messages
  • -q: Quiet processing
  • -c "%.6f": Set format for GPS coordinates

Using these settings, I get the following coordinates:

[Composite] Β  Β  GPSAltitude Β  Β  Β  Β  Β  Β  Β  Β  Β  Β  : 93.9 m Above Sea Level
[Composite] Β  Β  GPSLatitude Β  Β  Β  Β  Β  Β  Β  Β  Β  Β  : 52.669959 N
[Composite] Β  Β  GPSLongitude Β  Β  Β  Β  Β  Β  Β  Β  Β  Β : 13.280862 E
[Composite] Β  Β  GPSPosition Β  Β  Β  Β  Β  Β  Β  Β  Β  Β  : 52.669959 N, 13.280862 E

Which sure enough brings me right to the ice cream place "Il Pistacchio" in Hohen Neuendorf, which I visited earlier today.

Il Pistacchio on OpenStreetMap

Watch for changed files in SyncThing

For syncing files between my devices I'm using SyncThing. This tool is reliable, available on Linux, Android, Mac and iOS. And it encrypts the communication.

But sometimes I want to know when files in certain directories have changed - as example in my Obsidian vault. This allows me to post-process the files.

Some of the use cases I have in Obsidian:

  • Resolve links in Daily Notes: when I share a URL from my RSS reader or from other sources into Obsidian, the URL sometimes is just a link to a URL shortener. I then later need to resolve the link - or let a script do it right away for known shortlinks, and update the daily note.
  • Remove tracking information from URLs: many shared links include campaign and tracking information, and this can be removed straight away.
  • Extract content from certain Toots: I follow a couple interesting accounts on Mastodon, and when I share the Toot link into Obsidian, the script extracts the Toot content and adds it, along with the original link, to a pre-defined note.
  • Extract links from Toots: many news websites include a link (sometimes again with tracking information) in their Toots. When I share such a Toot into Obsidian, a script picks up the link, extract the target link and updates the daily note.

All of this is not very complicated, and a couple of lines in Python do the job. The main parts for the script are:

  • extract the API key from the SyncThing configuration
  • Open a connection to the local SyncThing instance
  • Watch for certain events


Continue reading "Watch for changed files in SyncThing"

PGSQL Phriday #008 – pg_stat_statements

The topic for this month's PGSQL Phriday blogging challenge is: pg_stat_statement. And Michael Christofides gave me a perfect opener in his invitation.

For anyone who doesn't know, I'm running a weekly interview series with people from the PostgreSQL community. It's called "PostgreSQL Person of the Week". One of the questions in the default set I give everyone is:

What is your favorite PostgreSQL extension?

And guess what the answer is: by far everyone's favorite is pg_stat_statements!

What does this extension do? It tracks statistics for planning and execution for queries run by users. This can be used to find long-running queries, users who run too many or too heavy queries, or just generate statistics about the workload. In short: very useful data. And the extension itself does not need a lot of resources. Even better.

This extension is so popular that it has double the interview mentions than the next one (which is PostGIS - by itself also a very popular extension). From the slides I occasionally present at conferences or meetups:

PostgreSQL has a lot of extensions, head over to the PostgreSQL Extension network (PGXN) which is operated by David E. Wheeler to find out about around 360 extensions. Currently in my interviews I have 51 different extensions mentioned.

This extension is so useful that people say:

  • Julia Gugel: "I like pg_stat_statements as it helps a lot with performance troubleshooting."
  • Daniel Westermann: "pg_stat_statements, because it is just required if you want to troubleshoot performance related issues. I still wonder why it comes as an extension and is not there by default."
  • LΓ¦titia Avrot: "Of course, I advise my customers to use pg_stat_statements to monitor their performance"
  • Alexander Kukushkin: "The pg_stat_statements extension is something that everyone must enable for performance monitoring and troubleshooting."
  • Flavio Gurgel: "I cannot live without pg_stat_statements, I think it’s mandatory for server optimisation."
  • Anthony Nowocien: "pg_stat_statements and I will be glad to see it in core."

This is just a small selection of quotes, but this shows that everyone loves pg_stat_statements. I encourage you to head over and read more interviews. There's plenty of insight from community members.

PGSQL Phriday #007 – Triggers for tracking changes in a table

This month's #PGSQLPhriday is hosted by LΓ¦tita Avrot, and she asks about triggers.

History time. Shortly after I started using PostgreSQL, I had a need to track changes in tables. Back then - this was the early version 7.x days - there was no such option available. I set out to write a tool for it. The logical choice to do that was to pick triggers to implement this. Today the world is different, PostgreSQL gained replication, and along with this, one can hook tools into the replication and stream all the changes. Back then there was no replication.

The second thing I discovered was that pl/pgSQL can't do the job. That was a rather big disappointment. My idea was to have one function which can be used with a trigger, the function figures out the columns and writes the changes into a separate table. However one can't access arbitrary column names in NEW and OLD in pl/pgSQL trigger functions. Something like this doesn't work:

columnname1 := "created_at";
columnname2 := "changed_at";

NEW.$columnname1 := OLD.$columnname1;
NEW.$columnname2 := OLD.$columnname2;

In pl/pgSQL, you have to "know" the column names in advance. Depesz recently posted some workarounds for this, but these options also have not been available back then.

Which made me write the tool in C. This at least allowed me to access the NEW and OLD values, and recoed changes. The tool is called "table_log", I also presented it at the first PGDay in Prato, Italy in 2007, and originally it was hosted on pgfoundry. This site is also long gone, I later copied the code to GitHub. But I also know that PostgreSQL 9.x had some internal changes which renders the tool non-working. However because the entire ecosystem had improved, and other tools are available, I did not update the old code anymore.

My conclusion: Triggers were one of the first "advanced" features I used in PostgreSQL, and I like them very much. They allowed me to implement an audit feature I need.

fwupdmgr: /usr/libexec/fwupd/efi/fwupdx64.efi and /usr/libexec/fwupd/efi/fwupdx64.efi.signed cannot be found

From time to time our laptops receive firmware updates, by using the Linux Vendor Firmware Service (short: fwupd). This worked fine for a long time, until it didn't. One day I was facing the following error message:

root@laptop:/root# fwupdmgr update

β•‘ Upgrade Embedded Controller from 0.1.23 to 0.1.25?                           β•‘
β•‘                                                                              β•‘
β•‘ ...                                                                          β•‘
β•‘                                                                              β•‘

Perform operation? [Y|n]: 
Downloading…             [***************************************]
Decompressing…           [***************************************]
Authenticating…          [***************************************]
Waiting…                 [***************************************]
Waiting…                 [***************************************]
/usr/libexec/fwupd/efi/fwupdx64.efi and /usr/libexec/fwupd/efi/fwupdx64.efi.signed cannot be found

During the first few occasions I basically ignored the error message, and attributed it to a glitch in a software package. Maybe a later update will fix this.

But this never happened, so I looked into the issue.

Ubuntu split the 1.6.x version of fwupd into separate packages, and does not install the packages fwupd-signed and fwupd-unsigned to deal with EFI binaries.

apt-get install -y fwupd-signed fwupd-unsigned

Now everything is working again:

root@laptop:/root# fwupdmgr update
β•‘ Upgrade Embedded Controller from 0.1.23 to 0.1.25?                           β•‘
β•‘                                                                              β•‘
β•‘ ...                                                                          β•‘
β•‘                                                                              β•‘

Perform operation? [Y|n]: 
Downloading…             [***************************************]
Downloading…             [***************************************]
Decompressing…           [***************************************]
Authenticating…          [***************************************]
Waiting…                 [***************************************]
Writing…                 [***************************************]
Waiting…                 [***************************************]
Successfully installed firmware
Do not turn off your computer or remove the AC adapter while the update is in progress.
Waiting…                 [***************************************]

Voila! Also updated the playbook which installs the laptops, to include the two new packages.

QNAP: exclude files and directories from rsync

I'm moving files from one QNAP system to another, and I'm using rsync for this. It's preinstalled on a QNAP system. So far, so good.

To sync entire shared volumes, I want to exclude the '@Recently-Snapshot' and '@Recycle' entries - I don't want to sync the trash bin and I also don't want to sync entire snapshots.

The usual approach when using rsync is to just use the --exclude option.

rsync --exclude='@Recently-Snapshot' --exclude='@Recycle'

To my surprise this does not work. rsync on the QNAP does not complain, but also does not ignore the entries. Using escapes in front of the '@' doesn't work either. Ok, which version is the rsync program anyway?

[~] # rsync --version
rsync  version 3.0.7  protocol version 30
Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.

Ouch, that is old. Very old. Released December 2009. Pretty sure QNAP did not fix all the bugs in there.

But according to the documentation, and the --help output, it accepts the --exclude option. Still not working though.

Ok, there is one more option: --exclude-from

I create a text file and add the two entries in there:


And then I use the --exclude-from option to skip entries in these two directories:

rsync --exclude-from=/tmp/pattern.txt

This option works. At least something.

Summary: The rsync on a QNAP system does not accept the --exclude parameter, but the --exclude-from parameter works.

And for everyone asking why I don't use the integrated file copy: this one skips certain files, but I also want my dot files copied over.

PGSqlPhriday #006: One Thing You Wish You Knew While Learning PostgreSQL: psql commands

For this month's #PGSQLPhridayGrant Fritchey asks: What is the one thing you wish you knew while you learn PostgreSQL.

My preferred client for PostgreSQL is psql, and while it is very powerful I like a few features a most:

  • \timing
  • \watch

Both are internal commands in psql, \timing is there for a very long time, but got improved at some point. \watch came later, but is also there for a couple years now.


Continue reading "PGSqlPhriday #006: One Thing You Wish You Knew While Learning PostgreSQL: psql commands"

Dynamic content in static websites in Hugo

With people moving away from Twitter, mostly to Mastodon, discovering the new accounts became a problem.

For people in the PostgreSQL community I created a website which lists different social media accounts. This website is part of the "PostgreSQL Person of the Week" interview project, however the data source is dynamic, and stored in a different repository. This allows me to keep the repository for the website private, but publish the data for the social media links - this data is public anyway. The interview repository is private, because who wants to see upcoming interviews anyway? ;-)

The interview website is made with Hugo, a static website generator. Normally Hugo looks for content, templates, and other data in the current directory - my private repository.

As part of compiling the website, Hugo can fetch external data, either in JSON or CSV format. This is using the getJSON() and the getCSV() functions, which can be used in Shortcodes, as example.


Continue reading "Dynamic content in static websites in Hugo"

PostgreSQL 95

Someone at FOSDEM 2023 asked the question: "What happens when PostgreSQL rolls over the version number to 95? Will this cause problems like back then in Windows?"

What does that even mean? When Microsoft released the version after Windows 98, they opted for naming it Windows 10, not Windows 9. Because apparently a lot of code out there checks if the string starts with "Windows 9" and then assumes that the OS is one of the very old ones. This might not be the only such problem, as another blog article by Microsoft shows. Apparently they used "3.95" for the Windows 95 internal version, because lazy programmers.

You may also remember that there is already a "Postgres95", released around 1994 (shortly before Windows 95 was released). This was before the name was "PostgreSQL", and this is the first version which had SQL support. Before that, QUEL was the query language.

Enough history. And even though the release of PostgreSQL 95 is still a few years out, this raises two questions:

  1. Does today's source code work (aka: compile, and pass tests) with version number 95?
  2. Does your application work against version PostgreSQL 95?


Continue reading "PostgreSQL 95"