Blinky – die App die stressen soll
Von Andy Babic am 07.03.2024
Die Ursprungsidee für unser Projekt entsprang dem kreativen Geist von Grischa. Seine Inspiration entsprang dem Wunsch, ein Interface während des Autofahrens zu evaluieren – natürlich in einer simulierten Umgebung. Die zugrunde liegende Idee war, dass ein Interface, das auch unter den Ablenkungen und Herausforderungen des Autofahrens problemlos funktioniert und bedient werden kann, intuitiv und einfach genug gestaltet ist.
Ursprünglich planten wir, unsere Methode auf dem Gelände der Fachhochschule vorzustellen, um eine authentische Testumgebung zu schaffen. Jedoch stellten wir fest, dass dies nicht möglich war, da unsere Versicherung nicht bereit war, uns die nötige Deckung zu gewähren. Als Alternative beschlossen wir, einen anderen Stresstest nach dem gleichen Schema durchzuführen.
Leider stellten wir fest, dass einige dieser Tests nicht alleine oder vollständig reproduzierbar waren. Dies führte uns zu der Überlegung, wie wir eine zuverlässige Methode entwickeln könnten, um die Aufmerksamkeit in einer kontrollierten Umgebung zu beeinträchtigen.
Aus dieser Herausforderung entstand die Idee, eine Webanwendung zu entwickeln, die genau dies bewerkstelligen sollte: die Aufmerksamkeit der Benutzer gezielt zu beeinträchtigen und dabei alle relevanten Daten aufzuzeichnen. Diese Idee war der Ausgangspunkt für die Entwicklung unserer innovativen Stresstest-Webanwendung.
Unser Ansatz war es, eine benutzerfreundliche Plattform zu schaffen, die es den Benutzern ermöglicht, Stresstests für ihre Anwendungen durchzuführen, und gleichzeitig eine detaillierte Analyse der Ergebnisse zu ermöglichen. Dabei setzen wir auf moderne Technologien wie WebSockets für eine effiziente Echtzeitkommunikation und Svelte für ein reaktives und performantes Frontend.
Die Kernidee hinter unserer Webanwendung ist einfach: Benutzer können individuelle Stresstests erstellen, indem sie Parameter wie Testdauer, Ereignisse und weitere Einstellungen festlegen. Sobald der Test erstellt ist, generiert die Anwendung einen QR-Code, der gescannt werden kann, um den Test zu starten.
Nach dem Start des Tests werden alle verbundenen Geräte in einem vordefinierten Muster zum Blinken gebracht und geben gleichzeitig einen Alarm aus. Jeder Benutzer muss jeden Alarm quittieren, was eine effektive Überwachung und Reaktion auf die Testbedingungen ermöglicht.
Ein entscheidender Aspekt unserer Webanwendung ist die umfangreiche Aufzeichnung aller Testparameter und Ereignisse. Diese Daten werden sorgfältig gespeichert und können später für eine detaillierte Analyse und Bewertung der Anwendungsnutzung verwendet werden.
Darüber hinaus verfügt unsere Anwendung über ein umfassendes Benutzermanagement, das es Administratoren ermöglicht, Benutzerkonten zu verwalten und Zugriffsrechte zu steuern. Benutzer können ihre erstellten Tests speichern und später erneut laden, um sie erneut durchzuführen oder zu modifizieren.
Dank der Verwendung von WebSockets können wir eine nahtlose Echtzeitkommunikation zwischen den Benutzern und der Anwendung gewährleisten, was eine schnelle Reaktion auf Ereignisse während des Tests ermöglicht. Darüber hinaus ermöglicht die Verwendung von Svelte als Frontend-Technologie eine reaktionsschnelle Benutzeroberfläche mit einer beeindruckenden Leistung, selbst bei umfangreichen Stresstestszenarien.
Insgesamt sind wir davon überzeugt, dass unsere Webanwendung einen bedeutenden Beitrag zur Verbesserung der Qualität und Leistungsfähigkeit von Softwareanwendungen leisten wird, indem sie Benutzern eine effektive Möglichkeit bietet, deren Belastbarkeit unter realen Bedingungen zu testen und zu bewerten.
Neues Learning 1: Der Websocket
Die Entscheidung, WebSocket als Kommunikationsprotokoll für das SyncBlink-Projekt zu verwenden, war strategisch und basierte auf verschiedenen Überlegungen, die die Anforderungen und Ziele des Projekts berücksichtigten.
Zunächst einmal bietet WebSocket eine bidirektionale, dauerhafte Verbindung zwischen dem Server und den Clients. Im Vergleich zu herkömmlichen HTTP-Anfragen, die eine neue Verbindung für jede Anfrage öffnen und schließen, ermöglicht WebSocket eine kontinuierliche Kommunikation in Echtzeit. Dies ist besonders wichtig für Stresstestszenarien, in denen schnelle Reaktionszeiten und die Möglichkeit, Befehle sofort an die verbundenen Geräte zu senden, entscheidend sind.
Ein weiterer wichtiger Aspekt ist die Effizienz von WebSocket in Bezug auf die Netzwerkbelastung. Durch die Vermeidung des Overheads, der mit HTTP-Anfragen verbunden ist, und die Reduzierung der Latenzzeit bietet WebSocket eine optimierte Lösung für die Echtzeitkommunikation.
Darüber hinaus ermöglicht WebSocket die nahtlose Übertragung von Daten in einem standardisierten Format. Dies erleichtert die Entwicklung von Anwendungen, da Entwickler sich auf die Implementierung der Geschäftslogik konzentrieren können, ohne sich um die Details der Datenübertragung kümmern zu müssen.
Ein weiterer entscheidender Faktor für die Verwendung von WebSocket in unserem Projekt war die Notwendigkeit einer gemeinsamen Echtzeiterfahrung für alle Benutzer. WebSocket ermöglicht es, dass alle verbundenen Clients synchronisiert werden und gleichzeitig die gleichen Befehle erhalten, um die Geräte im Test zu steuern. Dies ist besonders wichtig für die Durchführung von koordinierten Stresstests, bei denen die Aktionen aller Benutzer simultan erfolgen müssen.
Insgesamt war WebSocket die ideale Wahl für das SyncBlink-Projekt aufgrund seiner Fähigkeit, eine zuverlässige, effiziente und synchronisierte Echtzeitkommunikation zu ermöglichen. Diese Entscheidung hat maßgeblich dazu beigetragen, eine leistungsstarke und benutzerfreundliche Plattform für Stresstests zu schaffen, die den Anforderungen unserer Benutzer gerecht wird.
Ein grober Aufbau des Websockets:
- Verbindungsaufbau:
- Clients (sowohl Hosts als auch Teilnehmer) stellen eine Verbindung zum WebSocket-Server her.
- Hosts verbinden sich einfach mit “wss://syncblink-ws.bandy-app.com”, während Clients eine Gruppen-ID an die URL anhängen müssen (z.B., “wss://syncblink-ws.bandy-app.com/?groupId=<hostGroupId>”), um sich einer bestehenden Session anzuschließen.
- Nachrichtenformat:
- Sowohl der Server als auch die Clients kommunizieren durch Senden und Empfangen von Nachrichten in einem standardisierten Format:
{type: "typeOfMessage", data: "objectWithData"}
.
- Sowohl der Server als auch die Clients kommunizieren durch Senden und Empfangen von Nachrichten in einem standardisierten Format:
- Typen von Nachrichten:
- socket_opened: Bestätigt die erfolgreiche Verbindung.
- new_client: Informiert den Host über einen neuen Teilnehmer und sendet eine Liste aller verbundenen Geräte.
- closing_client: Informiert den Host, dass ein Teilnehmer die Verbindung getrennt hat, und sendet die Geräte-ID des sich trennenden Clients.
- trigger: Sendet einen Befehl an ein spezifisches Gerät, um eine Aktion auszuführen (z.B., ein Licht zu blinken). Diese Nachricht enthält Gruppen-ID, Geräteinformationen und zusätzliche Eigenschaften für den Trigger.
- stop: Beendet alle Client-Verbindungen innerhalb einer Gruppe, lässt aber den Host verbunden.
- Sitzungsverwaltung:
- Der Server verwaltet aktive Sessions und Geräte mittels einer internen Map-Struktur. Jeder Client (bzw. Gerät) wird einer Session zugeordnet, wobei jeder Session eine eindeutige Gruppen-ID zugewiesen ist.
- Bei jeder Verbindung wird überprüft, ob es sich um einen neuen Client oder einen Host handelt. Neue Clients erhalten eine Geräte-ID und werden der entsprechenden Session zugeordnet. Hosts verwalten die Session und erhalten Updates über Client-Verbindungen und -Trennungen.
- Ereignisbehandlung:
- Sobald eine Verbindung steht, können Nachrichten für verschiedene Zwecke gesendet werden: Geräte triggern, Sessions stoppen, und über Zustandsänderungen informieren.
- Der Server verarbeitet eingehende Nachrichten, führt die angeforderten Aktionen aus, und leitet entsprechende Befehle an die betreffenden Clients weiter.
- Fehlerbehandlung:
- Fehler während der WebSocket-Kommunikation (z.B., wenn der angeforderte Master oder Client nicht gefunden wird) führen zum Senden einer Fehlermeldung mit dem Typ “error” und einer Beschreibung des aufgetretenen Fehlers.
- Fehler während der WebSocket-Kommunikation (z.B., wenn der angeforderte Master oder Client nicht gefunden wird) führen zum Senden einer Fehlermeldung mit dem Typ “error” und einer Beschreibung des aufgetretenen Fehlers.
Neues Learning 2: Das G in Vue steht für Gut
Neues Learning 3: Svelte mit Tailwind & Skeleton/Flowbite machen Spaß
Ursprünglich hatten wir geplant, Vue.js für das Frontend zu verwenden. Vue.js ist bekannt für seine Einfachheit und Flexibilität, besonders für kleinere Anwendungen. Jedoch stellten wir fest, dass die Verwendung von TypeScript mit Vue.js zu Komplikationen führte, ähnlich wie Java und JavaScript nicht immer nahtlos zusammenarbeiten. Deshalb entschieden wir uns nach einigen Stunden und Tagen der Evaluation gegen Vue.js und wählten stattdessen Svelte. Die Entscheidung erwies sich als äußerst positiv, da Svelte eine leistungsstarke Alternative darstellt, die sich nahtlos in unser Projekt integrieren ließ und eine äußerst angenehme Entwicklererfahrung bietet.
Tailwind CSS und Skeleton für das Styling: Da wir wenig Zeit in die Gestaltung des Frontends investieren wollten, entschieden wir uns für Tailwind CSS, um schnell und effizient ansprechende Benutzeroberflächen zu erstellen. Tailwind CSS ermöglicht es uns, den Styling-Prozess zu beschleunigen, indem wir die Styles direkt in den HTML-Dateien definieren. Obwohl dies anfangs etwas ungewohnt war, stellten wir fest, dass dies eine effektive Möglichkeit ist, das Styling zu vereinfachen und gleichzeitig eine hohe Flexibilität zu bieten. Zusätzlich nutzten wir Skeleton als UI-Bibliothek, um das Aussehen unserer Anwendung weiter zu verbessern und sicherzustellen, dass sie sowohl funktional als auch ästhetisch ansprechend ist.
Kommunikation über WebSockets: Die Kommunikation im Frontend erfolgt über eine WebSocket-Verbindung zum Server. Diese bidirektionale, dauerhafte Verbindung ermöglicht eine effiziente Echtzeitkommunikation zwischen dem Frontend und dem Backend-Server. Durch die Verwendung von WebSockets können wir sicherstellen, dass alle Benutzer synchronisiert sind und dass Testergebnisse sofort aktualisiert und angezeigt werden können. Dies ist besonders wichtig für Stresstestszenarien, bei denen eine schnelle Reaktionszeit und präzise Steuerung erforderlich sind.
Strukturierte Architektur und reaktives Zustandsmanagement: Das Frontend ist strukturiert und organisiert, um eine klare Trennung von Verantwortlichkeiten zu gewährleisten und die Wartbarkeit zu erleichtern. Wir verwenden Svelte-Komponenten, um die Benutzeroberfläche zu definieren und WebSocket-Funktionen, um die Kommunikation mit dem Server zu verwalten. Reaktive Zustandsmanagement-Techniken, wie z.B. die Verwendung von Stores, ermöglichen es uns, den Zustand der Anwendung effektiv zu verwalten und die Benutzeroberfläche dynamisch zu aktualisieren, basierend auf den Änderungen, die über WebSockets empfangen werden.
Insgesamt bietet die Frontend-Architektur von SyncBlink eine robuste und flexible Grundlage für die Durchführung von Stresstests und die effiziente Verwaltung von Benutzerinteraktionen in Echtzeit. Durch die Verwendung von Svelte, Tailwind CSS und WebSockets konnten wir eine ansprechende und leistungsfähige Anwendung entwickeln, die den Anforderungen unserer Benutzer gerecht wird.
Ein grober Aufbau unseres Frontends
- Verbindungsaufbau über WebSockets:
- Der Websocket.ts im
src/lib
-Ordner ist verantwortlich für das Einrichten der WebSocket-Verbindung mit dem Server. DieconnectWebSocket
-Funktion erlaubt es dem Frontend, sich entweder als Host oder als Client zu einer Gruppe (Session) zu verbinden, indem optional eine Gruppen-ID an die WebSocket-URL angehängt wird.
- Der Websocket.ts im
- Session-Management und Gerätetriggerung:
- Innerhalb der WebSocket-Kommunikation gibt es Funktionen wie
startSession
,triggerDevice
, undstopSession
, die für das Senden spezifischer Nachrichtentypen zum Server verantwortlich sind. Diese Funktionen werden verwendet, um Tests zu starten, Geräte innerhalb einer Session zu triggern oder die Session zu beenden.
- Innerhalb der WebSocket-Kommunikation gibt es Funktionen wie
- Komponenten für Benutzerinteraktion:
- TestModal.svelte, BlinkModal.svelte, und ShareTestModal.svelte sind Svelte-Komponenten, die die Benutzerinteraktion mit der Anwendung darstellen. Sie nutzen die oben genannten WebSocket-Funktionen, um Benutzereingaben wie das Starten eines Tests oder das Triggern eines Geräts in Echtzeit zu verarbeiten.
- Dynamische Testkonfiguration:
- Der TestForm.svelte im
src/routes/(main)
-Ordner ermöglicht es dem Benutzer, Testparameter wie Testdauer, Ereignisanzahl und Geräteanzahl festzulegen. Nach der Konfiguration können diese Einstellungen genutzt werden, um die Testsession über WebSockets zu starten.
- Der TestForm.svelte im
- Reaktives Zustandsmanagement:
- Die Stores in
src/lib/stores
, wie z.B.websocketData.ts
unduser.ts
, verwalten den Zustand der Anwendung, einschließlich der verbundenen Geräte und Benutzerdaten. Diese Stores sind zentral für das Aktualisieren der UI basierend auf den Änderungen, die über WebSockets empfangen werden.
- Die Stores in
- Feedback und Ergebnisanzeige:
- Nach dem Abschluss von Tests können die Ergebnisse über die results/+page.svelte-Komponente visualisiert werden. Diese Komponente zeigt eine Zusammenfassung der Testergebnisse, ermöglicht das Herunterladen der Daten und bietet eine visuelle Darstellung der gesammelten Daten.
Zusammenfassend ermöglicht die Frontend-Architektur von SyncBlink eine reibungslose und effiziente Echtzeitkommunikation zwischen den Benutzern und dem Backend-Server für die Durchführung von Stresstests. Durch die Nutzung von WebSockets wird sichergestellt, dass alle Teilnehmer einer Session synchronisiert sind und dass die Testergebnisse in Echtzeit analysiert und dargestellt werden können.
Neues Learning 4: Warum Tailwind großartig ist?
HTML-Datei mit normalem CSS:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tailwind vs. Normal CSS</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1 class="text-2xl font-bold text-blue-500">Hello, world!</h1>
<p class="text-lg text-gray-700">This is a paragraph with some text.</p>
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-700">Click me</button>
</div>
</body>
</html>
styles.css:
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.container h1 {
font-size: 24px;
font-weight: bold;
color: #1e40af;
}
.container p {
font-size: 16px;
color: #4b5563;
}
.container button {
padding: 10px 20px;
background-color: #4299e1;
color: #fff;
border-radius: 4px;
cursor: pointer;
}
.container button:hover {
background-color: #3182ce;
}
Mit Tailwind:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tailwind vs. Normal CSS</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
<div class="container mx-auto p-4">
<h1 class="text-2xl font-bold text-blue-500">Hello, world!</h1>
<p class="text-lg text-gray-700">This is a paragraph with some text.</p>
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-700">Click me</button>
</div>
</body>
</html>
In diesem Beispiel sehen Sie, dass Tailwind CSS Klassen verwendet, um das Styling direkt im HTML-Code anzugeben, während herkömmliches CSS in einer separaten Datei definiert ist. Der Einsatz von Tailwind CSS ermöglicht es, das Styling direkt in den Elementen zu definieren, was die Entwicklung beschleunigen kann, während herkömmliches CSS eine separate Stylesheet-Datei erfordert.
Skeleton: Ein UI-Framework für Svelte +Tailwind
Skeleton ist ein leichtgewichtiges und minimalistisches UI-Framework, das speziell für die Verwendung mit Svelte entwickelt wurde. Es bietet vorgefertigte Komponenten und Layouts, die es einfach machen, ansprechende Benutzeroberflächen für Svelte-Anwendungen zu erstellen, ohne dabei aufgebläht oder überladen zu wirken.
Merkmale von Skeleton:
- Leichtgewichtig und minimalistisch: Skeleton ist bewusst schlank und minimalistisch gehalten, um eine einfache Integration in Svelte-Projekte zu ermöglichen, ohne unnötigen Overhead oder unnötige Komplexität.
- Einfache Verwendung: Skeleton bietet eine Reihe von vorgefertigten Komponenten und Layouts, die einfach in Svelte-Anwendungen eingebunden werden können. Dies erleichtert die Entwicklung von Benutzeroberflächen, indem es Entwicklern ermöglicht, sich auf die Funktionalität ihrer Anwendungen zu konzentrieren, anstatt Zeit mit dem Erstellen von UI-Komponenten zu verbringen.
- Responsives Design: Die Komponenten und Layouts von Skeleton sind responsiv und passen sich automatisch an verschiedene Bildschirmgrößen und Geräte an. Dies gewährleistet eine konsistente Benutzererfahrung auf allen Geräten und Bildschirmgrößen.
- Modular und anpassbar: Skeleton ist modular aufgebaut, was es Entwicklern ermöglicht, nur die Komponenten und Funktionen zu verwenden, die sie benötigen. Darüber hinaus ist Skeleton vollständig anpassbar und kann leicht an die spezifischen Anforderungen und Designrichtlinien eines Projekts angepasst werden.
- Aktive Community und Unterstützung: Skeleton wird von einer aktiven Community von Entwicklern unterstützt, die regelmäßig Updates und Verbesserungen bereitstellen. Darüber hinaus gibt es eine Vielzahl von Ressourcen und Dokumentationen, die Entwicklern helfen, das Beste aus dem Framework herauszuholen.
Insgesamt bietet Skeleton eine einfache und effektive Möglichkeit, ansprechende Benutzeroberflächen für Svelte-Anwendungen zu erstellen, ohne dabei auf Komplexität oder übermäßigen Code zurückgreifen zu müssen. Mit seiner schlanken und minimalistischen Herangehensweise ist Skeleton eine hervorragende Wahl für Entwickler, die eine einfache und benutzerfreundliche UI-Lösung für ihre Svelte-Projekte suchen.
Neues Learning 5: Pocketbase für das Datenmanagement
Um die Benutzerkonten, Testdaten und andere relevante Informationen effizient zu verwalten, haben wir uns für Pocketbase als unsere Datenbanklösung entschieden. Pocketbase bietet eine benutzerfreundliche und skalierbare Plattform für das Speichern und Abrufen von Daten in Echtzeit.
Pocketbase faden wir dabei immer cool, denn wer das süße Maskottchen mal ins herz geschlossen hat, der will es natürlich auch mit Daten füttern !
Warum Pocketbase?
- Einfachheit und Benutzerfreundlichkeit: Pocketbase bietet eine einfache und intuitive Schnittstelle für das Datenmanagement. Durch die Verwendung von Pocketbase konnten wir schnell und effizient Datenbankoperationen durchführen, ohne uns um komplexe Konfigurationen oder Administration kümmern zu müssen.
- Echtzeitdatenbank mit WebSockets: Eine der herausragenden Funktionen von Pocketbase ist die Unterstützung von Echtzeitdatenbanken mit WebSockets. Dies ermöglicht es uns, Daten in Echtzeit zwischen dem Frontend und dem Backend auszutauschen, was besonders wichtig ist für die Synchronisation von Benutzerinteraktionen und Testergebnissen in unserer Anwendung.
Leider haben wir das erst später erfahren. So haben wir unser Websocket nicht mit Pocketbase erstellt… Tja - Skalierbarkeit und Zuverlässigkeit: Pocketbase bietet eine hoch skalierbare und zuverlässige Infrastruktur für das Datenmanagement. Wir können unsere Anwendung problemlos erweitern, wenn die Anforderungen wachsen, und gleichzeitig sicherstellen, dass unsere Daten sicher und geschützt sind.
- Dokumentenorientierte Datenbankstruktur: Pocketbase basiert auf einer dokumentenorientierten Datenbankstruktur, die flexibel und anpassungsfähig ist. Dies ermöglicht es uns, Daten in einer strukturierten und übersichtlichen Weise zu organisieren, ohne uns um komplexe relationale Datenbankmodelle kümmern zu müssen.
- Entwicklerfreundlichkeit: Pocketbase bietet eine Reihe von Entwicklerwerkzeugen und -funktionen, die die Entwicklung und Wartung unserer Anwendung erleichtern. Durch die Verwendung von Pocketbase konnten wir unsere Entwicklungszeit verkürzen und gleichzeitig sicherstellen, dass unsere Anwendung robust und leistungsstark ist.
The comments are closed.