QGIS already supports this for a convenient, remotely triggered refresh function of PostGIS layers by listening on the qgis channel if a PostgreSQL connection exists:
Load a PostGIS layer
Set its symbology to something dynamically randomized so you see changes if the map is refreshed
In the layer’s rendering options set it to refresh on notification
In a PostgreSQL client trigger a notification event, e.g. NOTIFY qgis, 'hi'; or SELECT pg_notify('qgis', 'refresh plz!');
The layer is refreshed in QGIS
You can set the layer(s) to refresh on any event on the qgis channel or only for specific messages. For example you could set each PostGIS layer to refresh on a different message, e.g. their table name and use that in a PostgreSQL trigger.
QGIS comes with PyQt and PyQt (of course) has its own API to let you talk to database servers. And luckily its QSqlDriver class even has a notification signal that let’s you react to notification events in the most convenient way.
So I wrote something:
from qgis.PyQt.QtSql import QSqlDatabase, QSqlQuery, QSqlDriver
def exec_notification(name, source, payload):
"""ZOMG don't ever do this!"""
except SyntaxError as e:
iface.messageBar().pushMessage("PG NOTIFY", str(e))
db = QSqlDatabase.addDatabase("QPSQL")
db.setConnectOptions("service=foo") # using ~/.pg_service.conf
if not db.open():
str, QSqlDriver.NotificationSource, "QVariant"
Run it in QGIS’ script editor and now you can remotely execute any Python code by sending it from PostgreSQL. For example:
Of course this is a horrible idea and you should never run code that a third-party sends to you. Instead you should write specific methods on the Python side and sent well defined messages to control exactly which methods get executed. But, hey it works!
Trigger a notification if a PostgreSQL-stored QGIS project gets updated and in QGIS notify the user if they have said project open.
Make a tiny plugin that lets the user specify a mapping of message -> Python code scripts
At first I had used a simple db.driver().notification.connect(on_notification), expecting the slot to simply receive all the arguments that the notification signal would send. But this led to Qt using a different notification signal (just sending the channel name) or something because the name is overloaded. Qt super explainer eyllanesc once again saved the day by showing that one can (and in this case needs to) specify the correct signature so Qt picks the correct signal to connect to. This was a major learning for me.
For debugging I used another slot function connected to the signal which uses both the QGIS message log and the message bar to inform the user about incoming notification events, take it if you want:
A bad surprise to me was that my QGIS installation on Ubuntu 22.04 (using https://qgis.org/ubuntu) did not have a dependency graph that included PostgreSQL support in QtSql. Ouch! I would have thought this would be usable in any standard QGIS installation out of the box. I had to install libqt5sql5-psql. On Windows this seems to be no issue, both a MSI installer and an advanced OSGeo4W install had the necessary modules. Phew!
The [PythonPlugins] section uses the plugins’ directory names and shows if a plugin is activated or not (true/false).
Plugins can store their options anywhere. No really. Anywhere! You will find some in their own sections, e. g.:
Qgis2threejs (directory “Qgis2threejs“) uses a [Qgis2threejs] section, named the same as its directory
First Aid (firstaid) uses a [FirstAid] section, using different case than its directory, and another section [firstaid] for other options
Plugin Builder 3 (pluginbuilder3) uses a [PluginBuilder] section, named differently than its directory
QGIS GML Application Schema Toolbox (gml_application_schema_toolbox) stores options in [QGIS%20GML%20Application%20Schema%20Toolbox] (needlessly) using URL encoding
Räumlicher Filter (spatial_filter) uses two sections: [SpatialFilter] and [SpatialFilterSymbol] (sorry, we didn’t know better…)
There is a [Plugins] and a [plugins] section. I found some plugins storing some options in the [plugins] section, e.g. First Aid storing some firstaid\debugger-geometry=... there. [Plugins] seems to be used by core plugins. [plugins] stores e.g. if QGIS should automatically check for new ones (although that is also might be tracked in the [plugin-manager] section, no idea which option comes from an older QGIS version maybe).
Some things can be stored elsewhere, I am not sure who does it, maybe some objects do this automatically? E.g. in the [QgsCollapsibleGroupBox] section you might find the states of all(?) QgsCollapsibleGroupBox objects such as gml_application_schema_toolbox\gmlas_bbox_group\collapsed=false concerning a plugin’s widget. Or in [Windows] you might find FirstAidDebugDialog\geometry=....
Plugins might alter any other options of course. There is no way of knowing what plugin touched what (great power and mostly good :) ).
Uninstalling a plugin does not remove the sections from the INI. The plugin itself does not have a chance to clean that up and QGIS has no way of knowing what to remove. (Of course it might be wanted to keep settings around, but it would be nice to be able to really prune something.)
tl;dr: There is no standard, no rules nor best practices for QGIS plugins to store their options.
PS: This post might get updated as I learn. Corrections and improvements are highly appreciated.
PPS: Excuse the big bold highlighting. That’s for me.
Hetzner is a nice, cheap host for server. Unfortunately they do not let you download backups and snapshots of cloud servers locally. So you are kind of locked in with them.
Here is how I create full disk backups for e.g. standard CX11 servers with default images.
Make sure you understand everything before you attempt this. Pay special attention to your own partitions and make sure you archive what you really need. Consider imaging the whole device instead of just a partition.
Create a backup
Create a new snapshot of your server
Create a new server from it
Boot said server in rescue mode
Use good old dd and gzip to image the main disk to a local archive
The bs=1M is fairly random by me, worked well, didn’t care to optimize
gzip (with the default compression level) kind of maxed out the server CPU but still enabled me to almost max out my download bandwidth. Of course the ratio between remote CPU compression speed vs download bandwidth depends on your specific situation. You might want to use xz or zstd instead.
Don’t be stupid, do it twice and compare the checksums
If you do not need your server to be live during backup, you can skip the snapshotting and second server of course, just boot your server in rescue mode instead.
Build a new server from a backup
Create a new server using the same or a similar configuration as the backed up one
The SD card is broken. The internet says it is typical for SD cards to go read-only as a symptom of fail. Trying to rsync or ddrescue the card’s contents using a separate devices led to stalls and read errors.
I might be able to salvage some of the files by using Android’s share functionality but there was nothing important on the card so I won’t bother trying. The card is broken beyond repair and all files are lost.
I want to backup my Android SD card so I inserted it to my computer (tried multiple ones by now). I can see the file tree and browse it just fine. But if I try to read a file, it fails because instead of the actual file contents, all I get is some gibberish. Weirdly enough, the file header is partially identical between different files and contains the words “whatever” and “CONSOLE”. When inserted in my phone I can read and use those files just fine. The phone is a Sony Xperia XZ1 Compact.
Here are some example hexdumps of the file headers from some JPG and OPUS files:
Die Idee war ursprünglich, dass dort Kommentare und Diskussionen zu den im Transparenzportal Hamburg (TPHH) veröffentlichten Datensätzen gepostet werden könnten. Und das vielleicht sogar direkt im TPHH eingebettet.
Dazu hat ein Python-Skript (als Bot namens “Heidi Kabel” ;) ) jede Minute die API des TPHH nach neuen Datensätzen gefragt, die Metadaten abgerufen und sie schön formatiert und aufbereitet als Foren-Threads gepostet. Ein spaßiges Bastel-Projekt, irgendwann 2019.
Die Dokumentation für die Forumsinstallation und der Code für den Bot liegen in:
Naja, dann kam Corona und Treffen von Code for Hamburg gab’s eh schon kaum noch. Die Seite hat praktisch niemand außer mir genutzt, es gab keine 10 Posts, die nicht vom Bot waren. Mit der Einbindung im TPHH wurde es auch nichts (ich hatte mich aber auch nicht drum gekümmert).
Ich hatte es für mich selbst noch als einfaches Interface für die Daten und als praktischen Benachrichtigungsservice auf bestimmte Keywords genutzt, aber jetzt klappt das Update der Forensoftware nicht mehr (Bug von Discourse mit angeblich nicht mehr einzigartigen Tags und es gab keine Rückmeldung auf meine Fragen, von daher …) und ich will da nix auf veralteter Software laufen lassen. Übernehmen wollte es niemand aus dem Verein und im Fediverse hat sich auch niemand gemeldet. Von daher mach ich die Tage das Licht aus.
PS: Ich hoffe Code for Hamburg wird irgendwann mal wieder reaktiviert, mit regelmäßigen Treffen, wo gehackt und gebastelt wird. Toi toi toi!
+repage makes IM not write the offset to the files but actually crop “properly”. Maybe pdfcrop has such parameter too?
Installing a printer in Cups via a USB->Serial adapter
Make sure to “modprobe usbserial“. dmesg should show a printer being connected if you plug it in now. Then Cups should see it too.
RTTY with SDR# and fldigi (for the german DWD stations)
In SDR#: Use USB, filter bandwidth 1000. center the RTTY in your window.
In fldigi: Op Mode -> RTTY -> Custom. Set the carrier shift to custom and then enter 450 in the custom shift field below. Baud rate: 50, 5 bits per character, no parity, 1.5 stop bits. Save and Close. Make sure the Rv button is green!
CW decoding with SDR# and fldigi
In SDR#: Use the CW-L or CW-U preset. Tune so the morse code is right in the middle of your “reception window”.
In fldigi: Op Mode -> CW. Turn off squelch by making the SQL button not green but grey.
It works very well for non-human morse for me. Radio amateur morse is harder and so far full of “spelling errors”. :)
PDF to image with imagemagick/graphicsmagick
If you want to create images from PDF files, use for example mogrify -verbose -geometry 1600 -density 300 -format png *.pdf Without a decent “-density” parameter, you will probably get a blurry image as result.
echo 0 | tee /sys/devices/system/cpu/cpufreq/boost
Might work, might not, depending on unknown factors. Whatever, I just wanted to make some all-core-but-unimportant process to run without going 95°C. For that it worked perfectly well. CPU temps of a Ryzen 5 3600 after many hours of full utilization were at ~65°C. CPU frequencies were capped to 3.6GHz with this while jumping up to 4.2GHz (and ~94°C) without.
Obviously this has an impact on performance.
To re-enable just echo a 1 instead. This is reset anyways when you reboot your system.
Then (if you really want to do it), uncomment the function call in the last line and execute the script. Follow the instructions.
To clean up remove or restore the QGIS/QGISCUSTOMIZATION3.ini file in your profile and remove the license directory from your profile, restore the previous value of UI/Customization/enabled in your profile (just remove the line or disable Settings -> Interface Customization).
If you want to hate yourself in the future, put it in a file called startup.py in QStandardPaths.standardLocations(QStandardPaths.AppDataLocation) aka the directory which contains the profiles directory itself.
BTW: If you end up with QGIS crashing and lines like these in the error output:
... Warning: QPaintDevice: Cannot destroy paint device that is being painted QGIS died on signal 11 ...
It is probably not a Qt issue that caused the crash. The QPaintDevice warning might just be Qt telling you about your painter being an issue during clean up of the actual crash (which might just be a wrong name or indentation somewhere in your code, cough).
This post’s purpose is to link “Tiardey USB Single Foot Pedal Optical Switch Control One Key Programm Computer Tastatur Maus Game Action HID” to “PCsensor” and the footswitch tool on search engines so others who wonder if the device is easy to use on Linux learn that this is the case. Hope it helps!
I bought this https://www.amazon.de/dp/B09TQFBS3C which came with a chinese/manual saying “FS2007 User Manual” and also says “FS2007U1SW (mechanical switch)” (mine clicks, so I guess it is not the “FS2007U1IR (silent photoelectric switch)”. The manual links to pcsensor.com for Windows drivers.
Plugin the device. dmesg should show something like:
[Sun Jan 8 20:25:05 2023] usb 1-4: new full-speed USB device number 7 using xhci_hcd [Sun Jan 8 20:25:05 2023] usb 1-4: New USB device found, idVendor=1a86, idProduct=e026, bcdDevice= 0.00 [Sun Jan 8 20:25:05 2023] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [Sun Jan 8 20:25:05 2023] usb 1-4: Product: FootSwitch [Sun Jan 8 20:25:05 2023] usb 1-4: Manufacturer: PCsensor [Sun Jan 8 20:25:06 2023] input: PCsensor FootSwitch Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:1A86:E026.0001/input/input19 [Sun Jan 8 20:25:06 2023] input: PCsensor FootSwitch Mouse as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:1A86:E026.0001/input/input20 [Sun Jan 8 20:25:06 2023] input: PCsensor FootSwitch as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:1A86:E026.0001/input/input21 [Sun Jan 8 20:25:06 2023] hid-generic 0003:1A86:E026.0001: input,hidraw0: USB HID v1.11 Keyboard [PCsensor FootSwitch] on usb-0000:00:14.0-4/input0 [Sun Jan 8 20:25:06 2023] input: PCsensor FootSwitch as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.1/0003:1A86:E026.0002/input/input22 [Sun Jan 8 20:25:06 2023] hid-generic 0003:1A86:E026.0002: input,hidraw1: USB HID v1.10 Device [PCsensor FootSwitch] on usb-0000:00:14.0-4/input1 [Sun Jan 8 20:25:06 2023] usbcore: registered new interface driver usbhid [Sun Jan 8 20:25:06 2023] usbhid: USB HID core driver [Sun Jan 8 20:25:10 2023] usb 1-4: reset full-speed USB device number 7 using xhci_hcd
Sweet, so it is just some rebranded PCsensor device.
lsusb says ID 1a86:e026 QinHeng Electronics FootSwitch btw.
footswitch -m ctrl -k 1 will configure it to send Ctrl+1 when pressed for example. See the readme for usage and more examples.
You can use more than 3 of these devices via this pull request. I have four connected via a USB hub 1a40:0101 (“Terminus Technology Inc. Hub (branded “hama”), https://www.amazon.de/dp/B08YRZT1RL) and they work just fine.