String auflösen

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von emsig.

    String auflösen

    Hallo erstmal!!!

    Bin neu hier, ebenso bin ich Neuling was Programmieren mit VB angeht. Ein paar Kenntnise sind vorhanden. Habe folgende Frage und hoffe das ich hier richtig bin:

    Ich kommuniziere über USB mit einer Steuerung, welche mir nach senden eines Zeichens "?" eine Antwort schickt. Die Antwort schaut z.B wie folgt aus:

    <Idle,MPos:1.000,2.000,3.000,WPos:4.000,5.000,6.000>
    ok


    Denke mal was da ankommt nennt man String. Jetzt zu meiner eigentlichen Frage: Wie zerlege ich den String, dass ich nur den Status und die Koordinaten getrennt rausbekomme. So z.B.:

    Status.text = Idle
    MX.text = 1.000
    MY.text = 2.000
    MZ.text = 3.000
    WX.text = 4.000
    WY.text = 5.000
    WZ.text = 6.000

    die Werte können positiv und auch negativ sein. Das "OK" in der nächsten Zeile kann/soll ignoriert werden, ebenso das "<" am Anfang und ">" am Ende.

    Die Abfrage und die Meldung erfolgt alle 200ms automatisch.


    Bin sehr dankbar für Anregungen, Lösungsvorschläge usw....

    Besten Dank im Voraus
    lg
    Dafür dürfte man sich erstmal ein Datenmodell überlegen:
    Die einzelnen Positionen sind jeweils ein Tripel. Nun kann man dafür eine Struct anlegen

    VB.NET-Quellcode

    1. Public Structure Vector3f
    2. Public Sub New()
    3. End Sub
    4. Public Sub New(X As Single,Y As Single,Z As Single)
    5. Me.X = X
    6. Me.Y = Y
    7. Me.Z = Z
    8. End Sub
    9. Public X,Y,Z As Single
    10. End Structure

    und auf diese Weise baut man dann noch die zu empfangenden Pakete auf, das Auseinandernehmens des Strings kommt erst nachdem eine halbwegs Architektur aufgebaut wurde.
    Dies dürfte sehr schön mit RegEx gehen(für Geschwindigkeit mit IndexOf+Substring)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Danke für die erste schnelle Antwort!

    und zugegeben, (bitte habt nachsicht mit mir :-D) verstehe ich davon gerade Bahnhof...

    Ich fang mal oben an: Was versteht man mit
    Die einzelnen Positionen sind jeweils ein Tripel
    ?

    Was sagt mir bzw. wie kann/soll/muss ich den obigen Code verstehen?
    Tripel für Drei, du hast ja schließlich 3 Zahlen pro Position, also X, Y, Z-Koordinate, mehr Bedeutung hatte das nicht.
    Da du obigen Code nicht zu verstehen scheinst, muss ich dich leider - was vielen nicht gefällt - auf die Grundlagen verweisen.
    Also mach dich mal über Dinge wie Klassen, Objekte usw. Schlau ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Zerlegen des Strings geht z. B. so:
    (Ausführbares Konsolenprogramm).

    VB.NET-Quellcode

    1. Module Module1
    2. Sub Main()
    3. Dim t As String
    4. t = "<Idle,MPos:1.000,2.000,3.000,WPos:4.000,5.000,6.000>"
    5. If t.Contains("Idle") Then
    6. t = System.Text.RegularExpressions.Regex.Replace(t, "[<>MPosW: ]", "")
    7. Console.WriteLine("Status = " & t.Split(",")(0))
    8. Console.WriteLine("MX = " & t.Split(",")(1))
    9. Console.WriteLine("MY = " & t.Split(",")(2))
    10. Console.WriteLine("MZ = " & t.Split(",")(3))
    11. Console.WriteLine("WX = " & t.Split(",")(4))
    12. Console.WriteLine("WY = " & t.Split(",")(5))
    13. Console.WriteLine("WZ = " & t.Split(",")(6))
    14. End If
    15. Console.Read()
    16. End Sub
    Danke für Code, den kann ich zumindest ansatzweise nachvollziehen. Für mich stellt sich jzt die Frage, wo füge ich den Code ein?

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.ComponentModel
    3. Imports System.Threading
    4. Imports System.IO.Ports
    5. Public Class frmMain
    6. Dim myPort As Array 'COM Ports detected on the system will be stored here
    7. Delegate Sub SetTextCallback(ByVal [text] As String) 'Added to prevent threading errors during receiveing of data
    8. Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    9. 'When our form loads, auto detect all serial ports in the system and populate the cmbPort Combo box.
    10. myPort = IO.Ports.SerialPort.GetPortNames() 'Get all com ports available
    11. cmbBaud.Items.Add(9600) 'Populate the cmbBaud Combo box to common baud rates used
    12. cmbBaud.Items.Add(19200)
    13. cmbBaud.Items.Add(38400)
    14. cmbBaud.Items.Add(57600)
    15. cmbBaud.Items.Add(115200)
    16. For i = 0 To UBound(myPort)
    17. cmbPort.Items.Add(myPort(i))
    18. Next
    19. cmbPort.Text = cmbPort.Items.Item(0) 'Set cmbPort text to the first COM port detected
    20. cmbBaud.Text = cmbBaud.Items.Item(0) 'Set cmbBaud text to the first Baud rate on the list
    21. btnDisconnect.Enabled = False 'Initially Disconnect Button is Disabled
    22. btnSend.Enabled = False
    23. txtTransmit.Enabled = False
    24. OvalShape1.FillGradientColor = Color.Red 'Status auf Rot
    25. GbShortcuts.Enabled = False
    26. TPoll.Interval = TbPoll.Text
    27. TPoll.Start()
    28. End Sub
    29. Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
    30. SerialPort1.PortName = cmbPort.Text 'Set SerialPort1 to the selected COM port at startup
    31. SerialPort1.BaudRate = cmbBaud.Text 'Set Baud rate to the selected value on
    32. 'Other Serial Port Property
    33. SerialPort1.Parity = IO.Ports.Parity.None
    34. SerialPort1.StopBits = IO.Ports.StopBits.One
    35. SerialPort1.DataBits = 8 'Open our serial port
    36. SerialPort1.Open()
    37. btnConnect.Enabled = False 'Disable Connect button
    38. btnDisconnect.Enabled = True 'and Enable Disconnect button
    39. btnSend.Enabled = True
    40. txtTransmit.Enabled = True
    41. OvalShape1.FillGradientColor = Color.LimeGreen 'Status auf Grün
    42. GbShortcuts.Enabled = True
    43. End Sub
    44. Private Sub btnDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisconnect.Click
    45. SerialPort1.Close() 'Close our Serial Port
    46. btnConnect.Enabled = True
    47. btnDisconnect.Enabled = False
    48. btnSend.Enabled = False
    49. txtTransmit.Enabled = False
    50. OvalShape1.FillGradientColor = Color.Red 'Status auf ROT
    51. GbShortcuts.Enabled = False
    52. End Sub
    53. Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
    54. SerialPort1.Write(txtTransmit.Text & vbCr) 'The text contained in the txtText will be sent to the serial port as ascii
    55. 'plus the carriage return (Enter Key) the carriage return can be ommitted if the other end does not need it
    56. End Sub
    57. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    58. ReceivedText(SerialPort1.ReadExisting()) 'Automatically called every time a data is received at the serialPort
    59. End Sub
    60. Private Sub ReceivedText(ByVal [text] As String)
    61. 'compares the ID of the creating Thread to the ID of the calling Thread
    62. If Me.rtbReceived.InvokeRequired Then
    63. Dim x As New SetTextCallback(AddressOf ReceivedText)
    64. Me.Invoke(x, New Object() {(text)})
    65. Else
    66. Me.rtbReceived.Text &= [text]
    67. End If
    68. End Sub
    69. Private Sub cmbPort_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbPort.SelectedIndexChanged
    70. If SerialPort1.IsOpen = False Then
    71. SerialPort1.PortName = cmbPort.Text 'pop a message box to user if he is changing ports
    72. Else 'without disconnecting first.
    73. MsgBox("Valid only if port is Closed", vbCritical)
    74. End If
    75. End Sub
    76. Private Sub cmbBaud_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbBaud.SelectedIndexChanged
    77. If SerialPort1.IsOpen = False Then
    78. SerialPort1.BaudRate = cmbBaud.Text 'pop a message box to user if he is changing baud rate
    79. Else 'without disconnecting first.
    80. MsgBox("Valid only if port is Closed", vbCritical)
    81. End If
    82. End Sub
    83. Private Sub rtbReceived_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rtbReceived.TextChanged
    84. If ckbScroll.Checked Then
    85. rtbReceived.SelectionStart = rtbReceived.Text.Length
    86. rtbReceived.ScrollToCaret()
    87. End If
    88. End Sub
    89. Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    90. rtbReceived.Text = " "
    91. End Sub
    92. Private Sub txtTransmit_Enter(ByVal sender As System.Object, ByVal e As KeyEventArgs) Handles txtTransmit.KeyDown
    93. If e.KeyCode = Keys.Enter Then
    94. rtbReceived.Text &= (txtTransmit.Text & vbCr)
    95. SerialPort1.Write(txtTransmit.Text & vbCr) 'The text contained in the txtText will be sent to the serial port as ascii
    96. 'plus the carriage return (Enter Key) the carriage return can be ommitted if the other end does not need it
    97. End If
    98. End Sub
    99. Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
    100. txtTransmit.Text = " "
    101. End Sub
    102. Private Sub LlHelp_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LlHelp.LinkClicked
    103. rtbReceived.Text &= ("$$" & vbCr)
    104. SerialPort1.Write("$$" & vbCr)
    105. End Sub
    106. Private Sub LlStatus_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LlStatus.LinkClicked
    107. rtbReceived.Text &= ("?" & vbCr)
    108. SerialPort1.Write("?" & vbCr)
    109. End Sub
    110. Private Sub LlStart_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked
    111. rtbReceived.Text &= ("~" & vbCr)
    112. SerialPort1.Write("~" & vbCr)
    113. End Sub
    114. Private Sub Label10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label10.Click
    115. End Sub
    116. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    117. End Sub
    118. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TPoll.Tick
    119. If SerialPort1.IsOpen() Then
    120. SerialPort1.Write("?" & vbCr)
    121. End If
    122. End Sub
    123. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    124. TPoll.Stop()
    125. TPoll.Interval = TbPoll.Text
    126. TPoll.Start()
    127. End Sub
    128. End Class


    Im obigen Code Zeile 74 hab ich ja die Daten als String.

    könnte das dann so aussehn:?

    VB.NET-Quellcode

    1. If ReceivedText.Contains("<" & ">") Then
    2. ReceivedText = System.Text.RegularExpressions.Regex.Replace(ReceivedText, "[<>MPosW: ]", "")
    3. Label7.Text = (ReceivedText.Split(",")(1))
    4. usw...
    5. End If

    Über Anregungen und Beschwerden über den momentanen Code bin ich ebenso sehr dankbar :)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „emsig“ ()

    Danke für eure Hilfestellung, leider hatte ich ab 18h kein iNet mehr, durfte somit selber rann... :D

    Die If Abfrage mit "<" and ">" hatte natürlich nicht funktioniert, bin dann selbst daruf gekommen.
    Ich konnte den Code mittlerweile so adaptiern, dass immer wenn ich ne Statusabfrage mache, auch die Koordinaten aktualisiert werden. Funktioniert auch, leider aber nur einmal, und das zeitverzögert.

    Problem was ich habe, ist folgendes. Im Moment, wird die Statusabfrage untereinander in eine RichTextBox geschrieben (soll später nicht mehr so sein). Die Zerlegung des Strings erfolgt leider nur in der ersten Zeile oben aus der Rtb heraus. Wie bekomme ich das hin, dass immer die letzte Zeile bzw. die letzte Statusabfrage zerlegt wird?

    Im Bild kann man gut erkennen, dass nur die oberste Zeile verwendet wird...
    dropbox.com/s/yucr2vgf0hcj9ct/…5-01-08 19.46.03.png?dl=0

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „emsig“ ()

    hat jemand ne Idee...

    ... oder nen Lösungsansatz wie das obige beschriebene Problem behoben werden kann?

    Mein Gedanke wäre folgender:

    Wenn über Serielle ein "<" reinkommt, warte ich bis ">" kommt. Alles dazwischen ist mein Status der dann in der Form "Label.Text" aktualisiert werden soll...

    Ist das ein ordentlicher Ansatz? Wenn ja, wie löse ich das?

    Bin für Anregungen sehr dankbar!!!