T-Shirt & Cognitive Services

19. Februar 2019

Innovation ist ein zentrales Leitmotiv bei SDX, das wir auch auf Messen und Fachkongressen als Aussteller transportieren – unter anderem über die App X-Suzzle, die wir bereits seit 2015 als Xamarin Cross-Platform-App für iOS, Android und Windows Mobile (damals gab’s das noch ;-)) auf Messen nutzen.
Um bei Besuchern auch weiterhin Interesse für SDX zu wecken, wurden Anforderungen an eine neue, innovative Messe-App definiert:

  • Inhaltlich geeignet, um Interessenten anzusprechen
  • Nutzung moderner Technologien, um das SDX-Know-How zu transportieren
  • Einsatz im Umfeld einer Messe – Stichwort unzuverlässige Internet-Verbindung
  • Professionell durch robuste, stabile Umsetzung und effiziente Ressourcennutzung

.

Geiles T-Shirt – coole Technologien 🙂

Der inhaltliche Aspekt war (relativ) schnell gefunden: Ein individuelles T-Shirt als Give-away mit den persönlichen Skills der Besucher als Tag-Cloud.
Für einen humorvollen Einstieg in die Interaktion mit dem Besucher wurde eine Personenerkennung inkl. Avatar in die neue Messe-App „X-Tag“ eingebaut.

Unser aktueller Innovations-Fokus liegt auf Azure Services (Cognitive Sevices, Data Analytics, …), Xamarin als native cross-platform Technologie ist aktueller denn je. Damit sind auch die technischen Aspekte der App (relativ) schnell klar: Offline-fähiger Xamarin-Client mit Azure Services und Cognitive Services als Backend.

Dieser Beitrag betrachtet die X-Tag App aus technischer Sicht.

User Experience

Die erste technischer Herausforderung ergibt sich aus der Zielgruppe: Mit der Anwendung sollen auf Messen und Fachkongressen Interessenten – Kunden und Bewerber – angesprochen werden; die Anforderung an die Qualität der User Experience sind entsprechend hoch.

Das Ergebnis kann sich sehen lassen. Hier sind ein paar Screenshots des Android-Clients, die den Funktionsumfang gut wiedergeben:

Screenshot_20190130-133120 Screenshot_20190130-133426 Screenshot_20190130-133720 Screenshot_20190130-133731

  • Der Anwender kann sich seine persönliche Tag-Cloud erstellen und als T-Shirt bestellen. Dies ist die Kernfunktionalität, die auch offline verfügbar ist.
  • Cognitive Services werden genutzt, um das Ergebnis weiter zu personalisieren. Dies ist optional und zudem nur verfügbar, wenn eine Internetverbindung besteht.
  • Die Daten werden verschlüsselt an das Backend übertragen, sobald eine Netzverbindung besteht. Nach erfolgreicher Übertragung werden sie lokal gelöscht.

Die App ist mit Xamarin und Xamarin.Forms umgesetzt. Technische Hintergründe zur Gestaltung der GUI hat ein Kollege in einem Vortrag auf der OOP betrachtet (ein Artikel ist in Vorbereitung), so dass ich hier darauf nicht weiter eingehe.

Die Tag-Cloud

Die Erstellung der Tag-Cloud brachte einige besondere Herausforderungen mit sich: Das Tag-Cloud-Image wird von der App regelmäßig neu berechnet sobald sich durch Eingaben des Anwenders Änderungen ergeben. Dies muss schnell und unter Berücksichtigung von Speicherbeschränkungen der Devices erfolgen. Zusätzlich muss das Backend in der Lage sein, diese Berechnung mit der für den T-Shirt-Druck notwendigen hohen Auflösung zu wiederholen – natürlich bei identischem Ergebnis.

Um dies zu erreichen, wurde eine eigenen Portierung von wordcloud2.js (Live-Demo) umgesetzt. Diese steht am Client für Xamarin.Android und Xamarin.iOS zur Verfügung, sowie basierend auf System.Drawing für das Backend.

Eine erste .NET/C#-Migration der JavaScript-Bibliothek war relativ schnell vorhanden, die initiale Migration auf die unterschiedlichen Plattformen (Windows, Android, iOS) war nicht gerade trivial, aber letztlich Handarbeit.

Als besondere Herausforderung stellte sich eine kleine, unscheinbare Randbedingung heraus: Der Algorithmus muss nicht nur auf allen Plattformen funktionieren … er muss auf allen Plattformen ein identisches Ergebnis produzieren. Andernfalls wäre die Neuberechnung im Backend nicht umsetzbar. Leider ist es so, dass aufgrund von Unterschieden in der Behandlung von Schriftarten Texte in jedem System anders platziert werden. Der Algorithmus zur Erzeugung der Tag-Cloud arbeitet pixelgenau, so dass Wörter, die auf dem Client sauber aneinander ausgerichtet wurden, im Backend verschoben dargestellt wurden und ineinanderliefen – ein Resultat, das definitiv nicht den Erwartungen entsprach!

Konsequenz war, dass die jeweiligen Plattform-APIs nicht für die Textplatzierung verwendet werden konnten. Vielmehr musste die entstehende Pixeldarstellung von Hand ausgemessen und dann platziert werden. Folgende Bilder geben einige dieser Detailaspekte wieder: Die Textdimension wird für die Positionierung detailliert ausgemessen, zur Platzierung wird der Text in ein gröberes Raster gelegt und anhand dieses Rasters werden die einzelnen Begriffe aneinander ausgerichtet:

image 000-3-withBounds image

Somit war auch dieses Problem schlussendlich gelöst.

Die Architektur

Die Architektur hatte im Wesentlichen zwei Herausforderungen zu bewältigen:

  1. Der Einsatz im Umfeld einer Veranstaltung/Messe impliziert häufig Gegebenheiten wie eine unzuverlässige Internet-Verbindung; die Anwendung kann also nicht davon ausgehen, dass das Backend immer zur Verfügung steht.
  2. Vor dem Hintergrund des Nutzungsprofils – zwischen Veranstaltungen liegen i.d.R. Wochen oder Monate, in denen die Anwendung nicht genutzt wird – sollte auf eine kosteneffiziente Ressourcennutzung geachtet werden.

Diese beiden zentralen Anforderungen wurden durch Offline-Fähigkeit der App und ein Backend auf Basis von Azure Functions, Azure Storage und eine Azure Logic App (für den Email-Versand) erreicht:

image

Der Client

Die App speichert die Informationen einer Session – d.h. die Parameter für die Tag-Cloud, die eingegebenen Daten, etc. – zunächst lokal. Damit ist die Anwendung dann frei und der nächste Anwender kann sich sein T-Shirt erstellen.

Die Übertragung der Informationen an das Backend findet im Hintergrund statt, sobald eine Verbindung besteht. Zu berücksichtigen ist, das für jede Session mehrere Informationen zu übertragen sind und dass es auch während der Übertragung zu Abbrüchen kommen kann. Der Ablauf dazu ist wie folgt:

  1. Mit einem einfachen Ping-Aufruf wird zunächst die Erreichbarkeit des Backends geprüft.
  2. für jede vorhandene Session…
    1. Die eigentlichen Nutzdaten werden an das Backend übertragen. Das sind die erfassten Daten (d.h. die Parameter für die Tag-Cloud, die T-Shirt-Größe etc.), sowie das Kamerabild.
    2. Durch einen abschließenden Aufruf bestätigt der Client, dass alle Informationen zu einer Session erfolgreich übertragen wurden.
    3. Die Daten der Session werden lokal gelöscht.

Sollte es an irgendeiner Stelle zu Fehlern kommen, wird diese Verarbeitung abgebrochen. Zu einem späteren Zeitpunkt beginnt der Ablauf erneut – in der Hoffnung, dass dann eine erfolgreiche Übertragung möglich ist.

 

Das Backend

Das Backend nimmt die Daten zunächst nur entgegen, ohne sie zu verarbeiten. Erst mit der abschließenden Bestätigung wird die weitere Verarbeitung angestoßen – was aber asynchron erfolgt, damit der Client nicht unnötig darauf warten muss.

Die Verarbeitung besteht aus dem Aufbereiten des Tag-Cloud-Images in der nötigen Auflösung für den Druck, sowie dem Email-Versand. Die Umsetzung dieser Backendfunktionalität wurde vollständig in Azure Functions umgesetzt, wobei vor allem REST- und Queue-Trigger zum Einsatz kamen.

Das folgende Bild gibt einen Teil der Abläufe wieder (Azure Functions sind in gelb dargestellt, Storage in blau):

Backend (simple)

Der Client nutzt Functions mit REST-Trigger zum Bereitstellen der Information und deren Ablage in Blob und Table Storage. Hierbei findet keinerlei Verarbeitung statt, um den Client nicht unnötig warten zu lassen. Auch mit dem letzten Aufruf des Clients zu einer Session wird lediglich ein Eintrag in einer Storage Queue vorgenommen. Eine Function mit entsprechendem Queue-Trigger übernimmt dann die eigentliche Verarbeitung. Datenbereitstellung und –verarbeitung sind somit sauber entkoppelt. Das Bild zeigt außerdem eine Function mit zeitabhängigem Trigger zum Löschen der Daten nach einstellbaren Fristen; hiermit werden Datenschutzanforderungen umgesetzt, die bei personenbezogenen Daten immer zu beachten sind.

Fazit

Die beschriebene Umsetzung der Architektur erfüllt die eingangs beschriebenen Anforderungen in nahezu idealer Art und Weise. Zum einen wird die Anwendung durch das beschriebene Vorgehen sehr unempfindlich gegen unzuverlässige Internet-Verbindungen, was auf Messen und generell „im Feld“ oft immer noch Realität ist. Zum anderen ist die Nutzung von Azure Functions und Azure Storage extrem kosteneffizient. Kosten für Azure Functions fallen nur bei Nutzung an und schließen ein Freikontingent ein; Kosten für Storage sind, verglichen mit anderen Datenbanken, sehr gering.