Org Test

This is my Org

Markup

My org is amazing.

Give it a lick.

Code

for i in range(10):
    if i % 2 == 0:
        print("{} ist ungerade".format(i))

Images

And an image:

Inside the post, for testing.

Formula

You can set the variable includes_math, but it seems not to work.

Inline doesn't work: $\alpha$

Display does work: $$\beta$$

In Mmark inline maths $$\omega$$ work.

Edit: It was stated that \(\alpha\) this \( TeX Code \) works.

Table

Table 1

a b c
d e f

Table 2

a b c
d e f

My post is amazing.

Nullam eu ante vel est convallis dignissim. Fusce suscipit, wisi nec facilisis facilisis, est dui fermentum leo, quis tempor ligula erat quis odio. Nunc porta vulputate tellus. Nunc rutrum turpis sed pede. Sed bibendum. Aliquam posuere. Nunc aliquet, augue nec adipiscing interdum, lacus tellus malesuada massa, quis varius mi purus non odio. Pellentesque condimentum, magna ut suscipit hendrerit, ipsum augue ornare nulla, non luctus diam neque sit amet urna. Curabitur vulputate vestibulum lorem. Fusce sagittis, libero non molestie mollis, magna orci ultrices dolor, at vulputate neque nulla lacinia eros. Sed id ligula quis est convallis tempor. Curabitur lacinia pulvinar nibh. Nam a sapien.

Here is an image:

Sample image

Formeln

$$\alpha$$

Bilder aussortieren

Es gab eine Feier, jemand hat Fotos gemacht und rumgeschickt. Oder vielleicht habe ich selbst hundert mal den selbe Essen fotografiert. Jedenfalls sind da ein Haufen Bilder und ich will nur die guten behalten.

Dieses Aussortieren macht wenig Spaß und soll deshalb schnell gehen. Wenn man es gut macht hat man danach nur noch 5-10% der Bilder. Der Lohn: Man kann den wenigen guten Bildern viel mehr Beachtung schenken.

Erstaunlicherweise bietet der einfachste (und schnellste) mir bekannte Imageviewer dafür das beste Interface bereit: feh

Vorbereitung

Wir bilden den Sortierprozess auf das Filesystem ab. Wärend dem sortieren haben wir 3 Haufen von Fotos:

  • die noch unsortierten Fotos (~/Pictures/feier)
  • die guten Fotos (~/Pictures/feier/good)
  • die schlechten Fotos (~/Pictures/feier/bad)
mkdir ~/Pictures/feier
cd ~/Pictures/feier
mv ~/Downloads/feier.zip .
mkdir good bad
unzip feier.zip

Wir werden die schlechten Bilder erst wegwerfen wenn wir mit dem sortieren ganz fertig sind (so vermeiden wir unglückliche Versehen).

Sortieren

Hier steckt die ganze Magie drin:

feh --auto-zoom --scale-down --action1 "mv %f good/" --action2 "mv %f bad/" .

Übersetzt bedeutet das: “Zeige alle Bilder im aktuellen Verzeichnis (.) nacheinander (als Slideshow) an, so gezoomt das man immer das ganze Foto sehen kann. Wenn ich die Taste 1 drücke, verschiebe das aktuelle Bild ins Verzeichnis good, wenn ich 2 rücke verschiebe es nach bad.”

Nette Annehmlichkeiten sind dabei:

  • Wenn man gerade nicht sicher ist, kann man mit den Pfeiltasten einfach zum nächsten Bild springen und die Entscheidung verschieben.
  • Ein Bild, bei dem man eine Wahl getroffen hat wird nicht mehr angezeigt. Sind keine Bilder mehr übrig, wird das Programm beendet
  • Will man unterbrechen, hilft die Taste q, was man bisher sortiert hat bleibt auch sortiert.
  • feh ist zwar schlank und klein, aber zum zoomen und Bilder richtig herum drehen reicht es noch.
  • Wie die meisten Unix-workflows ist auch dieser sehr flexibel. Ideen, die man damit schnell verwirklichen könnte:
    • einen dritten Ordner (bin_nicht_sicher)
    • mehrere Sortierdurchläufe.
    • Photos taggen
  • Das Interface ist so einfach wie nur irgend möglich: Man sieht nur das Bild und hat genau 2 Tasten für 2 Möglichkeiten.
  • Es geht schnell. Wenn man mal ein bisschen drin ist hat man schnell einige Hundert Bilder sortiert.

Nachbereitung

Zum Schluss (und wenn man sich sicher ist) wirft man die schlechten Fotos weg und behält die guten:

rm bad/* -f
mv good/* .
rmdir good bad

Bilder von hier und hier.

Hörbücher auf SailfishOS

Unterwegs höre ich sehr gerne Hörbücher - besonders in vollen öffentlichen Verkehrsmitteln, wo man ohnehin nicht viel anderes machen kann als Musik/Podcasts/Hörbüchern zu lauschen oder seinen Feedreeder durchzuarbeiten. Auf SailfishOS gibt es keinen nativen Client, aber die Standardapp “Medien” funktioniert wunderbar. Wie ist also der Workflow?

Umweg über den Rechner

Bestimmt geht das auch direkt auf dem Telefon, aber ehrlich gesagt habe ichs noch nicht ausprobiert. Außerdem geht es dank ssh/scp sehr flott auch von der Kommandozeile.

Hörbuch finden

Ich könnte es gar nicht besser zusammenschreiben als es im Wiki Audiobooks Subreddit steht.

Für diesen Blogpost wählen wir The Wrong Box auf Librivox.

Hörbuch herunterladen

Hörbücher sind meistens mehrere Audiodateien, zum Beispiel eine für jedes Kapitel. Meistens bekommt man diese schön kompakt in einer zip-Datei, die lädt man herunter und entpackt sie. Manchmal sieht man aber auch nur eine Website voll mit Links zu dein einzelenen Dateien (wsl für Leute, die alles direkt im Browser konsumieren wollen). In diesem Fall hilft dieser Befehl.

lynx -dump https://librivox.org/the-wrong-box-by-robert-louis-stevenson-and-lloyd-osbourne/ | grep 64kb.mp3$ | awk '{print $2}' | xargs -n1 wget

In Worten: Schau dir alle Links der genannten Webseite an, nimm die die auf “64kb.mp3” enden und lade sie einzeln herunter. (Es könnte also schlau sein, das in einem leeren Ordner auszuführen.)

Bei librivox ist das aber eigentlich nicht nötig, man kann alles direkt herunterladen (sogar per Torrent, wohooo!).

Es macht übrigends alles (erheblich) einfacher, wenn die Dateien so benannt sind, dass die alphabetische und die logische Ordnung übereinstimmen.

ssh aufs Telefon

Testweise kann man sich schonmal aufs Telefon verbinden und den Ordner anlegen, wo die Dateien später liegen sollen. Ssh muss in den Einstellungen des Telefons unter “Entwicklermodus” aktiviert werden, dort findet man auch Passwort und IP-Adresse.

ssh nemo@192.168.178.29
mkdir Music/wrong_box

Hörbuch aufs Telefon

Da wir ja jetzt schon alles vorbereitet haben, reicht ein kurzes Befehl:

scp *.mp3 nemo@192.168.178.29:/home/nemo/Music/wrong_box

Das wars schon.

Hören

Wir können alles in der Medien-App anhören. Nach dem aktuellen Kapitel wird automatisch zum nächsten gesprungen.

Firefox History in der Kommandozeile

Firefox ist so bekannt geworden, weil man alles mögliche an ihm einstellen kann. Warum ist es dann so schwer, ihn von der Kommandozeile zu steuern?

Ich würde wirklich gerne ein paar Skripte schreiben, welche die aktuell geöffneten Seiten von Firefox auswerten (zum Beispiel um die aktuelle Seite in eine Liste einzutragen, einen Eintrag in meinen Passwortmanager zu machen oder ähnliches).

Leider ist das scheinbar sehr schwierig, denn dieser riesige Kloß von einem Browser kann scheinbar nicht nach außen kommunizieren (Ich arbeite gerade mit Mozilla Firefox 46). Folgenden Notbehelf habe ich gefunden:

Die neuste Seite ist aktuell

Ich nehme vereinfachend an, dass ich mich nur für die Seite interessiere, die als letztes aufgerufen wurde. Dann muss man nur in der Firefox History nachschauen, welche Seite die letzte war und sie ausgeben.

Warum ist das leichter? Firefox speichert seine History, Bookmarks und noch ein paar andere Dinge in einer sqlite Datenbank: $HOME/.mozilla/iwfal82r.default/places.sqlite. (Der Teil vor “default” sieht jedes mal ein bisschen anders aus, aber das findet man schon. Im Folgenden benutze ich ein Regexsternchen, so dass die Befehle bei jedem funktionieren sollten.) Da ich ja neulich schon etwas Erfahrung mit Datenbanken gesammelt habe, wage ich mich da mal rein.

So sieht eine Datenbank von innen aus

In der Datenbank

sqlite3 $HOME/.mozilla/firefox/*.default/places.sqlite

SQLite version 3.13.0 2016-05-18 10:57:30
Enter ".help" for usage hints.
sqlite>

Wir sind jetzt in der Datenbank (raus kommen wir mit Ctrl-D). Erstmal schauen wir was es hier für tables gibt:

sqlite> .tables
moz_anno_attributes  moz_favicons         moz_items_annos    
moz_annos            moz_historyvisits    moz_keywords       
moz_bookmarks        moz_hosts            moz_places         
moz_bookmarks_roots  moz_inputhistory  

Die Tabelle die wir brauchen ist die moz_places. Hier ist unsere gesamte Browserhistory drin (habe ich hier rausgefunden). Wir schauen uns die Spalten der Tabelle an:

sqlite> pragma table_info(moz_places);
0|id|INTEGER|0||1
1|url|LONGVARCHAR|0||0
2|title|LONGVARCHAR|0||0
3|rev_host|LONGVARCHAR|0||0
4|visit_count|INTEGER|0|0|0
5|hidden|INTEGER|1|0|0
6|typed|INTEGER|1|0|0
7|favicon_id|INTEGER|0||0
8|frecency|INTEGER|1|-1|0
9|last_visit_date|INTEGER|0||0
10|guid|TEXT|0||0
11|foreign_count|INTEGER|1|0|0

Für uns sind url und last_visit_date wichtig (denn wir wollen ja die URL, die zuletzt aufgerufen wurde). Wir tasten uns mal langsam ran:

Alle URLS, die ich je aufgerufen habe

Alphabetisch sortiert.

sqlite> select url from moz_places;
...
Alle URLS, die ich je aufgerufen habe

Nach Datum sortiert.

sqlite> select url from moz_places order by last_visit_date;
...
Wann die letzte URL aufgerufen wurde
sqlite> select max(last_visit_date) from moz_places;
1464029535578940

Hmm, eigentlich sollte hier ein Datum stehen. Laut table_info ist dieses als Integer kodiert. Das Internet hilft weiter.

sqlite> select max(last_visit_date) as raw_visit_date,datetime(last_visit_date/1000000,'unixepoch') from moz_places;
1464029535578940|2016-05-23 18:52:15

Sieht doch gleich viel besser aus, die ISO 8601 lebe hoch. Aber irgendwie ist das um zwei Stunden falsch? Ach ja, Zeitzonen.

sqlite> select max(last_visit_date) as raw_visit_date,datetime(last_visit_date/1000000,'unixepoch','localtime') from moz_places;
1464029535578940|2016-05-23 20:52:15

Geht doch.

Eigentlich brauchen wir diese schick formatierten Strings aber gar nicht, wir wollen ja nur nach Zeit sortieren. Deswegen orientieren wir uns am ersten Versuch.

Die URL, die ich als letztes besucht habe

Genau genommen fragen wir eher nach allen urls, die zu dem Zeitpunkt aufgerufen wurden, an dem wir zuletzt eine url aufgerufen haben.

sqlite> select url from moz_places where last_visit_date=(select max(last_visit_date) from moz_places);
http://www.schauderbasis.de/

Hurra, es funktioniert!

Für Skripte

Damit wir uns nicht ständig in sqlite einloggen müssen, kann man das auch von außen tun.

$ sqlite3 $HOME/.mozilla/firefox/*.default/places.sqlite "select url from moz_places where last_visit_date=(select max(last_visit_date) from moz_places)"
http://www.schauderbasis.de/

So, da ist sie. Die letzte besuchte Url. Das funktioniert, auch sofort nach dem Aufrufen der Url oder wenn der Firefox aus ist.

Bilder von hier und hier

An der Weboberfläche kratzen

Ich mag Programmieren, aber mit Netzwerk, Browser, Javascript und Webseiten kenne ich mich nicht gut aus. Wenn ich dann einen Fuß ins kalte Wasser halte, ist es schon spannend (für mich). Hier mein jüngstes Erlebnis:

Bilder in Ghost

Meine Freundin hat, wie ich, einen Ghostblog. Anders als ich schreibt sie dort regelmäßig und oft, mit vielen Bildern über Abenteuer in der Küche. Neulich konnte sie plötzlich keine Bilder mehr hochladen.

Something went wrong

Fehlerjagd

Fehler eingrenzen:

  • Die Fehlermeldung ist wenig hilfreich.
  • So wenig hilfreich, das man nicht mal sinvoll danach googlen kann.
  • Till und ich haben Blogs auf dem gleichen Server, können aber Bilder hochladen.
  • Auf Sandras Blog kann man keine Bilder hochladen, egal ob von ihrem oder meinem Account.
  • Firefox, Safari oder Chrome - kein Unterschied
  • Verschiedene Dateitypen oder kleinere Bilder ändern nichts an der Fehlermeldung.
  • Die offizielle Ghost Dokumentation ist lausig. Immerhin gibt es einen sehr kurzen Abschnitt über Image upload issues. Nichts Hilfreiches. Das angesprochene Cloudflair benutzen wir nicht.

Ideen, woran es liegen könnte:

  • Sandras Blog ist von allen mir bekannten Ghostblogs der mit dem meisten Content, insbesondere der mit den meisten Bildern. Vielleicht gibt es da irgendwo ein Quota, dass erreicht ist?
  • Sandras Blog ist der mit dem Umlaut in der url (“Gewürzrevolver”). So bitter es ist, das hat bis jetzt einige Probleme gemacht. Liegt es vielleicht daran?

Mehr kann ich jetzt alleine nicht rausfinden, ab hier brauche ich Ansprechpartner.

Mal fragen

Ich befrage Till (der Herr über den Server) und den Ghost Slack Channel help, wo ein Kevin mir freundlich zur Seite steht.

“Gibt es auf unserem Server irgendeine Begrenzung des Speicherplatzes?”

Nein, Till weiß von keinem Quota und ein mysteriöses künstliches Quota bei Ghost scheint auch nicht zu existieren.

“Wo soll ich nach Fehlern suchen?”

Schau mal in den Web Inspektor.

Wie immer, wenn ich mit dem Support spreche google ich nebenbei, was die Antworten bedeuten. Den Webinspektor ist das Tor in die Javascript-Hölle. Here be dragons. Aber here be also a log of what happens in your browser when you interact with a website.

Webinspektor öffnen

Ich öffne also den Webinspector und versuche, ein Bild auf den Blog hochzuladen. Tatsächlich finde ich nach ein bisschen herumsuchen eine Fehlermeldung.

So sieht ein Fehler auf einer Webseite aus

Die Fehlermeldung

Die Fehler kommt in Form eines JSON Objektes, die entscheidende Zeile ist:

EACCES, open '/var/www/ghost/revolver/content/images/2016/04/Organigram-svg.png'

Sehr hilfreich sieht das erstmal nicht aus. Aber wenn man mal schaut, was EACCES überhaupt heißt, bekommt man heraus dass es sich wohl um einen permission error in dem angegebenen Ordner handelt. (Diese Schlussfolgerung zieht eigentlich der hilfreiche Kevin aus dem Ghost Chat, ich plappere das nur fleißig nach).

Also nochmal dem Till geschrieben, mit der Bitte die Rechte in dem Ordner zu checken und - tatsächlich, das war es. Der Upload funktioniert jetzt wieder und Sandra kann ihren neuen Blogpost mit Bildern ausstatten (Spargel, Huäääääääh!).

Abschliessende Gedanken:

  • Fehlermeldungen sollten immer aus zwei (!) Teilen bestehen: Eine technische (für den Entwickler) und eine menschenlesbare für den User.
  • “Something went wrong.” ist keine gute Fehlermeldung. Da ist keine nützliche Information drin. Dass es nicht geklappt hat sieht der User auch so.
  • Der Fehlersuche war nicht qualvoll und nervig, denn alle waren geduldig und haben sich professionell verhalten. So macht das Spaß, danke an Till und Kevin.
  • Wie so oft bei Computerproblemen gilt: Wenn du noch nicht wirklich selbst versucht hast, das Problem zu lößen, dann ist es nicht angebracht anderer Leute wertvolle Zeit dafür in Anspruch zu nehmen.
  • Keiner weiß, wie das mit den Rechten passiert ist (mit den Rechten weiß man das nie so recht). Till war es nicht und auch sonst keiner. Auf dem Server spukt es.

(Titelbild von hier, Pixabay ist eine tolle Quelle für freie Bilder)

ping Datenbank

Pingplot war als Vorbereitung für ein etwas größeres Projekt gedacht, für das ich eine Datenbank einsetzen möchte. Also sollte ich erst mal lernen, wie man mit Datenbanken arbeitet.

Tatsächlich habe ich am Ende etwas mehr gelernt als gedacht und ein bisschen älteres Wissen aufgefrischt.

Grundidee

Daten, die laufend generiert werden sollen gesammelt und visualisiert werden. Zum Üben nehme ich den Ping zu einer Website. Der eignet sich weil es ein beständiger Strom von nicht zufälligen, aber auch nicht voraussagbaren Datenpunkten ist.

Es wird 4 zentrale Programme in unserem Setup geben:

  1. Die Steuerzentrale
  2. Die Datenquelle
  3. Die Datenbank
  4. Die Datenaufbereitung

Mir ist wichtig, das am Ende alles auf Knopfdruck funktioniert. Der Befehl, einen Plot zu erstellen ist nur ein Befehl sein und es ist keine weiteres Eingreifen meinerseits notwendig, erst recht kein hin- und herkopieren von Daten. Dieses Prinzip hat sich bei meiner Bachelorarbeit extrem gut bewährt - irgendwann drückt man nur noch auf den Knopf und hat etwas später 50 Graphen und Diagramme, die man analysieren kann.

Die Steuerzentrale - Gnu Make

Als ich zum ersten mal ein Makefile benutzt habe war ich wirklich begeistert von der Idee: Wenn man in einem Directory ohnehin immer wieder das gleiche macht, kann man das auch automatisieren. Und tatsächlich habe ich beim Programmieren immer ein Terminal laufen, in das ich permanent die selben Sachen eingebe:

  • compilieren
  • testcase mit den einen Parametern
  • testcase mit den anderen Parametern
  • Zwischenergebnisse aufräumen, um sie neu zu erstellen
  • git
  • temporäre Dateien aufräumen– Ups, da war was Wichtiges dabei :(

Stattdessen schreibt man ein Makefile, indem das alles vorformuliert ist und gibt dann nur noch Befehle wie:

make compile

oder

make plot

Dank tab-completion geht das schneller und man vertippt sich nicht ausversehen. Ich finde es ja allgemein ganz gut, wenn ein Programm möglichst viel über sich selbst weiß und sich selbst quasi selbst organisiert (Solange klar ist, das ich noch der Chef bin - die Apple-Lösung mit diesen Mediathekformat, in das man nicht reinschauen kann).

Die Syntax von Makefiles ist erstmal sehr einfach. Man schreibt das target auf, einen Doppelpunkt dahinter - und danach eingerückt die Befehle, die ausgeführt werden sollen wenn das target aufgerufen wird.

plot:
	gnuplot graph.plot
	feh --reload 1 ping.png &

Mehr muss man erstmal nicht wissen.

Die Datenquelle - ein kurzes Shell-Skript

Um den Ping zu einer Website herauszufinden, reicht ein einfaches

$ ping www.schauderbasis.de
PING www.schauderbasis.de (5.45.107.67) 56(84) bytes of data.
64 bytes from v22013121188416155.yourvserver.net (5.45.107.67): icmp_seq=1 ttl=61 time=29.9 ms
64 bytes from v22013121188416155.yourvserver.net (5.45.107.67): icmp_seq=2 ttl=61 time=37.2 ms
64 bytes from v22013121188416155.yourvserver.net (5.45.107.67): icmp_seq=3 ttl=61 time=28.2 ms
...

Uns interessieren die Werte zwischen time= und ms. Um die herauszubekommen hat für mich folgendes funktioniert:

  • Nur noch ein Wert stat unendlich viele:
$ ping -c 1 www.schauderbasis.de
PING www.schauderbasis.de (5.45.107.67) 56(84) bytes of data.
64 bytes from v22013121188416155.yourvserver.net (5.45.107.67): icmp_seq=1 ttl=61 time=29.8 ms

--- www.schauderbasis.de ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 29.865/29.865/29.865/0.000 ms
    
  • Nur noch die zweite Zeile, wo die wichtige Information drin steht:
$ ping -c 1 www.schauderbasis.de | sed -n 2p
64 bytes from v22013121188416155.yourvserver.net (5.45.107.67): icmp_seq=1 ttl=61 time=28.9 ms
  • Davon die achte Spalte
$ ping -c 1 www.schauderbasis.de | sed -n 2p | awk '{print $8}'
time=29.1
  • Und dann alles ab dem sechsten Buchstaben:
$ ping -c 1 www.schauderbasis.de | sed -n 2p | awk '{print $8}' | cut -c 6-
29.6

Wunderbar.

Mehr Werte

Damit wir nachher eine ordentliche Datenbasis haben, wollen wir viele Werte hintereinander generieren. Eigentlich macht das ping ja schon selbst, aber wir bauen uns hier eine eigene Schleife, so das wir Daten sofort einlesen können.

Optionale Argumente (wusste ich vorher auch nicht) gehen so:

# number of datapoints to generate: take first argument or 10 as default
n=${1:-10}
# sleeptime: take second argument or 1 as default
t=${2:-1}

Am Ende (mit ein bisschen Zeug aus dem nächsten Abschnitt) sieht das ganze so aus.

database_name="pingDB"
table_name="pingtimes"
url="www.schauderbasis.de"
dbdo="mysql -u root -s $database_name -e"

# number of datapoints to generate: take first argument or 10 as
# default
n=${1:-10}
# sleeptime; take second argument or 1 as default
t=${2:-1}

for i in `seq $n`
do
    pingtime=$(ping -c 1 $url | sed -n 2p | awk '{print $8}' | cut -c 6-)
    $dbdo "insert into $table_name (Zeitpunkt, URL, Ping) values (NOW(), '$url', $pingtime);"
    sleep $t
done

Gar nicht mal so hässlich, von bash bin ich schlimmeres gewohnt.

Die Datenbank - MariaDB

Es gibt verschiedene Datenbanken für verschiedene Zwecke. Ich habe mich für MariaDB entschieden, hauptsächlich wegen dem Artikel im Arch-Wiki zum aufsetzen und dem Tutorial auf der Website von MariaDB, das mit genau so viel Information gegeben hat wie ich als blutiger Anfänger brauchte.

Beim Lernen hat mir wirklich sehr geholfen, das ich mit einem Makefile arbeite. So konnte ich einfach Zeilen wie diese eintragen:

database_name = pingDB
table_name = pingtimes
general_do = mysql -u root -e
dbdo = mysql -u root $(database_name) -e

prepare_database:
	$(general_do) "create database if not exists $(database_name)"

prepare_table:
	$(dbdo) "create table if not exists $(table_name) (Zeitpunkt TIMESTAMP, URL VARCHAR(30), Ping FLOAT UNSIGNED)";

show_table:
	$(dbdo) "select * from $(table_name)"

Was man sich aufgeschrieben hat, kann man schon mal nicht wieder vergessen.

Tatsächlich ist die SQL-Syntax gar nicht so schlimm, solange man relativ einfache Anfragen stellt. Das war bei mir zum Glück der Fall und das bisschen was ich brauchte konnte ich dann auch relativ flott auswendig.

Am Ende hatte ich eine Datenbank mit einer Tabelle, die (mit dem Skript von oben) so aussah:

$ make show_table
mysql -u root pingDB -e "select * from pingtimes"
+---------------------+----------------------+------+
| Zeitpunkt           | URL                  | Ping |
+---------------------+----------------------+------+
| 2016-01-25 16:56:40 | www.schauderbasis.de | 29.8 |
| 2016-01-25 16:56:41 | www.schauderbasis.de | 30.1 |
| 2016-01-25 16:56:42 | www.schauderbasis.de | 29.0 |
| 2016-01-25 16:56:43 | www.schauderbasis.de | 32.2 |
| 2016-01-25 16:56:44 | www.schauderbasis.de | 28.8 |
| 2016-01-25 16:56:45 | www.schauderbasis.de | 29.6 |
| 2016-01-25 16:56:47 | www.schauderbasis.de | 30.1 |
| 2016-01-25 16:56:48 | www.schauderbasis.de | 29.8 |
| 2016-01-25 16:56:49 | www.schauderbasis.de | 28.6 |
| 2016-01-25 16:56:50 | www.schauderbasis.de | 29.2 |
+---------------------+----------------------+------+

Die Datenaufbereitung - Gnuplot

Eigentlich kam für mich kein anderes Tool in Frage, Gnuplot passt einfach zu gut. Ich habe schonmal was zu verschiedenen Plottern aufgeschrieben und hier war die Entscheidung klar.

Das schwierigste war die Frage, wie man die Daten aus der Datenbank in Gnuplot hinein bekommt. Gut das Gnuplot alles kann:

# Output from mysql is normaly formated as ascii-boxes,
# with the flag -B it is just tab-separated.
set datafile separator "\t"

plot '< mysql -u root -B pingDB -e "SELECT Zeitpunkt, Ping FROM pingtimes;"' using 1:2

Im Prinzip wird hier die SQL-Abfrage direkt von Gnuplot ausgeführt. Kein Problem.

Es ist gar nicht so klar, wie das mit der Zeit eingelesen werden soll. SQL liefert das Datum und die Uhrzeit schön nach ISO 8601: 2016-01-25 16:56:40

Gnuplot kommt von klugen Leuten, die wissen dass es auf der Welt sehr viele sehr schlimme Formate gibt, in der Leute die Zeit angeben. Deswegen gibt man einfach an, in welchem Format das Datum eingelesen und ausgegeben werden soll:

# time format used for reading input
set xdata time
set timefmt "%Y-%m-%d %H:%M:%S"

# time format used for printing on axis
set format x "%H:%M:%S"

Einfacher geht es nicht. Eine Aufschlüsselung der Variablen (falls nötig) gibt es im hervorragenden Handbuch. Es scheint aber das gleiche Format zu sein wie bei dem Programm date, also reicht wsl auch die entsprechende manpage.

Jetzt ist nur noch die Frage, wie der Graph aussehen soll. Ich habe mich entschieden, die Werte interpolieren zu lassen, damit der Graph schön glatt ist. Das Stichwort hier heißt smooth, man sollte es in Gedanken aber immer smooooooooth aussprechen.

Und das wars

Eigentlich ziemlich einfach, hier funktionieren ein paar mächtige Werkzeuge sehr gut zusammen. Es hat Spaß gemacht und ich habe jede Menge über wichtige Standardwerkzeuge gelernt.

Der Code liegt hier zur freien Verfügung (mit freier Lizenz natürlich).

Gedanken zum Projekt

  • Für so ein kleines Projekt würde man normalerweise keine riesige Datenbank anschmeißen. Matthias meinte, dass die meisten Leute die nicht wissen welche Datenbank sie benutzen sollen mit sqlight wahrscheinlich am besten bedient sind.
  • Bash ist eine furchtbare Programmiersprache. Aber leider sehr nützlich.
  • Ich weiß nicht wer sich ausgedacht hat, dass Variablen in Make und bash fast, aber nur fast gleich aussehen und funktionieren. Was soll das?
  • Ich war erst ein bisschen genervt, dass man in SQL immer brüllen muss: “CREATE TABLE IF NOT EXISTS pingtimes”. Dann habe ich gemerkt, dass das gar nicht notwendig ist - die Sprache ist case insensitive: “create table if not exists pingtimes”. Manche Sachen (zum Beispiel die Datentypen) habe ich trotzdem in Caps gelassen, das sah irgendwie richtiger aus.
  • Wenn ich cooler wäre würde ich einen Cronjob einrichten, der das Skript regelmäßig anstößt (~alle 5 Minuten?). Das könnten interessante Graphen sein.
  • Mit wenig Aufwand könnte man das Skript umbauen, so dass andere Werte aufgezeichnet und verarbeitet werden. Zum Beispiel:
    • die Batterie (Wie viel Prozent habe ich im Schnitt noch übrig?)
    • RAM und CPU
    • Wie viele Wlans verfügbar sind (verschlüsselt vs. unverschlüsselt?)
  • Nachdem ich viel im Internet nach Gnuplotschnipseln gestöbert habe entdeckte ich gegen Ende des Projektes, dass Gnuplot ein hervorragendes und ausführliches Handbuch mit vielen Beispielen und Bildern hat. Nächstes mal weiß ich das vorher.
Musik hören

Wenn man irgendwann seine Musik gefunden hat, weiß man recht genau was einem gefällt (bei mir ist es Soundtrack Musik). Woher bekommt man die jetzt? Da fallen einem spontan mehrere Wege ein:

  • kaufen
  • piratisieren
  • im Radio hören
  • Streamingdienste
  • Konzerte
  • freie Musik

Gehen wir da mal kurz durch.

kaufen

Ich habe keine Lust, mir eine große Musiksammlung anzulegen, indem ich einzelne CDs oder Alben kaufe. Das ist teuer und umständlich - und man hört immer wieder das selbe. Falls mich mal einzelne Lieder wirklich wegflashen mache ich das gerne.

piratisieren

Mag ich nicht. Das muss jeder erstmal mit sich selbst ausmachen.

Radio

Quelle: https://pixabay.com/en/radio-retro-transistor-radio-old-543122/

Radio nervt mich, wegen Werbung und Moderatoren. Für Musik habe ich noch keinen Radiosender gefunden, der mich nicht nach kürzester Zeit genervt hat. Aber es gibt ja auch noch Internet Radio… Hier wird es interessant:

Internetradio

Internet Radio besticht auf mehreren Ebenen:

  • Keine Werbung: Die meisten Sender beschränken sich darauf, den Sendernamen alle halbe Stunde zwischen zwei Liedern in den Namen des Senders zu sagen.
  • Auswahl: Es gibt ja soooooo viele Internet Radio Sender. Wer einen weiteren aufmachen will muss ja auch Frequenzen aufkaufen - es reicht eine IP-Adresse. Ich persönlich mag das Soundtrackradio.
  • skriptbar: Oh ja, da geht viel. Unter anderm werden auch stets die Metadaten (zum Beispiel Name des Stücks, Komponist, Interpret…) mit übertragen. Hier sei auf jeden Fall die Software streamripper erwähnt. Sie gehört zu den großen Schätzen in meiner Software-Repertoire.
  • Clients: Es gibt quasi keinen Musikplayer, der mit Internetradio nichts angangen kann. Man hat also freie Auswahl.

Wenn ich am Computer Musik hören will ist es also mit dieser Zeile getan:

mpd; mpc add http://209.9.229.206:80; mpc play

(Naja, eigentlich steht die IP-Adresse in /etc/hosts und für die Zeile gibt es einen Alias.)

Streamingdienste

Zu Streamingdiensten (abseits von Internetradio) habe ich nie einen echten Zugang gefunden. Bestimmt ist das toll für viele, ich habs nie für mich entdeckt.

Konzerte

Zählt nicht. Und selbst musizieren auch nicht. Livemusik hat andere Regeln, hier geht es um Musik, die sich in den Alltag integrieren lässt.

Freie Musik

Und dann gibt es da noch die freie Musik - Musik unter freien Lizenzen. Das macht es natürlich schön unkompliziert: Stücke aussuchen und runterladen und immer dann hören, wenn man mag.

Es ist halt nicht so leicht, die zu finden. Ein guter Startpunkt kann die Website Jamendo sein. Dort habe ich auch die Grundlage für das Intro der Echokammer gefunden.

Fazit

Ich höre Musik beim kochen, beim essen, beim Programmieren und auch dazwischen. (Unterwegs höre ich Podcasts). Und eigentlich ist höre ich immer Internetradio, das funktioniert für mich einfach am besten.

Gewürzrevolver

Der Blog meiner Freundin, es geht ums Kochen und Backen. Alle Rezepte haben wir selbst gekocht und probiert und dabei die Fotos gemacht. Und ich hatte sogar mal einen Gastbeitrag.

Tills Blog

Wenn man über Tech-Trends Bescheid wissen will, kann man sich eigentlich immer an Till wenden. Der Blog ist klasisch als ein persönliches Logbuch gehalten. Aber keine Angst: Genau wie ich ist Till meistens zu faul zum bloggen und man wird nicht von Posts überschwemmt.

LichtEmitter

Andi studiert was mit Strom und schreibt in seinem Blog übers basteln mit LED-Streifen, Lötkolben und Microkontroller. Außerdem hat er den Anspruch, alle Posts zweisprachig zu schreiben und hat das irgendwie in Ghost reingefummelt, so dass es gut aussieht. Ich weiß bis heute nicht wie er das gemacht hat.