<?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>Beiträge von Christoph Fabritz - Mobile USTP MKL</title>
	<atom:link href="https://mobile.fhstp.ac.at/author/dm121506/feed/" rel="self" type="application/rss+xml" />
	<link>https://mobile.fhstp.ac.at/author/dm121506/</link>
	<description>Die &#34;Mobile Forschungsgruppe&#34; der USTP, sie  sammelt hier alles zu den Themen Design, UX und Entwicklung mobiler Applikationen</description>
	<lastBuildDate>Sat, 11 Nov 2017 17:16:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://mobile.fhstp.ac.at/wp-content/uploads/2025/03/icon-120x120.webp</url>
	<title>Beiträge von Christoph Fabritz - Mobile USTP MKL</title>
	<link>https://mobile.fhstp.ac.at/author/dm121506/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Funktionale Programmierung</title>
		<link>https://mobile.fhstp.ac.at/allgemein/funktionale-programmierung/</link>
		
		<dc:creator><![CDATA[Christoph Fabritz]]></dc:creator>
		<pubDate>Mon, 21 Nov 2016 14:53:44 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Forschung]]></category>
		<category><![CDATA[Trends]]></category>
		<category><![CDATA[functional programming]]></category>
		<category><![CDATA[parallel programming]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=6654</guid>

					<description><![CDATA[<p>Die Entwicklung von immer schnelleren CPUs ist an ihre Grenzen gestoßen. Dies liegt nicht nur an den grundlegenden, physikalischen Grenzen von Materialien sondern auch am Trend der ständigen Miniaturisierung und dem Fokus auf Energieeffizienz. Um dennoch immer mehr Performance aus unserer Hardware herauszuholen, setzt man auf dessen Parallelisierung, d.h. mehr Kerne in unseren CPUs und <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/funktionale-programmierung/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/funktionale-programmierung/">Funktionale Programmierung</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Die Entwicklung von immer schnelleren CPUs ist an ihre Grenzen gestoßen. Dies liegt nicht nur an den grundlegenden, physikalischen Grenzen von Materialien sondern auch am Trend der ständigen Miniaturisierung und dem Fokus auf Energieeffizienz.<br />
Um dennoch immer mehr Performance aus unserer Hardware herauszuholen, setzt man auf dessen Parallelisierung, d.h. mehr Kerne in unseren CPUs und GPUs.<br />
<span id="more-6654"></span><br />
Jeder der sich schon einmal an paraleller Programmierung versucht hat, wird wissen, dass das anfangs gar nicht so leicht ist. Das liegt daran, dass unsere Programmiersprachen zu einer Zeit entwickelt wurden, in der Arbeitsspeicher knapp und teuer war und CPUs alle 18 Monate doppelt so schnell wurden. Wir brauchten keine parallelen Algorithmen, um unsere Programme schneller laufen zu lassen. Alles was man brauchte war eine neue CPU. Die Last lag auf den Hardware-Designern, nicht auf den Software-Entwicklern.<br />
Nun aber müssen wir als Programmierer selbst dafür sorgen, unsere Hardware optimal zunutzen. Dies können wir nicht, in dem wir Programme schreiben wie bisher, sondern wir müssen uns grundlegend neu orientieren. Hier kommt die funktionale Programmierung zum Tragen.<br />
Das Haupthindernis der Pallelisierung ist „shared, mutable state“, also Zustand der zwischen Threads geteilt und verändert wird. Dies führt zu unvorhersehbaren Resultaten.</p>
<pre style="white-space: pre;font-family: monospace !important;">
class Shape {
&nbsp;&nbsp;&nbsp;&nbsp;private int width;
&nbsp;&nbsp;&nbsp;&nbsp;private int height;
    
&nbsp;&nbsp;&nbsp;&nbsp;Shape(int w, int h) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width = w;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height = h;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;public void setDim(w, h) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width = w;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height = h;
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Shape s = new Shape(30, 20);
s.setDim(10, 5);    // A
s.setDim(20, 55);  // B
println(s);
</pre>
<p>Dieser simple Code soll uns als Beispiel dienen. Was wird uns println in der Console anzeigen? Wenn wir beide setDim Aufrufe sequentiell abarbeiten „Shape{width=20, height=55}“, was für jeden verständlich ist. Wie sieht das Ergebnis jedoch aus, wenn wir setDim A und B gleichzeitig   parallel ausführen? Nun, das können wir nicht mit Sicherheit sagen. Es kann jedes dieser folgenen Ergebnisse sein: „Shape{width=30, height=20}“, „Shape{width=10, height=20}“, „Shape{width=20, height=20}“, „Shape{width=30, height=5}“, „Shape{width=30, height=55}“, „Shape{width=10, height=5}“, „Shape{width=10, height=55}“, „Shape{width=20, height=55}“, „Shape{width=20, height=5}“. Es ist nicht nur unmöglich vorherzusagen, ob s wie setDim A oder B aussehen wird, auch haben wir zusätzlich „corrupt state“ indem s auch Zustände zwischen A und B annehmen kann. Dies erhalten wir durch mutable state und Funktionen mit Nebenwirkungen (setDim verändert Variablen außerhalb der Funktion).</p>
<p>Bei der funktionalen Programmierung verzichtet man auf veränderbare Zustände (mutable state) und Funktionen mit Nebenwirkungen (side effects). Dies klingt in erster Linie unmöglich, da wir gewohnt sind, ständig Variablen zuverändern.</p>
<pre style="white-space: pre;font-family: monospace !important;">
class Shape {
&nbsp;&nbsp;&nbsp;&nbsp;public final int width;
&nbsp;&nbsp;&nbsp;&nbsp;public final height;
    
&nbsp;&nbsp;&nbsp;&nbsp;Shape(int w, int h) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width = w;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height = h;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;public Shape setDim(w, h) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new Shape(w, h);
&nbsp;&nbsp;&nbsp;&nbsp;}
}

Shape s = new Shape(30, 20);
Shape s2 = s.setDim(10, 5).setDim(20, 55);
println(s);
println(s2);
</pre>
<p>Schon durch kleine Veränderungen können wir unsere Klasse „thread-safe“ machen. Unsere Variablen sind nun alle Konstanten. Wollen wir unsere Klasse „verändern“ generieren wir in Wirklichkeit eine Kopie mit unserem neuen Zustand. Unabhängig davon, ob wir nun sequentiell oder parallel arbeiten, println(s) und println(s2) werden immer „Shape{width=30, height=20}“ und „Shape{width=20, height=55}“ in der Console anzeigen. Wir haben immutable state (unveränderliche Zustände) und Funktionen ohne Nebenwirkungen.</p>
<p>Dies ist nur eine kleine Kostprobe zur funktionalen Programmierung und nur eines der Themen, mit denen ich mich intensiv auseinander setze. Am Ende des Jahres angekommen kann ich sagen, dass 2016 für mich ein akademisch prägendes Jahr war. Unter anderem schrieb ich an Papers für IEEE-Konferenzen mit Kollegen von CSUN. Ich freue mich schon auf 2017, um mir weitere Ziele setzen zu können.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/funktionale-programmierung/">Funktionale Programmierung</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Elm &#8211; Haskell im Browser</title>
		<link>https://mobile.fhstp.ac.at/allgemein/elm-haskell-im-browser/</link>
		
		<dc:creator><![CDATA[Christoph Fabritz]]></dc:creator>
		<pubDate>Tue, 20 Oct 2015 17:44:36 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[Browser]]></category>
		<category><![CDATA[Elm]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=5615</guid>

					<description><![CDATA[<p>Ich glaube, dass es eine Zeit im Leben eines jeden Programmierers gibt, in der er sich mit Haskell auseinander setzen muss. So ergeht es nun auch mir. An dieser Stelle würde ich euch gerne von meinen Erfahrungen mit dieser Sprache erzählen. Die Chance, dass einem Webentwicklern Haskell unter kam, war und ist immer noch sehr <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/elm-haskell-im-browser/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/elm-haskell-im-browser/">Elm &#8211; Haskell im Browser</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Ich glaube, dass es eine Zeit im Leben eines jeden Programmierers gibt, in der er sich mit Haskell auseinander setzen muss. So ergeht es nun auch mir. An dieser Stelle würde ich euch gerne von meinen Erfahrungen mit dieser Sprache erzählen.<br />
<span id="more-5615"></span><br />
Die Chance, dass einem Webentwicklern Haskell unter kam, war und ist immer noch sehr gering. Es kompiliert zu Assembly und läuft daher schon mal nicht im Browser. Zusätzlich ist es als &#8220;akademische Sprache&#8221; verschrien, welche von der Industrie erfolgreich ignoriert wird. Es ist jedoch eine unbestreitbare Tatsache, dass funktionale Sprachen immer beliebter werden &#8211; und zurecht. Die jahrzehntelange Fehlentwicklung der Programmierung, die wir Objektorientierung nennen, scheint immer mehr Leuten endlich aufzufallen. Ohne Null aber mit parallelisierbaren (jep, das wird auch noch im Browser kommen) Algorithmen lebt es sich eben angenehmer.<br />
Mit Elm ist Haskell nun auch endlich im Browser angekommen. Hier ein kleiner Ausschnitt eines Programmes:</p>
<pre style="font-family:monospace">---------------------------------------------------------
module ColorSliders where

import Color exposing (Color, toRgb)

type alias Model = List Color

type ModelAction
  = Set Color
  | Back


update : ModelAction -&gt; Model -&gt; Model
update action (x :: xs) =
  let all = x :: xs
  in
    case action of
      Set color -&gt; if color == x then all else color :: all
      Back -&gt;
        let
          newHistory' = List.drop 1 all
        in
          if List.isEmpty newHistory' then [Color.rgb 0 0 0] else newHistory'


view : Signal.Address ModelAction -> Model -> Html
view address (x::xs) =
  let
    rgb' color = (String.concat [(toString color.red)
                                ,","
                                ,(toString color.green)
                                ,","
                                ,(toString color.blue)])
    listItem color = li [] 
  in
    div []
      [view' address x
      ,view' address x
      ,input [type' "button"
             ,value "Back in Time"
             ,onClick address Back] []
      ,ol [] (List.map listItem (x :: xs))]

------------------------------------------------------------------------------
</pre>
<p>Man muss den Code nicht auf Anhieb verstehen, aber jeder Entwickler wird sofort die Toplevel-Definitionen wieder erkennen. Wir können ein Modul mit dem Namen ColorSliders erkennen, welches andere Module importiert. Zusätzlich definiert das Modul ein Model, Modelaktionen. Diese werden von einer &#8220;update&#8221;-Funktion verwendet, welche eine Modelaktion und ein Model erhält und dafür ein neues Model (ein neuer State) zurückliefert. Eine &#8220;view&#8221;-Funktion nimmt einen Callback für Aktionen und ein Model und gibt dafür HTML zurück. Keine großen Überraschungen hier. Jede Funktion kann mit einer Typdefinition versehen werden. Dies ist optional. Elm ist eine statisch-typisierte Sprache, d.h. alles hat einen eindeutigen Typ zur Kompilierzeit, der sich im Laufe des Programmes auch nicht ändern kann, jedoch ist der Compiler schlau genug, um Typen selbst herauszufinden, falls wir diese nicht angeben. Dies wird auch als &#8220;type inference&#8221; bezeichnet. Dies ist eine große Hilfe, da der Compiler sofort schreit, falls wir auf ein Attribut zugreifen wollen, dass es in der Definition des Typs nicht gibt. Auch Null gibt es nicht -> keine NullpointerExceptions.</p>
<p>Ich glaube es ist eine gute Übung, die gleiche Applikation in verschiedenen Sprachen umzusetzen. Dadurch erhält man auch einen guten Vergleich. Daher habe ich die App aus einen meiner vorherigen <a href="https://akirchknopf-21110.php.fhstp.cc/allgemein/funktionale-uis-mit-om/">Beiträge (https://akirchknopf-21110.php.fhstp.cc/allgemein/funktionale-uis-mit-om/)</a> in Elm realisiert.<br />
Das Ergebnis ist natürlich das Gleiche. Der komplette Quellkode ist auch wieder dabei. Vergleicht die Lösungen. Ich hoffe ich konnte damit eure Neugier für andere Sprachen wecken. Haskell wird mich auf jeden Fall noch über Jahre hinweg beschäftigen.<br />
<iframe src="http://dm121506.students.fhstp.ac.at/2014/history-test-elm/" style="height: 800px; width: 400px" /></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/elm-haskell-im-browser/">Elm &#8211; Haskell im Browser</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SQL-Tips</title>
		<link>https://mobile.fhstp.ac.at/allgemein/sql-tips/</link>
		
		<dc:creator><![CDATA[Christoph Fabritz]]></dc:creator>
		<pubDate>Tue, 25 Aug 2015 14:33:37 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[Datenbanken]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=5343</guid>

					<description><![CDATA[<p>In einer Applikation kann es an vielen Stellen zu Geschwindigkeits-Engpässen kommen. In der kurzen Zeit, in der ich nun in der kommerziellen Software-Entwicklung tätig bin, habe ich einige Tricks aufgeschnappt, um den Umgang mit SQL-Datenbanken effizienter zu gestalten. Wirbel um SQL-Datenbanken gab es schon seit dem es sie gibt, jedoch hat die Kritik an Speichersystemen <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/sql-tips/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/sql-tips/">SQL-Tips</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In einer Applikation kann es an vielen Stellen zu Geschwindigkeits-Engpässen kommen. In der kurzen Zeit, in der ich nun in der kommerziellen Software-Entwicklung tätig bin, habe ich einige Tricks aufgeschnappt, um den Umgang mit SQL-Datenbanken effizienter zu gestalten.</p>
<p><span id="more-5343"></span></p>
<p>Wirbel um SQL-Datenbanken gab es schon seit dem es sie gibt, jedoch hat die Kritik an Speichersystemen wie MySQL, in einer Zeit, in der NoSQL-Datenbanken im Trend liegen, deutlich zugenommen. Ein Teil der Kritik mag berechtigt sein, jedoch lassen sich auch viele Punkte auf Situationen zurück führen, bei denen SQL-Datenbanken nicht effizient gehandhabt werden, oder die Problem-Domäne mit anderen Speichermedien deutlich besser abgebildet werden kann (Graphendatenbanken, Triplestores, &#8230;). Auf eines lässt Kritik aber auf jeden Fall immer schließen, nämlich dass SQL-Systeme noch immer stark in Verwendung sind, sonst würde ja keiner über sie nörgeln.</p>
<p>An dieser Stelle will ich euch nun einige Techniken zeigen, die euch helfen sollen, Queries zu beschleunigen.</p>
<p><strong>*) Indizieren</strong><br />
Indexe ermöglichen das Durchsuchen einer Tabelle zu beschleunigen. Fragt ihr eine Spalte in einer SQL-Query ab (WHERE-Klausel), die keinen Index besitzt, muss die Datenbank-Engine jede Reihe in eurer Tabelle überprüfen. Das Suchen wird also mit jeder weiteren Reihe langsamer. Besitzt die Spalte jedoch einen Index, wird ein Eintrag in einer speziellen Datenstruktur angelegt, welcher von diesem Index auf die Spalten zeigt, zu dem der Index gehört. Ein solcher &#8220;Lookup&#8221; ist also um einiges schneller, als jede Reihe überprüfen zu müssen.<br />
Es gibt Datentypen, welche Indexe in manchen SQL-Engines nicht unterstützen. Ich hatte das Problem mit einer Tabelle, in der jede Reihe eine Link-Spalte besaß. Diese Link-Spalte war vom Typ TEXT, da Links oft weit über VARCHARs hinausgehen können. Es durften nur neue Elemente in die Tabelle gelangen, deren Link-Feld es noch nicht gab. Die Link-Spalte konnte jedoch wegen des TEXT-Typs keinen Unique-Index besitzen. Die erste Umsetzung bestand darin, bei jedem Insert auf Einzigartigkeit zu überprüfen, e.g.<br />
&#8220;INSERT INTO tabelle1 (info, link)<br />
   SELECT :info, :link FROM DUAL<br />
   WHERE NOT EXISTS (SELECT * FROM tabelle1 WHERE link = :link LIMIT 1)<br />
   LIMIT 1;&#8221;<br />
Diese Lösung funktionierte, ist aber schnell an ihre Grenzen gestoßen, da dieses Statement mit jedem Eintrag in der Tabelle länger dauert.<br />
Die Abhilfe verschaffte ein Hash-Feld. Anstatt die Link-Spalte selbst Unique machen zu wollen, wird der Inhalt jedes Link-Feldes in einen Hash verwandelt, welcher einen Datentyp hat, der leicht indiziert werden kann. Folgende Spalte wurde hinzugefügt: `linkhash` BINARY(20) mit einem Unique-Index. Nachdem es hinzugefügt wurde, musste es natürlich mit dem gehashten Wert des Link-Feldes befüllt werden.<br />
&#8220;UPDATE tabelle1 SET linkhash = UNHEX(SHA1(tabelle1.link));&#8221;<br />
Wie man anhand des Statements sieht, wird ein SHA1-Hash des Links berechnet und in einer effizienten Binär-Form gespeichert.<br />
Das Insert-SQL vereinfachte sich wie folgt:<br />
&#8220;INSERT IGNORE INTO tabelle1 (info, link, linkhash)<br />
   VALUES (:info, :link, UNHEX(SHA1(:link)));&#8221;<br />
Da das Linkhash-Feld einen Unique-Index besitzt, wird nur ein neuer Eintrag in der Tabelle angelegt, wenn der Hash des Links einzigartig ist. Diese Umstellung hat einen immer langsamer werdenden Vorgang wieder in den unteren Millisekunden-Bereich beschleunigt.<br />
Trotzdem ein Wort der Warnung. Indexe erhöhen den verursachten Datenaufwand, da diese eben weitere Datenstrukturen anlegen müssen. Zudem können Update-Statements langsamer werden, da der Hash bei jedem Update neu berechnet und in den Index-Datenstruktur gespeichert werden muss. Daher empfiehlt es sich Indexe auf Spalten und Tabellen anzuwenden, welche hauptsächlich durchsucht und weniger upgedatet werden.</p>
<p><strong>*) Aggregates</strong><br />
Aggregates sind Funktionen wie zum Beispiel AGV, COUNT und SUM. Angenommen wir haben einen Webshop und die Tabellen &#8220;personen&#8221;, &#8220;produkte&#8221; und eine M:M Tabelle zwischen &#8220;personen&#8221; und &#8220;produkte&#8221;, welche speichert, wer wann was gekauft hat. Nun wollen wir auf jeder Produkt-Seite einen Zähler anzeigen, wie oft dieses Produkt schon gekauft wurde. Ein entsprechendes SQL könnte so aussehen:<br />
&#8220;SELECT COUNT(*) FROM personen_produkte WHERE produkt_id = :id;&#8221;<br />
Auch hier könnten wir wieder Indizes auf produkt_id setzen, jedoch müsste die SQL-Engine trotzdem immer wieder alle gefundenen Einträge zusammen zählen.<br />
Hier hilft es oft, den aktuellen Stand zu &#8220;cachen&#8221;. Anstatt immer wieder neu zu zählen, fügen wir in der Tabelle &#8220;produkte&#8221; eine neue Spalte hinzu, welche immer den aktuellen Zähler-Stand für dieses Produkt beinhaltet. Gedanklich passt das Feld sogar sehr gut zu der &#8220;produkte&#8221;-Tabelle. Kauf nun jemand das Produkt, wird neben dem Eintrag in der M:M-Tabelle zusätzlich der Zähler inkrementiert. Dies muss unter der Verwendung von Datenbank-Triggern nicht einmal zusätzlichen Programmier-Aufwand bedeuten. Nun können wir für den Zähler einfach die entsprechende Reihe abfragen:<br />
&#8220;SELECT zaehler FROM produkte WHERE id = :id;&#8221;<br />
Vorsicht ist bei dieser Lösung trotzdem geboten. Wird das Produkt theoretisch hunderte Mal in der Sekunde gekauft, können Trigger diesen Prozess verlangsamen. Man muss sich fragen, muss ich den Zähler öfters anzeigen, oder muss ich öfters einen neuen Einkauf registrieren und wann rentiert sich die eine, oder andere Methode. Natürlich kann man Zähler auch anders Cachen, zum Beispiel auf Anwendungsebene, es soll aber als Beispiel für alle möglichen Fälle dienen.</p>
<p><strong>*) Batch-Processing</strong><br />
Mit dieser Optimierung sind wir nun auf der Anwendungs-Seite gelandet. Latenzen entstehen ja nicht nur durch die Datenbank-Operationen selbst, sondern auch durch die Verbindungen zwischen Client/Server und Server/Datenbank. Durch Batch-Processing lassen sich mehrere Queries auf einmal zum Server übertragen. Hier kommt es auf die Library an, mit welcher man die Datenbank benutzt.<br />
JDBC verfügt über die Möglichkeit, Batches zusammen zubauen und auf einmal zu versenden. Wer mehr zu JDBC lesen will, findet hier einen guten Überblick (<a href="http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm" target="_blank">http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm</a>).<br />
Meines Wissensstandes nach verfügt PDO nicht über ein natives Batch-Feature. In diesem Fall kann man aber immer noch SQL zusammenstoppeln. Ein Beispiel lässt sich durch Pseudo-Code (nicht PDO) verdeutlichen:</p>
<p>1)<br />
var items = [{title: &#8220;Title 1&#8221;}, {title: &#8220;Title 2&#8221;}, &#8230;];<br />
for (item in items) {<br />
    var sql = &#8220;INSERT INTO tabelle 1 (title) VALUES (:title);&#8221;<br />
    connection.execute(sql, item);<br />
}</p>
<p>2)<br />
var items = [{title: &#8220;Title 1&#8221;}, {title: &#8220;Title 2&#8221;}, &#8230;];<br />
var items_sql = [];<br />
var sql = &#8220;INSERT INTO tabelle 1 (title) VALUES &#8220;;<br />
for (item in items) {<br />
    items_sql.push(&#8220;(:title)&#8221;);<br />
}<br />
sql += items_sql.join(&#8220;, &#8220;) + &#8220;;&#8221;; // &#8220;INSERT INTO tabelle 1 (title) VALUES (:title), (:title), &#8230;&#8221;<br />
connection.execute(sql, items);</p>
<p>In Fall 1) rufen wir immer wieder execute auf, was jedes Mal eine Netzwerk-Latenz auslöst. Dies können wir durch Fall 2) vermeiden. Wir bauen ein großes SQL und senden es nur einmal zur Datenbank. Durch dieses Verfahren habe ich Laufzeiten schon um 90% verringern können. Es gibt jedoch auch Datenbanken, welche in der Applikation embedded sind (läuft im selben Prozess, hat also keine Netzwerk-Latenz). Hier lassen sich natürlich geringere Verbesserungen erzielen.</p>
<p>Ich hoffe diese Tipps werden euch von Nutzen sein. Mir haben sie auf jeden Fall geholfen. Es gilt jedoch: es handelt sich hier um anekdotische Evidenz. Nur weil es für meine Anwendung funktioniert hat, muss es nicht für jede andere auch passen. Vielleicht ist eure Datenbank nicht das Bottleneck, sondern die Anwendung oder eine andere Schicht. Daher immer die Performance vor und nach den Änderungen vergleichen und gegebenen Falls rückgängig machen. Es heißt ja auch &#8220;Premature optimization is the root of all evil&#8221;.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/sql-tips/">SQL-Tips</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Funktionale UIs mit Om</title>
		<link>https://mobile.fhstp.ac.at/allgemein/funktionale-uis-mit-om/</link>
		
		<dc:creator><![CDATA[Christoph Fabritz]]></dc:creator>
		<pubDate>Tue, 05 Aug 2014 19:06:41 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[ClojureScript]]></category>
		<category><![CDATA[Om]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=4587</guid>

					<description><![CDATA[<p>In meinem letzten Beitrag habe ich von Facebooks React berichtet, um die View in Web-Apps einfacher beschreiben zu können. In diesem Artikel berichte ich nicht von etwas völlig anderem und werfe React somit über den Haufen, sondern zeige euch Om, eine Library die auf React aufbaut. Zur Erinnerung: React ist eine JS-Bibliothek, welche Daten (App-State) <a class="read-more" href="https://mobile.fhstp.ac.at/allgemein/funktionale-uis-mit-om/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/funktionale-uis-mit-om/">Funktionale UIs mit Om</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In meinem letzten Beitrag habe ich von Facebooks React berichtet, um die View in Web-Apps einfacher beschreiben zu können. In diesem Artikel berichte ich nicht von etwas völlig anderem und werfe React somit über den Haufen, sondern zeige euch Om, eine Library die auf React aufbaut.<br />
<span id="more-4587"></span><br />
Zur Erinnerung: React ist eine JS-Bibliothek, welche Daten (App-State) in den Browser render, zum Beispiel ein Array mit Kommentaren. Ändern sich diese Daten (postet jemand ein Kommentar), wird diese Änderung im Browser angezeigt. Traditioneller Weise müssten wir hier mit .appendChild und der Gleichen arbeiten. Dies übernimmt jedoch React für uns, welchem wir nur beschreiben, wie unsere Liste mit Kommentaren zu jedem Zeitpunkt in der Lebenszeit der Webseite im Browser auszusehen hat.<br />
Zusammenfassend lässt sich also sagen: <strong>React hält den App-State und die View (DOM) synchron.</strong></p>
<p>Wo kommt nun Om ins Spiel? Nun, vor einiger Zeit bin ich von JavaScript abgewandert und auf ClojureScript umgestiegen. In einem meiner früheren Artikel habe ich darauf aufmerksam gemacht, dass JavaScript vollkommen ungeeignet ist, um ganze Applikationen damit zu programmieren. Das haben auch andere erkannt, weshalb sich immer mehr Sprachen etablieren, welche zu JavaScript kompilieren (GWT, CoffeScript, &#8230;). Diese Sprachen bieten einen Mehrwert und Abstraktionen, welche mit reinem JavaScript nur umständlich zu verwirklichen sind. Ich habe mich für ClojureScript entschieden, da ich Clojure (kompiliert zu Java-Bytecode) schon von der Server-Seite her kannte.</p>
<blockquote><p>Exkurs ClojureScript:</p>
<pre class="brush: plain; title: ; notranslate">
// JavaScript
var x = 5 + 5;
var o = {y: x};
var inc = function (i) { return i + 1; };
o.y === x;
inc(x);

// ClojureScript
(let &#x5B;x (+ 5 5)
      o {:y x}
      inc #(+ 1 %)]
  (= (:y o) x)
  (inc x))
</pre>
<p>Diese Beispiele sollen JavaScript-Code und ClojureScript gegenüberstellen. ClojureScript ist eine Lisp-Sprache, dass heißt jedes Programm ist gleichzeitig eine Datenstruktur. JavaScript-Programme schreiben wir mit Text. var x = 5 + 5; ist nur Text, welcher von der JavaScript-Engine ausgeführt wird. In der ClojureScript-Variante fallen die verschiedenen Klammern auf. Diese öffnen und schließen Datenstrukturen. Runde Klammern sind Listen, eckige sind Vectoren und geschwungene Klammern sind Maps. Das heißt unser Lisp-Programm ist eigentlich ein Array und kein Text. Dies eröffnet Möglichkeiten für Macros und Meta-Programming, da wir Lisp-Code laden und wie Arrays bearbeiten können. Wenig überraschend kommt Lisp aus dem Forschungs-Bereich der künstlichen Intelligenz, da dies erlaubt den eigenen Code zu inspizieren, beliebig umzuschreiben und neu auszuführen (sich selbst verändernde Programme).<br />
Ein weiteres Merkmal von ClojureScript ist, dass unsere Datenstrukturen unveränderlich sind. In unserem Beispiel oben bedeutet dies, dass wir o.y (oder o und x) nicht überschreiben können. Jede Veränderung führt zu der Entstehung einer Kopie der Datenstruktur, welche die Änderungen beinhaltet. Zusätzlich gibt es keine Klassen und Objekte. ClojureScript ist keine Objekt-orientierte Sprache, sondern eine funktionale Sprache. State und Funktionalität werden nicht in Klassen vereint, sondern Funktionen erhalten Werte und liefern Werte zurück, ohne einen State zu manipulieren.<br />
Hiermit will ich es auch mit der Beschreibung von ClojureScript belassen. Sollte sich jemand mehr dafür interessieren, kann ich gerne noch weitere Artikel zu dieser Sprache schreiben.</p></blockquote>
<p><strong>Om ist ein Interface zu React in ClojureScript. Das heißt wir können React-Componenten einfach in ClojureScript erstellen.</strong></p>
<p>Sehen wir uns Mal an, wobei es uns helfen kann. Als Beispiel für diesen Artikel wollen wir die neuen HTML5 Input-Sliders verwenden, um ein Farbfeld live mit RGB-Slidern verändern zu können. Um die Sache mit der Synchronisation noch interessanter zu machen, verdoppeln wir die Slider und Farbfeld und versuchen Änderungen in beiden zu reflektieren. Als Bonus wollen wir alle Änderungen in einer History beobachten können. Hier mal eine Skizze:</p>
<p><a href="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/08/1.png"><img fetchpriority="high" decoding="async" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/08/1.png" alt="1" width="312" height="724" class="aligncenter size-full wp-image-4601" /></a></p>
<p>Wie sehen nun unsere Abhängigkeiten aus? Es muss ja schließlich alles synchronisiert sein. Wenn ich den Slider für Rot verändere, muss sich der zweite &#8220;Rot&#8221;-Slider mitbewegen, es muss sich das Farbfeld aktualisieren und es muss ein neuer Eintrag in der History erstellt werden. Wenn man nun alle Abhängigkeiten einträgt, ergibt sich ein Bild wie folgt:</p>
<p><a href="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/08/Untitled1.png"><img decoding="async" src="https://akirchknopf-21110.php.fhstp.cc/wp-content/uploads/2014/08/Untitled1.png" alt="Untitled1" width="420" height="791" class="aligncenter size-full wp-image-4603" /></a></p>
<p>Bei diesem Anblick kann einem schon das Schaudern kommen, wenn man bedenkt, was man alles synchron halten muss.</p>
<p>Eine Implementierung in JavaScript könnte so aussehen (Klick auf Result):<br />
<iframe width="100%" height="1000" src="http://jsfiddle.net/LWew2/3/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><br />
Es ist sicherlich nicht die beste Implementierung, aber auch nicht die schlechteste. Wir haben eine redraw-Funktion, in welcher wir alle Elemente mit den aktuellen Daten aktualisieren. Wir rufen redraw() bei jeder Veränderung auf. Dies alles zu machen ist etwas mühsam und mit mehr Elementen wächst die redraw-Funktion immer weiter und weiter, was eigentlich nicht sehr modular ist.</p>
<p>Dieses Beispiel habe ich in ClojureScript und Om reimplementiert.<br />
<iframe loading="lazy" width="100%" height="1000" src="http://dm121506.students.fhstp.ac.at/2014/history-test-1/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><br />
Auch wenn man nicht so viel von ClojureScript versteht und auf &#8220;Source&#8221; klickt, sieht man, dass es nicht &#8220;die eine, große redraw-Funktion&#8221; gibt. Die Applikation ist in modulare Komponenten unterteilt. Um das Farbfeld zu verdoppeln, habe ich nur den bestehenden Component ein zweites Mal eingefügt (eine Zeile Arbeit) und an die selben Daten geknüpft. Alle Komponenten reflektieren automatisch den State mit dem sie verknüpft wurden und halten sich synchronisiert. So Programme zu schreiben ist meiner Meinung nach einfacher und sinnvoller, als pures JavaScript.</p>
<p>Am Schluss des Artikels angekommen, wäre ein besserer Titel vielleicht &#8220;Warum ich von JavaScript auf ClojureScript mit Om umgestiegen bin&#8221; gewesen. In einem Artikel kann man nur schwer auf ClojureScript und Om gleichzeitig in Form von ausführlichen Tutorials eingehen. ClojureScript muss man schon für zwei Wochen gelebt haben, um die Vorteile wirklich greifbar zu machen. Wenn das eher nichts für euch ist, hat euch dann hoffentlich das Beispiel ein wenig gezeigt, dass man sich über Abhängigkeiten, Modularität und der Synchronisation von State bei Applikationen Gedanken machen muss &#8230; und HTML5 Slider in Aktion. Ich empfehle euch, das Beispiel selber mal in JavaScript auszuprogrammieren. Da bin ich gespannt, auf welche Lösungen ihr kommt. Postet einfach ein Kommentar mit Link.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/allgemein/funktionale-uis-mit-om/">Funktionale UIs mit Om</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>UIs mit Facebooks React</title>
		<link>https://mobile.fhstp.ac.at/development/uis-mit-facebooks-react/</link>
					<comments>https://mobile.fhstp.ac.at/development/uis-mit-facebooks-react/#comments</comments>
		
		<dc:creator><![CDATA[Christoph Fabritz]]></dc:creator>
		<pubDate>Sat, 26 Jul 2014 17:25:42 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Webdevelopment]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=4537</guid>

					<description><![CDATA[<p>Für JavaScript gibt es mittlerweile viele Bibliotheken, um graphische Benutzeroberflächen zu erzeugen. Obwohl diese recht unterschiedlich sein können, haben sie jedoch eines gemeinsam und zwar wie sie mit Änderungen umgehen. In diesem Artikel gehen wir darauf ein, was Facebook mit ihrem eigener UI-Bibliothek anders macht. Zu Beginn ein simples Beispiel. Nehmen wir an, wir hätten <a class="read-more" href="https://mobile.fhstp.ac.at/development/uis-mit-facebooks-react/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/uis-mit-facebooks-react/">UIs mit Facebooks React</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Für JavaScript gibt es mittlerweile viele Bibliotheken, um graphische Benutzeroberflächen zu erzeugen. Obwohl diese recht unterschiedlich sein können, haben sie jedoch eines gemeinsam und zwar wie sie mit Änderungen umgehen. In diesem Artikel gehen wir darauf ein, was Facebook mit ihrem eigener UI-Bibliothek anders macht.<br />
<span id="more-4537"></span><br />
Zu Beginn ein simples Beispiel. Nehmen wir an, wir hätten eine Applikation geschrieben, welche Kommentare (oder Nachrichten, Produkt-Reviews, usw.) anzeigt und die Möglichkeit bietet, selbst Kommentare zu verfassen. Werden Kommentare von jemandem (man selbst oder jemand an einem ganz andere Browser/Computer) gepostet, werden diese sofort angezeigt. Das heißt also, dass wir eine aktive Verbindung (Polling, WebSocket, REST, usw.) zu einem Server haben, von welchem wir ständig die neuesten Kommentare bekommen.</p>
<p>Zwei traditionelle Herangehensweisen an das Realisieren dieser Applikation könnten so aussehen:<br />
  1) Eine Funktion die zu Beginn die Liste der Kommentare erstellt und eine welche die Updates in die vorhandene Liste einfügt. Dies hat den Nachteil, dass wir zwei Funktionen brauchen die fast das Gleiche machen, dies aber <strong>schnell (Vorteil)</strong>. Zusätzlich ist es <strong>nicht </strong>besonders <strong>data-driven</strong> und sehr <strong>imperativ</strong>, da die Liste ständig manipuliert wird und ein Eigenleben durch <strong>Hidden-State</strong> entwickeln kann. <strong>template(model) != view</strong>. Eine weitere Überlegung: Was ist wenn wir im Nachhinein beschließen, dass Kommentare sowohl veränderbar und löschbar sind, natürlich von jedem Browser aus und dass soll jede andere Person sofort in ihren Browsern sehen können. Dies würde wieder zwei weitere Funktionen benötigen, die darüber Bescheid wissen müssen, welches Kommentar die Veränderung und Löschung betrifft (weiterer State 🙁 ). Da können wir froh sein, dass JS single-threaded ist, denn in anderen Programmiersprachen wären wir nun in der Locking-Hölle (4 Funktionen die auf denselben State zugreifen &#8211;<strong> shared State</strong>).<br />
  2) Eine Funktion welche die bestehende Liste komplett entfernt und zusammen mit allen vorherigen Updates neu aufbaut. <strong>Nachteil: schlechte Geschwindigkeit/Performance</strong> | <strong>Vorteil: data-driven, functional, template(model) == view, kein Hidden-State</strong></p>
<p>Facebook hat erkannt, dass man mit keiner der beiden Lösungen glücklich wird. Dies liegt der Entstehung von React zugrunde. Dabei ist React aber kein Framework, es zwingt den Nutzern nichts, wie zum Beispiel Routers oder Templates, auf. Man muss bestehende Applikationen nicht komplett auf React umstellen, sondern kann es für einzelne Komponenten verwenden und es spielt dabei gut mit anderen Bibliotheken wie jQuery zusammen.<br />
Die Herangehensweise von React zu unserem vorherigen Beispiel ist es, <strong>eine Funktion</strong> zu erstellen, welche für eine gegebene Liste von Kommentaren das HTML erzeugt, also die Funktion von 2). Diese ruft React selbstständig auf, falls sich die Liste von Kommentaren verändert, wenn wir zum Beispiel an das Kommentaren-Array die Updates anhängen. Dabei greifen wir das HTML nicht direkt an, sondern ändern nur ein JavaScript-Array. React produziert nun selbstständig das HTML und vereint es mit dem was schon im DOM vorhanden ist. Daher <strong>löscht es nicht das gesamte DOM, sondern fügt nur die Differenz ein</strong>. Mit dieser Herangehensweise haben wir alle Vorteile der beiden anderen. Wir bekommen ein functional, data-driven Interface ( template(model) == view ), behalten aber die Geschwindigkeit der imperativen Lösung 1) durch das Vereinen von Differenzen mit dem was schon am Bildschirm vorhanden ist.</p>
<p>Ganz konkret sieht das in React dann so aus:<br />
Variante 1 mit Properties:</p>
<pre class="brush: jscript; title: ; notranslate">
/** @jsx React.DOM */
var Kommentare = React.createClass({
    render: function() { return (
        &lt;ol&gt;
            {this.props.kommentare.map(function (kommentar) {
                return (&lt;li&gt;{kommentar}&lt;/li&gt;);
            })}
        &lt;/ol&gt;
  );}
});

var kommentare = &#x5B;&quot;Kommentar 1&quot;, &quot;Kommentar 2&quot;];

setInterval(function() {  // &quot;Server-Verbindung&quot;
  var neueKommentare = &#x5B;&quot;Kommentar 3&quot;]; // vom Server
  kommentare = kommentare.concat(neueKommentare);
  React.renderComponent(
    &lt;Kommentare kommentare={kommentare} /&gt;,
    document.body
  );
}, 50);
</pre>
<p>Variante 2 mit State:</p>
<pre class="brush: jscript; title: ; notranslate">
/** @jsx React.DOM */
var Kommentare = React.createClass({
    getInitialState: function() {
        return {kommentare: &#x5B;]};
    },
    componentDidMount: function() {
        setInterval(function() { // &quot;Server-Verbindung&quot;
            var neues_array = this.state.kommentare.concat(neue_kommentare);
            this.setState({kommentare: neues_array});
        }, 50);
    },
    render: function() { return (
        &lt;ol&gt;
            {this.state.kommentare.map(function (kommentar) {
                return (&lt;li&gt;{kommentar}&lt;/li&gt;);
            })}
        &lt;/ol&gt;
  );}
});

React.renderComponent(
  &lt;Kommentare /&gt;,
  document.body
);
</pre>
<p>Der Grundbaustein von React ist der Component (React.createClass), welcher definiert, wie das resultierende DOM aussehen soll. React wird mit einer optionalen domain-specific-language ausgeliefert, namens JSX (hier das XML-Markup im JavaScript). Das JSX wird vor dem Ausliefern zu JavaScript kompiliert. Hat man größere Projekte steigert JSX die Leserlichkeit ungemein und kann ich daher nur empfehlen. Wer lieber pures JS schreiben will, muss Elemente mit zum Beispiel </p>
<pre class="brush: plain; title: ; notranslate">React.DOM.div({})</pre>
<p> erzeugen, was natürlich weitaus schwieriger zu lesen ist als </p>
<pre class="brush: plain; title: ; notranslate">&lt;div&gt;&lt;/div&gt;</pre>
<p>.<br />
Als React-Umsetzung unseres Beispiels sind zwei gleichwertige Varianten angeführt. Ein setInterval simuliert in beiden Varianten die Server-Verbindung. Variante 1 verlässt sich dabei nur auf Daten von außen (kein Hidden-State). Jedes Mal, wenn wir neue Kommentare vom Server erhalten, hängen wir diese an unser Kommentaren-Array an und lassen React die Liste an Kommentare neu rendern (React.renderComponent-Funktion). Wie schon zuvor erwähnt, wird nicht die gesamte ol-Liste neu gerendert, es werden nur Differenzen zwischen neuem und alten State appliziert. In Variante 2 definieren wir einen Component, der sich selbst um seine Server-Verbindung kümmert und sich selbst neu rendert (mit jedem Aufruf von this.setState()). Es bleibt dem Programmierer überlassen, welche Variante bevorzugt wird. Meine Empfehlung geht an Variante 1, da kein Hidden-State verwendet wird.<br />
Wie in den Varianten gezeigt wird, bedarf es nur einer Funktion (render), welche <strong>definiert wie das Component zu jedem Zeitpunkt auszusehen hat</strong>. Wir kümmern uns danach als Programmierer nur mehr um das Manipulieren von Daten (Arrays, Objecte, &#8230;) und nicht um das Manipulieren des DOMs (createElement, getElementBy&#8230;, appendChild, &#8230; fällt alles weg 🙂 ). Das macht React für uns. Hiermit können wir besseren Code schreiben, da wir nicht ständig Funktionen wie appendChild, innerHTML und der Gleichen aufrufen müssen und können unsere ganze Aufmerksamkeit unserem Model widmen.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/uis-mit-facebooks-react/">UIs mit Facebooks React</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://mobile.fhstp.ac.at/development/uis-mit-facebooks-react/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Navigate by Barcode</title>
		<link>https://mobile.fhstp.ac.at/news/navigate-barcode/</link>
		
		<dc:creator><![CDATA[Christoph Fabritz]]></dc:creator>
		<pubDate>Sun, 04 May 2014 16:50:16 +0000</pubDate>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Tests]]></category>
		<category><![CDATA[Trends]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=4455</guid>

					<description><![CDATA[<p>An dieser Stelle will ich auf einen Artikel aufmerksam machen, welcher sich mit der Navigation in Gebäuden mit Hilfe von Barcodes befasst. Interessantes Konzept und lesenswert. Artikel: http://gizmodo.com/navigate-by-barcode-and-never-get-lost-again-1571514179 Publikation: http://dl.acm.org/citation.cfm?id=2556288.2556994 Robinson, Simon, Jennifer S. Pearson, and Matt Jones, ‘A Billion Signposts: Repurposing Barcodes for Indoor Navigation’, in Proceedings of the SIGCHI Conference on Human Factors <a class="read-more" href="https://mobile.fhstp.ac.at/news/navigate-barcode/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/news/navigate-barcode/">Navigate by Barcode</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>An dieser Stelle will ich auf einen Artikel aufmerksam machen, welcher sich mit der Navigation in Gebäuden mit Hilfe von Barcodes befasst. Interessantes Konzept und lesenswert.<br />
Artikel:<br />
<a title="Navigate by Barcode and Never Get Lost Again" href="http://gizmodo.com/navigate-by-barcode-and-never-get-lost-again-1571514179" target="_blank">http://gizmodo.com/navigate-by-barcode-and-never-get-lost-again-1571514179</a></p>
<p>Publikation:<br />
<a title="A billion signposts: repurposing barcodes for indoor navigation" href="http://dl.acm.org/citation.cfm?id=2556288.2556994" target="_blank">http://dl.acm.org/citation.cfm?id=2556288.2556994</a><br />
Robinson, Simon, Jennifer S. Pearson, and Matt Jones, ‘A Billion Signposts: Repurposing Barcodes for Indoor Navigation’, in Proceedings of the SIGCHI Conference on Human Factors in Computing Systems, CHI ’14 (New York, NY, USA: ACM, 2014), pp. 639–642 &lt;http://dx.doi.org/10.1145/2556288.2556994&gt;</p>
<p>The post <a href="https://mobile.fhstp.ac.at/news/navigate-barcode/">Navigate by Barcode</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>RSSI-Messungen von Bluetooth auf Android</title>
		<link>https://mobile.fhstp.ac.at/development/rssi-messungen-von-bluetooth-auf-android/</link>
		
		<dc:creator><![CDATA[Christoph Fabritz]]></dc:creator>
		<pubDate>Thu, 24 Apr 2014 00:31:07 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Native Development]]></category>
		<guid isPermaLink="false">https://akirchknopf-21110.php.fhstp.cc/?p=4437</guid>

					<description><![CDATA[<p>Bei RSSI handelt es sich um die Stärke, mit welcher ein Signal empfangen wird. Dies kann (mit Vorsicht) als Entfernungs-Indikator zwischen zwei Geräten genutzt werden. Wer solche Messungen mit Bluetooth auf Android-Geräten schon einmal durchgeführt hat, muss schnell feststellen, dass ein fortlaufendes Auslesen dieses RSSI-Wertes in Android nicht so einfach funktioniert. Dies liegt daran, dass <a class="read-more" href="https://mobile.fhstp.ac.at/development/rssi-messungen-von-bluetooth-auf-android/">[...]</a></p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/rssi-messungen-von-bluetooth-auf-android/">RSSI-Messungen von Bluetooth auf Android</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Bei RSSI handelt es sich um die Stärke, mit welcher ein Signal empfangen wird. Dies kann (mit Vorsicht) als Entfernungs-Indikator zwischen zwei Geräten genutzt werden.</p>
<p>Wer solche Messungen mit Bluetooth auf Android-Geräten schon einmal durchgeführt hat, muss schnell feststellen, dass ein fortlaufendes Auslesen dieses RSSI-Wertes in Android nicht so einfach funktioniert. Dies liegt daran, dass dar Event zum Auslesen nur gefeuert wird, wenn ein neues Gerät gefunden wurde. Da das andere Gerät nach dem ersten Mal schon bekannt ist, bekommt man nur eine einzelne Momentaufnahme des Wertes, was Beobachtungen über die Zeit schwer macht. Verändert sich der Abstand der Geräte zueinander, muss man die Mess-Applikation daher neu starten.</p>
<p><span id="more-4437"></span></p>
<p>Um den Messvorgang einfacher zu gestalten, habe ich eine einfache Funktion geschrieben, die auch für andere Entwickler und Tüftler interessant sein könnte.</p>
<pre class="brush: java; title: ; notranslate">package com.example.rssi_test.app;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bluetooth_search();
    }

    public void bluetooth_search() {
        final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            return;
        }
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, RESULT_OK);
        }

        registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, (short) 0);

                Log.i(&quot;rssi&quot;, &quot;&quot; + rssi);

                unregisterReceiver(this);
                mBluetoothAdapter.cancelDiscovery();
                bluetooth_search();
            }
        }, new IntentFilter(BluetoothDevice.ACTION_FOUND));

        mBluetoothAdapter.startDiscovery();
    }
}
</pre>
<p>Diese einfache Funktion registriert einen Handler, welcher feuert, wenn ein Gerät entdeckt wurde. Es wird der RSSI ausgelesen, der Handler entfernt und die Erkennung neugestartet. Dadurch kann dasselbe Gerät mehrmals ausgelesen werden.<br />
Hier sind ein paar meiner Messungen.</p>
<table>
<tbody>
<tr>
<th>Entfernung [m]</th>
<th>RSSI min</th>
<th>RSSI max</th>
</tr>
<tr>
<td>0.5</td>
<td>-48</td>
<td>-51</td>
</tr>
<tr>
<td>1</td>
<td>-54</td>
<td>-62</td>
</tr>
<tr>
<td>2</td>
<td>-69</td>
<td>-79</td>
</tr>
<tr>
<td>3</td>
<td>-77</td>
<td>-86</td>
</tr>
<tr>
<td>4</td>
<td>-76</td>
<td>-81</td>
</tr>
</tbody>
</table>
<p>Wie man sieht, sind die Werte nicht allzu aussagekräftig. Falls man erkennen will, ob jemand durch eine Tür geht, würde ich jedoch nach einem RSSI-Wert größer (positiv größer) -60 Ausschau halten.</p>
<p>The post <a href="https://mobile.fhstp.ac.at/development/rssi-messungen-von-bluetooth-auf-android/">RSSI-Messungen von Bluetooth auf Android</a> appeared first on <a href="https://mobile.fhstp.ac.at">Mobile USTP MKL</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
