Drafts-Rezepte V: Wetterdaten mit OpenWeatherMap

Ich habe mir wieder ein kleines Skript (current_weather.py) gebastelt, mit dem ich für einen beliebigen Ort die aktuelle Temperatur und Luftfeuchtigkeit erhalte. Als Datenquelle dient die API von OpenWeatherMap, abgerufen wird es wieder über Pythonista. Das Skript sieht folgendermaßen aus:

# -*- coding: utf-8 -*-
import clipboard
from console import alert
from json import loads
from sys import argv, exit
from urllib import urlopen, quote
import webbrowser

def error_dialog(title, message):
  '''A diaolog box for error messages.'''
	try:
		alert(title, message)
	except KeyboardInterrupt:
		pass
	webbrowser.open('drafts://')
	exit(message)

def filter_data(data):
	'''create output string from response'''
	weather = loads(data)
	temperature = weather['main']['temp']
	humidity = weather['main']['humidity']
	output = 'Temperatur: {0} Celsius\nLuftfeuchtigkeit: {1}%'.format(temperature, humidity)
	return output

def get_current_weather_in(data):
	'''get current weather data'''
	api_url_base = 'http://api.openweathermap.org/data/2.5/weather?q={0}&units=metric&lang=de'
	try:
		response = urlopen(api_url_base.format(data))
	except IOError:
		error_dialog('Connection Error', 'Unable to perform request.')
	if response.getcode() == 200:
		weather_data = filter_data(response.read())
		webbrowser.open('drafts://x-callback-url/create?text={0}'.format(quote(weather_data)))
	else:
		error_dialog('Error', 'Status code: {0} - Message: {1}'.format(response.getcode(), response.read()))

if __name__ == '__main__':
	get_current_weather_in(argv[1])

Gist

Das Skript kann dann über die Drafts-Action ausgeführt werden:

pythonista://current_weather?action=run&argv=[[draft]]

Import-Link

Im Grunde war das auch schon alles. In Drafts muss dann in einer neuen Notiz nur der Name der Stadt eingegeben werden. Gegebenenfalls sollte sicherheitshalber noch das Land hinzugefügt werden. So würde Hamburg, de mir die aktuelle Temperatur und Luftfeuchtigkeit für Hamburg geben.

Drafts-Rezepte IIII: Hashes berechnen

Dann geht es fröhlich in der Reihe kleiner Skripte für Drafts und Pythonista weiter. Da ich hin und wieder mal Hashes als Prüfsummen benötige, hatte ich immer eigene Apps dafür auf dem iPhone. Da diese allerdings für ihren eigentlichen Zweck zu groß waren – sie waren allesamt auch noch hässlich -, habe ich sie nun durch folgendes Skript ersetzt. Das läuft bei mir ganz ordentlich.

Hierzu brauche ich wieder einen Action in Drafts, die in diesem Fall auf das Skript hasher in Pythonista zugreifen soll. Das sieht so aus:

pythonista://hasher?action=run&argv=[[draft]]

Import-Link

Etwas umfangreicher, daher auch erklärungsbedürftiger ist das Skript in Python. Dieses habe ich mal im Grunde angelegt, dass es wie ein Programm für die Shell genutzt werden kann.

# -*- coding: utf-8 -*-
import argparse
import clipboard
import hashlib
from sys import argv
import webbrowser

def hash_data(hashstring, hashfunction, url):
    '''Get the hash of given string.'''
    # Determine if a method for hashfunction
    # exists in hashlib. If no attribute/method is
    # found, default to sha1.   
    if hasattr(hashlib, hashfunction):
      hash_method = getattr(hashlib, hashfunction)
    else:
    	hash_method = hashlib.sha1

    # Put hash to clipboard, if hashstring exists.
    if hashstring:
    	clipboard.set(hash_method(hashstring).hexdigest())
    else:
        raise ValueError

    # Pythonista doesn't support x-callback.
    # So this is a pragmatic approach to calling
    # another app after hashing the string.
    webbrowser.open(url)

def parse_input(data):
    '''Parse input from Drafts command-line-like.'''
    parser = argparse.ArgumentParser(description='input a string to hash.')

    # Expects strings to hash.
    parser.add_argument('inputstring',
                        metavar='STRING',
                        nargs='*',
                        help='the string to hash')

    # Set the hash function.
    parser.add_argument('-hs', '--hs', '-hash', '--hash',
                        metavar='HASH-NAME',
                        default='sha1',
                        dest='hash',
                        help='the hash function of hashlib to use. defaults to sha1')

    # Intended to set a callback-like action.
    # Use to open a specific app via url scheme, if necessary. Otherwise will open Drafts.
    parser.add_argument('-u', '--u', '-url', '--url',
                        metavar='URL',
                        default='drafts://',
                        dest='url',
                        help='url scheme to call after hashing. use to call an app.')

    args = parser.parse_args(data)
    hash_data(' '.join(args.inputstring), args.hash, args.url)

if __name__ == '__main__':
    parse_input(argv[1].split(' '))

Gist

Ich muss also etwas erklären, was das Skript macht. Es kann drei Sorten von Input verarbeiten:

-hs (–hs, -hash, –hash) HASH_BEZEICHNUNG: Dieser Befehl ist optional und gibt die zu verwendenden Hashfunktion* an. Ist die Bezeichnung unbekannt oder falsch, wird der Standardwert ’sha1′ angenommen.

-u (–u, -url, –url) URL_SCHEMA: Dieser Befehl ist optional und gibt das URL-Schema einer aufzurufenden Anwendung an. Standardmäßig ist ‚drafts://‘ vorgegeben.

inputstring *STRING: Alle übrigen Übergabewerte werden zum Inputstring hinzugefügt, der gehasht wird.

Es lässt sich doch besser mit einigen Beispielen erklären. Nehmen wir mal folgenden Eingaben in Drafts an, wobei jede Zeile einer Eingabe entspricht:

Test

Test -s md5

Test -u tweetbot://

Test und noch mehr Test -s sha512

Die erste Eingabe würde den SHA1-Hash von ‚Test‘ berechnen, die zweite würde denselben String als MD5-Hash berechnen. Beide Eingaben führen dazu, dass nach der Berechnung in Pythonista wieder Drafts aufgerufen wird. Die dritte Eingabe berechnet den Standard, also SHA1, von ‚Test, kehrt aber nicht nach Drafts zurück, sondern öffnet Tweetbot (sofern es installiert wurde). Die letzte Eingabe nimmt ‚Test und noch mehr Test‘ und berechnet den SHA512-Hashwert für die Zeichenfolge.

* Laut der Dokumentation für Python 2.7, das von Pythonista genutzt wird, werden folgende Hashfunktionen unterstützt:

This module implements a common interface to many different secure hash and message digest algorithms. Included are the FIPS secure hash algorithms SHA1, SHA224, SHA256, SHA384, and SHA512 (defined in FIPS 180-2) as well as RSA’s MD5 algorithm (defined in Internet RFC 1321).

Drafts-Rezepte III: hAppy

Ein kleines Häppchen zwischendurch für den meines Erachtens grundsätzlich sympathischsten Client für ADN, den ich auf iOS finden konnte. hAppy* ist eine Grinsebacke. Es unterstützt auch einige Aktionen über das URL-Schema. Nicht alles lässt sich hier praktisch umsetzen. Sinnvoll sind aus meiner Sicht diese Actions, um sie aus Drafts zu starten.

Neuen Post erstellen

happy://create?text=[[draft]]

Link-Import

Post anzeigen
Eigentlich eine schöne Sache, allerdings müssen wir für die Posts ihre numerische ID angeben.

happy://post?postId=[[draft]]

Link-Import

Profil anzeigen
Auch hier ist die ID ein numerischer Wert, nicht aber der öffentlich bekannte Name.

happy://profile?userId=[[draft]]

Link-Import

Die folgenden Actions sind aus Drafts heraus etwas unpraktisch, weil sie eigentlich nur Ansichten in hAppy öffnen. Außerdem wird die Angelegenheit dadurch erschwert, dass Drafts keine leeren Drafts als Ausgangspunkt für Actions erlaubt. Das ist nachvollziehbar, aber führt dazu, dass mindestens ein Zeichen gegeben werden muss, damit eine der folgenden Actions zündet.

Stream öffnen

happy://stream

Link-Import

Mentions öffnen

happy://mentions

Link-Import

Direktnachrichten öffnen

happy://messages

Link-Import

Explore öffnen

happy://explore

Link-Import

Mit den nächsten kleinen Rezepten wird es noch spannender, weil ich mich daran machen werde, deutlich mehr Funktionalität einzubinden.

* Für den Theme-Editor per IAP lohnt sich hAppy schon. Das ist unter den ADN-Clients extrem innovativ.

Drafts-Rezepte I: Yubnub

Mit Drafts ist die Automatisierung auf iOS sehr viel einfacher geworden. Ich habe mir vorgenommen, in der nächsten Zeit mal ein paar nützliche Rezepte zu posten, die den Alltag erleichtern können. Spätestens wenn Pythonista ins Spiel kommt, wird es etwas komplexer. Den Anfang will ich aber mit einem vergleichsweise einfachen Fall machen, der mir das Leben aber ungemein erleichtert.

Ich habe noch nie einen Hehl aus meiner Begeisterung für Yubnub* gemacht. Auf dem Desktop wandele ich alle Browser-Adresszeilen in eine Art Kommandozeile für’s Web ab. Da das Web zu durchsuchen unter iOS eine Qual ist, hätte ich gerne Yubnub auch dort. Mit Drafts ist das sehr einfach. Ich lege ein neues Draft an, beispielsweise mit einem Yubnub-typischen Suchkürzel und den Suchbegriffen wie etwa g iPhone Bumper. In diesem Fall würde Yubnub die Anfrage nach iPhone Bumper an Google weiterleiten. Dann löse ich zum Beispiel folgende URL-Action auf den Draft aus:

Safari

http://yubnub.org/parser/parse?command=[[draft]]

Import-Link

Aber nicht alle von uns wollen im schnöden Safari durchs Web. Auch da lässt sich was machen, solange ein installierter Browser sich mit einem URL-Schema bei iOS angemeldet hat.

Chrome

googlechrome://yubnub.org/parser/parse?command=[[draft]]

Import-Link

Dolphin

dolphin://http://yubnub.org/parser/parse?command=[[draft]]

Import-Link

Das sind nur Beispiele für eine Vielzahl von iOS-Browsern, die das Schema unterstützen und damit auch nun mit Yubnub mehr Komfort ins mobile Surfen bringen. Ein Liste mit weiteren Browsern findet sich bei HandleOpenURL. Das Schema muss in der Regel nur um die Browserbezeichnung ergänzt werden.

In den kommenden Tagen werden hier noch mehr Rezepte für URL-Actions aufschlagen. Das war bislang nur der Anfang. Es geht noch sehr viel mehr.

* Yubnub als zwischengeschalteter Dienst kann natürlich alle Suchanfragen protokollieren – zusätzlich zu den eigentlichen Zielseiten. Die Abwägung von Nutzen und Datenschutzaspekten kann ich niemandem abnehmen.

Codecademy hat Web-API-Kurse

Mir ist jetzt erst aufgefallen, dass Codecademy nicht CodeAcademy heißt. Ist eigentlich auch egal, dort gibt es gute Grundlagenkurse in gängigen Skript-/Programmiersprachen und Webtechniken. Seit Neuestem werden dort auch kostenlose Kurse zu APIs angeboten. Das trifft sich hervorragend, denn bei meinen bislang kurzen Auseinandersetzungen, habe ich noch nicht wirklich Grundsätzliches gelernt.

Die Übungen sprechen diverse APIs an, auch wenn derzeit nicht die geläufigsten Namen der Social-Media-Welt dabei sind. Das macht nicht wirklich etwas, da die Grundprinzipien bei den gängigen RESTful-APIs vergleichbar sind.

Im Moment sind Kurse für drei Sprachen vorhanden. Für JavaScript, Ruby oder Python gibt es jeweils einen kurzen Grundkurs zu den Basics von APIs, also wozu diese Schnittstellen dienen oder wie das mit den HTTP-Request ist. Darauf folgen die eigentlichen inhaltlichen Online-Kurse, in denen ein geführter Gang durch Code in der jeweiligen Sprache beginnt.

Da ich mich derzeit auf Python eingeschossen habe, habe ich dort angefangen. Der simpelste Kurs ist mit Sicherheit der, in dem nur ein wenig Katzencontent als Platzhalter geladen wird. Da ist noch recht wenig Arbeit zu leisten. Etwas umfassender wird es bei der API von bitly, doch der für mich schwerste Brocken waren die Kurse zu den APIs von NPR.

Hierzulande wird dieses spendenfinanzierte, öffentliche Radio der USA weniger bekannt sein. Die Unterschiede sind gewaltig, doch hat der Sender selbst einen Bildungsanspruch, der mit denen der öffentlich-rechtlichen in Deutschland vergleichbar ist. Daher bietet NPR auch viele verschiedene Formate, Texte, Radiosendungen, Mitschriften und Videos frei zugänglich an.

Dementsprechend ist die Story-API enorm groß. NPR wirft mit riesigen Datenobjekten um sich. Glücklicherweise sind die Übungen in Python gut strukturiert, sodass es leicht fällt, recht zügig die erste Basis-URL mit Query-Elementen versehen zu haben, die mit JSON-, XML- oder andern Objekten gewürdigt werden. Danach geht es darum, aus diesen Objekten die relevanten Informationen auszulesen.

Diese Kurse zu NPR-APIs haben den Vorteil, dass sie auf zusätzliche Bibliotheken verzichten. Zwar ist es dadurch weniger komfortabel, doch der Lerneffekt ist größer, solange die Querys und Objekte „von Hand“ erstellt werden. Bibliotheken, die Requests vereinfachen oder beim Parsen der Datenobjekte Zeit sparen, nehmen am Anfang zu viel Last ab und würden den Blick auf die Konzepte verstellen.

So sind die Kurse zu den APIs gute, praxisbezogene Lerneinheiten für alle Einsteigerinnen und Einsteiger, die ihre Kenntnisse in den jeweiligen Sprachen auf die Probe stellen wollen. Gerade das anfangs überwältigende der NPR-Objekte macht dabei klar, wie wichtig gute Kenntnisse sind, wie diese Daten am besten zu verarbeiten sind.

NodeBox – Datenvisualisierungsbaukasten

Seien wir ehrlich, im Hausgebrauch gibt es meist nur einen Weg, Daten grafisch darzustellen. Das Ding nennt sich Excel-Diagramm und sieht in der Regel nach gar nichts aus. Außerdem ist die Darstellung von Daten mit Excel handwerklich immer noch ein Plage, das Ergebnis immer dürftig. Nur weil wir uns daran gewöhnt haben, sollten wir es nicht schönreden. Die Tools, die das Office-Paket von Microsoft mitbringt, zwingen auch noch feste Formen auf. Die Gedanken sind frei, wie wir sie darstellen aber nicht – wenn es nach Redmond geht.

Ich zumindest bin mit den bunten Klecksen, die da in jeder PowerPoint-Präsentation hausen, mittlerweile auf Kriegsfuß. Noch komme ich ohne sie nicht aus, der Tag aber wird kommen, an dem ich sie völlig hinter mir lassen kann. Mit NodeBox bin ich da schon einen Schritt weiter.

Noch hatte ich nicht viel Zeit damit, es reicht aber für einen ersten Ausblick. NodeBox verspricht wirklich einiges. Zuallererst die erwünschte Freiheit, auch wenn sie mit den Kosten verbunden ist, anfangs ein wenig mehr Aufwand betreiben zu müssen, um sich daran zu gewöhnen. Doch das Baukastenprinzip, mit dem die Daten und die Aufbereitung dieser Daten in Knoten organisiert ist, ist zugänglich genug.

Schon das erste Tutorial macht klar, hier behalten Anwenderinnen und Anwender die volle Kontrolle über die Daten. Die Schranken zur guten Visualisierung bestehen nur noch in den eigenen Fertigkeiten. Nichts ist mehr mit dem seltsamen faulen Zauber, der in Excel im Hintergrund waltet. Vorgeblich soll es einem in Excel ja leicht gemacht werden, doch sobald man auch nur komplexere Zusammenhänge darstellen will, stellt sich heraus, Excel nimmt einem nicht nur das Denken ab, es führt eine Lobotomie aus.

NodeBox verlangt etwas mehr Eigenleistung, das ist der Preis, der sich aber, so mein Eindruck nach wenigen Probesitzungen, langfristig bezahlt macht.

Käuferrechte: Nur weil mir der Datenträger gehört, gehört mir nicht der Inhalt.

Die Endbenutzerlizenzen, Nutzungsverträge, Digitalknebel, all diese rechtlichen Bestimmungen und Kontrakte, klicke ich – wie vermutlich die meisten anderen Nutzerinnen und Nutzer digitaler Güter – weg. Es ist eine erlernte Reaktion auf einen rechtlich wie menschlich für juristische Laien nicht zu bewältigenden Akt der Abstraktion. Es ist Teil meiner medialien Sozialisation, diesen Bestimmungen weder Glauben noch Gehör zu schenken. In Zeiten der Downloads noch weniger. Auf spiel-gekauft.de werden wichtige Informationen zur Rechtslage gesammelt. Denn schon die Laienannahme, der Kauf eines Datenträgers entspreche dem Kauf der Software, wird von Produzenten und Verkäufern der Software in den untergeschobenen, unübersichtlichen Bestimmungen bestritten.

Die positive Seite des Digitalen schlägt dabei oft ins Gegenteil um, wenn Anwenderinnen und Anwender in wesentlichen Bereichen im Umgang mit ihrer Erwerbung beschnitten werden. Datenschutz, Sicherungskopien und der Weiterverkauf sind für die Softwarehersteller oftmals ein von geringer Priorität oder ihnen sogar ein Dorn im Auge. Durch die rechtliche Verklausulierung werden diese aus der analogen Welt selbstverständlich erscheinenden Nutzerrechte – bewusst oder nicht – beschnitten und bestritten. Selten werden diese Beschneidungen aber eingepreist.

Daher halte ich es für wichtig, sich der rechtlichen Grundlagen und ihrer Folgen bewusst zu sein, um mündige Kaufentscheidungen zu treffen.

iKeePass

Es ist kein Geheimnis, ich nutze KeePass, wo es nur geht. Auch unterwegs ergeben sich Situationen, in denen ich auf meine Datenbanken zugreifen muss, weil ich nicht alle Passwörter mit einem nachvollziehbaren System erstellen kann. Hierzu gibt es auf iOS einige Apps, die Zugriff auf KeePass-Datenbanken ermöglichen. Der einfachste Weg ist, die Datenbank in einer Dropbox vorzuhalten, mit der die App dann synchronisiert. iKeePass* ist eine dieser Apps.

Bedauerlicherweise habe ich mit iKeePass mehrere Probleme. Eigentlich hat die App alles, was ich mir für einen reibungslosen Einsatz vorstelle: Dropbox-Synchronisierung, Unterstützung der Datenbankformate von KeePass 1.x und 2.x, einen Passwortgenerator und viele Funktionen mehr.

Die Probleme fangen aber schon beim UI-Design der App an. Wäge ich Zweckdienlichkeit und Optik gegeneinander ab, gewinnt im Zweifel Ersteres. Daher kann ich die angestaubte Optik, die steinzeitliche Elemente der iOS-UI nutzt, verschmerzen. Dass aber auf dem iPhone ein wesentlicher Teil des Bildschirms an eine Seitenleiste verloren wird, ist für mich auf Anhieb unangenehm. Die Usability wird dadurch eingeengt. Generell steuert sich die App durch unzählige Menüs und Untermenüs, wird je nach Aufgabe, die ich erledige, zur Klickorgie. Dabei entstehen gelegentlich störende Glitches in der Suche nach Einträgen.

Wesentlich für meine Enttäuschung ist aber die in meiner Version unzuverlässige Dropbox-Synchronisierung. Mehrere Male war die Integrität der in der Dropbox liegenden Datenbank gestört. Die Datenbank war in dieser Form unbrauchbar geworden. Damit geht mein Vertrauen in diese App völlig verloren. Auch die Hilfe gibt da wenig Anlass, das Vertrauen wiederherzustellen:

You can access and restore previous version of your database using your dropbox web interface. See dropbox faq here: https://www.dropbox.com/help/11/en

Die Sicherung der Daten soll also von einem externen Dienst gewährleistet werden. Das ist mir zu wenig. Denn im Falle der Wiederherstellung alter Backups in der Dropbox verliere ich im Zweifel auch einige Einträge. Doch die Datenbank habe ich ja gerade, um mir deren Inhalte nicht mehr merken zu müssen. Das Zutrauen zu iKeePass‘ ordentlichem Umgang mit meinen Datenbanken ist damit grundlegend gestört.

*Die von mir benutzte Version ist 2.5.3. Das Video ist für eine Testversion von 2.4. Optisch sind beide aber noch vergleichbar.

Blockly

Noch eine kleine visuelle Spielerei zum einfachen Erstellen von Code. Mit Blockly (via) liegt der Entwurf für einen graphischen Editor vor, in dem nach dem Baukastenprinzip Code zusammengesteckt wird. Einzelne Kontrollelemente werden wie Puzzlestücke aneinandergereiht.

Noch ist es nur ein Konzept, mit den derzeit in der Code-Demo vorhandenen Funktionen ist aber schon einiges möglich. Grundlegende mathematische und logische Operationen bearbeiten die Variablen, die in einfache Schleifen und If-Abfragen geleitet werden können. Das noch mehr geht, deuten die Listen-Elemente und Prozeduren-Elemente an. Es spricht nichts gegen komplexeren Code, der im Editor schlicht Stück für Stück entsteht. Weiterlesen

VLC aus der Ferne steuern – von jedem mobilen Gerät

Film und Fernsehen ruhen sich im Sommerloch aus, Ebbe herrscht. Zeit, liebgewonnene Serien wieder auszugraben. Gerade ist es bei mir How I Met Your Mother. Ab der ersten Staffel, also mit blauem Horn, dem Fiero und der vermaledeiten Lachspur. Good times. Dafür schmeiße ich dann doch mal wieder den VLC Media Player auf meinem Rechner an, der aus vielen Gründen installiert werden sollte. Das ist schon eine feine Sache, wenn nicht die Fernbedienung fehlen würde, die meinem Rechner fehlte. Ein Blick auf den Tisch zeigt aber, da liegt doch hin und wieder so ein mobiles Gerät, dem nachgesagt wird, es sei smart. Smarter als ich, denn es brauchte eine Weile. Erst dann kam ich darauf, im AppStore nach geeigneter Hilfe zu suchen. Und es gibt einiges. Weiterlesen