C++/Java - int(0 - 1023) to byte Array (two bytes only) - java

How do I get the following int to a byte array. I have been reading other SO questions and everything is confusing, could someone explian what is happening in the code.
int val = 1023; // the int will vary from 0 to 1023 (it's the analogRead value from an Arduino board)
the purpose of me wanting this as a byte array is so that i can use it for Arduino's server.write().
This is what I've come up with so far:
int val = analogRead(A0);
Serial.println(val);
byte value[2];
value[1] = val & 0x000000ff;
value[0] = (val & 0x0000ff00) >> 8;
server.write(value[0]);
server.write(value[1]);
I am trying to communicate TCP with an Android application I have written, here is the recieving end:
mmInStream = mmSocket.getInputStream();
final byte[] buffer = new byte[16384]; // two bytes
int bytes;
bytes = mmInStream.read(buffer);
Log.d(null,buffer[0]+buffer[1]);
is this correct?
The Arduino console is spitting out the values, example:
870
870
870
872
However my Android application is spitting out the following, example:
3102
3105
1033
1035
I must be doing something wrong here!
ANSWER: Arduino sends unsigned bytes, java recieves only signed bytes. I fixed it with a little code on the java end.

Whenever you're going to be dealing with some binary communications protocol, be it a TCP connection, Serial Port, USB, etc. you need to save yourself some future headaches and define your protocol.
Specifically, this means field widths, and byte order. When sending binary data over a network protocol, we almost always send it in "network order", which is "big-endian", meaning the most-significant byte first.
Example: I want to send a four-byte int a = 0x12345678 over the network. If you do it correctly, the bytes go out in the order 12 34 56 78.
However, I believe your ATMEGA chip is little-endian, which means that bytes are stored (in memory) with the least-significant byte first. So if you were to just cast that int to a unsigned char* and send 4 bytes, they would go out in the order 78 56 34 12.
So in order to send that value out, you should first decide how many bytes it's going to be. Since you've limited it to the range 0 - 1023, you've observed that it will fit into just two bytes. Good. So your protocol is:
Offset 0: value Size: 2
Now, you need to send it in network order. Your example code:
byte value [2];
value[1] = val & 0x000000ff;
value[0] = (val & 0x0000ff00) >> 8;
is putting the most significant byte at position 0, and the least significant byte at position 1. So a value of 0x1234 will go out in the order 12 34. Perfect.
Your code is correct (on the Arduino side).
Now, on the receiving side, you need to make sure that you're receiving data in network order also. I haven't done any Java network programming, so you'll need to check with the documentation to see how it handles network binary streams. In particular, when you go to read that "16-bit unsigned integer" from the network, the byte order needs to be respected.
Perhaps this will help you on the Java side:
network byte order to host byte order in java

This will encode an int as a byte array.
// Encoding
byte value[2] = { highByte(val), lowByte(val) };
This will convert a byte array back to an integer
// Decoding
int val = value[0] << 8 + value[1];

Related

Merging two bytes?

I am learning how MIDI works and am wondering how to merge two bytes. There is a paragraph that states the following
“The status and channel Bytes are merged into one byte (00-FF) Because these messages have an MSB (Most Significant Byte) of 1 the command statuses actually begin at 80 hexadecimal (128 and up to 255) The LSB (Least Significant Byte takes a value of 0-F Hexadecimal (0 to 15) to specify which MIDI channel the command will be sent to. A command message tells the MIDI gear to perform certain types of things like play a note, change the volume, add effects, and other types of things. This table shows the different command status and what they do.”
I am not 100% sure what it means by merging Bytes into a byte. Any help would be appreciated. If you could provide an example of how to do this in java with an explanation I’d be even more grateful.
So I found the answer to the problem.
Byte b1 = 0xF;
Byte b2 = 0xF;
Byte merged = (b1 >> 4 | b2);
Byte 1 is shifted four bits to the left to guarantee it is the most significant bit while byte 2 is bitwise or as the least significant bits. The important thing is that the paragraph i posted above says you may merge two bytes together. Both bytes must be at a maximum of 4 bits. If they exceed 8 bits total the result is a short or int based on how large the result is.

Unknown input byte length convert to int

My android program need to receive int values from arduino analog sensor via usb and print them on real time graph, i receive byte[] from call back function.
i tried many ways to convert from byte[] to string or int include new String new Integer BigInteger parseInt and some code method that i find in other topics, but nothing work i receive only half of the correct values, other values to much bugger or smaller.
The byte[] length changed from 1 to 4 , their is some empty bytes, it look like this(log):
How i can to convert it to correct values? where the problem?
In ideal i need receive int values between 230 to 300 from sensor.
It seems that your sensor is using text protocol. If I convert your bytes to ASCII chars, it will be:
..
10-LF
50-2
53-5
56-8
..
13-CR
10-LF
50-2
53-5
..
54-6
13-CR
10-LF
etc.
Interpreted as
258
256
so, I thing the best solution is to accumulate received bytes as chars and when CRLF is reveived, read whole string (with stripped CRLF) as int - probably via parseInt.
Arduino code segment?
Guessing badly : int is a 16 bit value byte is 8 bits.
Int_8 is -128 to 127 . uint8_t 0-255 not supported by java as far as i know but you can use the char type unsigned 16 bit(need to cast it).

Incoming Data of bytes

I am dealing with a socket connection in which I send and then receive bytes. I have the socket code written and I can both send and receive bytes but there is a catch...
I am sending data within a language called Delphi and then receiving them in the android code. But I come into a bit of a problem.
In delphi a byte has a maximum value of 255 whereas in Android the maximum byte is 127. How would you get around this? Is there a way to use an unsigned byte? Should I use shorts instead of bytes?
Any help is appreciated.
To read a single byte you can cast it to a larger Java/Android primitive type to interpret it as an unsigned value by performing a bitwise & (AND) with an 8 bit mask. To write a value to the socket as an unsigned byte value use a larger primitive type to set the value, then cast this value to a byte to write to the socket. For example:
short shortVal = 255;
byte byteVal = (byte) shortVal;
System.out.println("signed value = " + byteVal);
shortVal = (short) (byteVal & 0xFF);
System.out.println("unsigned value = " + shortVal);
Java/Android interprets the byte as a signed value (in this case, -1), but the 8 bits in the byte (11111111) are still the same as the least significant 8 bits in the short 255 (0000000011111111).
The same technique can be used with larger types (use int with 16 bit mask to interpret short as unsigned, long with 32 bit mask to interpret int as unsigned), but with multibyte values be careful to take into account the endianness of the network protocol and convert byte order if needed.

Java How to read unsigned short using inputstream?

The C++ client send a byte array to the Java Server.The first two bytes indicate the length of the residual byte array.The client uses unsigned short,but there's no unsigned short in java.How can I read the first two bytes in my server?
And another problem is,in C++ the first byte indicates the lower 8 bits and the second byte indicates the upper 8 bits.For example,the two bytes is 35 02,it convert to decimal should to be 565,not 13570.
My java code like this:
DataInputStream dis = new DataInputStream(is);
int b1 = dis.readUnsignedByte();
int b2 = dis.readUnsignedByte();
int length = (b2 << 8) | b1;
It seems to work.But I can't make sure it is exact in any condition.I hope for your suggestions.thx~
Err, DataInputStream.readUnsignedShort()!
I can't make sure it is exact in any condition
You can't test 65536 values? It's not difficult.
To convert an unsigned short to a signed int you can do
int value = dis.readShort() & 0xFFFF;
Your other problem has to do with the byte order. I suggest taking a look at the ByteBuffer which you can specify the byte order on using the order method.

Java- gzip member trailer

This is part of a larger assignment that I've mostly got done except for this one part, which is a bit embarrassing because it sounds really simply on paper.
So basically, I've got a large amount of compressed data. I've been keeping track of the length using a CRC32
CRC32 checksum = new CRC32();
...
//read input into buffer
checksum.update(buff, 0, bytesRead);
So it updates everytime more info is read in. I've also kept track of the uncompress length using
uncompressedLength += manage.read(buff);
So it is an int value that has the number of bytes of the original file. This is a little Endian machine.
From what I can tell, what I need is four byte CRC, which I used
public byte[] longToBytes(long x) {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong(x);
return buffer.array();
}
byte[] c = longToBytes(checksum.getValue());
BUT this is 8 bytes. CRC32.getValue returns a long. Can I convert it to an int in this case without losing information I need?
And then the ISIZE is supposed to be...the four byte compressed length modulo 2^32. I've got the variable uncompresedLength which is an int. I think I just have to convert it to bytes and that's all?
I've been hexdumping the result from gzip and the result from my program and my header and data are right, I'm just missing my trailer.
As for why I'm doing this manually, it's because of an assignment. Trust me, I'd love to just use GZIPOoutputStream if I could.
CRC32 has 32 bits... the class returns long because of the super interface.
uncompressed length should be long, since nowadays files larger than 2G isn't uncommon.
so in both cases, you need to convert the lowest 32 bits of a long to 4 bytes.
static byte[] lower4bytes(long v)
{
return new byte[] {
(byte)(v ),
(byte)(v>> 8),
(byte)(v>>16),
(byte)(v>>24)
};
}
To write an integer in little-endian form, simply write the low byte of the integer (i.e. modulo 256 or anded with 0xff), then shift it down eight bits or divide by 256, then write the resulting low byte, and repeat that two more times. You'll write four bytes. Since you only write four, you will automatically be writing the length modulo 232.

Categories