Android Question Bluetooth Connection - Strange Stuff

rodmcm

Active Member
Licensed User
Hi
I am transmitting integers from ESp32 to B4A ( only 6 at a time in an array). Having all sorts of problems with errors including B4r Serialization. This experiment went back to basics to try and sort the problem by developing bytes from Ints ( been through the byte converter route as well)

The attached is a summary of the reception at the B4A on a Levono Tablet. Some of the data is fine, then it all turns to custard.

Has anyone any idea why this should be? I have tried different ESP's but unfortunately only one tablet.

Code sending from B4R

B4X:
Sub SendBT
    If btConnected Then
    '    bt_astream.Write(ser.ConvertArrayToBytes(Array(SendArray(0),SendArray(1),SendArray(2),SendArray(3),SendArray(4),SendArray(5),SendArray(6))))
        Log(SendArray(0)," ",SendArray(1)," ",SendArray(2)," ",SendArray(3)," ",SendArray(4)," ",SendArray(5)," ",SendArray(6))
        Dim SendByteArray(20) As Byte
        Dim j =0 As Int
        For i = 0 To 9
            SendByteArray(j) =Bit.And(SendArray(i),0xFF)
            SendByteArray(j+1) = Bit.And(Bit.ShiftRight(SendArray(i),8),0xff)
            j=j+2
        Next
        
        Log(SendByteArray(0)," ",SendByteArray(1)," ",SendByteArray(2)," ",SendByteArray(3)," ",SendByteArray(4)," ",SendByteArray(5)," ",SendByteArray(6)," ",SendByteArray(7)," ",SendByteArray(8)," ",SendByteArray(9)," ",SendByteArray(10)," ",SendByteArray(11)," ",SendByteArray(12)," ",SendByteArray(13))
        
        bt_astream.Write(SendByteArray)
        Delay(400)
    End If
End Sub
Code Receiving at B4A

B4X:
 AStream_NewData (Buffer() As Byte)
'Log("Buffer Length  "& Buffer.length)
'Log(bc.HexFromBytes(Buffer))
    If Buffer.Length Mod 2 = 0 And Buffer.Length<=20 Then
        Log(Buffer(0) &" "&Buffer(1) &" "&Buffer(2) &" "&Buffer(3) &" "&Buffer(4) &" "&Buffer(5) &" "&Buffer(6) &" "&Buffer(7) &" "&Buffer(8) &" "&Buffer(9) &" "&Buffer(10) &" "&Buffer(11) &" "&Buffer(12) &" "&Buffer(13) &" "&Buffer(14) &" "&Buffer(15) &" "&Buffer(16) &" "&Buffer(17) &" "&Buffer(18) &" "&Buffer(19))
        Dim Data(Buffer.length) As Int
        Dim j As Int =0
        For i=0 To Buffer.Length-1 Step 2
            Dim Byte1 As Byte =Bit.Shiftleft(Buffer(i+1),8)
            
            'Data(j) = Bit.Or(Buffer(i),Bit.Shiftleft(Buffer(i+1),8))    ' Adds bytes to make an integer
            Data(j) = Bit.Or(Buffer(i),Byte1)
            j=j+1
        Next
    If Data.Length = 0 Then Return                            'invalid message
        Log("FromESP32  "& Data(0) & "  "& Data(1) &"  " & Data(2) & "  " & Data(3)&"  "& Data(4)&"  "& Data(5)&"  "& Data(6))
 

Attachments

emexes

Well-Known Member
Licensed User
Do you have ByteConverter library in B4R?

If so, could use something like:
B4X:
Dim bc As ByteConverter

Dim IntsToSend(6) As Int = Array As Int(111, 222, 333, 444, 555, 666)

Log(IntsToSend.Length)
For I = 0 To IntsToSend.Length - 1
    Log("IntsToSend(" & I & ") = " & IntsToSend(I))
Next

Dim BytesToSend() As Byte = bc.IntsToBytes(IntsToSend)    'split 32-bit Ints to 8-bit bytes

Log(BytesToSend.Length)
For I = 0 To BytesToSend.Length - 1
    Log("BytesToSend(" & I & ") = " & BytesToSend(I))
Next
and then the matching reverse function bc.IntsFromBytes at the other end to unpack the bytes and convert them back to Ints
 
Last edited:

emexes

Well-Known Member
Licensed User
In fact, all that bit twiddling and looping above can probably just be condensed down to:
B4X:
Dim bc As ByteConverter
bt_astream.Write(bc.IntsToBytes(SendArray))
assuming that you want to send ALL of SendArray().
 

rodmcm

Active Member
Licensed User
Found the problem but not the solution!!!!

Ints in B4r are 2 bytes and ints in B4A are 4 bytes. (I used B4r to test my send and receive and of course it worked fine)

If I use

bt_astream.Write(bc.IntsToBytes(SendArray)) at the send end

and

Dim Data() As Int = bc.IntsFromBytes(Buffer) at the receive end

does not work at the B4A end
 

emexes

Well-Known Member
Licensed User
Dim Data() As Int = bc.IntsFromBytes(Buffer) at the receive end

does not work at the B4A end
Hmm. Good thing one of us is awake. No worries, though:
B4X:
Dim Data() As Short = bc.ShortsFromBytes(Buffer)
 

emexes

Well-Known Member
Licensed User
(been through the byte converter route as well)
Einstein here somehow missed this. But... I use ByteConverter all the time when reading BLE packets, all works great, so I probably would have posted something about giving it another go anyway.

Did the B4A ShortsFromBytes correctly unpack the B4R IntsToBytes?

If not, then the Bit operations should be able to do the job too, and I'll have a closer look at why they were not working in your case.
 

rodmcm

Active Member
Licensed User
Solved!
B4X:
Sub AStream_NewData (Buffer() As Byte)
    ' Converts buffer with 2 bytes per int from B4R to B4A Int with 4 bytes per int
    Dim Data(Buffer.length) As Int
    Dim j As Int =0
    For i=0 To Buffer.Length-1 Step 2
        bc.LittleEndian = True
        Data(j) = bc.IntsFromBytes(Array As Byte(Buffer(i),Buffer(i+1),0,0))(0)     ' first, second, third and fourth byte
    j=j+1
    Next
    Log("FromESP32  "& Data(0) & "  "& Data(1) &"  " & Data(2) & "  " & Data(3)&"  "& Data(4)&"  "& Data(5)&"  "& Data(6))
End Sub
 

emexes

Well-Known Member
Licensed User
:)

I still prefer bc.ShortsFromBytes, but to each their own, and presumably there is a reason for Data() to be Int.

What about when AStream splits up the received data into variously-sized chunks? Or worse: odd-sized chunks?
 

rodmcm

Active Member
Licensed User
Buffer.length Mod 2 takes care of the odd number of bytes.. I know that I have 10 integers coming down so Buffer.length<=20

Like your pun!
bc.shorts works fine... 32000 off enough for me.
I really need to come to grips with bytes etc.. I didnt know what a short was until you pointed it out!
astream in prefix mode
 

emexes

Well-Known Member
Licensed User
Buffer.length Mod 2 takes care of the odd number of bytes.. I know that I have 10 integers coming down so Buffer.length<=20

astream in prefix mode
When I saw "astream in prefix mode", all my but-what-about-? worries melted away.

Well, some of them flipped.* Why not just check for Buffer.Length = 20 ? When would you receive fewer than 20 bytes? And if you did somehow receive a 2-byte packet, wouldn't the Log() throw a subscript-out-of-bounds error?

You could probably let go of the safety net where Data() is Dimmed to twice the size it needs to be (to be sure, to be sure ?!) eg: for a 20-byte packet that has 10 numbers in it, the Dim Data(Buffer.Length) is allocating space for 20 numbers. I'm guessing this is a hangover from the dark old days of "manually" unpacking the numbers.

Other beauties of: Dim Data() = bc.ShortsFromBytes(Buffer) are that 1/ the array is automatically allocated to the required size, and 2/ Data.Length tells you how many numbers were received, no calculation or hardcoding of data type size necessary.

Excellent save with the bc.LittleEndian = True. (I'd forgotten that there are still smouldering pockets of BigEndian misleds about ;-)

This communication link code of yours is going to be a Work Of Art by the time we're both happy with it!


* you can't keep a natural pessimist down (or should that be: up?)
 

emexes

Well-Known Member
Licensed User
I really need to come to grips with bytes etc..
If you're going to be doing any sort of communication packet or file record stuff, then it certainly helps to visualise data as bits and bytes. Byte arrays are good because they exactly represent the physical arrangement of the data being moved about, although I am a bit sad about the Java/B4X bias towards signed numbers, which makes some arithmetic shortcuts a bit shaky if the high bit is involved.

I didn't know what a short was until you pointed it out!
And I didn't know that the B4R Int is only 16 bits, so we've both learned something new! Although your info was sadder: given that a programmer using B4R is likely to be using a B4X language at the other end of the cable also, it would have been good to minimize the amount of mental gear-changing necessary when moving back and forth between the two environments.

Perhaps one day the gods will smile upon us and implement C99-style stdint types in B4X. Write once, run anywhere. Should probably be a capital A for Anywhere.

:)
 
Top