<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>IOException.de &#187; Benjamin Erb</title>
	<atom:link href="http://www.ioexception.de/author/benjamin-erb/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ioexception.de</link>
	<description>Ausgewählter Nerdkram von Informatikstudenten der Uni Ulm</description>
	<lastBuildDate>Fri, 13 Jan 2012 07:38:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Einfache Visualisierung von Geodaten – Teil 2: Leaflet &amp; jquery.couch.js</title>
		<link>http://www.ioexception.de/2011/08/30/einfache-visualisierung-von-geodaten-%e2%80%93-teil-2-leaflet-jquery-couch-js/</link>
		<comments>http://www.ioexception.de/2011/08/30/einfache-visualisierung-von-geodaten-%e2%80%93-teil-2-leaflet-jquery-couch-js/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 09:48:49 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[gis]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[visualisierung]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=1119</guid>
		<description><![CDATA[Im vorherigen Teil haben wir gesehen, wie man Geodaten mithilfe von CouchDB abspeichern kann. Da diese Datenbank zugleich ein Webserver ist und die Daten im JSON-Format gespeichert werden, eignet sie CouchDB auch gut für AJAX-Abfragen. Hierfür gibt es eine auf jQuery aufbauende Library namens jquery.couch.js, die von den AJAX-Requests abstrahiert und direkt browser-seitige Interaktionen mit [...]]]></description>
			<content:encoded><![CDATA[<p>Im <a href="http://www.ioexception.de/2011/08/09/einfache-visualisierung-von-geodaten-%E2%80%93-teil-1-couchdbgeocouch/">vorherigen Teil</a> haben wir gesehen, wie man Geodaten mithilfe von CouchDB abspeichern kann. Da diese Datenbank zugleich ein Webserver ist und die Daten im JSON-Format gespeichert werden, eignet sie CouchDB auch gut für AJAX-Abfragen. Hierfür gibt es eine auf jQuery aufbauende Library namens <a href="http://daleharvey.github.com/jquery.couch.js-docs/symbols/%24.couch.html">jquery.couch.js</a>, die von den AJAX-Requests abstrahiert und direkt browser-seitige Interaktionen mit der Datenbank ermöglicht.</p>
<p>Im diesem Beitrag soll gezeigt werden, wie man mit der offenen Karten-Library <a href="http://leaflet.cloudmade.com/">Leaflet</a> und jquery.couch.js geographische Daten aus CouchDB heraus auf einer Karten anzeigen kann.</p>
<div id="attachment_1153" class="wp-caption alignleft" style="width: 310px"><a href="http://www.ioexception.de/wp-content/uploads/2011/08/couchdb-leaflet.png"><img class="size-medium wp-image-1153 " title="couchdb-leaflet" src="http://www.ioexception.de/wp-content/uploads/2011/08/couchdb-leaflet-300x203.png" alt="" width="300" height="203" /></a><p class="wp-caption-text">Beispiel-Visualisierung von ulmapi.de, ebenfalls basierend auf CouchDB und Leaflet.</p></div>
<p>Wir verwenden die CouchApp aus dem ersten Teil weiter, und fügen zu den bisherigen Map/Reduce Views noch statische HTML- und Javascript-Dateien hinzu (im <code>_attachments</code> Ordner), die dann im Browser abgerufen werden können. Beim Aufruf dieser Webseite wird ein HTML-Grundgerüst übertragen, sowie eine JavaScript-Datei, die beim Aufruf die eigentlichen Datensätze via jquery.couch.js aus der CouchDB nachlädt.</p>
<p>Als Mapping-Library verwenden wir Leaflet, eine Open-Source Bibliothek für Kartendarstellungen im Browser. Leaflet abstrahiert von verschiedenen Kartenprovidern und erlaubt es somit, unterschiedliche Datenquellen zu verwenden, wie zum Beispiel auch Bing Maps oder <a href="http://cloudmade.com/">Cloudmade</a>. Letzteres ist ein Service, der auf Basis der Open Street Map Daten Kartenkacheln mit individuellen Stilen rendert und hostet – für Visualisierungen oft sehr hilfreich, da reguläre Karten meist zu viele Karteninformationen enthalten oder farblich überladen sind. In unserem Fall haben wir einen einfach Graustufenkarte gewählt. Leaflet selbst lässt sich relativ leicht verwenden, es muss eine CSS-Datei sowie eine JavaScript-Datei importiert werden, und ein div-Block im HTML enthalten sein, worin später die Karte gerendert werden soll. Somit sieht unser HTML-Gerüst zu Beginn so aus:</p>
<pre class="brush: xml;">
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;style/leaflet.css&quot; /&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.min.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.couch.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;js/leaflet.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;js/maploader.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
	&lt;div id=&quot;map&quot;&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Es werden jQuery, jquery.couch.js und die Leaflet-Libs geladen, und die letzte importierte JavaScript-Datei soll nun unseren Code zum initialisieren der Karte und dem Laden der Daten aus der CouchDB enthalten. Zunächst erstellen wir eine Karte und rendern sie, sobald die Seite vollständig geladen wurde (jQuery Callback für document.ready):</p>
<pre class="brush: jscript;">
$(document).ready(function(){

		var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/[YOUR_API_KEY]/33481/256/{z}/{x}/{y}.png';
		var cloudmadeAttribution = 'UlmApi.de / Shape Files: Stadt Ulm (cc-by-sa), Map data &amp;copy; 2011 OpenStreetMap contributors, Imagery &amp;copy; 2011 CloudMade';
		var cloudmade = new L.TileLayer(
			cloudmadeUrl, {
				maxZoom : 18,
				attribution : cloudmadeAttribution
		});

		var map = new L.Map('map', {
			center : new L.LatLng(48.399976,9.995399),
			zoom : 12,
			layers : [ cloudmade ],
			zoomControl : false
		});
});
</pre>
<p>In der <code>cloudmadeUrl</code> muss für Cloudmade Karte ein korrekter API-Key angegeben werden, der nächste Parameter im Pfad identifiziert den Kartentyp. Beim Initialisieren der Karte wird dann die ID des <code>div</code>s angeben, bei uns &#8216;map&#8217;. Nun sollte unsere Karte bereits dargestellt werden, nachdem wir die CouchApp neu deployen (außerhalb des Fokus dieses Artikels, mehr dazu auf <a href="http://couchapp.org/">couchapp.org</a>).</p>
<p>Was nun noch fehlt, ist das Nachladen der Geodaten aus der CouchDB und die Anzeige auf der Karte. Hierfür verwenden wir jquery.couch.js als Wrapper für die AJAX-Requests gegen CouchDB und die GeoJSON-Funktionalität von Leaflet:</p>
<pre class="brush: jscript;">
$.couch.db('database_name').view('design_doc_name/view_name', {

	success: function(data){
		if(data &amp;&amp; data.rows &amp;&amp; data.rows.length){

			var geoJsonLayer = new L.GeoJSON();

			for(var i = 0;i&lt;data.rows.length;i++){
				geoJsonLayer.addGeoJSON(data.rows[i].value.geometry);
			}

			map.addLayer(geoJsonLayer);
		}
	}
});
</pre>
<p>Das obige Snippet sollte im vorherigen Code hinter der Erzeugung der Karte eingefügt werden. Es ruft von der Datenbank &#8216;database_name&#8217; den View &#8216;view_name&#8217; des Design-Dokuments &#8216;design_doc_name&#8217; auf, und iteriert bei erfolgreicher Abfrage über alle Zeilen. Von jeder Zeile wird dabei die geometry-Property zu einem GeoJSON-Layer hinzugefügt, der am Ende an die Karte übergeben wird. Da unser View aus Teil 1 bereits GeoJSON generiert, und Leaflet nativ GeoJSON lesen und darstellen kann, ist das Hinzufügen von Geodaten auf die Karte sehr einfach.</p>
<p>Hier noch ein paar weiterführende Links mit vertiefenden Inhalten zu den einzelnen Themen:</p>
<ul>
<li><a href="http://leaflet.cloudmade.com/reference.html">Leaflet Reference</a></li>
<li><a href="http://couchapp.org/">CouchApp</a></li>
<li><a href="http://www.scribd.com/doc/40221773/Umsetzung-einer-verteilten-Anwendung-mit-der-dokumentenorientierten-Datenbank-CouchDB">Diplomarbeit von Lena Herrmann</a> über Webanwendungen mit CouchDB und CouchApp</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2011/08/30/einfache-visualisierung-von-geodaten-%e2%80%93-teil-2-leaflet-jquery-couch-js/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Einfache Visualisierung von Geodaten – Teil 1: CouchDB/GeoCouch</title>
		<link>http://www.ioexception.de/2011/08/09/einfache-visualisierung-von-geodaten-%e2%80%93-teil-1-couchdbgeocouch/</link>
		<comments>http://www.ioexception.de/2011/08/09/einfache-visualisierung-von-geodaten-%e2%80%93-teil-1-couchdbgeocouch/#comments</comments>
		<pubDate>Tue, 09 Aug 2011 15:43:01 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[geo]]></category>
		<category><![CDATA[gis]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[nosql]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=1103</guid>
		<description><![CDATA[Die Hochschulgruppe Open Data Ulm hat es sich zur Aufgabe gemacht, offene und öffentliche Daten rund um die Region Ulm zu aggregieren, aufzuarbeiten und zu visualisieren. Näheres zu diesem Projekt sowie bereits gesammelte Datensätze gibt es unter UlmApi.de 
Für unser Vorhaben habe ich als Persistenzlösung die dokumentenorientierte Datenbank CouchDB gewählt, da sie für uns mehrere [...]]]></description>
			<content:encoded><![CDATA[<p>Die Hochschulgruppe Open Data Ulm hat es sich zur Aufgabe gemacht, offene und öffentliche Daten rund um die Region Ulm zu aggregieren, aufzuarbeiten und zu visualisieren. Näheres zu diesem Projekt sowie bereits gesammelte Datensätze gibt es unter <a href="http://ulmapi.de">UlmApi.de</a> </p>
<p>Für unser Vorhaben habe ich als Persistenzlösung die dokumentenorientierte Datenbank <a href="http://couchdb.apache.org/">CouchDB</a> gewählt, da sie für uns mehrere interessante Features bietet:</p>
<ul>
<li><strong>schemalos</strong>: Anders als relationale Datenbanken benötigen schemalose Datenbanken keine im Voraus fest definierte Struktur der Einträge. Für unsere Geodaten ist dies sehr hilfreich, da außer einer ID und den Geodaten noch beliebige zusätzliche Daten pro Eintrag mitgespeichert werden können.</li>
<li><strong>JSON</strong>: Für die Speicherung strukturierter Daten stellt dieses Format eine leichtgewichtige Alternative zu XML dar.</li>
<li><strong>webbasiert</strong>: Die Datenbank ist zugleich ein Webserver und der Zugriff auf die Daten läuft somit über HTTP.</li>
<li><strong>verteilt/replizierend:</strong> Ein wichtiges Konzept von CouchDB ist die einfache aber mächtige Replikation zwischen verschiedenen Instanzen. Im Kontext unserer offenen Datensammlungen ermöglicht dies, dezentralte Kopien der Daten anzulegen, diese lokal zu editieren oder erweitern und wieder auf unsere Hauptdatenbank zu laden.</li>
<li><strong>Attachments</strong>: Neben strukturierten Daten lassen sich auch ganze Dateien speichern. Dies ist vor allem für archivierte Rohdaten in proprietären Formaten interessant.</li>
<li><strong>CouchApps</strong>: Neben der Speicherung der Daten sind vor allem einfache Anwendungen interessant, die diese visualisieren oder aufbereiten. Das Konzept der <a href="http://couchapp.org/">CouchApps</a> ermöglicht es uns, simple Webanwendungen direkt auf der Datenbank zu deployen und verfügbar zu machen.</li>
<li><strong>räumliche Indizes</strong>: Dank <a href="http://vmx.cx/">Volker Mische</a> besitzt CouchDB einen zusätzlichen Index (<a href="https://github.com/couchbase/geocouch">GeoCouch</a>), der statt eindimensionaler B-Bäume zweidimensionale R-Bäume benutzt. Damit lassen sich Dokumente mit räumlichen Daten abspeichern, indizieren und effizient abfragen.</li>
</ul>
<p>Von der Stadt Ulm haben wir als ersten Datensatz Shapefiles der Ulmer Stadtteile und Stadtviertel bekommen. Diese wurden zunächst vom Ausgangsformat (Gauss-Krueger-Shapefiles) in das GeoJSON-Format mit WGS84-Koordinaten konvertiert. Mithilfe eines kleinen node.js Skriptes wurden die einzelnen Shapes dann als Dokumente auf die Couch geladen. </p>
<p>Ein Dokument hat hierbei folgende Form (<a href="http://ulmapi.de/v1/geodaten/ul-st14">Originaldokument</a>):</p>
<pre class="brush: jscript;">
{
   &quot;_id&quot;: &quot;ul-st14&quot;,
   &quot;_rev&quot;: &quot;1-797187e292d93b6d661ca8f7fec3f6c9&quot;,
   &quot;type&quot;: &quot;stadtteil&quot;,
   &quot;name&quot;: &quot;Weststadt&quot;
   &quot;geometry&quot;: {
       &quot;type&quot;: &quot;Feature&quot;,
       &quot;properties&quot;: {
           &quot;identifier&quot;: &quot;ST 14&quot;,
           &quot;name&quot;: &quot;Weststadt&quot;
       },
       &quot;geometry&quot;: {
           &quot;type&quot;: &quot;Polygon&quot;,
           &quot;coordinates&quot;: [
               [
                   [
                       9.981459,
                       48.395751
                   ],
                   …
              ]
           ]
       }
   },
   &quot;creator&quot;: &quot;Stadt Ulm&quot;,
   &quot;license&quot;: {
       &quot;name&quot;: &quot;Creative Commons - Namensnennung-Weitergabe unter gleichen Bedingungen 3.0 Deutschland (CC BY-SA 3.0)&quot;,
       &quot;link&quot;: &quot;http://creativecommons.org/licenses/by-sa/3.0/de/&quot;
   },
}
</pre>
<p>Die <code>_id</code> bestimmt das Dokument eindeutig, das <code>_rev</code> Feld ist für die Versionskontrolle verantwortlich. Als ID haben wir einen internen Identifier der Stadt genommen und noch mit einem &#8220;ul&#8221; Präfix versehen. Der Rest des Dokuments kann frei strukturiert werden. In unserem Fall verwenden wir noch ein <code>type</code> Feld, durch das wir später Dokumente unterschiedlichen Typs unterscheiden können (z.B. <code>stadtteil</code> oder <code>stadtviertel</code>). Das geometry Feld (hier gekürzt) enthält die geografischen Daten im <a href="http://geojson.org/geojson-spec.html">GeoJSON</a>-Format. Die sonstigen Felder beschreiben noch den Urheber und die Lizenz der Daten sowie den Namen des Eintrags.</p>
<p>Nun ist die Datenbank gefüllt, später sollen aber die Daten auch wieder abgefragt werden können. Als &#8220;NoSQL&#8221; Datenbank bietet CouchDB hierfür aber keine SQL-Statements an, stattdessen muss man mithilfe von <a href="http://de.wikipedia.org/wiki/MapReduce">MapReduce</a> beschreiben, wie aus den Daten Indizes gebildet werden sollen:</p>
<pre class="brush: jscript;">function(doc) {
	if (doc.type) {
		if(doc.type === 'stadtviertel'){
		    emit(['stadtviertel', doc._id], {
		    	'geometry' : doc.geometry,
		    	'label' : &quot;&lt;b&gt;Stadtviertel &quot;+doc.name+&quot;&lt;/b&gt;&lt;br/&gt;ID: &quot;+doc._id+&quot;&lt;br/&gt;(Stadteil &quot;+doc.stadtteil+&quot;)&quot;
		    });
		}
		else if(doc.type === 'stadtteil'){
		    emit(['stadtteil', doc._id], {
		    	'geometry' : doc.geometry,
		    	'label' : &quot;&lt;b&gt;Stadtteil &quot;+doc.name+&quot;&lt;/b&gt;&lt;br/&gt;ID: &quot;+doc._id
		    });
		}
	}
};
</pre>
<p>Damit erzeugen wir eine sortiere Liste von Schlüssel-Wert-Paaren. Der Schlüssel ist selbst wieder komplex und besteht aus zwei Teilen. Der erste Teil ist der Typ, der zweite Teil die ID des Dokuments. Damit kann man später durch die sogenannte <a href="http://wiki.apache.org/couchdb/View_collation">View Collation</a> Abfragen durchführen, die sich auf einen bestimmtem Typ beschränken (zur Wiederholung: ohne SQL gibt es hier auch kein WHERE Statement). In diesem Fall werden bisher nur Dokumente des Typs <code>stadtteil</code> oder <code>stadtviertel</code> eingetragen, und als Wert eines Eintrages wird bereits die spätere Nutzung auf einer Karte vorbereitet – es werden die Geodaten sowie ein Label indiziert. Damit lassen sich nun schon Stadtteile/Stadtviertel abfragen.</p>
<p>Ergänzt man dies noch um einen räumlichen Index, so werden auch räumliche Abfragen ermöglicht. Hierfür werden in den Index als Schlüssel die Geodaten (unverändert im GeoJSON Format) eingetragen, den Wert selbst bliebt leer, da das Feld <code>_id</code> sowieso eingetragen wird und vorest keine weiteren Daten mehr benötigt werden:</p>
<pre class="brush: jscript;">
function(doc){
	if(doc.geometry &amp;&amp; doc.geometry.geometry){
		emit(doc.geometry.geometry, null);
	}
};
</pre>
<p>(Das etwas merkwürdig anmutende <code>doc.geometry.geometry</code> entstand einerseits dadruch, dass unser Feld mit dem GeoJSON-Objekt <code>geometry</code> heißt, das GeoJSON-Objekt selbst aber komplex ist und nur in einem Teil davon die eigentlichen Geodaten hinterlegt sind.)</p>
<p>Mithilfe dieses Index lässt sich nun bei einem gegebenen geografischen Raum überprüfen, welche Objekte darin enthalten sind. Also zum Beispiel ausgehend von einer Koordinate, ob sie sich in Ulm befindet und wenn ja, in welchem Stadtteil/Stadtviertel.</p>
<p>Im nächsten Teil wird näher betrachtet, wie die nun abgespeicherten und indizierten Geodaten im Browser auf einer Karte dargestellt werden können, und zwar direkt aus CouchDB heraus.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2011/08/09/einfache-visualisierung-von-geodaten-%e2%80%93-teil-1-couchdbgeocouch/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Präsentieren mit HTML5-Foliensätzen</title>
		<link>http://www.ioexception.de/2011/08/05/prasentieren-mit-html5-foliensatzen/</link>
		<comments>http://www.ioexception.de/2011/08/05/prasentieren-mit-html5-foliensatzen/#comments</comments>
		<pubDate>Fri, 05 Aug 2011 11:48:24 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[uni ulm]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=1057</guid>
		<description><![CDATA[Kurzversion: HTML5 Foliensatz, basierend auf einem Google Template, das zusätzlich Notizen und einen Presenter Mode bietet: Demo / Code
Nicht nur die Frage, wie man richtig präsentiert (Stichwort Zen vs. Death by PowerPoint), sondern auch die Frage, mit welchen Anwendungen man präsentiert, ist oft umstritten. Ich persönlich konnte mich bisher mit Powerpoint und Konsorten eher wenig [...]]]></description>
			<content:encoded><![CDATA[<p><em>Kurzversion: HTML5 Foliensatz, basierend auf einem Google Template, das zusätzlich Notizen und einen Presenter Mode bietet: <a href="http://www.benjamin-erb.de/tmp/html5slides-uulm-presenter/template/index.html#1">Demo</a> / <a href="https://github.com/berb/html5slides-uulm">Code</a></em></p>
<p>Nicht nur die Frage, wie man richtig präsentiert (Stichwort <a href="http://www.presentationzen.com/">Zen</a> vs. <a href="http://en.wikipedia.org/wiki/Death_by_PowerPoint">Death by PowerPoint</a>), sondern auch die Frage, mit welchen Anwendungen man präsentiert, ist oft umstritten. Ich persönlich konnte mich bisher mit Powerpoint und Konsorten eher wenig anfreunden – vor allem Typografie und Einschränkungen bei der Gestaltung waren problematisch. Als Alternative habe ich bisher oft LaTeX Beamer verwendet, was allerdings je nach visueller Komplexität auch oft relativ zeitaufwendig ist, sich aber zumindest bei Grafiken in Vektorformaten und mathematischen Inhalten auch schnell auszahlt.</p>
<p><strong>HTML5-basierte Foliensätze</strong></p>
<p>Mit dem Aufkommen von HTML5 entstand eine zusätzliche Möglichkeit. Dank der neuen Multimedia-Tags wie &lt;audio&gt; und &lt;video&gt; sowie mächtigeren CSS Stilen bietet HTML nun die Grundlagen für browser-basierte Präsentationen. Mittlerweile gibt es hierfür auch schon mehrere Templates:</p>
<ul>
<li><a href="http://paulrouget.com/dzslides/">DZSlides</a></li>
<li><a href="http://code.google.com/p/html5slides/">html5slides</a></li>
<li><a href="http://meyerweb.com/eric/tools/s5/">S5: A Simple Standards-Based Slide Show System</a></li>
</ul>
<p>Noch mehr Alternativen gibt es in dieser <a href="http://en.wikipedia.org/wiki/Web-based_slideshow">Auflistung</a>. Ein weiteres sehr schönes Beispiel ist ein Foliensatz zu HTML5, der selbst quasi eine Technologiedemonstration enthält: <a href="http://slides.html5rocks.com">http://slides.html5rocks.com</a></p>
<p>Der Vorteil von HTML-basierten Präsentationen ist die hohe Anzahl von Medien (u.a. auch SVG, Flash Videos oder ganze Webseiten als IFrames), die man einbetten kann. Ein einfaches, weitläufig bekanntes Markup ermöglicht das schnelle Erstellen von Folien, und mit einer Kombination aus HTML, CSS und JavaScript lassen sich dennoch auch komplexe Spezialfunktionen realisieren.</p>
<p>Mir persönlich hat das html5slides Template ganz gut gefallen, das Google entwickelt und für die Google I/O Slides eingesetzt hat. Da das Template unter einer Apache License veröffentlicht wurde, habe ich zunächst damit begonnen, es an das Uni Ulm Corporate Design anzupassen. Außerdem hatte ich ein paar kleine Änderungen am Code vorgenommen, um zum Beispiel eine Nummerierung der Folien zu ermöglichen.</p>
<p><strong>Presenter Mode?</strong></p>
<p>Prinzipiell war das Ergebnis schon mal akzeptabel, allerdings wurden die oft genannten Probleme bei solchen HTML-Foliensätzen schnell offensichtlich – fehlende Notizen für den Vortragenden und nur eine Ausgabe.</p>
<p>Eher durch Zufall bin ich auf ein anderes Konstrukt gestoßen, dass seit HTML5 Cross-Frame-Communication erlaubt, also den Austausch von Nachrichten zwischen zwei verschiedenen Frames (mit einigen Einschränkungen): <a href="https://developer.mozilla.org/en/DOM/window.postMessage"><code>window.postMessage()</code></a></p>
<p>Die Möglichkeit, zwischen Frames zu kommunizieren, ist natürlich auch ideal dafür, Daten zwischen Frames zu synchronisieren. Übertragen auf zwei verschiedene Präsenationsframes ermöglicht dies beim Weiterschalten der Folien in einem Frame, den zweiten Frame zu aktualisieren. Schematisch sieht das so aus:</p>
<div id="attachment_1084" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.ioexception.de/wp-content/uploads/2011/08/html5slides.png"><img src="http://www.ioexception.de/wp-content/uploads/2011/08/html5slides-300x200.png" alt="" title="html5slides" width="300" height="200" class="size-medium wp-image-1084" /></a><p class="wp-caption-text">(CC-BY-NC) Icons by picol.org / w3.org</p></div>
<p>Im Hauptfenster kann per Tastendruck ein zusätzliches Popup geöffnet werden (1). Das neue Popup öffnet die gleiche URI der Präsentation und wird auf dem Bildschirm des Vortragenden platziert. Schaltet der Vortragende nun im Hauptfenster weiter zu nächsten Folie, so erzeugt dies ein Nachricht an das zweite Frame (2), das dann ebenfalls weiterschaltet.</p>
<p>Eine weitere Ergänzung war die Unterstützung von Notizen als Overlay über die Folien. Kombiniert mit dem Dual-Screen-Ansatz ermöglicht dies, dem Publikum die Folien zu zeigen, dem Vortragenden auf einem zweiten Bildschirm die Folien plus den verfügbaren Notizen.</p>
<p>Ausführliche Beispiele mit Code gibt es in einer <a href="http://www.benjamin-erb.de/tmp/html5slides-uulm-presenter/template/index.html#1">Beispielpräsentation</a>, den kompletten Code auf github: <a href="https://github.com/berb/html5slides-uulm">https://github.com/berb/html5slides-uulm</a></p>
<p>Auf der Feature Wishlist steht noch ein alternativer CSS-Stylesheet für den Druckexport. Außerdem ein Tool, dass externe Daten wie Bilder per Base64 encoding als Data URI integriert und JavaScript sowie Stylesheets inline einbindet, sodass die Präsentation als einzelne HTML5 Datei ohne externe Abhängigkeiten abgespeichert werden kann. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2011/08/05/prasentieren-mit-html5-foliensatzen/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Einfache Mobilapplikation mit Sensordaten und Real-Time-Streaming</title>
		<link>http://www.ioexception.de/2011/06/18/einfache-mobilapplikation-mit-sensordaten-und-real-time-streaming/</link>
		<comments>http://www.ioexception.de/2011/06/18/einfache-mobilapplikation-mit-sensordaten-und-real-time-streaming/#comments</comments>
		<pubDate>Sat, 18 Jun 2011 14:20:46 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[ubiquitous computing]]></category>
		<category><![CDATA[uulm]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[location awareness]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[uni ulm]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=1030</guid>
		<description><![CDATA[Im Rahmen der Vorlesung &#8220;Mobile &#038; Ubiquitous Computing&#8221; (bin derzeit mitbetreuender Hiwi) waren wir auf der Suche nach passenden Übungsaufgaben. Eine Übung davon sollte verschiedene Aspekte aktueller Mobilapplikationen (Sensorkontext, Web Services, Live Notifications) einbeziehen, ohne dabei allzu komplex zu werden. 
Als ansatzweise reales Szenario hierfür dient die Mensa. Zu Stoßzeiten ist es häufig schwierig, in [...]]]></description>
			<content:encoded><![CDATA[<p>Im Rahmen der Vorlesung &#8220;Mobile &#038; Ubiquitous Computing&#8221; (bin derzeit mitbetreuender Hiwi) waren wir auf der Suche nach passenden Übungsaufgaben. Eine Übung davon sollte verschiedene Aspekte aktueller Mobilapplikationen (Sensorkontext, Web Services, Live Notifications) einbeziehen, ohne dabei allzu komplex zu werden. </p>
<p>Als ansatzweise reales Szenario hierfür dient die Mensa. Zu Stoßzeiten ist es häufig schwierig, in einer größeren Gruppe gemeinsam zu essen. Spätestens an den Kassen teilt sich die Gruppe auf und es ist schwierig, die Anderen zu finden. Ein Teil sitzt vielleicht auch schon an irgendeinem Tisch, während andere immer noch an der Essensausgabe warten. Was man also <em>unbedingt</em> braucht, ist ein Mensafinder. Der Mensafinder ermöglicht es, anderen seine grobe Position in der Mensa mitzuteilen oder aufzuzeigen, wo andere Leute sitzen. Aufgrund der Einschränkungen vor Ort (kein GPS-Empfang, WLan-Ortung zu ungenau) haben wir uns auf eine einzige Kontextinformationen beschränkt, die bereits eine ausreichende Lösung bietet – die Kompassausrichtung. Anstatt die genaue Position zu ermitteln, verwenden wir eine grobe Richtung abhängig von einem Fixpunkt im Zentrum des Raums (Wendeltreppe). Bereits sitzende Personen richten ihr Mobilgerät in Richtung des Fixpunktes aus, suchende Personen können ausgehend vom Fixpunkt den Richtungen folgen.</p>
<p><a href="http://www.ioexception.de/wp-content/uploads/2011/06/mensafinder.png"><img src="http://www.ioexception.de/wp-content/uploads/2011/06/mensafinder.png" alt="" title="mensafinder" width="600" height="338" class="alignnone size-full wp-image-1045" /></a></p>
<p>Technisch besteht der Mensafinder aus einem Webservice und mobilen Anwendungen. Der Webservice basiert auf REST und bietet als besonderes Feature das &#8216;Streamen&#8217; neuer Events (neue/aktualisierte Peilungen oder Abmeldungen). Hierfür wird durch den Client eine HTTP-Verbindung geöffnet und serverseitig nicht direkt geschlossen. Stattdessen werden neue Events via Chunked Encoding in die offene Verbindung geschrieben, ähnlich wie bei Streaming API von Twitter. Der Service wurde mit node.js implementiert, <a href="https://github.com/berb/mensafinder/tree/master/service">Quellcode</a> sowie <a href="https://github.com/berb/mensafinder/tree/master/api">Dokumentation der REST API</a> sind auf <a href="https://github.com/berb/mensafinder">github</a> verfügbar. </p>
<p>Da es sich nur um eine Demo-Applikation handelt, fehlen einige wichtige Features. Es gibt keine Authentisierung der Benutzer und es werden alle Peilungen aller Benutzer übertragen (es gibt keine Kontaktlisten). Interessant wäre natürlich die Anbindung an bestehende Dienste, die bereits eine Authentisierung und Kontaktlisten bereitstellen, so wie beispielsweise <a href="http://developers.facebook.com/blog/post/108/">Facebook Connect</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2011/06/18/einfache-mobilapplikation-mit-sensordaten-und-real-time-streaming/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>GUIs &amp; Threads in Java ME</title>
		<link>http://www.ioexception.de/2011/04/05/guis-threads-in-java-me/</link>
		<comments>http://www.ioexception.de/2011/04/05/guis-threads-in-java-me/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 11:25:29 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[java me]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=954</guid>
		<description><![CDATA[Obwohl moderne Plattformen wie Android und iOS als auch alternative Ansätze wie mobile Webanwendungen zunehmend den Markt mobiler Applikationen beherrschen, spielt auch nach über 10 Jahren Java ME noch eine Rolle in diesem Bereich. Vor allem für Nicht-Smartphones und Low-End-Geräte ist Java ME eine verbreitete Technologie. Dieser Beitrag soll erläutern, wie man mit Java ME [...]]]></description>
			<content:encoded><![CDATA[<p>Obwohl moderne Plattformen wie Android und iOS als auch alternative Ansätze wie mobile Webanwendungen zunehmend den Markt mobiler Applikationen beherrschen, spielt auch nach über 10 Jahren Java ME noch eine Rolle in diesem Bereich. Vor allem für Nicht-Smartphones und Low-End-Geräte ist Java ME eine verbreitete Technologie. Dieser Beitrag soll erläutern, wie man mit Java ME Anwendungen implementieren kann, die aufwendige oder länger dauernde Operationen im Hintergrund ausführen und somit eine &#8220;responsive&#8221; GUI bereitstellen.</p>
<p>Bei interaktiven Anwendungen, die Inhalte aus dem Internet laden oder komplexe Berechnungen durchführen, ist es besonders wichtig, die Benutzerschnittstelle durch diese Aktionen nicht vollständig zu blockieren. So können zum Beispiel HTTP Requests in mobilen Netzwerken mehrere Sekunden benötigen – die Anwendung sollte trotzdem benutzbar bleiben oder zumindest dem Anwender über den Ladevorgang informieren.</p>
<p>Wie auch bei Desktop-Applikationen liegt hierbei der Schlüssel im Umgang mit Nebenläufigkeit. So wie es in gewöhnlichen Java-Anwendungen mit GUI einen AWT-Thread gibt, der mit einer Event-Queue auf GUI-Ereignisse wartet und diese verarbeitet, gibt es auch in Java ME ein ähnliches Konstrukt für die Benutzerschnittstelle. Wichtig ist es nun, länger dauernde Operationen nicht in dem jeweiligen Thread auszuführen, sondern in einem separaten Thread. So können auch weiterhin GUI-Ereignisse abgefangen werden, auch wenn die Operation noch andauert. Die eigentliche Aufgabe – I/O Operationen, Berechnungen etc. – wird in einem eigenen Thread oder einem Pool von Threads durchgeführt. Die Aktion wird aus dem GUI-Thread heraus gestartet (z.B. nach dem Click auf einem Button), allerdings eben nicht im GUI-Thread, sondern separat. Somit wird das Starten der Operation asynchron und somit nicht blockierend durchgeführt, und auch mit dem Resultat sollte ähnlich umgegangen werden. Das Ergebnis der Operation sendet nach Bearbeitung das Ergebnis wiederum an den GUI-Thread, der dies dann darstellt. Für den letzteren Fall gibt es bereits ein fertige Methode: <code>javax.microedition.lcdui.Display.callSerially(Runnable r)</code>. Diese Methode reiht das angegebene <code>Runnable</code> an das Ende der Event-Queue ein. Der GUI-Thread arbeitet wiederum die Events und <code>Runnables</code> der Reihe nach ab.</p>
<p>Für das Absenden von Hintergrundaktionen aus dem GUI-Thread bietet sich ein ähnliches Vorgehen an: Mithilfe einer blockierenden Queue sollten neue <code>Runnable</code>s angelegt und eingetragen werden. Ein Thread oder ein Pool von Threads sollte nun aus der Queue lesen und die dortigen <code>Runnable</code>s ausführen. Am Ende der <code>run()</code>-Methode jedes <code>Runnable</code>s  sollte nun das Resultat der Aufgabe wieder an die GUI zurückgegeben werden. Hierfür ist nun die <code>Display.callSerially(Runnable r)</code> hilfreich.</p>
<p>Die folgende Grafik illustriert das grundsätzliche Vorgehen:<br />
<a href="http://www.ioexception.de/wp-content/uploads/2011/04/eventqueue2.png"><img class="alignnone size-full wp-image-966" title="eventqueue" src="http://www.ioexception.de/wp-content/uploads/2011/04/eventqueue2.png" alt="" width="600" height="400" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2011/04/05/guis-threads-in-java-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Streiflicht 2011</title>
		<link>http://www.ioexception.de/2011/02/12/streiflicht-2011/</link>
		<comments>http://www.ioexception.de/2011/02/12/streiflicht-2011/#comments</comments>
		<pubDate>Sat, 12 Feb 2011 12:43:34 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[ubiquitous computing]]></category>
		<category><![CDATA[uulm]]></category>
		<category><![CDATA[streiflicht]]></category>
		<category><![CDATA[uni ulm]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=864</guid>
		<description><![CDATA[Am Mittwoch, den 16. Februar, stellen Studierende des Studiengangs Medieninformatik die Highlights ihrer Anwendungsfächer um 16 Uhr im H20 vor. Erfreulicherweise sind mit MAMPF und diretto auch zwei Projekte von uns mit dabei.

Projekte:

Interaktive Musikbibliothek (Interaktive Systeme)
Interaktives Skript MMS (Interaktive Systeme)
Campus Radio (Medienpädagogik)
MAMPF (Ubiquitous Computing)
diretto (Ubiquitous Computing/Interaktive Systeme)
Parkhaus (Interaktives Video)
Biologische Barcodes in Gesichtern (Computer Vision)
Mehrbildanalyse zur [...]]]></description>
			<content:encoded><![CDATA[<p>Am Mittwoch, den 16. Februar, stellen Studierende des Studiengangs Medieninformatik die Highlights ihrer Anwendungsfächer um 16 Uhr im H20 vor. Erfreulicherweise sind mit <em>MAMPF</em> und <em>diretto</em> auch zwei Projekte von uns mit dabei.</p>
<p><a href="http://www.ioexception.de/wp-content/uploads/2011/02/streiflicht2011-600px.jpg"><img class="alignnone size-full wp-image-865" title="streiflicht2011-600px" src="http://www.ioexception.de/wp-content/uploads/2011/02/streiflicht2011-600px.jpg" alt="" width="600" height="170" /></a></p>
<p>Projekte:</p>
<ul>
<li>Interaktive Musikbibliothek (Interaktive Systeme)</li>
<li>Interaktives Skript MMS (Interaktive Systeme)</li>
<li>Campus Radio (Medienpädagogik)</li>
<li>MAMPF (Ubiquitous Computing)</li>
<li>diretto (Ubiquitous Computing/Interaktive Systeme)</li>
<li>Parkhaus (Interaktives Video)</li>
<li>Biologische Barcodes in Gesichtern (Computer Vision)</li>
<li>Mehrbildanalyse zur Bestimmung von Kopfposen (Computer Vision)</li>
<li>Realtime Rendering (Computer Graphics)</li>
</ul>
<p>Weitere Informationen gibt es unter: <a href="http://www.uni-ulm.de/in/mi/highlights.html">http://www.uni-ulm.de/in/mi/highlights.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2011/02/12/streiflicht-2011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TCP Echo-Server in einer Zeile node.js</title>
		<link>http://www.ioexception.de/2011/01/11/tcp-echo-server-in-einer-zeile-node-js/</link>
		<comments>http://www.ioexception.de/2011/01/11/tcp-echo-server-in-einer-zeile-node-js/#comments</comments>
		<pubDate>Tue, 11 Jan 2011 09:13:11 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=860</guid>
		<description><![CDATA[Der folgende Einzeiler erzeugt einen TCP-Server, der alle eingehenden Daten direkt zurücksendet:

require('net').createServer(function(s){require('util').pump(s,s);}).listen(8000);

Und nein, das ist kein Perl ;-)
]]></description>
			<content:encoded><![CDATA[<p>Der folgende Einzeiler erzeugt einen TCP-Server, der alle eingehenden Daten direkt zurücksendet:</p>
<pre class="brush: jscript;">
require('net').createServer(function(s){require('util').pump(s,s);}).listen(8000);
</pre>
<p>Und nein, das ist kein Perl ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2011/01/11/tcp-echo-server-in-einer-zeile-node-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AF Ubiquitous Computing &#8211; Präsentationsvideos</title>
		<link>http://www.ioexception.de/2010/10/05/af-ubiquitous-computing-prasentationsvideos/</link>
		<comments>http://www.ioexception.de/2010/10/05/af-ubiquitous-computing-prasentationsvideos/#comments</comments>
		<pubDate>Tue, 05 Oct 2010 11:39:07 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[ubiquitous computing]]></category>
		<category><![CDATA[uulm]]></category>
		<category><![CDATA[streiflicht]]></category>
		<category><![CDATA[uni ulm]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=621</guid>
		<description><![CDATA[MAMPF [Fabian Groh, Oliver Stamm, Steffen Scherle, Sven Reichel, Timo Müller]


diretto ))) [Benjamin Erb, Christian Koch, Stefan Kaufmann]

]]></description>
			<content:encoded><![CDATA[<p><strong>MAMPF </strong>[Fabian Groh, Oliver Stamm, Steffen Scherle, Sven Reichel, Timo Müller]</p>
<p><iframe src="http://player.vimeo.com/video/15552654?title=0&amp;byline=0&amp;portrait=0&amp;color=d10a0a" width="600" height="450" frameborder="0"></iframe></p>
<p><br/><br/><br />
<strong><a href="http://www.diretto.org">diretto )))</a></strong> [Benjamin Erb, Christian Koch, Stefan Kaufmann]</p>
<p><iframe src="http://player.vimeo.com/video/15532144?title=0&amp;byline=0&amp;portrait=0&amp;color=d10a0a" width="601" height="338" frameborder="0"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2010/10/05/af-ubiquitous-computing-prasentationsvideos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Effiziente Bereichs-Queries mit CouchDB/GeoCouch</title>
		<link>http://www.ioexception.de/2010/08/16/effiziente-bereichs-queries-mit-couchdbgeocouch/</link>
		<comments>http://www.ioexception.de/2010/08/16/effiziente-bereichs-queries-mit-couchdbgeocouch/#comments</comments>
		<pubDate>Mon, 16 Aug 2010 17:45:12 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[datenbanken]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[nosql]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=615</guid>
		<description><![CDATA[Im Vergleich zu klassischen SQL-Datenbank erfordern NoSQL-Datenbank vor allem bei der Datenabfrage ein Umdenken. Im Falle von CouchDB lässt sich zwar mit View Collation schon einiges erreichen, allerdings bei weitem nicht alles. Auf eine solche Grenze bin ich gestoßen, als ich Zeiträume speichern und abfragen wollte, also Einträge die ein Start- und Enddatum besitzen. Anfragen [...]]]></description>
			<content:encoded><![CDATA[<p>Im Vergleich zu klassischen SQL-Datenbank erfordern NoSQL-Datenbank vor allem bei der Datenabfrage ein Umdenken. Im Falle von <a href="http://couchdb.apache.org/">CouchDB</a> lässt sich zwar mit <a href="http://wiki.apache.org/couchdb/View_collation">View Collation</a> schon einiges erreichen, allerdings bei weitem nicht alles. Auf eine solche Grenze bin ich gestoßen, als ich Zeiträume speichern und abfragen wollte, also Einträge die ein Start- und Enddatum besitzen. Anfragen auf diese Daten könnten nun zu einem fixen Zeitpunkt alle darin ablaufenden Einträge erfragen, oder ausgeweitet auf einen Zeitraum auflisten, welche Einträge innerhalb eines Zeitfensters liegen. All dies ist mit CouchDB nicht wirklich lösbar. </p>
<p>Einen kleinen Workaround bietet die Idee, die Zeitleiste zu segmentieren und immer dann für einen Eintrag einen Key zu emitten, wenn der Zeitraum des Eintrages innerhalb dieses Bereichs liegt. Eine solche Map-Funktion könnte wie folgt aussehen. Hierbei wird für einen Eintrag jeweils ab dem Beginn für alle 5 Minuten ein Schlüssel in den Index emittiert.</p>
<p>Dokumentaufbau:</p>
<pre class="brush: jscript;">
{
   &quot;_id&quot;: &quot;s-ffc0b6b0-59d4-4a3b-ad36-7ec05e7db1de&quot;,
   &quot;begin&quot;: &quot;2010-08-05T09:11:52.156Z&quot;,
   &quot;end&quot;: &quot;2010-08-05T09:23:13.457Z&quot;
}
</pre>
<p>Map-Funktion:</p>
<pre class="brush: jscript;">
//length of time segment (here 5 min)
var periodLength = (60*5);

function(doc)
{
        if(doc.begin &amp;&amp; doc.end)
        {
                //start and end time as UNIX timestamps (seconds, not milliseconds)
                var begin =  Math.round(new Date(doc.begin).getTime()/1000);
                var end =  Math.round(new Date(doc.end).getTime()/1000);

                //calculate first matching segment of period
                var p = (begin - (begin%periodLength));

                //emit key for each matching period
                while(p&lt;=end)
                {
                        emit([p, doc._id], null);
                        p = p + periodLength;
                }
        }
}
</pre>
<p>Der resultierende View sieht dann in etwa so aus:<br />
<a href="http://www.ioexception.de/wp-content/uploads/2010/08/btree_periodical.png"><img src="http://www.ioexception.de/wp-content/uploads/2010/08/btree_periodical.png" alt="" title="btree_periodical" width="600" height="282" class="alignnone size-full wp-image-614" /></a><br />
Oder als Abfrage:<br />
<code>http://localhost:5984/entries/_design/entries/_view/docsByPeriodList?startkey=[1280998800]&#038;endkey=[1281000193,{}]</code></p>
<pre class="brush: jscript;">
{&quot;total_rows&quot;:3,&quot;update_seq&quot;:2,&quot;offset&quot;:0,&quot;rows&quot;:[
{&quot;id&quot;:&quot;s-ffc0b6b0-59d4-4a3b-ad36-7ec05e7db1de&quot;,&quot;key&quot;:[1280999400,&quot;s-ffc0b6b0-59d4-4a3b-ad36-7ec05e7db1de&quot;]15,&quot;value&quot;:null},
{&quot;id&quot;:&quot;s-ffc0b6b0-59d4-4a3b-ad36-7ec05e7db1de&quot;,&quot;key&quot;:[1280999700,&quot;s-ffc0b6b0-59d4-4a3b-ad36-7ec05e7db1de&quot;],&quot;value&quot;:null},
{&quot;id&quot;:&quot;s-ffc0b6b0-59d4-4a3b-ad36-7ec05e7db1de&quot;,&quot;key&quot;:[1281000000,&quot;s-ffc0b6b0-59d4-4a3b-ad36-7ec05e7db1de&quot;],&quot;value&quot;:null}
]}
</pre>
<p>Eine viel bessere Lösung bietet jedoch die CouchDB-Erweiterung <a href="http://github.com/vmx/couchdb">GeoCouch</a>. Dank des R-Trees lassen sich Bereichtsabfragen effizient durchführen. Da GeoCouch eigentlich für zweidimensionale Geokoordinaten gedacht, muss sie und die GeoJSON-Syntax etwas missbraucht werden. Anstatt einer WGS84-Koordinate emittieren wir einfach einen UNIX-Zeitstempel und lassen den anderen Grad leer:</p>
<pre class="brush: jscript;">
function(doc)
{
        if(doc.begin &amp;&amp; doc.end)
        {
                //start and end time as UNIX timestamps (seconds, not milliseconds)
                var begin =  Math.round(new Date(doc.begin).getTime()/1000);
                var end =  Math.round(new Date(doc.end).getTime()/1000);

                emit(
                        {
                                type: &quot;Point&quot;,
                                bbox : [0,start,0,end]
                        }, null
                );
        }
}
</pre>
<p>So lassen sich nun effiziente Bereichsabfragen durchführen:<br />
<code>http://localhost:5984/entries/_design/entries/_spatial/entriesByPeriod?bbox=0,1280998800,0,1281000600</code></p>
<pre class="brush: jscript;">
{&quot;update_seq&quot;:16,&quot;rows&quot;:[
{&quot;id&quot;:&quot;s-ffc0b6b0-59d4-4a3b-ad36-7ec05e7db1de&quot;,&quot;bbox&quot;:[0,1280999512,0,1281000193],&quot;value&quot;:null}
]}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2010/08/16/effiziente-bereichs-queries-mit-couchdbgeocouch/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ein PubSubHubbub-Subscriber-Client für Java</title>
		<link>http://www.ioexception.de/2010/08/14/pubsubhubbub-subscriber-java-client/</link>
		<comments>http://www.ioexception.de/2010/08/14/pubsubhubbub-subscriber-java-client/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 21:02:18 +0000</pubDate>
		<dc:creator>Benjamin Erb</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[atom]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.ioexception.de/?p=606</guid>
		<description><![CDATA[Das Web ist mit HTTP fest an ein Client/Server-Modell gebunden und eine dadurch implizierte Asynchronität der Kommunikation. Requests können ausschließlich von Clients initiiert werden und immer von Servern in Form von Responses beantwortet. Ein solches Modell ist ausreichend für den Abruf von Informationen, setzt allerdings Schranken bezüglich anderer Interaktionsformen. Andere Protokolle wie XMPP, SIP oder [...]]]></description>
			<content:encoded><![CDATA[<p>Das Web ist mit HTTP fest an ein Client/Server-Modell gebunden und eine dadurch implizierte Asynchronität der Kommunikation. Requests können ausschließlich von Clients initiiert werden und immer von Servern in Form von Responses beantwortet. Ein solches Modell ist ausreichend für den Abruf von Informationen, setzt allerdings Schranken bezüglich anderer Interaktionsformen. Andere Protokolle wie XMPP, SIP oder auch Technologien wie nachrichtenbasierte Middlewaresysteme besitzen oft keine so deutliche Trennung zwischen Client/Server und erlauben weniger eingeschränkt die Kommunikation zwischen Knoten. Dadurch enstehen neben dem Request/Reply Muster weitere typischen Muster für den Austausch von Nachrichten. Ein Muster für die Benachrichtigung über Ereignisse ist das Publish/Subscribe Muster. Interessierte Knoten subskribieren sich für bestimmte Ereignisse und ereigniserzeugende Knoten publizieren diese. </p>
<p>Ein solches Kommunikationsmuster ist mit HTTP direkt nicht möglich, auch wenn es insbesondere für Feeds interessant wäre. Zwar bestehen mit Server Pushes / Long Polling oder dem aufkommenden WebSocket Standard vereinzelte Lösung für das prinzipielle Problem, dass HTTP keine serverinitiierte Kommunikation erlaubt, jedoch sind diese Insellösungen bisher kaum in der Breite verwendbar. </p>
<p>Google hat mit dem <a href="http://code.google.com/p/pubsubhubbub">PubSubHubbub</a>-Protokoll ein einfaches offenes Protokoll erschaffen, dass auf reinem HTTP basiert und ein solches Publish/Subscribe Muster unterstützt. Der Trick hierbei ist die Tatsache, dass alle beteiligten Knoten selbst sowohl Server wie auch Client sind und somit sowohl Requests empfangen wir auch versenden können. </p>
<p>Im Rahmen des diretto Projekts habe ich für unseren Client eine java-basierte Subscriber-Implementierung entwickelt. Als Feed kann jeder PubSubHubbub-fähige Atom-Feed benutzt werden. Im Falle einer Änderung des Feeds, zum Beispiel der Veröffentlichung eines neuen Eintrags, wird das &#8220;Delta&#8221; des Feeds, also der neue Teil an die Callback-Methode übergeben.</p>
<pre class="brush: java;">
Subscriber subscriber = new SubscriberImpl(&quot;subscriber-host&quot;,8888);
Subscription subscription = subscriber.subscribe(URI.create(&quot;http://feed-host/my-push-enabled-feed.xml&quot;));

subscription.setNotificationCallback(new NotificationCallback()
{

    @Override
    public void handle(SyndFeed feed)
    {
        //TODO: Do something more useful with the new entries
    	WireFeed inFeed = (WireFeed) feed.originalWireFeed();
    	if(inFeed instanceof Feed)
    	{
    		List&lt;?&gt; entries = ((Feed) inFeed).getEntries();
    		for (Object o : entries)
    		{
    			if(o instanceof Entry)
    			{
    				final Entry entry = (Entry) o;
    				System.out.println(&quot;New entry: &quot;+entry.getId());
    			}
    		}
    	}
    }

} );
</pre>
<p>Der Client benutzt intern <a href="http://rome.dev.java.net/">Rome</a> für die Auswertung der Atom-Feeds und <a href="http://www.eclipse.org/jetty/about.php">Jetty</a> als leichtgewichtigen, internen Webserver. Der Subscriber muss übrigens für den Hub erreichbar sein, insofern sollte er an eine öffentliche IP und den angegebenen Port gebunden werden.</p>
<p>Projekt auf github: <a href="http://github.com/berb/java-sub-pubsubhubbub">java-sub-pubsubhubbub</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioexception.de/2010/08/14/pubsubhubbub-subscriber-java-client/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

