Daten über Bluetooth senden und empfangen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 68 Antworten in diesem Thema. Der letzte Beitrag () ist von tron25.

    Man kann nicht sagen es ist die Rückgabegröße, es ist nur die Größe eines Buffers, nach einem Lesvorgang kann die Zahl schon wieder höher sein, wenn die gegenseite weiterschreibt. Mach ein fach 32, selbst wenn der Buffer nicht voll wird.

    Wegen dem Umbenennen, könnte sein das du was falsch umbenannt hast. Kannstes nochmal versuchen, dann aber nur die kleinegeschriebenen "stream" austauschen.
    So, nun bin ich wieder einen kleinen Schritt vorangekommen. Das mit 32 hat leider nicht funktioniert. Dann habe ich gelesen, dass "StreamReader" eigentlich zum Lesen aus Dateien verwendet wird. Die Funktion habe ich jetzt folgendermaßen umgeschrieben:

    VB.NET-Quellcode

    1. Private Sub HyperFlat76Tastenabfrage()
    2. While Ausfuehren
    3. If Client.Available() > 0 Then
    4. Datenstrom = Client.GetStream()
    5. Using Rueckgabe As New StreamReader(Datenstrom)
    6. Dim Rueckgabetext As String = Rueckgabe.ReadLine
    7. RaiseEvent DatenEmpfangen(Rueckgabetext)
    8. End Using
    9. End If
    10. Thread.Sleep(1)
    11. End While
    12. End Sub


    Nach der Deklaration von Rueckgabetext stehen darin tatsächlich Bytes:
    ChrW(27) & "3" & ChrW(1) & ChrW(5) & vbNullChar & ChrW(1) & ">�d" & ChrW(27) & "2" & ChrW(20) & "B" & ChrW(27) & "8�" & vbTab & ChrW(17) & vbVerticalTab & "_A" & ChrW(27) & "8�"

    Beim zweiten Durchlauf wird die Schleife bei der Zeile

    VB.NET-Quellcode

    1. If Client.Available() > 0 Then

    mit der Fehlermeldung
    "System.ObjectDisposedException: "Auf das verworfene Objekt kann nicht zugegriffen werden.
    Objektname: "System.Net.Sockets.Socket"."
    verlassen.

    Wenn ich allerdings ".ReadToEnd" in der Zeile

    VB.NET-Quellcode

    1. Dim Rueckgabetext As String = Rueckgabe.ReadToEnd

    eintrage, wird die Schleife an dieser Stelle gleich beim ersten Mal ohne Kommentar verlassen.

    Ich habe alle "stream"s, die ich in "Datenstrom" geändert habe, gecheckt. Das paßt alles.

    tron25 schrieb:

    Using Rueckgabe As New StreamReader(Datenstrom)


    Das hatte wir schon, der zugrunde liegende Stream wird geschlosssen, der BluetoothClient wohl auch.
    Also wieder:

    VB.NET-Quellcode

    1. Using Rueckgabe As New IO.StreamReader(Stream, System.Text.Encoding.Default, 32, True)

    Das letzte Argument, der Boolean sorgt doch dafür das beim schliessen/Disposen des Streamreaders der zugrundeliegende Stream offen bleibt, wenn dieser True ist.
    Anstatt 1 für die Buffergröße nimm einfach 32. Selbst wenn der Buffer nicht voll wird, ist das nicht schlimm.

    Klappt ja ansonsten, wobei du nochmal in die Doku schauen solltest was für ein encoding verwendet wird, diese Fragezeichen könnten ein Encoding-Problem sein. Wegen dem ReadToEnd, möglicherweise hängt er dort fest, ich kann nur mutmaßen, wenn kein Event gefauert wird, könntest du einen Breakpoint setzen, um zu schauen, ob diese Zeile überhaupt erreicht wird und um zu schauen was in den Variablen steckt.

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

    Ich habe mir mal die Definition von
    "Streamreader" angeschaut. Folgende Parameter sind notwendig:
    stream
    Encoding
    DetectEncodingFromByteOrderMarks
    BufferSize
    LeaveOpen

    So sieht es dann aus:

    VB.NET-Quellcode

    1. Using Rueckgabe As New IO.StreamReader(Datenstrom, System.Text.Encoding.Default, false, 32, True)


    die folgende Zeile mußte ich auch ändern, da die Funktion ohne Kommentar an dieser Stelle verlassen wird:

    VB.NET-Quellcode

    1. Dim Rueckgabetext As String = Rueckgabe.ReadLine


    Wenn ich das Programm nun laufen lasse, gibt er mir Werte zurück, wenn ich die Touchoberfläche berühre. Sehr selten bekomme ich auch einen Wert zurück, wenn ich eine Taste drücke. Allerdings hängt das Programm nun, manchmal auch sehr lang. Ich fürchte, dass das was mit dem "ReadLine" und "ReadToEnd()" zu tun hat. Wie schon geschrieben, funktioniert "ReadToEnd" nicht.

    Die Zeichenfolge, die zurückgegeben wird, ist richtig codiert. Ich habe mir eine Funktion geschrieben, die die einzelnen Zeichen in Ascii-Werte umwandelt und mir zurückgibt. So kann ich auch prüfen, welche Werte zurückgegeben werden. "27 31" ist der Anfang von Tastendrücken, "27 56" zeigt Berührungen, usw. In der Dokumentation des Brailledisplay werden die Werte erklärt.

    Gibt es eine Möglichkeit, den Stream komplett auszulesen, bevor er weitergegeben wird, ohne "ReadToEnd"?
    Also bei ReadLine kann es passieren das kein Zeilenumbruch reinkommt und der Ablauf deswegen dort höngen bleiben kann. Bei ReadToEnd sollte eigendlich alles gelesen werden, passiert das auch mit BufferSize = 1? Müsste sich eigendlich gleich verhalten.

    Aber du kannst es auch anders probieren, BluetoothClientClient.Available() gibt dir ja die Zahl der zum aktuellen Zeitpunkt vorhandenen Bytes zum lesen im Stream, also einen Byte Array nehmen, größe Anzahl lesbarer Bytes. Diese dann einlesen, und wenn alles gelesen ist, ein String draus machen. Aber so kann es passieren, das viele Bruchstücke rein kommen, also keine ganzen Zeilen. Also auch aufpassen, nicht in einer singleline TextBox das gelesene anzeigen, wegen der Bruchstücke, kann mittendrin ein newLine kommen. Readline ging ja hin und wieder, also vorsicht. Wenn du jetzt die Schlafzeit des threads erhöhst, könnte sich das auswirken auf wie viel zu lesen das ist, schau dir mal an was passiert wenn du nun den Thread 20, 50 oder 100 MS schlafen legst, wenn du fleissig am Gerät drückst.

    VB.NET-Quellcode

    1. If Client.Available() > 0 Then
    2. stream = Client.GetStream()
    3. Dim buffer() As Byte = New Byte(Client.Available - 1) {}
    4. Dim bytesGelesen As Integer = 0
    5. Dim bytesZuLesen As Integer = buffer.Length
    6. While bytesGelesen < bytesZuLesen
    7. bytesGelesen += stream.Read(buffer, bytesGelesen, bytesZuLesen - bytesGelesen)
    8. End While
    9. Rueckgabetext = System.Text.Encoding.Default.GetString(buffer)
    10. RaiseEvent DatenEmpfangen(Rueckgabetext)
    11. End If
    12. Thread.Sleep(1)

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

    So, jetzt scheint es zu funktionieren. Das Brailledisplay sendet neben sekündlichen Geräteinformationen über Akkuzustand, Firmware usw. bei jedem Drücken bzw. Loslassen jeweils 7 Bytes. Die ersten 2 (chr(27), chr(49)) zeigen, das eine Taste gedrückt bzw. losgelassen wurde. Die nächsten 3 Bytes sind interne Informationen. Die zwei letzten Bytes beschreiben die unteren und oberen Tastenzustände. Jetzt bastele ich eine Select-Anweisung, um Tasten, Tastenkombinationen und bei 0,0 das Absenden des entsprechenden Befehls einzuarbeiten.

    VB.NET-Quellcode

    1. Private Sub Bluethooth_DatenEmpfangen(Daten As String) Handles BluetoothVerbindung.DatenEmpfangen
    2. If InvokeRequired Then
    3. BeginInvoke(Sub() Bluethooth_DatenEmpfangen(Daten))
    4. Else
    5. If Len(Daten) > 0 Then
    6. HyperFlat76RueckgabeAuswerten(Daten)
    7. End If
    8. End If
    9. End Sub
    10. Public Sub HyperFlat76RueckgabeAuswerten(Daten)
    11. Select Case Mid(Daten, 1, 2)
    12. Case Chr(27) & Chr(49)
    13. 'Untere Tasten
    14. Select Case Mid(Daten, 6, 1)
    15. Case Chr(1)
    16. 'Rechts
    17. Case Chr(2)
    18. 'Hoch
    19. Case Chr(4)
    20. 'Links
    21. Case Chr(8)
    22. 'Runter
    23. Case Chr(16)
    24. 'Mitte
    25. Case Chr(64)
    26. 'Linke Taste
    27. Case Chr(128)
    28. 'Rechte Taste
    29. End Select
    30. End Select
    31. End Sub


    Die oberen Tasten beinhalten zwei Umschalttasten. Dadurch steigen die möglichen Kombinationen um ein Vielfaches. Dazu kommzt später auch das Ausarbeiten von bis zu 10 Fingerpositionen.

    Es wartet noch viel Arbeit auf mich.

    An dieser Stelle möchte ich mich nochmal ganz herzlich für die gute und wertvolle Hilfe bedanken.
    Ich habe ein neues Bluetooth-Problem. Wenn ich das Programm starte, ohne das ein Bluetoothgerät aktiviert ist, sprich der USB-Bluetooth-Stecker steckt nicht drin, dann bricht das Programm mit der folgenden fehlermeldung ab:
    System.PlatformNotSupportedException: "No supported Bluetooth protocol stack found."
    Die Zeile

    VB.NET-Quellcode

    1. Private Client As New BluetoothClient

    wird dabei markiert.
    Mir ist schon klar, das kein Objekt als Bluetooth-Client erzeugt werden kann, wenn es kein Bluetoothgerät gibt. Normalerweise würde ich vorher abfragen, welche Bluetoothgeräte vorhanden sind und dann entsprechend ein solches Objekt erzeugen. Aber wie kann ich es machen, wenn das Objekt im Klassenkopf erstellt wird? Die zweite Möglichkeit wäre, ein neues Objekt bei einem gefundenen Gerät zu erzeugen. Allerdings weiß ich nicht, wie ich dieses Objekt dann als Global deklarieren kann.
    Also mit Klassenkopf, meinst du einfach am Anfang in der Klasse? Also im Gültigskeitsbereich der Klasse?

    Dann instanziere den BluetoothClient wenn du diesen brauchst, also das new in dieser Zeile löschen. Denn beim instanzieren passiert das, daher hab ich auch in dem Beispiel-Code das instanzieren in einem Try-Catch-Block und fange die PlatformNotSupportedException ab und zeige dem User eine MessageBox. Möglicherweise bietet die 32feet auch was um zu testen um ohne dem Try-Catch auszukommen, aber gesehen hab ich bisher nichts.


    VB.NET-Quellcode

    1. Private Client As BluetoothClient
    2. Public Function Connect(deviceName As String) As Boolean
    3. Try
    4. Dim deviceInfo As BluetoothDeviceInfo = Nothing
    5. client = New BluetoothClient()
    6. Dim devices As BluetoothDeviceInfo() = client.DiscoverDevices()
    7. For Each d As BluetoothDeviceInfo In devices
    8. If d.DeviceName.ToLower().Equals(deviceName.ToLower()) Then
    9. deviceInfo = d
    10. End If
    11. Next
    12. If deviceInfo Is Nothing Then
    13. MessageBox.Show("Kein Device mit dem Namen: " & deviceName & " gefunden!")
    14. Return False
    15. End If
    16. Dim endPoint As New BluetoothEndPoint(deviceInfo.DeviceAddress, BluetoothService.SerialPort)
    17. client.Connect(endPoint)
    18. If client.Connected Then
    19. stream = client.GetStream()
    20. Return True
    21. End If
    22. MessageBox.Show("Konnte keine Verbindung zum Device aufbauen!")
    23. Catch ex As PlatformNotSupportedException
    24. MessageBox.Show("Kein Bluetooth verfügbar!")
    25. End Try
    26. Return False
    27. End Function

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Takafusa“ ()