ppedv Team Blog: Windows Phone 8/8.1 Kinderecke

Das Smartphone wird immer mehr zum beliebten Gameboy Ersatz, um zu verhindern das die Weitergabe an Kinder und Jugendliche zu immensen in-App Käufen und enormen Telefonrechnungen führt verfügt bereits Windows 8 über eine Kinderecke. Diese abgesicherte Umgebung konfiguriert man bei der Initialisierung über Einstellungen –> Kinderecke, es ist sinnvoll für spätere Konfiguration eine Kachel auf dem Startbildschirm anzulegen.

Kindereckenkonfig



Dieser Modus wird dann durch nach links wischen auf dem Sperrbildschirm aktiviert und bietet folgende Vorteile:

-In- App Käufe werden geblockt sofern keine Brieftaschen-Pin hinterlegt ist

nichtmoeglich

- In der Kinderecke ist weder ein Browser noch der Zugriff Daten des Handys noch der SD Karte verfügbar.
Spiele, Musik, Videos und Apps können jedoch einzeln frei gegeben werden.

KCmixedwip

 

Sollte das Smartphone ein mal verloren werden bietet Windows Phone den Service es zu Orten bzw. die letzte Position, die bestimmt werden konnte, zu Orten.

Unter www.windowsphone.com in der Rubrik Mein Handy –> Mein Handy finden ,
lässt sich, nach dem Login per Microsoft Konto, die letzte Position des Smartphones anzeigen bzw. das Smartphone anklingeln selbst wenn es eigentlich auf Stumm geschalten ist.

 

aktuellerStandort

codefest.at [MS]: Teil 1: Plattformübergreifende App-Entwicklung mit dem MVVMbasics Framework

Gastbeitrag von Andreas Kuntner

Dieser Artikel ist der erste Teil einer dreiteiligen Serie.

Andreas Kuntner arbeitet als .NET Entwickler mit Schwerpunkt auf Client-, UI- und Mobile Development, und betreut in seiner Freizeit das MVVMbasics Framework und den Developer-Blog http://blog.mobilemotion.eu/

Das Model-View-Viewmodel Design Pattern ist – nicht zuletzt dank Universal Apps für Windows 8 und Windows Phone – mittlerweile den meisten Entwickler ein Begriff. Um das Pattern in „Real Life“ Projekten zu verwenden braucht es aber das eine oder andere MVVM Framework – wer will schon das INotifyPropertyChanged Interface oder Command Binding jedes Mal aufs neue selbst implementieren?

Das MVVMbasics Framework ist seit wenigen Tagen in der Version 2.0 verfügbar – zu diesem Anlass möchte ich euch anhand einer kleinen Demo-App zeigen, was damit möglich ist und wo es die tägliche Arbeit erleichtern kann, sowohl in Bezug auf die typischen MVVM-Anwendungsfälle wie etwas Data und Command Binding, als auch im Bereich der plattformübergreifenden Entwicklung.

Eine erste App

Die komplette Solution steht zum Mitschauen unter http://mobilemotion.eu/downloads/SimpleChat.zip zum Download zur Verfügung – hier im Blog werde ich nur die wichtigsten Code-Snippets zeigen.

Als Demo habe ich einen kleinen, sehr primitiven Chat-Client geschrieben. Dazu ist natürlich eine Server-Anbindung notwendig - Das kann ein Azure-Mobile-Service oder ein beliebiges anderes Webservice sein, ich habe für die Demo ein (sehr reduziertes) Test-Service gebaut dass ich lokal hosten kann, und das nur drei Funktionen bietet: Anlegen eines Users, Senden einer neuen Nachricht, und Abrufen aller neuen Nachrichten. Auf diese drei Funktionen werden wir aus dem Client zugreifen.

Los geht’s! Neue Solution anlegen und ein Projekt hinzufügen – um später für eine plattformübergreifende Lösung gerüstet zu sein, empfehle ich die Models und Viewmodels vom Rest zu trennen. Wir legen also als erstes Projekt eine Portable Class Library an, die .NET 4.5, Windows 8 und Windows Phone 8.1 unterstützt:

clip_image001

Zu diesem Projekt muss jetzt die MVVMbasics Bibliothek hinzugefügt werden. Eine Suche nach „mvvmbasics“ im NuGet Package Manager bringt eine Liste an Ergebnissen, wir installieren das erste angebotene Paket „MVVMbasics“ (die weiteren Bibliotheken dienen nur der Abwärtskompatibilität und werden in neuen Projekten nicht mehr benötigt):

clip_image003

Jetzt ist es an der Zeit, die Struktur des Programms festzulegen: Für das einfache Demoprogramm ist nur ein einziges Datenmodell nötig das eine einzelne Chatnachricht repräsentiert. Außerdem wird das Programm zwei Pages beinhalten, eines zum Login und eines für den tatsächlichen Chat, für jede dieser Pages brauchen wir ein Viewmodel. (In MVVMbasics existiert immer exakt ein Viewmodel pro Fenster bzw. Page, alle anderen Daten werden in Models organisiert. Diese fixe 1:1-Beziehung ist für die plattformübergreifende Navigation sowie um direkt auf Navigations-Events zu reagieren notwendig, wie wir später noch sehen werden). Wir legen also (zur besseren Übersicht am besten in zwei neuen Namespaces Models und Viewmodels) die Klassen MessageModel, LoginViewmodel und ChatViewmodel an.

Data Binding

Models werden in MVVMbasics immer vom Typ BaseModel abgeleitet, das für eine korrekte (und möglichst einfache) Implementierung des INotifyPropertyChanged Interfaces sorgt. Im Fall des MessageModel erstellen wir drei Properties, die den Namen des Users der die Nachricht geschrieben hat, den Inhalt der Nachricht, und den Zeitpunkt zu dem die Nachricht geschrieben wurde beinhalten. Jedes Property, das an ein Control in der Page gebunden werden soll, muss bei Änderung das PropertyChanged Event auslösen - dafür bietet MVVMbasics die Set Methode:

private string _username;

public string Username
{
	get { return _username; }
	set { Set(ref _username, value); }
}

Die Set Methode sorgt dafür, dass der Inhalt des Properties mit dem neuen Wert befüllt wird, und löst das PropertyChanged Event aus – beides aber nur dann, wenn der alte und neue Wert des Properties unterschiedlich sind. Die anderen beiden Properties Content und Timestamp werden analog definiert.

Viewmodels müssen immer von der Basisklasse BaseViewmodel abgeleitet werden. Diese erbt intern von BaseModel, sodass die bequeme INotifyPropertyChanged Implementierung wie oben beschrieben auch hier zur Verfügung steht, und bietet zusätzliche Methoden an die für die Navigation gebraucht werden.

Das LoginViewmodel enthält drei Properties: Name und Age (der Benutzer muss zur Anmeldung seinen Namen und sein Alter angeben), sowie Username (dieser setzt sich aus Namen und Alter zusammen und wird zur Anmeldung ans Webservice geschickt). Das Username Property erhält nur einen Setter, der von den anderen beiden Properties abhängt:

public string Username
{
	get { return String.Format("{0} ({1})", Name, Age); }
}

Name und Age müssen nun zusätzlich zu ihren eigenen auch noch das PropertyChanged Event des Username Properties auslösen. Wir nutzen dazu eine erweiterte Variante der Set Methode:

private string _name;
public string Name
{
	get { return _name; }
	set { Set(ref _name, value, () => NotifyPropertyChanged(() => Username)); }
}

In diesem Fall wird der Set Methode als dritter Parameter eine Methode (hier in Form einer Lambda Expression) übergeben, die nach dem Aktualisieren des Property-Werts aufgerufen wird, allerdings nur wenn der alte und neue Wert des Properties unterschiedlich waren. Innerhalb dieser Methode lösen wir durch die NotifyPropertyChanged Methode das PropertyChanged Event des Username Property aus.

Holger Sirtl: Hintergrundinformationen zu den Neuerungen in Azure Media Services

Die Azure Media Services wurden letzte Woche deutlich erweitert. Nicht zuletzt die Möglichkeiten zum Live Streaming unter Media Indexer erweitern das Funktionsspektrum der Media Services beträchtlich. Zeit, ein paar Informationsquellen zusammen zu suchen, über die man sich in diesen neuen Funktionen einarbeiten kann.

Live Streaming

Bisher boten die Media Services ausschließlich Unterstützung für on-demand Streaming, d.h. Videos mussten zunächst nach Azure hochgeladen werden, wo sie nach Abschluss des Uploads dann konvertiert, verschlüsselt, bearbeitet und dann zum Streaming bereitgestellt werden konnten. Ab sofort ist auch Live Streaming möglich, d.h. Videos können bereits während des Uploads über Streaming Clients ausgelesen werden.

Azure Media Indexer

Der Media Indexer ist ein Werkzeug zum Extrahieren von Inhaltsinformationen aus Videos, die dann als Grundlage für Suchfunktionen genutzt werden können. Neben dem Auslesen von Meta-Informationen können für englischsprachige Videos sogar Untertitel erzeugt und mit entsprechenden Zeitstempeln für die Wiedergabe versehen werden. Der Media Indexer erweitert somit die Möglichkeiten zur Archivierung und zum Durchsuchen von Videoinhalten beträchtlich.

Artikel und Blogposts

Folgende Artikel und Blogposts kann ich als Lektüre empfehlen:

Aus dem Azure Media Services Blog sind folgende Artikel äußerst lesenswert:

Karsten Kempe: ‘TFS loves Git’ auf der BASTA! 2014

Basta ALM TodayEingebettet in die Basta! 2014 findet die ALM Today Konferenz vom 22.09. bis 25.09. in Mainz statt. Ich freue mich als Sprecher dabei sein zu können. Am Mittwoch den 24.09. werde ich Einblicke in die Beziehung von Git und Team Foundation Server geben, dem heißesten Promi-Paar seit Angelina Jolie und Brad Pitt.

TFS loves Git

Promi-Hochzeiten hat und wird es immer geben. Meist sind die beiden Partner erfolgreich und sexy. Als sich TFS und Git zueinander bekannten, war die Skepsis groß. Er (der TFS) ist laut Gartner die führende ALM Plattform, gilt aber als schwer und behäbig. Sie (Git) ist eine der angesagtesten Versionskontrollen unserer Zeit, leicht und sexy! Würde diese Beziehung gut gehen? Diese Liebe hält nun schon seit mehr als einem Jahr und ist enger als je zuvor. Grund genug also, um sich die Partnerschaft einmal näher anzusehen. Wer profitiert von wem? Und warum sind sie als Paar so außerordentlich erfolgreich? In dieser Session erhalten Sie einen Eindruck über das Zusammenspiel von Git und TFS und sehen wie man als Entwickler von den Stärken der Beiden profitieren kann.

ALM Today Konferenz

Die ALM today im Rahmen der BASTA! bündelt konsequent diese einzelnen Aspekte des Application Lifecycle Managements unter einem Dach: Die methodischen Aspekte aus der Agilität, die Qualitätssicherung durch das Testing sowie das Tooling rund um Visual Studio und TFS. Ergänzt werden diese Aspekte nun durch neuere Trends wie DevOps, Design Thinking und Softskills sowie Vermarktungs- und Managementstrategien.

Die ausgewählten Sessions und erfahrenen Sprecher der ALM today repräsentieren diese erweiterten und entscheidend Produkt-Lifecyle von der ersten Idee, über die Entwicklung, den Betrieb und Vertrieb bis hin zum zufriedenen Kunden. Das notwendige und praxisorientierte Know-how für die digitale Transformation und IT Leadership unter einem Dach.

Holger Schwichtenberg: nameof()-Operator in C# 6.0

Der neue C#-Operator nameof() bringt Typsicherheit in allen Fällen, wo bisher der Name eines Typs, eines Klassenmitglieds, eines Namensraums oder einer Variablen als Zeichenkette zu verwenden war.

codefest.at [MS]: Hadoop/HDInsight Einführung Big Data mit HDInsight/Hadoop für .NET Entwickler


“HDInsight is Microsoft’s Hadoop-based service that brings an Apache Hadoop-based solution to the cloud. It gives you the ability to gain the full value of Big Data with a modern, cloud-based data platform that manages data of any type, whether structured or unstructured, and of any size.”

Quelle: http://azure.microsoft.com/en-us/pricing/details/hdinsight/

image

Big Data mit Hadoop und HDInsight

In dieser Blog-Reihe über Big Data mit Hadoop und HDInsight möchte ich euch, den Entwicklern, den Einstieg in die Welt von Big Data schmackhaft machen. Das natürlich auf Basis der Microsoft Lösung HDInsight, die ja zu 100% Hadoop beinhaltet. Aber bevor wir so richtig mit Hands-On loslegen können, sollten wir uns ein wenig mit der vorhandenen Technologie in der Theorie beschäftigen, die dem Ganzen zu Grunde liegt. Keine Angst, ich bin eher ein „Mann der Praxis“, ich werde mich also so kurz wie möglich halten, damit wir recht bald einmal die Praxis beleuchten können.

Was ist Big Data?

Bevor wir uns den Technologie-Stack selbst genauer ansehen können, sollten wir uns dem Begriff “Big Data” einmal genauer widmen. Nun ja, da beginnen die Schwierigkeiten bereits. Big Data kann nämlich für jeden etwas anderes bedeuten. Für mich bedeutet es, dass Daten vorliegen, die einfach zu komplex sind, um sie in traditionellen relationalen Datenbanken UND auch in multidimensionalen Datenbanken zu analysieren. Das ist aber eben nur eine Begründung für Big Data, nämlich rein die Anzahl der Daten, bzw. eben die Datenmenge. Aber für mich ist auch schon ein einzelnes Buch „Big Data“, da die Wörter in einem Buch komplett unstrukturiert vorliegen (Vorsicht in etwaigen Diskussionen über Big Data in eurem Lieblingsliteraturzirkel, der Autor eines Buches sieht das naturgemäß etwas anders) und es nun einmal schwierig ist, die Anzahl der Hauptwörter oder alle Bindewörter in einem, oder mehreren Büchern einfach einmal so zu zählen. Also wie ihr möglicherweise schon an anderer Stelle gelesen habt, zieht man sich in der einschlägigen Literatur zu dem Thema auf eine allgemeine Beschreibung zurück.

Im Allgemeinen haben sich, wenn man von Big Data spricht, die „3V’s“ eingebürgert (Doug Laney von Gartner hat schon 2001 darüber sinniert, siehe hier) . Das sind Volume, Variety und Velocity. Sehen wir uns jeden dieser drei einmal kurz an:

· Volume – Datenmenge: Hierunter fallen sowohl große Datenmengen von Terrabytes bis Petabytes, als auch viele kleine Datenmengen, die es gemeinsam zu analysieren gilt.

· Variety – Datenvielfalt: Nicht nur die (sehr) großen Datenmengen an sich, sondern auch die Vielfältigkeit der anfallenden Daten sind eine der Herausforderungen im Big Data Bereich. Ihr werdet das vermutlich selbst kennen aus eurer Vergangenheit, oder in eurer aktuellen Firma, wo die Daten aus unternehmensinternen, und/oder aber auch aus externen Quellen stammen. Diese unterschiedlichen Daten liegen entweder

o strukturiert (z. B. in relationalen Datenbanken)
o halb-strukturiert (z. B. Log-Dateien von Web-Servern) und/oder
o komplett unstrukturiert (z. B. Texte, Webseiten, Video-, Audio-Dateien) vor.

· Velocity – Geschwindigkeit: Daten, die sich andauernd verändern und kurze Gültigkeit/Aktualität beinhalten. Diese erfordern eine andauernde Generierung und Verarbeitung – sehr häufig in Echtzeit.

image

Noch extra erwähnen möchte ich, dass die zugrundeliegenden Daten natürlich vertrauenswürdig und korrekt sein MÜSSEN, denn wenn die Datenbasis schon schlecht ist, dann wird es mit der besten Technologie nicht gelingen brauchbare Ergebnisse für den Endbenutzer zu erzeugen, aber das war ja schon in der Vergangenheit bei euren Projekten mit relationalen Datenbanken und Analysis Services ja auch schon ein kritischer Punkt.

Soweit so gut, aber ich kann es schon richtig hören, wie ihr mir zuruft:

Die 3V’s sind nett und gut, aber SQL Server und/oder SQL Server Analysis Services mit den Integration Services erledigen diesen Job für die oben angeführten Problemstellungen doch hervorragend. Hmm, ja, möglicherweise, für strukturierte Daten. Möglicherweise.

Mit den unstrukturierten Daten und der komplexen Bearbeitung derselben sind wir nun schon eher bei des Pudels Kern angelangt, warum wir mit den bisher eingesetzten Technologien vermutlich an Grenzen stoßen werden und was das Thema Big Data im Endeffekt ausmacht. Wir wollen ja nicht „nur“ einen Server, der sich um die großen Daten, die unstrukturiert vorliegen (oder vielen kleinen Daten) kümmert, sondern die Bearbeitung der Daten soll mit mehreren Maschinen durchgeführt werden.

Und, Schwupps sind wir schon beim nächsten Thema angelangt. Die verwendete Technologie für das Thema Big Data. Aber eines sollte hier noch klar gesagt werden: Big Data wird keine der erwähnten Technologien ersetzen, sondern im Gegenteil. Es wird ergänzend eingesetzt. Für manche von euch ist das bestimmt eine Frohbotschaft, es kommt noch mehr Technologie auf euch zu….

Die Big Data Technologie

Die Daten sollen also mit „geballter Power“, also mit mehreren Maschinen, „beackert“ werden, und das nicht mit SQL oder MDX. Die Daten werden eher in einer Art Batch-Processing bearbeitet, das Resultat landet möglicherweise (muss nicht sein) wieder in Tabellenform. Nun, das genau ist eine (sehr kurze) Zusammenfassung der Kernfunktionalität von Hadoop. Das verteilte Bearbeiten von Daten, innerhalb eines Clusters mit einem Head-Node und mehreren Data-Nodes, wo jedes Node an einem Teil der Daten die Bearbeitung durchführt, um das gewünschte Resultat zu erzeugen.

Hadoop Übersicht

Hadoop selbst ist ein Open Source Projekt und ein Apache Projekt - http://hadoop.apache.org. Der innerste Kern besteht aus 2 Teilen:

· Hadoop Distributed File System (HDFS) – speichert die Daten im Cluster. Die Daten werden in Blöcke geteilt und auf verschiedene Nodes im Cluster verteilt.

· MapReduce – ein Programmiermodell, das in zwei Phasen aufgegliedert ist. Wie der Name schon sagt eben Map und Reduce. Damit ist es möglich die Datenbearbeitung auf mehrere Nodes zu verteilen, in der Map Phase werden so Zwischenergebnisse erzeugt, die in der Reduce Phase – ebenfalls parallelisiert - zu einem Gesamtergebnis weiter verarbeitet werden.

Mit diesem Wissen können wir uns schon einmal ansehen, wie die Basis Komponenten innerhalb eines Hadoop Clusters aussehen könnten (sofern dieser einmal läuft, was aber keine große Hexerei ist, wie wir in meinem nächsten Blog Eintrag sehen werden) und wie diese zusammen interagieren:

· Der Name Node (auch oft “Head Node” innerhalb des Clusters genannt): Hält primär die Metadaten für HDFS und da die Daten ja verteilt von den Daten Nodes in einzelnen Datenblöcken bearbeitet werden, muss jemand die Ablage der Daten koordinieren und den Cluster überwachen und bei einem Ausfall dementsprechend reagieren, d. h. die Daten neu auf die verbliebenen Data Nodes verteilen. Dies ist die Aufgabe des Name Node, was ihn aber auch gleichzeitig zum „Single Point of Failure“ in einem Hadoop Cluster macht.

· Data Node: Speichert ihm zugewiesene Daten in sogenannten HDFS Datenblöcken. Diese Datenblöcke werden innerhalb eines Hadoop-Clusters repliziert um Ausfallsicherheit zu gewährleisten. Jeder Data Node meldet sich fortwährend beim Name Node, der ansonsten auf einen Ausfall reagieren muss.

Soweit zur Datenhaltung, die Überwachung eine MapReduce-Jobs obliegt zwei sogenannten Trackern:

· Der Job Tracker verteilt die einzelnen Aufgaben innerhalb des MapReduce Jobs, ist aber im Fehlerfall weniger kritisch zu handhaben als der Ausfall des Name Nodes, da bei Neustart des Job Tracker alle Jobs erneut gestartet werden.

· Der Task Tracker erledigt die eigentliche Arbeit bei dem angeforderten MapReduce Job, läuft üblicherweise auf jedem Data Node.

Bildlich gesprochen lässt sich das folgendermaßen darstellen:

image

Soweit zum Core, weitere zugehörige Hadoop-Projekte, die durchaus hilfreich sind und das Gesamtbild - und die damit verbundenen technologischen Möglichkeiten - doch um einiges erweitern:

· Hive – Die Ergebnisse, die mit MapReduce Jobs erzeugt werden können mittels Hive in einer SQL ähnlichen Abfragesprache, der Hive Query Language (HQL) aus dem Hive store abgefragt werden. Hive ist ideal, um die mittels MapRedue erzeugten Ergebnisse in die bestehende BI Landschaft zu integrieren.

· Pig – Eine weitere Möglichkeit, die Daten von MapReduce Jobs abzufragen ist Pig, welches eine Scripting Engine mit dem Namen Pig Latin zur Verfügung stellt. Mit dieser können Abfragen ‚anprogrammiert‘ werden, also Prozedural abgefragt werden, im Gegensatz zu Hive, das wie erwähnt, ähnlich zu SQL – also deklarativ – arbeitet.

· HCatalog – Dieser setzt auf den Hive Metastore auf und stellt Schnittstellen für MapReduce und Pig zur Verfügung, um Daten in Tabellenform darzustellen.

· Oozie – Eine Workflow Engine für mehrere MapReduce Jobs.

· Sqoop – Wird angewendet, um Daten aus und in relationale Datenbanken in HDFS zu importieren und/oder zu exportieren.

Weitere sind noch: Fume (zum Importieren von Daten in HDFS), Mahout (machine-learning), oder Ambari (Monitoring Tool für den Cluster). Zusammengefasst sieht die Landschaft dann im Großen und Ganzen so aus:

image

Wie man deutlich erkennen kann ist Hadoop nicht etwa (nur) eine Datenbank, bzw. ein Datenbankmanagementsystem (wie SQLServer z. B. eines ist). Es ist ein verteiltes Dateisystem, das mit riesigen (unstrukturierten) Datenmengen – mit dutzenden Terabytes - gefüttert werden kann, diese wiederum mit MapReduce Jobs bearbeitet und sortiert werden können - und das mit Hilfe der zu Grunde liegende Cluster-Technologie in Sekunden. In Kombination mit den erwähnten Unterprojekten kann Hadoop Prozesse ausführen, die weit über die Leistung eines (normalerweise) eingesetzten relationalen Datenbank, oder Datawarehouse-Systems hinausgehen.

Sehen wir uns doch einmal gemeinsam ein paar Einsatzszenarien für Big Data und Hadoop/HDInsight an.

Einsatz-Szenarien

1. Hadoop als ETL-Tool

Wenn große Datenmengen zur Verfügung stehen, dann steht man immer wieder vor der großen Herausforderung die für das Unternehmen relevanten Daten herauszufiltern. Nun, Hadoop ist hier ein eleganter Ansatz. Die Daten werden in Hadoop geladen und mit MapReduce Jobs bearbeitet. Mit eigenen Filtern und eigener Logik - das Resultat sind strukturierte, summierte Daten. Diese können mit bestehenden Analyse-Werkzeugen verfeinert werden, bzw. dem Reporting zugeführt werden.Normalerweise wird nu rein kleiner Prozentsatz vom gesamten vorhandenen Datenstrom für ein bestimmtes Business-Problem benötigt. Hadoop mit MapReduce, dem Clusteraufbau und den weiteren Unterprojekten ist dafür eine sehr gut geeignete Plattform.

2. Hadoop als Exploration-Engine

Wenn die Daten einmal im Cluster sind können nahezu beliebige Tools zur Analyse verwendet werden. Dies werden wir in einem der Blog-Einträge noch genauer betrachten, wenn wir Excel, PowerBI, Reportung Services usw. auf unseren (lokalen) Cluster loslassen. Neue Daten werden hinzugefügt, die bestehenden Ergebnisse bleiben weiter vorhanden und können aber natürlich zur erneuten/weiteren Analyse der Daten verwendet, bzw. weiter verdichtet werden. Das Laden in andere Systeme, wie einem SQLServer, bzw. einem SQL Server Analysis Server ist problemlos möglich und so können die Ergebnisse innerhalb des Unternehmens weiteren Anwendern zur Verfügung gestellt werden.

3. Hadoop als Archiv

Historische Daten Daten werden nicht ewig vorgehalten, sondern landen irgendwann einmal im Archiv. Werden die Daten für eine Analyse wieder benötigt, so ist es häufig mühsam diese wieder herzustellen. Mit dem Ergebnis, dass historische Daten oft nicht für die Analyse zur Verfügung stehen, da man versucht diesen Aufwand zu vermeiden. Die zugrunde liegende Speichertechnik in HDFS, sowie die effektiven Indizierungsmöglichkeiten innerhalb des Clusters - und da Speicher heutzutage günstig ist - können die (originalen) Daten in einem Hadoop Cluster weiter vorgehalten werden. Der Aufwand der Wiederherstellung entfällt und die Daten stehen jederzeit für eine historische Analyse zur Verfügung.

Microsoft HDInsight - Hadoop unter Windows

HDInsight ist die Microsoft Implementierung für Big Data Lösungen mit Apache Hadoop als Unterbau. Ihr braucht jetzt keine Angst zu haben, falls ihr denkt, dass Microsoft hier nun etwas eigenes gebaut hätte.

HDInsight ist zu 100 Prozent kompatibel mit Apache Hadoop und baut komplett auf den Open Source Framework auf.

Microsoft hat das Projekt großartig unterstützt, indem es die Funktionalität zur Verfügung gestellt hat, um Hadoop unter Windows laufen zu lassen, da Hadoop ursprünglich nur für Linux entwickelt wurde. Sie haben den notwendigen Source Code der Community zur Verfügung gestellt und diese hat dann diesen dankenswerter Weise (für uns Windows Entwickler) komplett in den Source einfließen lassen. Somit läuft Hadoop unter Windows und Microsoft hat hier die Unterstützung noch nicht gestoppt. Es wurden weitere APIs geschrieben, um mit C# Hadoop anprogrammieren zu können, bzw. den ODBC-Treiber entwickelt um auf die Daten von Hadoop auch aus bestehenden Applikation zugreifen zu können. Auch das werden wir in im Laufe dieser Blog-Reihe sehen können.

HDInsight ist in zwei Ausprägungen verfügbar, als Cloud-Lösung und als lokale Installation:

1. Windows Azure HDInsight Service: Solltet Ihr noch keine Azure Subscription euer eigen nennen, ist es nun soweit, HDInsight steht euch unter Azure zur Verfügung und wartet nur darauf, von euch als Cluster verwendet zu werden. Wir werden die Installation und die anfallenden Kosten im nächsten Blog-Eintrag näher beleuchten.

2. Windows Azure HDInsight Emulator: Eine hervorragende Lösung von Microsoft, die einen single-node, geeignet als Einzelplatz Installation, zur Verfügung stellt, welcher z. B. auf eurer Entwicklungsmaschine bestimmt eine ganz gute Figur macht. Dafür ist er nämlich gemacht: als lokale Big Data Entwicklungsinstallation zu dienen. Eure Resultate könnt ihr dann in das Azure HDInsight Service überführen und in einen richtigen Cluster in Produktion bringen. Erst einmal ohne anfallender Kosten für den Cluster.

Und genau diese beiden Lösungen werden wir uns im zweiten Teil dieser Blog-Reihe genauer ansehen.

Zusammenfassung

Hadoop an sich eignet sich perfekt für die Verarbeitung umfangreicher Batchjobs. Hadoop kann Dutzende Terabyte dateibasierter Daten sehr schnell verarbeiten. Mit diesen grundlegenden, aber leistungsfähigen Funktionen ist Hadoop sehr gut geeignet, um große Dateien zu durchsuchen, Informationen zu aggregieren oder grundlegende mathematische Funktionen wie Summe, Mittelwert oder Durchschnittswert auszuführen. HDInsight ist Microsoft’s Cloud Lösung für Big Data, zu 100% basierend auf den Open Source Framework Hadoop.

So, erst einmal genug der Theorie, ab jetzt wird kräftig mit der Software gearbeitet, ich hoffe ihr seid bei den nächsten Einträgen wieder fleißige Leser!


Berndt Hamböck ist seit 2007 MCT, darüber hinaus befasst er sich mit Lösungen für komplexe Anwendungsszenarien mit den neuesten Microsoft Technologien. Die Erfahrungen aus der Projektarbeit gibt er in Vorträgen und Trainings weiter und begleitet Entwicklerteams in Softwareunternehmen bei Projekten im Microsoft Umfeld. Folge ihm auf Twitter, um nichts zu verpassen.

Das ist ein Gastbeitrag. Die Meinung des Autors muss sich nicht mit jener von Microsoft decken. Durch den Artikel ergeben sich keinerlei Handlungsempfehlungen. Microsoft übernimmt keine Gewähr für die Richtigkeit oder Vollständigkeit der Angaben.

Holger Sirtl: Microsoft Migration Accelerator für Azure als Preview verfügbar

Letzte Woche hat Microsoft den Migration Accelerator (MA) für Azure als Preview verfügbar gemacht. Damit ist es möglich, virtuelle Maschinen aus physischen, VMware-, AWS- und Hyper-V- Umgebungen sehr einfach nach Microsoft Azure zu migrieren. Die Preview ist zunächst auf einen eingeschränkten Benutzerkreis beschränkt, wird jedoch nach und nach geöffnet.

Der Migration Accelerator vereinfacht viele Aspekte einer Migration virtueller Maschinen nach Microsoft Azure:

  • Analyse der Workloads, die in der virtuellen Maschine ausgeführt werden
  • Installation des Remote Agents
  • Einrichten der Netzwerkkonfiguration
  • Konfiguration der Endpunkte

Der Migration Accelerator ist zunächst nur in Nordamerika (USA & Kanada) verfügbar und unterstützt als Gastbetriebssystem nur Windows Server 2008 R2 und höher. Der Einsatz des Accelerators selbst ist kostenlos, Kosten fallen nur für die Workloads an, die am Ende tatsächlich auf Microsoft Azure ausgeführt werden, also die virtuellen Maschinen.

Jochen Kalmbach: Reverse-String – Unicode-Aware

In vielen Beispielen wird für den Einstieg in die String-Klasse von .NET das “umdrehen” eines Strings aufgeführt. Da der String “immutable” ist, geht dies ja nicht direkt und man muss i.d.R. den Umweg über ein Array gehen. Der Code dafür schaut meistens so aus (C++/CLI):

  String^ ReverseString(String^ text)
  {
    array<Char> ^ charArray = text->ToCharArray();
    Array::Reverse(charArray);
    return gcnew String(charArray);
  }

Das Beispiel ist zwar einfach, aber es ist dann doch wieder zu einfach… es beachtet nämlich nur Zeichen, die aus genau einem Char bestehen. Im Unicode gibt es aber sher viele Zeichen (Glyph), die aus mehr als einem Char bestehen. So gibt es diverse Combining-Characters.

So kann man das “ä” als \u00e4 (sog. precomposed character) schreiben oder auch als ‘a’ + \u0308 (combining character).

Verwendet man die zweite Schreibweise, so geht das umdrehen des Strings, welche rein Char-basiert ist, schief! Dreht man dann z.B. das Wort “absa?gen” (mit combining chartacter) um, so kommt plötztlich “neg?asba” heraus, da das ? plötzlich dem “g” zugesprochen wird!

Deshalb sollte man für ein Unicode-Aweare “Reverse” immer jedes gesamte Text-Element verwenden. Und siehe da, .NET bietet hierfür natürlich auch die passenden Helferklassen ;)

String^ ReverseStringUnicodeAware(String^ text)
{
  System::Globalization::TextElementEnumerator ^enumerator = System::Globalization::StringInfo::GetTextElementEnumerator(text);
  auto elements = gcnew System::Collections::Generic::List<String^>();
  while (enumerator->MoveNext())
    elements->Add(enumerator->GetTextElement());
  elements->Reverse();
  return String::Concat(elements);
}

Es gibt da auch noch im VB.NET Namespace die Methode “Microsoft::VisualBasic::Strings::StrReverse“. Ich rate aber dringend davon ab diese zu verwenden, da diese nur ein Array::Reverse macht und somit genau die falsche Methode verwendet! (dies scheint aber wohl ein Bug zu sein, da die Implementierung dies wohl richtig machen sollte)

Hier das vollständige Beispiel:

String^ ReverseString(String^ text)
{
  array<Char> ^ charArray = text->ToCharArray();
  Array::Reverse(charArray);
  return gcnew String(charArray);
}

String^ ReverseStringUnicodeAware(String^ text)
{
  System::Globalization::TextElementEnumerator ^enumerator = System::Globalization::StringInfo::GetTextElementEnumerator(text);
  auto elements = gcnew System::Collections::Generic::List<String^>();
  while (enumerator->MoveNext())
    elements->Add(enumerator->GetTextElement());
  elements->Reverse();
  return String::Concat(elements);
}

int main()
{
  // Simple example:
  String^ str = "Hallo";
  System::Windows::Forms::MessageBox::Show("'" + str + "' => '" + ReverseString(str) + "'");

  // Combining characters: (WRONG)!
  String^ str2 = gcnew String(gcnew array<Char> { 'a', 'b', 's', 'a', 0x0308, 'g', 'e', 'n' });  // absägen
  System::Windows::Forms::MessageBox::Show("'" + str2 + "' => '" + ReverseString(str2) + "'");  // WRONG!

  // Combining characters: (CORRECT)
  System::Windows::Forms::MessageBox::Show("'" + str2 + "' => '" + ReverseStringUnicodeAware(str2) + "'");  // CORRECT!
}

Siehe auch mein (alter) Artikel über Unicode: Einführung in Codepages und Unicode

ppedv Team Blog: deklarativ Variablen in HTML mit Angular zuweisen

Ein Angular Controller enthält eine Liste die per Ajax Call aus einem Json REST Service gefüllt werden. Dies ist eine Eigenschaft des Scope.

   1:  App.controller('chatController', function ($scope, $http) {
   2:      $scope.chatUsers = [];

Diesem Array soll bestimmte Werte vorbelegt werden. Als Anwendungsfall kann man eine Dropdownliste nennen. In dieser sollen drei Länder vorbelegt werden wie z.B. DE, AT und CH. Der Rest soll aus der Datenbank bzw. aus einem Service zusätzlich angezeigt werden. Wie kann man also Werte vorbelegen? Natürlich geht das im JavaScript Code des Controllers. Auch ein Modul lässt sich dafür einsetzen. Wenn man allerdings mit ng-init arbeitet, kann man mit einem deklarativen Ansatz dem UI Designer die Entscheidung überlassen. Das Array wird im HTML Code befüllt.

   1:   <div ng-controller="chatController">
   2:          <div ng-init="chatUsers = [ {name:'Franz',  userId:700000},
   3:                                   {name:'Laura',  userId:1300000}
   4:      ]"></div>

Diesen Ansatz könnte man durchaus auch für Offline Daten nehmen um etwas anzuzeigen, solange der Service nicht bereit ist.

Sven Hubert: Automatic creation of build processes for feature branches

TFS functions enhanced and simplified using the TFS ASAP

In order to decouple the implementation of features and their requirements it is recommended to use feature branches. When a certain stability is achieved the source code changes are integrated into the main branch.

To validate the source code quality in terms of compilability, executability of tests and compliance with the code analysis rules it is useful to set up an additional continuous build process for each branch. This leads to an automatic quality check after each check in.

While creating a feature branch is straightforward and only a matter of seconds setting up the build is quite complicated and time consuming. Why can’t this not be that simple as well? It can be.

The easiest way to set up a build process is cloning an existing. For this purpose, appropriate permissions are required.

Then a number of settings have to be adjusted:

- Name (according the conventions)

- Trigger (Rolling builds)

- Source Settings

- Projects, which should get compiled

- Test Categories, Symbol Server Settings, Retention Policy, etc.

The proper modification of one of the parameters will quickly be forgotten. That’s why, the first build of a new feature branch is almost always going wrong.

This complicated and especially error-prone step can be automated through the use of the TFS Automated Servicing & Administration Platform. To enable this automation rule a configuration file needs to be added to the directory in which the feature branches will get created afterwards.

clip_image006

The configuration file refers to the build definition which should be used as a template and contains all different settings.

For all the branches that are created under the directory, a suitable build process will automatically be set up by the server in the background. Hereby the application of a feature branch with associated build process is as quick and easy as the previous application of a branch without a continuous quality check.

In addition, the build definition is generated even if the user does not have the necessary rights. A softening of the rights concept is thereby avoided.

You have  small extension through the TFS Automated Servicing & Administration Platform with great effect which leads to improved quality and more time to concentrate on the really value-adding tasks.

Automatic creation of build processes for feature branches is a post from: AIT Blog

ppedv Team Blog: Windows 8.1: Was wurde aus dem Leistungsindex?

Vor langer Zeit führte Microsoft den Leistungsindex mit Windows Vista ein. Dabei handelte es sich um eine Art Benchmark, über die der Nutzer seinen PC von Windows bewerten konnte. Nach einem Leistungstest ergab sich am Ende für die verschiedenen Komponenten wie beispielsweise CPU, Arbeitsspeicher, Festplatte und Grafikkarte eine Bewertung.

Der Leistungsindex konnte über Systemsteuerung > System und Sicherheit > System eingesehen und aktualisiert werden.

clip_image002

Da Microsoft den Leistungsindex in Windows 8.1 entfernt hat, kann er nicht wieder aktiviert werden. Er lässt sich jedoch über einen kleinen Umweg aufrufen.

Hierzu rufen Sie in Windows 8.1 die Suche mit Windows + S auf. Danach geben Sie winsat ein und klicken auf das gefundene Feature winsat.

Nach Abschluss des Durchlaufs rufen Sie PowerShell auf, indem Sie erneut die Suche öffnen und PowerShell eingeben. Im PowerShell Fenster geben Sie in den Befehl „gwmi win32_winsat“ ein und drücken Enter.

clip_image004

Die Anzeige ist zwar nicht so hübsch grafisch dargestellt wie in Vorgängerversionen, allerdings ist die Ausgabe der Leistungswerte dennoch informativ.

Es gibt zusätzlich die Möglichkeit im Ordnerverzeichnis: „C:\Windows\Perfomance\WinSAT\DataStore“, in dem sich die Datei „Formal.Assessment(Initial).WinSAT.xml“ befindet, diese im entsprechenden Editor oder im Browser aufzurufen. Der Wert für den Leistungsindex findet sich im Knoten <WINSPR><SystemScore> inklusive weiterer Detailwerte für die anderen Komponenten.

clip_image006

clip_image008

 

 

ppedv Team Blog: Import eines EFS-Verschlüsselungszertifikats

 

Haben Sie Ihr Kennwort für das Benutzerkonto vergessen und musste dieses vom Administrator zurückgesetzt werden?  Sollen Dritte auf Ihre verschlüsselten Dateien zugreifen können oder möchten Sie Ihre verschlüsselten Dateien auf einem anderen Rechner einsehen? In allen Fällen lässt sich das Problem durch den Import des Verschlüsselungszertifikats lösen. Sobald dieses unter Windows in einem Benutzerkonto importiert wird, können die mit diesem Zertifikat verschlüsselten Dateien unter diesem Konto eingesehen werden.

 

  1. Doppelklicken Sie auf die exportierte EFS-Datei.
  2. Kicken Sie im Dialogfeld Zertifikatimport-Assistent auf die Schaltfläche Weiter. Bild19.png
  3. Geben Sie bei Bedarf den Standort und Namen des digitalen EFS-Zertifikats ein, und klicken Sie dann auf Weiter.          Bild20.png
  4. Geben Sie das Schutzkennwort ein, das während des Exports des EFS-Zertifikats erstellt wurde, sowie den Punkt Schlüssel als exportierbar markieren und klicken Sie dann auf Weiter.                        Bild24.png
  5. Damit der Zertifikatimport-Assistent das EFS-Zertifikat in den korrekten Speicherort importieren kann, markieren Sie das Optionsfeld Alle Zertifikate in folgendem Speicher speichern), und klicken Sie dann auf Weiter. Bild25.png
  6. Klicken Sie im letzten Fenster auf Fertig stellen.

Nun ist das Zertifikat installiert und kann verwendet werden.

Fabian Deitelhoff: Teil 7 – Raspberry Pi als Mediacenter mit Raspbmc (Gesamtfazit)

Teil 7 - Raspberry Pi als Mediacenter mit Raspbmc (Gesamtfazit)Und wir sind am Ende der Reise angelangt. Ich hoffe, ich konnte allen ein paar Infos auf den Weg zum eigenen Mediacenter mitgeben :). Das Thema lag mir am Herzen, weil ich häufig dazu gefragt werde. Zudem wollte ich auch endlich mal eine Blogserie schreiben. Nach etwas über einem Jahr, in dem mein Mediacenter jetzt läuft, wurde das auch mal Zeit.

In diesem letzten Teil geht es, im weitesten Sinne, um einen kleinen Blick über den Tellerrand. Ist eine XBMC-Installation auf einem Raspberry Pi wirklich die einzige Lösung? Ist der Raspberry Pi an sich als Hardware unersetzlich oder gibt es auch hier Alternativen?

Auf diese Fragen möchte ich eingehen, wenn auch nur knapp. Denn um alles aufzuschreiben, reicht auch eine Serie von sieben Blogposts nicht aus. Ich denke also, dass ich von Zeit zu Zeit noch Beiträge ergänzen werde. In welche Richtungen diese Beiträge aber genau gehen, weiß ich aktuell noch nicht.

Dieser Blogpost ist Teil einer Serie zum Thema “Raspberry Pi als Mediacenter mit Raspbmc”. Im Rahmen dieser Serie sind die folgenden Teile erschienen. Der jeweils aktuelle Beitrag ist hervorgehoben.

  1. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Hardware)
  2. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Software)
  3. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration I)
  4. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration II)
  5. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Performance)
  6. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Tipps & Tricks)
  7. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Gesamtfazit)

Ein Blick über den Tellerrand

Aber nicht nur um Alternativen bei der Hard- und Software dreht sich dieser Beitrag. Ich möchte auch etwas zur Realisierung beziehungsweise Lösung sagen, die jetzt am Ende herausgekommen ist. Im August 2013 habe ich den Raspberry Pi mit Raspbmc konfiguriert und seither recht häufig im Einsatz gehabt. Das ein oder andere ist mir dabei aufgefallen.

Weitere Hardware

Fange ich einfach mal mit der Hardware an. Neben dem Raspberry Pi gibt es noch viele weitere Modelle, die, unter anderem, als Basis für ein Mediacenter einsetzbar sind. Zu nennen sind da sicherlich die folgenden, sogenannten Single-Board-Computer:

  • Cubieboard
  • Odroid-X2
  • PandaBoard ES
  • BeagleBoard-XM
  • VIA APC
  • MinnowBoard
  • CuBox
  • Utilite

Und das sind nur einige, von denen ich persönlich gehört habe oder von denen auf anderen Blogs häufiger die Rede ist. Die Liste erhebt keinen Anspruch auf Vollständigkeit, denn das ist sie sicherlich alles andere.

Der zusätzliche Leistungsgewinn unterscheidet sich von Board zu Board. Teilweise gibt es schon Dual- oder gar Quad-Core ARM Prozessoren, mit weit über einem Gigabyte Arbeitsspeicher. Häufig ist auch Flash-Speicher direkt mit verbaut und die I/O-Anschlüsse sind zahlreicher.

Zusätzliche Leistung beziehungsweise Ausstattung allgemein bedeutet aber auch immer einen höheren Preis. Mit 40-60 Euro sind einige der Boards nur etwas teurer als der Raspberry Pi. Die Preise reichen aber auch durchaus über die 150 Euro Grenze hinaus, was schon einiges mehr ist. Auch bei Mini-Computern verhält es sich wie so häufig in der IT-Welt. Mehr Leistung und größere Ausstattung müssen bezahlt werden.

Ob die größere Hardware sein muss, kommt immer auf die Anwendungsfälle an. Manchmal muss es etwas größeres als der Raspberry Pi sein. Für ein Mediacenter, wie ich es in den letzten sechs Teilen vorgestellt habe, reicht der Pi aber absolut aus.

Eine gute Liste inklusive detaillierter Beschreibung zur Ausstattung findet sich auf raspberrypi-kaufen.de.

Weitere Software

Auch bei der Software gibt es eine umfangreichere Auswahl als Raspbmc. Bei der Auswahl der Software stellt sich zunächst die Frage, welche Aufgabe der Raspberry Pi in Zukunft übernehmen soll. Ist der Einsatz von XBMC geplant, ergibt sicherlich eine auf XBMC angepasste Distribution Sinn. Dadurch lässt sich viel Aufwand sparen, nicht nur bei der Installation. Ganz allgemein tauchen immer wieder folgende Distributionen auf meinem Radar auf. Auch hier erhebt die Liste wieder keinen Anspruch auf Vollständigkeit:

  • OpenELEC
  • Xbian
  • RasPlex

Sicherlich gibt es noch eine ganze Reihe mehr. Ausprobiert habe ich noch keine Distribution aus der Liste. Ich war und bin mit Raspbmc sehr zufrieden. Es gibt viele vergleichende Blogposts, die Vor- und Nachteile der jeweiligen Distribution gegeneinander aufführen, so dass eine Entscheidung vielleicht einfacher fällt.

Bewertung der Lösung

Wie ich in der Serie schon des Öfteren geschrieben habe, bin ich mit der Lösung sehr zufrieden. Sonst würde ich die Kombination aus Raspberry Pi und Raspbmc auch nicht schon über ein Jahr lang betreiben, sondern hätte mich schnell nach Alternativen umgesehen.

Die Stabilität gefällt mir. Hin und wieder habe ich das Gefühl, dass die Updates nicht eingespielt werden. Warum es hier hakt, weiß ich auch nicht genau. In so einem Fall darf der Raspberry Pi einmal neustarten. Beim Hochfahren werden dann die neuen Dateien heruntergeladen und installiert. Allerdings mache ich das auch nur wenn es mir zwischendurch aufgefallen ist. Ich unterziehe den Raspberry Pi keiner regelmäßigen Wartung oder ähnliches. Für diese Serie habe ich einige Male neu gestartet, um ordentliche Screenshots zu bekommen. Davor hatte der Pi eine Uptime von etwas über 50 Tagen. Finde ich völlig in Ordnung. Bisher habe ich auch noch keine Probleme mit der Stromversorgung oder ähnlichem gehabt. In einigen Berichten habe ich gelesen, dass der Pi beziehungsweise das Netzteil irgendwann aufgeben, wenn er dauerhaft eingeschaltet ist. Glücklicherweise ist mir das bisher noch nicht passiert.

Auch die Integration mit anderen Lösungen gefällt mir gut. Die Kommunikation mit meinem Fernseher klappt gut und Plugins für die Mediathek und Co. sind ebenfalls benutzbar. Was mir fehlt sind Lösungen für Watchever und andere Streaming-Anbieter. Der Grund sind Lizenzprobleme, da der Raspberry Pi lizenzfrei konzipiert wurde. Viele Streaming-Anbieter setzen aber bei ihrer Lösung auf Silverlight, so dass es hier schon zu Problemen kommt. Ich hoffe, hier macht es Netflix, das in Kürze in Deutschland starten soll, anders. Wenn dieser Anbieter, oder irgendwann auch andere, es schafft, den Markt für Lösungen wie den Raspberry Pi zu öffnen, werden sich wohl viele Leute überlegen, ob sie das Angebot nicht mindestens testen. Für mich ist das mittlerweile der Hauptgrund, warum ich noch kein Streaming-Angebot getestet habe. Mein Fernseher unterstützt es leider nicht direkt und ich möchte mir einfach keine Spielekonsole oder ähnliches ins Wohnzimmer stellen, nur um damit einen völlig fremden Dienst nutzen zu können.

Noch habe ich Hoffnung, dass sich das irgendwann realisieren lässt :).

Gesamtfazit

Am 01. September 2014 fing es mit Teil 1 an. Nun ist die Serie zu Ende. Ich bin mit der Lösung zufrieden und wollte die Informationen gerne teilen. Auch wenn ich sicherlich an vielen Stellen etwas vergessen habe, was mir in den nächsten Wochen und Monaten wieder einfällt. Aber dann werde ich die betreffenden Teile einfach aktualisieren und eine Notiz hinterlassen, was sich geändert hat.

Feedback finde ich ja sowieso schon toll. In diesem Fall aber ganz besonders. Wenn jemandem etwas auffällt, was nicht ganz richtig ist oder verbessert werden kann, bitte ich um eine Nachricht oder um einen Kommentar beim betreffenden Teil. Dann versuche ich den Missstand so schnell wie möglich zu korrigieren.

Bis dahin wünsche ich allen “Happy Mediacentering” ;).

ppedv Team Blog: JQuery Mobile mit ASP.NET Intro Video

Auf der #NRWConf hatte ich das Vergnügen einen Vortrag zu mobile Web Apps mit JQM und ASP.NET halten zu dürfen. Morgens beim ersten eMail check, der Schock. Nach Bluescreen bootet mein Fujitsu T904  bzw. Windows 8.1 in den Reparaturscreen. Ein kryptische Meldung, das kein lokaler Admin Account vorhanden ist, verhindert sämtliche Reparatur Optionen. Auch ein Boot von USB ist nicht möglich.

Dank wunderbarer Hilfe von Daniel Fischer, Melanie Eibl und Stefan Lange konnte ich die Session um 14:50 doch noch durchführen. Letztlich dank eines brandneuen Surface Pro 3 time sponsored bei Stefan. Sozusagen Live Test von Tastatur und Device. Wer schon mal Ad Hoc eine andere Umgebung und vor allem anderes Keyboard benutzt hat, kennt die Stolpersteine.

Also aus vier per Facebook angekündigten Slides wurden 0. Beinahe 60 Minuten Live Coding mit Northwind rund um

  • Visual Studio 2013 und ASP.NET Webforms Modelbinding
  • Jquery Mobile Einrichten und Funktion Intro
  • Listen- Relationen, Suchen, nummerisches Paging- Forward Paging
  • Formular- Anzeigen Edit

Die Stimmung im Publikum war großartig. Szenenapplaus, aktives mitgehen- You Rock!

Um allen das Nachlesen, bzw. nachschauen zu ermöglichen share ich hier das Recording, das ich Tage vorher aufgenommen habe, um das Timing der Demos zu testen. (Produktwarnung VB.NET und Webforms Zwinkerndes Smiley)

Übrigens Vimeo weil ohne störende Werbung und fern der Datenkrake Google.

Die NRWConf war ein Superevent, sehr persönlich und engagiert. Danke an Daniel Fischer und Kostja Klein. Es war mir eine Ehre.

Holger Sirtl: Microsoft Azure wächst weiter: SQL Databases, API Management, Media Service, Websites, Rollenbasierte Zugriffskontrolle etc.

Vergangene Woche hat Microsoft weitere Neuerungen in Microsoft Azure veröffentlicht:

  • SQL Databases: Allgemeine Verfügbarkeit (GA) der neuen Leistungsstufen für Azure SQL Database
  • API Management: Allgemeine Verfügbarkeit (GA) des API Management Service
  • Media Services: Live Streaming, Inhaltsschutz, schnelleres und kosteneffektiveres Encoding und Media Indexer
  • Websites: Integration von Virtual Network, neues skalierbares CMS mit WordPress und Aktualisierungen beim Website Backup im Preview Portal
  • Rollenbasierte Zugriffskontrolle: Vorschau für rollenbasierte Zugriffsrechte bei verschiedenen Azure Management Operationen
  • Alerting: Allgemeine Verfügbarkeit (GA) des Alerting Service und neue Alerts für verschiedene Ereignisse

Diese Funktionen sind ab sofort verfügbar (wenngleich einige von ihnen noch in Preview sind).

Neuerungen in Azure SQL Database

In SQL Database haben sich folgende Neuerungen ergeben:

  • Ab sofort stehen die Leistungsstufen Basic, Standard und Premium zur Auswahl.
  • Alle Leistungsstufen haben Verfügbarkeiten laut SLAs von 99,99%.
  • Jede SQL Database hat ein konsistentes, garantiertes Performance-Level. DIe Datenbanken sind derart voneinander isoliert, dass sie sich nicht gegenseitig in der Performance beeinflussen können.
  • Eingebauter Point-in-Time Restore Support, d.h. es wird möglich, Datenbanken auf einen quasi beliebigen Stand aus der Vergangenheit zurückzusetzen.
  • Eingebauter Auditing Support mit dem es möglich ist, Änderungen in der Datenbankänderungen nachzuverfolgen.
  • Eingebaute Aktive Geo-Replikation in der Premium Edition. Dabei können bis zu vier lesbare, sekundäre Datenbanken in jeder Azure Region erstellt werden. Wenn die Aktive Geo-Replikation aktiviert ist, werden die Daten laufend aus der primären in die sekundären Datenbanken übertragen.

Weitere Informationen zu diesen Neuerungen und SQL Database im Allgemeinen gibt es auf folgenden Seiten:

Neuerungen im API Management Service

Im API Management Service haben sich folgende Neuerungen ergeben bzw. stehen ab sofort folgende Funktionalitäten zur Verfügung:

  • Der Azure API Management Service ist ab sofort allgemein verfügbar
  • Mit dem API Management Service können bestehende APIs, die auf Azure oder außerhalb von Azure betrieben werden, effizient verwaltet und Partnern (Kunden, Entwicklern etc.) zugänglich gemacht werden
  • APIs können mit Zugriffsquotas (maximale Zugriffe pro Zeiteinheit) versehen werden
  • Für die Zugriffe können Auswertungen erstellt werden.
  • API-Verfügbarkeiten können überwacht und Fehler schnell erkannt werden
  • Entwicklern können spezielle Portalseiten und darüber Dokumentation und Informationen zum Aufruf bereitgestellt werden

Weitere Informationen zu diesen Neuerungen und API Management im Allgemeinen gibt es auf folgenden Seiten:

Neuerungen bei den Media Services

Lange erwartet, nun ist er da: der Live Streaming Support (Public Preview). Diese und weitere Neuerungen bei den Media Services:

  • Live Streaming Unterstützung, die bereits bei der Fußball-Weltmeisterschaft weiteren sportlichen Großereignissen eingesetzt wurde.
  • DRM Schutz von Inhalten mit PlayReady und AES 128-Bit Verschlüsselung.
  • Schnelleres und kostengünstigeres Encoding, für dessen Kosten nur die Menge an Ausgabedaten ausschlaggebend ist. Über die Leistungsstufen Basic, Standard und Premium kann die Codierleistung bedarfsabhängig gesteuert werden.
  • Weitere Medienpartner: Telestream’s Wirecast, Newtek’s Tricaster, Cires21 und JW Player.

Weitere Informationen zu diesen Neuerungen und Media Services im Allgemeinen gibt es auf folgenden Seiten:

Neuerungen bei Websites

Die Websites werden weiter ausgebaut. Folgende Neuerungen wurden bekanntgegeben:

  • Integrationsmöglichkeit mit Virtual Network. Damit wird es beispielsweise möglich, von einer Website aus eine nicht-öffentliche SQL Datenbank in einer Virtual Machine einzubinden oder On-Premises-Ressourcen sicher und geschützt zu integrieren.
  • Unterstützung für eine skalierbare Wordpress Konfiguration zur schnellen Bereitstellung vorkonfigurierter Wordpress-Installationen.
  • Verbesserungen beim Website Backup: jetzt können die Zielspeicher für die Backups und beim Restore neben neuen Website-Slots auch bestehende Deployment-Slots konfiguriert werden.

Weitere Informationen zu diesen Neuerungen und Websites im Allgemeinen gibt es auf folgenden Seiten:

Rollenbasierte Zugriffskontrolle für administrative Aufgaben

Bisher war es möglich, andere Personen zu Co-Administratoren in einer Subscription zu ernennen. Damit hatten diese Personen fast die gleichen Rechte wie der Beitzer der Subscription (ohne Einschränkung auf bestimmte Elemente der Subscription). Jetzt können Rechte deutlich feingranularer vergeben werden:

  • Erteilung von Rechten für Resource Groups oder einzelne Ressourcen wie Websites oder VMs.
  • Rollenbasierte Zugriffskontrolle ist in Azure Active Directory integriert, so dass Rechte für User und User Groups erteilt werden können.
  • Rollenberechtigungen können in den Stufen Owner, Contributor und Reader vergeben werden.

Weitere Informationen zur rollenbasierten Zugriffskontrolle:

Neuerungen bei Alerts

Folgende Neuerungen gibt es zu Alerts zu vermelden:

  • Die Alerts sind ab sofort allgemein verfügbar.
  • Die Grenze von zehn Alerts pro Subscription wurde entfernt.
  • Alerts können jetzt auch für betriebsbezogene Ereignisse (z.B. Start/Stop einer Website) eingerichtet werden.
  • Alerts können an die Administratoren oder eine beliebige andere E-Mail-Adresse verschickt werden.

Weitere Informationen zu Azure Alerts:

Code-Inside Blog: How we moved from Wordpress to Jekyll - on Windows

As I told you in an older post we moved successfully (more or less…) from Wordpress to Jekyll. And we did this with our Windows Machines. I will explain very shortly how we did this migration and how we got Jekyll run on Windows.

1. Install a comment system like Disqus and Migrate the existing Comments

Jekyll is a static page generator and … well… its static. No “dynamic” content here. Therefor comments needs to be outsourced, because this is something “dynamic”. A popular service for comments is Disqus. Install Disquis in your Wordpress Installation and make sure all comments are visible on your blog. Disqus offers a Wordpress Plugin (which was kinda buggy) and can import comments via the Export XML (see step 2).

2. Export Wordpress Pages/Posts/Comments

Go in your Wordpress Administration and Export everything via “Tools” - “Export”. This generates a Wordpress Export XML.

3. Backup all Images/Assets/Media Files from your Wordpress Installation

The Wordpress Export will only contain non-binary data. In order to save images and other uploads copy everything under wp-uploads to your machine.

4. Convert Pages and Posts to Markdown via wpXml2Jekyll

I used wpXml2Jekyll to convert the Wordpress Export to Markdown. There are some other tools out there, but this one is very easy and does its job. If you know C# (or want to learn it) you can look at the source code and enhance it. The result should contain Posts and Pages as Markdown.

5. Finetuning - Search & Replace in the Markdown files.

Notepad++ was a big help in this step. I removed some old domain references in the Markdown files and some “invalid” characters from the export. Might not be needed, but keep in mind: You now have a bunch of text files, which are very easy to edit.

6. Install Jekyll - on Windows.

Now it’s time to run Jeykll. It should be much easier on Linux or Mac, but I use Windows and this is the best description I found on the Web: Run Jekyll on Windows Make sure you follow each step. You will need Ruby, Ruby Dev Kit, Ruby Gems, Jekyll and Phyton - and make sure Ruby and Phyton are in the PATH Variable. This was a major pain point for me - but trust me: It works.

7. Running Jekyll with Content

Now you should move the Pages/Posts to Jekyll and put the copied media files somewhere. Our Blog-Repository contains the Markdown & Media Files. In this step you should test your site and see if everything is served as expected.

8. Make it Awesome

As you can see - we are still working on this, but now our Blog is powered by Jekyll and saved on GitHub - which is super awesome.

Summary

The steps are not hard, but we needed some time to do this migration and we have still room for improvements. Biggest issue was to get Jekyll running on Windows. Hope this might help you when you migrate your Blog from Wordpress to Jekyll.

Hendrik Lösch: Handgefertigtes Bootstrapping & View Handling in WPF

Ich wurde per Twitter gefragt ob ich mir nicht ein wenig Quellcode einer WPF Applikation ansehen könnte um diverse Tipps zu dessen Verbesserung zu äußern. Statt aber nur aufzuzeigen was mir daran nicht gefällt, habe ich mich daran gemacht zu beschreiben welchen anderen Weg man gehen kann um mehrere Ansichten innerhalb einer WPF Anwendung zu […]

codefest.at [MS]: SQL Server 2014, 2012 und 2008 Performance Monitoring & Tuning Hands-on Workshop vom 26.-28. November 2014 in Wien

Achtung, alle Datenbank ExpertInnen: Wie in den vergangenen Jahren findet auch heuer wieder ein SQL Server Performance Tuning Workshop mit Ramesh Meyyappan in Wien statt!

Der Trainer Ramesh Meyyappan ist ausgewiesener SQL Experte. Als ehemaliger Program Manager im Microsoft SQL Server Development Team hat Ramesh mehr als 15 Jahre Erfahrung mit SQL Server Performance Monitoring, Tuning und Troubleshooting.

Die Ziele:

“To provide participants with knowledge on how to monitor and tune performance of Microsoft SQL Server 2014, 2012 and 2008. The course addresses CPU, Memory, Disk, Query and Lock monitoring and tuning techniques for optimal performance and to maximize the utilization of existing hardware. Best practice guidelines for configuration and maintenance are covered. After the workshop, the attendees should be able to identify and tune performance issues.”

Die Agenda:

  • Analyzing current activity and performance bottlenecks of SQL Server in a Production environment
  • Monitoring and Tuning CPU Utilization
  • Monitoring and Tuning Disk I/O and Database Files
  • Monitoring and Tuning Memory Utilization
  • Monitoring and Tuning Query Optimization and Query Execution
  • Monitoring and Tuning Locks, Deadlocks and other Concurrency Issues
  • Monitoring and Tuning In-Memory OLTP and Clustered Columnstore Indexes
  • Monitoring and Tuning AlwaysOn Availability Groups, Database Mirroring, Backup Compression and Database Encryption

Die Voraussetzungen:

Der Workshop findet in englischer Sprache statt, Wissen über Clustering, Heap und Non-cluster-Indexing, Database Engine, Tuning Wizard und SQL Profiler ist Voraussetzung.

Termin: 26.-28. November 2014

Ort: Wien

Die Kosten für den 3-Tages-Workshop betragen Euro 2.100,- exkl. USt.
Early Bird Discount bis 14. Oktober 2014: Euro 150,-

Zur Anmeldung…
Die Teilnehmeranzahl ist auf 12 begrenzt.

Feedback von Seminarteilnehmern…

Viel Spaß!

ppedv Team Blog: Windows 8/8.1: Fritz!fax installieren

Nicht nur im privaten Bereich, sondern auch in vielen kleinen Unternehmen im Einsatz: eine Fritz!Box mit Telefonfunktion (z.B. Fritz!Box 7390). Der Hersteller AVM stellt für diese Modelle die Software Fritz!fax kostenlos zur Verfügung. Diese ermöglicht das einfache Faxen auf einem Computer in Form von Druckertreibern.

Die aktuelle Version von Fritz!fax hat die Versionsnummer 03.07.04 und ist laut Hersteller mit 32bit- und 64bit-Versionen von Windows XP, Windows Vista und Windows 7 kompatibel. Windows 8 bzw. Windows 8.1 ist nicht aufgeführt – die Installation unter diesen Windows-Versionen bereitet auch in der Tat Probleme! Mit einigen Einstellungen, die man vor der Installation vornehmen muss, steht jedoch der Installation und der Betrieb von Fritz!fax unter Windows 8/8.1 nichts im Wege:

1. CAPI over TCP aktivieren
Damit vom Computer aus gefaxt werden kann, muss die Funktion “CAPI over TCP” in der Fritz!Box aktiviert sein. Hierfür einfach ein Telefon (analog oder ISDN) an die Fritz!Box anschließen und die Tastenfolge #96*3* eingeben und auflegen. Dadurch wird die Funktion aktiviert. (Falls die Funktion schon aktiviert ist und es Probleme beim Faxen gibt die Funktion einmal  mit der Tastenfolge #96*2* deaktivieren und danach wieder aktivieren).

2. Benutzerkontensteuerung (vorübergehend) deaktivieren
Unter der Systemsteuerung (“System und Sicherheit” –> “Einstellungen der Benutzerkontensteuerung ändern”) kann die Benutzerkontensteuerung deaktiviert werden, in dem man den Schieberegler auf die unterste Position stellt (nach der Installation von Fritz!fax wieder zurückstellen!)

Einstellungen für Benutzerkontensteuerung

3. Kompatibilitätsmodus aktivieren
In den Eigenschaften der heruntergeladenen Setup-Datei von Fritz!fax (Rechts-Klick auf FRITZ!fax_3.07.04.exe –> Eigenschaften;  Registrierkarte “Kompatibilität”) vor “Programm im Kompatibilitätsmodus ausführen von” den Haken aktivieren und als Windows Version “Windows 7” auswählen. Hinzu kommt die Einstellung “Programm als Administrator ausführen”, die in dem Eigenschaften-Fenster etwas weiter unten zu finden ist.

Eigenschaften von FRITZ!fax_3.07.04.exe

4. Installation von Fritz!fax starten
Jetzt kann das Setup-Programm von Fritz!fax gestartet werden.

Setup

Man sollte hier jedoch etwas Geduld mitbringen. Da Fenster mit der Prozent-Anzeige bleibt für eine kurze Zeit bei 99% stehen. Danach verschwindet dieses und es kann dann paar Minuten dauern, bis das eigentliche Setup-Programm zu sehen ist!

Setup2

Je nach aktiver Firewall können Nachfragen bzgl. einer Port-Aktivierung erscheinen, die dann auch genehmigt werden sollten, damit das Setup-Programm mit der Fritz!Box kommunizieren kann.

5. Fertig!
Nach der Installation sollten sich unter “Geräte und Drucker” (Systemsteuerung –> “Hardware und Sound”) die Drucker “FRITZfax” und “FRITZfax Color” befinden und können ab sofort verwendet werden.

codefest.at [MS]: OpenSource Windows Phone 8.1 Apps (WinRT)

Christoph Wille hat bereits seine App Vienna Realtime für Entwickler auf GitHub zur Verfügung gestellt. Nun sind zwei weitere Apps erschienen: Sprudelsuche und OzonWerte, damit man über die Spritpreise und Ozonwerte in Österreich immer bestens informiert ist.

image image

Beide Apps gibt es bereits als Windows Store App. Nun hat Christoph Wille eine Windows Phone 8.1 (WinRT) dafür geschrieben. Falls ihr gerne an bestehenden Apps lernt, so könnt ihr Euch den Source Code auf Github für die Sprudelsuche und die Ozonwerte herunterladen. Die Apps gibt es natürlich auch im Store hier und hier.

ppedv Team Blog: Umstellung auf Windows Phone 8.1, Screenshots und Facebook

 

Windows Phone 8.1 ist nun für die meisten Handytypen verfügbar, ein Feature das im Kontext der Umstellung aber vielleicht nicht jedem bekannt und trotzdem nützlich ist, ist die schnelle Erstellung von Screenshots. Durch Druck auf die Lauter- und Powertaste (vormals Home- und Powertaste) gleichzeitig wird das analoge Notieren von Fehlermeldungen überflüssig. Wer sich nicht sicher ist ob er schon Windows Phone 8.1 nutzt, schaut einfach hier: Einstellungen –> Info

image

Versionen 8.0.0xxx Windows 8
Versionen 8.0.1xxx Windows 8.1

Warnung: Die Smartphones von Nutzern, welche die Developers Preview App für Windows 8.1 verwendeten, meldeten vermehrt komplett unbrauchbare Smartphones, welche erst wieder mit dem Nokia Recovery Tool zurückgesetzt werden mussten. Das ging mit Datenverlust einher. 

Wer bisher schon Facebook auf seinem Smartphone installiert hatte, wird nach der Umstellung eventuell den folgenden Effekt erleben:                                                                                                                                                                                                                                                                                                                                       

Facebookbugedited

Bei der Umstellung kann es dazu kommen, dass die Verkettung von Kontakten auf dem Handy gelöst wird.
Um wieder wie gewohnt die Facebook Kontakte im Chatverlauf angezeigt zu bekommen und aus dem Chat heraus zu schreiben bedarf es in der Regel drei einfacher Schritte.

1. Handy neu starten.

2. Per Browser auf Facebook einloggen und etwaigen Nachfragen zur Verknüpfung von Kontakten zustimmen.

3. Handy noch einmal neu starten.

Fabian Deitelhoff: Teil 6 – Raspberry Pi als Mediacenter mit Raspbmc (Tipps & Tricks)

Teil 6 - Raspberry Pi als Mediacenter mit Raspbmc (Tipps & Tricks)Nach der ganzen Installation und Konfiguration der letzten Teile geht es nun, im sechsten Teil der Serie, um ein paar Tipps & Tricks.

Auch diese Tipps & Tricks sind eher optional. Kommt immer darauf an, was mit dem Mediacenter geplant ist. Wie schon im letzten Teil zur Performance ist es aber durchaus sinnvoll und nützlich, einmal darüber nachzudenken, ob die hier vorgestellten Optionen für das eigene Mediacenter nützlich sind.

Der Beitrag geht auf das Senden von Kommandos über SSH ein und zeigt, was für die Wiedergabe von MPEG-2- und VC-1-Videos eingerichtet werden muss. Für mich waren diese Formate über ein Jahr lang kein Thema, da ich mir nur HD-Videos im mkv-Format ansehe. Viele selbst erstellten Videos, beispielsweise vom letzten Urlaub oder einer Hochzeit, sind aber als MPEG-2 oder VC-1 kodiert.

Zusätzlich verweise ich noch auf die Wiki-Seite zu Tastaturbefehlen. Diese sind häufig recht nützlich, insbesondere wenn das Mediacenter noch konfiguriert wird. Hinterher eher weniger. Zumindest nutze ich nur noch selten diese Befehle.

Dieser Blogpost ist Teil einer Serie zum Thema “Raspberry Pi als Mediacenter mit Raspbmc”. Im Rahmen dieser Serie sind die folgenden Teile erschienen. Der jeweils aktuelle Beitrag ist hervorgehoben.

  1. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Hardware)
  2. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Software)
  3. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration I)
  4. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration II)
  5. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Performance)
  6. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Tipps & Tricks)
  7. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Gesamtfazit)

Tipps & Tricks

Mittlerweile ist das Mediacenter also einsatzbereit. Die Hardware ist vorhanden, die Software installiert sowie konfiguriert und auch das ein oder andere Problem mit der Performance ist gelöst beziehungsweise hoffentlich gar nicht erst aufgekommen. Jetzt geht es noch um ein paar Tipps & Tricks, die hilfreich sein können.

Senden von Kommandos

Raspbmc kennt viele Kommandos, die über Tastatur, Maus und Fernbedienung empfangen werden können. Hin und wieder ist es aber auch von Vorteil, diese Kommandos von einem entfernten Rechner zu senden. Ein Beispiel ist die Screenshot-Funktion, mit der ich die meisten Abbildungen aus den Blogposts erstellt habe.

Zunächst brauchen wir dafür aber ein kleines Softwarepaket. Das lässt sich einfach über das folgende Kommando installieren:

sudo apt-get install xbmc-eventclients-xbmc-send

Nachdem apt-get das Paket installiert hat, eventuell fehlen noch einige Abhängigkeiten, die zusätzlich installiert werden, ist es auch schon möglich, Kommandos zu senden. Eine weitergehende Konfiguration ist nicht möglich. Sind wir über SSH eingeloggt, kann beispielsweise der folgende Befehl abgesetzt werden:

xbmc-send --action="UpdateLibrary(video)"

Der erste Teil, genauer gesagt xbmc-send, ist das eigentliche Kommando. Der Parameter –action nimmt die Aktion entgegen, die in dem Beispiel oben dafür sorgt, dass die Film-Bibliothek aktualisiert wird. Dass funktioniert auch, um einen Screenshot zu erstellen, womit wir wieder beim Beispiel vom Anfang dieses Kapitels sind. Der Befehl dazu lautet TakeScreenshot:

xbmc-send --action="TakeScreenshot"

Von diesen Kommandos gibt es eine ganze Reihe. Eine gute Übersicht mit Namen “List of built-in functions” gibt es im Wiki zu XMBC.

MPEG-2 und VC-1 Codes

Ein Grund für mich, mir ein Mediacenter mit Raspbmc und dem Raspberry Pi zu bauen, war die Idee, weg von Datenträgern zu kommen. Darauf hatte ich einfach keine Lust mehr. Damit einher ging auch der Wunsch, sämtliche Medien abspielen zu können, also völlig unabhängig vom Datenformat zu sein um – im schlimmsten Fall – nicht noch verschiedene Geräte vorhalten zu müssen.

Dafür ist der Raspberry Pi grundsätzlich sehr gut geeignet. Raspbmc kann alles abspielen was vorstellbar ist. Dass gilt allerdings nur für Formate, die frei von Lizenzen sind. Hintergrund ist, dass der Raspberry Pi für den Bildungsbereich entwickelt wurde. Er sollte demnach so günstig wie möglich sein, was bei hohen Lizenzkosten nicht der Fall ist. Daher fehlen die Codecs für MPEG-2- und VC-1-Videos. Gerade ersteres kommt oft bei Smartphones und sonstigen Aufnahmegeräten aus dem Heimbereich zum Einsatz.

Glücklicherweise ist es überhaupt kein Problem, diese beiden Codecs nachzuinstallieren. Die beiden dafür notwendigen Lizenzschlüssel können im Raspberry Pi Webshop erworben werden und sind mit unter fünf Euro für beide Codecs auch absolut erschwinglich. Für den Kauf der Lizenzen brauchen wir zunächst die Seriennummer des Raspberry Pi, denn die Lizenzen werden an diese Seriennummer gebunden. Diese Nummer steht, soweit ich weiß zumindest, nicht irgendwo auf der Platine. Allerdings ist es auch ganz einfach, sie über die Kommandozeile zu bekommen. Einfach mittels SSH zum Raspberry Pi verbinden und folgendes Kommando ausführen:

cat /proc/cpuinfo

Die Ausgabe sieht dann wie folgt aus. Bitte beachtet, dass die Striche in der letzten Zeile, in der die Seriennummer steht, von mir eingefügt wurden. Dort steht eine Buchstaben- und Zahlenkombination.

pi@raspbmc:~$ cat /proc/cpuinfo
processor       : 0
model name      : ARMv6-compatible processor rev 7 (v6l)
Features        : swp half thumb fastmult vfp edsp java tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xb76
CPU revision    : 7

Hardware        : BCM2708
Revision        : 000d
Serial          : 00000000--------

In der letzten Zeile steht die 16-stellige Seriennummer. Bitte notieren und den Webshop der Raspberry Pi Foundation besuchen. Dort gibt es die MPEG-2 und VC-1 Lizenzschlüssel. Hintergrund ist, dass die Seriennummern an das jeweilige Raspberry Pi-Board gebunden sind. Wer mehrere Raspberry Pis mit den Codes ausstatten möchte, muss die Codes auch mehrfach kaufen.

Beim Kauf einfach die Seriennummer des Raspberry Pi eingeben und mit PayPal bezahlen. Eine andere Möglichkeit für den Bezahlvorgang ist leider nicht vorhanden, soweit ich weiß. Auf der Webseite sind zwar bis zu 72 Stunden für die Lieferung der Lizenzschlüssel angegeben, ich habe meine aber schon nach circa vier Stunden per E-Mail erhalten. Diese E-Mail hat – unter anderem – den folgenden Inhalt:

Thank you for purchasing codec license keys from the Raspberry Pi Store.To enable codecs on your device(s), add the following lines to the config.txt file in the FAT partition of your SD card:

decode_MPG2=———-
decode_WVC1=———-

Auch hier habe ich den wichtigen Inhalt wieder entfernt und gegen Striche ausgetauscht. An Stelle der Striche stehen normalerweise die 10-Zeichen langen Lizenzschlüssel. Auch diese sind alphanumerisch, enthalten also Buchstaben und Zahlen. Diese Lizenzen müssen wir jetzt nur noch installieren. Dazu gibt es einen manuellen und einen komfortableren Weg. Ich beschreibe hier letzteren, da die Raspbmc-Installation sowieso zur Verfügung steht und wir dann auch Gebrauch der Einstellmöglichkeit machen können.

Im Menüpunkt Programme | Raspbmc Settings gibt es einen Bereich zur Systemkonfiguration, wie Abbildung 1 zeigt. Hier können wir die beiden Lizenzschlüssel eingeben. Mehr oder weniger komfortabel, je nachdem, ob wir die Fernbedienung, eine Tastatur und das konfigurierte Tablet nutzen. Die beiden letzteren Möglichkeiten sind deutlich komfortabler. Nach der Eingabe möchte der Raspberry Pi nur einen Neustart von uns und die Lizenzschlüssel sind installiert. Auch im Bild sind die beiden Lizenzschlüssel wieder entfernt. Sie kommen in die beiden Felder, die mit einer 0x belegt sind. Der Rest ist geschwärzt.

Abb. 1: Raspbmc Konfiguration zur Aktivierung der Codes MPEG-2 und VC-1.

Abb. 1: Raspbmc Konfiguration zur Aktivierung der Codes MPEG-2 und VC-1.

Für den Test brauchen wir noch mal eine SSH-Verbindung. Nach der erfolgreichen Verbindung zum Raspberry Pi bitte die beiden Kommandos eingeben:

vcgencmd codec_enabled MPG2
vcgencmd codec_enabled WVC1

In beiden Fällen sollte ein enabled zurückkommen, was bedeutet, dass beide Codecs aktiv sind. Jetzt sind auch MPEG-2- und VC-1-Videos kein Problem mehr.

Tastaturbefehle

Zum Schluss dieses Teils noch ein kleiner Hinweis auf die Tastaturbefehle. Diese vereinfachen die Bedienung des Mediacenters in vielen Situationen erheblich. Insbesondere bei angeschlossener Tastatur fand ich es wichtig zu wissen, wie ich ein Kontextmenü öffnen kann oder auch für die ganzen Screenshots, die in dieser Blogserie zum Einsatz kamen.

Ich möchte gar nicht groß die möglichen Tastaturbefehle aufzählen, denn es gibt eine ganze Menge davon. Im XBMC-Wiki gibt es eine spezielle Seite dazu, auf die ich gerne verweisen möchte. Dort sind auch die Unterschiede beschrieben, in denen ein Befehl eine jeweils andere Aktion ausführt. Beispielsweise Global und wenn ein Video abgespielt wird.

Zwischenfazit

Diese Blogserie zum Raspberry Pi als Mediacenter nähert sich dem Ende. Wir sind schon am Ende des 6. Teils angekommen. Wer die in der Serie enthaltenen Posts als Anleitung genutzt hat, sollte schon ein gut funktionierendes Mediacenter zur Verfügung haben. Kleinigkeiten, die eingestellt werden können, gibt es natürlich immer. So auch hier. Die oben genannten Tipps & Tricks sind lediglich in kleiner Ausschnitt des möglichen.

Im nächsten und gleichzeitig letzten Teil geht es dann um ein abschließend Gesamtfazit, einen kleinen Blick über den Tellerrand, sowie um eine Bewertung der Lösung aus meiner persönlichen Sicht.

ppedv Team Blog: Sichern des EFS-Verschlüsselungszertifikats

Sobald Sie eine Datei oder einen kompletten Ordner erstmals mit EFS verschlüsseln, erzeugt Windows ein entsprechendes Zertifikat für das betreffende Benutzerkonto. Dieses Zertifikat ist nur für das jeweilige Benutzerkonto unter dem aktuellen Kennwort des Benutzers gültig. Um einen Verlust der Informationen zu verhindern, fordert Windows nach dem Verschlüsseln den Benutzer zur Sicherung des Zertifikats auf.

Um das zum Verschlüsseln benötigte Zertifikat auf einem (externen) Datenträger zu sichern, gehen Sie in folgenden Schritten vor:

  1. Rufen Sie gegebenenfalls das Dialogfeld Verschlüsselndes Dateisystem auf und wählen Sie den Befehl Jetzt sichern (empfohlen).

    http://www.winhelpline.info/forum/attachments/allgemein-windows-vista/10248d1182973464-schluessel-fuer-dateiverschluesselung-sichern-meldung.png
  2. Sobald das Willkommen-Dialogfeld des Zertifikatexport-Assistenten erscheint, klicken Sie auf die Weiter-Schaltfläche. Wählen Sie im Folgedialogfeld die Optionen des zu exportierenden Zertifikats aus. Welche Optionen freigegeben werden, hängt von der Systemumgebung ab.

  3. Tippen Sie im Dialogfeld Kennwort in das Kennwort-Feld sowie in das Bestätigungsfeld jeweils ein Kennwort ein. Dieses Kennwort dient zum Zugriff auf das Zertifikat und stellt einen gewissen Schutz dar, falls die gesicherte Zertifikatdatei in falsche Hände gerät. Ohne das Kennwort lässt sich mit dem Zertifikat nichts anfangen.

  4. Im Dialogfeld Dateiname wählen Sie über die Schaltfläche Durchsuchen einen Exportpfad und legen den Namen der Sicherungsdatei fest.

  5. Im letzten Dialogschritt werden Ihnen nochmals die Exportoptionen angezeigt. Klicken Sie auf die Fertig stellen-Schaltfläche, um den Vorgang abzuschließen.

 

Der Assistent wird geschlossen und der Export beginnt. Sobald Sie das Dialogfeld mit dem Hinweis auf den erfolgreichen Abschluss des Exports über die OK-Schaltfläche beenden, liegt auf dem Zielmedium eine Exportdatei vor. Fertigen Sie sich gegebenenfalls Sicherungskopien auf einem Wechseldatenträger an und bewahren Sie diese an einem sicheren Ort auf.

Sven Hubert: Automatisches Anlegen von Buildprozessen für Feature Branches

TFS Funktionen vereinfacht und erweitert mit dem TFS ASAP

Zur Entkopplung einer Implementierung von voneinander unabhängigen Komponenten und deren Anforderungen bietet sich der Einsatz von Feature Branches an. Erst nachdem auf diesen eine gewisse Stabilität erreicht ist werden die Quellcodeänderungen in den Main Branch übertragen.

Das Anlegen eines Feature Branches ist unkompliziert und abhängig von der Menge des Quellcodes in der Regel nur eine Sache von Sekunden.

Zur Überprüfung der Quellcodequalität hinsichtlich Kompilierbarkeit, Lauffähigkeit von Tests und der Einhaltung der Code Analyse Regeln ist es sinnvoll einen zusätzlichen kontinuierlichen Buildprozess für den Branch einzurichten. Dieser führt nach jedem Eincheckvorgang automatisch eine Qualitätskontrolle durch. Die Einrichtung dessen benötigt schon ein paar Minuten – zumindest ohne den TFS ASAP.

Für das Anlegen des Prozesses bietet sich das Klonen eines Bestehenden an. Hierzu sind entsprechende Rechte notwendig.

clip_image002

Im Anschluss müssen eine Reihe von Einstellungen angepasst werden. Hierzu gehören unter anderem folgende:

- Name (entsprechend den Konventionen)

- Trigger (Rolling builds)

- Source Settings

- Projekte, die kompiliert werden sollen

- Test Categories, Symbol Server Settings, Retention Policy, …

Schnell werden hierbei einzelne Parameter vergessen. Der erste Build eines neuen Feature Branches geht deshalb quasi immer schief.

Dieser etwas komplizierte und vor allem fehleranfällige Schritt kann durch den Einsatz der TFS Automated Servicing & Administration Platform automatisiert werden.

Hierzu wird in das Verzeichnis unterhalb dessen die Feature Branches erstellt werden eine Konfigurationsdatei eingecheckt.

In dieser werden das zu verwendende Template sowie abweichende Einstellungen definiert.

Für alle Branches, die im Anschluss unterhalb des Verzeichnisses angelegt werden, wird automatisch serverseitig im Hintergrund ein passender Buildprozess eingerichtet. Damit ist das Anlegen eines Feature Branches mit zugehörigem Buildprozess genauso schnell und einfach wie das bisherige Anlegen eines Branches ohne einen Buildprozess der fortlaufend die Qualität überprüft.

Darüber hinaus wird die Builddefinition erzeugt auch wenn der Benutzer nicht über die notwendigen Rechte verfügt. Eine Aufweichung des Rechtekonzeptes wird hierdurch vermieden.

Eine kleine TFS Erweiterung durch den TFS ASAP mit großer Wirkung!

Automatisches Anlegen von Buildprozessen für Feature Branches is a post from: AIT Blog

codefest.at [MS]: SignalR und Unity in euren Multiplayer-Indie-Games

Ihr, als .Net-Entwickler, kennt SignalR möglicherweise bereits als Microsoft-Programmierbibliothek um Nachrichten in Echtzeit zu verschiedenen Clients zu übertragen. Das klingt zuerst einmal schwierig, ist es in Wirklichkeit aber nicht.

Grübelt ihr noch über ein Einsatzszenario? Nun, wie wäre es mit einem großen Monitor, oder Fernseher für euer Support-Team? Auf diesem wird der aktuelle Status von verschiedenen System angezeigt. Sollte eines der Systeme etwas Ungewöhnliches entdecken, dann schickt es zum SignalR-Hub eine Meldung. Alle angeschlossenen Clients erhalten diese Meldung umgehend und können dementsprechend reagieren.
clip_image002

Ich hoffe, ihr seid ein wenig neugierig geworden und wollt jetzt wissen, wie das genau funktioniert? Nun das hat mir mein Blogger-Kollege Toni Pohl schon hier in diesem Blog-Eintrag von letztem Jahr abgenommen. Ich empfehle euch diesen Eintrag zu lesen, dann können wir anschließend an dieser Stelle weiter machen.

Unity und SignalR

Ich möchte euch zeigen, wie man Unity mit SignalR verwenden kann. Für Multi-Player-Games bietet es sich ja geradezu an. Mit einer eventuell bereits vorhandenen Azure-Subscription habt ihr noch dazu alles, was ihr als Infrastruktur in Produktion benötigt. Dazu aber möglicherweise ein anderes Mal mehr. Ich würde gerne mit euch gemeinsam einen Teaser für ein Spiel schreiben. Die heutige Funktionalität ist recht einfach zusammengefasst:

· Unity als Entwicklungstool.
· Ein witziger Hintergrund.
· Ein Sprite (in diesem Fall eine geöffnete Hand), welches sich mit der Maus bewegen lässt.
· Wenn die linke Maustaste gedrückt wird, dann soll eine Faust gebildet werden, also in etwa so, als würde man nach einem Objekt greifen.
· Ein Web-Client, der den gleichen Hintergrund verwendet.
· Ebenfalls die geöffnete Hand, sowie die geschlossene Hand.
· Wenn das Unity-Spiel startet, dann soll sich auf der Webseite die Hand genauso bewegen, wie in dem Unity-Client.
· Wird im Unity-Spiel die Maustaste gedrückt, dann wird die Hand zu einer Faust, das soll der Web-Client widerspiegeln.

Lange Rede, kurzer Sinn, das soll so funktionieren, wie ich es hier auf youtube kurz vorzeige.
Was benötigt ihr dazu? Ich nehme an, wenn ihr diesem Blog folgt, dann habt ihr das schon installiert:

· Unity, die Testversion von http://unity3d.com/ reicht vollkommen.
· Visual Studio 2013, wenn ihr die Visual Studio Integration mit Unity verwenden wollt.
· Visual Studio Tools für Unity von hier: http://unityvs.com/ diese bitte herunterladen und installieren.

Für die ganz Ungeduldigen unter euch, den Source Code gibt es wieder hier zum Download.

Spiele-Sprites

Für den Spiel-Teaser selbst benötigen wir noch ein Hintergrund-Bild, dieses findet ihr als .psd-Datei hier, hat die Größe von 800x500 Pixel und sieht so aus:

clip_image004

Damit wir auch etwas Bewegung in die Sache bringen - die beiden Bilder für die sich bewegende Hand:

clip_image005 clip_image006

Das war es bereits, es kann also losgehen mit dem Unity-Client.

Ein kleiner Hinweis noch, solltet ihr noch nie mit Unity gearbeitet haben, dann lege ich euch meinen letzten Blog-Eintrag ans Herz, da werden einige der Schritte, die ich hier nur kurz anreiße – vor allem beim Anlegen des Projektes – genauer beschrieben. Diesen findet ihr hier.

Der Unity Client Teil 1 – noch ohne SignalR

Im ersten Teil wollen wir den Unity-Client so weit bringen, dass die Hand mit der Maus bewegt werden kann und beim Klicken der Maus sich die Hand schließt und auch wieder öffnet. Im Unity-Client müssen wir somit folgendes tun:

· Ein neues 2D-Unity-Projekt erstellen.
· Den Hintergrund und die Hand in die Spielszene einfügen.
· Ein „wenig“ Physik für die Hand hinzufügen.
· Ein Script erstellen, damit die Hand bewegt werden kann.
· Wenn die Maus gedrückt wird, schließt sich die Hand und öffnet sich wieder, wenn die Maustaste losgelassen wird.

Ein neues 2D-Unity-Projekt erstellen

Im geöffneten Unity erstelle ich ein neues 2D-Projekt und gebe diesem den Namen SignalRUnitySample.

clip_image007

Eine gewisse Ordnerstruktur in Unity ist immer eine gute Sache, um die Dateien nicht irgendwie herumfliegen zu lassen. Das sollte ungefähr so aussehen:

clip_image008

Ich habe auch gleich die drei Bilder in den Ordner Textures mit Drag & Drop hineingezogen.

Den Hintergrund und die Hand in die Spielszene einfügen

Dazu ziehen wir den Hintergrund aus dem Assets\Textures-Folder auf die Main Camera in der Hierarchy-Ansicht. Danach holen wir aus dem Assets\Textures-Folder den Sprite mit dem Namen OpenHand als eigenständiges Objekt – ich habe dieses dann umbenannt auf Player.

clip_image009

Ich habe die Anzeigegröße in Unity noch angepasst, um das Resultat mit dem im Browser besser vergleichen zu können. Dazu klickt ihr in Unity auf Game und in der DropDown fügt ihr mittels Add eine neue Auflösung mit 800x500 Pixel ein.

clip_image010

Danach skaliert ihr noch den Hintergrund und die Hand, dementsprechend. D. h. den Hintergrund skaliert ihr auf der X- und Y-Achse 2 mal. Das macht ihr auch mit dem Player-Objekt (der Hand). Des Weiteren sollte die Hand im aktuellen Layer weiter vorne liegen (Wert 1), damit wir diese auch sehen und diese nicht hinter dem Hintergrund gezeichnet wird.

clip_image012 clip_image014

Jetzt sollte noch etwas Bewegung in die Sache kommen.

Physik und Skript für das Player-Objekt

Wie schon bei dem PhoneCatcher-Spiel das letzte Mal, benötigt unser Player-Objekt einen RigidBody 2D, an dem aber „Is Kinematic“ gesetzt wird, um die Schwerkraft abzuschalten. Die Spieler-Hand wird ja mit der Maus, durch den Spieler selbst, bewegt. Dieser wird mit dem Add Component-Button hinzugefügt (an dem Player Objekt).

clip_image016 clip_image017

Jetzt noch ein Skript mit dem Namen PlayerController, wiederum mit dem Add Component an dem Player Objekt. Falls ihr das alles richtig gemacht habt, dann sieht das im Inspector bisher so aus:

clip_image018

Das Skript ist bisher ebenfalls keine große Überraschung, da es sich an dem vom letzten Mal orientiert. Wir benötigen die Grenzen des Spielfeldes, damit die Hand nicht darüber hinaus bewegt werden kann. Zusätzlich muss das Spieler-Sprite ausgetauscht werden, wenn die Maustaste gedrückt wird – und wieder zurückgesetzt werden, damit wieder die geöffnete Hand sichtbar ist, wenn die Maus losgelassen wird.

using UnityEngine;
public class PlayerController : MonoBehaviour { 
    public Camera cam;
    private float maxWidth;
    private float maxHeight;
 
    bool isHandOpen = true;
    public Sprite clickedSprite;
    private Sprite standardSprite;
 
    void Start()
    {
        if (cam == null)
            cam = Camera.main;
        var corner = new Vector3(Screen.width, Screen.height, 0f);
        var targetWidth = cam.ScreenToWorldPoint(corner);
        float playerWidth = renderer.bounds.extents.x;
        float playerHeight = renderer.bounds.extents.y;
        maxWidth = targetWidth.x - playerWidth;
        maxHeight = targetWidth.y - playerHeight;
 
        standardSprite = this.GetComponent<SpriteRenderer>().sprite;
    }
    void FixedUpdate()
    {
        var currentPosition = cam.ScreenToWorldPoint(Input.mousePosition);
        float targetWidth = Mathf.Clamp(currentPosition.x, -maxWidth, maxWidth);
        float targetHeight = Mathf.Clamp(currentPosition.y, -maxHeight, maxHeight);
        var newPosition = new Vector3(targetWidth, targetHeight, 0f);
        rigidbody2D.MovePosition(newPosition);
 
        if (Input.GetMouseButtonDown(0))
        {
            isHandOpen = false;
            MouseDown();
        }
        else if(Input.GetMouseButtonUp(0))
        {
            isHandOpen = true;
            MouseUp();
        }
    }
 
    private void MouseDown()
    {
        Debug.Log("MouseDown");
        this.GetComponent<SpriteRenderer>().sprite = clickedSprite;
    }
 
    private void MouseUp()
    {
        Debug.Log("MouseUp");
        this.GetComponent<SpriteRenderer>().sprite = standardSprite;
    }
}

Zurück in Unity muss noch das Sprite für die Public-Variablen clickedSprite befüllt werden, dazu muss aus Assets\Textures das ClosedHand-Sprite mittels Drag & Drop auf die Skript-Variable gezogen werden.

clip_image019

Wenn das geklappt hat, dann solltet ihr das einmal ausprobieren. Die Hand müsste über den Bildschirm flitzen, wenn ihr die Maus bewegt. Wenn die Maustaste gedrückt wird, dann seht ihr die Faust. Nach dem Loslassen der Maustaste ist wieder die geöffnete Hand sichtbar. Der Unity-Client ist erst einmal fertig, jetzt müssen wir den SignalR-Teil erstellen.

Echtzeit-Kommunikation mit SignalR

Der Unity-Client wird sich am SignalR-Hub, der als Web-Applikation läuft, anmelden und Meldungen absetzen. Der SignalR-Hub informiert alle angemeldeten Clients und diese werden dementsprechend reagieren. Wir benötigen also eine neue Web-Applikation, ihr könnt dafür entweder eine komplett neue Solution in Visual Studio anlegen, oder auch die von Unity angelegte Solution verwenden. Wie auch immer ihr euch entscheidet, wir benötigen eine neue ASP.NET Web Application, ich habe den Namen SignalRUnityWeb ausgewählt. Diese soll leer sein und per Default noch keinerlei Funktionalität zur Verfügung stellen.

clip_image021clip_image023

Wie mittlerweile fast schön üblich benötigen wir zwei NuGet Packages. Dazu drückt am Web-Projekt die rechte Maustaste und wählt „Manage NuGet Packages…“ an.

Das erste Package ist Microsoft ASP.NET SignalR, derzeit in der Version 2.1.1

clip_image025

Das zweite Package ist Microsoft.Owin.Host.SystemWeb in der Version 3.0.0

clip_image027

Jetzt können wir mit dem Implementieren loslegen, wir benötigen eine neue SignalR Hub Class (v2), dazu drückt ihr die rechte Maustaste am Web-Projekt und wählt Add-> SignalR Hub Class (v2), sollte das bei euch nicht zu sehen sein, dann bitte über Add->New Item und sucht nach SignalR – das nächste Mal, taucht der Eintrag dann in der Liste auf.

clip_image029

Diese sollte den Namen SignalRSampleHub bekommen.

clip_image030

Wir passen die Default-Implementierung nur rudimentär an, ich hätte gerne eine Send-Methode mit zwei Parametern, und zwar WER hat die Meldung abgesetzt und WAS ist der Inhalt.

using Microsoft.AspNet.SignalR;
namespace SignalRUnityWeb
{
    public class SignalRSampleHub : Hub
    {
        public void Send(string name, string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.broadcastMessage(name, message);
        }
    }
}

Wenn wir SignalR 2.0 verwenden, benötigen wir noch eine OWIN Startup class, wiederum mit der rechten Maustaste am Web-Projekt und Add-> OWIN Startup class, bzw. über Add->New Item.

clip_image031

Der Name soll Startup.cs sein.

clip_image032

Die Implementierung ist kurz und bündig und stellt unseren SignalR-Hub zur Laufzeit zur Verfügung.

using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SignalRUnityWeb.Startup))]
namespace SignalRUnityWeb
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

Wenn ihr die Web-Applikation ausführt, so wird das leider nicht klappen, da es da noch einen Versionskonflikt mit der aktuellen Microsoft.Owin-DLL gibt.

clip_image034

Diesen können wir in der Web.config lösen, indem wir der .NET-Laufzeitumgebung mitteilen, sodass die Version 3.0 der DLL auch funktioniert.

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" 
                        publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Jetzt benötigen wir noch eine Webseite in unserer Web-Applikation, ich würde vorschlagen wir nennen diese index.html. Diese soll das Hintergrundbild und die Hand darstellen, sowie sich an unserem SignalR-Hub anmelden. Wenn eine neue Meldung eintrifft, dann muss die Hand bewegt werden und bei gedrückter Maustaste das Bild gewechselt werden. Dank Microsoft und jQuery sind das nur ein paar Zeilen JavaScript-Code.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>SignalR-Unity Sample</title>
    <style>
        body {
            background: url(Images/game-background.png);
            /*background-size:*/
            background-repeat: no-repeat;
        }
        #player {
            position: absolute;
            top: 30px;
            left: 30px;
        }
    </style>
 
</head>
<body>
    <img id="player" src="Images/OpenHand.png" />
 
    <div id="infoContainer">
        <label id="message"></label>
    </div>
 
    <!--Script references. -->
    <!--Reference the jQuery library. -->
    <script src="Scripts/jquery-1.6.4.min.js"></script>
    <!--Reference the SignalR library. -->
    <script src="Scripts/jquery.signalR-2.1.1.min.js"></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="signalr/hubs"></script>
    <!--Add script to update the page and receive messages.-->
    <script type="text/javascript">
        $(function () {
            // Declare a proxy to reference the hub.
            var signalrHub = $.connection.signalRSampleHub;
            // Create a function that the hub can call to broadcast messages.
            signalrHub.client.broadcastMessage = function (name, message) {
                var messageobj = JSON.parse(message);
                if (messageobj.action == 'Position') {
                    $('#player').css('left', messageobj.value.x + 'px');// update x value
                    $('#player').css('top', 500 - $('#message').height() - messageobj.value.y + 'px');// update x value
                    $('#message').text('x:' + messageobj.value.x + "px, y:" + messageobj.value.y + 'px');
 
                    if (messageobj.value.handOpen == 'True')
                        $('#player').attr('src', 'Images/OpenHand.png');
                    else
                        $('#player').attr('src', 'Images/ClosedHand.png');
                }
            };
            // Start the connection.
            $.connection.hub.start().done(function () {
                $('#message').text('connected');
            });
        });
    </script>
</body>
</html>

Nun sollten noch die drei Bilder, die in dem Unity-Client verwendet werden, in die Web-Applikation kopiert werden, und zwar in einen Unterordner mit dem Namen Images.

clip_image035

Solltet ihr eine eigene Visual Studio Solution für diese Web-Applikation erstellt haben, dann startet diese nun. Der Signal-R Hub ist damit erstellt und aktiv. Die Webseite ist nun am Hub als erster Client angemeldet und wartet auf Meldungen vom SignalR-Hub.

clip_image036

Kommen wir zum letzten Abschnitt, SignalR und Unity zu verbinden.

Der Unity Client Teil 2 – Kommunikation mit SignalR

Zurück in Unity legen wir ein leeres GameObject an und geben diesem den Namen SignalRObject.

clip_image037clip_image038

Leere Game-Objekte sind sehr praktisch, in unserem Fall ist es so, dass wir nur ein Script benötigen (um den SignalR-Hub zu informieren), aber keinerlei sichtbaren Aktionen am Bildschirm ausführen werden. Also fügen wir gleich das Skript hinzu, wir geben diesem den Namen SignalRUnityController.

clip_image039

Speichert bitte nun eure Spiel-Szene im Scenes Folder, ich habe dieser den Namen GameScene gegeben. Das ist an dieser Stelle WICHTIG, da ihr sonst möglicherweise durch einen Absturz von Unity alles, was ihr bisher gemacht habt, verlieren könnt. Das liegt weniger an Unity, als an der Programmbibliothek, die wir uns im nächsten Schritt zu unserem Projekt dazuholen.

clip_image040

Bearbeiten wir nun gleich das Skript in Visual Studio 2013 und erweitern es, um den SignalR-Hub anzusprechen.

Leider verwendet Unity nicht die .Net 4.0 Laufzeitumgebung, sondern Mono mit der .NET 3.5 Runtime. Dadurch können wir leider das Microsoft NuGet Package (Microsoft.AspNet.SignalR.Client) für SignalR nicht in unserem Unity C# Projekt verwenden. Es gibt aber auf Github ein Projekt, welches für unsere Zwecke ausreichend ist, in diesem wurde die SignalR-Bibliothek auf .NET 2.0 „heruntermigriert“. Dieses findet ihr hier: https://github.com/jenyayel/SignalR.Client.20

Ich habe dieses Projekt meiner Unity-Solution als eigenständiges Projekt hinzugefügt und danach die Referenz zu dem C#-Projekt dazugegeben.

clip_image042clip_image044

Jetzt können wir die SignalRUnityController skripten. Ich dachte mir, dass wir die SignalR-Funktionalität abschaltbar machen, das kann sehr praktisch sein, wenn man den Unity-Client etwas „tweaked“, was ja vor allem gegen Ende in der Spiele-Entwicklung recht viel Zeit in Anspruch nimmt. Die URL zum SignalR-Hub sollte ebenfalls konfigurierbar sein (dort setzt auch bitte eure URL ein, die ist in eurem Web-Projekt vermutlich anders als meine – zumindest der verwendete Port). Der Rest ist sehr ähnlich dem JavaScript-Client, der Unity Client muss sich am Hub anmelden und möchte (im Gegensatz zum JavaScript-Client) Informationen senden. Die Informationen bestehen aus einem String (wer sendet, der UnityClient) und einem weiteren String, dieser wird allerdings als JSON versendet. Dadurch ist diese Klasse in mehreren meiner Projekte einsetzbar.

using SignalR.Client._20.Hubs;
using UnityEngine;
public class SignalRUnityController : MonoBehaviour {
    public bool useSignalR = true;
    public string signalRUrl = "http://localhost:5225/";
 
    private HubConnection _hubConnection = null;
    private IHubProxy _hubProxy;
    private Subscription _subscription;
    void Start()
    {
        if (useSignalR)
            StartSignalR();
    }
    void StartSignalR()
    {
        if (_hubConnection == null)
        {
            _hubConnection = new HubConnection(signalRUrl);
 
            _hubProxy = _hubConnection.CreateProxy("SignalRSampleHub");
            _subscription = _hubProxy.Subscribe("broadcastMessage");
            _subscription.Data += data =>
            {
                Debug.Log("signalR called us back");
            };
            _hubConnection.Start();
        }
        else
            Debug.Log("Signalr already connected...");
    }
    public void Send(string method, string message)
    {
        if (!useSignalR)
            return;
 
        var json = "{" + string.Format("\"action\": \"{0}\", \"value\": {1}", method, message) + "}";
        _hubProxy.Invoke("Send", "UnityClient", json);
    }
}

Was jetzt noch fehlt ist, dass die Informationen aus der FixedUpdate-Methode im PlayerController in der Send-Methode der SignalRUnityController-Klasse landen.

Dazu reichen uns insgesamt vier Zeilen Code. Das Trickreiche daran ist zum einen, dass wir eine Referenz auf das leere Gabe-Objekt benötigen, an dem das Skript zum Senden der Informationen hängt, zum anderen müssen die Koordinaten vom Unity-Format in Weltkoordinaten umgerechnet werden. Abschließend noch einen JSON-String gebaut und es kann auch schon losgehen.

using UnityEngine;

public class PlayerController : MonoBehaviour {

public Camera cam;

private float maxWidth;

private float maxHeight;

bool isHandOpen = true;

public Sprite clickedSprite;

private Sprite standardSprite;

private SignalRUnityController _signalr;

void Start()

    {

if (cam == null)

            cam = Camera.main;

_signalr = (SignalRUnityController)GameObject.Find("SignalRObject")

            .GetComponent(typeof(SignalRUnityController));

var corner = new Vector3(Screen.width, Screen.height, 0f);

var targetWidth = cam.ScreenToWorldPoint(corner);

float playerWidth = renderer.bounds.extents.x;

float playerHeight = renderer.bounds.extents.y;

        maxWidth = targetWidth.x - playerWidth;

        maxHeight = targetWidth.y - playerHeight;

        standardSprite = this.GetComponent<SpriteRenderer>().sprite;

    }

void FixedUpdate()

    {

var currentPosition = cam.ScreenToWorldPoint(Input.mousePosition);

float targetWidth = Mathf.Clamp(currentPosition.x, -maxWidth, maxWidth);

float targetHeight = Mathf.Clamp(currentPosition.y, -maxHeight, maxHeight);

var newPosition = new Vector3(targetWidth, targetHeight, 0f);

        rigidbody2D.MovePosition(newPosition);

if (Input.GetMouseButtonDown(0))

        {

            isHandOpen = false;

            MouseDown();

        }

else if(Input.GetMouseButtonUp(0))

        {

            isHandOpen = true;

            MouseUp();

        }

var worldCoordinates = cam.WorldToScreenPoint(newPosition);

var json = "{" + string.Format("\"x\": \"{0}\", \"y\": \"{1}\", \"handOpen\": \"{2}\"",

            worldCoordinates.x, worldCoordinates.y, isHandOpen) + "}";

        _signalr.Send("Position", json);

    }

private void MouseDown()

    {

Debug.Log("MouseDown");

this.GetComponent<SpriteRenderer>().sprite = clickedSprite;

    }

private void MouseUp()

    {

Debug.Log("MouseUp");

this.GetComponent<SpriteRenderer>().sprite = standardSprite;

    }

}

Damit Unity auch unsere beiden Referenzen kennt, die in unserem Projekt nun notwendig sind, müssen die beiden DLLs

· Newtonsoft.Json.dll

· SignalR.Client.20.dll

in den Assets-Folder kopiert werden. Ihr findet diese im bin\Debug-Verzeichnis von dem SignalR.Client.20 Projekt.

clip_image046

clip_image048

Bevor ihr in Unity den Client startet, achtet bitte darauf, dass die Web-Applikation mit dem SignalR-Hub läuft, da sonst Unity hängen bleibt und ihr Unity erneut starten müsst. ACHTUNG, falls ihr eure Spielszene nicht zuvor gespeichert habt, dann verliert ihr alle ungespeicherten Schritte.

Wenn die Web-Applikation und der Unity-Client läuft und ihr die Maus bewegt, werden sich die Hände gemeinsam bewegen.

Falls ihr SignalR mit anderen Clients verwenden wollt, dann solltet ihr einen Blick auf die folgenden Native-Implementierungen werfen:

· iOS (3rd Party): https://github.com/DyKnow/SignalR-ObjC
· Android (offizieller Android-Client): https://github.com/SignalR/java-client
· Windows Phone 8/8.1 (offizieller .Net Client): https://github.com/SignalR/SignalR

Für Unity muss noch ein Wrapper um diese Bibliotheken herum geschrieben werden, dazu findet ihr Näheres in der Unity-Dokumentation:

http://docs.unity3d.com/Manual/PluginsForIOS.html
http://docs.unity3d.com/Manual/PluginsForAndroid.html
http://docs.unity3d.com/Manual/wp8-plugins-guide-csharp.html

Zusammenfassung

Microsoft SignalR und Unity ergeben die perfekte Lösung für Multiplayer-Spiele. Mit wenigen Schritten ist die Echtzeit-Kommunikation bereit gestellt. Ich bin schon gespannt, welche tollen Spiele ihr mit dieser Kombination bauen werdet. Ich freue mich darauf und hoffe ihr habt genauso viel Spaß wie ich beim Entwickeln eurer Indie-Games!


Berndt Hamböck ist seit 2007 MCT, darüber hinaus befasst er sich mit Lösungen für komplexe Anwendungsszenarien mit den neuesten Microsoft Technologien. Die Erfahrungen aus der Projektarbeit gibt er in Vorträgen und Trainings weiter und begleitet Entwicklerteams in Softwareunternehmen bei Projekten im Microsoft Umfeld. Folge ihm auf Twitter, um nichts zu verpassen.

Das ist ein Gastbeitrag. Die Meinung des Autors muss sich nicht mit jener von Microsoft decken. Durch den Artikel ergeben sich keinerlei Handlungsempfehlungen. Microsoft übernimmt keine Gewähr für die Richtigkeit oder Vollständigkeit der Angaben.

Uli Armbruster: Aus der täglichen Retrospektive #3

2014-07-31 12.08.30Unsere Retrospektiven gehen weiter und die Teammitglieder entwickeln meiner Einschätzung nach auch langsam ein besseres Gespür für Impediments. Das ist für mich als Scrum Master besonders erfreulich. Ich habe mir wieder einmal etwas herausgegriffen, von dem ich denke, dass es dem Leser auch helfen kann.

Es hat sich herausgestellt, dass ein wichtiger Prozess bisher nicht explizit gemacht war: Der Go Live.

Das führte unter anderem dazu, dass das Update erst mit mehreren Tagen Verzögerung und teilweise sogar mit Änderungen aus dem neuen Sprint durchgeführt wurde. Darüber hinaus war nicht gewährleistet, dass mit der Codebasis auch die Datenbasis aktualisiert wurde. Deshalb haben wir uns zusammengesetzt, den Prozess besprochen und diesen im Wiki festgehalten.

 

image

Darin wird klar zw. Daten und Code Go Live unterschieden. Das bedeutet auch unterschiedliche Termine und Verantwortliche. Interessanterweise wurde in der Diskussion deutlich, dass der Prozess noch detailliert visualisiert und kommuniziert werden muss. In Kanban ist das fest als Regel aufgelistet:

                  Visualize Your Workflow

 

Einen Einblick in unser Wiki und den Prozess werde ich demnächst in Form eines Screencasts auf YouTube und natürlich auf meinen Blog stellen. Als Abonnent kriegt ihr das automatisch mit.

Mit welchem Tool verfasst bzw. persistiert ihr eure Regeln? Wer macht das? Wird das kontinuierlich erweitert oder war das nicht mehr notwendig? Ist es euch auch schon öfters passiert, dass ihr feststellen musstet, dass Regeln nicht explizit gemacht und dadurch Probleme verursacht wurden? Gerne könnt ihr mir einen Kommentar schreiben.


Einsortiert unter:CIO Topics, German, Projects Tagged: Agile Development, Retrospektive, Scrum

Hendrik Lösch: Multi-Device Hybrid Apps in the Cloud

Einer der Gründe warum ich mit Microsoft basierenden Technologien arbeite, ist die Möglichkeit sich in vielen Dingen einfach darauf konzentrieren zu können was man tatsächlich tun will. Ok, es gibt immer wieder Situationen wo man sich dann doch durch so ekelige Dinge wie XML Configs wursteln muss, aber auf der anderen Seite gibt es dann […]

Christian Binder [MS]: Du bist C++ Entwickler - arbeitest aber noch mit VS 2010?

Das VC C++ Team in Redmond hat eine Umfrage für VS 2010 C++ Entwickler bereitgestellt. Ziel ist es herauszufinden und besser zu verstehen, welche Blocker Entwickler haben, die aktuelle Visual Studio Version zu verwenden. Das C++ Team bietet auch die Möglichkeit direkt Kontakt aufzunehmen, um bei Fragen zum Upgrade zu unterstützen. Hier geht es zum Feedback.

Danke für Euer Feedback
Chris

ppedv Team Blog: SharePoint 2013 – Bedingte Formatierung verwenden

Leider gibt es in SharePoint 2013 nicht mehr die einfache Möglichkeit, wie in SharePoint 2010, eine bedingte Formatierung einzurichten, wenn in einer Spalte einer Liste bestimmte Ausdrücke stehen. Dieses Vorhaben muss in der aktuellen SharePoint-Version etwas umständlicher, bzw. komplizierter umgesetzt werden. In diesem Blog zeige ich eine Möglichkeit, wie wir das bewerkstelligen können: nämlich per JavaScript.

Der erste Schritt besteht darin, folgende Codezeilen in der Ansicht “Alle Vorgänge” einer Liste wie im unteren Screenshot abgebildet einzufügen.

<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.js" type="text/javascript"></script>

<script type="text/javascript">

    $(document).ready(function()

    {

        $('.ms-vb2:contains("Completed")').css('background-color', 'lightgreen');

        $('.ms-vb2:contains("Not Started")').css('background-color', 'red');

        $('.ms-vb2:contains("In Progress")').css('background-color', 'orange');

});

</script>

 

Das machen wir im SharePoint Designer. Dazu öffnen Sie die Liste und rechts unter Ansichten die Ansicht Alle Vorgänge.

image

Nun sehen Sie die Code-Ansicht im SharePoint Designer. Sie bewegen sich hinter die Zeile:

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">

In meinem Fall ist es die Zeile 16.

Benutzerdefinierte Formatierung_SP2013

Im Code müssen wir, je nachdem welche Ausdrücke in einer Liste verwendet werden, noch einige kleine Anpassungen vornehmen.

In meinem Beispiel wird demonstriert, wie sich der Spalten einfärben, je nach darin enthaltenem Text. Somit passen Sie je nach Bedarf, den nachfolgend farbig gekennzeichneten Text in den abgebildeten Zeilen mit Ihren verwendeten Ausdrücken entsprechend an. Gegebenenfalls können Sie die Farben ebenso verändern, die jeweils am Ende der Zeile definiert werden.

$('.ms-vb2:contains("Vorgang genehmigt")').css('background-color', 'lightgreen');

$('.ms-vb2:contains("Vorgang abgelehnt")').css('background-color', 'red');

$('.ms-vb2:contains("Warte auf Genehmigung")').css('background-color', 'orange');

 

Das Resultat sieht in meiner Aufgabenliste folgendermaßen aus.

Liste mit Formatierung

Fertig!

Viel Spaß damit

ppedv Team Blog: EFS-Verschlüsselung für Dateiobjekte einschalten

In Windows 8 Pro bzw. Enterprise lassen sich ganze Ordner und Dateien mit dem verschlüsselnden Dateisystem (Encrypting File System, EFS) verschlüsseln. Dies ermöglicht Ihnen, kritische Inhalte gegen unbefugte Einsichtnahme und Missbrauch durch Dritte zu schützen.

Das Einschalten der EFS-Verschlüsselung für Dateien und Ordner ist sehr einfach und schnell durchgeführt.

1. Öffnen Sie das Eigenschaftenfenster eines Ordners oder einer Datei und gehen dann über die Registerkarte Allgemein auf die Schaltfläche Erweitert.

image

2. Anschließend setzen Sie einen Haken bei Inhalt verschlüsseln, um Daten zu schützen und schließen die Dialogfelder (wobei die Optionen zum Verschlüsseln einer Datei oder eines Ordners zu wählen sind).

image

 

Zu beachten ist, dass sich das Komprimieren und Verschlüsseln gegenseitig ausschließen. Windows fragt daher beim Schließen der Registerkarte (unten links) ab, ob nur das markierte Element oder auch der übergeordnete Ordner verschlüsselt werden soll. Wählen Sie den gewünschten Modus aus und klicken Sie auf OK.

image

Anschließend wird das betreffende Element vollständig verschlüsselt. Mit einem verschlüsselten Ordner können Sie wie mit einem normalen unverschlüsselten Ordner arbeiten. Der einzige Unterschied besteht darin, dass nur zugriffsberechtigte Personen auf den Inhalt des verschlüsselten Ordners oder die verschlüsselte Datei zugreifen können. Dritten wird der Zugriff verwehrt. Selbst wenn diese Zugriff auf die verschlüsselte Datei erhalten, nutzt dies (ohne das zugehörige Zertifikat zur Entschlüsselung) nichts.

Im Falle eines Zugriffs einer nicht berechtigten Person, erhält diese keinen Einblick in die Datei (oder Ordner).

Unbenannt

Fabian Deitelhoff: Teil 5 – Raspberry Pi als Mediacenter mit Raspbmc (Performance)

Teil 5 - Raspberry Pi als Mediacenter mit Raspbmc (Performance)Teil fünf der Serie zum Raspberry Pi als Mediacenter. Wie doch die Zeit vergeht. Neben der Hardware, Installation, und verschiedenem zur Konfiguration geht es nun um die Performance unseres Mediacenters.

Die Geschwindigkeit ist natürlich auch für ein Mediacenter eine wichtige Angelegenheit und gleichzeitig ein zweischneidiges Schwert. Denn auf der einen Seite sollen die Videos nicht ruckeln. Insbesondere bei Full HD-Videos. Gleichzeitig müssen aber auch noch ein paar Reserven vorhanden sein, um das Mediacenter flüssig bedienen zu können. Der ein oder andere Hintergrund-Task läuft zudem auch noch.

Auf der anderen Seite darf die Hardware aber nicht sonderlich hungrig nach Energie sein. Die Abfuhr der Wärme ist in einem lüfterlosen Gehäuse nicht sonderlich gut und Energie, die eingespart werden kann, ist sicherlich immer positiv zu verbuchen.

Daher geht dieser Beitrag etwas auf die Performance des Mediacenters ein und verrät den ein oder anderen Knackpunkt, an dem es recht häufig scheitert, wenn das Mediacenter nicht so flüssig reagiert wie erhofft.

Dieser Blogpost ist Teil einer Serie zum Thema “Raspberry Pi als Mediacenter mit Raspbmc”. Im Rahmen dieser Serie sind die folgenden Teile erschienen. Der jeweils aktuelle Beitrag ist hervorgehoben.

  1. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Hardware)
  2. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Software)
  3. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration I)
  4. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration II)
  5. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Performance)
  6. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Tipps & Tricks)
  7. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Gesamtfazit)

Performance

Ein kritischer Punkt für ein Mediacenter ist die Performance. Auf der einen Seite ist damit gemeint, ob die Hardware leistungsstark genug ist, um alle gewünschten Medien abzuspielen. Im Falle des Raspberry Pi ist das aber der Fall. Da wir uns darum nicht mehr kümmern müssen, soll es in diesem Teil um etwas anderes gehen.

Ich möchte gerne einige Performance-Killer aufzählen, die immer wieder dafür sorgen, dass sich darüber beschwert wird, der Raspberry Pi hätte nicht genug Leistung, um als Mediacenter zu fungieren. In dieser Serie, wie im Teil 3 zur allgemeinen Konfiguration gezeigt, habe ich zwar empfohlen, die Hardware leicht zu übertakten, um einfach ein paar Reserven mehr zur Verfügung zu haben. Erforderlich ist das aber nicht. Jetzt soll es darum gehen, welche anderen Faktoren dafür sorgen können, dass die Leistung, beispielsweise beim Abspielen von Videos, nicht so gut wie gewünscht ist. Diese anderen Faktoren können so groß sein, dass auch ein bis an die Grenzen übertakteter Raspberry Pi in die Knie gezwungen wird und seine Aufgabe als Mediacenter nicht mehr gerecht werden kann.

SSH-Verbindung aufbauen

Um die Performance zu überprüfen, brauchen wir zunächst eine SSH-Verbindung. Grundsätzlich ist die Auslastung auch in den Einstellungen zu sehen. Allerdings ist das auf die Dauer doch recht aufwändig. Wer keine VNC-Verbindung einrichten möchte und das Mediacenter auch sonst nicht in Reichweite hat, sitzt immer vorm Fernseher, um sich die Auslastung anzuzeigen. Nicht sehr praktisch. Eine SSH-Verbindung macht es hier einfacher.

Eine kleine Begegnung mit SSH gab es schon einmal im Artikel zur Headless WIFI Konfiguration für den Raspberry Pi. Ich nutze als Client für die Verbindung von meinem Windows-Rechner aus gerne die Software MobaXterm anstatt beispielsweise PuTTY. Erstere hat einige Vorteile. Grundsätzlich funktioniert aber jedes Tool, mit dem eine SSH-Verbindung aufgebaut werden kann.

Eine SSH-Verbindung ist – beim Raspberry Pi – ohne größere, manuelle Konfiguration möglich. Was genau dazu notwendig ist, habe ich bereits im dritten Teil der Serie erklärt. Wenn der SSH Server beziehungsweise Dienst läuft, reicht es aus, auf dem Client einfach MobaXterm zu starten und den folgenden Befehl einzugeben.

ssh pi@192.168.2.101

Anschließend wird das Passwort verlangt. Wenn keine Einstellungen vorgenommen wurden, lautet das Standardpasswort raspberry für den Standardbenutzer pi. Abbildung 1 zeigt den Login-Versuch und die Ausgabe des Raspberry Pis, wenn der Login erfolgreich war. Welche IP-Adresse der Raspberry Pi hat, musste ich zuvor herausfinden. Beispielsweise über die Software eures Routers, die alle angemeldeten Geräte des Netzwerks auflistet. In meinem Netzwerk meldet sich der Pi mit dem Netzwerknamen xbmc-fb78.

Abb. 1: Erfolgreicher Verbindungsversuch mit dem Raspberry Pi über SSH.

Abb. 1: Erfolgreicher Verbindungsversuch mit dem Raspberry Pi über SSH.

Mehr ist für den SSH-Zugang an dieser Stelle nicht erforderlich. Steht die Verbindung erst einmal, können wir auf diesem Weg Befehle über die Kommandozeile an den Raspberry Pi schicken.

Ein Performance-Überblick

Um etwas über die Performance zu erfahren, brauchen wir nur ein einziges Linux-Kommando. Mittels top können wir uns ausgeben lassen, welcher Prozess gerade wie viele Ressourcen verbraucht. Mit Ressourcen sind hier beispielsweise der Arbeitsspeicher und der CPU-Verbrauch gemeint. Das folgende Listing zeigt die Ausgabe am Beispiel meines Mediacenters.

PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
  975 pi        20   0  364m  66m  21m S  28.5 17.6  11647:58 xbmc.bin
 6663 pi        20   0  3116 1340  924 R   1.3  0.3   0:01.71 top
   35 root       1 -19     0    0    0 S   1.0  0.0 290:20.40 VCHIQr-0
   81 root      20   0     0    0    0 S   0.3  0.0  10:45.17 kworker/0:2
  581 root      20   0  1976 1848 1496 S   0.3  0.5 152:29.34 startpar
 6619 root      20   0  3128 1428  980 S   0.3  0.4   0:01.18 dropbear
    1 root      20   0  3128 1676 1200 S   0.0  0.4   0:01.33 init
    2 root      20   0     0    0    0 S   0.0  0.0   0:00.01 kthreadd
    3 root      20   0     0    0    0 S   0.0  0.0  23:37.28 ksoftirqd/0
    5 root       0 -20     0    0    0 S   0.0  0.0   0:00.00 kworker/0:0H
    7 root      -2   0     0    0    0 S   0.0  0.0   6:29.77 rcuc/0
    8 root      -2   0     0    0    0 S   0.0  0.0   0:00.00 rcub/0
    9 root      20   0     0    0    0 S   0.0  0.0  15:05.65 rcu_preempt
   10 root      20   0     0    0    0 S   0.0  0.0   0:00.00 rcu_bh
   11 root      20   0     0    0    0 S   0.0  0.0   0:00.00 rcu_sched
   12 root       0 -20     0    0    0 S   0.0  0.0   0:00.00 khelper

Die Ausgabe zeigt, dass aktuell nur zwei Prozesse unter dem Benutzer pi laufen, was korrekt ist. Direkt an erster Stelle steht ein Prozess, der dem Kommando xbmc.bin entsprungen ist. Dabei handelt es sich um das Mediacenter. Das top-Kommando aktualisiert im Übrigen seine Ausgabe alle drei Sekunden, so dass auch ein Verlauf der Auslastung zu sehen ist. Die CPU sollte immer zwischen 25% und maximal 50% Auslastung durch das Mediacenter liegen. Woran es genau liegt, dass die Beanspruchung nicht unter 25% sinkt, ist mir auch noch nicht ganz bewusst. Vermutlich liegt es daran, dass die Software in keinen Ruhemodus gefahren wird. Am HDMI-Ausgang liegt immer die grafische Ausgabe an, so dass bei einem Wechsel des Anschlusses sofort ein Bild zur Verfügung steht. So ist zumindest meine Beobachtung mit meinem Mediacenter. Als kleine Randnotiz: die Ausgabe oben habe ich drastisch gekürzt. Es laufen noch deutlich mehr Prozesse, die in diesem Fall aber alle nicht relevant sind.

Über 50% sollte die Auslastung im Leerlauf aber auch nicht steigen. Werte darüber sind ein gutes Anzeichen dafür, dass der Raspberry Pi mit irgendwelchen Aufgaben ausgelastet ist. Beispielsweise wenn neue Videos, Serien oder Bilder auf die externe Festplatte kopiert wurden und eine Indexierung ansteht, bei dem auch Cover heruntergeladen werden müssen.

Anhand der oben gezeigten Ausgabe wird aber schon deutlich, warum nicht noch viele weitere Prozesse ständig im Hintergrund laufen sollten. Bei einem HD-Film wird der Raspberry Pi noch mehr beansprucht. In der Regel ist das kein Problem und die Hardware kommt mit den Anforderungen ohne Probleme zurecht. Allerdings nicht, wenn noch ein weiterer Prozess 30% oder mehr der Leistung beansprucht. Und wie schnell diese 30% oder mehr erreicht sind, zeigt das folgende Beispiel.

Optionaler VNC-Server

Der VNC-Server erlaubt es, anders als SSH, eine Verbindung mit einem entfernten Rechner aufzubauen und den Bildschirminhalt zu übertragen. Wir können also die Maus steuern und direkt mit grafischen Elementen, beispielsweise einem Desktop, interagieren, als ob wir vor dem entfernten Gerät sitzen würden. Na ja, nicht wirklich ganz so gut. Etwas Verzögerung ist natürlich vorhanden.

Dieser VNC-Server kann beim Raspberry Pi direkt aktiviert werden. In Teil drei habe ich das kurz bei den allgemeinen Einstellungen zu den Diensten erwähnt. Zugegeben, dass ist sehr einfach, komfortabel und ohne viel Nachdenken erledigt. Die folgende Ausgabe des bekannten top-Kommandos zeigt, was das für Folgen hat. Auch hier ist die Ausgabe wieder drastisch gekürzt, um nicht zu viel Platz zu benötigen.

PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
 6752 root      20   0 50432  13m  988 R  46.3  3.5   0:23.58 vnc_dispmanx
 6799 pi        20   0  345m  43m  19m R  34.4 11.5   0:19.66 xbmc.bin
    1 root      20   0  3128 1676 1200 S   0.9  0.4   0:01.51 init
 6819 pi        20   0  3112 1336  920 R   0.9  0.3   0:00.43 top

Neben dem Prozess zum Kommando xmbc.bin gibt es nun einen weiteren. Das Kommando vnc_dispmanx ist der VNC-Server, den wir aktiviert haben. Dieser verbraucht, ohne dass eine Verbindung besteht, über 46% der CPU-Ressourcen. Schwankt der Prozess des Mediacenters also, kann es durchaus sein, dass die gesamte Auslastung zwischen 80% und 95% liegt. Und das dauerhaft. Jetzt sollte klar sein, warum der Raspberry Pi Probleme bekommt, wenn jetzt noch ein Video abgespielt werden soll. Die Folge sind Bildaussetzer beziehungsweise Ruckler beim Video und auch der Ton ist alles andere als unterbrechungsfrei oder synchron mit dem Bild.

Den VNC-Server also einfach in den Einstellungen des Raspbmc zu aktivieren, scheint keine gute zu sein. Ein kleines Shell-Skript kann hier helfen, den Server einfach bei Bedarf zu starten und anschließend wieder zu stoppen. Dazu ist zunächst zwar eine SSH-Verbindung notwendig, allerdings kann ich das verschmerzen. Meine persönliche Erfahrung ist, dass ich eine VNC-Verbindung sehr, sehr selten brauche. SSH reicht vollkommen aus. Vielleicht lasse ich in zukünftigen Versionen den VNC-Server komplett weg.

Nichtsdestotrotz soll es jetzt um das besagt Skript gehen. Das habe ich auch einfach mal im folgenden Listing aufgeführt.

#!/bin/sh

case $1 in
  start)
    if [ -f /var/run/vnc.pid ] ; then
      echo "VNC server is already running"
    else
      initctl stop xbmc
      sudo vnc_dispmanx 2>/dev/null &
      echo $! | sudo dd of=/var/run/vnc.pid
      initctl start xbmc
    fi
    ;;
  stop)
    if [ -f /var/run/vnc.pid ] ; then
      sudo kill -TERM $(cat /var/run/vnc.pid)
      sudo rm /var/run/vnc.pid
    else
      echo "VNC server is not running"
    fi
    ;;
  *)
    echo "Usage $0 start|stop"
    ;;
esac

Ich möchte an dieser Stelle gar nicht großartig auf die Programmierung an sich eingehen, sondern lediglich zeigen, wie dieses Skript eingebunden werden kann. Obwohl eingebunden deutlich übertrieben ist. Denn viel mehr als an die richtige Stelle kopieren ist gar nicht nötig.

Das Skript kann entweder direkt mit MobaXTerm auf den Raspberry Pi oder manuell in eine Datei kopiert werden. Ersteres funktioniert sehr gut die sogenannte SFTP-Funktion. Nach dem Anmelden ist auf der linken Seite eine Verzeichnissstruktur abgebildet. Dort kann einfach eine Datei mittels Drag & Drop abgelegt werden. Ebendiese Datei wird dann auf den Raspberry Pi kopiert. Und zwar genau dort hin, wo wir uns gerade, also nach dem Login, befinden. Manuell geht es am einfachsten über einen Texteditor. Also beispielsweise durch das Kommando:

nano vncserver

Damit wird eine Datei Namens vncserver angelegt und mit dem Programm nano geöffnet. Dort bitte das Skript rein kopieren. Entweder über das Kontextmenü der Maus oder über die Tastenkombination SHIFT + INSERT. Anschließend die Datei mit STRG + W speichert und mit STRG + X schließen. Egal welchen Weg wir nehmen, jetzt gibt es eine neue Datei im Home-Verzeichnis unseres Raspberry Pis. Als Dateinamen empfehle ich vncserver. Ein anderer geht aber auch. Eine Endung ist nicht erforderlich.

Nun muss das Skript noch als ausführbar gekennzeichnet werden, was über das folgende Kommando möglich ist:

chmod +x vncserver

Zum Schluss braucht das Skript noch einen neuen Speicherort. Das nächste Kommando kopiert die Datei an die richtige Stelle:

sudo mv vncserver /usr/local/sbin

Genau genommen wird die Datei an diese Stelle verschoben. Denn im Home-Verzeichnis brauchen wir sie nicht mehr. Nachdem wir diese Schritte ausgeführt haben, kann der Server manuell über die Kommandozeile gestartet und gestoppt werden. Das erledigen die folgenden beiden Kommandos:

vncserver start oder vncserver stop

Damit ist auch das Problem erledigt, dass der VNC-Server immer im Hintergrund läuft und ständig sehr viele Ressourcen an sich bindet. Damit ist der VNC-Server optional und nicht immer ständig vorhanden. Ob VNC überhaupt notwendig ist, muss jeder für sich entscheiden. Ich benutze es in letzter Zeit sehr selten. SSH reicht für meine Zwecke aus.

Zwischenfazit

Dieser fünfte Teil der Serie befasste sich mit einigen Performance-Aspekten. Allerdings ist das nur eine sehr kleine Auswahl, die zeigen sollte, dass ein Dienst, der im Hintergrund läuft, sehr viele Ressourcen binden kann. Das ist insbesondere dann ärgerlich, wenn dieser Dienst gar nicht oft benötigt wird. Zwischenzeitlich kann es nützlich sein, mal mit dem top-Kommando nachzuschauen, ob der Raspberry Pi unter größerer Last steht.

Das Thema Performance sollte aber nur ein Thema sein, wenn es zu Problemen kommt. Wenn beispielsweise Videos ruckeln oder das Gehäuse des Raspberry Pis deutlich wärmer wird als handwarm. Vorher würde ich mir keine großen Sorgen machen.

Im kommenden Teil 5 geht es um ein paar Tipps & Tricks, die das Leben mit dem Raspberry Pi beziehungsweise Raspbmc einfacher machen können. Wir kümmern uns auch um das Abspielen von MPEG-2- und VC-1-Videos, die von unserem Mediacenter aktuell noch nicht verstanden werden.

Sven Hubert: Overview of implemented requirements across branches

TFS functions enhanced and simplified using the TFS ASAP

One of the main advantage of the TFS is the ability to link multiple artifacts which are related to a project. Source code changes, builds and requirements are joined together to a whole. The main benefit of such a deeply integrated environment is transparency.

That makes it easy to find out which requirements or features have already been become part of a build. Only a small work item query is necessary to achieve that.

Collecting the information in order to write a release summary is done within seconds.

There are of course some prerequisites. The requirements have to be planned and split into smaller tasks. The tasks have to be linked when source code changes were checked in and a build process has to be defined.

If you are working with branches (which is highly recommended) you need a bit of discipline and concentration in addition. If you prefer to have it easy and secure also in this scenario it is time to have a deeper look onto TFS Automated Servicing & Administration Platform.

A small application consisting of two features illustrates the approach. Each feature consists of two requirements. Each is broken down into two tasks. To implement the features independently two feature branches are used. The results are integrated on the main branch. The release will get created on a separate branch. Therefore the release notes have to be collected.

Features, requirements and tasks are at first defined and structured in the backlog or the task board.

Two feature branches are created based on the main branch as well as the release branch.

For each branch a build process will be defined.

During the check-in-process the implemented tasks are linked by the developer.

Thereafter the running build process links everything together.

Now it is possible to create a work item query showing all work items which have already been resolved on that branch.

As soon as the requirements are fulfilled they are merged into the main branch. In order to use the work item query on this branch it is also necessary to link all requirements which have been resolved on the source branch with the check-in.

After testing the integrated requirements they have to be merged into the release branch. Once again it is necessary to link all requirements which are resolved on the main branch.

In the shown example with two features this is an easy task. But in reality you typically have a bunch of requirements to merge. Selecting always the right ones requires a smart work item query and especially a lot of concentration.

Here TFS ASAP comes into play. This error-prone task will be done by this server side extension in the background. All work items which are related to a merge process are linked automatically with the resulting merge change set. Work items which had previously been linked to a check-in into the source branch are taken into consideration

The integrity of the work item query which is used to create the release notes is hereby ensured.

Merge operations are simplified and forgetting requirements gets impossible.

A small extension through the TFS Automated Servicing & Administration Platform with great effect!

The creation of the release notes can even be more simplified by adding a field “Release Note” to the requirement work item definition. These information can get transformed directly into a document using the AIT Build Suite.

Overview of implemented requirements across branches is a post from: AIT Blog

Holger Sirtl: Best Practices und Links zu Azure SQL Database

Nachdem ich immer wieder Sammlungen von Informationen zu Microsoft Azure zusammenstellen muss, möchte ich mit diesem Blog mal damit anfangen, nützliche Links zu einer der zentralen Services aufzulisten: SQL Database.

Mit SQL Database verfügt Microsoft Azure über eine echte relationale Datenbank als Cloud Service. Diese ist schnittstellenkompatibel zu SQL Server. Damit ist es möglich, SQL Database über bekannte Technologien (z.B. Entity Framework, ADO.NET, JDBC) und Werkzeuge (z.B. SQL Server Management Studio) zuzugreifen. In vielen Fällen reicht es aus, die Adressierung der anzusprechenden Datenbank über den Connection String zu einer entsprechenden Cloud Datenbank vorzunehmen.

SQL Database wird in drei Editionen angeboten: Basic, Standard und Premium. Basic eignet sich als kostengünstige Alternative für geringere Lasten und Datenbankgrößen bis 2 GB, Standard bietet höhere Transaktionsleistungen für Datenbanken bis 250 GB und Premium garantiert höchste Performanz- und Transaktionsleistung bei Datenbanken bis 500 GB. Zwischen den Editionen kann zur Laufzeit einfach gewechselt werden, so dass auf Änderungen in den Lastanforderungen reagiert werden kann.

Allgemeine Links

Folgende Links enthalten wirklich nützliche Informationen für alle, die sich mit dem RDBMS-as-a-Service Angebot in Microsoft Azure auseinandersetzen wollen.

Best Practices

SQL Server vs. SQL Database

Alexander Schmidt: Visual Studio 14 CTP angetestet

  Ich hatte viel zu lange keine wirkliche Zeit, mir die CTP für das kommende VS 14 anzusehen. Inzwischen ist die 3. CTP-Version draußen und in gewohnter Manuier wird ein Blick drauf geworfen. Screencast (in Arbeit) Links Englische Version der News im MS Support-Bereich Anleitung zur Nutzung eines fertigen Azure-Images zum Probieren Probieren Wer nicht […]

Fabian Deitelhoff: LEGO Mindstorms EV3: Kennenlernworkshop in Unna

LEGO Mindstorms EV3Am Samstag, den 06. September 2014, war es endlich wieder soweit. Das neue Semester bei den Volkshochschulen hat für mich begonnen. Dieses Mal ging es mit einem kleinen Kennenlernworkshop zum LEGO Mindstorms EV3 los.

Dieser Workshop dauerte vier Unterrichtseinheiten. Zusammen mit einer Pause von 15 Minuten war der Vormittag von 10.00 Uhr bis 13.15 Uhr gut gefüllt mit Themen Rund um den LEGO Mindstorms EV3 für Einsteiger. Insgesamt elf Teilnehmer hatten sich dazu entschlossen, etwas zum Mindstorms-System zu erfahren. Eine gute Gruppengröße, um auch individuell auf Fragen eingehen zu können, auch wenn die Zeit bei einem einzigen Vormittag recht knapp bemessen ist. Aber der Kurs hieß nicht umsonst Kennenlernworkshop :).

Inhaltliches

Der Inhalt war zugeschnitten auf Einsteiger, die noch nie etwas mit dem LEGO Mindstorms System, im Speziellen mit der aktuellen Version EV3, zu tun gehabt haben. Am Anfang habe ich etwas über die Geschichte des Mindstorms, den Zweck und der Community erzählt. Danach ging es natürlich um die Komponenten, die Hardware, Software, Entwicklungsumgebung und wie damit die ersten, kleinen Programme entwickelt werden können.

LEGO Mindstorms EV3 - Kennenlernworkshop bei der VHS Unna.

LEGO Mindstorms EV3 – Kennenlernworkshop bei der VHS Unna.

Circa die zweite Hälfte des Workshops haben wir, beziehungsweise insbesondere die Kinder :), damit verbracht, eigene Ideen umzusetzen, zu testen und zwischendurch auch vorne am Beamer für alle vorzustellen. Sehr häufig funktionierten die Programme direkt von Anfang an. Hin und wieder mussten einige Ein- und Ausgabeports anders belegt werden. Manchmal kam es auch zu witzigen Situationen, wenn die Systeme etwas ganz anderes vollbrachten als gedacht. Als Softwareentwickler ist das natürlich nichts Neues ;).

Fazit

Mir hat es viel Spaß gemacht. Die Gruppe war sehr gut drauf und hat in Windeseile verstanden, worauf geachtet werden muss und was ich mit den kleinen Aufgabenstellungen meine. Ganz vorne mit dabei waren natürlich die Kinder. Ich bin jedes Mal aufs Neue erstaunt, wie schnell das System an sich, die Funktionsweise und die Abläufe selbst von neunjährigen schon durchschaut und angewandt werden können. Ob ich früher auch so schnell war, als ich meine ersten Schritte vollbracht habe? Ich habe da ganz starke Zweifel.

Einige von den Teilnehmern sehe ich auch in meinem Ferien-Workshop Anfang Oktober wieder, worauf ich mich sehr freue. Mal schauen, was wir dann für Aufgaben lösen.

Uli Armbruster: Testen von Datenbankabfragen – Es geht auch einfach

In diesem Screencast zeige ich wie selbst Abfragen mit mehreren Bedingungen und Sortierungen einfach getestet werden können. Unter der Haube kommt das Entity Framework zum Einsatz. Davon kriegt man dank Dependency Injection aber nichts mit.

Die erwähnte Webcast Serie, sowie weiteren Beispielcode und das Projekt auf Github gibt es hier. Feedback oder Fragen nehme ich gerne entgegen. Wenn ihr wollt, dass ich die Serie fortsetze, sprecht mich über einen Kanal eurer Wahl an.


Einsortiert unter:.NET Framework, Architecture, C#, Development, German, Projects Tagged: Clean Code, EntityFramework, TDD

Code-Inside Blog: Visual Studio 2013 Hidden Gem: Paste JSON or XML as C# Classes

I was looking for an easy way to “convert” an XML structure to a normal C# structure and stumbled upon a handy feature of Visual Studio 2013. This also works for any JSON content as well.

What you need:

Copy your XML or JSON in the clipboard and make sure you have a .NET 4.5 project selected. I’m not sure why this limitation is in place, but you can use the generated classes in .NET 4.0 and even lower I guess.

Then just click Edit - Paste Special - Paste XML/JSON As Classes.

foo

The generated classes:

The generated classes should work with JSON.NET or any XML Serializer. The Code for the XML is a bit messy, but works and gives you a starting point.

Sample from here:

public class Rootobject
{
    public string firstName { get; set; }
    public string lastName { get; set; }
    public bool isAlive { get; set; }
    public int age { get; set; }
    public float height_cm { get; set; }
    public Address address { get; set; }
    public Phonenumber[] phoneNumbers { get; set; }
    public object[] children { get; set; }
    public object spouse { get; set; }
}

public class Address
{
    public string streetAddress { get; set; }
    public string city { get; set; }
    public string state { get; set; }
    public string postalCode { get; set; }
}

public class Phonenumber
{
    public string type { get; set; }
    public string number { get; set; }
}

Note: There are many other web based XML/JSON to C# converter out there - so feel free to use whatever works for you. I didn’t know this little feature.

Sven Hubert: ALM kompakt: Kann man die Zustände aus dem Kanban-Board auswerten?

Out-of-the-box ist der Zustand eines Work Items, wie es im Kanban-Board dargestellt wird, nicht als Work Item Feld verfügbar und damit nicht mittels einer Work Item Query abzufragen. Jedoch gibt es Abhilfe.

Auf Basis unserer Automatisierungsplattform TFS ASAP kann man eine Regel implementieren, die ereignisgesteuert den Kanban-Status stets im Work Item hinterlegt, sobald sich dieser ändert. Der Ablauf sieht wie folgt aus:

image

Je nachdem, wie das neue Feld definiert ist, kann man den Kanban-Status dadurch sogar im Data Warehouse des TFS verfügbar machen.

Damit wird der Kanban-Status per Work Item Query und damit z.B. auch aus Excel heraus auswertbar. Auch in den Reports kann man dann auf diese Information zurückgreifen.

Haben Sie Interesse an dieser oder anderen Automatisierungen für den TFS? Setzen Sie sich mit uns in Verbindung: info@aitgmbh.de

ALM kompakt: Kann man die Zustände aus dem Kanban-Board auswerten? is a post from: AIT Blog

Holger Schwichtenberg: Klassendefinition in PowerShell 5.0 mit dem neuen Schlüsselwort "class"

In der kommenden Version der PowerShell lassen sich Klassen direkt in der PowerShell-Skirptsprachensyntax definieren.

Holger Schwichtenberg: Vorträge im September

Eine Liste der Vorträge des Dotnet-Doktors im September auf Konferenzen in Wuppertal, Lingen und Mainz.

Fabian Deitelhoff: Teil 4 – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration II)

Teil 4 – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration II)Und schon sind wir beim vierten Teil der Serie zum Raspberry Pi als Mediacenter. Im Grunde ist das Mediacenter mittlerweile einsatzbereit. Die Hardware ist vorhanden, die Software installiert und die wichtigsten Dinge konfiguriert. Wer mindestens eine Quelle hinzugefügt hat, wird auch eventuell schon die Wiedergabe von Videos getestet haben. Es sollte alles einwandfrei funktionieren.

In diesem Teil möchte ich nun einige weitere Konfigurationen ansprechen. Diese betreffen die Remote-Steuerung mittels der iPad App und einige Addons, die das Leben etwas erleichtern. Gerade letzteres, die Addons, übernehme viele wichtigen Aufgaben bei Raspbmc. Viele sind schon vorkonfiguriert, so dass wir uns keine Gedanken um sie machen müssen. Andere installiere ich gerne zusätzlich.

Alles in allem keine großen Sachen, wenn man weiß, wo sich die Einstellungen verbergen und was sie konkret bedeuten.

Dieser Blogpost ist Teil einer Serie zum Thema “Raspberry Pi als Mediacenter mit Raspbmc. Im Rahmen dieser Serie sind die folgenden Teile erschienen. Der jeweils aktuelle Beitrag ist hervorgehoben.

  1. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Hardware)
  2. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Software)
  3. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration I)
  4. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Konfiguration II)
  5. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Performance)
  6. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Tipps & Tricks)
  7. Teil – Raspberry Pi als Mediacenter mit Raspbmc (Gesamtfazit)

Konfiguration II

Das Mediacenter, beziehungsweise die Software Raspbmc, ist ab jetzt so gut wie konfiguriert. Videos werden von diversen Quellen erkannt und auch abgespielt. Für ein Mediacenter sind das gute Nachrichten :). Um etwas haben wir uns aber noch nicht gekümmert.

Remote-Steuerung

Offizielles XBMC LogoDie Rede ist von der Bedienung des Mediacenters. Das ist auf verschiedene Arten möglich. Zum einen über die Fernbedienung des Fernsehers. Zumindest je nach Modell. Denn leider werden zwar eine Vielzahl von verschiedenen Geräten unterstützt, längst aber nicht alle. Das Zauberwort heißt hier HDMI-CEC. Dahinter verbirgt sich eine bidirektionale, also zweiseitige, Verbindung zwischen TV-Gerät und weiteren Consumer-Geräten. In diesem Fall der Raspberry Pi. CEC bedeutet ausgeschrieben Consumer Electronics Control. Unterstützt das TV-Gerät diesen Standard, ist die Wahrscheinlich sehr groß, dass das Mediacenter direkt über die Fernbedienung des Fernsehers mitgesteuert werden kann, was sehr komfortabel ist. Bei meinem Philips TV (7000 Series 42PFL7696K) ist das glücklicherweise der Fall. Dort firmiert diese Funktionalität zwar nicht unter HDMI-CEC sondern unter “EasyLink“, gemeint ist damit aber das selbe.

Die andere Möglichkeit der Steuerung des Mediacenters ist eine App auf einem Smartphone oder Tablet. Unterstützung gibt es hierbei sowohl für iOS als auch für Android. Bei Android ist es sogar möglich, einkommende Anrufe und Textnachrichten auf dem Fernsehgerät anzuzeigen. Aufgrund des Umfangs kümmern wir uns in diesem Beitrag um die Konfiguration der iPad-App. Im zweiten Teil haben wir diese bereits installiert.

Damit die App und unser Mediacenter überhaupt kommunizieren können, muss XBMC in Version 11 oder höher vorhanden sein. In diesem Fall ist das kein Problem, da wir den Raspberry Pi erst vor kurzem aufgesetzt haben. Wer aber noch eine ältere Installation sein Eigen nennt, muss gegebenenfalls updaten. Die Einstellungen auf Seiten des Raspberry Pi sind schnell gemacht. Abbildung 1 zeigt, wo es langgeht – und zwar bei dem Menüpunkt Dienste in den Einstellungen. Hinter diesem Menüpunkt verbergen sich eine Reihe von Optionen, die wir uns ansehen sollten. Direkt unter Allgemein, siehe Abbildung 2, sollte der Gerätename kontrolliert werden. Ich habe den Namen auf dem Standard XBMC gelassen, da das Mediacenter das einzige im Netzwerk ist. Hintergrund ist, dass viele Tools diesen Namen anzeigen, wenn die Installation automatisch erkannt wird. Bei mehreren Installationen von Raspbmc ist eine Unterscheidung also durchaus angebracht. Weiter geht’s mit Abbildung 3, in der die Einstellungen für den Webserver zu sehen sind. Dieser Webserver ist dafür verantwortlich, Befehle von außen, also auch von einem iPad oder ähnliches, anzunehmen und umzusetzen. Ohne diese Webserver läuft demnach gar nichts. Also bitte aktivieren und eine gute Benutzername/Passwort-Kombination ausdenken. Das ist wichtig, denn wirklich sicher ist der Webserver nicht. Der Raspberry Pi sollte daher nicht aus dem Internet erreichbar sein, beispielsweise indem er sich hinter einem Router mit Firewall befindet.

Abb. 1: Hauptmenüpunkt für die Einstellungen zur Remote-Steuerung. Abb. 2: Allgemeine Einstellungen zum Namen des Mediacenters. Abb. 3: Die Konfiguration des Webservers.

Damit sind die ersten Schritte gemacht. Nun müssen wir noch die allgemeine Fernsteuerung des Raspbmc erlauben. Abbildung 4 zeigt die dafür notwendigen Einstellungen im Menüpunkt Fernsteuerung. Lokale Programme bedeuten in diesem Kontext, dass auch Programme auf dem Raspberry Pi die Steuerung übernehmen dürfen. Entferne Programme sind genau das, was wir konfigurieren möchten. Nämlich externe Programme im gleichen Netzwerk wie auf einem Tablett oder Smartphone. Zu guter Letzt aktivieren wir noch die Zeroconf-Einstellung, wie in Abbildung 5 gezeigt, falls die Option nicht schon aktiviert ist. Dadurch können externe Programme die Konfiguration des Raspbmc herausfinden und sind schneller einsatzbereit. Wir müssen dann weniger manuell Einstellen, was den Komfort erhöht.

Abb. 4: Allgemeine Einstellungen zur Fernsteuerung. Abb. 5: Zeroconf Einstellung für die Weitergabe der Konfiguration.

Auf der Raspberry Pi-Seite sind wir fertig. Die oben beschriebenen Einstellungen ermöglichen eine Konfiguration von externen Geräten beziehungsweise ganz allgemein von Anwendungen.

Jetzt fehlen nur noch ein paar Schalter an der iPad App und die Fernsteuerung funktioniert. Abbildung 6 zeigt die Konfiguration für einen neuen XBMC-Server innerhalb der App. Dafür einfach unten neben dem Icon für den Ausschalter tippen und das Fenster öffnet sich. Dadurch, dass wir die Zeroconf-Einstellung aktiviert haben, vereinfacht sich diese Konfiguration. Die Schaltfläche “Finde XBMC” kann alle relevanten Einstellungen ermitteln. Wir müssen nur noch den Benutzernamen und das Passwort eingeben. Waren die Konfiguration und der anschließende Verbindungsaufbau erfolgreich, sollte sich das Bild aus Abbildung 7 ergeben.

Um die Daten in der iPad App zu aktualisieren, einfach den gewünschten Menüeintrag anwählen, beispielsweise TV-Serien, und dann in der Mitte von oben nach unten wischen, um die Synchronisation anzustoßen. Wenn dadurch noch nicht alles synchronisiert wurde, bitte mit den anderen Menüpunkten wiederholen. Hat alles funktioniert, werden die Filme, wie in Abbildung 8, beziehungsweise die Serien, wie in Abbildung 9, angezeigt. Jetzt steht dem Filmgenuss, gesteuert über die iPad App, nichts mehr im Wege :).

Abb. 6: Einstellungen für einen neuen XBMC Server in der iPad App. Abb. 7: Erfolgreiche Verbindung mit dem Mediacenter. Abb. 8: Übersicht aller Filme in der iPad App. Abb. 9: Übersicht aller TV-Serien in der iPad App.

Addons

Addons, beziehungsweise Plugins, wie sie auch genannt werden, sind ein Herzstück von Raspbmc. Viele Funktionen des Mediacenters basieren bereits auf Addons, die vorinstalliert sind, so dass wir uns als Anwender da gar keine Gedanken mehr zu machen müssen. Ein bekanntes Beispiel ist das Raspbmc Settings Addon, mit dem wir im ersten Teil zur Konfiguration die Einstellungen für den Raspberry Pi vorgenommen haben. Auch der Confluence Skin, der Bildschirmschoner und The Movie Database sind als Addons realisiert, um nur einige wenige zu nennen.

Abb. 10: Menüeintrag Addons im Hauptmenü der Einstellungen. Abb. 11: Optionen für Raspbmc-Addons. Abb. 12: Liste der aktivierten Addons.

Abbildung 10 zeigt den Menüeintrag für die Addons im Hauptmenü der Konfigurationen, zu erreichen über System | Einstellungen | Addons. Beim Öffnen erscheint die Auswahl aus Abbildung 11. Es gibt eine Liste von aktivierten und deaktivierten Addons. Zusätzlich können Addons aus einer zip-Datei aus einem lokalen Verzeichnis heraus installiert oder in einer Online-Quelle gesucht werden. Der Menüpunkt Aktivierte Addons führt zu einer recht großen Liste, die in Abbildung 12 zu sehen ist. Ich habe also sicherlich nicht untertrieben, als ich etwas weiter oben im Text kurz angerissen habe, dass viele Funktionen von Raspbmc auf Addons basieren.

Neben den bereits vorhandenen Addons gibt es einige, die ich immer wieder installieren würde, weil sie sehr nützliche, zusätzliche Funktionen bereitstellen. Beispielsweise das Video Addon der ARD Mediathek. Darüber besteht der komfortable Zugriff auf die Inhalte der Mediathek, ohne mit einem Browser hantieren zu müssen. In meinen Tests funktionierte der Zugriff recht gut. Hin und wieder war es leicht am Ruckeln. Ich kann allerdings nicht sagen, ob dass zu dem Zeitpunkt an meiner DSL-Leitung lag, am Addon oder an der Mediathek an sich. In diesem Beitrag möchte ich aber auf andere, aus meiner Sicht noch deutlich wichtigere Addons hinweisen.

Zunächst brauchen wir die Liste aller weiteren Addons. Aus Abbildung 10 kennen wir schon die vorhandenen Menüeinträge. Dort bitte den Eintrag Weitere Addons auswählen und dann die einzig vorhandenen Menüpunkt auswählen. Dahinter verbirgt sich das offizielle XBMC Addon-Repository. Also die Sammelstelle für alle möglichen Addons. Der Zugriff kann etwas dauern. Einfach Geduld haben :).

Ich installiere bei jedem Mediacenter auf jeden Fall zwei Addons. Einmal den Watchdog und das XBMC Backup. Erstgenanntes Addon befindet sich unter Dienste, letzteres unter Programm Addons. Abbildung 13 zeigt einen Screenshot, wie das Addon XBMC Backup heruntergeladen wird. Ist der Download komplett, kann der Eintrag zum Addon geöffnet und das Addon an sich konfiguriert werden, was Abbildung 14 zeigt. Ich habe das Addon so eingestellt, dass wöchentlich ein Backup in ein Verzeichnis meiner Netzwerkfestplatte kopiert wird. Damit sollte, so hoffe ich erst einmal, die Konfiguration des Mediacenters gesichert sein. Passiert mal etwas, spart mir das hoffentlich viel Zeit :). Allerdings muss ich auch noch mal das Rückspielen des Backups testen, was ich bisher noch nicht gemacht habe. Abbildung 15 zeigt abschließend noch den Eintrag des Watchdog Addons. Hier ist die Installation identisch. Zuerst herunterladen, dann konfigurieren und abschließend aktivieren. Dieser Watchdog sorgt dafür, dass die Datenbanken, beispielsweise für Filme und Serien, immer aktuell bleiben. Kopiere ich etwas in die entsprechenden Verzeichnisse der Netzwerkfestplatte, bemerkt dass der Watchdog und aktualisiert die Datenbanken, so dass das Mediacenter die Dateien direkt abspielen kann. Das ist sehr vorteilhaft und hat mir bisher gute Dienste geleistet.

Abb. 13: Download des Addons XBMC-Backup. Abb. 14: Konfiguration des XBMC-Backups. Abb. 15: Eintrag des Watchdog Addins, das bereits konfiguriert und aktiviert ist.

Das soll es beim Thema Addons erstmal gewesen sein. Natürlich gibt es noch viel mehr, die Vorgehensweise ist aber immer identisch: Addon auswählen, herunterladen, konfigurieren und aktivieren. Welche Addons für einen selbst wichtig sind, ist natürlich Geschmackssache. Am besten einfach mal die vorhandenen Möglichkeiten durchstöbern und das ein oder andere ausprobieren.

Zwischenfazit

Die tatsächlich notwendige Konfiguration haben wir schon im dritten Teil kennengelernt. Dieser Teil hat sich dagegen etwas mehr mit dem Komfort beschäftigt, denn zwingend erforderlich sind die genannten Einstellungen nicht. Aber sie erleichtern es doch enorm, mit dem Mediacenter zu interagieren.

Im kommenden Teil 5 geht es dann um die Performance des Mediacenters. Diese wird durch viele Faktoren beeinflusst. Einige davon möchte ich gerne erwähnen und zeigen, wie damit am besten umgegangen wird.

Jürgen Gutsch: Ionic – ein weiteres Framework für mobile Applikationen

Im Zuge eines Umbaus meines Mobile App CMS wurde es Zeit, sich eine alternative zu jQuery und jQueryUI umzuschauen. Das System läuft recht gut, allerdings gibt es mit jQueryUI  auf Windows Phone einen unschönen Effekt mit dem Footer. Zusätzlich sollte iOS besser unterstützt werden, was eine neue Version von Cordova erfordert. Da ich also das System eh anfassen musste, könnte ich es doch auch grad modernisieren.

Christian Weyers Vortrag auf der dotnet-Cologne 2014 brachte mich dazu einen genaueren Blick auf Ionic zu werfen.

Problem: Umlaute im Windows-Benutzernamen führen dazu, das bestimmte Tools und Frameworks wie z. B: NPM und Ruby nicht voll funktionieren. Speziell Linux basierte Tools die auf das Userverzeichnis zugreifen haben Probleme. Ich werde in Zukunft vermeiden meinen Namen mit Umlauten als Windowsbenutzername zu nutzen.

Was ist Ionic?

Im Grunde handelt es sich um ein CSS Framework mit JavaScript Erweiterungen, analog zu Twitters Bootstrap, allerdings nicht auf jQuery basierend, sondern auf Angular.JS. Auch ein Großteil der Markup-Codes wird mit Angular Direktiven geschrieben. Ionic ist vor allem dazu gedacht mobile Applikationen für Telefon und Tablet zu erstellen, da es allerdings komplett auf HTML5 basiert, kann es mit ein paar Anpassungen auch für eine mobile-fähige Web-App genutzt werden:

http://ionicframework.com/

Leider kann ich das System mit dem Build und der Cordova so wie es auf der Ionic-Website angeboten wird nicht voll nutzen. Das liegt tatsächlich an dem genannten Umlautproblem.

Also was tun?

Es bleibt also der klassische weg. CSS und JavaScripts herunterladen und manuell in eine HTML-Datei einbinden. Mit den ersten Spielereien ist dabei folgendes entstanden, das ich hier mal mit Chrome und IE vergleichend abfotografiert habe:

ionic1

Rechtes Seitenmenü
ionic2

Linkes Seitenmenü, z. B. mit Settings
ionic3

Modal Dialog der von unten hinein rutscht:
ionic4

Der Code?

Später mehr, aber hier ein paar Impressionen:

Das Side Menu Layout:

<body ng-controller="meinControler">
    <ion-side-menus>
        <ion-side-menu-content>
            <ion-header-bar class="bar-positive">
                <div class="buttons">
                    </button menu-toggle="left" class="button button-icon icon ion-navicon">
                </div>
                <h1 class="title">GUTSCH-ONLINE</h1>
                <div class="buttons">
                    </button menu-toggle="right" class="button button-icon icon ion-settings">
                </div>
            </ion-header-bar>
            <ion-content scroll="true" class="padding">
            …

Das linke Seitenmenu:

<ion-side-menu side="left">
    <ion-header-bar class="bar-dark">
        <h1 class="title">Inhalt</h1>
    </ion-header-bar>
    <ion-content scroll="true">
        <ul class="list">
            <li class="item">Blog</li>
            <li class="item">Vorträge</li>
            <li class="item">Fachartikel</li>
            <li class="item">Community</li>
            <li class="item">Projekte</li>
            <li class="item">Kontakt</li>
            <li class="item">Impressum</li>
        </ul>
    </ion-content>
</ion-side-menu>

Das Modele fenster wird als Angular-Template eingebunden:

<script id="searchModal.html" type="text/ng-template">
    <ion-modal-view>
        <ion-header-bar class="bar-positive">
            <h1 class="title">Suche</h1>
            </button class="button button-icon icon ion-close"
                  ng-click="closeSearch()">
        </ion-header-bar>
        <ion-content class="padding">
            <div class="list list-inset">
                <label class="item item-input"">
                    </i class="icon ion-ios7-search placeholder-icon">
                    <input type="search" placeholder="Search">
                </label>
            </div>
            <button class="button button-full button-positive">Suchen</button>
            …
       </ion-content>
    </ion-modal-view>
</script>

Die die erste Spielerei noch nicht so viel Logik enthält, beinhaltet der Controller nur den Code um das Modale Fenster zu starten und zu schließen:

ionicApp.controller('meinControler', function ($scope, $ionicModal) {
    $ionicModal.fromTemplateUrl('searchModal.html', {
        scope: $scope,
        animation: 'slide-in-up'
    }).then(function(modal) {
        $scope.searchModal = modal;
    });
    
    $scope.openSearch = function(){
        $scope.searchModal.show();
    };
    $scope.closeSearch = function(){
        $scope.searchModal.hide();
    };
});

Uli Armbruster: Bessere Enumerations in NET

Ist euch der Smell von typischen Enumerations auch schon in die Nase gestiegen? In diesem Webcast zeige ich eine Alternative zu den typischen Enums in NET. Damit können das Open Closed Principle und Separation of Concerns besser umgesetzt werden, was meiner Meinung nach zu einer höheren Kohäsion führt.

 

Weiterführende Links:

 

Wie haltet ihr es mit Enums? Arbeitet ihr schon auf diese Weise? Wollt ihr mehr Webcasts zu Clean Code?


Einsortiert unter:.NET Framework, Architecture, C#, Development, German Tagged: Clean Code, DDD, Video

codefest.at [MS]: Woher bekomme ich Grafiken und Sounds für mein Spiel?

Es gibt natürlich Programmierer, die gleichzeitig künstlerisch begabt und gut im Entwickeln sind. Aber für die meisten  Entwickler stellt sich bei der Spiele-Entwicklung immer die Frage, woher man gute Grafiken und Sounds für das Spiel bekommen soll.

Grafiken und andere Medienassets sind natürlich ein sehr essentieller Bestandteil eines Spiel. Durch die Assets kann ein Spiel mehr oder weniger feingeschliffen wirken. Wenn du weder einen Grafiker kennst, der deine genialen Ideen als Design verwirklicht, noch selbst gewandt in diesem Bereich bist, dann brauchst du nicht verzweifeln. Wir haben für dich eine Liste an freien Ressourcen für grafische und Sound Assets zusammengestellt, damit deinem Wahnsinnsspiel nichts mehr im Wege stellt.

Und wenn du deinem Spiel wirklich das gewisse Etwas verleihen willst, dann sind hier 10 Tipps, um ein Spiel auf’s nächste Level zu bringen.

ppedv Team Blog: Surface Pro 3 – perfekt für die Reise

Seit Kurzem darf auch ich ein Surface Pro 3 mein Eigen nennen. Aufgrund meines Jobs als CTO der ppedv bin ich häufig unterwegs. Ich bin in der glücklichen Position noch immer Trainings im SharePoint Development Umfeld zu halten. Wegen der häufigen Reisen habe ich es zu meinem Hobby gemacht, bei meinem Reisegepäck jedes mögliche Gramm Gewicht einzusparen.

Das Surface Pro 3 ist nun ein weiterer Schritt. Mein bisheriges Notebook, ein Lenovo 230, bleibt ab sofort zu Hause und ich bin nur noch mit dem Windows-Tablet, das mein Notebook ersetzen soll, unterwegs.

Mein Hauptthema ist SharePoint Development. Und gleich vorweg, einen SharePoint Server habe ich nicht am Surface installiert. Das wäre doch etwas übertrieben. Für meine Demos verwende ich einen Rechner, den ich in einem Rechenzentrum in Deutschland gemietet habe. Vom Surface aus greife ich nur per RDP zu. Damit ist das Thema Performance für mich auch schon erledigt. Mein Surface wird in der Schulung nur als RDP Client genutzt. (Wehe, es gibt keine Internet-Verbindung. Aber eine Backup-Versorgung in Form meines Nokia 630 Dual-Sim ist immer dabei.)

Videoausgang

Ohne Beamer ist bei mir keine Schulung möglich. Daher ist der Videoausgang für mich ein wichtiger Punkt. Das Surface bietet nur einen Mini-Displayport. Daher sind ab sofort 2 Adapter in meinem Reisegepäck. Einer für VGA und einer für HDMI. Es sind noch nicht alle Beamer in unseren 12 Standorten auf HDMI umgerüstet. Und selbst wenn wir diese ausgetauscht haben, kann ich den VGA-Adapter nicht zu Hause lassen. Ich kann nicht erwarten, dass jeder unserer Inhouse-Kunden einen HDMI Beamer hat.

Trotz dieser beiden Adapter ist mein Reisegepäck noch immer leichter als früher mit Notebook.

Ein zweiter Monitor

Ich bin ein großer Fan von zwei Monitoren. Der erste ist für die Teilnehmer und zeigt das aktuelle Schulungsgeschehen. Der zweite Monitor ist für firmeninterne Belange wie Email und Lync. Um auch unterwegs einen zweiten Monitor nutzen zu können, habe ich von Lenovo einen externen Monitor mit Touch-Funktionalität – ein tolles Gerät, das nur über USB 3 angeschlossen wird. Und hier ist der erste Kritikpunkt am Surface. Es hat nur einen USB 3 Port. Genau genommen benötige ich auch nicht mehr. Maus und externe Tastatur sind mittels Bluetooth angeschlossen. Dateitransfer per USB-Stick ist “retro”. Daher verteile ich meine Dateien per OneDrive.

Der einzige große Haken: der Monitor zieht mehr Strom als das Surface liefern möchte/kann. Sobald die Helligkeit des externen Monitors über 15 (auf einer 100-teiligen Skala) gestellt wird, geht der Monitor in Stromsparmodus, als wäre er abgesteckt worden. Damit kann man auch lustige Effekte erzielen: Die Einstellung auf 13, und dann Excel starten. Die große weiße Fläche benötigt wohl mehr Strom. Ergebnis: der Monitor geht offline. Excel wieder beenden und der Monitor wird wieder gefunden und das Notebook (Surface) schaltet auf Zwei-Monitor-Betrieb. Da ich aber auf diese Erlebnisse bei einer Schulung verzichten kann, habe ich mir einen USB 3 Hub mit Stromversorgung gekauft. Und wieder sind ein paar Gramm mehr in meinem Gepäck.

High Resolution-Anzeige

Das Surface arbeitet mit einer Auflösung von 2166 x 1440 Punkten. Das Bild ist toll und es ist ein Vergnügen mit dem Surface zu arbeiten - solange die Windows Symbole auf 150% Größe gestellt wurden. Und hier kommen zwei weitere Probleme auf mich zu.

Am externen Monitor wirkt 150% viel zu groß. Weniger als 150% kann ich aber am Surface nicht lesen. D.h. Fenster zwischen extern und intern hin-und herschieben ist nicht. Meine Lösung ist nun, am externen Monitor das RDP-Fenster anzuzeigen. Im virtuellen Rechner ist Normal-Größe eingestellt und somit passt die Auflösung wieder. Aber sobald ich das RDP-Fenster am internen Display anzeige, ist alles so klein, dass es für mich nicht mehr erkennbar ist.

Und damit zu Problem 2: wenn ich mit einer RDP-Verbindung am internen Display arbeite, muss ich im Remote-Rechner die Größe der Elemente auf 150% einstellen um damit arbeiten zu können. Da das Verstellen leider immer eine Neuanmeldung benötigt, muss ich mich zweimal anmelden bevor ich arbeiten kann. Wenn ich dann wieder bei einer Dockingstation mit “richtigen” Monitoren bin, darf ich wieder zweimal anmelden, da ich ja wieder alles zurückstellen muss.

Mobiles Arbeiten

Das war es aber auch schon mit meiner Kritik. Bisher habe ich mein Surface im Flugzeug und im Zug verwendet. Ich muss sagen, die Tastatur, das Typecover, ist fast so angenehm wie die vom Büro-PC. Normales Schreiben ist möglich. Im Flugzeug fällt nur auf, dass der Standfuß nicht weit nach hinten geklappt werden kann, da sich das Surface mit Tastatur und ausgeklapptem Standfuß auf dem Flugzeugtischchen nicht ausgeht. Klappe ich den Standfuß nicht so weit auf, dann ist das Display steiler und passt für mich nicht optimal. Da die Flugzeit nach Deutschland meist um die 60 Minuten liegt, kann ich damit leben.

Die Wärmeentwicklung des i5-Prozessors ist mir nicht negativ aufgefallen. Einzig während der Installation des Visual Studios wurde das Surface etwas wärmer. Aber das installiere ich (hoffentlich) nur einmal.

Tablet-Modus

In der Früh lese ich im Hotelzimmer immer gerne die Tageszeitung. Da ich diese mir nicht nachschicken lasse, lese ich die Online-Ausgabe am Tablet. Seit dem Surface bleibt mein Samsung Tablet zu Hause, da ich dieses nicht mehr benötige. Vom Surface kommt die Tastatur runter und ich lese im Hochformat Presse und Standard. Das neue Displayformat macht sich dabei wirklich bezahlt und ist sehr angenehm.

Fazit

Das Surface gebe ich nicht mehr her. Für meinen Einsatzbereich ist es optimal. Ein Windows-PC und ein Tablet in einem. Die wenigen Kompromisse gehe ich gerne ein, um das Gewicht meines Reisegepäcks zu optimieren.

ppedv Team Blog: SQL Azure Login failed for User..

This session has been assigned a tracing ID of 'f3254cff-3db3-46e6-b6d1-22cb065a633f'.  Provide this tracing ID to customer support when you need assistance.

Beinahe hätte ich zwei Azure-Experten verschlissen. Eine Website mit EF6 und ASP.NET Identity soll auf einer Azure Website gehostet werden. Visual Studio 2013 bietet dazu die Möglichkeit per veröffentlichen die Website per Click zu Azure zu deployen.

Die Anwendung wurde lokal entwickelt mit einer lokalen SQL Server Datenbank. Das Kopieren und Migrieren der Anwendung war nicht ganz problemlos. Es mussten sogar Änderungen am Code durchgeführt werden, weil die JSON Serialisierung auf Azure plötzlich nicht mehr funktionierte. (Lacyloading).

Die Connection Strings werden in der Datei Web.Config gespeichert. Hier wurden der Default Wert (DefaultConnection) für die ASP.NET Identity Datenbank (von mir aspnetdb genannt) und einer für die Anwendungsdaten. Der Wizard tauscht dann beim Deployment die Connection Strings aus. Damit nutzt man zur Laufzeit die Echtdaten. Das Schema ergänzt den Wert von Inital Catalog Projektnamen um _db für defaultConnection.

image

Als nächstes sollte man sich auf der bei Azure gehosteten Website anmelden können. Das funktionierte aber nicht. Seltsamerweise zeigt das Portal keine fehlerhaften Anmeldeversuche.

image

Die Lösung fand sich im Visual Studio Server Explorer. Dort gibt es einen Bereich für Azure, in dem man auch die Einstellungen zur Website vornehmen kann. Dort findet sich noch einmal die Verbindungszeichenfolge DefaultConnection mit dem Verweis auf die vorhin erwähnte Datenbank xxxx_db. Geändert, gespeichert - geht.

image

codefest.at [MS]: Spiele-Entwicklung mit Unity und Visual Studio 2013

Die Indie-Spieleentwicklung für die Microsoft Plattform hat mittlerweile auch schon eine längere Geschichte. Als damals das XNA Game Studio auf dem Markt erschienen ist, war das für alle Programmierer, die schon immer Ihr eigenes Spiel entwickeln wollten, sensationell. Monogame hat dann quasi die Weiterentwicklung, bzw. eher die Neuentwicklung von XNA fortgesetzt und hat es uns ermöglicht die Spiele mit Xamarin auch auf iOS und Android zu bringen. Tja, und was soll ich sagen, seit ca. 2 Jahren wird die Geschichte der Spieleentwicklung durch Unity quasi neu geschrieben.

Es macht unheimlichen Spaß sein eigenes Spiel mittels Unity zu entwickeln. Die Scripts wurden zu Beginn noch in JavaScript geschrieben, mittlerweile klappt das hervorragend in C#. Die IDE, die dafür verwendet wurde war bisher MonoDevelop. Das war schon sehr, sehr nett, allerdings ist es für einen eingefleischten C# Entwickler doch noch eine nette Zugabe, wenn das auch in und mit Visual Studio funktioniert.

Und was soll man noch mehr sagen? Das klappt. Dank Microsoft. Durch den Zukauf der Firma SyntaxTree, das ist jene Firma, die ein Produkt mit dem Namen UnityVS entwickelt hatte.

Und jetzt ist es soweit, Visual Studio Tools für Unity wurden durch eben diesen Zukauf von Microsoft released. Ein guter Grund sich das einmal genauer anzusehen. Ich dachte mir ich baue ein kleines Spielchen für zwischendurch.

Das Unity VS 2013 Spiel

Die Idee ist eigentlich recht einfach:

· Wir sehen einen Windows Store.
· Da regnet es Windows Phone’s vom Himmel herunter.
· Diese können mit einer Microsoft Tasse aufgefangen werden, das gibt dann Bonuspunkte.
· Aber leider fallen da auch „böse“ iPhones herunter, werden diese gefangen, dann werden natürlich Punkte abgezogen, da diese der Microsoft Tasse nun einmal gar nicht schmecken.

Probespielen ist jederzeit in eurem Browser möglich: http://hambogames.azurewebsites.net/phoneCatcher.html

image

Ich hoffe ich habe euch etwas neugierig gemacht? Nun denn, lasst uns loslegen.

Für diejenigen, die es gar nicht erwarten können, gibt es den Source Code hier zu finden:
https://github.com/BerndtHamboeck/PhoneCatcher

Implementierung

Um das kleine Spielchen mit mir „mitzuprogrammieren“ benötigt Ihre folgendes:

· Einen Rechner mit Visual Studio 2010, 2012, oder 2013(ich verwende 2013 Update 3).
· Und natürlich eine Installation von Unity, die Testversion erfüllt durchaus unsere Zwecke, diese bekommt Ihr hier: https://unity3d.com/unity/download, ich verwende in diesem Beispiel die Version 4.5.2.
· Visual Studio Tools für Unity von hier: http://unityvs.com/, diese bitte herunterladen und installieren.
· Da Unity einen älteren C#-Compiler verwendet benötigt Ihr auch den .NET Framework 3.5 (wichtig, falls Ihr schon unter Windows 8/8.1 entwickelt).

Das war es dann auch schon, wir können loslegen.

Notwenige Schritte

Damit ihr gleich einmal vorab sehen könnt, was euch in den folgenden Abschnitten erwartet hier eine kleine Zusammenfassung:

· Schritt eins:
o Erstellen des Unity Projektes
o Anlegen der Projektstruktur
o Importieren der Game-Sprites

· Schritt zwei:
o Aufbau der Spielansicht
   Hintergrund-Bild hinzufügen
   Microsoft-Tasse zum Auffangen hinzufügen
   Physik hinzufügen
o Erstes Scripting
   Konfiguration der Visual Studio 2013 Unity Integration
   Erstellen des C#-Scripts zum Bewegen der Tasse
   Implementieren des Scripts
   Debuggen mit Visual Studio 2013

· Schritt drei:
o Fallende Windows Phones und iPhones
o Auffangen der Game Sprites
o Zerstören gefangener, bzw. ‚verlorener‘ Game Sprites
o Re-Spawn neuer Telefone

· Schritt vier:
o Punkte für gefangene Windows Phones
o Abzüge für gefangene iPhones
o Ende des Spiels nach N-Sekunden
o Neustart des Spiels

Das klingt nach einer Menge Arbeit, ist aber mit etwas Geschick, und, falls Ihr Unity schon ein wenig kennt, in circa 2h zu schaffen. Bei Probleme könnt Ihr jederzeit im fertigen Source Code nachsehen.

Erstellen des Unity Projektes

Los geht’s, wir öffnen Unity um ein neues Spiel zu erstellen. Ich bin schon richtig aufgeregt, ich hoffe euch geht es genauso!

Dazu müssen wir:
· Unity öffnen
· Im Project Dialog von Unity ein neues Projekt erstellen mit folgenden Einstellungen
   o Project Location: C:\GameDev\PhoneCatcher
   o Setup Defaults for: 2D

imageimage

Die Einstellung für 2D ist von Vorteil, da es sich ja auch um ein 2D Spiel handeln wird und Unity einige Einstellungen dann bereits vorab für uns (und 2D) optimiert.

Sehr gut, das Projekt sollten wir also nun erstellt haben, als nächstes wollen wir die Dateistruktur anlegen und die Grafiken einbinden, die wir in diesem Spiel verwenden wollen.

Anlegen der Projektstruktur

Da wir einige Dateien im Zuge der Entwicklung des Spiels anlegen werden, empfiehlt es sich eine vernünftige Projektstruktur anzulegen. Wir benötigen in diesem Projekt folgende Ordner:

· Prefabs – wir lassen Objekte den Bildschirm herunter regnen. Diese haben nicht nur ein Aussehen, damit diese fallen können, müssen diese Objekte auch den Regeln der Physik gehorchen – also sprich: fallen. Und nicht nur das, wenn diese kollidieren, dann müssen wir reagieren (es gibt dann Punkte, oder eben nicht). Also lange Rede kurzer Sinn, was sind Prefabs? Objekte, die mehr können als nur hübsch aussehen, also zusammengesetzte Objekte, die wir als einzelnes (neues) Objekt verwenden können.

· Scenes – das sind die einzelnen Screens, die in dem Spiel verwendet werden. Wir erstellen dieses Mal nur einen Screen, aber falls weitere dazukommen, hat schon alles seine Ordnung.

· Scripts – Programmieren wird uns in diesem Spiel nicht erspart werden, und schließlich ist es ja genau das, was einem bei der Spiele-Entwicklung am meisten Spaß macht. Der Code, der plötzlich die „Puppen tanzen lässt“ (bei uns sind es aber Texturen von Mobiltelefonen).

· Sprites – Herr, lass Telefone regnen. Die wir auffangen wollen, ach und einen Hintergrund benötigen wir auch noch. Tja, und diese Texturen kommen in diesen Folder. Geht ganz einfach, machen wir dann gleich als nächstes.

Am Ende sollte das in der „Project“-Ansicht dann so aussehen:

image

Das Vorgehen ist immer das Gleiche, ich zeige es euch für den Sprites-Folder. Ihr klickt mit der rechten Maustaste auf Assets und wählt Create -> Folder.

image

Jetzt gebt Ihr den gewünschten Namen ein image. Das führt Ihr bitte für alle Folder aus, bis alle vorhanden sind. Den Sprites Folder wollen wir gleich einmal befüllen.

Importieren der Game-Sprites

Welche Texturen benötigen wir denn nun genau? Ich würde vorschlagen, wir verwenden für dieses Spiel folgende:

· „Gute“ Telefone, Windows Phones
· „Böse“ Telefone, iPhones
· Einen Becher, mit dem wir die Telefone fangen können
· Einen Hintergrund, damit das Ganze nicht so langweilig aussieht.

Ich habe für euch einige Texturen vorbereitet, wie Ihr weiter unten sehen könnt.

image

Ihr könnt diese aus dem Verzeichnis https://github.com/BerndtHamboeck/PhoneCatcher/tree/master/Assets/Sprites einzeln abspeichern, bzw. aus dem Zip von github herauskopieren. Wie auch immer ihr euch entscheidet, anschließend zieht ihr diese in den Sprites Folder, das müsste dann so aussehen:

image

Sehr gut, das Spiel nimmt langsam etwas Formen an, sicherheitshalber speichern wir die momentane (noch leere) „Scene“ gleich einmal ab, solltet Ihr eine kurze Pause benötigen, dann könnt Ihr das Projekt danach jederzeit wieder laden. Das geht ganz schnell, durch File -> Save Scene und wir geben dieser den Namen ‚Main‘. Sieht am Ende so aus:

image

Gut, jetzt wollen wir unsere Spielszene einmal mit Objekten bevölkern.

Aufbau der Spielansicht

Beginnen wir mit dem Einfügen der Microsoft Tasse. Dazu zieht ihr diese aus der Assets -> Sprites Folder Ansicht in die „Hierarchy“ Ansicht. In dieser Ansicht sind alle Objekte angezeigt, die in der momentanen Scene verwendet werden. Bisher ist dort nur die „Main Camera“ zu sehen.

Die Kamera ist dafür da, dem Spieler eure Szene zu zeigen. Dazu kann die Kamera statisch über der Szene angebracht sein (wie in diesem Spiel) oder z. B. einem Charakter folgen, wie das z. B. in einem Jump & Run der Fall wäre. In einer Szene können auch mehrere Kameras vorhanden sein, diese können auch gleichzeitig im Spiel angezeigt werden, wie das in einem Spiel mit Split-Screen der Fall wäre, oder z. B. in einem Rennspiel für eine kleine Übersichtskarte der Rennstrecke.

image

Die Kamera, ist nun nicht ideal positioniert, die Tasse sollte weiter unten zu sehen sein. Wir wollen die Positionierung dieser nun im „Inspector“ noch individuell anpassen. Und zwar wählen wir dafür die „Main Camera“ in der Hierarchy an und ändern die Y Position auf 4.5.

image

Im nächsten Schritt fügen wir das Hintergrundbild hinzu. Dazu ziehen wir wiederum aus Assets -> Sprites den Background in die „Hierarchy“ Ansicht.

image

Das Resultat ist, nun ja, nennen wir es, durchwachsen. Das Bild ist nicht ganz passend, darum sollten wir die Größe und Positionierung anpassen. Dazu gibt es 2 Möglichkeiten, die erste Variante ist, dass der Background Sprite angewählt wird und im Inspector der Wert „Pixels to Units“ angepasst wird. Achtung, erst nachdem Apply gedrückt wird, wird die Änderung sichtbar. Ihr könnt gerne mit den Werten experimentieren, 150 dürfte für unsere Belange genügen.

imageimage

Die zweite Variante wäre gewesen, das Background Objekt in der Scene anzuwählen und die Eigenschaften im Abschnitt „Scale“ anzupassen. Das ist nun nicht mehr notwendig könnt ihr aber ebenfalls gerne einmal ausprobieren. Ihr solltet die Position so anpassen, dass der Hintergrund passend in der Scene zu sehen ist.

image

Soweit so gut, jetzt ist allerdings unsere Tasse verschwunden. Wir sollten Unity mitteilen, in welcher Reihenfolge Objekte zu zeichnen sind. Dafür gibt es den „Sorting Layer“, der steht auf „Default“ (im oberen Bild sehr schön zu sehen), sowohl am Background Objekt, als auch an der Tasse. Um weitere Layer für die Sortierung einzufügen, klickt auf die kleinen Pfeilchen rechts neben Sorting Layer im Sprite Renderer und wählt „Add Sorting Layer“.

image

Wir benötigen zwei weitere Layer. Einen für den Hintergrund (das Hintergrundbild) und einen weiteren für den Vordergrund (die Tasse).

image

Sobald die beiden Layer angelegt wurden, sollten diese zugewiesen werden, dazu wählt ihr zuerst den Background an und weist den „Background“ Layer für die Eigenschaft Sorting Layer zu.

imageimage

Das Gleiche für die Tasse, allerdings den „Foreground“ Layer als Sorting Layer.

Physik ermöglichen

Damit sich Objekte physikalisch realistische verhalten können, steht in Unity für 2D Spiele die Rigidbody2D-Komponente zur Verfügung. Solche ‚gepimpten‘ Objekte sind in einer Szene nicht statisch, sondern fallen von oben nach unten, oder können durch Kollisionen, bzw. Scripte bewegt werden. Und das ist es eigentlich, was wir mit unserer Tasse machen wollen. Diese von links nach rechts bewegen, das herunterfallen müssen wir unterbinden, das bleibt dann später unseren Telefonen vorbehalten.

imageimageimage

Wir aktivieren die Eigenschaft „Is Kinematic“, diese deaktiviert die Physik des Rigidbodies, das Objekt kann nur noch über ein Script bewegt werden. Das ist genau was wir wollen, wir kümmern uns selbst um die Bewegung des Bechers, nämlich darf er sich nach links, oder rechts bewegen.

image

Der nächste Schritt ist nun das Script zu erstellen, welches auch wirklich die Bewegung ausführt.

Erstes Scripting mit Visual Studio 2013

Unity installiert mit MonoDevelop einen eigenen Code-Editor mit. Das ist an und für sich schon toll, wir wollen allerdings Visual Studio verwenden, dazu muss wie eingangs erwähnt Visual Studio Tools für Unity installiert sein, das war es aber noch nicht ganz. Es sind noch weitere Schritte notwendig.

Konfiguration der Visual Studio 2013 Unity Integration

Zuerst muss eine Plattform unter der das Spiel abläuft eingestellt werden, wo die Kommunikation zwischen Unity und dem Editor - also Visual Studio – reibungslos funktionieren kann, das ist als Plattform image. Der Web Player beispielsweise klappt nicht reibungslos, also führen wir diese Einstellungen gleich einmal durch, das macht Ihr über File->Build Settings und wählt PC, Mac & Linux Standalone, Target Plattform ‚Windows‘, aktiviert Development Build und Script Debugging. Abschließend schließt ihr einfach das Fenster.

imageimage

Im zweiten Schritt müsst Ihr das Visual Studio Unity Package installieren. Mit Unity Packages bietet Unity ein Werkzeug, um einzelne Dateien, Objekte, Texturen, bis hin zu ganzen Scenes zu bündeln, die man dann z. B. an jemanden versenden und dann wieder in ein anderes Projekt importieren kann. Und genau das haben die Kollegen von SynaxTree für uns getan, die Visual Studio Integration wird durch ein Unity Package unterstützt und dieses müssen wir zu unserem Projekt hinzufügen. Das geht mit Asset -> Import Package -> Visual Studio 2013 Tools, im neuen Fenster klickt Ihr auf Import.

imageimage

Das war es schon, ob es geklappt hat, sehen wir im nächsten Schritt, wenn wir ein Script erstellen und dieses sich in Visual Studio 2013 öffnen soll.

Skript erstellen

Das Script ist in Unity erst einmal nichts weiter als eine weitere Komponente. Ihr wählt also die Tasse an und drückt im Inspector wieder den imageButton. Die Komponente ist ein „New Script“ mit dem Namen MSCupLogoController und als Sprache verwenden wir CSharp (und nicht JavaScript).

imageimage

Ich würde euch empfehlen das Script in den Scripts-Folder mit Drag & Drop zu verschieben, das Script landet per Default im Assets Folder. Das sollte bei euch dann so aussehen, wie in dem folgenden Bild: Links ist der Scripts Folder angewählt, darin ist unser Script (mittlerer Pfeil) und rechts sieht man, dass das Script aktiv ist und der Tasse zugewiesen ist.

image

Nun wird es spannend, klickt mit der Maus doppelt auf das Script (mittlerer Pfeil). Wenn alles richtig konfiguriert ist, dann sollte sich Visual Studio mit dem von uns erstellten Script öffnen.

imageimage

Solltet Ihr diese Meldung sehen (nachfolgend), dann habt Ihr das Unity Package für Visual Studio nicht hinzugefügt, diese Meldung würde auch erscheinen, wenn Ihr ein anderes Unity Projekt – möglicherweise ein Beispielprojekt aus dem Internet, oder ein komplett neues (wie in meinem Fall auf dem Bild) – öffnet:

image

Die Integration mit Visual Studio könnt Ihr bei Bedarf auch wieder ausschalten, und zwar über das Menü Visual Studio Tools -> Configuration, dann wird wieder MonoDevelop als IDE verwendet.

imageimage

Ich gehe einmal davon aus, dass die Integration zwischen Unity und Visual Studio klappt und Ihr nun vor einem Script-Editor in Visual Studio sitzt. Ok, dann wollen wir die Tasse bewegen!

Implementieren des Scripts

In diesem Script werden wir zwei Methoden implementieren:

· Start – diese wird von Unity für jedes Objekt einmal aufgerufen, hier wollen wir uns die Bildschirmgröße merken, sowie die Breite der Tasse (das Script ist der Tasse zugewiesen, dadurch ist der Zugriff sehr einfach möglich) von der maximalen Breite abziehen. Warum? Erfahrt Ihr im nächsten Schritt.

· FixedUpdate – wird periodisch zu einem fixen Intervall aufgerufen und ist dafür gedacht physikalische Objekte anzupassen. Wir wollen die x-Achsenposition anpassen, passend zur Mausposition. Allerdings darf die Tasse dabei nicht aus dem Bild herausfallen, also die maximale Breite nicht über, bzw. unterschreiten (und darum das Abziehen von der Breite der Tasse, diese würde sonst aus dem Blickfeld des Spielers verschwinden).

Das Script sollte im Endeffekt so wie folgt aussehen, ich habe eine public Variable mit dem Namen cam eingefügt. Public Variablen können in Unity selbst, z. B. durch Drag & Drop zugewiesen werden. Ich benötige diese Variable eigentlich nicht (es ist die aktuelle Kamera), sie wird sich aber im nächsten Schritt als sehr nützlich erweisen.

using UnityEngine;
public class MSCupLogoController : MonoBehaviour
{ 
    public Camera cam;
    private float maxWidth;
    void Start ()
    {
        if (cam == null)
            cam = Camera.main;
 
        var corner = new Vector3(Screen.width, Screen.height, 0f);
        var targetWidth = cam.ScreenToWorldPoint(corner);
        float playerWidth = renderer.bounds.extents.x;
        maxWidth = targetWidth.x - playerWidth;
    } 
    void FixedUpdate ()
    {
        var currentPosition = cam.ScreenToWorldPoint(Input.mousePosition);
        float targetWidth = Mathf.Clamp(currentPosition.x, -maxWidth, maxWidth);
        var newPosition = new Vector3(targetWidth, 0f, 0f);
        rigidbody2D.MovePosition(newPosition);
    }
}

Ihr müsst in Visual Studio nichts kompilieren, sobald Ihr zu Unity zurück wechselt wird automatisch für euch übersetzt und etwaige Fehler werden sofort angezeigt. Ihr könnt auch z. B. in Unity kontrollieren, ob die public Variable cam im Editor auftaucht:

image

Ich hoffe euer Code ist fehlerfrei, denn wir wollen gleich einmal sehen, wie die Tasse über den Bildschirm gleitet (zumindest von links nach rechts).

Starten des Spiels

Am Besten versuchen wir es gleich einmal. Wechselt zurück zu Unity und drückt den Play Button.

image

Und es sollte losgehen (wobei das Ergebnis noch nicht wirklich den Anspruch erhebt ein Welthit zu werden). Die Ansicht wechselt auf „Game“ – von zuvor „Scene“. Mit der Maus könnt Ihr die Tasse von links nach rechts bewegen, diese fällt dabei nicht aus dem Bild (weder links, rechts, noch oben, oder unten).

image

Wichtig ist, dass Ihr nun keine Änderungen an Objekten vornehmt, da diese Änderungen nur während der Laufzeit Gültigkeit hätten. Das ist zwar praktisch, um Änderungen sofort im Spiel zu sehen, aber wie gesagt, diese würden verloren gehen, wenn ihr den Stopp Button drückt (der das Spiel beendet). Solltet ihr also etwas anpassen wollen, weil euch beim Testen des Spiels etwas auffällt, bitte immer zuerst den Stopp Button drücken und erst danach die Änderungen durchführen, dann bleiben diese natürlich erhalten.

Debuggen mit Unity

Visual Studio ist wie Ihr bestimmt wisst ein sehr mächtiges Werkzeug und eines der Stärken ist der eingebaute Debugger. Um diesen mit Unity zu nutzen, setzt Ihr am Besten einmal einen Breakpoint (die if-Abfrage für die cam Variable bietet sich an) und danach imagedrücken.

image

Nun wechselt ihr zurück zu Unity und drückt den Play Button.

image

Das Spiel startet und ihr läuft auf den Breakpoint, setzt das Programm fort (F5-Taste) und ihr könnt wieder die Tasse bewegen.

image

Die Tasse bewegt sich, jetzt wollen wir uns der herabfallenden Telefone widmen, diese müssen erzeugt, gefangen und zerstört werden.

Fallende Windows Phones und iPhones

Jetzt wollen wir einmal etwas “Action” in unser Spiel bringen. Dazu ziehen wir einmal eines der Telefone aus dem Assets->Sprites Folder auf den Hierarchy Bereich. Damit wird das Telefon zu unserer Spielscene hinzugefügt.

Ich habe im Inspector folgende Werte angepasst:

· Damit das Windows Phone am oberen Bildschirmrand angezeigt wird - Y: 8

· Die Textur der Telefone ist etwas zu gross, das wollen wir kleiner haben, ähnlich wie bei dem Hintergrund, dieses Mal aber mit der anderen Variante, nämlich durch setzen von Scale Y - Y: 0.75

· Das Telefon muss auf den richtigen Layer – so wie die Tasse zuvor, also Sorting Layer: Foreground

Jetzt müssen wir dem Telefon wieder das Fallen beibringen, also fügen wir wieder einen RigidBody 2D zu dem Telefon-Objekt hinzu. Wieder, so wie (zuvor an der Tasse) mit dem imageButton im Inspector am Telefon-Objekt.

imageimage

Am Besten ihr versucht gleich wieder einmal das Spiel zu starten, das Telefon wird herunterfallen, wenn ihr versucht das Telefon mit der Tasse zu fangen wird aber noch nichts passieren, das Telefon fällt vor eurer Tasse herunter, das sieht so aus, wie in dem Bild links, sollte aber so aussehen, wie im Bild rechts:

imageimage

Damit das Telefon hinter der Tasse erscheint, setzen wir den Wert an dem Tassen-Objekt für Order in Layer: 1

image

Auffangen der Game Sprites

Die Schwerkraft haben wir jetzt auch schon einmal in unserem Spiel kennen gelernt. Jetzt wollen wir Objekte miteinander kollidieren lassen. Und zwar unsere Telefone mit der Tasse, oder besser gesagt - in Unity-Sprache - zwei Rigidbodies, die aufeinanderstoßen (beim Auffangen, also wenn das Telefon in der Tasse verschwindet). Beim „Zusammenprall“ sollen diese ein physikalisch korrektes Kollisionsverhalten aufweisen, diese müssen, damit das in Unity klappt beide einen sogenannten Collider zugewiesen haben. Wir verpassen also erst einmal unserem Telefon einen Box Collider 2D– wieder mittels image- unter Physics 2D findet sich (unter anderem) der Box Collider 2D. Wenn das geklappt hat, erhält unser Telefon-Objekt in der Scene einen grünen Rahmen. Das passt hervorragend, da das genau der Bereich ist, bei dem eine Kollision mit einem anderen Objekt erkannt werden soll.

imageimageimage

Das war der erste, einfachere, Teil. Jetzt müssen wir der Tasse ebenfalls einen Collider zuweisen. Besser gesagt eigentlich zwei. Wenn das Telefon gefangen wird, dann wollen wir es ‚verschlucken‘, wenn das Telefon allerdings mit der Außenseite des Bechers getroffen wird, dann muss das Telefon abprallen.

Ein Box Collider 2D hilft uns in diesem Fall nicht weiter, wir benötigen eine andere Art von Collider, einen, den wir nach unseren Wünschen formen können. Einen Edge Collider 2D. Fügt diesen nun bitte wiederum mit image hinzu - unter Physics 2D findet ihr den Edge Collider 2D.

Dieser ist als grüne Linie an der Tasse zu sehen. Wenn ihr die Shift-Taste gedrückt haltet, dann könnt ihr den grünen Strich nach euren Wünschen „formen“. Der Collider sollte den Außenbereich der Tasse trapezförmig umschließen. Das erfordert ein klein wenig Geduld und etwas Übung, aber ich bin guter Dinge, dass das am Ende so aussieht, wie bei mir im rechten Bild.

imageimageimage

Am Besten ihr versucht das gleich wieder einmal, wenn ihr das Telefon mit der Aussenseite erwischt, dann müsste es (physikalisch korrekt) weggeschleudert werden. In dem nachfolgenden Bild habe ich die Tasse von rechts nach links verschoben und dabei das Telefon mit der Aussenkante erwischt, sodass diese nach links weggeschleudert wird.

image

Fügt danach noch einen zweiten Edge Collider 2D hinzu, an diesem aktiviert ihr „Is Trigger“, da dieser Collider für den Innenbereich der Tasse dient. Wenn ein Telefon mit diesem Edge Collider 2D kollidiert, dann soll ein Script ausgeführt werden, welches das gefangene Telefon zerstört.

image

Verbreitert den zweiten Edge Collider 2D etwas und schiebt ihn etwas höher. Solltet ihr Probleme haben mit dem Bearbeiten des zweiten Edge Colliders, dann könnt ihr den ersten einstweilen mit der Checkbox links oben deaktivieren.

image

Kollidieren und Fangen von Telefonen ist nun theoretisch möglich.

Zerstören gefangener Telefone

Jetzt benötigen wir ein neues Script. Wenn das Telefon gefangen wurde, soll es zerstört werden.

Also, wiederum ist der Button imageunser Freund und wir wählen Script mit dem Namen DestroyOnContact – ihr solltet das Script wieder in den Scripts-Folder verschieben, da es per Default unter Assets angelegt wird. Wichtig ist, dass das neue Script an der Tasse zu sehen ist.

image

Fehlt nur noch der Code, der ist recht kurz gehalten, da Unity die komplette Arbeit für uns erledigt. Durch das Anwählen der „Is Trigger“ CheckBox am Edge Collider 2D wird das Script aufgerufen – genauer die OnTriggerEnter2D Methode. Praktischerweise bekommen wir auch das Objekt, das mit der Tasse zusammenstößt, unser Telefon, mitgeliefert. Dieses wird kurzerhand aus dem Spiel genommen.

using UnityEngine;
using System.Collections;
 public class DestroyOnContact : MonoBehaviour {
     void OnTriggerEnter2D(Collider2D second)
    {
        Destroy(second.gameObject);
    }
}

Das solltet ihr gleich wieder „Probespielen“. Gefangene Telefone müssen sich jetzt in Luft auflösen. Langsam wird es ja ein richtiges Spiel. Wir haben allerdings noch ein Problem zu lösen. Was passiert mit dem Telefon, wenn es nicht gefangen wird?

Zerstören verpasster Telefone

Nun, nicht gefangene Telefone fliegen unendlich lange, immer weiter und weiter. Das ist natürlich nicht gut, denn wenn wir viele Telefone erzeugen würden – wir wollen schließlich noch mehr als ein Telefon auffangen, es soll ja ein richtiges Spiel werden – würden wir eine Menge Speicher und Ressourcen für die Kalkulation der unendlich fallenden Game-Objekte verbraten.

Wir sind uns also einig, dass verfehlte Telefone zerstört werden müssen. Dazu fügt ihr ein leeres Game-Objekt ein. Das ist ein beliebter Trick in Unity, wenn man nicht sichtbare Objekte in seinem Spiel benötigt, oder Objekte gruppieren möchte. Eingefügt wird es über das Menü GameObject und Create Empty.

image

Ändert den Namen von imageauf imageund weist ihm einen Edge Collider 2D zu, wiederum mit der Eigenschaft „Is Trigger“ aktiviert. Ausserdem zieht ihr das zuvor erstellte Script DestroyOnContact aus dem Asset->Scripts Folder auf das Cleanup-Objekt, da wir dieses Script gleich wiederverwenden wollen (es funktioniert tadellos, also warum ein neues Script schreiben).

image

Soweit so gut, der Edge Collider 2D gehört noch angepasst, dieser sollte außerhalb, mit einem gewissen Respektabstand zur eigentlichen Spielfläche platziert werden - dem Spieler soll hier gar nicht auffallen, dass wir die Telefone zerstören. Wir benötigen den Edge Collider 2D links, unterhalb und rechts der Spielfläche, da das Telefon ja abprallen kann und relativ weit weggeschleudert werden könnte (darum ist der Edge Collider 2D links und rechts auch etwas höher als das Spielfeld). Das sollte im Endeffekt dann ungefähr so aussehen:

image

Wenn ihr das Spiel wieder startet und das Telefon nicht auffängt, dann fällt es zwar aus dem Schirm, kollidiert aber mit dem neuen Edge Collider 2D und wird zerstört. Das wird ersichtlich, wenn ihr die Hierarchy-Ansicht beobachtet, dort verschwindet das Telefon-Objekt, sobald es zerstört wurde.

Re-Spawn neuer Telefone

Ein einzelnes Telefon, welches eingefangen werden kann ist nicht gerade ein spektakuläres Spiel. Es soll mehrere Telefone in verschiedenen Abständen „vom Himmel regnen“. D. h. wir müssen unser Telefon mehrmals erzeugen. Um ein Objekt in einem Spiel mehrfach nutzen zu können, stellt Unity sogenannte Prefabs zur Verfügung. Ein Prefab stellt ein beliebiges, möglicherweise aus mehreren Komponenten zusammengesetztes Objekt dar. Das klingt ganz nach dem Telefon-Objekt, welches wir bereits erstellt haben, also erstellen wir ein „Prefab“ aus unserem Telefon. Dazu zieht ihr das Telefon aus der Hierarchy-Ansicht in den Prefabs-Folder.

image

Fertig, wir haben nun ein Prefab, welches alle Eigenschaften unseres Telefons aufweist, dieses können wir beliebig oft erzeugen. Das Telefon-Objekt in der Hierarchy-Ansicht sollte übrigens weggelöscht werden, da wir dieses nicht mehr benötigen – wir haben nun das Prefab-Objekt, welches wir in unserem Script „on-the-fly“ erzeugen werden. Um das bewerkstelligen zu können, benötigen wir wiederum ein leeres Game-Objekt, dem wir den Namen GameController vergeben und ein neues Script mit dem Namen GameController mittels imagezuweisen. Nicht zu vergessen ist die Y-Position von 9, da im folgenden Script zwar die X-Position zufällig – innerhalb der erlaubten Grenzen – bestimmt wird, die Y-Position aber vom GameController verwendet wird und diese außerhalb des Bildschirms liegen sollte, damit die Telefone in den Bildschirm fliegen.

image

Dieses neue Script hat als Herzstück die Spawn Methode, diese instanziiert neue Telefone und zwar im Intervall zwischen ¼ Sekunde und ½ Sekunde.

using UnityEngine;
using System.Collections;
public class GameController : MonoBehaviour
{
    public Sprite[] sprites;
    public Camera cam;
    public GameObject phone;
private float maxWidth;
public float timeLeft = 30;
    void Start()
    {
        if (cam == null)
            cam = Camera.main;
        var corner = new Vector3(Screen.width, Screen.height, 0f);
        var targetWidth = cam.ScreenToWorldPoint(corner);
        float phoneWidth = phone.renderer.bounds.extents.x;
        maxWidth = targetWidth.x - phoneWidth;
        StartCoroutine(Spawn());
    }
 
    IEnumerator Spawn()
    {
        yield return new WaitForSeconds(2f);
        while (timeLeft > 0)
        {
            var spawnPosition = new Vector3(
                Random.Range(-maxWidth, maxWidth), transform.position.y, 0f);
            var spawnRotation = Quaternion.identity;
            Instantiate(phone, spawnPosition, spawnRotation);
            var spriteNum = Random.Range(0, sprites.Length - 1);
            phone.GetComponent<SpriteRenderer>().sprite = sprites[spriteNum];
            yield return new WaitForSeconds(Random.Range(0.25f, 0.5f));
        }
        yield return new WaitForSeconds(2f);
    }
}

Nun müssen alle Variablen in Unity zugewiesen werden:

· Sprites haben wir insgesamt 9 Stück – 6 Windows Phones, 3 iPhones
· Phone ist unser erstelltes Prefab

Die Variablen können durch Drag & Drop zugewiesen werden. Die Elemente 0 – 8 für die Sprites kommen aus dem Sprites-Folder. Achtet bitte darauf, dass die ersten drei Sprites die iPhones sind, das wird sich später bei der Punkte-Vergabe als hilfreich erweisen.

image

Der Phone Variable wird das Prefab, ebenfalls durch Drag & Drop zugewiesen:

image

Tja, was soll ich sagen, wir sollten das Spiel wieder einmal testen. Jetzt ist es ja auch fast schon ein richtiges Spiel, in unregelmäßigen Abständen fällt ein neues Telefon „vom Himmel“, welches wir mit der Tasse fangen können.

Spiel-Anzeigen und Neustart

Bisher ist es noch ein „Endlosspiel“, das heißt ihr könnt so lange spielen, bis ihr einfach keine Lust mehr habt. Das ist, nun ja, „nett“, und was noch dazu kommt, es gibt keinerlei Punkte für gefangene Windows Phones und keine „Schlechtpunkte“ für gefangene iPhones. Also ich finde, das sollten wir ändern.

Wir bauen zuerst die Anzeigen ein, die wir benötigen:

· Eine Anzeige für die verbleibende Zeit.
· Eine weitere Anzeige für die erzielten Punkte.
· Die verbleibende Spielzeit soll ebenfalls angezeigt werden.
· Abschließend noch eine weitere für einen „Game Over“-Text.

Das Ganze soll also zu einem richtigen Spiel „wachsen“ und sollte ungefähr so aussehen:

image

Dazu benötigen wir 4 neue Game Objekte und zwar vom Typ „GUI Text“. Diese fügt ihr mit Create -> GUI Text im Hierarchy Fenster hinzu (oder über das Menü GameObject->Create Other-> GUI Text).

imageimage

Das Ganze macht ihr somit insgesamt 4 Mal und gebt den Objekten bitte sprechende Namen, ich habe mich für die Namen: Timer Info, Score Info, GameOver Info und Restart Info entschieden.

image

Die Einstellungen für die ersten Beiden (Timer Info und Score Info) sind relativ simpel, ein vernünftiger Text und die richtige Platzierung und es ist geschafft. Einen Vorschlag könnt ihr untenstehend sehen.

imageimage

Ähnlich verhält es sich mit dem GUI Text für das GameOver Info Objekt. Zusätzlich wird dies noch unsichtbar geschaltet, da es erst sichtbar sein soll, wenn das Spiel auch tatsächlich zu Ende ist.

Genauso ist es bei dem GUI Text Restart Info Objekt, hier wird zusätzlich zum unsichtbar schalten noch ein weiteres Script benötigt – mit dem Namen Restart - mit dem das Spiel gestartet werden kann (nämlich dann, wenn der Text sichtbar ist und der Spieler auf dieses Objekt klickt).

imageimage

Das Restart-Script lädt den aktuellen Level erneut, dadurch werden alle Werte zurückgesetzt und der Spass kann von neuem beginnen.

using UnityEngine;
public class Restart : MonoBehaviour {
    void OnMouseDown()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

Punkte-Vergabe

In diesem Spiel soll es Punkte für gefangene Windows Phones geben, nämlich genau einen, allerdings auch einen Punkteabzug, wenn ein iPhone in der Tasse landet. Dazu fügen wir ein Script mit dem Namen Score unserer Tasse hinzu.

imageimage

In diesem Skript wird jedes Mal, wenn der Trigger an dem Edge Collider 2D ausgelöst wird festgestellt, ob es ein „gutes“ Telefon ist, oder ein „böses“ Telefon. Nur der „innere“ Edge Collider 2D löst an der Tasse den Trigger aus, also sind das wirklich nur gefangene Telefone, nicht diejenigen die einfach nur an der Tasse abprallen. Je nachdem, werden dann Punkte aufaddiert, oder abgezogen und die Anzeige aktualisiert. Dazu gibt es eine public Variable mit dem Namen scoreText.

using UnityEngine;
public class Score : MonoBehaviour
{
    public GUIText scoreText;
    public int catchValue = 1;
    private int score = 0;
    void Start()
    {
        score = 0;
        UpdateScore();
    }
    void OnTriggerEnter2D(Collider2D second)
    {
        Debug.Log("Tag on trigger: " + second.tag);
        if (second.tag == "Good")
            score += catchValue;
        else
            score -= catchValue;
        UpdateScore();
    }
    private void UpdateScore()
    {
        scoreText.text = "Score: " + score.ToString();
    }
}
Diese wird mit dem GUI Text Score Info Objekt – wiederum in Unity - verbunden.

image

Die Tags, die in dem Script verwendet werden, müssen allerdings noch definiert werden, dazu ist unser Prefab anzuwählen und die ComboBox für die Tags herunterzuklappen und „Add Tag…“ anzuwählen. Die beiden Tags, die wir benötigen sind: Good und Bad.

image

Jetzt müssen wir beim instanziieren eines neuen Telefons noch den Good/Bad Tag setzen. Wenn die Nummer in unserem Sprite-Array für die Telefone kleiner als 3 ist, dann ist es ein iPhone (Bad), ansonsten ein Windows Phone (Good). Dazu reicht eine Zeile Code im GameController Script in der Spawn Methode.

phone.GetComponent<SpriteRenderer>().sprite = sprites[spriteNum];
phone.tag = spriteNum < 3 ? "Bad" : "Good";
yield return new WaitForSeconds(Random.Range(0.25f, 0.5f));

Ich würde vorschlagen, dass jetzt wieder eine Runde probe spielen angesagt wäre. Schließlich gibt es jetzt schon Punkte abzustauben!

Ende des Spiels nach N-Sekunden

Das Spiel sollte nach, nun sagen wir einmal, 30 Sekunden beendet werden. Sobald das Spiel zu Ende ist, werden die beiden GUI Text Objekte GameOver Info und Restart Info eingeblendet. Dazu müssen wir unser GameController-Script erweitern.

using UnityEngine;
using System.Collections;
public class GameController : MonoBehaviour
{
    public Sprite[] sprites;
    public Camera cam;
    public GameObject phone;
    private float maxWidth;
    public float timeLeft = 30;
    public GUIText timerText;
    public GUIText gameOverText;
    public GUIText restartText;
    void Start()
    {
        if (cam == null)
            cam = Camera.main;
        var corner = new Vector3(Screen.width, Screen.height, 0f);
        var targetWidth = cam.ScreenToWorldPoint(corner);
        float phoneWidth = phone.renderer.bounds.extents.x;
        maxWidth = targetWidth.x - phoneWidth;
        StartCoroutine(Spawn());
        UpdateTimerText();
    }
    void FixedUpdate()
    {
        timeLeft -= Time.deltaTime;
        if (timeLeft > 0)
            UpdateTimerText();
    }
 
    private string UpdateTimerText()
    {
        return timerText.text = "Time Left: " + 
                Mathf.RoundToInt(timeLeft).ToString();
    }
 
    IEnumerator Spawn()
    {
        yield return new WaitForSeconds(2f);
 
        while (timeLeft > 0)
        {
            var spawnPosition = new Vector3(
                Random.Range(-maxWidth, maxWidth), transform.position.y, 0f);
            var spawnRotation = Quaternion.identity;
 
            Instantiate(phone, spawnPosition, spawnRotation);
            var spriteNum = Random.Range(0, sprites.Length - 1);
            phone.GetComponent<SpriteRenderer>().sprite = sprites[spriteNum];
            phone.tag = spriteNum < 3 ? "Bad" : "Good";
            yield return new WaitForSeconds(Random.Range(0.25f, 0.5f));
        }
        yield return new WaitForSeconds(2f);
        gameOverText.enabled = true;
        restartText.enabled = true;
    }
}
Fast geschafft, die drei neuen public Variablen wollen noch in Unity durch Drag & Drop befüllt werden.

image

Das war’s das Spiel ist fertig und wartet nur darauf von euch gespielt zu werden!

Zusammenfassung

Die Spiele-Entwicklung mit Unity macht einen Riesenspaß. Die Erfolge stellen sich sehr schnell ein. Mit Visual Studio 2013 ist es noch einmal einen Tick einfacher (für C#- Entwickler) geworden Spiele zu entwickeln. Ich bin gespannt, ob es euch gelingt einen Welthit mit dieser fantastischen Entwicklungs-Kombi zu programmieren. Ich wünsche euch auf jeden Fall alles Gute und viel Spaß mit der Entwicklung eures Spiels!


Berndt Hamböck ist seit 2007 MCT, darüber hinaus befasst er sich mit Lösungen für komplexe Anwendungsszenarien mit den neuesten Microsoft Technologien. Die Erfahrungen aus der Projektarbeit gibt er in Vorträgen und Trainings weiter und begleitet Entwicklerteams in Softwareunternehmen bei Projekten im Microsoft Umfeld.

Das ist ein Gastbeitrag. Die Meinung des Autors muss sich nicht mit jener von Microsoft decken. Durch den Artikel ergeben sich keinerlei Handlungsempfehlungen. Microsoft übernimmt keine Gewähr für die Richtigkeit oder Vollständigkeit der Angaben.

Stefan Henneken: IEC 61131-6: Abstract Factory

Sollen Instanzen eines Funktionsblocks anlegt werden, so muss vor dem Compilieren der genaue Typ des Funktionsblocks bekannt sein. Durch diese feste Zuordnung kann das Verhalten einer Anwendung nur schwer erweitert werden. Dieses ist z.B. der Fall, wenn sich der Funktionsblock in einer Bibliothek befindet und somit der Zugriff auf den Quellcode nicht möglich ist. Die Instanz-Variable ist fest an einen bestimmten Typ gebunden. Eine Klassenfabrik kann helfen diese starren Strukturen aufzubrechen.

Der Begriff Klassenfabrik bezeichnet in der objektorientierten Programmierung ein Objekt, welches andere Objekte erzeugt. Es gibt verschiedene Arten eine Fabrik umzusetzen. Eine davon ist die abstrakte Fabrik, die in dem folgenden Beispiel zum Einsatz kommt. Als Beispiel wird eine kleine SPS-Bibliothek zum Loggen von Meldungen erstellt. Eine abstrakte Klassenfabrik ermöglicht es dem Anwender, den Funktionsumfang der Bibliothek anzupassen, ohne Änderungen an den Sourcen durchführen zu müssen.

Variante 1: einfacher Funktionsblock

Der erste (naheliegende) Schritt besteht darin, einen Funktionsblock für das Loggen der Meldungen zu entwickeln. Hierbei nimmt die Methode Write() den Text entgegen und der Baustein schreibt die Meldung in eine Textdatei.

Sample01

Außerdem erweitert die Methode Write() den Text um das Wort Logger. Zur Kontrolle wird der gesamte Text zurückgegeben.

METHOD PUBLIC Write : STRING
VAR_INPUT
    sMsg    : STRING;
END_VAR

sMsg := CONCAT('logger: ', sMsg);
// open file
// write the message into the file
// close file
Write := sMsg;	

Die Anwendung des Bausteins sieht recht einfach aus.

PROGRAM MAIN
VAR
    fbLogger     : FB_Logger();
    sRetMsg      : STRING;
END_VAR

sRetMsg := fbLogger.Write('Hello');

Möchte der Anwender jedoch statt einer einfachen Textdatei wahlweise eine csv- oder xml-Datei nutzen, muss der Entwickler den Baustein erweitern.

Variante 2: Funktionsblock mit Funktionsauswahl

Ein möglicher Ansatz besteht darin, über die Methode FB_Init() jeder Instanz von FB_Logger einen Dateipfad mitzugeben, der festlegt, in welcher Datei die Meldungen gespeichert werden. Die Dateiendung dient hierbei als Kennung des Dateiformat.

Die Methode FB_init() erhält neben den beiden impliziten Parameter bInitRetains und bInCopyCode den zusätzlichen Parameter sFilename.

METHOD FB_init : BOOL
VAR_INPUT
    bInitRetains  : BOOL;
    bInCopyCode   : BOOL;
    sFilename     : STRING;
END_VAR

sFilenameExtension := F_ToLCase(RIGHT(sFilename, 3));

Die Dateiendung wird in der Variablen sFilenameExtension abgelegt.

FUNCTION_BLOCK PUBLIC FB_Logger
VAR
    sFilenameExtension : STRING;
END_VAR

In der Methode Write() differenziert eine IF-Anweisung die verschiedenen Varianten und ruft jeweils die passende private Methode auf. Dadurch ist der Funktionsblock in der Lage die Meldungen in unterschiedliche Dateiformate abzulegen.

METHOD PUBLIC Write : STRING
VAR_INPUT
  sMsg    : STRING;
END_VAR

sMsg := CONCAT('logger: ', sMsg);
IF (sFilenameExtension = 'txt') THEN
    Write := WriteTxt(sMsg);
ELSIF (sFilenameExtension = 'csv') THEN
    Write := WriteCsv(sMsg);
ELSIF (sFilenameExtension = 'xml') THEN
   Write := WriteXml(sMsg);
END_IF

Somit erhält FB_Logger fünf Methoden.

Sample02

FB_init() wird automatisch aufgerufen, wenn eine Instanz von FB_Logger angelegt wird. In diesem Beispiel somit beim Starten des Programms. Die Methode kann durch eigene Parameter erweitert werden, diese werden beim Deklarieren einer Instanz mit übergegeben.

WriteTxt(), WriteCsv() und WriteXml() wurden als private Methoden deklariert und sind somit nur innerhalb von FB_Logger aufrufbar.

Write() ist die Methode, die der Anwender von FB_Logger zum Schreiben der Meldungen nutzen kann.

Das Ergebnis ist ein Funktionsblock, der intern alle notwendigen Fälle abdeckt. Der Anwender kann beim Anlegen der Instanz die gewünschte Arbeitsweise durch den Dateinamen vorgeben.

PROGRAM MAIN
VAR
    fbLoggerTxt    : FB_Logger('File.csv');	
    sRetMsg        : STRING;
END_VAR

sRetMsg := fbLoggerTxt.Write('Hello');

Doch mit jeder weiteren Speicherart, wird der Baustein größer und belegt mehr Programmspeicher. Werden die Meldungen in eine csv-Datei geschrieben, so wird der Programmcode für die txt-Datei und xml-Datei mit in den Programmspeicher geladen, obwohl dieser nicht benötigt wird.

Variante 3: Funktionsblock mit dynamischer Instanziierung

Hierbei ist das Konzept der dynamischen Speicherverwaltung hilfreich. Dabei werden Instanzen von Funktionsblöcken zur Laufzeit angelegt. Um das bei unserem Beispiel nutzen zu können, werden die Methoden WriteTxt(), WriteCsv() und WriteXml() in separate Funktionsblöcke ausgelagert. Somit hat jede Variante seinen eigenen Funktionsblock, der die Methode Write() enthält.

METHOD PUBLIC Write : STRING
VAR_INPUT
    sMsg    : STRING;
END_VAR

Write := CONCAT('txt-', sMsg);
// open txt file
// write the message into the txt file
// close txt file

Der Operator __NEW() erhält als Parameter einen Standard-Datentypen, allokiert den notwendigen Speicher und liefert einen Zeiger auf das Objekt zurück.

pTxtLogger := __NEW(FB_TxtLogger);

pTxtLogger ist ein Zeiger auf FB_TxtLogger.

pTxtLogger : POINTER TO FB_TxtLogger;

Wurde __NEW() erfolgreich ausgeführt, so ist der Zeiger ungleich 0.

In der Methode FB_init() kann jetzt direkt eine Instanz des gewünschten Funktionsblocks dynamisch angelegt werden. Dadurch ist es nicht mehr notwendig, von allen möglichen Funktionsblöcken eine Instanz statisch anzulegen.

Um den Zugriff auf die Methode Write() des jeweiligen Logger-Bausteins zu vereinfachen, wird das Interface ILogger definiert. FB_TxtLogger, FB_CsvLogger und FB_XmlLogger implementieren diese Schnittstelle.

Zusätzlich zu den drei Zeigern auf die drei möglichen Funktionsblöcke enthält FB_Logger eine Variable vom Type ILogger.

FUNCTION_BLOCK PUBLIC FB_Logger
VAR
    pTxtLogger   : POINTER TO FB_TxtLogger;
    pCsvLogger   : POINTER TO FB_CsvLogger;
    pXmlLogger   : POINTER TO FB_XmlLogger;
    ipLogger     : ILogger;
END_VAR

In FB_init() wird die jeweilige Instanz des Funktionsblocks angelegt und dem entsprechenden Zeiger zugewiesen.

METHOD FB_init : BOOL
VAR_INPUT
    bInitRetains : BOOL;
    bInCopyCode  : BOOL;
    sFilename    : STRING;
END_VAR
VAR
    sFilenameExtension : STRING;
END_VAR

sFilenameExtension := F_ToLCase(RIGHT(sFilename, 3));
IF (sFilenameExtension = 'txt') THEN
    pTxtLogger := __NEW(FB_TxtLogger);
    ipLogger := pTxtLogger^;
ELSIF (sFilenameExtension = 'csv') THEN
    pCsvLogger := __NEW(FB_CsvLogger);
    ipLogger := pCsvLogger^;
ELSIF (sFilenameExtension = 'xml') THEN
    pXmlLogger := __NEW(FB_XmlLogger);
    ipLogger := pXmlLogger^;
ELSE
    ipLogger := 0;
END_IF

In Zeile 14, 17 und 20 wird der Variablen ipLogger der dynamisch angelegte Funktionsblock zugewiesen. Das ist möglich, da alle Funktionsblöcke das Interface ILogger implementieren.

Die Methode Write() von FB_Logger greift über ipLogger auf die Methode Write() von FB_TxtLogger, FB_CsvLogger oder FB_XmlLogger zu:

METHOD PUBLIC Write : STRING
VAR_INPUT
    sMsg    : STRING;
END_VAR

IF (ipLogger <> 0) THEN
    Write := ipLogger.Write(CONCAT('logger: ', sMsg));
END_IF

So wie FB_init() jedes Mal beim Anlegen eines Funktionsblocks aufgerufen wird, wird FB_exit() beim Löschen dementsprechend einmalig durchlaufen. In dieser Methode sollte der Speicher, der zuvor mit __NEW() allokiert wurde, mit __DELETE() wieder freigegeben werden.

METHOD FB_exit : BOOL
VAR_INPUT
    bInCopyCode : BOOL;
END_VAR

IF (pTxtLogger <> 0) THEN
    __DELETE(pTxtLogger);
    pTxtLogger := 0;
END_IF

IF (pCsvLogger <> 0) THEN
    __DELETE(pCsvLogger);
    pCsvLogger := 0;
END_IF

IF (pXmlLogger <> 0) THEN
    __DELETE(pXmlLogger);
    pXmlLogger := 0;
END_IF

Das UML-Diagramm des Beispiels sieht wie folgt aus:

Picture03

Somit besteht das Beispiel aus vier Funktionsblöcken und einem Interface.

Sample03

Die Schnittstelle ILogger vereinfacht die Entwicklung von weiteren Varianten. Allerdings ist darauf zu achten, dass der neue Funktionsblock das Interface ILogger implementiert und die Methode FB_init() im Funktionsblock FB_Logger eine Instanz des neuen Funktionsblocks anlegt. Die Methode Write() von FB_Logger muss hierbei nicht angepasst werden.

Beispiel 1 (TwinCAT 3.1)

Variante 4: abstract Factory

Beim Anlegen einer Instanz von FB_Logger wird durch die Dateiendung festgelegt, in welchem Format Meldungen geloggt werden. Bisher konnte zwischen txt-Datei, csv-Datei und xml-Datei gewählt werden. Sollen weitere Varianten hinzukommen, so muss weiterhin der Funktionsblock FB_Logger angepasst werden. Besteht kein Zugriff auf den Quelltext, so ist eine Erweiterung von FB_Logger nicht möglich.

Eine Klassenfabrik bietet eine interessante Möglichkeit den Funktionsblock FB_Logger deutlich flexibler zu gestalten. Hierbei wird ein Funktionsblock definiert (die eigentliche Klassenfabrik), der über eine Methode eine Referenz auf einen anderen Funktionsblock zurückliefert. Parameter, welche zuvor an die Klassenfabrik übergeben werden, entscheiden welche Art von Referenz erzeugt wird.

Die Funktionalität, die bisher in der Methode FB_init() von FB_Logger enthalten war, wird in einen separaten Funktionsblock, der Klassenfabrik FB_FileLoggerFactory, ausgelagert. Die Klassenfabrik FB_FileLoggerFactory erhält über die Methode FB_init() den Pfad auf die Log-Datei.

An die Methode FB_init() von FB_Logger wird eine Referenz auf die Klassenfabrik übergeben. Die Klassenfabrik liefert über die Methode GetLogger() die Referenz auf den entsprechenden Funktionsblock (FB_TxtLogger, FB_CsvLogger oder FB_XmlLogger) zurück. Das Anlegen der Instanzen erfolgt jetzt durch die Klassenfabrik, nicht durch den Funktionsblock FB_Logger.

Da die Klassenfabrik bei diesem Beispiel immer die Methode GetLogger() bereitstellt, wird diese von einem abstrakten Basis-Funktionsblock abgeleitet, welcher diese Methode vorgibt.

Abstrakte Funktionsblöcke enthalten keine Funktionalitäten. Die Rümpfe der Methoden bleiben leer. Somit kann ein abstrakter Funktionsblock mit einem Interface verglichen werden.

Da die Klassenfabrik von einer abstrakten Klasse (oder hier: abstrakter Funktionsblock) abgeleitet wird, spricht man von einer abstrakten Klassenfabrik.

Das UML-Diagramm sieht somit wie folgt aus:

Picture05

Hier die Darstellung der einzelnen POUs:

Picture06

Für die Nutzung von FB_Logger muss beim Anlegen einer Instanz eine Referenz auf die gewünschte Klassenfabrik übergeben werden.

PROGRAM MAIN
VAR
    fbFileLoggerFactory   : FB_FileLoggerFactory('File.csv');
    refFileLoggerFactory  : REFERENCE TO FB_FileLoggerFactory := fbFileLoggerFactory;
    fbLogger              : FB_Logger(refFileLoggerFactory);	
    sRetMsg               : STRING;
END_VAR

sRetMsg := fbLogger.Write('Hello');

Die Klassenfabrik FB_FileLoggerFactory entscheidet in der Methode FB_init(), ob eine Instanz von FB_TxtLogger, FB_CsvLogger oder FB_XmlLogger angelegt werden soll.

METHOD FB_init : BOOL
VAR_INPUT
    bInitRetains  : BOOL;
    bInCopyCode   : BOOL;
    sFilename     : STRING;
END_VAR
VAR
    sFilenameExtension : STRING;
END_VAR

sFilenameExtension := F_ToLCase(RIGHT(sFilename, 3));
IF (sFilenameExtension = 'txt') THEN
    pTxtLogger := __NEW(FB_TxtLogger);
    ipLogger := pTxtLogger^;
ELSIF (sFilenameExtension = 'csv') THEN
    pCsvLogger := __NEW(FB_CsvLogger);
    ipLogger := pCsvLogger^;
ELSIF (sFilenameExtension = 'xml') THEN
    pXmlLogger := __NEW(FB_XmlLogger);
    ipLogger := pXmlLogger^;
ELSE
    ipLogger := 0;
END_IF

Die Methode GetLogger() von FB_FileLoggerFactory gibt das Interface ILogger zurück. Über dieses Interface kann auf die Methode Write() des Loggers zugegriffen werden.

METHOD PUBLIC GetLogger : ILogger
VAR_INPUT
END_VAR

GetLogger := ipLogger;

FB_Logger holt sich in FB_init() auf diese Weise Zugriff auf den gewünschten Logger.

METHOD FB_init : BOOL
VAR_INPUT
    bInitRetains       : BOOL;
    bInCopyCode        : BOOL;
    refLoggerFactory   : REFERENCE TO FB_AbstractLoggerFactory;
END_VAR

IF (__ISVALIDREF(refLoggerFactory)) THEN
    ipLogger := refLoggerFactory.GetLogger();
ELSE
    ipLogger := 0;
END_IF

In der Methode Write() von FB_Logger erfolgt der Aufruf indirekt über das Interface ILogger.

METHOD PUBLIC Write : STRING
VAR_INPUT
    sMsg    : STRING;
END_VAR

Write := 'Error';
IF (ipLogger <> 0) THEN
    Write := ipLogger.Write(sMsg);
END_IF	

Beispiel 2 (TwinCAT 3.1)

Vorteile einer abstract Factory

Dadurch, dass an FB_Logger eine Klassenfabrik übergeben wird, ist die Funktionalität erweiterbar, ohne das ein Funktionsblock geändert werden muss.

Als Beispiel, wird das obrige Programm so erweitert, dass über die Methode Write() von FB_Logger Meldungen in eine Datenbank geschrieben werden.

Hierzu sind zwei Schritte notwendig:

1. Es wird eine neue Klassenfabrik definiert, die von FB_AbstractLoggerFactory abgeleitet wird. Dadurch erhält die neue Klassenfabrik die Methode GetLogger().
2. Es wird der Funktionsblock fürs Loggen angelegt. Dieser implementiert das Interface ILogger und somit die Methode Write().

Die neue Klassenfabrik (FB_DatabaseLoggerFactroy) ist so ausgelegt, das verschiedene Arten von Datenbanken nutzbar wären. Die Methode FB_init() enthält drei Parameter vom Typ string. Zwei Parameter definieren den Benutzernamen und das Passwort, während der dritte Parameter die Verbindungsdaten für die Datenbank enthält.

FB_SQLServerLogger ist der Loggerbaustein für SQL-Server Datenbanken. Es könnten noch weitere Varianten folgen wie z.B. FB_OracleLogger für Oracle-Datenbanken.

Somit erweitert sich das Programm um die Funktionsblöcke FB_DatabaseLoggerFactroy und FB_SQLServerLogger.

Der linke Bereich stellt die Bausteine dar, die sich in einer SPS-Bibliothek befinden könnten. Auf der rechten Seite befinden sich die beiden Funktionsblöcke, die notwendig sind, um das Verhalten von FB_Logger zu verändern.

Picture07

Die Anwendung der neuen Funktionsblöcke ist denkbar einfach:

PROGRAM MAIN
VAR
    fbDatabaseLoggerFactory  : FB_DatabaseLoggerFactory('MyDatabase', 'User', 'Password');
    refDatabaseLoggerFactory : REFERENCE TO FB_DatabaseLoggerFactory := fbDatabaseLoggerFactory;
    fbLogger                 : FB_Logger(refDatabaseLoggerFactory);	
    sRetMsg                  : STRING;
END_VAR

sRetMsg := fbLogger.Write('Hello');

Beispiel 3 (TwinCAT 3.1)

Weder FB_Logger noch ein anderer Baustein aus der SPS-Bibliothek musste angepasst werden, um den Baustein FB_Logger in seiner Funktion zu erweitern. Dieses wurde möglich, in dem die Anhängigkeiten der Funktionsblöcke untereinander geändert wurden.

Bei der 3. Variante werden alle Logger-Funktionsblöcke (FB_TxtLogger, FB_CsvLogger, …) direkt von FB_Logger angelegt. Zwischen diesen Funktionsblöcken besteht somit eine feste Abhängigkeit.

Picture08

Bei der 4. Variante befindet sich zwischen den Logger-Funktionsblöcken und FB_Logger eine weitere Ebene. Diese Ebene ist jedoch abstrakt. Die Referenz, die an FB_Logger über die Methode FB_init() übergeben wird, ist eine Referenz auf einen abstrakten Funktionsblock.

Picture09

Erst bei der Benutzung der Bausteine, sprich wenn die Applikation entwickelt wird, legt der Anwender fest, welche konkrete Klassenfabrik anzuwenden ist. Der Funktionsblock FB_Logger sieht nur einen Funktionsblock, der von FB_AbstractLoggerFactory abgeleitet wurde und somit die Methode GetLogger() enthält. Diese Methode liefert das Interface ILogger zurück, hinter der sich die Methode Write() des eigentlichen Loggers befindet.

Wo die konkrete Klassenfabrik definiert wurde, innerhalb der gleichen SPS-Bibliothek oder an anderer Stelle, ist für den Baustein FB_Logger nicht relevant. Auch wie die Klassenfabrik die Logger-Bausteine anlegt, ist für FB_Logger ohne Bedeutung.

Genutzte Bausteine (FB_TxtLogger, …) werden nicht direkt an den nutzenden Baustein (FB_Logger) übergeben. Vielmehr wird die Kontrolle über das Erzeugen der genutzten Bausteine an ein weiteres Modul (FB_FileLoggerFactory, ...) übertragen.

Dependency Injection

Der Funktionblock FB_Logger erhält über die Methode FB_init() eine Referenz auf die Klassenfabrik. Somit wird über diese Referenz Funktionalität in den Funktionsblock hineingegeben. Dieses Konzept wird Dependency Injection bezeichnet.

Open Closed Principle

Die objektorientierte Softwareentwicklung definiert einige sogenannte Prinzipen. Das Einhalten dieser Prinzipen soll helfen, die Softwarestruktur sauber zu halten. Eines dieser Prinzipen ist das Open Closed Principle oder auch Offen für Erweiterungen, geschlossen für Änderungen.

Offen für Erweiterungen:

Das bedeutet, dass sich durch die Verwendung von Erweiterungsmodulen die ursprüngliche Funktionalität eines Moduls verändern lässt. Dabei enthalten die Erweiterungsmodule nur die Anpassungen von der ursprünglichen Funktionalität.

Geschlossen für Änderungen:

Das bedeutet, dass keine Änderungen des Moduls nötig sind, um es zu erweitern. Das Modul bietet definierte Erweiterungspunkte, über die sich die Erweiterungsmodule anknüpfen lassen.

Wie das Beispiel zeigt, hilft eine Klassefabrik beim Umsetzen dieses Open Closed Principle.

Fazit

Durch den Einsatz einer abstract Factory konnte der Baustein FB_Logger in seiner Funktionalität erweitert werden, ohne dass dieser geändert wurde. Die neuen Sprachfeatures der IEC 61131-3 haben dieses möglich gemacht. Interfaces, Vererbung und die dynamische Speicherverwaltung bieten völlig neue Ansätze im Design von SPS-Bibliotheken.


ppedv Team Blog: Was ist schneller? CAML oder KQL

Unlängst beschäftigte ich mich mit der Frage, welcher Weg der schnellste ist, um auf die Daten zu zugreifen: der Zugriff über eine CAML Abfrage oder der Zugriff über den Search Index.

Daher habe ich eine SharePoint Kontakt-Liste mit ca. 18.000 Datensätzen gefüllt und dann eine simple Abfrage programmiert. Die Aufgabenstellung war die Suche im “CompanyName” mit dem BeginsWith Operator.

Die CAML Variante:

            lbAusgabe.Items.Clear();
            SPList firmen = SPContext.Current.Web.Lists["Firmen"];

            DateTime start = DateTime.Now;

            int anz = 0;
            string caml = @"<Where><BeginsWith>
                    <FieldRef Name='Company'/>
                    <Value Type='Text'>{0}</Value>
                    </BeginsWith></Where>";
            SPQuery q = new SPQuery();
            q.Query = string.Format(caml, txtSuche.Text);
            q.QueryThrottleMode = SPQueryThrottleOption.Override;
            q.RowLimit = 100;
            
            foreach (SPListItem it in firmen.GetItems(q))
            {
                lbAusgabe.Items.Add(it["Company"].ToString() ?? "");
                anz++;
            }
            DateTime ende = DateTime.Now;

            double Dauer = (ende - start).TotalMilliseconds;

            lblDauer.Text = "Dauer:" + Dauer.ToString("#,###");
            lblAnzahl.Text = "Anzahl: " + anz.ToString();

Diese Abfrage liefert nur die ersten 100 Datensätze. Da die Abfrage aber über alle Datensätze läuft, ist es notwendig das List Throttling zu deaktivieren. Daher wird der QueryThrottleMode auf “Override” gestellt.

Die zweite Variante verwendet die Keyword Query Language (KQL) und greift somit auf den Search-Index zu:

            int anz = 0;
            lbAusgabe.Items.Clear();
            SPList firmen = SPContext.Current.Web.Lists["Firmen"];
            DateTime start = DateTime.Now;

            KeywordQuery q = new KeywordQuery();
            q.QueryText = "CompanyOWSTEXT:" + txtSuche.Text + "*";
            q.QueryText += " AND Path:" + firmen.ParentWeb.Site.Url + firmen.ParentWebUrl + firmen.RootFolder + "*";
            q.SelectProperties.Add("Company");
            q.RowLimit = 100;

            SearchExecutor se = new SearchExecutor();
            ResultTableCollection rtc = se.ExecuteQuery(q);

            var resultTables = rtc.Filter("TableType", KnownTableTypes.RelevantResults);
            var resultTable = resultTables.FirstOrDefault();

            foreach(DataRow dr in resultTable.Table.Rows)
            {
                lbAusgabe.Items.Add(dr["Company"].ToString() ?? "");
                anz++;
            }

            DateTime ende = DateTime.Now;

            double Dauer = (ende - start).TotalMilliseconds;

            lblDauer.Text = "Dauer:" + Dauer.ToString("#,###");
            lblAnzahl.Text = "Anzahl: " + anz.ToString();

 

Spannend war die Messung der Abfragezeiten. Um valide Ergebnisse zu bekommen, habe ich jede Abfrage mehrmals ausgeführt. Hier die Ergebnisse in Millisekunden:

  CAML Search
Abfrage 1 413 138
Abfrage 2 423 201
Abfrage 3 449 109
Abfrage 4 425 113
Abfrage 5 472 105
Abfrage 6 459 112
Mittelwert 440,2 129,7

 

Hier ist eindeutig zu erkennen, dass der Zugriff über die Search deutlich schneller ist. Allerdings wurde in der Liste kein Index gesetzt. Sobald in der Kontakt-Liste auf das Feld “CompanyName” ein Index gesetzt wird, sieht das Ergebnis anders aus:

  CAML Search CAML Mit index
Abfrage 1 413 138 34
Abfrage 2 423 201 23
Abfrage 3 449 109 27
Abfrage 4 425 113 26
Abfrage 5 472 105 27
Abfrage 6 459 112 30
Mittelwert 440,2 129,7 27,8

 

Und hier sieht man ganz klar, warum es empfehlenswert ist einen Index zu verwenden. Durch diese simple Konfiguration kann die Abfragezeit deutlich reduziert werden!

SharePoint ist keine Datenbank! Wenn die SharePoint-Listen aber dennoch als Datenbank verwendet werden, dann sollte man wie in jeder richtigen Datenbank auch Indizes verwenden!

Diese und weitere Varianten im Umgang mit SharePoint-Listen per Programmcode werden auch in unserer Schulung “SharePoint 2013 - Lösungen entwickeln und anpassen" behandelt.

codefest.at [MS]: Microsoft Azure - die Cloud-Computing-Plattform der Zukunft bei der PPEDV AG

Mit Hilfe von Microsoft Azure können Sie Ihre Anwendungen, Dienste und Speicherplatz privat oder hochverfügbar direkt in den Rechenzentren von Microsoft beliebig skalierbar bereitstellen.
Microsoft Azure entlastet Sie dabei von jeglichen Administrationsaufwand. Statt sich mit Serverinfrastruktur auseinanderzusetzen, können Sie sich voll und ganz auf das konzentrieren, was wirklich zählt:
Ihre Anwendungen und deren Mehrwert für Ihre Kunden und Benutzer.

Starten Sie mit dem vorhandenen Know-how der PPEDV AG und der Software, die Sie bereits kennen sofort und ganz bequem durch. Visual Studio, .NET, Windows Server, Active Directory, SQL Server, SharePoint und BizTalk funktionieren am besten mit Azure und profitieren vom End-to-End-Support auf Unternehmensniveau von Microsoft.

In dem Microsoft Azure Kurs der PPEDV AG lernen Sie eine bestehende ASP.NET Anwendung um die neuen Azure Funktionalitäten zu erweitern. Die Microsoft Azure Schulung der ppedv AG legt den Schwerpunkt auf die Entwicklung von Cloud-Lösungen mit .NET inkl. Speicherung, Cloud Service, Service Bus und Active Directory. Sie lernen darüber hinaus mit den integrierten Visual Studio-Tools Apps schneller zu entwickeln, zu debuggen und zu durchlaufen.

Kursbegleitend zum Azure Kurs wird die Original Microsoft MOC 10978 als Unterlage verwendet. Wir freuen uns auf Ihren Besuch zu unserem offiziellen MOC Azure Training in Wien am 4.-7 November 2014.
Melden Sie sich noch heute an…

Und wer sich schon vorab – oder Abseits der angebotenen Schulungen - intensiver mit Azure auseinandersetzen möchte, findet eine Reihe von kostenfreien Azure Trainings im Rahmen der Microsoft Virtual Academy – z.B. Designing Applications for Windows Azure Jump Start…

friends header

bloggers headline

links header

 
Don't contact us via this (fleischfalle@alphasierrapapa.com) email address.