2010-11-30 5 views
4

Ich arbeite mit einem eingebetteten Gerät, das über RS232 mit dem PC verbunden ist.Wie könnte ich ein serielles Kommunikationsprotokoll in einer objektorientierten Form implementieren?

Ich muss eine Software zur Kommunikation mit diesem Embedded-Gerät tun.

Ich programmiere in Delphi. Ich habe in der Vergangenheit nie objektorientiert gearbeitet. Aber ich versuche das zu ändern.

Ich bin nicht in der Lage, objektorientiert zu denken, um dieses Problem zu lösen.

Ich habe dieses Protokoll:

<STX><STX><COMMAND>[<DATA><DATA>...]<CHKSUM><ETX> 

wo:

<STX> is the Start of TeXt (0x55); 
<COMMAND> can be 0x01 for read, 0x02 for write, etc; 
<DATA> is any value; 
<CHKSUM> is the checksum; 
<ETX> is the End of TeXt (0x04). 

Die Software Computer einen Befehl über die serielle senden wird, und das Gerät wird antworten, das gleiche Protokoll.

Zum Beispiel:

Reset command 
PC sends  : <STX><STX><0x09><0x00><CHKSUM><ETX> 
Device answer: <STX><STX><0x09><0x00><CHKSUM><ETX> 

Get Version 
PC sends  : <STX><STX><0x00><0x02><CHKSUM><ETX> 
Device answer: <STX><STX><0x00><0x00><VER_L><VER_H><CHKSUM><ETX> 

Ich habe eine Datei-Stream an das Gerät zu senden.

Ich möchte Vorschläge und/oder Beispiele für die beste Art und Weise erhalten, dies in einer objektorientierten Weise zu implementieren. Ich würde gerne auch einen Unit-Test machen können.

Dank

+0

Serielle Kommunikation benötigt eine State-Machine, um gut zu funktionieren. Es gibt viele Möglichkeiten, objektorientierte Zustandsautomaten zu machen. – mj2008

Antwort

0

Sortieren von hart von der geringen Menge an Informationen zu beantworten, aber ich habe, ist hier, wie ich es tun würde:

Entweder Klasse, die weiß, wie themself serialisiert werden oder Sie nutzen die Besucher Muster für die Serialisierung. Dies hat den Vorteil, dass Sie Ihre Daten von der Serialisierung entkoppeln und andere Serialisierungsmechanismen einfacher implementieren können.

Ich hätte also eine Datenklasse, eine Command-Klasse, die eine Sammlung von Daten (wählen Sie Ihren bevorzugten Container) enthält. Die Command-Klasse würde wahrscheinlich die Prüfsummenberechnung mit einer öffentlichen Methode durchführen. Ich hätte auch eine Kommunikationsklasse, um den Befehl zu kapseln und die Kommunikation zu beginnen und zu beenden. Dann hätte ich eine Klasse, die für die Schnittstelle mit dem seriellen Port verantwortlich ist, die eine Send-Methode hätte, die eine Referenz auf die Kommunikationsklasse nehmen würde.

Aus den verfügbaren Informationen kann ich mit dem Design kommen.

Wie für Komponententest, mit einem guten Design, sollten Sie in der Lage, fast alles zu testen. Denken Sie daran, Stubs zu verwenden, damit Sie während des Testens nicht auf diese serielle Schnittstelle stoßen. Erstellen Sie eine gefälschte serielle Kommunikationsklasse, die beispielsweise in eine Zeichenfolge schreibt, und vergleichen Sie die ausgegebene Zeichenfolge mit dem erwarteten Wert.

1

Nun, ich denke, es gibt so viele Lösungen wie es Programmierer gibt. Ohne mehr über Ihr System zu wissen, würde ich wahrscheinlich mit diesem Ansatz gehen:

Erstellen Sie eine Basisbefehlsklasse, sagen wir mal; TBaseCommand. Definieren Sie Ihre gemeinsame Schnittstelle auf dieser Ebene, wie Send(), Receive(), Run() usw.

Füllen Sie nur Code für Funktionen für alle Befehle, wie Senden, Empfangen usw. ...

Funktionen, die sich in der Ausführung unterscheiden, werden virtualisiert, um in der nächsten Schicht definiert zu werden. Hieraus eine neue Klasse für jeden Befehl ableiten und den befehlsspezifischen Code, z. B. Run(), ausfüllen.

Mit Run() können Sie leicht Ihre Befehle auf dem Bildschirm simulieren, indem Sie die Funktion Run() überschreiben.

, und sind Ihr Transportprotokoll und sollten von Ihrer Kommunikationsschnittstelle (separate Protokollklasse?) Angewendet und entfernt werden. Ihre Protokollklasse kann auch Prüfsummenfehler verarbeiten und versuchen, sie erneut zu senden. Wenn sie nicht gelöst werden kann, melden Sie einen Fehler.

Dies war nur ein paar Dinge auf meinem Kopf mit Ihrer begrenzten Beschreibung ...

3

Sie in anderen seriellen Sende aussehen sollte/Kommunikationsmodelle, wie zum Beispiel HTTP erhalten. In .NET sammelt das HTTPWebRequest-Objekt alle Informationen, die über die Leitung gesendet werden sollen - einschließlich Befehl (HTTP METHOD: GET, PUT, POST usw.) und Byte-Stream. Das HTTPWebRequest-Objekt (und der HTTP-Stack) behandelt intern den "Papierkram" der Berechnung von Prüfsummen der Daten, Chunking von großen Daten in kleinere Pakete usw. Alles, was Ihr Code tun muss, ist das Request-Objekt aufzubauen, den Befehl zu setzen, a zuzuweisen Datenstrom an die Eigenschaft des Anforderungsobjekts senden und senden.

Ein weiterer Grund, warum Sie sich bestehende Kommunikationsobjektmodelle wie .NET HTTP ansehen sollten, ist, dass serielle Kommunikationen aus der Perspektive Ihrer Host-CPU im Allgemeinen asynchron sind. Während der Übertragung der Zeichen der Anforderung auf der seriellen Schnittstelle und während auf die Antwort gewartet wird, kann viel CPU-Zeit verstreichen. Verwenden Sie ein asynchrones Modell für Ihre Anfrage/Antwort, damit Sie den aufrufenden Thread nicht blockieren und Ihre Benutzeroberfläche möglicherweise einfrieren.

Zum Fortsetzen des .NET HTTP-Beispiels verfügt HTTPWebRequest über eine GetResponse-Methode, die die Anforderung sendet und den aufrufenden Thread blockiert, bis eine Antwort empfangen wird. HTTPWebRequest verfügt außerdem über ein BeginGetResponse()/EndGetResponse() - Paar, sodass Sie die Anforderung senden und einen Rückruf bereitstellen können, der ausgeführt wird, wenn die Antwort zu einem späteren Zeitpunkt eintrifft.

Auch wenn Ihr sofortiges Design mit einem Thread-blockierenden synchronen Aufrufmodell in Ordnung ist, sollten Sie zumindest asynchrone Codierungsmuster untersuchen und in Betracht ziehen, Ihr Objekt als solches zu implementieren. Sie können eine asynchrone Methode immer syntax-Thread-blockierend aufrufen, aber es ist viel schwieriger, eine synchrone Methode asynchron aufzurufen. Investieren Sie jetzt etwas Zeit, um sich weitere Optionen zu bieten.

+0

Das sind riesige Protokolle mit einer Komplexität weit über seine Bedürfnisse hinaus. Halte es einfach! Die empfohlene Methode (von Microsoft) besteht darin, Threads für TX und RX zu verwenden, wobei die Überlappungsstruktur auf Ereignisse wartet. Sobald es nichts zu tun gibt, werden die Fäden schlafen und den Prozess freimachen. –

+2

Ich habe nicht vorgeschlagen, dass er HTTP verwendet, um serielle Kommunikation zu implementieren. Er fragte nach Ideen, wie man ein Objektmodell anordnen könnte. Er sollte ein asynchrones Aufrufobjektmodell verwenden, und HTTP ist ein weit verbreitetes Modell, um nach Ideen zu suchen, was in Ihrem eigenen asynchronen Objektmodell erstellt werden soll. Die überlappende E/A-Struktur der API bietet keine Anleitung zum Erstellen eines bequemen und robusten Objektmodells. Es ist ein Detail auf niedriger Ebene, das ein Objektmodell wahrscheinlich verwenden würde, aber das Objektmodell muss wahrscheinlich mehr tun, als nur die API aufzurufen. – dthorpe

Verwandte Themen