Sending USB commands using usbmanager api to thermal printer - android

Hello I am using the following printer and emulation commands from the following doc:
http://www.hengstler.com/gfx/file/shop/printer/eXtendo_X-80/D-684-112_EmulationCommandSetReference_eXtendo-E-V1_07.pdf
I doing this in Java using the Android USB Manager class like so:
....
public void printData(String str, int characterSize, int startPos){
Log.d(TAG, str);
final String character = str;
setCharSize(characterSize);
startPage(startPos);
if(character != null){
Thread t = new Thread(new Runnable() {
#Override
public void run() {
byte[] bytes = character.getBytes();
ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
buffer.put(bytes);
UsbRequest req = new UsbRequest();
req.initialize(mConnection, ep);
req.queue(buffer, bytes.length);
if(mConnection.requestWait() == req){
buffer.clear();
endPage();
} else{
Log.d("USB", "No USBRequest received");
}
}
});
t.start();
}
}
public void endPage(){
Thread t = new Thread(new Runnable() {
#Override
public void run() {
byte[] array = new byte[]{29,(byte)240,06,1,20};
ByteBuffer buffer = ByteBuffer.allocate(array.length);
buffer.put(array);
UsbRequest req = new UsbRequest();
req.initialize(mConnection, ep);
req.queue(buffer, array.length);
if(mConnection.requestWait() == req){
buffer.clear();
} else{
Log.d("USB", "No USBRequest received");
}
}
});
t.start();
}
....
This all works great, I am able to print, use line feeds, set font/char sizes...etc. The only methods I am having trouble with is the one above (endPage function) which is supposed to cut the paper (see PDF above).
This is in the PDF:
2.1.18 ESC [F0]+[06]+[x]+[n]+[m] End of page
Page 27
This does not seem to do anything. I thought maybe I needed to use the controlTransfer instead and perhaps endpoint0 (which I have captured in an endpoint as well) but this doesn't do anything either. Does anyone see an obvious issue with how I'm sending this particular command to the device? This is the first time using the USB Manager / Device API and Transfers so I'm not super familiar with it. Since the other functions work, I'm hoping it may be an easy find/fix for someone more familiar with the USB interface / Communication.
UPDATE
The PDF has some errors I think, the function for cut says 29 but 1B^16..obviously incorrect, so I've also tried like this:
char[] initEP = new char[]{0x1B, 0xF1, 0x01, 0x03, 0x0A, 150};
char[] cutP = new char[]{0x1B,0xF0,0x06,01,10};
String Ptxt= new String(initEP)+ " text data \n \n \n"+ new String(cutP);
byte[] array = Ptxt.getBytes();
Still nothing. Also, the initial setup (page size) doesn't seem to do anything anyway, which leads me to believe there is an issue with the ESC??

In your code above, the command for initiating a full cut should be ...
char[] cutP = new char[]{0x1B, 0xF0, 0x06, 1, 2}
... and, in case your printer is capable of doing partial cuts, then it should be ...
char[] cutP = new char[]{0x1B, 0xF0, 0x06, 1, 1}

According to support from the manufacturer, the following is correct (and works for me):
byte[] array = {0x1B,(byte)0xF0,0x06,01,01};
The char[] array was not working I had to use a byte[] array for the cut to work and send the print data in a previous buffer. Here are the correct values:
End of print ->02
hex
0x02 = full cut
0x01 = partial cut
0x12 = intermediate full cut
0x11 = intermediate partial cut

Related

Arduino/Android Bluetooth delay

We are developping an app that uses Bluetooth library to communicate with an Arduino in bluetooth via an HC-05 module. We made a dummy configuration to test the delay without any computation from eather the Arduino or the app and we have a huge delay of about 1 second between a request and an answer...
Protocol looks easy : Android send byte -2 and if byte received is -2, Arduino send -6, -9 and Android answer again and again.
Android Code :
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
for(int i=0;i < readBuf.length;i++)
{
if((int) readBuf[i] != 0) {
txtArduino.append(String.valueOf((int) readBuf[i]) + ", ");
}
}
byte[] msg = {-2};
mConnectedThread.writeByte(msg);
break;
}
};
};
Arduino Code :
const int receveidBuffLen = 8*4;
void setup() {
Serial.begin(115200);
}
void loop() {
if (Serial.available() > 0)
{
byte buff[receveidBuffLen];
Serial.readBytes(buff, receveidBuffLen);
for(int i=0; i < receveidBuffLen;i++)
{
if(buff[i] == (byte) -2) // 254
{
byte message[2] = {(byte) -6, (byte) -9};
Serial.write(message, 2);
Serial.flush();
}
}
}
delay(3);
}
Does anyone know where the delay comes from?
We changed the HC05 baudrate (from 9600 to 115 200) : nothing happened. We changed HC05 with another : nothing happened. We used the Blue2Serial library (Bluetooth as SPP) before and delay was the same... We used another controler (ESP8266) and delay still was 1 second...
Looks like this string is an issue:
Serial.readBytes(buff, receveidBuffLen);
Where receveidBuffLen is 32.
Although you get single byte at a time, you're trying to read 32 of them. Of course, if there are no more bytes, the code will be stuck until timeout.
Furthermore, after bytes is read, you never check how many bytes were actually read, but do scan whole the array from bottom to top:
for(int i=0; i < receveidBuffLen;i++)
instead, you have to do something like this:
int bytesAvailable = Serial.available();
if (bytesAvailable > 0)
{
byte buff[receveidBuffLen];
int bytesToRead = (bytesAvailable < receveidBuffLen) ? bytesAvailable : receveidBuffLen;
// Read no more than the buffer size, but not more than available
int bytesActuallyRead = Serial.readBytes(buff, bytesToRead);
for(int i=0; i < bytesActuallyRead;i++)
...
There are a couple problems with the code that might cause delays:
delay function at end of loop - This will slow down the processing that the Ardunio can keep up with
Calling Serial.flush() - This will block the processing loop() until the internal TX serial buffer is empty. That means the Arduino is blocked and new RX data can pile up, slowing the response time.
Calling Serial.readBytes() - You should focus on the smallest unit of data and process that each loop() iteration. If you are trying to deal with multiple message per loop, that will slow now the loop time causing a delay.
You can try to implement a SerialEvent pattern on the Arduino. We will only read one byte at a time from the serial buffer, keeping the processing that the loop() function has todo to a bare minimum. If we receive the -2 byte we will mark a flag. If the flag is marked the loop() function will call the Serial.write() function but will not block for the data to transmit. Here is a quick example.
bool sendMessage = false;
byte message[2] = {(byte) -6, (byte) -9};
void loop()
{
if (sendMessage == true)
{
Serial.write(message, 2);
sendMessage = false;
}
}
/*
SerialEvent occurs whenever a new data comes in the hardware serial RX. This
routine is run between each time loop() runs, so using delay inside loop can
delay response. Multiple bytes of data may be available.
*/
void serialEvent()
{
while (Serial.available())
{
// get the new byte:
byte inChar = ((byte) Serial.read());
if (inChar == ((byte) -2))
{
sendMessage = true;
}
}
}
We just find some solutions by ourselves and want to share them :
Initial situation : 1050 ms for an answer. Alls solutions are independent and done with the initial situation.
Remove Serial.flush() : 1022 ms.
Add a simple Serial.setTimeout(100) in Arduino Code : 135 ms. (Oh man!)
Add a simple timeout to inputStream of 100ms in Android : 95 ms.
Which solution is the best, we can't say but it works now...

Android USB host : interrupt do not respond immedietly

I have a usb device which have a button.
And I want to an android app to catch a signal of the button.
I found inferface and endpoint number of the button.
It had seemed to perform ordinarily at galaxy S3 and galaxy note.
But later, I found that it has delay at other phones.
I was able to receive instant responses about 10% of the time; usually there was a 2-second delay, with some cases where the whole response was lost.
Although I couldn't figure out the exact reason, I realized that the phones that had response delays were those with kernel version 3.4 or later.
Here is the code that I used initially.
if(mConnection != null){
mConnection.claimInterface(mInterfaces.get(0), true);
final UsbEndpoint endpoint = mInterfaces.get(0).getEndpoint(0);
Thread getSignalThread = new Thread(new Runnable() {
#Override
public synchronized void run() {
byte[] buffer = new byte[8];
final ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
while(mConnection!=null){
int len = mConnection.bulkTransfer(endpoint, buffer, buffer.length, 0);
if( len>=0 ){
// do my own code
}
}
}
});
getSignalThread.setPriority(Thread.MAX_PRIORITY);
getSignalThread.start();
}
edit timeout
when the timeout was set to 50ms, I wasn't able to receive responses most of the time. When the timeout was 500ms, I was able to initially get some delayed-responses; however, I lost all responses after several tries with this setting.
Using UsbRequest
In addition to using the bulktransfer method, I also tried using UsbRequest and below is the code that I used.
#Override
public synchronized void run() {
byte[] buffer = new byte[8];
final ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
UsbRequest inRequest = new UsbRequest();
inRequest.initialize(mConnection, endpoint);
while(mConnection!=null){
inRequest.queue( byteBuffer , buffer.length);
if( mConnection.requestWait() == inRequest ){
// do my own code
}
}
}
However, the same kind of delay happened even after using UsbRequest.
Using libusb
I also tried using libusb_interrupt_transfer from an open source library called libusb.
However this also produced the same type of delay that I had when using UsbDeviceConnection.
unsigned char data_bt[8] = { 0, };
uint32_t out[2];
int transfered = 0;
while (devh_usb != NULL) {
libusb_interrupt_transfer(devh_usb, 0x83, data_bt, 8, &transfered, 0);
memcpy(out, data_bt, 8);
if (out[0] == PUSH) {
LOGI("button pushed!!!");
memset(data_bt, 0, 8);
//(env)->CallVoidMethod( thiz, mid);
}
}
After looking into the part where libusb_interrupt_transfer is processed libusb, I was able to figure out the general steps of interrupt_transfer:
1. make a transfer object of type interrupt
2. make a urb object that points to the transfer object
3. submit the urb object to the device's fd
4. detect any changes in the fd object via urb object
5. read urb through ioctl
steps 3, 4, 5 are the steps regarding file i/o.
I was able to find out that at step 4 the program waits for the button press before moving onto the next step.
Therefore I tried changing poll to epoll in order to check if the poll function was causing the delay; unfortunately nothing changed.
I also tried setting the timeout of the poll function to 500ms and making it always get values of the fd through ioctl but only found out that the value changed 2~3 seconds after pressing the button.
So in conclusion I feel that there is a delay in the process of updating the value of the fd after pressing the button. If there is anyone who could help me with this issue, please let me know. Thank you.
Thanks for reading

How to send image from matlab to android over bluetooth?

Problem:
I want to send an image from matlab to android over bluetooth.
Matlab and android are connected to each other and I can send strings without a problem.
fprintf(tabletObj, 'sleep');
I have a really huge byteArray containing the image I want to send to android. Here you can see just the first bytes:
planString = [-119,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,72,0,0,0,72,8,6,0,0,0,85,-19,-77,71,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,-120,0,0,29,2,73,68,65,84,120,-100,-75,-100,121,-68,37, ... ]
After that, I set in matlab the OutputBufferSize to the size of the image and send it to the tablet.
s = whos('planString');
obj1.OutputBufferSize = s.bytes;
% Send it to tablet
fwrite(tabletObj, planString, 'int8');
In android you can see following incoming bytes.
Why are there just the first 6 bytes and not more?
The next incoming bytes are more then just 6 bytes, why?
I set the buffersize in android to the same size like matlab.
private void listen() {
byte[] buffer = new byte[picSize]; // buffer store for the stream
Log.i(TAG, "buffer length" + buffer.length);
while (true) {
try {
inputStream.read(buffer);
newMessageReceived(new String(buffer, "UTF-8")); // Send the obtained bytes to the UI activity
} catch (IOException e) {
break;
}
}
}
Edit #1:
I used following code to get only the "right" bytes and put that into an ArrayList with bytes. Now, it seems like that I have just the needed bytes. But it's too slow! You need to wait for more than 1 min. to get all bytes from matlab. Is there a better solution? Why are the incoming bytes split sometimes in 3, sometimes in 15, ...? (see picture below code)
ArrayList<byte[]> bytes = new ArrayList<byte[]>();
...
int nread = inputStream.read(buffer);
byte[] newOne = new byte[nread];
System.arraycopy(buffer, 0, newOne, 0, nread);
bytes.add(newOne);
private void listen() {
byte[] buffer = new byte[10000];
int nbytes = 0;
while (true) {
try {
int nread = inputStream.read(buffer, nbytes, buffer.length - nbytes);
nbytes += nread;
... // after getting all bytes
newMessageReceived(buffer, nbytes); // Send bytes to the UI activity
} catch (IOException e) {
break;
}
}
}
#greenapps thanks for the solution.

issue in reading a serialized object

I am trying to create a client-server android app in which I want to transfer a file using a UDP protocol. Till now I am able to transfer the file and receive the acknowledgements for the packets.
Now I want to add the sequence numbers to the with the data in the packet. I have tried to do the following:
Create a ByteArrayOutputStream.
Wrap it in an ObjectOutputStream
Write data to the object using writeObject()
Serialized class includes:
public class Message implements Serializable {
private int seqNo;
private byte[] data;
private boolean ack;
public Message(int seqNo, byte[] data, boolean ack) {
this.seqNo = seqNo;
this.data = data;
this.ack = ack;
}
Client Side
byte[] fileBytes = new byte[500];
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(outStream);
while((numBytesRead = inputBuf.read(fileBytes)) != -1) {
//DatagramPacket packet = new DatagramPacket(fileBytes, fileBytes.length);
if (os == null) {
os = new ObjectOutputStream(outStream);
}
Message msg = new Message(++seqNo, fileBytes, false);
os.writeObject(msg);
os.flush();
os.reset();
byte[] data = outStream.toByteArray();
atagramPacket packet = new DatagramPacket(data, data.length);
clientSocket.send(packet);
}
Server Side
byte[] incomingData = new byte[1024];
while (true) {
try{
DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length);
serverSocket.receive(incomingPacket);
byte[] data = incomingPacket.getData();
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
if (is == null) {
is = new ObjectInputStream(in);
}
Message msg = (Message) is.readObject();
System.out.println(msg.getSeqNo());
out.write(msg.getData(),0,msg.getData().length);
}
The problem that I am facing is
I am receiving the same sequence number for each packet (i.e. 1)
I am not sure about the buffer size for the incoming packet, as I am using 500 bytes at Client side and 1024 at
the Sever. And if I take 500 bytes at both the sides I get an EOFexception.
I would really appreciate if you could suggest better ways to implement the same thing! Thanks :)
Message msg = new Message(++seqNo, fileBytes, false);
Here you are assuming that the prior read() filled the buffer. On the last read() before end of file it almost certainly won't, and it isn't guaranteed to fill it any time, only to transfer at least one byte.
You should be passing the read count 'numBytes' to this constructor, and it should create a byte array of that size, and copy only that many bytes into it.
Other issues:
It is impossible for 'os' to be null at the point you're testing it.
Ditto 'is'.
You should be creating a new ObjectOutputStream and ByteArrayOutputStream per datagram.
Java Datagrams keep shrinking to the size of the shortest datagram payload received so far. You must either create a new one per receive, or at least reset its length before each receive.
you need a larger buffer at the receiver because of ObjectOutputStream overheads.
I don't believe this code presently works at all, let alone that you keep getting the same sequence number. More likely you keep getting the same message, because you're ignoring an exception somewhere.

Why is data from Arduino to Android using Android host api garbled?

I followed this tutorial to get started using Android host api with an Arduino board. I am using the Arduino Uno. I am able to transmit data and turn on a LED on the Arduino board and I can receive feedback from the Arduino board. I am trying to write to my Android device over the USB connection from the Arduino board like so:
Serial.print("Test");
I am receiving the Arduino data on the Android side like this:
byte[] buffer = new byte[10];
int bytes;
//try-catch statements omitted for simplicity
bytes = mUsbConnection.bulkTransfer(mUsbEndpointIn, buffer, buffer.length, 0);
Every once and awhile the data will be intact but more often than not, what I receive from the Arduino is a garbled mix of those letters from my original message(t,e,s, and t). Many times only 1 or 2 letters are displayed. If anyone could point me in the right direction or share some similar experience I would be appreciative. Thanks.
Edit
When I print out the data into Logcat, there are multiple copies of the data. For example, if I receive "ste" from Arduino, it will be printed out 2-5 times in Logcat.
I think I found something that works at least temporarily:
public void run(){
int i = 0;
byte[] buffer = new byte[4];
byte[] finalBuffer = new byte[8];
byte[] sendBuffer = new byte[8];
int bytes = 0;
while(true){
try{
bytes = mUsbConnection.bulkTransfer(mUsbEndpointIn, buffer, buffer.length, 0);
if (bytes == EXIT_CMD) {
return;
}
if (bytes > 0){
byte[] temporaryBuffer = new byte[bytes];
System.arraycopy(buffer, 0, temporaryBuffer, 0, bytes);
System.arraycopy(temporaryBuffer, 0, finalBuffer, i, bytes);
i += bytes;
java.util.Arrays.fill(buffer, (byte) 0);
}
//Dollar sign terminates string to indicate end of line
if (finalBuffer[7] == 36){
i = 0;
System.arraycopy(finalBuffer, 0, sendBuffer, 0, sendBuffer.length);
messageHandler.obtainMessage(UsbHostTestActivity.ARDUINO_MESSAGE,
sendBuffer.length, -1, sendBuffer).sendToTarget();
java.util.Arrays.fill(finalBuffer, (byte) 0);
}
I had to send strings that were 8 characters exactly from Arduino and they had to end with a dollar sign($) in order to indicate the end of the line, but the data being passed to my message handler always seemed to be correct. It's not the most robust solution but maybe someone can modify it to make it better or take another approach? Please let me know!

Categories

Resources