Reputation: 151
I'm sending from my android phone integer as byte with the following code(I put only the needed chunks):
private byte[] intToByteArray ( final int i ) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(i);
dos.flush();
return bos.toByteArray();
}
//thread sender
data = new byte[16];
...
try {
temp = intToByteArray((int) (roll*100));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
data[3] = temp[0];
data[4] = temp[1];
data[5] = temp[2];
data[6] = temp[3];
...
p = new DatagramPacket(data, 16);
udpSocket.send(p);
The sending code works because I have tried it with a Java received, and the results are correct. The real receiver has to be implemented with an embedded device, Murata SN8200: I receive the packet, but I my integer results (for instance, roll) are not correct. The code that I'm using for converting from byte to int is the following:
void getSubArray(char* dest, char* source, int start, int end){
uint8_t i, j = 0;
for(i=start; i<end; i++){
dest[j] = source[i];
j++;
}
}
int byteToInt(char* bytes)
{
int ch1 = bytes[0];
int ch2 = bytes[1];
int ch3 = bytes[2];
int ch4 = bytes[3];
if ((ch1 | ch2 | ch3 | ch4) < 0)
WPRINT_APP_INFO ( ("boh\r\n"));
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
...
//thread receiver
wiced_packet_get_data(packet, 0, (uint8_t**)&rx_data, &rx_data_length, &available_data_length);
traffic_type = rx_data[0];
id = rx_data[1];
takeOffPressed = rx_data[2];
getSubArray(temp, rx_data, 3, 7);
roll = byteToInt(temp);
WPRINT_APP_INFO ( ("Rx: \" Packet Type: %c Id: %c TakeOffPressed = %c \r\n roll: %d \r\n ", (unsigned char )traffic_type, (unsigned char )id, (unsigned char)takeOffPressed, roll);
Reading other discussions I have already tried to do: roll = (int*)(temp); as suggested in another post, but it doesn't work for me (aliasing compiler error). Any idea to solve the problem? thanks
Upvotes: 0
Views: 147
Reputation: 180181
You have some possible signedness confusion. Consider your byteToInt()
function:
int byteToInt(char* bytes)
{
int ch1 = bytes[0];
int ch2 = bytes[1];
int ch3 = bytes[2];
int ch4 = bytes[3];
if ((ch1 | ch2 | ch3 | ch4) < 0)
WPRINT_APP_INFO ( ("boh\r\n"));
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
Suppose the 4-byte value that was sent was 511
(decimal). The bytes sent are then 0x00 0x00 0x01 0xff
. Now suppose that the receiving system features signed, two's complement char
s, which is not uncommon. In that case, on the receiver those chars will be interpreted as values 0 0 1 -1
(decimal). There are now two problems with this:
ch4
in my example) is undefined.-1 << 0
would be to yield -1
(a zero-bit shift evaluating to the value of its left operand). In that case, the overall computed value would be 256 + -1 = 255
.Of course, that's just an example, but only one in sixteen 32-bit int
s have the high bit of every byte clear.
Both issues could be addressed by performing the computation with the appropriate unsigned quantities. That could be done like this:
int byteToInt(char* bytes)
{
uint8_t ch1 = bytes[0];
uint8_t ch2 = bytes[1];
uint8_t ch3 = bytes[2];
uint8_t ch4 = bytes[3];
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
Note, too, that it is wasteful to extract a subarray to pass to byteToInt()
. It would be better to just use a bit of pointer arithmetic:
roll = byteToInt(rx_data + 3);
Upvotes: 1
Reputation: 649
#include <sdint.h>
#include <string.h>
#include <netinet/in.h>
uint32_t byteToInt(char* bytes)
{
uint8_t b[4];
memcpy(b, bytes, 4);
if ((b[0] | b[1] | b[2] | b[3]) < 0)WPRINT_APP_INFO ( ("boh\r\n"));
return ntohl(*((uint32_t *)b));
}
...
//thread receiver
wiced_packet_get_data(packet, 0, (uint8_t**)&rx_data, &rx_data_length, &available_data_length);
traffic_type = rx_data[0];
id = rx_data[1];
takeOffPressed = rx_data[2];
memcpy(temp, rx_data+3, 4);
roll = byteToInt(temp);
WPRINT_APP_INFO ( ("Rx: \" Packet Type: %c Id: %c TakeOffPressed = %c \r\n roll: %d \r\n ", (unsigned char )traffic_type, (unsigned char )id, (unsigned char)takeOffPressed, roll);
no need of
void getSubArray(char* dest, char* source, int start, int end)
you can replace it by a
memcpy(void* dest, void* src, size_t t);//from string.h
alse I have modified your byteToInt function to a thing more interessting
Upvotes: 1