Forum: PC-Programmierung C# Serial read


von Christoph (Gast)


Lesenswert?

Hallo,
Ich habe eine Software die Daten sendet und eine die sie über einen 
virtuellen Port empfängt.
Beide Anwendungen sind in C# Forms programmiert.
Die sendende Anwendung schickt in unterschiedlichen Intervallen, 
unterschiedliche Zeilenanzahlen.


Die gesendeten Daten haben das Format S0P0N0 \r\n (die Nullen sind die 
Werte die sich ändern), Ich bin gerade ratlos wie ich das Problem mit 
unterschiedlicher Zeilenzahl handeln kann und wie ich am besten die 3 
Werte wieder aus dem String extrahiere.
Das Sendeprotokoll könnte ich falls nötig relativ leicht ändern.

Ich hoffe jemand kann mir weiterhelfen,
MfG. Christoph

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Grundsätzlich geht immer die Regex.Match-Methode;

hier geht es mit der String.Split-Methode noch einfacher:

1
String.Split(new Char[] {'S', 'P', 'N'}, "S0P0N0")
2
// returns {"0", "", "0", "", "0"}
… oder so ähnlich.

VG Torsten

von Meisterklops (Gast)


Lesenswert?

Ist eine Instanzmethode, also
1
var s = "S0P0N0";
2
var x = s.Split(new [] { 'S', 'P', 'N' }, StringSplitOptions.RemoveEmptyEntries);
3
// Dann Fehlerprüfung und Typumwandlung ...

Christoph schrieb:
> Ich bin gerade ratlos wie ich das Problem mit
> unterschiedlicher Zeilenzahl handeln kann

Den entsprechenden Code für jede Zeile ausführen (Schleife)?

von Meisterklops (Gast)


Lesenswert?

Nachtrag: Als Separatoren-Array kann man natürlich auch eine (readonly) 
Klassenvariable verwenden anstatt es immer wieder neu zu erzeugen.

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Meisterklops schrieb:
> Ist eine Instanzmethode
Blöde Instanzmethoden! :(
Da hätten die auch eine Extension draus machen können! ;)
1
public static class myString {
2
    static String[] Split(this String S, char[] chrs) {
3
        return S?.Split(chrs);
4
    }
5
}

Ich war in Gedanken bei String.Join(). Sorry + Danke, Meisterklops!

> Den entsprechenden Code für jede Zeile ausführen (Schleife)?
… und dann vorher mit s?.Split(null) die Zeilen finden?

Oder eben mit einer RegEx in einem einzigen Schritt:
https://msdn.microsoft.com/library/b873y76a(v=vs.110).aspx
Kapitel "Alternatives to String.Split".

: Bearbeitet durch User
von Christoph (Gast)


Lesenswert?

Danke!

Werd das gleich mal in mein Programm einbauen und testen,
nur das Empfangen ist damit noch immer nicht gelöst.

Wenn der serialPort ein "DataReceivedEvent" auslöst werden ja alle 
empfangenen Daten in den Empfangspuffer geschrieben oder?
Also pro ausgelöstem Event eine Zeile lesen funktioniert nicht oder?

MfG. Christoph

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Christoph schrieb:
> Wenn der serialPort ein "DataReceivedEvent" auslöst werden ja alle
> empfangenen Daten in den Empfangspuffer geschrieben oder?

Wenn der SerialPort ein "DataReceivedEvent" auslöst, dann bedeutet das, 
dass neue Daten in den Empfangspuffer geschrieben wurden. Vielleicht 
meitest Du das so?

Mit SerialPort.Read(…) oder SerialPort.ReadExisting() werden alle
empfangenen Daten aus dem Empfangspuffer gelesen.

Mit SerialPort.ReadLine() nur eine Zeile.

Aber SerialPort.ReadLine() wartet und hält Deinen Thread an.

Benutzt Du einen BackgroundWorker oder sowas wie "readWriteThread = new 
System.Threading.Thread(readWrite)"?

> Also pro ausgelöstem Event eine Zeile lesen funktioniert nicht oder?

Richtig. System.IO.Ports.SerialPort bietet keinen fertigen 
NewLineReceivedEvent 'out of the box' an.

: Bearbeitet durch User
von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

Torsten C. schrieb:
> Benutzt Du einen BackgroundWorker oder …?
> Christoph schrieb:
>> Also pro ausgelöstem Event eine Zeile lesen funktioniert nicht oder?
> Richtig. System.IO.Ports.SerialPort bietet keinen fertigen
> NewLineReceivedEvent 'out of the box' an.

PS: Beim BackgroundWorker würde das 'NewLineReceivedEvent' nur anders 
heißen, also 'BackgroundWorker.ProgressChanged'.

Ich bevorzuge aber System.Threading.Thread mit selbst definiertem 
NewLineReceivedEvent.

Nutzt Du das Windows-Presentation-Framwork oder Windows-Forms?

Je nachdem wird das Ereignis dann über Invoke im UI-Thread ausgelöst.

von daniel (Gast)


Lesenswert?

ich habe ähnliches Problem vor kurzen gehabt.
Allerdings habe ich in Python das Testprogramm geschrieben.
Wenn das Telegramm kontinuierlich gesendet wird, muss du zunächst
synchronisieren.

Pseudocode
data = ser.read(TELEGRAM_LENGTH) # damit fällt sicher ein volles 
Telegramm hinein
idx = data.find(TELEGRAM_START) # muss eindeutig sein (Verwechslung mit 
Daten prüfen)
start = data.substring(idx,end)
telegram = start + ser.read(TELEGRAM_LENGTH - length(start ))

von Torsten C. (torsten_c) Benutzerseite


Lesenswert?

daniel schrieb:
> idx = data.find(TELEGRAM_START)…

Das läuft also auf einen weiteren, einen eigenen Empfangspuffer 
hinaus.

In C# würde sich dafür ein StringBuilder anbieten.

Christoph schrieb:
> Beide Anwendungen sind in C# Forms programmiert.

Das hatte ich gestern übersehen.
Also sähe das Event dann so ähnlich aus:
1
// Deklaration:
2
public event EventHandler<String> NewLineReceivedEvent;
3
// Auslösen aus dem readWriteThread dann mit:
4
string EmpfangeneZeile = "S0P0N0"; // vorher mit StringBuilder.Remove() entfernt
5
this.Invoke((MethodInvoker)(() => {
6
    EventHandler<string> handler = NewLineReceivedEvent;
7
    handler(this, EmpfangeneZeile);
8
}));

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.