Erste IoT-Schritte: Laufende Temperaturmessung mit dem Arduino und ThingSpeak

Bei meinem letzten Beitrag zum Thema hatte ich schon beschrieben, wie man den Arduino mit Hilfe eines E32-Shields ins WLAN bringt. Nun sollte das Ganze einen nützlichen Zweck erfüllen. Für den Anfang reichte mir der Anschluss eines einfach DS18B20-Temperatursensors und die fortlaufende Dokumentation der Messung bei einem IoT-Server. Natürlich kann man auch selbst einen MQTT-Server (sprich: Mosquito-Server) aufsetzen und verwenden, aber ThingSpeak bietet sich hier einfach aus mehreren Gründen an. Vor allem auch deshalb, weil es bereits eine fertige Bibliothek für den Arduino gibt, sodass man die Befehle zum Senden der Werte auf einem hohen Abstraktionslevel belassen kann.

Wie so oft gilt auch hier: Natürlich gibt es das alles schon und es ist auch alles im Netz frei verfügbar und dokumentiert. Aber es kostet dann doch relativ viel Aufwand, alles zusammen zu tragen und im Detail zu verstehen. Daher schreibe ich meine Vorgehensweise hier strukturiert auf. Ebenfalls gilt: Natürlich braucht der wahre Profi den Arduino gar nicht dafür, ein kleiner ESP8266 genügt ebenso. Aber es geht ja auch ein wenig um den Spaß und um das Verständnis des Ganzen, und dafür ist der Arduino einfach besser geeignet. Natürlich wäre das Gleiche auch mit einem Raspberry Pi machbar, der große Vorteil hier liegt darin, dass man sich ein schönes Python-MQTT-Skript schreiben kann und die Fallen vom Arduino-C etwas umschifft.

Doch zurück zum Arduino-Beispiel. Die Verkabelung der Hardware ist – basierend auf der bereits bestehenden Kombination aus Arduino und ESP-Shield – denkbar einfach. Der Temperatursensor bringt drei Kabel mit, die an 3,3V- (rot), GND- (schwarz) und einen beliebigen Digital-PIN (gelb) des Arduino bzw. des aufgesteckten Shields angeschlossen werden. Fertig.

Die eigentliche Kunst liegt also in der Software. Als Basis nehme ich den verkürzten Sketch aus dem WLAN-Anschluss-Beispiel:

#include "WiFiEsp.h"
#include "SoftwareSerial.h"

SoftwareSerial Serial1(3, 2); // RX, TX

char ssid[] = "MeinTollesWLAN";
char pass[] = "**********";
int status = WL_IDLE_STATUS;
WiFiEspClient client;

void setup(void) {
Serial.begin(9600);
Serial1.begin(9600);
WiFi.init(&Serial1);

while ( status != WL_CONNECTED) {
Serial.print("Verbindungsaufbau zu ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
}

Serial.println("Verbindung hergestellt!");
Serial.println();
printWLAN();
Serial.println();
}

void loop(void) {
}

void printWLAN()
{
IPAddress ip = WiFi.localIP();
Serial.print("IP-Adresse: ");
Serial.println(ip);
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
long rssi = WiFi.RSSI();
Serial.print("Signalstaerke (RSSI): ");
Serial.println(rssi);
}

Wie man leicht sieht, macht der Sketch vorerst nichts abgesehen vom Verbindungsaufbau zum WLAN. Soweit so gut. Beginnen wir mit den Bibiotheken und Konstanten, die wir für alles Weitere benötigen. Die Bibliotheken heißen „OneWire“ (Temperatursensor) und „ThingSpeak“ (Verbindung zum IoT-Server).

ThingSpeak kann man auf der folgenden Seite herunterladen und dann der (sehr kurzen) Installationsanleitung folgen:

https://github.com/mathworks/thingspeak-arduino

Und wenn man gerade schon dabei ist, verfährt man ebenso mit der hier erhältlichen OneWire-Library.

Welche Konstanten werden nun benötigt? Zum einen die Nummer des PINs, an dem das gelbe Datenkabel des Sensors angeschlossen wurde. In meinem Beispiel ist das die Nr. 5. Um mit ThingSpeak arbeiten zu können, muss zudem ein Account bei dem Dienst angelegt werden. Nach dem Login kann dann ein einzelner Channel erstellt werden, der künftig die Daten entgegen nimmt. Die Nummer des Channels sowie unser APIKey von ThingSpeak sind die letzten benötigten Konstanten:

#include "OneWire.h"
#include "ThingSpeak.h"

int Sensor_Pin = 5;
unsigned long Channel = 123456789abcdef;
const char * APIKey = "************";

Bei unserer Messung verwenden wir ein Objekt aus der Klasse OneWire, dem als Parameter die Nummer des PINs übergeben wird:

OneWire ds(Sensor_Pin);

In der setup-Funktion wird die Kommunikation mit dem ThingSpeak-Server initialisiert, dabei wird die WLAN-Verbindung als Übertragungsweg übergeben:

ThingSpeak.begin(client);

Kommen wir zur Loop-Funktion. Diese soll im Grunde folgende Elemente enthalten: Messen, Ausgeben, Übertragen, Warten. Das Messen ist dabei mit riesigem Abstand die komplexeste Aufgabe und wird daher in eine eigene Funktion „getTemp“ ausgelagert. Der Rest ist relativ einfach. Damit nur echte Messwerte eingetragen werden, verwende ich „-100“ als Fehlerwert, alles darüber hinaus wird an ThingSpeak übertragen. Dabei müssen Channel, das Datenfeld (in unserem Fall einfach das einzige, also 1), der gemessene Wert sowie der APIKey übertragen werden. ThingSpeak kann man nicht mit beliebig vielen Werten fluten, 20 Sekunden Wartezeit zwischen den Messungen sind hier i.d.R. angemessen. Somit ergibt sich die Loop-Funktion:

void loop(void) {
float temperatur = getTemp();
Serial.println(temperatur);
if ( temperatur > -100) {
ThingSpeak.writeField(Channel, 1, temperatur, APIKey);
}
delay(20000);
}

Tja, und nun geht’s ans Eingemachte, namentlich um die Funktion „getTemp“. Ich gebe zu, dass ich – der ich nie wirklich C gelernt habe – dann doch einige Zeit intensiv darüber nachdenken musste, um die gefundenen Programmierbeispiele zu verstehen. Ich habe sie hier auf das Nötigste gekürzt und versuche sie zu erläutern.

Wir benötigen zwei Byte-Arrays namens „addr“ (für die Adressdaten des Sensors, es könnte mehrere geben) und „data“ (für die Messwerte). Zudem gilt es, ein paar Fehler abzufangen, z.B. Fehler in der Prüfsumme (CRC) oder gar einen nicht gefundenen oder nicht unterstützten Adapter. In all diesen Fällen wird unser Fehlerwert „-100“ zurückgegeben:


byte data[12];
byte addr[8];

if ( !ds.search(addr)) {
ds.reset_search();
return -100;
}

if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC fehlerhaft!");
return -100;
}

if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Kein Sensor erkannt");
return -100;
}

Durch den Aufruf von „ds.search(addr)“ wird der Array praktischerweise direkt mit den Adressdaten des Sensors gefüllt, sodass wir nun – da keine Fehler aufgetreten sind – damit arbeiten können. Die nächsten Schritte sind im Einzelnen: Reset der Kommunikation, Auswahl des Sensors, Durchführen einer Messung und schließlich das Auslesen der Werte aus einem Zwischenspeicher, Speichern der Werte in unserem Datenarray. Anschließend kann wieder ein Reset der Suche nach Sensoren erfolgen.

ds.reset();
ds.select(addr);
ds.write(0x44); // Kommando: Messung durchfuehren
ds.reset();
ds.select(addr);
ds.write(0xBE); // Kommando: Werte auslesen
for (int i = 0; i < 9; i++) {
data[i] = ds.read();
}
ds.reset_search();

Fast fertig. Doch unsere Messwerte sind noch ein wenig „kryptisch“ und entsprechen nicht gerade dem, was wir aufzeichnen wollen. Die eigentlich interessanten Werte „MSB“ (most significant byte) und „LSB“ (least significant byte) stecken in unseren Datenfeldern 1 bzw. 0:

byte MSB = data[1];
byte LSB = data[0];

Sie enthalten die gemessene Temperatur in Binärdarstellung, wie ein Blick in das Datenblatt des DS18B20 verrät:

Um daraus nun einen „gewohnten“ Temperaturwert zu erhalten, bedarf es einer bitweisen Verschiebung des MSB um 8 Stellen nach links und einer bitweisen Verknüpfung mit dem LSB (und gleichzeitig einer Umwandlung in eine Fließkommazahl zur Basis 10):

float tempRead = ((MSB << 8) | LSB);

Wie man dem Datenblatt entnehmen kann, enthält das Ganze aber auch Nachkommastellen, das wurde bei der Umwandlung nicht berücksichtigt. Durch welche Zahl muss nun geteilt werden? Da unsere eigentliche „Basis“ (die 2^0 – Stelle) an vierter Position befindet, ist die Zahl um den Faktor 2^4 = 16 zu hoch. Es folgt:

float TemperatureSum = tempRead / 16;
return TemperatureSum;

Fertig! Hier noch einmal der komplette Sketch, viel Spaß beim Ausprobieren:


#include "OneWire.h"
#include "ThingSpeak.h"
#include "WiFiEsp.h"
#include "SoftwareSerial.h"

int Sensor_Pin = 5;
unsigned long Channel = 123456789abcdef;
const char * APIKey = "************";

OneWire ds(Sensor_Pin);

SoftwareSerial Serial1(3, 2); // RX, TX

char ssid[] = "MeinTollesWLAN";
char pass[] = "**********";
int status = WL_IDLE_STATUS;
WiFiEspClient client;

void setup(void) {
Serial.begin(9600);
Serial1.begin(9600);
WiFi.init(&Serial1);
ThingSpeak.begin(client);

while ( status != WL_CONNECTED) {
Serial.print("Verbindungsaufbau zu ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
}

Serial.println("Verbindung hergestellt!");
Serial.println();
printWLAN();
Serial.println();
}

void loop(void) {
float temperatur = getTemp();
Serial.println(temperatur);
if ( temperatur > -100) {
ThingSpeak.writeField(Channel, 1, temperatur, APIKey);
}
delay(20000);
}

float getTemp(){

byte data[12];
byte addr[8];

if ( !ds.search(addr)) {
ds.reset_search();
return -100;
}

if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC fehlerhaft!");
return -100;
}

if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Kein Sensor erkannt");
return -100;
}

ds.reset();
ds.select(addr);
ds.write(0x44); // Kommando: Messung durchfuehren
ds.reset();
ds.select(addr);
ds.write(0xBE); // Kommando: Werte auslesen

for (int i = 0; i < 9; i++) {
data[i] = ds.read();
}

ds.reset_search();

byte MSB = data[1];
byte LSB = data[0];

float tempRead = ((MSB << 8) | LSB);
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}

void printWLAN()
{
IPAddress ip = WiFi.localIP();
Serial.print("IP-Adresse: ");
Serial.println(ip);
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
long rssi = WiFi.RSSI();
Serial.print("Signalstaerke (RSSI): ");
Serial.println(rssi);
}

Anmerkungen zu Big Data und den Folgen für die Speicher-Infrastruktur

Was ist Big Data?

Der Terminus „Big Data“ ist nun schon seit einigen Jahren auf dem Markt. Neuigkeiten wie der NSA-Skandal haben sicherlich dazu beigetragen, Aufmerksamkeit für den ganzen Themenkomplex zu wecken. Mögliche Konsequenzen der neuen Datenwelt, die ja ein wichter Teil der digitalen Transformation sind, werden inzwischen in den allgemeinen Medien ausführlich dargestellt und besprochen.

In den Wissenschaften, insbesondere in den Natur- und Lebens-, den Wirtschafts- und Sozial- aber auch in den Geisteswissenschaften, werden „Big Data“-Techniken als neue Arbeitsmethoden immer wichtiger. Grund genug, hier ein paar Überlegungen zu „Big Data“ und zur technologischen Basis anzustellen.

Der Begriff. Ganz grob gesprochen geht es bei „Big Data“ um die Verknüpfung verschiedener und umfangreicher Datenbestände. In der Hoffnung, neue Informationen bzw. Erkenntnisse gewinnen zu können, werden diese korreliert und analysiert; eine komplexe Jonglage also.

Google Trends verrät, dass seit 2009 „Big Data“ als Suchbegriff austritt und dann rasch relevanter wird. Die Methode ist im Kern nicht ganz so neu und baut ganz erheblich auf älteren Ansätzen wie Data Warehouse auf. Aber „Big Data“ ist eine umfangreiche Ansammlung verschiedener Technologien: Gartner hat einen eigenen Big Data Hype Cycle zusammengestellt, in dem das Thema in über drei Dutzend Teilgebiete differenziert wird. Trotzdem hat sich inzwischen eine allgemeine Charakterisierung für „Big Data“ entwickelt, welche um englische Begriffe kreist, die alle (mnemotechnisch günstig) mit einem V beginnen:

Die ersten drei Vs. Diese drei „klassischen“ Vs gehen auf einen steinalten Artikel von D. Laney aus dem Jahr 2001 zurück und heißen: Volume, Velocity und Variety.

Volume: Wie “Big Data” schon nahelegt, ist der schiere Umfang der verwendeten Daten eine wichtige Kenngröße. Während man heute sicherlich einige Terabyte (10^12) aufbieten können muss, treibt einige Leute schon die Sorge um, dass irgendwann die Präfixe knapp werden könnten und bringen Brontobytes (10^27) ins Gespräch …

Velocity (Schnelligkeit): Hiermit ist die Geschwindigkeit gemeint, mit der Daten erzeugt, verarbeitet und analysiert werden. Auch die Analyse während der Erzeugung, also eines Datenstroms, ist eine besondere Ausprägung dieses Merkmals.

Variety (Verschiedenheit): Die gemeinsame Verwendung von Daten aus unterschiedlichen Quellen sowie von strukturierten und unstrukturierten Daten ist ebenfalls typisch. Dies ist auch eine echte Weiterentwicklung des sehr strukturierten Data Warehouse Ansatzes.

Noch mehr Vs. Nach den genannten drei Vs kamen aber noch weitere Merkmale dazu:

Veracity (Wahrhaftigkeit): Dieses Charakteristikum greift den spannenden Umstand auf, dass auch Daten ausgewertet werden, die inkonsistent oder nicht sonderlich vertrauenswürdig sind. Man ahnt schon, dass dies ganz neue Herausforderungen mit sich bringt.

Variability (Veränderlichkeit): Diese besondere Ausprägung spielt eine Rolle, wenn Daten aus einer Sprachverarbeitung heraus verwendet werden. Dann kann sich die Bedeutung der Daten selbst verändern.

Visualisation (Veranschaulichung): Gerade die Analyse des Datenmaterials ist eine ziemliche Herausforderung. Der eingangs erwähnte WDR-Beitrag enthält auch ein paar mahnende Fehlinterpretationen, denen man ganz leicht aufsitzen kann. Für ein wirkliches Verständnis der „mutmaßlichen Befunde“, ist eine Veranschaulichung bereits in der Analyse unabdingbar. Zur Darstellung der Ergebnisse ist das weite Gebiet der Infographiken ein wichtiges Hilfsmittel. [1] [2] [3] [4]

Und noch ein V. Als siebtes (und bislang) letztes V findet sich

Value: Das ist eigentlich die „Sinnstiftung“ von Big Data, nämlich die Erinnerung, dass eine nützliche, wertvolle Erkenntnis am Ende der Übung stehen soll.

Weitere und ausführlichere Darstellungen finden sich im Web reichlich [5], [6].

Big Data = Technik + Algorithmik + Analytik? Die Charakteristiken von „Big Data“ scheinen mir nahe zu legen, dass hier drei Schichten zusammengebracht werden müssen, um ein fundiertes und werthaltiges Ergebnis zu erreichen:

  1. DieTechnik, welche die Voraussetzungen zur Haltung und Verarbeitung von Daten ist. Diese kann natürlich als Service im Sinn des Cloud-Paradigmas realisiert werden.
  2. Die Algorithmik, also die Konstruktion oder Wahl geeigneter Software zur Auswertung der Daten.
  3. Die Analytik, welche Hypothesen aus der Auswertung falsifiziert oder validiert, um ein Verständnis der Aufgabenstellung zu erreichen. Auf dieser Ebene ist die Semantik der Ergebnisse der dominierende Aspekt.

Die sieben Charakteristiken von Big Data sind nicht alle gleichermaßen auf diesen Schichten ausgeprägt. Vielmehr sind einige Schwerpunkte evident:

Technik Algorithmik Analyse
Value Stark
Visualisation Stark
Variability Mittel Stark
Veracity Stark Stark
Variety Stark Stark
Velocity Stark Stark
Volume Stark Mittel

Dass sich die drei „klassischen Vs“ – Volume, Velocity und Variety – in der Technik- und Algorithmik-Schicht besonders deutlich niederschlagen, ist wenig überraschend. Bei Veracity und Variability steht schon per definitionem die Semantik der Daten im Mittelpunkt.

Nun noch ein paar Überlegungen zur Speicherung und dem Management von Daten im Big Data Kontext.

 

Big Data und die IT-Infrastruktur

Traditionelle Speicher-Architekturen. Das Speichern und Verwalten von Daten kann auf recht unterschiedliche Weise erfolgen. Auf einer ziemlich tiefliegenden Technikebene können beispielsweise „Block Devices“ genutzt werden, um Portionen von Bytes zu schreiben und zu lesen. Das ist flexibel und performant, aber mühselig und eher für Experten geeignet. Anwender arbeiten normalerweise mit Dateisystemen oder auch (im Fall hochgradig strukturierter Daten) relationalen Datenbanken. Dateisysteme organisieren die einzelnen Dateien in einer Hierarchie und bieten oft Features wie Zugriffsteuerung, Versionierung, Replikation. In der Big Data Welt wird aber immer häufiger von Objekt-Speicher gesprochen, der die guten alten Filesysteme ablösen wird. Warum wird das so sein?

Objekt-Speicher. Das Konzept des Objekt-Speichers beruht auf dem Ansatz, die Details der Speicherung wie etwa Speicherort zu verbergen. Mit dem Speicherobjekt kann nur über eine definierte, schlanke Schnittstelle interagiert werden. Konkret besteht das Speicherobjekt aus einer eindeutigen Identitätskennung (ID), Metadaten, einer Menge von Standardmethoden (in der Regel ein API mit den CRUD-Aktionen – und häufig Accounting für die Cloud) sowie dem eigentlichen Dateninhalt. Das unterscheidet sich sehr erheblich vom Filesystem: Da der Speicherort verborgen ist, gibt keine Hierarchie (sondern nur die ID). Raffinierte, mächtige Features sind im Objekt-API nicht implementiert.

Das klingt auf den ersten Blick nicht besonders verlockend. Allerdings kommen mit diesem Ansatz auch Vorteile:

  1. Der Zugriff über eine ID und ein API ist einfach zu standardisieren. Verschiedene Speicher können dann gleichartig genutzt werden.
  2. Der Umgang mit Datenobjekten über ein API, also von einer Anwendung aus, ist grundsätzlich einfacher als das hantieren mit Dateien. Dabei muss nämlich mit dem Betriebssystem eines Servers oder aber einem Netzwerkprotokoll interagiert werden, was typischerweise ziemlich komplex und variantenreich ist.
  3. Die Objekt-Metadaten können im Prinzip erweitert werden, was Dateisysteme meist nicht vorsehen.
  4. Das Datenmanagement kann erheblich flexibler und weitreichender agieren, weil der Speicherort vor den Nutzenden verborgen ist. Dadurch können mehr steuernde und optimierende Eingriffe transparent durchgeführt werden.
  5. Im Zusammenspiel mit den Objekt-Metadaten kann das Datenmanagement besser automatisiert werden. Bei Filesystemen ist dies nur bei speziellen HSM-Lösungen möglich.
  6. Durch die Entkopplung von Nutzung und Management können horizontal skalierende Lösungen (scale out) einfacher realisiert werden.

Vorteile sind also sowohl in der Datennutzung als auch im Datenmanagement zu erwarten, wobei es hauptsächlich um Standardisierung, Automatisierung und Flexibilisierung geht.

Volume, Velocity, Variety und Speicher-Objekte. Bezüglich Volume und Velocity sind die Vorteile des Objektspeichers bezüglich des Datenmanagements (also 4, 5 und 6) relevant. Bei riesigen Datenmengen mit erheblichen Veränderungsraten wird die Transparenz und Automatisierung von Management-Aktivitäten immer wichtiger, da dies Einschränkungen bei der Verfügbarkeit reduziert und einen „smarten“ Umgang bei Lastwechseln ermöglicht.

Während die Nutzenden stärker von Fragen der Kapazitätsplanung entlastet werden können, verbleibt ihnen die Bürde des Umgangs mit den unterschiedlichen Datenquellen. Die Komplikationen, die sich aus der Variety ergebenen könnten, werden beim Objekt-Speicher aber durch die einfachere und einheitliche Schnittstelle aus ID und API (also 1, 2 und 3) entschärft.

Für die interaktive Standardnutzung im Büroalltag werden Filesysteme sicherlich weiterhin ihre Bedeutung behalten, denn dort ist die hierarchische Organisation oft sehr sachgemäß. Für die Nutzung von Speicherbeständen aus Anwendungen heraus, welche diese dann komplexe Analysen in diesen Beständen durchführen, sind Objekt-Speicher aber zweifellos die bessere Wahl.

Es wird spannend sein, wie sich Nachfrage und Angebot in den nächsten Jahren an unserer Universität entwickeln werden. Gartner gelangt übrigens zu dem Schluss, dass Big Data im Jahr 2014 die Hype-Cycle-Phase des „Trough of Disillusionment“ erreicht hat. Good Luck, Big Data!

 

Weitere Informationen

Provost, F.; Fawcett, T.: Data Science for Business; O’Reilly; 2013

Strg+Alt+Entf unter Windows bei iMac mit deutscher (Bluetooth-)Tastatur

Auf meinem älteren iMac (Late 2009) mit deutscher, schnurloser Bluetooth-Tastatur nutze ich regelmäßig eine Windows7-Bootcamp-Installation. Der Anmeldevorgang beginnt bei der Standardeinstellung mit der Tastenkombination „Strg-Alt-Entf“, die ich (ohne Keyboard Remapping oder Verwendung eines anderen USB-Keyboards) der Apple-Tastatur nicht entlocken kann. Aber so kann man es beim Anmeldebildschirm erreichen:

1. Bildschirmtastatur einblenden (links unten)

2. Tastatur-Layout auf „Englisch (USA)“=“EN“ umschalten (links oben)

3. Auf der Bildschirmtastatur Ctrl-Alt-Del eingeben. Dies erzielt die erwünschte Wirkung.

Die Regel, welche diese Eingabe erfordert, kann beispielsweise mit dem Tool „netplwiz“ deaktiviert werden. Dazu einfach (als Admin) „netplwiz“ als Kommando ins Eingabefeld des Startmenüs eingeben.

 

Streaming auf AppleTV über Subnetzgrenzen hinweg

airplay_appletvMit dem Update auf Softwareversion 6.1 bekam das AppleTV in Verbindung mit iOS 7.1 und höher ein neues Feature: AirPlay Discovery via Bluetooth. Dies ermöglicht nun viel einfacher die Verbindung zwischen AppleTV und AirPlay-Klienten, wenn sich diese nicht im selben IP-Subnetz befinden. Einrichtungen mit vielen IT-Anwendern sind gezwungen, einzelnen Abteilungen oder Arbeitsgruppen eigene getrennte IP-Subnetze zuzuordnen. Oft wird dem WLAN-Netz auch ein eigener IP-Bereich zugewiesen. Befindet sich das AppleTV dann netztechnisch im IP-Bereich einer Arbeitsgruppe, müssen die Klienten einige Barrieren überwinden.

Haben beide Geräte Bluetooth aktiviert und die aktuelle Softwareversion installiert, wird auf dem iPad/iPod/iPhone das AppleTV angezeigt. Unter Umständen ist jedoch keine Kommunikation zwischen den Klienten möglich. AirPlay erfordert, dass vom AppleTV eine neue TCP/UDP-Session zum Endgerät aufgebaut werden kann, obwohl die ursprüngliche Session vom Endgerät initiiert wurde.

Damit schließt AirPlay Umgebungen aus, die NAT mittels Port-Addresstranslation durchführen. Diese Hürde kann man jedoch durch Aufbau einer VPN-Verbindung überwinden. Verteilt das VPN-Gateway jedem Endgerät eine eigene IP, kann so doch AirPlay eingesetzt werden.

Nun müssen gegebenenfalls noch Freigaben eingerichtet werden, wenn die Subnetze durch eigene Firewalls abgesichert sind. Leider verwendet AirPlay dynamische Ports, so dass ganze Bereiche freigegeben werden müssen. Dabei verläuft die Kommunikation von hohen Ports (49152 – 65535) zu hohen Ports.

Folgende Freigaben sollten eingerichtet werden:Firewallregeln

Je nach Firewall-Typ müssen auch die Rückantworten zu den fünf Freigaben eingetragen werden, also Quellnetz/-port und Zielnetz/-port vertauscht.

Mit diesen Freigaben sollte AirPlay funktionieren. Wir konnten mit den gewählten Einstellungen Videos, Musik und den Bildschirminhalt erfolgreich auf das AppleTV streamen.

Projekt Mepevea – D’r Zoch kütt!

Als umweltbewusster oder zumindest geiziger Mitarbeiter des Öffentlichen Dienstes verzichtet man in der Regel bei längerer Anfahrt zum Arbeitsplatz auf den privaten PKW und nimmt freudig am öffentlichen Personennahverkehr (ÖPNV) teil. Sprich: Die Deutsche Bahn (und in Köln auch die KVB) ist unser Freund! Gerüchteweise sind die bereitgestellten Verkehrsmittel nicht immer dann vor Ort, wenn man es laut Fahrplan erwarten könnte. Damit man die daraus resultierende Wartezeit nicht am Bahnsteig, sondern am Frühstückstisch bzw. im bequemen Bürosessel verbringen kann, sind aktuelle Informationen über die Verspätungen unerlässlich.

Nun hat sich in der Vergangenheit der Service der DB dahingehend deutlich verbessert. So sind die Verspätungsinformationen inzwischen minutengenau und in Realzeit sowohl im Web als auch mittels der App „DB Navigator“ abrufbar. Der o.g. Mitarbeiter des Ö.D. ist allerdings nicht nur geizig (jaja, und umweltbewusst), sondern auch klickfaul und noch dazu ein Spielkind. So kam ich auf die Idee, sowohl in meinem trauten Heim als auch im Büro mittels ohnehin vorhandener Technik einen (für mich) optimalen Anzeigebildschirm zu basteln.

Dieser sollte nicht nur die aktuellen Verspätungen meiner Zugverbindungen, sondern auch weitere interessante Informationen anzeigen, genauer gesagt: Aktuelle Nachrichten, Wettervorhersage und (zuhause) zusätzlich das Kamerabild einer per WLAN verbundenen IP-Kamera. Als Hardware kamen ein günstiger und dank Notebook-Anschaffung ohnehin kaum noch gebrauchter PC-Bildschirm sowie zeitgemäß ein Raspberry Pi zum Einsatz. Das System sollte in jedem Fall ohne weitere Peripherie, speziell ohne Maus und Tastatur, auskommen. Softwareseitig setzte ich daher auf Google Chrome im Kiosk-Modus. Mittels der Erweiterung „Easy Auto Refresh“ kann man dafür sorgen, dass Chrome die angezeigte Seite automatisch einmal pro Minute neu lädt. Das Kamerabild läuft ohnehin im Streaming-Mode.

Der graphische Desktop des Raspi musste so eingestellt werden, dass er sich nicht automatisch abschaltet. Die Kontrolle über die Anzeige sollte ausschließlich per Ein/Aus-Knopf des Monitors ablaufen. Dies erreicht man über die eine Einstellung in LightDM.

Da ich mir die Installation und Konfiguration eines Webservers sparen wollte, verwende ich eine einfache lokale HTML-Seite auf dem Raspi. Die beiden gewünschten Elemente „Aktuelle Nachrichten“ und „Wettervorhersage“ sind sehr leicht über passende Widgets realisierbar. Ich habe hierzu die Angebote von wetterdienst.de und rp-online genutzt, es gibt jedoch zahlreiche weitere Anbieter.

mepevea

Richtig interessant wurde es dann bei der Einbindung der Verspätungsanzeige. Wie ich feststellen musste, bietet die Bahn leider keine geeignete API zu diesem Zweck. Mir blieb nichts anderes übrig als die entsprechende Webseite zu parsen. Diese Erkenntnis war die Geburtsstunde von Projekt „Mepevea“ (MEin PErsönlicher VErspätungsAnzeiger).

Wie erwähnt wollte ich auf die Installation und den Betrieb eines Webservers verzichten. Die Anzeige soll ja ohnehin nur für mich persönlich laufen. Daher musste ich die eigentliche Logik nebst Parser in ein Pythonskript packen, welches per Cronjob aufgerufen wird (ja, ich arbeite unter Linux und ignoriere Windows seit Jahren – die Portierung sollte aber kein großes Problem darstellen). Als Basismodul für den Parser dient natürlich „BeautifulSoup“, darüber hinaus werden urllib zum Abruf der Seite und einige weitere Module benötigt. Der Start lautet also:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import bs4, urllib2, time, fileinput, sys, urllib

„fileinput“ verwende ich, um später den <div>-Block im HTML durch die korrekten Daten auszutauschen, z.B.:

for line in fileinput.FileInput("/home/pi/anzeige/bahnlinks.html",inplace=1):
if line.startswith('<div id="bahn">'):
   line = text
   sys.stdout.write(line)

Natürlich macht es Sinn, abhängig vom Wochentag und der Tageszeit die Anzeige zu variieren (Hinfahrt, Rückfahrt, Abend/Wochenende), also z.B.:

timestamp = time.localtime(time.time())
if timestamp[6] > 4:
   textlist.append("<b>Bahnanzeige erst am Montag wieder! Schönes Wochenende!</b>")

Hier wird schon klar: Individuelle Anpassung ist unerlässlich und ich kann die Beispiele nur anreißen. Keine Sorge: Am Ende werde ich als „großes Beispiel“ mein komplettes Skript bereitstellen.

Zentrales Element des Skriptes ist die Parserfunktion. Sie erhält als Parameter die URL der Bahn (dazu später) und jagt sie durch BeautifulSoup:

def parser(url):
   page = urllib2.urlopen(url).read()
   soup = bs4.BeautifulSoup(page)

Man möge mir an dieser Stelle glauben, dass wir die spannenden Inhalte erhalten, wenn wir nach den Keywords, genauer gesagt den <td>-Klassen „overview timelink“ und „overview tprt“ suchen:


zeilen = soup.find_all('td', {"class" : "overview timelink"})
verspaetungen = soup.find_all('td', {"class" : "overview tprt"})

Schon hier erkannt man, wo das größte Problem unserer schönen Bastelei liegt: Sollte die Bahn die Klassennamen aus irgendwelchen Gründen ändern, funktioniert natürlich nichts mehr. Das gleiche gilt für die URLs und die HTML-Struktur. Genau aus diesem Grund gibt es ja i.d.R. kapselnde APIs, aber die stehen hier wie gesagt nicht zur Verfügung.

Standardmäßig erhält man von der Bahn die nächsten drei Züge ab dem definierten Zeitpunkt. Ich habe die finale Version noch so erweitert, dass man dies variieren kann, aber das würde hier zu weit führen. Ebenso müsste ich nun eigentlich auf die Details von BeautifulSoup eingehen, um den folgenden Codeblock zu erläutern. Aber auch dies möchte ich mir sparen und auf die gute Online-Dokumentation des Moduls verweisen. Unsere Verbindungen sowie die aktuellen Verspätungen erhalten wir so:


parsedtext = ''
zaehler = 0
for zeile in zeilen:
   for zelle in zeile.children:
      parsedtext += zelle.contents[0]
   parsedtext += '<span style="color: red;">'
   for verspaetung in verspaetungen[zaehler].children:
      if str(verspaetungen[zaehler]).count("okmsg") > 1 or str(verspaetungen[zaehler]).count("red") > 1:
         parsedtext += verspaetung.contents[0]
         break
   parsedtext += '</span>'
   zaehler += 1

Ich bin mir zu 99% sicher, dass dies nicht die eleganteste Version ist, um die Informationen zu erhalten und aufzubereiten. Aber sie funktioniert. Wer das Ganze kürzer, schöner und verständlicher hinbekommt, ohne dass die Funktionalität leidet, möge sich bei mir melden.

Kommen wir nun zu den benötigten URLs. In einer ersten Version hatte ich pro Zug eine URL auf Basis des Bahntools „query2.exe“ verwendet, die auch deutlich einfacher zu parsen war (Anmerkung: Bitte von der Endung „.exe“ nicht täuschen lassen: Es handelt sich um einen Webservice, nicht um ein lokales Programm.). Leider musste ich feststellen, dass die Bahn bei jeder (geplanten) Mini-Fahrplanänderung die URL komplett verändert. Auf Dauer war das also leider keine Lösung. Stattdessen verwende ich nun die „Vorstufe“ namens „query.exe“. Diese hat klar definierte und – hoffentlich – dauerhaft beständige Parameter. Als Parameter benötigen wir den Code des Startbahnhofs, den Code des Zielbahnhofs und die Startzeit.

Während die Startzeit natürlich jedem selbst überlassen bleibt und einfach in der Form hh:mm verwendet wird, muss man sich die Codes (sog. IBNR) der Bahnhöfe einmalig heraussuchen. Dies geht zum Glück sehr einfach mittels einer Onlinesuche.

Lautet die IBNR des Startbahnhofs bspw. 8000208, die des Zielbahnhofs 8000133 und die gewünschte Startzeit ist 17:00 Uhr, lautet die gesuchte URL:

http://reiseauskunft.bahn.de/bin/query.exe/dox?S=8000208&Z=8000133&time=17:00&start=1

Damit lässt sich nun für jede beliebige Verbindung und Kombination von Tageszeiten ein passender Anzeiger (eben ein „Mepevea“) bauen.

Für weitere Ideen, Verbesserungsvorschläge etc. bin ich jederzeit dankbar. Und wenn jemand die Bahn überreden könnte, doch mal eine entsprechende API bereitzustellen, das wäre ein Traum. 😉

Wie versprochen: Den vollständigen Text des Skriptes sowie eine Beispiel-HTML-Seite findet man unter http://dl.distinguish.de/mepevea.zip

Was ist ein CMS? Oder: Manchmal muss man das Einfache komplizierter machen, um das Komplizierte einfach machen zu können.

Die Uni Köln setzt schon seit vielen Jahren Content Management Systeme (CMS) für die Gestaltung ihrer Webseiten ein. Dabei werden verschiedenste Systeme bunt gemischt. Das Rechenzentrum setzt dabei auf TYPO3, für das ich als Webmaster verantwortlich bin.
Ich möchte hier auf kein spezielles CMS eingehen weil Joomla, Drupal, WordPress, TYPO3 und die vielen anderen Systeme vor der gleichen Aufgabe stehen. Die einen können das eine besser, die anderen etwas anderes, unterm Strich unterscheiden sie sich nicht viel.

Doch CMS werden häufig missverstanden. Im Gegensatz zu den Anfangszeiten des Internets, in denen jeder, der Webseiten erstellte, auch ein profundes Wissen über die zugrundeliegende Technik hatte, ist – zumindest an der Uni – die Verantwortung für die Erstellung von Web-Inhalten längst von den „Techies“ weg-gewandert und zählt nun im Grunde zur normalen Büro- und Schreibarbeit.

Das Internet lässt sich jedoch nur deswegen so kinderleicht bedienen, weil viele schlaue Köpfe sich die komplizierte Arbeit gemacht haben, es einfach zu machen.

Zudem wachsen – von vielen oft unbemerkt – die Anforderungen. Der Masse verborgen bleiben, zum Beispiel, die Bemühungen, die Webseiten auch für Sehbehinderte und Menschen mit anderen Handicaps bedienbar zu machen. Dies wird aber wieder interessant, wenn wir versuchen Webseiten mit unseren Smartphones und anderen Mobilgeräten zu bedienen.
Die neusten Generationen von Smartphones mögen mit ihren hohen Bildschirmauflösungen in der Lage sein, Webseiten darzustellen wie es ein Computer mit großem Monitor macht, aber die Schrift wird auf den kleinen Displays unleserlich klein, während – im Vergleich zur Bildschirmgröße – unsere Finger viel zu groß für Links sind, die für die Bedienung mit einem kleinen Mauszeiger optimiert sind.

Was ist „Content“?

Wikipedia bescheinigt Content Management Systemen: „Besonderer Wert wird bei CMS auf eine medienneutrale Datenhaltung gelegt. So kann ein Inhalt auf Wunsch beispielsweise als PDF- oder als HTML-Dokument abrufbar sein“.
In der Theorie schreibt ein Redakteur also seine Texte frei von den Beschränkungen des Mediums, welches zur Auslieferung der Inhalte verwendet wird. Die Inhalte wären in dieser Philosophie also reine Information.

Wer aber schon einmal unsäglich missverstanden wurde, weil eine eigene E-Mail vom Adressaten völlig anders interpretiert wurde, als sie gemeint war, weiß, dass die bloßen Wörter eines Texts nicht alle Informationen übertragen. Im persönlichen Gespräch kann man zusätzliche Gestik, Mimik, Betonung und dramatische Pausen nutzen. Im Geschriebenen versuchen wir diese Stilelemente mit Fettdruck, Kursivschrift, farbigen Unterlegungen und nicht zuletzt auch mit Smileys und anderen Emoticons zu simulieren.

Diese Methoden sind jedoch nicht „medienneutral“. Ein Farbenblinder übersieht vielleicht rote Unterlegungen. Und wie erklärt man einem Text-To-Speach-Programm, wie es von Blinden benutzt wird, was ein kursiver Text ist, und wie dieser vorzulesen ist?
Es ist aber nicht nur die Barrierefreiheit, in der Industrie werden teilweise „Hands-Free“-Systeme nachgefragt, wie Sie sie vielleicht von (SMS-)Vorlesefunktionen neumodischer Autoradios kennen.
In vielen Bereichen ist es einfach praktisch, sich das Medium, mit dem man Inhalte konsumiert jederzeit frei aussuchen zu können.

Ein weiteres Schlagwort ist dabei auch das „Semantische Web“. Gemeint ist dabei der Versuch, die Inhalte im Internet so aufzubereiten, dass Computer (Hauptsächlich die der großen Suchanbieter) auch die Bedeutung dessen verstehen, was auf einer Seite steht, anstatt Webseiten als einfache Zeichenketten zu betrachten. Wie viel besser wären Suchmaschinen, wenn sie unterscheiden könnten, ob ein Text von „Frau Rosa Blume“ handelt, oder von einer Blume, die rosa ist?

Wie kann mir ein CMS dabei helfen?

Natürlich muss zwischen der Theorie und dem praktisch Anwendbaren ein Kompromiss gefunden werden, der mal besser, mal weniger gut auf einen konkreten Anwendungsfall passt.

Die meisten Content-Managemant-Systeme haben natürlich ein Hauptausgabemedium, welches in den allermeisten Fällen eine normale Webseite ist. Daher werden von den meisten CMS Rich-Text- oder gar vollständige WYSIWYG-Editoren angeboten. Die Funktionen (Textstil, Überschriften, Absätze, Einrückungen, Einfügen von Tabellen und Bildern…) kennen die meisten aus Office-Programmen. Und an dieser Stelle kommt es häufig zu einem Missverständnis: Ein CMS ist kein Word. Man arbeitet nicht auf einer freien weißen Seite, dessen Layout frei bestimmt werden kann, sondern eher auf einem Formular mit Textbereichen, welche mit Inhalt gefüllt werden sollen.
Idealerweise positioniert man also nicht die Elemente, sondern man zeichnet sie aus, um die fehlenden Informationen medienneutral und für den Computer verständlich nachzutragen.

Beispiele:

Will man einen Textabsatz, zu dem ein Bild gehört, anlegen, so wäre es nicht medienneutral cm-genau oder Pixel-weise die Position des Bildes zu bestimmen. Besser wäre es, den Text und das Bild zu speichern und die Beziehung dazwischen einzutragen. Diese Text-Bild-Beziehungen könnten sein:

  • „Das Bild ist eng mit dem Inhalt des Textes verknüpft, beide bilden eine Einheit, der Text sollte das Bild umfließen.“
  • „Das Bild begleitet den Text eher lose, und kann auch einfach daneben stehen.“
  • „Der Text, erklärt das Bild, welches der eigentlich wichtige Inhalt ist. Das Bild sollte also so groß wie möglich dargestellt werden, und der Text darunter stehen.“

Dies ist natürlich nur ein kleiner Auszug der Möglichkeiten, die so vielseitig sein können, wie die Menschen, welche die Inhalte erstellen. Um dies also nicht allzu sehr ausufern zu lassen, wird ein CMS daher eher vereinfachte Optionen anbieten, ohne auf den konkreten Grund für die Text-Bild-Beziehung einzugehen:

  • „Text mit Bildumfluss“
  • „Text mit Bild daneben“
  • „Text mit Bild darüber“

Ein anderes Beispiel ist ganz pragmatischer Natur: Wichtige Textpassagen werden gerne rot markiert. Wenn man mal von den Schwierigkeiten von Menschen mit Rot/Grün-Schwäche absieht, kann das Problem entstehen, dass bei einem Wechsel des Designs diese Passage unleserlich wird, wenn sich auch die Farbe des Texthintergrundes im neuen Design geändert hat. Häufiger ist aber der Fall, dass die konkret gewählte Farbe nicht mehr mit dem Farbkonzept des Designs harmoniert. Vorleseprogramme kommen hier, wie gesagt, ebenfalls an ihre Grenzen.
In diesem Fall ist es ratsam, den Textteil als „wichtig“ zu markieren. Im Design würde man dann wiederum definieren, wie „wichtiger Text“ dargestellt werden soll – dies kann dann wieder, wenn es zum Design passt, rot sein, später aber leicht von zentraler Stelle dem Design entsprechend geändert werden können.

Dem Semantischen Web würden hier natürlich Auszeichnungen helfen, die besagen „Das ist ein Name“, „Hier steht eine Adresse“ oder auch „Dies ist ein Akronym“. Von Suchmaschinen ausgewertet, könnte man schnell Suchanfragen formulieren, die einem zum Beispiel alle Seiten anzeigen, auf denen eine bestimmte Person erwähnt wird. Dies ist jedoch – zumindest bei redaktionell erstellten Texten – Zukunftsmusik, für die aber derzeit die Grundlagen geschaffen werden.

Natürlich kann nicht mit allem so abstrakt verfahren werden, und dem Redakteur sollen durchaus noch Möglichkeiten bleiben, seine Inhalte auch optisch ansprechend zu gestalten. Ob ein Bild im Text Rechts oder linksbündig sein soll, um die Gesamtseite aufzulockern, oder ob er zum Verdeutlichen von Zusammenhängen auch Farbmarkierungen anbringen kann, auf die in nicht-visuellen Darreichungsformen verzichtet werden kann, sollte ihm dabei offen stehen.
Dennoch sollte man das Credo „Weniger ist manchmal mehr“ nicht aus den Augen verlieren und hin und wieder einen Kompromiss eingehen, um in der Zukunft weniger Probleme zu haben.

Fazit:

Zwischen dem utopischen Ideal, alle Informationen mitsamt aller Metadaten zu jeder Zeit und über jede denkbare Kommunikationsform in jeweils bester Weise zur Verfügung gestellt zu bekommen, und einem aramäischen Pergament, welches Sie nur nach jahrelangem Studium entziffern können, liegt irgendwo ein Kompromiss, der die Kommunikation für uns alle vereinfacht. Dazu ist es also manchmal nötig, etwas weniger darüber nachzudenken, wie ich einen Inhalt grafisch aufbereite, und dafür etwas mehr darüber, warum ich ihn genauso haben möchte, wie ich mir das vorgestellt habe.
Oder überspitzt ausgedrückt: „Frage nicht (immer) was das CMS für Dich tun kann, frage auch mal, was Du für das CMS tun kannst (damit es Dich besser versteht)“

MySQL-Upgrade wie es sein sollte

Nicht, dass ich im Allgemeinen zu extremer Prokrastination neige, aber im Falle des netten kleinen ToDos „Update der MySQL-Server auf 5.5“ bin ich eindeutig schuldig. Das schob ich nämlich bereits seit Ende 2012 leise vor mir her, da ich den Aufwand für außerordentlich hoch hielt. Zur Ausgangssituation: Aus historischen Gründen hatten wir eine recht heterogene Landschaft im Bereich MySQL-DB-Server, bestehend aus:

* 1 Master-Slave-Cluster, Version 5.1, basierend auf original MySQL-RPMs

* 2 Master-Slave-Clustern, Version 5.1, basierend auf IUS-RPMs

* 1 Master-Slave-Cluster, Version 5.5, basierend auf original MySQL-RPMs

* 1 Master-Master-Cluster, Version 5.1, basierend auf original MySQL-RPMs

Wohlgemerkt: Alle auf RHEL5! Die nun alle auf eine homogene Basis zu stellen (nämlich Version 5.5, basierend auf IUS-RPMs) und dabei sowohl die Daten als auch die Replikation leben zu lassen, schien nur durch komplette Dump-Restores mit zwischenzeitlicher Neuinstallation der Pakete zu funktionieren. Da wir hier über eine Datenmenge von insgesamt etwa einem Terabyte sprechen, rechnete ich mit einer ziemlich großen Downtime.

Ein wenig Recherche nach der optimalen Vorgehensweise brachte jedoch zutage, dass die Jungs und Mädels der IUS Community (http://iuscommunity.org), deren Repositories wir ja auch oft und gerne benutzen, tatsächlich auch an solche wirren Zustände gedacht haben. Genauer gesagt gibt es das hübsche Plugin „replace“ für die Paketverwaltung yum. Es lässt sich – natürlich nach Integration des IUS-Repos – per „yum install yum-plugin-replace“ installieren und eröffnet die Möglichkeit, yum mit der Option „replace-with“ aufzurufen.

So führt das folgende Kommando bspw. dazu, dass ein bisheriger 5.1-Server auf IUS-Basis nahtlos durch einen 5.5-Server ersetzt wird:

yum replace mysql51-libs --replace-with mysql55-libs

Der Wechsel ist aber – und das ist das eigentliche Erstaunliche – auch aus den MySQL-RPMs heraus möglich:

yum replace MySQL-server-community --replace-with mysql55-server

yum bzw. das Plugin löst selbst alle nötigen Abhängigkeiten auf. Ggf. beschwert es sich, dass die Herkunft einiger beteiligter Pakete nicht ermittelt werden konnte, dies kann man aber problemlos ignorieren.

Letztendlich war es mir so möglich, das gefürchtete Upgrade für alle Server in einer Stunde durchzuführen, ohne dass ich bislang ein Problem feststellen konnte. Einige Hinweise gilt es aber noch zu beachten:

  • Laut MySQL sollte immer der Slave zuerst aktualisiert werden.
  • Nach dem Upgrade von Slave und Master muss auf dem Master das Kommando „mysql_upgrade“ ausgeführt werden, um fehlende MySQL-Tabellen zu ergänzen. Zudem werden bei der Gelegenheit alle Tabellen geprüft und ggf. repariert.
  • Beim Wechsel von MySQL 5.5 aus MySQL-RPMs auf MySQL 5.5 aus IUS-RPMs musste ich zuvor manuell das Paket „MySQL-shared-compat“ entfernen. Das konnte das Plugin aus irgendwelchen Gründen nicht lösen.
  • Bei Statement-basierter Replikation wirft MySQL 5.5 im Gegensatz zu 5.1 Warnungen, wenn Anweisungen bspw. nicht-deterministische Ergebnisse liefern. Diese Warnungen waren nicht zu unterdrücken (jedenfalls habe ich den Schalter nicht gefunden), obwohl wir uns der Tatsache bewusst waren und die entsprechende Datenbank ohnehin von der Replikation ausgenommen hatten. Ein somit ohnehin fälliger Wechsel zum „Mixed“-Format war also unvermeidlich (Schalter „binlog-format = MIXED“)
  • In MySQL 5.5 fallen einige Konfigurationsoptionen weg bzw. sollten durch ihre Nachfolger ersetzt werden. Die Ersetzung kann bereits vor dem Upgrade in der my.cnf durchgeführt werden. Aufgefallen sind bei mir:
    • skip-locking
    • log-err (ersetzt durch log-error)
    • key_buffer (ersetzt durch key_buffer_size)
    • thread_cache (ersetzt durch thread_cache_size)

Mediawiki und LDAP – „Wollen Sie sich wirklich sperren?“

Ein lange gehegter Wunsch war die Anbindung der zentralen Mediawiki-Installation an die LDAP-Authentifizierung. Dank der Mediawiki-Erweiterung „LDAPAuthentication“ war dies prinzipiell auch überhaupt kein Problem. Dann aber kamen seltsame Fehlermeldungen, dass Benutzer plötzlich gesperrt seien, die definitiv noch Zugang zum Wiki haben sollten. Hier muss man nun wissen, dass nicht alle Wiki-User im LDAP verzeichnet sind, sodass zusätzlich auch lokale Accounts parallel existieren müssen. Also gibt es auch unabhängig vom LDAP die Möglichkeit, Benutzer direkt in Mediawiki zu sperren.

Ein Test meinerseits ergab die schöne Fehlermeldung „Sie sind dabei sich selbst zu sperren. Wollen Sie das wirklich?“ Okay, irgendwie geraten also die User bei der Sperrung durcheinander. Aber warum? Die Lösung fand ich in den Tiefen des PHP-Codes von Mediawiki, indem ich alle beteiligten Funktionen nacheinander durchtestete. In der Datei „functions/User.php“ heißt es in der Funktion „newFromName“:

$name = $wgAuth->getCanonicalName( $t->getText() );

Der LDAP-Server wird also nach dem kanonischen Namen des Users gefragt. In der Regel einfach nur unnötig, führt es genau hier sogar zu einem sehr unerfreulichen Ergebnis: Existiert der User nämlich nicht (mehr) im LDAP, werden ungültige Werte zurückgegeben. Dies führt dann dazu, dass plötzlich ein ganz anderer User – in diesem Fall z.B. ich selbst – als „Target“ dient.

Eine Änderung der o.g. Zeile brachte dementsprechend das gewünschte Verhalten:

$name = $t->getText();

Anmeldephase für die Computerkurse hat begonnen!

Ab sofort können sich alle Studierende und Beschäftigte der Uni Köln (und anderer Hochschulen in NRW) für die Computerkurse des RRZK in den kommenden Semesterferien anmelden.

Unter anderem gibt es Kurse in den Bereichen Betriebssysteme, Rechnersicherheit, Programmierung, Office-Anwendungen, Grafik und Multimedia, Statistik, Mathematik-Software, e-Learning und Literaturverwaltung.

Kursverzeichnis und Anmeldung unter: http://rrzk.uni-koeln.de/kursangebot.html

SoFS-Nutzung von Android Tablets

Bislang gab es nur Hinweise, wie SoFS von Windows und MacOS aus nutzbar ist. Aber auch von Android aus kann man dank Webdav gut auf SoFS zugreifen. Man installiert sich dazu aus dem Google Playstore zunächst den „Total Commander“ und darin dann das Webdav plugin. Dieses dann mit https(!) checken, sofsdav.uni-koeln.de/private/<username> als pfad, username und password konfigurieren und fertig! Dem Hin- und Her-Kopieren von Dateien zwischen Android-Device und SoFS steht nur noch die verfügbare Bandbreite im Wege…