Daten|teiler
Kopieren als Kulturtechnik

Symbian für Schlangenbeschwörer

5. September 2010 von Christian Imhorst

Dieser Artikel erschien erstmals in freiesMagazin 09/10: Vergleicht man Symbian mit neueren Betriebssystemen für Smartphones, wirkt es doch recht altbacken. Böse Zungen behaupten sogar, dass es das Windows 98 der mobilen Betriebssysteme sei, weil die Oberfläche seit gefühlten 10 Jahren gleich aussieht. Die Unterstützung von Open-Source-Software ist bei Symbian allerdings vorbildlich modern. Zum einen ist das Betriebssystem selbst mittlerweile Open Source [1] und zum anderen werden etliche Werkzeuge an die Hand gegeben, um freie Software zu schreiben. Eines dieser Werkzeuge heißt Python, das Nokia 2005 auf die S60-Plattform portiert hat. Da die Einarbeitungszeit für Programmieranfänger kürzer ist als in C++, kann man schnell lauffähige Programme entwickeln, die durch Module flexibel erweiterbar sind. Es ist die perfekte Gelegenheit für Freunde von GNU/Linux, Solaris oder einem BSD-System, eigene Programme zu schreiben und ihr Handy für ein größeres Aufgabengebiet fit zu machen.

Installation

Nachdem man überprüft hat, ob das eigene Handy zur S60-Reihe gehört [2], benötigt man die die Datei PythonForS60_2.0.0.tar.gz von der Webseite garage.maemo.org [3]. Von der Versionsnummer darf man sich nicht irritieren lassen; Python für S60 2.0 liegt Python 2.5.4 zugrunde. Nach dem Entpacken überträgt man die Dateien Python_2.0.0.sis, pips.sis und PythonScriptShell_2.0.0_3_0.sis aus dem Ordner PyS60Dependencies entweder per Bluetooth, USB-Kabel oder WLAN [4] auf das Telefon. Anschließend installiert man sie in dieser Reihenfolge in den Telefonspeicher. Die Installation muss in den Telefonspeicher und darf nicht auf die Speicherkarte erfolgen, da Python-Programme ansonsten Probleme haben, den Python-Interpreter zu finden.

Nach der Installation

Jetzt gibt es verschiedene Möglichkeiten, Python-Programme auf dem Handy auszuführen. Die einfachste ist, das Programm gleich auf dem Telefon zu tippen. Dazu öffnet man die Python-Shell und wählt „Interactive console“. Je nach Tastatur kann das Tippen auf dem Handy sehr anstrengend sein; der schöne Nebeneffekt ist aber, dass man auch in der S-Bahn oder an der Supermarkt-Kasse mit einem Python-Editor wie Ped [5] programmieren kann. Die Menschen um einen herum denken dann, dass man sehr beliebt sein muss, weil man eine SMS nach der anderen schreibt, und man wird ausnahmsweise mal nicht für einen vereinsamten Ober-Geek gehalten.

Eine Python-Shell fürs Handy

Im Lieferumfang von Python für S60 gibt es zwar schon eine Bluetooth-Konsole [6], die man auch sehr komfortabel mit den PUTools bedienen kann [7], aber was macht man, wenn kein Bluetooth, dafür aber WLAN vorhanden ist? Man richtet sich einfach eine Python-Shell übers WLAN ein. Die Verbindung zur WLAN-Shell steht auch schneller als die über Bluetooth, was ein entscheidender Vorteil ist, selbst wenn der Rechner über eine Bluetooth-Schnittstelle verfügt.

Damit die Python-Shell über WLAN funktioniert, benötigt man das Programm netcat, das im Normalfall unter GNU/Linux, Unix oder MacOS X schon installiert ist. Mit dem Befehl nc startet man das Kommando, um Daten mit TCP im Netzwerk zu übertragen:

stty raw -echo ; nc -l 1025 ; stty sane

Auf einigen GNU/Linux-Rechnern muss man noch den Schalter -p hinzufügen und nc -l -p 1025 eingeben. Bevor man das Terminal via netcat in eine Python-Shell des Handys verwandeln kann, werden dessen Einstellungen mit dem Systembefehl stty neu gesetzt. Dabei schaltet die Option raw die Pufferung aus, damit eine Eingabe Zeichen für Zeichen an die Shell weitergereicht wird. Buchstaben werden dabei uninterpretiert weitergeleitet, was soviel heißt, dass es kein Newline-Zeichen oder ähnliches mehr gibt und „Strg“ + „D“ zum Beispiel keinen Datenstrom mehr beendet. Die Option echo verhindert, dass die eingegebene Taste nochmal im Terminal angezeigt wird. Anschließend startet netcat, um auf hereinkommende Verbindungsanfragen am Port 1025 zu lauschen. Im letzten Teil des Kommandos startet man noch einmal stty, diesmal aber mit der Option sane, um die Pufferung des Terminals wieder herzustellen. Damit kann man die Python-Shell erneut mit der Tastenkombination „Strg“ + „D“ beenden.

Das folgende Skript für Ubuntu 10.04 vereinfacht die Verbindungsanfrage:

#!/bin/bash
# Script: wifishell.sh
# Object: Starts TCP/IP Console for S60 mobiles afterwards
# start wifishell.py on your S60
 
IP=$(ifconfig | grep 'inet '| grep -v '127\.0\.0\.1' | cut -d: -f2 | awk '{ print $1}')
PORT="1025"
 
echo "Your IP address is: $IP "
echo "Start now wifishell.py on your phone ..."
 
stty raw -echo ; nc -l 1025 ; stty sane

Im ersten Teil wird die IP-Adresse im eigenen Netzwerk ermittelt und in der Variable IP gespeichert, was aber nur für GNU/Linux-Rechner gilt. Verwendet man ein Betriebssystem wie MacOS X, Free-, Open- oder NetBSD, muss man stattdessen folgende Zeile in das Skript einfügen:

IP=$(ifconfig | grep -E 'inet.[0-9]' | grep -v '127\.0\.0\.1' | awk '{ print $2}')

Als Benutzer von OpenSolaris verwendet man folgende Zeile:

IP=$(ifconfig -a | grep 'inet ' | grep -v '127\.0\.0\.1' | awk '{ print $2}')

Wie bereits erwähnt, muss man bei manchen GNU/Linux-Betriebssystemen darauf achten, dass der Aufruf von netcat im zweiten Teil des Skripts mit den Schalter -p geschieht.

Das Gegenstück in Python, das Skript wifishell.py, muss auf das Handy kopiert werden. Wie alle anderen Python-Skripte auch, sollte es dort auf der Speicherkarte im Verzeichnis E:\Python\ liegen. Sobald wifishell.sh auf dem GNU/Linux-Rechner oder der Unix-Maschine nach Anfragen auf dem Port 1025 lauscht, startet man über die Python-Shell auf dem Telefon das Skript wifishell.py, um eine Verbindung zum Terminal auf dem Computer herzustellen. Läuft alles glatt, verwandelt sich das Terminal in eine Python-Shell auf dem Handy.

# Script: wifishell.py
# Object: Starts TCP/IP Console for S60 mobiles before start
# wifishell.sh on your Unix box
 
import btconsole, appuifw
import sys
try: # next lines are important to select an access point
    sys.modules['socket'] = __import__('btsocket')
except ImportError:
    pass
import socket
 
ip = appuifw.query(u"IP address:", "text")
port = 1025
 
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((str(ip), port))
btconsole.run_with_redirected_io(sock,btconsole.interact,None,None,locals())
sock.close()

Im Terminal sieht das dann so aus:

stty raw -echo ; nc -l 1025 ; stty sane
Python 2.5.4 (r254:67916, Nov  6 2009, 04:18:57) [C] on symbian_s60
>>> import appuifw
>>> appuifw.note(u'Hallo Welt!', 'info')

Hallo Welt!

Als erstes Programm in Python für S60 schreibt man klassischerweise eines, das „Hallo Welt!“ auf dem Bildschirm ausgibt. Das wird in diesem Fall schon mit einer grafischen Oberfläche gemacht, was ganz leicht ist. Man lädt dazu einfach das Modul appuifw.

>>> import appuifw
>>> appuifw.note(u'Hallo Welt!', 'info')

Im ersten Teil des Befehls erzeugt die Funktion note() des Moduls appuifw ein Hinweisfenster. Die Zeichenkette in der Klammer muss Unicode sein, daher das vorangestellte „u“. Die zweite Zeichenkette gibt an, dass es sich beim Fenster nur um eine Information handelt. Eine Aktion des Benutzers ist nicht gefordert und das Fenster verschwindet nach einer Weile von allein.

Der erste Programmierergebnis mit Python.

Neben appuifw für das Erstellen von Benutzeroberflächen können noch weitere spezielle Module für PyS60 in Programme importiert werden. Das sind e32 als Schnittstelle zum Betriebssystem, sysinfo liest Geräteinformationen aus, audio zeichnet Klänge auf und spielt sie ab, e32calendar ermöglicht den Zugriff auf den Kalender, camera auf die Kamera, contacts auf Kontakte, e32dbm auf die Datenbank, location auf die Standortinformationen, messaging auf SMS-Funktionen, telephone auf die des Telefons und graphics zeichnet grafische Elemente [8].

Mit jedem einzelnen Modul kann man eine Menge Sachen anstellen, zum Beispiel das Handy etwas sagen zu lassen:

import audio
audio.say(u"Hello World!")

Oder eine MP3-Datei abspielen:

 
import audio, e32
fn = u"e:\\Musik\\mymusic.mp3"
sound = audio.Sound.open(fn)
sound.play(times=1)
e32.ao_sleep(sound.duration()/1000000 + 3)
sound.close()

Oder ein kleines Skript schreiben, das per SMS um Hilfe ruft:

 
import messaging, appuifw
contact_number = "+49123456789"
contact_name = "Linus"
message = (u"SOS, ruf mich an.")
messaging.sms_send(contact_number, message, name=contact_name)
appuifw.note(u"Die Nachricht wurde gesendet", "info")

Dieses Skript könnte man weiter ausbauen: Statt um Hilfe zu rufen, könnte es eine automatisierte Antwort auf bestimmte SMS geben, oder man erweitert die Hilfe-SMS um eine Standortbestimmung mit dem Modul positioning, wenn das Handy GPS unterstützt, um seinen Standort mitzusenden.

Die Akku-Ladung wird normalerweise mit Strichen oder Balken angezeigt. Wer es genau wissen will, schreibt einfach ein kleines Skript mit sysinfo:

import appuifw, sysinfo
battery = sysinfo.battery()
appuifw.note(u'Battery: ' + str(battery) + ' %', 'info')

Als Dateien speichert man die Skripte in das Verzeichnis E:\Python\ auf dem Handy. Die Python-Shell schaut bevorzugt in diesem Ordner nach. Ausgeführt werden sie dann in der Python-Shell auf dem Handy, indem man „Run script“ und anschließend das Skript auswählt.

SIS-Pakete selber bauen

Nun kann es ganz schön lästig sein, immer diesen Weg einzuschlagen, wenn man mal kurz den Ladezustand überprüfen will. Einfacher ist es doch, gleich das Skript ohne Umweg über die Python-Shell zu starten. Dabei hilft das Programm ensymble [9]. Bei vielen Distributionen ist es in den Paketquellen enthalten, da es aber „nur“ ein Python-Skript ist, kann man die Datei auch einfach von der Webseite herunterladen. Mit ensymble gibt es allerdings ein kleines Problem: Das Skript benötigt Python 2.5. Das wird besonders diejenigen nicht freuen, die Ubuntu 10.04 „Lucid Lynx“ benutzen, da dort die älteste Python-Version 2.6 ist. Wer kein Python 2.5 besitzt, sollte es kompilieren, und zwar mit Zlib-Unterstützung. Die freie Programmbibliothek zum Komprimieren und Dekomprimieren von Daten ist bei Python 2.5 standardmäßig deaktiviert, wird aber von ensymble benötigt [10].

Ist ensymble heruntergeladen und steht Python 2.5 mit Zlib-Unterstützung bereit, müssen nur noch die Dateien ensymble.py, ein Skript (zum Beispiel das Skript für den Ladezustand des Akkus, das man batinfo.py nennen kann) und eine SVG-Datei als Icon im selben Ordner liegen. Für die SVG-Datei kann man sich für den Anfang gut bei den Icons des GNOME-Projekts unter /usr/share/icons/gnome/scalable bedienen, wenn man zu bequem ist, ein eigenes zu basteln. Dann kann die Verwandlung des Skripts in eine Installationsdatei für Symbian beginnen:

python2.5 ensymble.py py2sis --version=1.0.0 --icon=battery-low.svg --caption="Battery Info" --vendor="Christian Imhorst" batinfo.py batinfo.sis

Die Datei batinfo.sis lädt man anschließend auf das Handy und installiert es in den Telefonspeicher. Leider läuft das Programm nicht, wenn man es auf die Speicherkarte installiert, und es funktioniert natürlich nur auf Telefonen, auf denen auch Python für S60 bereits installiert ist. Nach der Installation findet man das Programm mit eigenem Icon im Installationsordner.

Das hochgeladene Skript findet man im Installationsordner wieder.

Zum Schluss …

… noch ein kleines Programm, um die Kalenderdatenbank des Telefons auszulesen und in einer Datei zu sichern. Die Termine kann man anschließend in den Kalender von Evolution oder Thunderbird importieren. Für solche kleinen Aufgaben ist Python für S60 einfach ideal:

# vcalendar export
import e32calendar, appuifw
 
cal = e32calendar.open()
if len(cal) == 0:
    appuifw.note( u"No calendar entries.", "info" )
id_list=list()
for id in cal:
    id_list.append(id)
 
vCal = cal.export_vcalendars(tuple(id_list))
 
# define the directory and file name
vCalendar = u"e:\\vCal.vcf"
 
# create file
file = open(vCalendar, 'w')
 
# write vcal into file and close the file
file.write(vCal)
file.close()
 
appuifw.note( u"Success!", "info" )

Zu Beginn des Skripts werden die beiden Module e32calendar für den Zugriff auf den Kalender und appuifw für Benutzeroberflächen geladen. Einmal teilt ein Hinweisfenster im Skript mit, dass es keinen Kalendereintrag gefunden hat, und am Ende, dass es erfolgreich fertig geworden ist. Die Funktion open() aus dem Modul e32calendar öffnet den Kalender und übergibt ihn an cal. Die einzelnen Einträge werden nacheinander einer Liste übergeben, die dann komplett in die Datei vCal.vcf geschrieben wird.

Literatur

Geschrieben in Gnu/Linux, Python