Freifunk, executive summary

2014-01-29 / Sebastian Morr / german, tech

Ich habe mir vor zwei Wochen Freifunk genauer angeguckt, und möchte euch hier mal zusammenfassen, was ich gelernt habe. Die Grundidee ist, in einer Stadt viele WLAN-Router aufzustellen, die sich untereinander vermeshen und so ein dezentrales (unzensier- und -drosselbares) Kommunikationsmedium bilden.

Lokale Communities

Für mich, der neu dazukommt, ist die Organisation der Community zunächst befremdlich: Jede Stadt pflegt ein eigenes Wiki, Mailinglisten und Standortkarten, was zu großer Informationsfragmentierung führt. Oft bauen die Städte sogar ihre eigene Firmware. Ist wohl gelebte Dezentralisierung, wirkt auf mich aber ineffizient. Die Community-Karte listet derzeit 57 Communities in Deutschland und Österreich auf.

Funktionsweise

Üblicherweise machen die Freifunk-Router zwei WLAN-Netze auf: Eines im Access Point-Modus, damit sich Endgeräte drauf verbinden können, eines im Ad-Hoc-Modus, zur Vernetzung mit anderen Routern.

Früher benutzte Freifunk das OLSR-Routingprotokoll, welches permanent die gesamte Netzwerktopologie auf alle Knoten verteilt. Das skalierte wohl nicht so gut, weshalb einige Freifunker eine einfachere Alternative entwickelten: B.A.T.M.A.N (“Better Approach To Mobile Adhoc Networking”). Ein Knoten ruft regelmäßig ins Netz, dass er da ist und merkt sich für jeden anderen Knoten, aus welcher Richtung er die meisten dieser Broadcast-Nachrichten empfangen hat. In diese Richtung werden dann Pakete geschickt, die für diesen Knoten bestimmt sind. Fertig.

Es gibt übrigens einen regelmäßigen Wettbewerb, in dem Mesh-Routing-Protokolle gegeneinander antreten, Battle Mesh ;-)

Hardware

In allen Stadt-Communities sind zur Zeit die Router der chinesischen Firma TP-LINK beliebt, und zwar in der Schnittmenge folgende Geräte:

  • TL-WR741ND: 4 MB Flash, 32 MB RAM, eine Antenne, ca. 23 Euro. Der Flash scheint recht knapp zu sein, reicht aber für normale Knoten aus. Das “D” im Namen bedeutet jeweils, dass man die Antennen austauschen kann, gibt die meisten auch mit fest verbauten Antennen.
  • TL-WR841ND: Hardware wie oben, aber zwei Antennen (doppelte Datenrate per MIMO, ca. 22 Euro. Es gibt von Hardwareversion 8 wohl eine “chinesische Version”, die crappy ist (halber Flash und RAM). Hier bekommt man aber meistens die unabgespeckte internationale Version.
  • TL-WR842ND: Zusätzlicher USB 2.0-Port, ca. 42 Euro.
  • TL-WR1043ND: Schnellere CPU, 8 MB Flash, 64 MB RAM, drei Antennen, USB 2.0, mit Gigabit-Ports, ca. 45 Euro. Laut Kiel “für größere Aufgaben geeignet”.
  • TL-WDR3500: 8 MB Flash, 128 MB RAM, drei Antennen, ca. 36 Euro. Unterstützt als einziger dieser Liste 5GHz-Frequenzen (wovon manche aber wegen geringerer Reichweite durch stärkere Streuung für diesen Zweck auch eher abraten). Momentane Empfehlung von Berlin.

Ich habe mir mal testweise einen TL-WR841ND gekauft und die Hamburger Firmware draufgespielt, dauert vielleicht 10 Minuten, dann ist der Router online.

Braunschweig?

Braunschweig befindet sich auf der Community-Karte in einem ziemlichen Freifunk-Loch. Große “Nachbarn” sind Halle, Bielefeld und Hamburg. Hannover reaktiviert sich angeblich gerade wieder, im Forum ist allerdings bisher wenig Aktivität.

Im Freifunk-Wiki gibt es eine Seite über Braunschweig, die von vereinzelten Anläufen berichtet (letzte Änderung: 2009), die Mailaddressen sind nicht mehr erreichbar. Auf der Hamburger Karte findet man zur Zeit vier Knoten, die mit der Hamburger Firmware ausgestattet sind (die ermöglicht von Haus aus Internetzugriff über ein VPN in die Niederlande, wo es keine Störerhaftung gibt.

Weitere Ressourcen

Wenn ihr noch Fragen habt, gerne her damit!

Bachelorarbeit: Woche 21

2013-11-30 / Sebastian Morr / german, thesis

Am Donnerstag habe ich die Bachelorstudiengangsabschlussbescheinigung abgegeben, yay! Die letzten Wochen war noch recht viel zu tun, weshalb ich das Gefühl hatte, mir keine Zeit für einen ausführlichen Blogpost nehmen zu können. Heute berichte ich von der Arbeit selbst, in einem kommenden Post dann noch vom Abschlussvortrag.

Hier kommt zunächst die Arbeit als PDF mit anklickbaren Querverweisen. Im Original sind die Seitenabstände anders, um zweiseitig schöner auszusehen. Der LaTeX-Sourcecode ist auf GitHub. Wer dieses Blog verfolgt hat, ist mit dem Inhalts bereit größtenteils vertraut. Neu sind Beschreibung und Auswertung der Evaluation.

Ich war überrascht und etwas enttäuscht, dass sich am Institut niemand die Zeit nahm, die Arbeit nochmal inhaltlich durchzugehen und zu kritisieren. Während ich mitbekommen habe, dass an anderen Instituten die Abschlussarbeiten oft zu einem guten Teil das Werk des Betreuers sind, war ich hier fast vollständig auf mich allein gestellt. Es war einerseits ganz schön, so autonom arbeiten zu können, andererseits bin ich sicher, dass die Arbeit bei einer intensiveren inhaltlichen Betreuung noch deutlich besser, formaler und tiefgehender hätte werden können.

LaTeX

Auch für lange Dokumente betreut Enrico LaTeX-Klassen im Corporate Design der TU. Während die einwandfrei aussehen, gefallen mir die Schriftarten nicht besonders, daher verwende ich ein blankes scrreprt.

Ich möchte euch folgende LaTeX-Pakete empfehlen, auf die ich beim Schreiben gestoßen bin:

  • microtype ist ein Schritt hin zur typografische Perfektion: Es optimiert Buchstabenabstände, macht die Seitenränder optisch gerade und minimiert Worttrennungen. Ein Blick in das (interaktive!) Handbuch sei höchst empfohlen!
  • cleveref erlaubt textuelle Verweise auf Referenzen per \cref{<name>}, wobei der Typ des verlinkten Dinges angefügt wird (der Verweis lautet dann zum Beispiel “figure 3.14”). Es gibt auch Befehle für “on page 42” etc.
  • menukeys habe ich zum Erstellen von hübschen Darstellungen von Tastenkombinationen benutzt (\keys{\ctrl + C}), es eignet sich auch zum Formatieren von Menüfolgen (\menu{Extras > Settings > General}).
  • listings ist recht gut bekannt für das Erstellen von Codelistings, ich möchte hier nur nochmal unterstreichen, dass das Paket sehr hübsch konfigurierbar ist: Man kann sehr einfach eigene Umgebungen für verschiedene Sprachen anlegen und eigenes Syntaxhighlighting definieren - für meine nutsh-Codeschnipsel oder für EBNF-Grammatiken war das sehr praktisch.
  • pgfplots benutze ich zum Zeichnen von Balken- und Boxplot-Diagrammen. Es basiert auf dem Zeichenpaket PGF/TikZ (was ebenfalls höchst extremst empfehlenswert ist!), ist ziemlich mächtig und gut konfigurierbar. Ich bin nicht restlos begeistert vom Interface, habe mich aber auch nicht lange damit beschäftigt und es tut was es soll.

Nitpicker

Das Nitpicker tool beschreibt sich als “overly picky language style checker”. Es überprüft formale englische Texte automatisch auf häufige grammatikalische, semantische und Rechtschreibfehler (verdammte passive voice ;-). Ich habe das Tool in einem Lightning Talk auf einem der letzten Kongresse kennengelernt und finde es inzwischen unersetzlich, um die gröbsten Schnitzer aus Texten rauszubügeln, bevor man es Menschen zu Lesen gibt. Benutzt es!

Fun fact: Das Nitpicker tool wird durch Katzenbilder angetrieben: 1, 2.

Motivation

Symbolbild: Research paper vs Internet

Beim eigentlichen Schreiben fiel es mir teilweise sehr schwer, konzentriert zu bleiben und nicht herumzuprokrastinieren. Irgendwann kramte ich einen Motivationstrick heraus, den ich auch schon beim Lernen für Klausuren erfolgreich angewendet habe: Die Pomodoro technique. Die funktioniert so:

  1. Man stellt einen Küchenwecker auf eine halbe Stunde.
  2. Solange der Wecker tickt, arbeitet man möglichst konzentriert, ohne sich ablenken zu lassen.
  3. Wenn der Wecker klingelt, malt man ein Kreuz irgendwohin und macht fünf Minuten Pause (Lüften, Nahrungs- und Flüssigkeitszufuhr, Äkta manniskor gucken).
  4. Nach jeweils vier Kreuzen macht man eine längere Pause von etwa einer halben Stunde. Dann GOTO 1.

Und das funktioniert ganz hervorragend für mich. Ich freue mich immer sehr auf die kommende Pause und schaffe es, mich während der halben Stunde nicht ablenken zu lassen. Mithilfe dieser Technik habe ich in den drei letzen Wochen vor der Abgabe etwa 6 bis 7 Stunden pro Tag konzentriert gearbeitet.

Pomodoro ist übrigens das italienische Wort für “Tomate” - der Typ, der sich das ausgedacht hat, hat einen Küchenwecker in Tomatenform benutzt.

Bachelorarbeit: Woche 13

2013-10-05 / Sebastian Morr / german, thesis

Blick zurück

So, der Vorkurs lief gut, die Teilnehmer schienen mir recht glücklich mit der Nut Shell, ich habe viel positives Feedback bekommen. Ich habe eine kleine Umfrage durchgeführt, um Spaß und Lernfortschritt quantifizieren zu können, die Ergebnisse werde ich in den kommenden Wochen hier veröffentlichen.

Blick nach vorn

Nun habe ich noch einen Monat zum tatsächlichen Schreiben der Arbeit. Hierzu habe ich eine grobe Gliederung entworfen, unten dargestellt als Outline. Die eingeklammerten Zeilen sind keine eigenen Abschnitte, sondern Zusammenfassungen der vorgesehenen Inhalte.

Ich habe versucht, den Hauptteil “von unten nach oben” zu strukturieren, also tatsächlich in der Reihenfolge, in der die Komponenten aufeinander aufbauen:

Abstract
    (Purpose)
    (Design + evaluation methods)
    (Major results)
    (Summary of conclusions)
Introduction
    (Topic: Command line tutorials)
    (Motivation: Traditional, static tutorials have problems)
        (Attention shift)
        (No goal affirmation)
        (No reaction to mistakes)
    (Core idea: Interlace tutorial text and CLI)
    (Role model: Text adventures)
    (Research question: Is this approach "better"?)
    (Prior approaches)
        (Try Ruby/Git/Haskell)
        (What's missing in them)
    (Conventions in this thesis)
Overview
    (Goals and principles)
        (Basic event loop: prompt -> editing -> execution/output)
        (Adaptability to arbitrary "targets")
        (Annotation + environment changing, otherwise raw CLI interaction)
    (Steps of this thesis)
    (Diagram: Layers)
Design
    Command line parser
        Purpose
            (Recognizing parts of command line output)
        Background
            (How a terminal works)
            (Escape characters)
            (Readline key combinations)
        Architecture
            (Component diagram)
            (Parser EBNF)
        Problems and workarounds
            (Command line editing)
            (...)
    Internal DSL
        (Purpose: High-level layer around CLI parser)
        (Description of necessary DSL calls)
    The nutsh language
        Purpose
            (Describes a self-contained teaching unit, a "lesson")
        Design goals
            (Easy to read and write)
                (Use syntax the user already knows: Regex + Go syntax)
                (Introduce new syntax for often-used semantics)
            (Minimize redundance)
                (DRY, allow reuse of code snippets)
        Properties
            (String-based)
            (Functional)
        Lexical elements
            (Token types)
            (Diagram: State machine)
        Syntax
            (EBNF of language constructs)
        Parsing
            (How YACC works)
        Semantics
            (Specification of language constructs)
        Interpreter
            (State)
            (Function stack)
        Automated testing
            (Motivation)
            (Testing algorithm)
        Examples
Implementation
    Used technologies
        (Go)
        (kr/pty for terminal emulation)
    High-level design
        (Diagram: Package diagram)
    Command line tool
        Usage
        Builtin functions
Application and evaluation
    Methods
        Setting
            (Description of setting: Preparatory course for CS students)
            (Previous teaching method)
            (Groups)
        Tutorial
            (Content, examples)
            (Best practises in lesson writing)
        Survey
            (Questions)
    Results
        (Pretty graphs)
        (Statistical evaluation)
Conclusions
    (Discussion of survey results)
Limitations and future directions
    (Future directions:)
        (Automated typo detection)
        (Simplified prompt syntax)
        (Lesson dependency tree)
    (Outlook, future of the Nut Shell)
Acknowledgements
    (...)
References
    (...)
Appendix A: Example lesson
    (nutsh source code)
    (Execution output)
Appendix B: Table of terminal escape codes
    (...)
Affidavit
    ("Erklärung an Eides statt")

Mit dem langen Kapitel zur Sprache (Spezifikation inklusive Erläuterungen zum Parsen, Interpretieren, etc.) bin ich noch nicht so zufrieden, vielleicht ist es lohnend, einige Abschnitte in den “Implementation”-Teil zu verschieben. Das bricht aber die schöne bottom-up-Struktur. Hm.

Bachelorarbeit: Woche 11

2013-09-16 / Sebastian Morr / german, thesis

Nur ganz kurz: Heute beginnt der Vorkurs! Ich bin so gespannt, ob alles klappt! Die letzen Wochen habe ich wirklich viel geschuftet, damit heute alles schön ist.

Wer mitmachen möchte, kann sich die kurze Installationsanleitung geben. Ihr braucht einen Go-Compiler und Git. Und Linux, natürlich. Getestet ist das aber eigentlich nur im Raum, in dem der Vorkurs stattfindet und auf meinem Notebook, keine Garantien ;-)

Warnung: Das Setup ist für absolute Neulinge, deshalb hängt es eine Zeile an eure .bashrc, die das nutsh-Skript in den PATH tut. Dieses Skript sorgt für automatische Aktualisierungen (es kommen jeden Tag neue Lektionen dazu).

Viel Spaß!

Bachelorarbeit: Woche 9

2013-09-04 / Sebastian Morr / german, thesis

Der letze Eintrag ist nun schon eine ganze Weile her, höchste Zeit für ein Statusupdate!

Sprache

Die Sprache, in der man Tutorials verfassen kann, nenne ich nutsh, in Analogie zur Nut Shell. Sie ist viele Iterationen durchlaufen, bis ich etwas fand, was mir mächtig genug erscheint, möglichst einfach zu lesen und zu schreiben und simpel umzusetzen ist. Die Irrwege schildere ich vielleicht ein anderes Mal ;-)

Grundlagen

Die Sprache basiert stark auf Strings ("blabla"). Stringausdrücke kann man verknüpfen ("bla"+"bla"), sowie auf Gleichheit überprüfen ("bla" == "bla"). Außerdem kann man überprüfen ob ein String einem Regulären Ausdruck entspricht ("bla" =~ "b.."). Jeder String kann als Wahrheitswert interpretiert werden, der bei einem leeren String falsch ist, ansonsten wahr. Die Vergleichsoperatoren geben bei Erfolg den (beliebig gewählten) String "true" zurück. Die üblichen logischen Operationen (! für nicht, && für und sowie || für oder) sind entsprechend definiert.

Es gibt noch die Kontrollfluss-Strukturen if-else sowie prompt, und man kann Funktionen definieren und aufrufen, und das reicht dann auch schon. Variablen sind nicht notwendig, weil man die auch in der Zielsprache definieren kann.

Naja, und typische C-Kommentare gibt es auch (// für Zeilenkommentare, /* ... */ für Blockkommentare).

Grundbefehle

Ganz zentral ist die Ausgabe von erklärendem Text. Dieser wird eingerückt und farbig hervorgehoben.

say("Dies ist erklärender Text")

Weil der Befehl so oft verwendet wird, kann man auch einfach schreiben:

"Dies ist die Kurzform"

Um einen Befehl im Kommandozeilen-Prozess auszuführen, benutzt man run. Rückgabewert ist die Ausgabe des Befehls.

run("echo testinhalt > /tmp/testdatei")

Ich überlege noch, ob auch hier eine Abkürzungsmöglichkeit sinnvoll wäre, etwa

!"echo testinhalt > /tmp/testdatei"

Kontrollfluss

Ganz wichtig ist die Prompt-Schleife:

prompt {
    // Befehle
}

Sie Semantik ist die einer Endlosschleife, zu deren Beginn jeweils ein Befehl vom Benutzer eingelesen wird. Sie kann durch ein break verlassen werden.

Es gibt zwei eingebaute Funktionen command und output, die jeweils das zuletzt eingegebene Kommando und dessen Ausgabe zurückgeben.

Weiterhin gibt es if-else Ausdrücke, deren Syntax stark von Go beeinflusst ist (keine Klammern um die Bedingung):

if command =~ "^rm " {
    "OMG!"
} else {
    "Brav!"
}

Funktions-Definition

Mehrfach verwendete Codeschnipsel kann man in Funktionen auslagern:

def exit_status {
    return(run("echo $?"))
}

def say_twice(text) {
    say(text)
    say(text)
}

prompt {
    say_twice("Der Rückgabewert war '"+exit_status+"'")
}

Funktionen ohne Argumente können auch ganz ohne Klammern aufgerufen werden.

Umgebende Zustände

Möchte man für eine Gruppe von Prompt-Schleifen die gleichen Bedinungen überprüfen, kann man diese Syntax benutzen:

def help {
    if command =~ "help" {
        "Don't panic!"
    }
}

help {
    prompt {
        if command =~ "panic" {
            break
        }
    }

    "Zweite Chance..."
    prompt {
        if command =~ "panic" {
            break
        }
    }
}

Das bedeutet: “Zu Beginn jedes Prompt-Durchlaufs, führe die Funktion help einmal aus. Das geht auch mit mehreren Funktionen:

def stay_in(dir) {
    if ! run("pwd") =~ "^"+dir {
        say("Bitte komm wieder zurück nach `"+dir+"`!")
        prompt {
            if run("pwd") =~ "^"+dir {
                break
            }
        }
        "Okay, weiter im Text."
    }
}

def help {
    if command =~ "help" {
        "Don't panic!"
    }
}

run("cd /tmp")

stay_in("/tmp"), help {
    "Wie spät ist es?"
    prompt {
        if command == "date" {
            break
        }
    }

    "Und wer bist du?"
    prompt {
        if command == "whoami" {
            break
        }
    }
}

Die Syntax einer solchen “Zustands-Schachtelung” hat mich am längsten aufgehalten, mit dem Ergebnis bin ich aber sehr zufrieden.

Was noch fehlt

Ein Tutorial braucht Metainformationen (Zielsprache, Name, nutsh-Version), man braucht eingebaute Funktionen zum Springen zwischen Lektionen und vielleicht auch ein goto, das wird sich zeigen.

Was ich außerdem möchte, ist ein eingebauter Befehl expect, mit dem man automatisiert überprüfen kann, ob man durch Eingabe dieses Befehls in den entsprechenden Zustand gelangt.

Umsetzung

Das Lexen, also das Zerlegen des Sourcecodes in seine Bestandteile (Strings, Keywords, Identifier, Operatoren, Klammern) ist hier so einfach, dass ich das in einer kurzen Funktion selbst mache.

Zum Parsen, also zum Erkennen der Struktur, benutze ich die yacc-Version, die zusammen mit Go ausgeliefert wird, und mache damit ganz gute Erfahrungen.

Den resultierenden Parse-Baum kann man dann sehr einfach interpretieren, auch dazu später vielleicht einmal mehr.

Wie geht es weiter?

Ich habe noch anderthalb Wochen bis zum Beginn des Vorkurses, in denen ich Inhalte erstellen und die aufgeführten noch fehlenden Sprachelemente umsetzen werde. Ich werde eine Onlineevaluation vorbereiten, um die Eindrücke der Vorkurs-Teilnehmer etwas quantifizieren zu können. Insbesondere wird es eine zweite “Kontrollgruppe” geben, die noch mit den alten Aufgabenblättern arbeitet, um eine Vergleichsmöglichkeit zu haben.

Ich bin gespannt!

Zum Abschluss noch die kurze Lektion aus dem letzen Blogpost in nutsh:

def common_mistakes {
    if command == "1s" {
        "Das ist ein kleines L, keine Eins! Probier's nochmal!"
    }
    if command == ".." {
        "`..` ist der Name des Verzeichnisses, du musst noch dazusagen,
        was du damit machen möchtest. Um \"hinzugehen\", schreib `cd`
        davor."
    }
    if command == "cd.." {
        "Da fehlt noch ein Leerzeichen zwischen `cd` und `..`!"
    }
}

def stayinroot {
    if !(run("pwd") =~ run("echo $ROOT")) {
        run("cd $ROOT")
        "Bleib bitte erstmal hier."
    }
}

run("ROOT=/tmp/nutsh")

run("rm -rf $ROOT")
run("mkdir $ROOT")
run("cd $ROOT")

run("mkdir schuhkarton")
run("mkdir schrank")
run("touch schrank/jacke")
run("touch schrank/hut")
run("touch linker_schuh")

"Hallo! Willkommen in der Nut-Shell! Ich möchte dir zeigen, wie du
mithilfe der Kommandozeile schnell und einfach mit Dateien und
Verzeichnissen umgehen kannst."

"Legen wir gleich los: Tipp mal `ls` ein und drück Enter."

common_mistakes, stayinroot {
    prompt {
        if command == "ls" {
            "Genau. `ls` steht kurz für \"list\" und zeigt dir die
            Dateien und Verzeichnisse an, die sich in deinem
            \"aktuellen\" Verzeichnis befinden. Die Verzeichnisse
            werden dabei blau dargestellt."

            "Du bist gerade in einem Ordner namens `/tmp/nutsh` - das
            steht auch in dem blauen Text, den wir \"Prompt\" nennen.
            Der Prompt endet mit einem Dollarzeichen, das heißt soviel
            wie: \"Du kannst jetzt ein Kommando eingeben!\""

            break
        }
    }

    "Du hast vielleicht gesehen, dass sich hier ein Verzeichnis namens
    `schrank` befindet. Um dieses zu deinem aktuellen Verzeichnis zu
    machen, tippst du `cd`, dann ein Leerzeichen und dann den Namen des
    Verzeichnisses, in das du möchtest. Begib dich doch mal in den
    Schrank und sieh dich darin um!"

    prompt {
        if run("pwd") == run("echo $ROOT/schrank") {
            if command == "ls" {
                "Genau. Hast du bemerkt, wie sich der Prompt geändert
                hat?"

                break
            }
        }
    }

    "Und wenn du wieder aus dem Schrank herausmöchtest? Die Abkürzung
    für das Verzeichnis oberhalb des aktuellen ist `..`!"

    prompt {
        if run("pwd") == run("echo $ROOT") {
            break
        }
    }

    "Gut. So, nun brauchen wir ein wenig Magie... *pling*"

    "[Der Schrank rumpelt und ächzt]"

    run("mkdir -p $ROOT/schrank/magische_tür/tür{1..3}")
    run("touch $ROOT/schrank/magische_tür/tür2/rechter_schuh")

    "Im Schrank hat sich nun etwas verändert. Geh hinein und such den
    rechten Schuh."

    prompt {
        if run("pwd") == run("echo $ROOT/schrank/magische_tür/tür2") {
            if command =~ "ls" {
                "Du hast ihn gefunden! Nun komm wieder aus dem Schrank
                heraus!"

                break
            }
        }
    }

    prompt {
        if run("pwd") == run("echo $ROOT") {
            break
        }
    }

    "Gut! So, das war eine Einführung in `ls` und `cd`. Hier ist das
    Tutorial erstmal zu Ende! Danke!"
}