Spanish Pasar de Bluetooth Clasico a BLE

Edu Portu

Member
Licensed User
Longtime User
Buenas tardes,
Tengo una APP que conecta a traves de Bluetooth "clasico" con una cerradura electronica, la APP funciona correctamente, pero ahora la nueva version de la cerradura usa Bluetooth BLE para ahorrar bateria y ya no funciona la APP.
Dejo aqui el codigo que uso en la APP (uso la clase Asynstreamtext) a ver si podeis orientarme en alguna manera de adaptarla para el BLE.

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim btAdmin As BluetoothAdmin
    Dim btDispositivo As Serial
    Dim AStreams As AsyncStreamsText
End Sub

Sub Activity_Create
    btAdmin.Initialize("BlueTeeth")
    btDispositivo.Initialize("InicializarDispositivo")
    InicializarDispositivo
End Sub

Sub InicializarDispositivo As Boolean
    Dim PairedDevices As Map
    Dim L As List
    Dim Res As Int
    Dim Resultado As Boolean

    Resultado = True
    EscribirLog("Conectando con la cerradura...")

    PairedDevices.Initialize
    Try
        PairedDevices = btDispositivo.GetPairedDevices
    Catch
        EscribirLog("Error de conexión...")
        btDispositivo.Disconnect
        Resultado = False
    End Try

    If PairedDevices.Size = 0 Then
        EscribirLog("Error Conectando - Ningun dispositivo encontrado...")
        Resultado = False
    Else
        Dim PorDefecto As Int = -1
        L.Initialize

        For i = 0 To PairedDevices.Size - 1
            L.Add(PairedDevices.GetKeyAt(i))
            If Main.IDDispositivo = PairedDevices.GetValueAt(i) Then PorDefecto = i
        Next
        
        If (Main.IDDispositivo <> "") And (PorDefecto <> -1) Then
            'ToastMessageShow(Main.IDDispositivo, True)           
            btDispositivo.Connect(PairedDevices.Get(L.Get(PorDefecto)))
        Else
            Res = InputList(L, "Elige dispositivo", -1)

            If Res <> DialogResponse.CANCEL Then
                Main.IDDispositivo = PairedDevices.GetValueAt(Res)
                funciones.EscConfig
                btDispositivo.Connect(PairedDevices.Get(L.Get(Res)))
            Else
                Resultado = False
            End If           
        End If

    End If
    
    Return Resultado
End Sub

Public Sub SendMessage (msg As String)
    EscribirLog(">> " & msg)
    AStreams.Write(msg&Chr(10)&Chr(13))'.GetBytes("utf8"))
End Sub

Sub InicializarDispositivo_Connected (Success As Boolean)
    If Success Then
        EscribirLog("Conexión establecida")
        If AStreams.IsInitialized Then AStreams.Close
        AStreams.Initialize(Me, "AStreams", btDispositivo.InputStream, btDispositivo.OutputStream)
        
        EscribirLog("Enviando comando a la cerradura...")
        SendMessage(CEI & "CM:FT" & CEF)   
        'AQUI HABRIA QUE ESPERAR A QUE NOS DEVUELVA ALGO LA CERRADURA
        Wait for AStreams_NewText(Respuesta As String)
        EscribirLog("Respuesta: " & Respuesta)
        
    End If
End Sub

Y esta es la clase AsynsStreamText:

B4X:
#Event: NewText (Text As String)
#Event: Terminated

'version: 1.00
'Class module
Sub Class_Globals
    Private mTarget As Object
    Private mEventName As String
    Private astreams As AsyncStreams
    Public charset As String = "UTF8"
    Private sb As StringBuilder
End Sub

Public Sub Initialize (TargetModule As Object, EventName As String, In As InputStream, out As OutputStream)
    mTarget = TargetModule
    mEventName = EventName
    astreams.Initialize(In, out, "astreams")
    sb.Initialize
End Sub

'Sends the text. Note that this method does not add end of line characters.
Public Sub Write(Text As String)
    astreams.Write(Text.GetBytes(charset))
End Sub

Private Sub astreams_NewData (Buffer() As Byte)
    Dim newDataStart As Int = sb.Length
    sb.Append(BytesToString(Buffer, 0, Buffer.Length, charset))
    Dim s As String = sb.ToString
    Dim start As Int = 0
    For i = newDataStart To s.Length - 1
        Dim c As Char = s.CharAt(i)
            If i = 0 And c = Chr(10) Then '\n...
            start = 1 'might be a broken end of line character
            Continue
        End If
        If c = Chr(10) Then '\n
            CallSubDelayed2(mTarget, mEventName & "_NewText", s.SubString2(start, i))
            start = i + 1
        Else If c = Chr(13) Then '\r
            CallSubDelayed2(mTarget, mEventName & "_NewText", s.SubString2(start, i))
            If i < s.Length - 1 And s.CharAt(i + 1) = Chr(10) Then '\r\n
                i = i + 1
            End If
            start = i + 1
        End If
    Next
    If start > 0 Then sb.Remove(0, start)
End Sub

Private Sub astreams_Terminated
    CallSubDelayed(mTarget, mEventName & "_Terminated")
End Sub

Private Sub astreams_Error
    Log("error: " & LastException)
    astreams.Close
    CallSubDelayed(mTarget, mEventName & "_Terminated")
End Sub

Public Sub Close
    astreams.Close
End Sub
 

JordiCP

Expert
Licensed User
Longtime User
A nivel de protocolo, BLE es bastante diferente que el BT clásico.

Lo que en BT clasico se escribe y lee por streams, en BLE se hace a través de caracteristicas. De alguna manera las características son como unos sockets a nivel de protocolo de BLE, y cada dispositivo implementa las suyas (y la sintaxis específica para las mismas). Una vez te has conectado al dispositivo, la comunicación va a través de las mismas.

Debes conocer el protocolo del fabricante, es decir, qué características escribir/leer, y qué es lo que espera exactamente. Es posible que el contenido a leer/escribir sea el mismo formato que cuando iba con BT clásico, pero también puede haber cambiado.

Te recomiendo este ejemplo de BLE, y adaptarlo al protocolo del fabricante.
 

Edu Portu

Member
Licensed User
Longtime User
Muchas gracias por tu respuesta.

Ya tengo mas o menos hecha la parte de conexion, pero tengo una duda.

En el Bluetooth clasico al conectar con:
B4X:
btDispositivo.Connect(PairedDevices.Get(i))
una vez finalizado el proceso de conexion, saltaba el evento
B4X:
Sub DispositivoBT_Connected (Success As Boolean)
con lo cual con el valor de la variable Success sabias si se habia conectado correctamente o no, pero con el Buetooth LE cuando conecto con:
B4X:
Manager.Connect2(id, False)
una vez finalizado el proceso salta el evento
B4X:
Sub Manager_Connected (services As List)
como se si la conexion ha sido realizada correctamente?
 

JordiCP

Expert
Licensed User
Longtime User
En el caso del BLE, si salta este evento, es que la conexion se ha realizado correctamente.

El siguiente paso es leer los servicios de la lista que te pasa. Cada uno puede estar formado por una o mas caracteristicas, y una de ellas deberia ser el canal de "comandos" de la cerradura, supongo.
 

Edu Portu

Member
Licensed User
Longtime User
Y si la conexion no se realiza correctamente no hay manera de controlarlo? Quiero decir, para poder mandar un mensaje al usuario de que ha habido error en la conexion y que lo vuelva a intentar por ejemplo...
 

JordiCP

Expert
Licensed User
Longtime User
Que recuerde, no. Pero puedes poner un timer: una vez detectado en el scan, si les dices de conectar y no lo ha conseguido en 4-5 segundos, es que no ha ido. Tanto si la app lo hace automaticamente como por interaccion del usuario, es la manera de hacerlo
 
Top