0xfefe: Danke für Nichts (Post mortem)

Der eine oder andere hat vielleicht schonmal von Fefe’s Blog gehört. Das ist eine Blog-Installation, die durch die Person Felix von Leitner mit regelmäßigen Inhalten gefüllt wird. Ich weiß nicht wann ich zum ersten Mal mit dem Blog in Berührung gekommen bin, aber das muss so um den 27c3 herum gewesen sein. Ich bin zum ersten Mal mit Inhalten von Fefe konfrontiert worden im Rahmen der Fnord News Show bzw. der Fnord Jahresrückblick 2009 auf dem Chaos Communication Congress 26c3 (mein erster Congress).

Als ich zum Zeitpunkt des 27c3 ein Jahr später Langeweile hatte, begann ich während wir mit einigen CCC’lern dem 27c3 per Videostream beiwohnten, eine kleine iOS App zu basteln, die Inhalte von Fefe’s Blog per RSS-Feed abholen und anzeigen sollte. Die erste primitive Version funktionierte bereits gegen Ende des 27c3 auf meinem Development iDevice, damals noch ein iPhone 3GS.

Nachdem die App einigermaßen stabil lief, packte ich die einfach kostenlos in den AppStore. Zu dem Zeitpunkt war ich ein eher schlechter iOS Developer (weil noch Anfänger in Sachen iOS) und ich habe iOS an einigen Stellen absolut nicht verstanden. Die App lief zwar, aber sie hatte einige extrem CPU-ineffiziente Stellen, da ich ein paar fancy Animationen haben wollte und die Renderingmechanismen bis zur Unkenntlichkeit falsch benutzt habe.

Die Fefe App (2010)

Hier ein Rückblick auf die erste Version der App die so um 2012 existierte und durchaus eine recht lustige User Experience bot durch die fancy Animationen:

Launch Screen Postingübersicht Posting mit Kommentaren Farbschema grün Farbschema Cyan

All diese runden Gebilde drehte sich in sich selbst und es gab ein herrlich dynamisches Gesamtbild. Man beachte, dass es zu dieser Zeit Kommentare zu Fefe’s Blog gab über eine nicht zum Blog selbst gehörende URL als Service refefe (http://blog.refefe.de/rss.xml). Das heisst Leute konnten da extern kommentieren und als ich das mitbekommen hatte, hab ich die Kommentare natürlich ebenfalls in der App angezeigt.

Aufgebaut hatte den re:Fefe-Service (vermutlich auch aus blossem Spass an der Freud) Linus Neumann. In 2013 hielt Linus zusammen mit anderen dazu einen recht empfehlenswerten und kurzweiligen Vortrag mit dem Titel „Die Trolldrossel (Erkenntnisse der empirischen Trollforschung)“ (hier bei Youtube).

Später bekam Linus für diese Aktion noch eine Abmahnung von Fefe’s Anwalt (zumindest sah das für Außenstehende so aus) das Schreiben (Seite 1, Seite 2, Seite 3) schaut zunächst ernstgemeint aus, aber das Veröffentlichungsdatum 1. April sollte bereits stutzig machen.

Und so berechtigt war es dann auch die Echtheit zu bezweifeln. Die Aufklärung zu dem Schreiben wurde auf der Anwaltsseite selbst veröffentlicht mit dem Wortlaut:

[…] Nachdem die Trollkommentar-Datenbank bemerkenswerte Ausmaße annahm und damit repräsentative Auswertung erlaubte, war es an der Zeit, das re Fefe-Blog würdig zu beenden.

Ein bloßes Abschalten hätten jedoch die Trolle nicht verstanden und als Zensur bewertet. Zudem konnte niemand voraussagen, wie die Trolle auf einen kalten Entzug reagieren würden. Um sich aus der Schusslinie zu nehmen, bat mich Linus um einen anwaltlichen False Flag-Angriff in Form einer 1.April-Abmahnung, die gegenüber den Trollen das Abschalten „erklärte“. Fefe war natürlich eingeweiht und einverstanden. […]

Der ReFefe-Service und die Kommentare wurden dann im April 2014 eingestellt mit Hinweis auf das Fake-Anwaltsschreiben mit dem folgenden Hinweis:

Da mir rechtliche Konsequenzen drohen, muss ich diese Seite leider schließen.
Mein Anwalt rät mir, mich nicht zum laufenden Verfahren zu äußern.
Ich hoffe ihr habt dafür Verständnis.

Mich hat damals – als ich begann Fefe’s Inhalte zu besuchen – denke ich die reine Sensationslust zu diesem Blog getrieben. Ich fand die Art und Weise wie dort polarisiert wurde vermutlich anziehend. Heute würde ich sagen, es war viel mehr mein Ego das von diesem Blog angezogen wurde. Das Ego, das nach einfachen Lösungen nach klaren Bewertungen, nach Empörung gesucht hat, um sich sein eigenes vielfach negatives Weltbild zu verstärken. Ich war unwissend. Mein Blick war verstellt. Mein Unbewusstsein hat es geschehen lassen, dass ich für dieses Blog eine App erstellt habe, die möglicherweise sogar noch zu dessen Popularität beigetragen hat (ebenso wie übrigens Re:Fefe).

Primär hatte mich eigentlich nur interessiert, iOS Aps zu entwickeln und die Möglichkeiten des iDevice auszureizen. Ich wollte mich optisch mit dem Userinterface alternativ ausprobieren und zugleich ein wenig mit CoreGraphics und CoreAnimation – zwei wichtigen iOS Frameworks – Spass haben. Rückblickend bedauere ich es sehr, für dieses Blog eine App entwickelt zu haben.

Nunja die Zeit ging ins Land, da die App funktionierte, bekam sie lange Zeit kein Update. iOS 7 brachte dann den großen UI-Style-Wechsel in UIKit und es war notwendig alle Apps anzupassen. Da ich eine Menge eigener Apps anpassen musste, nahm ich das zum Anlass eine zweite Version der App zu entwickeln und die Fefe App damit ebenso an den neuen Stil anzupassen. Diesmal, um meine Learnings im iOS Development einzubringen und das UI deutlich effizienter und performanter zu bauen. Für mich war es wieder eher die technische Challenge die mich erneut dazu trieb die App zu erweitern.

Die 0xfefe App (2014)

Es entstand die 0xfefe App, die App im Store wurde also auch umbenannt von Fefe in 0xfefe. Ziel der neuen Version war zugleich, die App nicht mehr ausschließlich an Fefe’s Blog zu koppeln. Stattdessen sollte die App beliebige RSS-Feeds als Quelle nutzen können. Diese App war daher in der Lage, jede beliebige RSS-Feed-URL als Konfiguration zu verwenden und den Feed dahinter anzuzeigen. Das ließ sich über die iOS Settings konfigurieren und war auch meine technische Rückversicherung, falls Apple die App wegen der Inhalte ablehnen sollte. Wär die App abgelehnt worden, hätte ich einfach einen anderen RSS-Feed integriert und den Nutzern einen Hinweis eingeblendet, wie sie ihr Lieblingsblog selbst konfigurieren könnten.

In der Praxis, haben allerdings lange nicht alle RSS-Feeds so gut mit der App funktioniert, wie der Feed von Fefe’s Blog, was daran lag, dass viele der RSS-Feeds da draussen im Web keine Full-Content-Feeds sind. Ich selbst hab nur während der Entwicklung andere Feeds konfiguriert, um zu testen, ob alles damit klar geht. Im täglichen Betrieb hatte ich nie eine andere URL konfiguriert.

Die zweite Version der App war letztlich ein weitreichender Rewrite. Das gesamte UI wurde neu geschrieben und auch um eine SoundEngine mit vielen lustigen Sounds bereichert. Es gab Favoriten und Statistiken und umfangreiche Konfigurationsoptionen. Viele neue Farbschemata kamen hinzu (inklusive eines Tageslicht-Scheme; das früh die Dark-/Light-Theme Features die heute normal sind vorwegnahm), und die fancy Animationen der Post-Entry-Buttons wurden auf CoreAnimation-konforme Technik umgestellt, die nur einen winzigen Bruchteil der vorherigen Performance schluckte.

Wem einige der App Sounds bekannt vorkamen, der hat vielleicht bemerkt, dass ich einige Sounds aus einer Flash-Datei extrahiert hatte, die damals von Kim Schmitz (alias Kimble) auf seiner Webseite kimvestor abrufbar war. Ich fand die Sounds so schön futuristisch und da es mir ja lediglich um ein Spassprojekt ging, hab ich da auch beherzt reverse-engineered, um die Sounds aus der kimvestor-flash-Datei zu extrahieren.

Hier ein Überblick über die App Version 2:

Postingübersicht Posting Favoriten Statistik Einstellungen

Wie man in den Screenshots sehen kann, kamen eine Menge nützlicher Features hinzu. Unter anderem gab es jetzt einen Favoriten-Speicher. Jeder favorisierte Post wurde auf dem iPhone in der App persistent gespeichert und war Volltext-durchsuchbar und -exportierbar. Das war durchaus nützlich, wenn man mal einen Post von Fefe auf die Schnelle gesucht hat.

Ein weiteres schönes Feature, was gar nicht so trivial zu implementieren war, war die Statistik. Die App hat auf Wunsch eine Statistik über Verweilzeiten und Abrufzahlen geführt und ausschließlich lokal gespeichert (da wurde auch nie irgendwas aus der App jemals „nach Hause telefoniert“). Diese Statistik wurde dann fein in einem Tortendiagramm animiert aufbereitet. Es kann zuweilen erschrecken wenn einem die Statistik belegt, wieviel Lebenszeit man der App gewidmet hat. Ich werde meine persönliche Nutzungsstatistik weiter unten in meinem Fazit veröffentlichen.

Das Ende der App (2019)

Das Jahresende 2019 sollte dann das finale Ende der App einläuten (zumindest für alle anderen außer mir). Mitbekommen sollte ich das nur indirekt… über einen Post in Fefe’s Blog (den ich hier mal zitiere):

Einige Leser haben mich darauf hingewiesen, dass irgendeine ominöse App-Klitsche gegen Geld auf Android und Apple eine Fefe-App anbietet.

Nein, die App kommt nicht von mir. Nein, die haben vorher nicht gefragt. Nein, ich finde das nicht gut.

Sollte ich dagegen vorgehen? Gute Frage. Muss ich mal drüber nachdenken.

Der Beißreflex ist natürlich da. Auf der anderen Seite verkaufen die kein Abo, und natürlich hat die App nichts, was man nicht auch im Browser hat.

Ich sähe ehrlich gesagt akuteren Handlungsbedarf, wenn jemand eine App mit meinen Inhalten anbietet, die dann Werbung einblendet.

Auf der anderen Seite besteht natürlich die Gefahr, dass ich Nachahmer einlade, wenn ich da jetzt nicht verbrannte Erde hinterlasse.

Alles nicht so einfach. […]

Ein wenig Recherche ergab dann auch, warum es da plötzlich eine solche Interruption gab, denn auf Twitter wurde ich recht schnell fündig:

Ich möchte auf den Post den Fefe dazu schrieb gar nicht mehr groß eingehen (man soll Vergangenes ruhen lassen), aber es ist schlicht nicht wahr, dass Fefe nicht von der App wusste. Denn ich hatte ihm sogar am 2. Januar 2015 im Nachgang des Congress einen echten Brief (so richtig auf Papier) geschrieben an die Adresse die im Impressum steht:

Fefes Blog
c/o Raumfahrtagentur
Gerichtsstrasse 66
D-13347 Berlin

Hier ein Auszug aus dem Brief der an Fefe ging…

Wer sich fragt um welche Sticker es da in dem Brief geht… hier eine Übersicht:

Diese Sticker hatte ich für den Congress in 2014 erstellt und in den Stickerboxen des Congress auch unter die Teilnehmer gebracht. Ich fand das Logo so hübsch, dass ich da paar Sticker von haben wollte.

Persönliches Fazit

Es war von Beginn an ein Fehler mit einer App Fefe’s Blog noch bekannter zu machen und den Zugang dazu auf einem iOS Gerät komfortabel über eine App kostenlos zu ermöglichen. Denn die Inhalte sind meiner Ansicht nach polarisierend, vereinfachend und überwiegend negativer Natur. Sie propagieren eine negative Weltsicht und füttern die empörungssüchtigen Egos der Besucher mittels Zynismus und Schadenfreude. Das lenkt ab von den eigentlich konstruktiven Möglichkeiten sich in der Welt positiv einzubringen. Daher rate ich vom Lesen von Fefe denjenigen ab, die nicht ihre negative Weltsicht (die ihnen ihr Verstand in Form des eigenen Ego präsentiert) weiter verstärken möchten.

Die App war übrigens fast immer kostenlos, bis auf eine Ausnahme, bei der ich Spam-Kommentare durch einen Minimalpreis von 0,79€ eine Zeit lang ausschließen wollte. Aber auch das hab ich dann später gelassen. Auch ein In-App-Purchase gab es mal, aber das war mehr, um IAP auszuprobieren und wurde ebenfalls eingestellt. Leider listet der AppStore einmal angelegte IAP’s für immer und ewig. Mein Pech.

Wer denkt ich hätte damit Geld verdient… der mache sich bitte sein eigenes Bild aus den Umsatz/Gewinn-Zahlen die Apple hier für den Zeitraum 2015 bis heute anzeigt:

Muss enttäuschend sein, wenn man erkennen muss, dass lediglich ca. 1000 Downloads von der App existierten und damit genau 0$ Umsatz/Gewinn gemacht wurden, tja. Was mich eher ärgert, dass die Apps soviele Crashes hatte, LOL.

Ich finde es schade, auf welche Art und Weise die App aus dem Store letztlich verschwand und möchte hier nochmal klarstellen, dass ich die App selbst aus dem Store genommen habe, weil ich keinen Bock auf irgend einen Fefe-Mob hatte, der mir dann eventuell meine anderen (für mich wirklich wichtigen) Apps oder andere Infrastruktur kaputtmacht. Ich hoffe dass der Mensch auf Twitter (den ich im Screenshot da oben verlinkt habe) sich nach seiner Aktion besser gefühlt hat. Er hat sein Ego sicher prima mit neuem Futter versorgt. Schade, denn für alle anderen hat er ein weitgehend ehrenamtlich gepflegtes Stück Software ungeplant deorbit’ed, für 15 minutes of fame!

Ich bin ihm jedoch im nachhinein dankbar für diesen Vorgang und vergebe seinem Ego. Denn für mich persönlich hat der Vorgang einen neuen Weg aufgezeigt, der mir persönlich eine deutlich konstruktivere und positivere Weiterentwicklung ermöglicht, die mir wichtiger ist als eine App die ich als Just-for-Fun-Projekt hatte.

Noch wichtiger ist jedoch, dass ich auch Zeit gewinne. Die App hat mich nicht nur bei der Entwicklung wertvolle Lebenszeit gekostet, sondern insgesamt über 329 Stunden wertvolle Zeit, das sind fast 2 volle Wochen meiner Lebenszeit nur durch das Lesen der Inhalte. Hier ein letzter Blick auf die App, bevor ich sie auch von meinem iDevice für immer heute gelöscht habe:

Letzte Übersicht Prozentuale Nutzung Absolute Zeit der Nutzung Anzahl Favoriten Löschung der App

Ich seh‘ es positiv: Ich hatte fast 10 Jahre meinen Spaß.

Dennoch, ich sage explizit an dieser Stelle „Danke für Nichts!“, denn letztlich hat mich das Blog und seine Postings fehlgeleitet und mich wertvolle Lebenszeit gekostet. Zumindest bin ich u.a. durch diese App ein deutlich besserer App Developer geworden. Und diese App war unter anderem auch die Source Code Grundlage für mehrere Congress Fahrplan Apps die es sonst so vermutlich nie gegeben hätte:

Why do I blog this? Ich schließe jetzt Anfang 2022 u.a. mit einigen Kapiteln meines bisherigen Lebens ab. Nämlich u.a. mit Negativität in jeder Form die meine Aufmerksamkeit in der Vergangenheit bekam. Fefe’s Blog ist für mich persönlich eine Quelle an Negativität. Mein Blick war lange Zeit verstellt das zu erkennen, aber es ist nicht gesund, sich Zynismus und Schadenfreude hinzugeben, oder auch nur seine negativen Erwartungen an die Zukunft verstärken zu lassen die so niemals eintreten müssen. Die Posts in Fefe’s Blog sollen aber Empörungscharakter haben und die negative Weltsicht von Fefe selbst bestärken, um letztlich sein Ego mit einem „Told you so“ zu boosten. Das Blog ist aus meiner Sicht ein Ego-Boosting-Projekt das jeden Besucher erfolgreich trollt. Eine positive Zukunft ist denkbar und möglich und es macht mehr Sinn sein eignes Ego nicht mit Negativität zu füttern und das fremde Ego von Fefe ebenso nicht mit Klickzahlen zu füttern. Man sollte es lassen die ganzen negativen Nachrichten in sich aufzusaugen. Das führt langfristig zu keiner einzigen Verbesserung. TL;DR: „Keep calm… …and don’t read Fefe.“ Andere bewerten das noch deutlich klarer und schrieben das auch nieder.

BaFin: Eine Verpflichtung der Kreditinstitute zur Entgegennahme von Münzgeld besteht tatsächlich nicht

Sicher geht es mir nicht allein so, dass ich zu Hause einige Münzen gesammelt habe… Münzen die bei der Benutzung von Bargeld irgendwie überproportional die Geldbörse ausbeulen und die man zwecks Defragmentierung des eigenen Geldbeutels ab und an beiseite tut.

Ich sammel die jetzt schon einige Jahre. Mein Behälter dafür war jetzt voll und ich dachte ich bring den Kram einfach mal zur Bank. Ja, falsch gedacht, geht nämlich nicht. Jedenfalls nicht wenn die eigene Bank dafür keinen Automat betreibt an dem man das machen kann.

Daher habe ich eine Mail an die BaFin geschrieben. Das ist die Bundesanstalt für Finanzdienstleistungsaufsicht, jene Behörde, die gerade kolossal in ihrer Aufgabe versagt hat den Wirecard Coup rechtzeitig als Betrug zu erkennen und stattdessen fleissig selber mitgezockt hat.

Die Frage

Folgende Frage schrieb ich per Mail an poststelle@bafin.de:

Sehr geehrte Damen und Herren,

ich wende mich mit einem Anliegen an sie von dem ich nicht in meinen kühnsten Vorstellungen gedacht hätte dass es notwendig ist.

Es geht darum dass offenbar alle Banken die Dienstleistungen im Rahmen der Finanzinfrastruktur Deutschlands anbieten, einer Ausnahme in der Teilnahme am Waren- und Güterverkehr unterliegen, die keinem einzigen anderen Marktteilnehmer gestattet wird, denn offenbar gilt derzeit Folgendes bzw. wird von den Banken für sich in Anspruch genommen:

1. Banken dürfen offenbar die Annahme von Bargeld verweigern

2. Banken dürfen offenbar die Annahme von Bargeld sofern sie diese ausschließlich ihren eigenen Kunden anbieten mit saftigen Gebühren belegen

Keinem einzigen anderen Marktteilnehmer ist dieses Vorgehen gestattet, da es Bargeld gegenüber Buchgeld bei jedem Zahlungsvorgang benachteiligen würde. Es würde ein Aufschrei durch Deutschland gehen, wenn der Supermarkt um die Ecke Bargeld(ein)zahlungen mit einer Gebühr belegen würde. Noch absuder wäre es, wenn der Supermarkt nur den Kunden die eine Kundenkarte von ihm haben Bargeld(ein)zahlungen erlauben würde und DENNOCH den eigenen Kunden gebühren für Bargeld in Rechnung stellen würde.

In meinem konkreten Fall möchte ich der Zahlungsmittelinfrastruktur Deutschlands gerne meine über mehrere Jahre gesammelten Münzen (in Form von 1,2,5,10,20,50 Cent sowie 1 und 2 EUR im Gewichtsumfang von einigen Kilogramm) wieder zukommen lassen, damit auch die Gesamtkosten für den Betrieb der Zahlungsmittelinfrastruktur gesenkt werden können, weil z.B. die Bundesbank keine neuen Münzen drucken muss, wenn bestehende den Weg zurück in das Zahlungsmittelsystem finden können.

Doch gerade dies ist bei meiner Bank, der 1822direkt offenbar nicht mit vertretbarem Aufwand möglich. Aktueller Stand: Eine Reise von Bremen nach Frankfurt ist nötig, um aktuell auf vorgesehenem Weg eine Einzahlung vornehmen zu können, da offenbar nur die Frankfurter Sparkasse eine Bargeldeinzahlung von mir als Kunde akzeptiert.

Hiermit wende ich mich an Sie als Vertreterin der Verbraucherrechte gegenüber dem deutschen Bankwesen, und möchte sie dringen bitten hier für eine Lösung zu sorgen.

Konkret:

1. Bitte klären sie mich auf, ob es eine Ausnahmeregel für Banken gibt, von der ich bisher nichts wusste, die Banken zu besonderen Marktteilnehmern erklärt, die NICHT dazu verpflichtet sind Bargeld wie ALLE anderen Marktteilnehmer anzunehmen

2. Bitte klären sie konkret mit meiner Bank 1822direkt (Ein Unternehmen der Frankfurter Sparkasse), auf welchem Weg ein für mich eine Bargeldeinzahlung für oben aufgeführtes Vorhaben möglich ist, OHNE dass hier eine Zahlungsmiteldiskriminierung stattfindet (in Form von zusätzlichen gebühren, oder Ähnlichem)

3. Zusätzlich möchte ich sie bitten, auf eine Regelung hinzuwirken, die verbraucherfreundlich ist und es JEDEM am Zahlungsmittelsystem teilnehmenden Marktteilnehmer erlaubt kostenfrei (i.e. ohne Benachteiligung von Bargeld(ein)zahlungen) bei JEDER Bank Geld einzahlen zu dürfen, das auf jedes beliebige Konto bei jeder beliebigen Bank mit Sitz in Deutschland (i.e. unter Aufsicht der BaFin stehend) gebuchte werden kann.

Ich sehe es als eine fundamentale Aufgabe eine Bank an Geld anzunehmen, und dieses einer beliebigen Person oder Organisation zukommen zu lassen.
Maximal würde ich eine Buchungsgebühr in Höhe der bisher üblichen Transaktionskosten akzeptieren, egal ob ich Kunde- oder Gast-Einzahler bei der Bank bin.

Für Rückfragen stehe ich gerne per E-Mail und auch postalisch zur Verfügung. Sollte es keine befriedigende Lösung für mein Vorhaben geben, werde ich in erwägung ziehen mit geeigneten NGO’s dem Thema mehr Aufmerksamkeit zu widmen und eintsprechend eine Klarstellung im Finanzrecht mit Hilfe sämtlicher Rechtsmittel zu erwirken die einem Bürger der Bundesrepublik Deutschland zugänglich sind.

Mit freundlichem Gruß,

Soweit mein – zugegeben etwas geharnischtes – Anliegen das ich an das „Referat VBS 3“ für Verbraucherbeschwerden richtete.

Nun kam die Antwort zurück und die lässt doch einigermaßen tief blicken mit was für einer komfortablen Machtposition sich die Banken da über die letzten Jahrzehnte offenbar die lästigen Verbraucheranliegen wegreguliert haben per Gesetz.

Die Antwort

Da muss ich erstmal ein Lob loswerden wie zügig die Antwort kam. Ich hatte mich schon drauf eingestellt, dass ich jetzt monatelang nichts mehr davon hören werde und dann einen Standardantwortbrief gespickt mit Wieselei-Textbausteinen erwartet. Stattdessen hat mich die Antwort allerdings dann inhaltlich mehr als nur überrascht. Hier die Antwort (einige Textstellen habe ich aus Gründen des Datenschutzes geschwärzt, diese beeinflussen die Aussage des Textes aber nicht wesentlich).

Schlussfolgerung

Aus meiner Sicht ist eine dringende Änderung nötig von BGB §675 Absatz 5 Satz 1 einerseits UND §1 Absatz 1 Satz 2 Nr. 1 & 2 Zahlungsdiensteaufsichtsgesetz (ZAG) andererseits. Und natürlich gehört das Münzgesetz, insbesondere §3 Absatz 1 Satz 2, angepasst.

Jetzt ist bloß die Frage, glaubt in diesem Land, bei diesen Politikern & Parteien noch jemand daran, dass es da eine Änderung geben wird? Insbesondere einem Bundesfinanzminister der SPD in der Regierung mit seinem persönlichen Track-Record in „Sachen Geld den Anderen/Banken/Großkonzernen geben“ – ich sag nur HSHNordbank, CumEx, Lufthansa, Wirecard, etc. – also ich leider nicht mehr.

Why do I blog this? Ich bin supersauer darüber dass ausgerechnet Banken offenbar bargeld ablehnen dürfen. Geldangelegenheiten sind deren einziger Zweck, das ist ihr Kernbusiness. Für mich bleibt das unfassbar und das möchte ich nicht als Argument gegen Bargeld verstanden wissen (Bargeld erfüllt eine wichtige Funktion: Diskriminationsfrei zu sein) sondern als Argument für eine härtere Gangart gegenüber den Banken in Deutschland.

ESP32/ESP8266: Optimizing the hell out of ESPAsyncWebServer

Das schöne an dem Microcontroller ist ja, dass man einen kleinen WebServer darauf laufen lassen kann. Damit hat man eine tolle Möglichkeit ein kleines aber immer verfügbares User Interface (UI) bereitzustellen, das mit fast allen modernen Geräten die einen Webbrowser haben (Tablet, Smartphone, Laptop, PC) sofort funktioniert.

WebServer in klein

Exception Decoder MenuWas man jedoch schnell vergisst, wenn man zuvor schon WebApplications mit WebServern wie nginx oder Apache ausgeliefert hat, ist der Ressourcenbedarf von so einem Server. Der Microcontroller ist halt klein deshalb ja auch „Micro“, hat wenig Speicher und wenig CPU-Zyklen die er für sowas entbehren kann.

Die Kunst liegt also in der Beschränkung. Doch das fällt sauschwer, wenn man erstmal einen gewissen Anspruch an seine Webseiten hatte. Niemand mag gern zurück in die Steinzeit und eine Webseite bauen z.B. ohne Stylsheets. Klar, das geht, sieht aber so schlimm aus und funktioniert auf dem Smartphone z.B. so gar nicht.

Zunächst habe ich den klassischen Weg zur Gestaltung meiner Webseite gewählt, ich hab HTML geschrieben mit Bildern darin und JavaScript das dynamisch Bilder austauscht und platziert, ich habe CSS geschrieben, das Bilder zur Gestaltung einsetzt. Es sieht wunderschön aus auf dem Desktop, aber… es crasht den WebServer des Microcontrollers. Da nutzt dann das ganze tolle Design auch nichts, wenn es letztlich nicht funktioniert.

Und ich habe zig Crashes gehabt. Ich habe mir mühsam den Arduino ESP8266/ESP32 Exception Stack Trace Decoder in der Arduino IDE installiert (Anleitung). Ein dekodierter Stacktrace sieht dann z.B. so aus:

Da sieht man, dass es im konkreten Fall eher ein Speicherproblem ist bei diesem Crash, weil eine alloc Funktion involviert ist. Aber viele andere Crashes sind eben anderer Natur.

Optimizing the hell out of it

Dann beginnt man zu begreifen und optimiert. Was kann man alles tun um zu optimieren? Anfangs dachte ich die Dateigröße wäre der Bottleneck des Microcontrollers. Ich hab die JS, CSS und HTML Dateien mittels GZIP komprimiert und mit dem content-type/gzip im Header ausliefern lassen. Das reduziert auch die Menge an Daten hervorragend. Oft wird nur noch ein Zehntel der Daten übertragen, was die Auslieferung selbst deutlich schneller macht.

Doch die Dateigröße ist gar nicht das Problem beim ESPAsyncWebServer. Das eigentliche Limit ist, dass der nur maximal 3 bis 4 Requests „gleichzeitig“ bzw. parallel bearbeiten kann. Der Rest der Requests hängt dann einfach und wartet ewig auf Antwort und wird verworfen oder führt zu einer Blockade des Webservers und einem späteren Crash. Es hat auch nichts damit zu tun, dass das SPIFFS Filesystem eine Obergrenze an gleichzeitig geöffneten Files hat wie mir ein Entwickler des ESPAsyncWebServer versicherte. Und darauf nun eine passende Antwort bzw. Optimierung zu finden ist gar nicht so einfach gewesen.

Klar, man kann das CSS und das JS alles mit in das HTML-file kippen, aber dann wird es schon arg unübersichtlich. Und des weiteren bleibt das Problem mit den vielen kleinen Icons bestehen, die alle je einen Request auslösen. Das kostet Zeit und trifft auf die Limitierung des Webservers. Das Hauptziel kann also zunächst nur sein die Anzahl initialer Requests (also der Requests die benötigt werden die Seite einmal komplett zu laden) zu minimieren. Und zwar sollte das so passieren, dass man unterhalb des Limits bleibt von max. 3-4 gleichzeitig eintreffenden Requests. Das ist natürlich ein Limit, dass sobald mehr als ein Nutzer gleichzeitig auf das UI zugreift bereits zu Problemen führen kann. Es ist schade, dass die Entwickler von ESPAsyncWebServer das nicht vorhergesehen haben und entsprechend zuviele Requests schlicht und einfach mit Fehler 503 ablehnen sondern stattdessen den Server crashen lassen. Aber vielleicht gibt es auch einen Grund der mir nicht begreiflich ist derzeit.

The Magic of Data-URI’s

Hier kommt dann jetzt eine Optimierungsstrategie zum Zuge, die auch bei „normalen“ Webseiten zu krass verbesserter User Experience (UX) führen kann. Das Einbetten der Bilddaten als sogenannte Daten-URI. Was ist das eine Daten-URI?

The data URI scheme is a uniform resource identifier (URI) scheme that provides a way to include data in-line in Web pages as if they were external resources. It is a form of file literal or here document. This technique allows normally separate elements such as images and style sheets to be fetched in a single Hypertext Transfer Protocol (HTTP) request […]

Das schreibt die Wikipedia dazu. und auf dieser Webseite heißt es „You can embed the image data directly into the document with data URIs.“ und genau das ist eine sehr sinnvolle Sache. Einerseits wird das Dokument (HTML, JS, CSS) in das man diese Daten dann einbettet zwar etwas größer, aber dafür unterbleiben Requests für Bilddaten komplett.

Aus folgendem Code für ein Favicon als Meta-Link im Header in HTML…

<link rel='icon' type='image/png' sizes='32x32' href='fav-icon-32x32.png'>

…wird folgender Code als eingebettete URI:

<link rel='icon' type='image/png' sizes='32x32' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA9tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wUmlnaHRzPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvcmlnaHRzLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcFJpZ2h0czpNYXJrZWQ9IkZhbHNlIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDowMzhmMTQ5NC1lNGJkLTExZTEtOGQ4MC1jYjVjZDBjYjc4N2QiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDJDODA5ODk0RjU1MTFFQThBRjNFQkJENEQ2MUU4MDUiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDJDODA5ODg0RjU1MTFFQThBRjNFQkJENEQ2MUU4MDUiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAyODAxMTc0MDcy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'>

Der entscheidende Teil ist, dass man statt einer Hyperlink-URI eine Data-URI nutzt, die eben so ausschaut:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAA

Als Werkzeug zur Umwandlung gibt es zahlreiche Online Tools dafür, wie z.B. den Image to data-URI converter. Dort kann man seine Grafikdateien umwandeln lassen. Es gibt auch apps z.B. für macOS den Data URI Converter von Chris Yip.
Mit dem richtigen Tool ist es jedenfalls schnell gemacht.

Ergebnis: Schnell, schneller, embedded Data-URI

Die Ergebnisse sprechen absolut für sich. Nachfolgend habe ich mit zwei Screenshots im Safari Browser festgehalten, die initialen Requests und deren Laufzeit und Datenumfang, die gegen den Controller gehen im zeitlichen Verlauf. Die Ergebnisse sind absolut eindeutig: Data-URI schlägt den klassischen Weg um Längen.

Man erkennt sofort, dass nach dem Laden der initialen HTML Seite core.html weitere Requests ausgelöst werden, klar ist die core.css und core.js werden benötigt, um die Seite überhaupt korrekt anzuzeigen. Aber allein schon die erste Seite auszuliefern benötigt 1,14 Sekunden Zeit, und dann wird es problematisch, da gleich fünf weitere Requests losgehen gleichzeitig, unter anderem eben auch requests wegen Grafiken. Das schafft der Server eben manchmal nicht. Und dann sieht man auch noch, dass jedes Bild ca. 300 bis 700 Millisekunden Zeit benötigt, und das ist sehr lang!! Die gesamte Seite ist erst nach über sechs Sekunden geladen.

Die gleiche Seite optimiert mit Data-URI’s verhält sich deutlich besser. Zwar wird der initiale Download der core.html um etwa 15KB größer, interessanterweise aber kostet das kaum Zeit. Und der initiale Download führt zu lediglich zwei weiteren Requests für die core.css und core.js. Beide Dateien enthalten selbst wiederum ausschließlich Data-URI’s und führen somit zu keinen Folgerequests.

Die Auswirkung ist enorm. Die Bilddaten sind nun in 10 bis 20 Millisekunden geladen statt wie vorher in 300 bis 700. Eine Verbesserung um Faktor zehn. Insgesamt ist die ganze Seite vollständig geladen nach nur etwas über zwei Sekunden. Das erspart satte 4 Sekunden Wartezeit.

Fazit

Wer Webseiten auf dem Microcontroller ausliefert, der sollte ausschließlich inline Data-URI’s für grafische Inhalte verwenden und die Anzahl der Requests soweit wie möglich senken. Für mein Setup bestünde jetzt noch die Option auch die core.css und core.js in die core.html zu integrieren. Dann wäre nur noch eine große Datei nötig.

Aus Gründen der Code-Übersicht sehe ich davon aber erstmal ab. Sollte es aber nochmal Probleme mit dem WebServer geben, dann kann ich hier gezielt weiter optimieren.

Why do I blog this? Das Problem des instabilen und ständig crashenden ESPAsyncWebServer hat mich einige endlos erscheinende Stunden des Debuggens gekostet. Weil ich auch einfach nicht wusste was den WebServer crasht und/oder blockiert und Serial.print() statements haben nicht wesentlich geholfen. Ich hoffe es hilft anderen nicht in die gleiche Falle zu tappen. Sehr hilfreiche Hinweise zum Thema ESPAsyncWebServer habe ich überigens im Diskussionsforum/Chat zu dem Server gefunden. Das hat mir sehr geholfen.