Android Question Asyncstreams output buffer size?

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
I'm developing a class that writes data to a Star TSP100iiiBi Bluetooth printer. This particular printer only supports raster graphics, so I have to send everything to it as a raster image, no plain ASCII text is supported.

The problem I'm having is that the last data I send to the printer never seems to actually make it to the printer. I create a 24k byte array (23,258 bytes using B4XBytesBuilder .ToArray function, actually) that I write directly to the Asyncstream via Stream.Write(EntireByteArray) and it throws no errors. After writing, I fire an event in the class that the Activity responds to by issuing a command that causes the class to close the connection (stream.SendAllAndClose followed by Serial.Disconnect). The last few bytes of what I'm sending never seem to get to the printer.

I verified the byte values I'm sending with Star Micronics developer integration to be correct, and Star's PassPRNT Android app produces output correctly when started from an intent. If I send multiple copies of the bitmap to the printer, all images print correctly except for the last one, which never completes.

As a work-around I wrote a routine that outputs the full array in 2k chunks (i.e. send 2K bytes, followed by a sleep for 100 milliseconds, then send the next 2k, etc. for the size of the output array) followed by a 250 millisecond pause before firing the event that leads to disconnecting. At no time during this have I observed the stream's OutputQueueSize change from zero.

This workaround seems to produce the desired output fairly reliably. Although, if I increase the buffer to 3K I start seeing the same behavior I got from just writing the entire byte array at once. A long way to go to get to my question, I know, but I wanted to give a framework for why I'm asking the question.

Is there some type of setting for the output buffer size that I can work with, or is there a reason I never see the OutputQueueSize value change from zero or am I failing at some other fundamental level?

-- Edit -- Rubber ducking this as I typed this post lead me to trying adding a sleep(5000) to my Stream.Write(EntireByteArray) method. This seems to solve the problem as well. I guess at this point it seems to indicate perhaps the .SendAllAndClose is not actually sending all before closing the stream? Or, perhaps it's still going when I close the serial connection? Either way, I would have to have some means of knowing if all the bytes have been sent as it seems I cannot use the OutputQueueSize value.
 
Last edited:
Solution
FWIW:

Assuming there's no way to query the output queue, I've decided to use the printer status command as my "complete" flag, foregoing any sleep statements.

The last command I send the printer is "give me your status," I then wait until I receive something from the printer or a timeout period has elapsed (I really don't care what I get at this point, just that I get something).

Once I get the status bytes from the printer, I then fire the complete event and close the connection. As a workaround, this seems to be the least "hackish."

I've tested this with up to four copies of a 6-inch image (113k bytes of data) and seems to be working reliably.

Erel

B4X founder
Staff member
Licensed User
Longtime User
The problem is that the data can pass between several layers until it actually reaches the connected device. AsyncStreams passes the data to the native API and assumes that the data was sent right after the execution returns from that call. Depending on the specific type of connection and implementation it can happen that the data wasn't actually sent yet.

Adding Sleep is sometimes the best solution, when the other device doesn't send any acknowledge signal.
 
Upvote 0

emexes

Expert
Licensed User
Another way to force flushing faster than waiting 5 seconds might be to send a heap of ASCII NULs aka CHR(0)

assuming that the raster data is normally enclosed within some kind of command packet, and that the printer ignores bytes that are not in a valid packet
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
The problem is that the data can pass between several layers until it actually reaches the connected device. AsyncStreams passes the data to the native API and assumes that the data was sent right after the execution returns from that call. Depending on the specific type of connection and implementation it can happen that the data wasn't actually sent yet.

Adding Sleep is sometimes the best solution, when the other device doesn't send any acknowledge signal.
The problem with that is how long to sleep? The amount of time has varied in my testing. 1000ms is fine for a 24k bitmap, when I send upwards of 64k worth of data, it is not. I hate to make the user wait for the app to get done printing unnecessarily. Is there no direct java code or function that can directly query the output buffer?

Another way to force flushing faster than waiting 5 seconds might be to send a heap of ASCII NULs aka CHR(0)
I did try this, I have sent up to 10k worth of null bytes and the behavior did not change.

I did check the printer commands, and there is no "are you still printing" status result. I can check paper out, print-head error, etc. but nothing to indicate "busy" or not. I don't think the issue is with the printer anyway, it seems to be strictly with my app and closing the serial connection before everything has been sent.

At this point, I'm seriously considering just making a 5-10k pure white bitmap and sending it after what I actually want to print but this seems a bit hackish and could come back to bite me if vertical spacing becomes important at some point in the future.
 
Last edited:
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
FWIW:

Assuming there's no way to query the output queue, I've decided to use the printer status command as my "complete" flag, foregoing any sleep statements.

The last command I send the printer is "give me your status," I then wait until I receive something from the printer or a timeout period has elapsed (I really don't care what I get at this point, just that I get something).

Once I get the status bytes from the printer, I then fire the complete event and close the connection. As a workaround, this seems to be the least "hackish."

I've tested this with up to four copies of a 6-inch image (113k bytes of data) and seems to be working reliably.
 
Upvote 0
Solution
Top