Android Question Bytes to fixed packet

Philip Prins

Active Member
Licensed User
Longtime User
Hello ,

I need to send a jpeg in packets of maximum 30 bytes to a server.
The problem is that the jpeg are different sizes.
How do i divide it?
I tried this , but how to handle oneven total data size?

B4X:
Public Sub SendPhoto(data() As Byte)
    Dim nbytes As Int=data.Length
    Dim bc As ByteConverter
    Dim ninp As Int
    Dim bufjpg(30) As Byte
    For ninp =0 To nbytes-1 Step 30
    bc.ArrayCopy(data,ninp,bufjpg,0,30)
    ptChannel.SendPublicCustomMessage(bufjpg,30)
    Next
End Sub
 

DonManfred

Expert
Licensed User
Longtime User
I need to send a jpeg in packets of maximum 30 bytes to a server.
What MISCONFIGURED Server you are using which expect Pictures in a size of 30 Bytes???????
 
Upvote 0

emexes

Expert
Licensed User
Can you send an image from some other device?
I meant to yourself, not to me, but never mind, I'm curious anyway :)

This is what i get as picture:
B4X:
               ��  JFIF     H H  � C ... [CODE]
Well, it's got the JFIF signature in there, so that's good - it is actually an image, compressed with JPEG; could easily have been PNG or some proprietary bitmap format.

It's a bit hard to read the binary data from the Unicode dump.  Can you:

1/ capture and log the actual first ~100 byte values?

2/ capture the data and send it back unaltered to a device that is known able to receive and display images, so that we *know* this packet data is correct?
 
Upvote 0

emexes

Expert
Licensed User
What MISCONFIGURED Server you are using which expect Pictures in a size of 30 Bytes???????
Plenty of protocols use small packet sizes, I figured it must be over one of those. Eg, BLE max data size is 27 bytes, SMS is 160 characters (not sure if they're bytes or ASCII or something else). CAN is worse: 8 bytes. And the packets aren't guaranteed to arrive in the same order as transmitted. Try shoehorning a more-capable protocol on top of that... we did, and it did actually work, but: only just :-/
 
Upvote 0

emexes

Expert
Licensed User
Righto, now that we've got an image transfer happening per the documentation at:

https://dev.proptt2.com/sdk-client-custommessage.html

using this Sub:
B4X:
Public Sub SendPhoto(Data() As Byte)

    Dim bc as ByteConverter    'if not already done elsewhere

    Dim SendBuffer(Data.Length + 12) As Byte    'allow extra 12 bytes for PTT header

    'PTT header per https://dev.proptt2.com/sdk-client-custommessage.html

    'Custom Message Basic header
    SendBuffer( 0) = 0x01    'Command = SENDPHOTO2CHANNEL
    SendBuffer( 1) = 0x01    'ContentType = Chunked message
    SendBuffer( 2) = 0x34    'MsgID You can decide it
    SendBuffer( 3) = 0x12    'ditto
 
    'Chunking header
    SendBuffer( 4) = 0x00    'CurrChunk = 1
    SendBuffer( 5) = 0x01    'ditto
    SendBuffer( 6) = 0x00    'ChunkCount = 1
    SendBuffer( 7) = 0x01    'ditto

    'Custom Message header
    SendBuffer( 8) = 0x02    'Type = Image format: JPEG
    SendBuffer( 9) = 0x00    'Reserved: Must be 0x00
    SendBuffer(10) = 0x00    'ditto
    SendBuffer(11) = 0x00    'ditto

    'JPEG image
    bc.ArrayCopy(Data, 0, SendBuffer, 12, Data.Length)

    Log("Data.Length = " & Data.Length & ", SendBuffer.Length = " & SendBuffer.Length)

    ptChannel.SendPublicCustomMessage(SendBuffer, SendBuffer.Length)

End Sub
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
let's see if we can send a multi-chunk image, ie > 30 kB.

It'd be useful if the documentation had an example. Like, are we meant to repeat the whole 12 bytes of header for each chunk sent, or just the Chunking header?

Presumably it'll either be all or one, so let's start with all.
 
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
let's see if we can send a multi-chunk image, ie > 30 kB.

It'd be useful if the documentation had an example. Like, are we meant to repeat the whole 12 bytes of header for each chunk sent, or just the Chunking header?

Presumably it'll either be all or one, so let's start with all.
They refer to chunkcount in the header so i assume a header for each chunk
 
Upvote 0

emexes

Expert
Licensed User
I feel like this was too easy, but give it a go anyway (never know your luck in the big city... ;-)
B4X:
Public Sub SendPhoto(Data() As Byte)

    Dim bc as ByteConverter    'if not already done elsewhere

    Dim ChunkSize As Int = 12345    'anything under 29988 should be ok, but let's play it safe for time being
    Dim DataBytesToSend As Int

    Dim ChunkCount As Int = Floor((Data.Length + ChunkSize - 1) / ChunkSize)    'probably doesn't need Floor() for Int division
    Dim CurrChunk As Int = 0

    For ChunkStart = 0 to Data.Length Step ChunkSize
        CurrChunk = CurrChunk + 1

        DataBytesToSend = Data.Length - ChunkStart
        If DataBytesToSend > ChunkSize Then
            DataBytesToSend = ChunkSize
        End If

        Dim SendBuffer(12 + DataBytesToSend) As Byte    'allow extra 12 bytes for PTT header

        'PTT header per https://dev.proptt2.com/sdk-client-custommessage.html

        'Custom Message Basic header
        SendBuffer( 0) = 0x01    'Command = SENDPHOTO2CHANNEL
        SendBuffer( 1) = 0x01    'ContentType = Chunked message
        SendBuffer( 2) = 0x34    'MsgID You can decide it
        SendBuffer( 3) = 0x12    'ditto
 
        'Chunking header
        SendBuffer( 4) = Bit.ShiftRight(CurrChunk, 8)
        SendBuffer( 5) = Bit.And(CurrChunk, 0xFF)
        SendBuffer( 6) = Bit.ShiftRight(ChunkCount, 8)
        SendBuffer( 7) = Bit.And(ChunkCount, 0xFF)

        'Custom Message header
        SendBuffer( 8) = 0x02    'Type = Image format: JPEG
        SendBuffer( 9) = 0x00    'Reserved: Must be 0x00
        SendBuffer(10) = 0x00    'ditto
        SendBuffer(11) = 0x00    'ditto

        'JPEG image
        bc.ArrayCopy(Data, ChunkStart, SendBuffer, 12, DataBytesToSend)

        Log(Data.Length & " " & ChunkCount & " " & CurrChunk & " " & ChunkStart & " " & BytesToSend & " " & SendBuffer.Length)

        ptChannel.SendPublicCustomMessage(SendBuffer, SendBuffer.Length)
    Next

End Sub
 
Upvote 0

emexes

Expert
Licensed User
Probably a good idea to also test it with that small JPEG image ie <= 12345 bytes, make sure that single-chunk images still work.
 
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
Probably a good idea to also test it with that small JPEG image ie <= 12345 bytes, make sure that single-chunk images still work.
Works good with small and big picture :)

Can you help with receiving part to append the chunks and remove the headers?
 
Upvote 0

emexes

Expert
Licensed User
Can you help with receiving part to append the chunks and remove the headers?
I should be quitting while we're ahead, but... let's do it. I'm on my last cup of tea for the night, though.

What have you got so far? Like, I assume there is some callback routine or receiving routine that the PTT library is sending you image chunks on.
 
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
I should be quitting while we're ahead, but... let's do it. I'm on my last cup of tea for the night, though.

What have you got so far? Like, I assume there is some callback routine or receiving routine that the PTT library is sending you image chunks on.


Can do it another day,no problem.

I receive a call back :
B4X:
Sub ptchev_OnPublicCustomMessageReceived(ChannelInstance As PTTChannel, SenderID As String, SenderName As String, DataBuffer() As Byte, DataLength As Int)

End Sub
 
Upvote 0

emexes

Expert
Licensed User
Hmm. How many people will a user receive images from at the same time? Can we just assume one? Or do we have to keep track of multiple incoming messages from different senders at the same time?

And how much memory have we got to play with? Like if a user is receiving 5 x 6 MB images simultaneously, it could get a bit squeezy.
 
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
Hmm. How many people will a user receive images from at the same time? Can we just assume one? Or do we have to keep track of multiple incoming messages from different senders at the same time?

And how much memory have we got to play with? Like if a user is receiving 5 x 6 MB images simultaneously, it could get a bit squeezy.

No not many , only one at a time.
And incidentally , i can limit the amount at the sending side ,both in size and interval.
 
Upvote 0

emexes

Expert
Licensed User
But I am thinking something like storing received blocks in a map, until map contains ChunkCount blocks, then assemble them into a single byte array.
 
Upvote 0

emexes

Expert
Licensed User
First draft, psuedocodish only, would look like:
B4X:
static variables:
    InImageSender As String
    InImageNumChunks As String
    InImageBuffer As Map
   

receiving routine (Sender As String, Data() As Byte)

    if Sender <> InImageSender then
        clear InImageBuffer
        InImageSender = Sender
        InImageNumChunks = from header of Data()
    end if

    ThisBlockNumber = from header of Data()
    inImageBuffer.Put(ThisBlockNumber, Data())

    if InImageBuffer.Size = ExpectedNumChunks Then
        Work out size of full image ie sum of chunk size - header
        Allocate full image buffer
        Read chunks in order, add to full image buffer
        Clear InImageBuffer
        Clear in progres variables
        pass full image to image_complete callback
    end if
 
Upvote 0
Top