WebSocket-Implementierung für den TI CC3235SF
So entwickeln Sie auf dem Chip von Texas Instruments
eine native Lösung für Echtzeitkommunikation
WebSockets sind heute der Goldstandard für Echtzeitkommunikation in der Softwareentwicklung. Ob IoT-Anwendungen, industrielle Steuerungen oder moderne Webanwendungen – überall dort, wo bidirektionale Kommunikation in Echtzeit gefragt ist, führt kein Weg an WebSockets vorbei.
Doch während die Technologie auf Desktop- und Serverplattformen zum Standard gehört, stehen Embedded-Entwickler oft vor verschlossenen Türen. Ein typisches Beispiel: Der TI CC3235SF. Dieser leistungsfähige Wireless-MCU von Texas Instruments bietet zwar hervorragende Netzwerkfunktionen – aber keine native WebSocket-Unterstützung.
In meiner Entwicklungspraxis habe ich diese Lücke mit einer eigenen WebSockets-Library geschlossen. Sie basiert auf C++ und nutzt die vorhandenen Netzwerk-APIs des Controllers. Das Ergebnis: Eine robuste Lösung, die sich nahtlos in TI-basierte Projekte integrieren lässt.
In diesem Artikel zeige ich Ihnen Schritt für Schritt
- wie Sie performante WebSocket-Implementierungen für den TI CC3235SF entwickeln und in Ihre Embedded-Projekte integrieren,
- welche technischen Voraussetzungen Sie für die WebSocket-Integration auf TI-Plattformen berücksichtigen müssen,
- wie meine WebSocket-Library im Detail funktioniert – mit praxisnahen Code-Beispielen für Ihre eigene Implementierung,
- wie Sie typische Herausforderungen bei der Entwicklung erkennen und mit erprobten Lösungsstrategien meistern können,
- welche Best Practices sich in der praktischen Embedded-Entwicklung mit WebSockets bewährt haben.
Business Impact: Die Bedeutung von Websockets für Ihre Applikationen
Wer technische Produkte entwickelt und vertreibt, steht vor der Herausforderung, sie fit für die Zukunft zu machen. Moderne Echtzeitkommunikation ist dabei ein entscheidender Wettbewerbsfaktor.
Die Implementierung von WebSockets auf TI-Systemen eröffnet Ihnen völlig neue Möglichkeiten: Ihre Produkte reagieren unmittelbar auf Steuerbefehle. Sie können Sensordaten in Echtzeit auswerten. Und Ihre Systeme lassen sich nahtlos in moderne IoT-Architekturen integrieren.
Der entscheidende Vorteil: Sie bleiben unabhängig. Statt auf eine möglicherweise kommende Lösung von Texas Instruments zu warten, können Sie schon heute die Weichen für morgen stellen. Die Investition in eine maßgeschneiderte WebSocket-Implementierung zahlt sich gleich mehrfach aus:
- Sie verkürzen die Entwicklungszeit neuer Features erheblich
- Sie sparen langfristig Kosten durch optimierte Kommunikation
- Sie gewinnen die volle Kontrolle über kritische Systemkomponenten
- Sie schaffen die Grundlage für innovative IoT-Anwendungen
Kurz: Sie machen Ihre Embedded-Systeme zukunftssicher und sichern sich einen technologischen Vorsprung am Markt.
"Als Entwickler fasziniert es mich immer wieder, wie eine scheinbar kleine Technologie wie WebSockets einen so großen Einfluss auf die Performance und die Möglichkeiten eines Systems haben kann. Besonders auf Embedded-Systemen zeigt sich, dass durchdachte Implementierungen den entscheidenden Unterschied machen."
WebSockets verstehen:
Warum moderne Systeme sie benötigen
WebSockets sind ein Kommunikationsprotokoll, das eine bidirektionale, persistente Verbindung zwischen Client und Server ermöglicht. Dies macht sie ideal für Echtzeitanwendungen wie IoT-Datenströme, industrielle Steuerungen oder vernetzte Sensorsysteme.
Der Unterschied zwischen
WebSockets und klassischem HTTP
Im Gegensatz zu HTTP, das auf einem Request-Response-Modell basiert, erlauben es WebSockets dem Server, aktiv Nachrichten an den Client zu senden, ohne dass dieser zuvor eine Anfrage stellen muss. Dies hat entscheidende Vorteile:
- Die bidirektionale Kommunikation ermöglicht eine echte Echtzeit-Interaktion, da Server und Client jederzeit unabhängig voneinander Daten austauschen können.
- Durch persistente Verbindungen reduziert sich die Latenz auf ein Minimum. Ihre Anwendungen reagieren dadurch praktisch verzögerungsfrei auf Ereignisse.
- Der deutlich reduzierte Overhead führt zu einer erheblich geringeren Netzwerklast. Dies macht Ihre Systeme insgesamt effizienter und kostengünstiger im Betrieb.
- Die effiziente Ressourcennutzung wirkt sich positiv auf Server-Infrastruktur und Energieverbrauch aus. Sie sparen dadurch messbar Betriebskosten.
Für die Echtzeitkommunikation stehen verschiedene Protokolle zur Verfügung. Neben WebSockets ist vor allem MQTT im IoT-Bereich verbreitet – beide überwinden die Einschränkungen des klassischen HTTP. Für unsere Implementierung auf dem TI CC3235SF setzen wir auf WebSockets, da sich diese durch ihre bidirektionale TCP-Verbindung besonders flexibel in bestehende Webanwendungen integrieren lassen.
Praxisrelevante Einsatzgebiete von WebSockets
- IoT-Kommunikation: In IoT-Anwendungen ermöglichen WebSockets die Echtzeitkommunikation zwischen Sensoren und Aktoren. Die direkte bidirektionale Kommunikation erlaubt eine präzise Steuerung der Geräte. Insbesondere Smart Home Systeme profitieren von der nahtlosen Integration aller Komponenten.
- Industrielle Anwendungen: WebSockets bilden die Basis für die verzögerungsfreie Steuerung von Maschinen und Anlagen. Prozessdaten werden in Echtzeit überwacht und ausgewertet. Selbst komplexe verteilte Systeme arbeiten dank stabiler Verbindungen synchron zusammen.
- Daten-Streaming: Die kontinuierliche Übertragung von Audio- und Videodaten profitiert von der effizienten WebSocket-Kommunikation. Sensordaten werden verzögerungsfrei ausgewertet und Prozesse lückenlos dokumentiert.
- Remote Collaboration: Teams an verschiedenen Standorten können synchron an Projekten arbeiten. Status-Updates erfolgen in Echtzeit, und selbst komplexe Maschinen lassen sich aus der Ferne präzise steuern.
- Chat-Anwendungen: Moderne Messaging-Systeme nutzen WebSockets für die unmittelbare Zustellung von Nachrichten. Support-Teams können so in Echtzeit mit Kunden kommunizieren und schnell auf Anfragen reagieren.
- Live-Updates: WebSockets sorgen dafür, dass Börsenkurse und Sportergebnisse ohne Verzögerung beim Nutzer ankommen. Auch dynamische Webinhalte werden sofort aktualisiert.
- Online-Multiplayer-Spiele: Die geringe Latenz von WebSockets ist ideal für Online-Spiele. Spielaktionen werden sofort synchronisiert und der Spielstatus ist für alle Teilnehmer immer auf dem neuesten Stand.
Business Impact:
Was sind Websockets?
Stellen Sie sich vor, Sie telefonieren mit jemandem. Das ist wie bei WebSockets: eine direkte, offene Verbindung, über die beide Seiten jederzeit sprechen können.
Das Gegenteil wäre, wenn Sie immer wieder neu anrufen müssten, um zu fragen "Gibt es was Neues?" – so funktioniert klassisches HTTP. Klar, dass das weder effizient noch echtzeitfähig ist.
WebSockets sind heute der Standard für moderne Kommunikation im Web und IoT-Bereich. Sie ermöglichen direkte, dauerhafte Verbindungen, sofortige Reaktion auf Ereignisse, deutlich geringere Kommunikationskosten und sind die Basis für “echte” Echtzeitanwendungen.
Kurz: WebSockets sind die Technologie, die Ihre vernetzten Produkte wirklich "smart" macht.
Wie sich WebSockets auf
Embedded Systemen unterscheiden
Auf Embedded-Systemen wie dem TI CC3235SF müssen wir bei der WebSocket-Implementierung besondere Vorsicht walten lassen. Die Einschränkungen in Bezug auf Speicher und Rechenleistung erfordern eine durchdachte Herangehensweise:
Effiziente Ressourcennutzung
- Speicheroptimierung: Der Stack-Speicher ist oft sehr begrenzt, weshalb wir auf dynamische Speicherzuweisung auf dem Heap setzen. Smart Pointer wie std::unique_ptr oder std::shared_ptr spielen hier ihre Stärken aus: Sie verhindern Dangling Pointers, schließen Speicherlecks aus und gewährleisten Thread-Sicherheit. Die Pufferverwaltung passen wir dynamisch an die tatsächliche Nachrichtengröße an, statt statische Puffer für maximale Größen vorzuhalten. Speziell optimierte Heap-Manager und Pool-Allokatoren reduzieren die Fragmentierung.
- Prozessorleistung: Das WebSocket-Protokoll erfordert die Maskierung von Datenframes durch eine XOR-Operation mit einem 4-Byte-Schlüssel. Auf dem TI CC3235SF mit 80 MHz SoC und RTOS ist dies normalerweise unkritisch – XOR ist effizient, die WebSocket-Task läuft isoliert, und typische Anwendungen haben moderate Nachrichtenfrequenzen. Nur bei extremen Anforderungen (>1000 Nachrichten/Sekunde mit großen Datenmengen) oder rechenintensiven parallelen Tasks könnte es zu Engpässen kommen.
- Energieeffizienz: Da Embedded-Systeme oft batteriebetrieben sind, optimieren wir sowohl das Speicher- als auch das Netzwerkmanagement für minimalen Stromverbrauch. Eine dynamische Speicherzuweisung vermeidet unnötige Allokationen, während der gezielte Einsatz von Stromsparmodi den Verbrauch minimiert.
Präzise Steuerung der Netzwerkverbindungen
- Verbindungsmanagement: Ein dynamisches Management stellt sicher, dass Ressourcen nur bei Bedarf gebunden werden. Automatische Wiederverbindungen mit Backoff-Strategien minimieren den Ressourcenverbrauch bei instabilen Netzwerken.
- Threading und Synchronisation: Das RTOS ermöglicht eine präzise Trennung von Tasks. Durch Mutexes und Smart Pointer verhindern wir Race Conditions und Deadlocks. Die Socket-Operationen sind thread-sicher implementiert, um fehlerhafte Speicherfreigaben auszuschließen.
Business Impact: Besonderheiten von Embedded-Systemen
Bei Embedded-Systemen geht es um mehr als nur "es muss funktionieren". Diese kleinen, meist batteriebetriebenen Geräte bieten weniger Leistung und weniger "Stauraum" und sind meist von der Batterie abhängig. Sie stellen besondere Anforderungen an die Software-Entwicklung:
- Ressourcen sind begrenzt: Wie bei einem Kleinwagen muss jedes PS und jeder Liter Tankvolumen optimal genutzt werden.
- Energieeffizienz ist entscheidend: Die Embedded-Systeme sollen oft monatelang mit einer Batterieladung auskommen.
- Zuverlässigkeit ist ein Muss: Im Gegensatz zu PC-Software sind Neustarts oder Updates nicht jederzeit möglich.
Mit der richtigen WebSocket-Implementierung meistern Sie diese Herausforderungen. Das Ergebnis: Langlebige, zuverlässige Systeme, die genau das tun, was sie sollen – ohne Kompromisse bei der Performance.
Der TI CC3235SF als Plattform für WebSocket-Implementierungen
Der TI CC3235SF ist ein leistungsfähiger Mikrocontroller von Texas Instruments, der speziell für die sichere und zuverlässige Netzwerkkommunikation in IoT- und Embedded-Anwendungen entwickelt wurde. Er kombiniert einen robusten Prozessor mit integrierter WLAN-Funktionalität – eine ideale Basis für WebSocket-Implementierungen.
Technische Vorteile des Controllers
- Integrierte Wi-Fi-Funktionalität: Der CC3235SF bietet einen integrierten Wi-Fi-Chip, der nahtlos mit der MCU interagiert. Dadurch können Entwickler direkt mit Netzwerkprotokollen wie TCP/IP arbeiten. Ein entscheidender Vorteil für die schnelle und effiziente Implementierung von WebSocket-Anwendungen.
- Flexible Netzwerk-API: Die sl_netsock-Bibliothek von Texas Instruments bietet eine flexible Schnittstelle für die Socket-Programmierung. Sie dient als solide Basis für die WebSocket-Implementierung und ermöglicht eine zuverlässige Netzwerkkommunikation auf professionellem Niveau.
- Sicherheitsfunktionen: Dank der integrierten Hardware-Verschlüsselungseinheit und Funktionen wie TLS/SSL eignet sich der CC3235SF hervorragend für die sichere Kommunikation. Gerade in WebSocket-Anwendungen, wo dauerhafte Verbindungen bestehen, ist dies ein unschätzbarer Vorteil für die Produktsicherheit.
- Energiemanagement: Durch die Unterstützung von Stromsparmodi und einem optimierten Netzwerk-Stack können auch energieeffiziente Anwendungen mit WebSockets realisiert werden. Dies ermöglicht den Einsatz in batteriebetriebenen Geräten mit langen Laufzeiten.
Business Impact: Warum dieser
Chip von Texas Instruments?
Der TI CC3235SF Mikrocontroller ist wie ein Schweizer Taschenmesser für die vernetzte Welt: Er bringt alles mit, was moderne IoT-Geräte brauchen. WLAN ist bereits integriert, Sicherheitsfunktionen sind an Bord, und der Stromverbrauch ist optimiert. Ein hochwertiges Elektronikmodul – bewährt, kostengünstig und millionenfach im Einsatz.
Produkte von einem Anbieter wie Texas Instruments garantieren zudem kurze Lieferzeiten und langfristige Verfügbarkeit. Besonders wertvoll für Entwickler: Die Möglichkeit zur Low-Level-Programmierung bis zur TCP/IP-Ebene gibt volle Kontrolle über die Implementation.
Das Einzige, was "ab Werk" fehlt, ist die WebSocket-Unterstützung. Aber genau hier setzen wir an: Mit der richtigen Expertise erweitern wir den Chip genau um die Funktionen, die Ihr Produkt braucht.
"Die Entwicklung für Embedded-Systeme ist wie Tetris auf Profi-Niveau: Jedes Byte muss optimal platziert werden, und am Ende muss alles nahtlos ineinander greifen. Bei der WebSocket-Implementierung auf dem TI CC3235SF ist genau diese Art der Optimierung die spannendste Herausforderung."
Entwicklungsprozess meiner
WebSocket-Library für den TI CC3235SF
Architektur der Library
Die Architektur der von mir entwickelten Websockets-Library für den TI CC3235SF basiert auf einer klaren Trennung von Aufgaben und Verantwortlichkeiten, um Flexibilität, Effizienz und einfache Wartbarkeit zu gewährleisten. Die Integration erfolgt in einem RTOS-Umfeld und nutzt Tasks sowie Event-Mechanismen, um eine zuverlässige Websocket-Kommunikation zu ermöglichen.
Der WebSocket-Task im RTOS
Im Zentrum der Library steht ein dedizierter Websocket-Task, der innerhalb des RTOS ausgeführt wird. Dieser Task steuert die gesamte Websocket-Kommunikation und enthält die folgenden wichtigen Komponenten:
Event Listener
Der Event Listener ist die zentrale Komponente, die auf eingehende Ereignisse reagiert und diese an die entsprechenden Module weiterleitet. Zu den Ereignissen, die der Listener verarbeitet, gehören:
- Verbindung öffnen: Startet den Verbindungsaufbau, einschließlich des HTTP-Upgrade-Mechanismus.
- Daten senden: Löst die Übertragung von Daten über die WebsocketConnection aus. Der Datenaustausch mit anderen Tasks erfolgt dabei über einen Mutex-Lock, um gleichzeitige Zugriffe auf freigegebene Ressourcen zu verhindern.
- Daten empfangen: Über das regelmäßige Receive-Event prüft die Library, ob neue Daten vom Server vorliegen. Auch hier wird der Zugriff auf freigegebene Ressourcen durch einen Mutex-Lock geschützt, um Konflikte bei der Verarbeitung der Daten zu vermeiden.
- Verbindung schließen: Initiiert das geordnete Schließen einer Verbindung.
Diese Ereignisse werden von parallelen Tasks im RTOS ausgelöst, wodurch verschiedene Funktionen unabhängig voneinander gesteuert werden können.
Timer für regelmäßiges Receive-Event
Ein integrierter Timer, der alle 50 Millisekunden ein Receive-Event auslöst, ist ein wesentlicher Bestandteil des Tasks. Dieses Event dient dazu, regelmäßig die Methode sl_netsock_receive() über die WebsocketConnection aufzurufen. Dadurch wird geprüft, ob neue Daten vom Server empfangen wurden. Dieses polling-basierte Design stellt sicher, dass eingehende Nachrichten zeitnah erkannt werden, auch wenn keine expliziten Events vom Netzwerk ausgelöst werden.
Kritische Fehlerbehandlung
Der Websocket-Task überwacht den Rückgabestatus aller aufgerufenen Methoden. Falls ein kritischer Fehler gemeldet wird – beispielsweise bei fehlerhaften Nachrichten oder Übertragungsfehlern –, schließt der Websocket-Task die Verbindung automatisch und führt alle erforderlichen Aufräumarbeiten durch.
Klassenstruktur der WebSocket-Library
Die von mir entwickelte Library ist in zwei Hauptklassen organisiert: WebsocketClient und WebsocketConnection. Diese arbeiten zusammen, um eine flexible und skalierbare Architektur zu schaffen.
WebsocketClient
Der WebsocketClient verwaltet die Verbindungen zu einem Server. Er ist dafür zuständig, mehrere Verbindungen parallel zu betreiben, deren Zustände zu überwachen und diese effizient zu koordinieren. Jede Verbindung wird durch eine Instanz der WebsocketConnection-Klasse repräsentiert. Zusätzlich übernimmt der WebsocketClient die folgende zentrale Aufgabe:
- Erzeugung und Übergabe von Websocket-Frames: Der WebsocketClient erstellt Instanzen der Klasse WebsocketFrame, die die Struktur der zu sendenden Daten im Websocket-Protokollformat definieren. Diese Frames werden im WebsocketClient erstellt und anschließend an die entsprechende WebsocketConnection-Instanz weitergereicht. Dies trennt die Protokoll-Logik (Frame-Erstellung) klar von der Low-Level-Datenübertragung (Connection).
- Fehlerweiterleitung: Jede Methode im WebsocketClient liefert einen Statuswert zurück, der den Erfolg oder Misserfolg der ausgeführten Aktion anzeigt. Bei einem fehlerhaften Status wird dieser an den Websocket-Task zurückgemeldet. Der WebsocketClient schließt selbst keine Verbindungen, sondern überlässt die Entscheidung über das weitere Vorgehen dem Websocket-Task.
WebsocketConnection
Die WebsocketConnection-Klasse repräsentiert eine einzelne Websocket-Verbindung (Endpunkt). Sie ist verantwortlich für die konkrete Umsetzung der Verbindung und unterstützt die folgenden Kernfunktionen:
- Verbindung öffnen: Beim Öffnen einer Verbindung initiiert die WebsocketConnection den HTTP Upgrade-Mechanismus, um die Verbindung von HTTP auf das Websocket-Protokoll umzustellen. Der Prozess umfasst den HTTP-Handshake, die Validierung der Serverantwort und den Wechsel zum Websocket-Protokoll. Dieses Ereignis wird durch einen parallelen Task im RTOS ausgelöst.
- Daten senden: Die WebsocketConnection stellt eine Methode zum Senden von Daten an den Server bereit. Diese nutzt die sl_netsock BSD-API, um die Datenübertragung auf niedriger Ebene effizient durchzuführen. Ein separates RTOS-Event triggert den Datenversand, wodurch parallele Tasks diese Funktion nutzen können. Der Datenaustausch zwischen Tasks erfolgt durch Mutex-Locks, die sicherstellen, dass Zugriffe auf gemeinsam genutzte Datenstrukturen wie Sendepuffer kontrolliert und konfliktfrei sind.
- Daten empfangen: Über das regelmäßige Receive-Event (alle 50 ms durch den Timer ausgelöst) wird geprüft, ob neue Daten vom Server verfügbar sind. Die Daten werden bei Verfügbarkeit sofort verarbeitet und an die übergeordneten Komponenten weitergeleitet. Empfangene Daten werden durch Mutex-Locks geschützt, um sicherzustellen, dass parallele Tasks nicht gleichzeitig auf den Datenpuffer zugreifen und so Datenkorruption verhindern.
- Verbindung schließen: Die Klasse bietet Funktionen zum geordneten Schließen einer Websocket-Verbindung. Dazu gehören die Benachrichtigung des Servers, das Freigeben von Ressourcen und die Aktualisierung des Verbindungsstatus. Auch dieser Prozess wird durch ein RTOS-Event ausgelöst.
- Status-Rückgabewerte: Alle Methoden der WebsocketConnection geben Statuswerte zurück, die den Erfolg oder Fehler der ausgeführten Operation anzeigen. Die WebsocketConnection selbst schließt jedoch keine Verbindungen. Stattdessen überlässt sie die Entscheidung über das weitere Vorgehen (z. B. Fehlerbehandlung oder Verbindungsabbruch) dem Websocket-Task über den WebsocketClient.
- Low-Level-Kommunikation: Sie verwendet die sl_netsock BSD-API, um die grundlegenden Netzwerkoperationen wie Senden und Empfangen von Daten durchzuführen.
Durch die Kapselung dieser Mechanismen in der WebsocketConnection-Klasse bleibt die Logik für den Verbindungsaufbau übersichtlich und anwenderfreundlich.
Interaktion und Stärken des WebSocket-Architekturkonzepts
Zusammenspiel der Library-Komponenten
- Der Websocket-Task agiert als zentrale Steuerung, die Verbindungen verwaltet und auf Statuswerte der WebsocketClient- und WebsocketConnection-Methoden reagiert. Kritische Fehler führen dazu, dass der Task die Verbindung schließt und alle Ressourcen freigibt.
- Der WebsocketClient erstellt Websocket-Frames, verarbeitet Rückgabewerte der WebsocketConnection und leitet Statusinformationen an den Websocket-Task weiter.
- Die WebsocketConnection übernimmt die konkreten Verbindungsoperationen – vom Aufbau und der Datenübertragung bis zum Übermitteln von Statuswerten – und ermöglicht so eine klare Trennung zwischen Low-Level-Operationen und dem Verbindungsmanagement.
Vorteile dieser Library-Architektur
- Robuste Fehlerbehandlung: Durch die zentrale Fehlerbehandlung im Websocket-Task wird sichergestellt, dass Verbindungen zuverlässig geschlossen werden und das System konsistent bleibt.
- Synchronisation: Durch den Einsatz von Mutex-Locks wird der parallele Zugriff auf freigegebene Ressourcen konfliktfrei und sicher.
- Ereignisgesteuert: Parallele Tasks können flexibel auf Verbindungen zugreifen, ohne sich gegenseitig zu blockieren.
- Effizienz: Der Timer-basierte Ansatz stellt sicher, dass eingehende Daten zuverlässig erkannt und verarbeitet werden.
- Modularität: Die klare Trennung von Aufgaben erleichtert die Wartung und Erweiterung.
- Flexibilität: Die Protokoll-Logik (WebsocketFrame) ist im WebsocketClient zentralisiert, während die Low-Level-Kommunikation durch die WebsocketConnection abstrahiert wird.
Codebeispiele für die WebSocket-Implementierung
Da der TI CC3235SF von Texas Instruments keine native WebSocket-Unterstützung bietet, zeigen wir Ihnen hier minimale Implementierungen der wichtigsten Komponenten.
Diese Code-Beispiele basieren auf der zuvor beschriebenen Architektur und können als Ausgangspunkt für Ihre eigene WebSocket-Implementierung auf dem TI CC3235SF dienen. Mit diesem Code erweitern Sie den Controller um die fehlende WebSocket-Funktionalität.
Codebeispiel für minimalen WebSocket Task
Der Websocket Task ist die zentrale Steuerungseinheit, die auf Ereignisse reagiert, den WebsocketClient aufruft und Verbindungen bei kritischen Fehlern schließt.
#include#include #include #include "WebsocketClient.h" // Event IDs #define EVENT_OPEN_CONNECTION (1 << 0) #define EVENT_SEND_DATA (1 << 1) #define EVENT_RECEIVE_DATA (1 << 2) #define EVENT_CLOSE_CONNECTION (1 << 3) // Globale Event-Objekte Event_Handle websocketEvent; // Timer Callback für das Empfangen-Event void receiveTimerCallback(UArg arg) { Event_post(websocketEvent, EVENT_RECEIVE_DATA); } // Websocket Task void WebsocketTask(UArg arg0, UArg arg1) { WebsocketClient wsClient; Event_Handle websocketEvent = (Event_Handle)arg0; // Event-Handle aus Argument while (true) { // Warten auf ein Event UInt postedEvents = Event_pend(websocketEvent, Event_Id_NONE, EVENT_OPEN_CONNECTION | EVENT_SEND_DATA | EVENT_RECEIVE_DATA | EVENT_CLOSE_CONNECTION, BIOS_WAIT_FOREVER); if (postedEvents & EVENT_OPEN_CONNECTION) { // Verbindung öffnen int status = wsClient.openConnection("wss://example.com", 443); if (status != WS_SUCCESS) { printf("Error opening connection: %d\n", status); continue; } } if (postedEvents & EVENT_SEND_DATA) { // Daten senden int status = wsClient.sendData("Hello, Server!"); if (status != WS_SUCCESS) { printf("Error sending data: %d\n", status); Event_post(websocketEvent, EVENT_CLOSE_CONNECTION); } } if (postedEvents & EVENT_RECEIVE_DATA) { // Daten empfangen char buffer[256]; int status = wsClient.receiveData(buffer, sizeof(buffer)); if (status != WS_SUCCESS) { printf("Error receiving data: %d\n", status); Event_post(websocketEvent, EVENT_CLOSE_CONNECTION); } else { printf("Received data: %s\n", buffer); } } if (postedEvents & EVENT_CLOSE_CONNECTION) { // Verbindung schließen wsClient.closeAllConnections(); printf("Connection closed.\n"); } } } // Initialisierung des Websocket Tasks und Timers void setupWebsocketTask() { // Event erstellen websocketEvent = Event_create(NULL, NULL); // Websocket Task erstellen Task_Params taskParams; Task_Params_init(&taskParams); taskParams.arg0 = (UArg)websocketEvent; taskParams.stackSize = 1024; Task_create(WebsocketTask, &taskParams, NULL); // Timer für Empfangen-Event erstellen Clock_Params clockParams; Clock_Params_init(&clockParams); clockParams.period = 50; // 50 ms Timer clockParams.startFlag = TRUE; Clock_create(receiveTimerCallback, 50, &clockParams, NULL); }
Codebeispiel für minimalen WebsocketClient:
Der WebsocketClient verwaltet Verbindungen und kommuniziert mit der WebsocketConnection. Es gibt Methoden zum Öffnen, Senden, Empfangen und Schließen von Verbindungen.
#include "WebsocketConnection.h" #include "WebsocketFrame.h" #includeclass WebsocketClient { private: std::vector connections; public: int openConnection(const char* url, int port) { WebsocketConnection* conn = new WebsocketConnection(); int status = conn->open(url, port); if (status == WS_SUCCESS) { connections.push_back(conn); } return status; } int sendData(const char* data) { WebsocketFrame frame(data); for (auto conn : connections) { int status = conn->send(frame); if (status != WS_SUCCESS) { return status; } } return WS_SUCCESS; } int receiveData(char* buffer, size_t bufferSize) { for (auto conn : connections) { int status = conn->receive(buffer, bufferSize); if (status != WS_SUCCESS) { return status; } } return WS_SUCCESS; } static void closeAllConnections() { for (auto conn : connections) { conn->close(); delete conn; } connections.clear(); } };
Codebeispiel für minimale WebSocketConnection:
Die WebsocketConnection kümmert sich um die Low-Level-Kommunikation mit der sl_netsock BSD-API.
#include "sl_netsock.h
#include "WebsocketFrame.h"
class WebsocketConnection {
private:
int socket;
public:
int open(const char* url, int port) {
// Beispiel für HTTP Upgrade
socket = sl_netsock_create();
if (socket < 0) {
return WS_ERR_SOCKET_CREATE;
}
int status = sl_netsock_connect(socket, url, port);
if (status < 0) {
return WS_ERR_CONNECT;
}
// Senden des HTTP Upgrade-Requests
status = sendHttpUpgrade();
// TODO: Antwort vom Server prüfen
return (status == WS_SUCCESS) ? WS_SUCCESS : WS_ERR_UPGRADE;
}
int receive(char* buffer, size_t bufferSize) {
int status = sl_netsock_receive(socket, buffer, bufferSize);
return (status >= 0) ? WS_SUCCESS : WS_ERR_RECEIVE;
}
void close() {
sl_netsock_close(socket);
}
private:
int sendHttpUpgrade() {
// HTTP Upgrade-Request senden (vereinfacht)
const char* upgradeRequest = "GET / HTTP/1.1\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"\r\n";
int status = sl_netsock_send(socket, upgradeRequest, strlen(upgradeRequest));
return (status >= 0) ? WS_SUCCESS : WS_ERR_UPGRADE;
}
};
Codebeispiel für minimalen WebSocketFrame
Der WebSocketFrame kapselt die Protokoll-spezifische Struktur der zu übertragenden Daten. Die Implementierung zeigt die grundlegende Frame-Konstruktion.
class WebsocketFrame {
private:
std::vector frameData;
public:
WebsocketFrame(const char* data) {
// Frame erstellen (vereinfacht)
frameData.push_back(0x81); // Text-Frame mit FIN-Flag
frameData.push_back(strlen(data));
frameData.insert(frameData.end(), data, data + strlen(data));
}
const char* data() const { return frameData.data(); }
size_t size() const { return frameData.size(); }
};
Praxistipps für eine erfolgreiche Implementierung von WebSockets auf dem Chip von Texas Instruments
Die Implementierung einer Websocket-Library auf dem TI CC3235SF von Texas Instruments ist nur der erste Schritt. In der Praxis müssen Sie auch auf Sonderfälle und Benutzerinteraktionen vorbereitet sein. Ich zeige Ihnen, wie Sie typische Fallstricke vermeiden und eine robuste Anwendung erstellen.
Prüfung der WLAN-Verbindung vor jedem Aufruf
Eine häufige Fehlerquelle bei Websocket-Implementierungen ist der Umgang mit instabilen WLAN-Verbindungen. Ohne entsprechende Prüfungen können verlorene Verbindungen zu schwer auffindbaren Fehlern und Ressourcenlecks führen. So gehen Sie das Problem an:
-
Empfehlung: Vor jeder Operation wie dem Senden oder Empfangen von Daten sollte geprüft werden, ob eine gültige WLAN-Verbindung zum Internet besteht:
- Wenn keine Verbindung besteht, muss die Websocket-Verbindung sofort durch Aufruf von SlNetSock_close() geschlossen werden.
- Ressourcen sollten anschließend freigegeben werden, um Speicher- und Sockets-Leaks zu verhindern.
- Umsetzung: Die Verbindungsprüfung kann direkt im Websocket-Task oder im WebsocketClient erfolgen. Eine zentrale Funktion zur Statusüberprüfung ist empfehlenswert.
-
Beispiel:
bool isWifiConnected() { // Implementierung zur Prüfung, ob WLAN aktiv und verbunden ist return sl_wlan_is_connected(); // Beispiel-Funktion } void checkAndCloseConnection(WebsocketClient& wsClient) { if (!isWifiConnected()) { printf("WiFi disconnected. Closing Websocket connection...\n"); wsClient.closeAllConnections(); } } -
Integriert im Websocket-Task:
if (!isWifiConnected()) { Event_post(websocketEvent, EVENT_CLOSE_CONNECTION); }
Verbindungstrennungen bei Benutzeraktionen
Was passiert, wenn ein Benutzer das WLAN-Modul ausschaltet oder ein WLAN-Profil löscht, während eine WebSocket-Verbindung aktiv ist? Ohne entsprechende Vorkehrungen führen solche abrupten Unterbrechungen zu inkonsistenten Zuständen in Ihrer Anwendung. Ich zeige Ihnen, wie Sie dies proaktiv behandeln:
-
Empfehlung: Bevor eine Benutzeraktion wie das Ausschalten von WiFi oder das Löschen eines WLAN-Profils durchgeführt wird, muss die Websocket-Verbindung zum Server ordnungsgemäß geschlossen werden. Dies umfasst:
- Senden eines Websocket-Close-Frames an den Server.
- Freigeben aller verwendeten Ressourcen, einschließlich Sockets.
- Sicherstellen, dass keine verbleibenden Threads oder Tasks auf die Verbindung zugreifen.
- Umsetzung: Diese Logik sollte in einem separaten Task implementiert werden, der Benutzeraktionen überwacht. Der Task sollte ein Event auslösen, um dem Websocket-Task zu signalisieren, dass die Verbindung geschlossen werden muss.
-
Beispiel:
void handleUserAction(Event_Handle websocketEvent) { // Benutzeraktion erkannt (z. B. WiFi powered off) printf("User action detected: WiFi powered off\n"); Event_post(websocketEvent, EVENT_CLOSE_CONNECTION); }
Warum diese Absicherungen wichtig sind
Die vorgestellten Implementierungsdetails für Embedded-Systeme wie dem TI CC3235SF sind entscheidend für die Zuverlässigkeit der gesamten Anwendung.
Hier sind die wichtigsten Gründe:
- Vermeidung von Inkonsistenzen: Wenn Verbindungen abrupt unterbrochen werden - sei es durch Benutzeraktionen oder instabile WLAN-Verbindungen - drohen fehlerhafte Zustände in der Anwendung. Nur durch kontrolliertes Schließen der Verbindung bleiben die Daten konsistent.
- Schonung von Ressourcen: Ein Socket, der nicht ordnungsgemäß geschlossen wird, blockiert wertvolle Systemressourcen. Besonders kritisch: Tasks, die weiterhin auf nicht mehr existierende Verbindungen zugreifen, können Speicherlecks verursachen.
- Robustheit der Anwendung: Je besser Ihre Anwendung auf unerwartete Ereignisse vorbereitet ist, desto stabiler läuft sie im Produktivbetrieb. Die systematische Behandlung von Verbindungsabbrüchen ist dabei ein entscheidender Faktor.
Fazit: WebSocket-Implementierung
für den TI CC3235SF
Die Implementierung von WebSockets auf dem TI CC3235SF mag zunächst herausfordernd erscheinen, ist aber mit dem richtigen Architekturansatz gut zu meistern. Die vorgestellte Library-Struktur für WebSockets mit ihrer klaren Trennung von Tasks, Client und Connection bietet eine robuste Grundlage für zuverlässige Echtzeit-Kommunikation.
Technische Erkenntnisse:
- Die dreigliedrige Architektur ermöglicht eine saubere Kapselung der Funktionalitäten
- Event-basierte Steuerung und systematische Fehlerbehandlung sorgen für Stabilität
- Sorgfältige Ressourcenverwaltung ist auf Embedded-Systemen entscheidend
Praxiserfahrungen:
- Besonderes Augenmerk verdient die WLAN-Verbindung und deren Überwachung
- Benutzerinteraktionen müssen proaktiv behandelt werden
- Regelmäßiges Testen unter realen Bedingungen ist unerlässlich
Ausblick: Die hier vorgestellte Implementierung lässt sich je nach Anforderung erweitern – etwa um zusätzliche Sicherheitsfunktionen oder spezifische Protokoll-Erweiterungen. Der modulare Aufbau erleichtert solche Anpassungen erheblich.