Convert java long to uint64_t

Hi all,

I have an issue converting a java long to an uint64_t value to the Arduino platform.
Here is the code, both for the Arduino part and the java one.

Arduino code:

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x20, 0x45 };
byte ip[] = { 192, 168, 33, 17 };
byte javaServer[] = { 192, 168, 33, 16 };

Server server(10001);
Client javaClient(javaServer, 10002);

void setup()
{
  int i = 0;
  uint64_t javaLong = 0;
  byte buffer[16];

  Serial.begin(57600);
  Ethernet.begin(mac, ip);
  server.begin();
  
  delay(3000);
  
  Client client = server.available();
  
  if (client) {
    Serial.println("Client available");
    
    // read the input buffer    
    Serial.println("Receiving bytes...");
    while (client.connected() && i < sizeof(buffer)) {
      if (client.available()) {
        buffer[i] = client.read();
        i++;
      }
    }
    Serial.println("Bytes received");
    
    Serial.print("Num of bytes readed: ");
    Serial.println(i);
    
    Serial.print("Received bytes: ");
    for (int i = 0; i < sizeof(buffer); i++) {
      Serial.print(buffer[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
    
    // copy the buffer value to the uint64_t variable
    memcpy(&javaLong, buffer, sizeof(uint64_t));
    
    Serial.print("Uint64_t value = ");
    Serial.print((unsigned long) javaLong);
    Serial.print(", binary: ");
    Serial.println((unsigned long) javaLong, BIN);
    
    client.stop();
  }
  else {
    Serial.println("Client not available!");
    return;
  }
    
  byte *longPtr = (byte *) &javaLong;
  
  Serial.print("Number to send (hex format): ");
  for (i = 0; i < sizeof(uint64_t); i++) {
    Serial.print(* (longPtr + i), HEX);
    Serial.print(" ");
  }
  Serial.println();
  
  if (javaClient.connect()) {
    // send
    if (longPtr) {
      Serial.println("Sending bytes...");
      for (i = 0; i < 8; i++) {
        javaClient.write(* (longPtr + i));
      }
      Serial.println("Sending finished");
    }
    
  delay(1);
  javaClient.stop();
  }
  else {
    Serial.println("NOT connected");
  }
}

void loop() { }

Java code:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;

public class SendReceiveUint64 {
  
  public static final int SHIFT_ONE_BYTE = 8;
  public static final int SHIFT_TWO_BYTES = 16;
  public static final int SHIFT_THREE_BYTES = 24;
  public static final int SHIFT_FOUR_BYTES = 32;
  public static final int SHIFT_FIVE_BYTES = 40;
  public static final int SHIFT_SIX_BYTES = 48;
  public static final int SHIFT_SEVEN_BYTES = 56;
  public static final int SHIFT_EIGHT_BYTES = 64;

  public static final long FIRST_8_BITS_MASK_LONG = 0x000000FFL;
  public static final long SECOND_8_BITS_MASK_LONG = 0x0000FF00L;
  public static final long THIRD_8_BITS_MASK_LONG = 0x00FF0000L;
  public static final long FOURTH_8_BITS_MASK_LONG = 0xFF000000L;


  public static void main(String[] args) {
    
    Socket socket = null, client = null;
    ServerSocket server = null;
    int serverPort = 10002;
    OutputStream sockOutput = null;
    InputStream sockInput = null;
    byte[] b = null;
//    long num = 2147483648L;
    long num = 21474836489L;
    
    System.out.println("Original long value: " + num);
    System.out.println("Bytes in (java) memory: " + Long.toHexString(num));
    System.out.println("Number in binary format: " + Long.toBinaryString(num));
    
    try {
      socket = new Socket("192.168.33.17", 10001);
      sockOutput = socket.getOutputStream();
      
      if (socket == null || sockOutput == null) {
        System.out.println("Error while creating socket");
        return;
      }

      b = longToByteArray(num);
      
      System.out.print("Hex format: ");
      for (int i = 0; i < b.length; i++) {
        System.out.printf("%02X ", b[i]);
      }
      System.out.println();
      
      sockOutput.write(b);
      
      socket.close();
    } 
    catch (IOException io) {
      io.printStackTrace();
    }
    
    try {
      server = new ServerSocket(serverPort);
      
      if (server == null) {
        System.out.println("Error while creating server socket");
        return;
      }
      System.out.println("Server started");
      
      client = server.accept();
      
      if (client == null) {
        System.out.println("No client connected");
        return;
      }
      System.out.println("New socket accepted");
      
      sockInput = client.getInputStream();
      
      byte[] buf = new byte[256];
      int bytesRead = 0;
      
      try {
        // delay needed to read all the input buffer
        Thread.sleep(200);
        bytesRead = sockInput.read(buf, 0, buf.length);
        System.out.println("Input buffer received");
        
        if (bytesRead < 0) {
          System.out.println("Trying to read from socket, but failed");
          return;
        }
        System.out.println("Readed " + bytesRead + " bytes");
        
        byte[] uint64Bytes = new byte[8];
        System.arraycopy(buf, 0, uint64Bytes, 0, uint64Bytes.length);
        
        System.out.print("Bytes received from the net (hex): ");
        for (int i = 0; i < uint64Bytes.length; i++) {
          System.out.printf("%02X ", uint64Bytes[i]);
        }
        System.out.println();
        
        long receivedNum = bytesToLong(uint64Bytes, (uint64Bytes.length - 1));
        System.out.println("Received number = " + num);
        
        System.out.print("Bytes in hex format: ");
        System.out.println(Long.toHexString(receivedNum));
        System.out.print("Bytes in binary format: ");
        System.out.println(Long.toBinaryString(receivedNum));
        
        System.out.print("Bytes in memory (hex): ");
        for (int i = 0; i < uint64Bytes.length; i++) {
          System.out.printf("%02X ", uint64Bytes[i]);
        }
        System.out.println();
        
      }
      catch (Exception e) {
        System.err.println("Exception reading from/writing to socket, e = " + e);
        e.printStackTrace(System.err);
        return;
      }
      socket.close();
    }
    catch (IOException e) {
      e.printStackTrace(System.err);
    }

  }
  
  public static byte[] longToByteArray(long value) {
    
    byte[] array = new byte[8];
    
    array[0] = (byte)  (value & FIRST_8_BITS_MASK_LONG);
    array[1] = (byte) ((value & SECOND_8_BITS_MASK_LONG) >>> SHIFT_ONE_BYTE);
    array[2] = (byte) ((value & THIRD_8_BITS_MASK_LONG)  >>> SHIFT_TWO_BYTES);
    array[3] = (byte) ((value & FOURTH_8_BITS_MASK_LONG) >>> SHIFT_THREE_BYTES);
    array[4] = (byte) ((value & FIRST_8_BITS_MASK_LONG)  >>> SHIFT_FOUR_BYTES);
    array[5] = (byte) ((value & SECOND_8_BITS_MASK_LONG) >>> SHIFT_FIVE_BYTES);
    array[6] = (byte) ((value & THIRD_8_BITS_MASK_LONG)  >>> SHIFT_SIX_BYTES);
    array[7] = (byte) ((value & FOURTH_8_BITS_MASK_LONG) >>> SHIFT_SEVEN_BYTES);
    
    return array;
  }
  
  public static long bytesToLong(byte[] value, int end) {
    
    byte[] b = new byte[8];
    
    // storing bytes in little-endian form
    for (int i = 0, pos = end; i < 8; i++) {
      b[i] = value[pos - i];
    }
    return ByteBuffer.wrap(b).getLong();
  }

}

I have no issue if the input number fits into 32 bits. Following is the output for the number 2147483648L.

Arduino side:

Num of bytes readed: 8
Received bytes: 0 0 0 80 0 0 0 0 
Uint64_t value = 2147483648, binary: 10000000000000000000000000000000
Number to send (hex format): 0 0 0 80 0 0 0 0

Java side:

Original long value: 2147483648
Bytes in (java) memory: 80000000
Number in binary format: 10000000000000000000000000000000
Hex format: 00 00 00 80 00 00 00 00 
Input buffer received
Readed 8 bytes
Bytes received from the net (hex): 00 00 00 80 00 00 00 00 
Received number = 2147483648
Bytes in hex format: 80000000
Bytes in binary format: 10000000000000000000000000000000
Bytes in memory (hex): 00 00 00 80 00 00 00 00

Instead, if the input long number does not fit into 32 bits, the result is incorrect. This is the output for the number 21474836489L.

Arduino side:

Num of bytes readed: 8
Received bytes: 9 0 0 0 0 0 0 0 
Uint64_t value = 9, binary: 1001
Number to send (hex format): 9 0 0 0 0 0 0 0

Java side:

Original long value: 21474836489
Bytes in (java) memory: 500000009
Number in binary format: 10100000000000000000000000000001001
Hex format: 09 00 00 00 00 00 00 00 
Input buffer received
Readed 8 bytes
Bytes received from the net (hex): 09 00 00 00 00 00 00 00 
Received number = 21474836489
Bytes in hex format: 9
Bytes in binary format: 1001
Bytes in memory (hex): 09 00 00 00 00 00 00 00

Does anyone have some suggestions?
Thanks in advance.

Bytes in (java) memory: 500000009
Number in binary format: 10100000000000000000000000000001001
Hex format: 09 00 00 00 00 00 00 00

The hex format does not appear to match the binary format.

Is this simply that the compiler won't handle 64 bit constants? How are you inputting 21474836489 into the program?

PaulS:

Bytes in (java) memory: 500000009
Number in binary format: 10100000000000000000000000000001001
Hex format: 09 00 00 00 00 00 00 00

The hex format does not appear to match the binary format.

Yes,

and the "hex format" come from this method:

  public static byte[] longToByteArray(long value) {
    
    byte[] array = new byte[8];
    
    array[0] = (byte)  (value & FIRST_8_BITS_MASK_LONG);
    array[1] = (byte) ((value & SECOND_8_BITS_MASK_LONG) >>> SHIFT_ONE_BYTE);
    array[2] = (byte) ((value & THIRD_8_BITS_MASK_LONG)  >>> SHIFT_TWO_BYTES);
    array[3] = (byte) ((value & FOURTH_8_BITS_MASK_LONG) >>> SHIFT_THREE_BYTES);
    array[4] = (byte) ((value & FIRST_8_BITS_MASK_LONG)  >>> SHIFT_FOUR_BYTES);
    array[5] = (byte) ((value & SECOND_8_BITS_MASK_LONG) >>> SHIFT_FIVE_BYTES);
    array[6] = (byte) ((value & THIRD_8_BITS_MASK_LONG)  >>> SHIFT_SIX_BYTES);
    array[7] = (byte) ((value & FOURTH_8_BITS_MASK_LONG) >>> SHIFT_SEVEN_BYTES);
    
    return array;
  }

Is there something wrong in the conversion?

MarkT:
Is this simply that the compiler won't handle 64 bit constants? How are you inputting 21474836489 into the program?

long num = 21474836489L;

Try 21474836489LL ? Otherwise enter it in two parts.

MarkT:
Try 21474836489LL ? Otherwise enter it in two parts.

Why 21474836489LL? "LL" seems not to exist in java.

And the java long type is 64 bytes large (see Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics)).

Maybe is there a bug in my longToByteArray() method?

I found the error in my longToByteArray() method. :slight_smile:

This is the correct code:

    b[0] = (byte) (n & 0xFF);
    b[1] = (byte) ((n >> 8) & 0xFF);
    b[2] = (byte) ((n >> 16) & 0xFF);
    b[3] = (byte) ((n >> 24) & 0xFF);
    b[4] = (byte) ((n >> 32) & 0xFF);
    b[5] = (byte) ((n >> 40) & 0xFF);
    b[6] = (byte) ((n >> 48) & 0xFF);
    b[7] = (byte) ((n >> 56) & 0xFF);

ramo102:

MarkT:
Try 21474836489LL ? Otherwise enter it in two parts.

Why 21474836489LL? "LL" seems not to exist in java.

And the java long type is 64 bytes large (see Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics)).

Maybe is there a bug in my longToByteArray() method?

I meant in the Arduino version, that's the one without 64bit longs!

MarkT:

ramo102:

MarkT:
Try 21474836489LL ? Otherwise enter it in two parts.

Why 21474836489LL? "LL" seems not to exist in java.

And the java long type is 64 bytes large (see Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics)).

Maybe is there a bug in my longToByteArray() method?

I meant in the Arduino version, that's the one without 64bit longs!

You asked me:

How are you inputting 21474836489 into the program?

And I input it from within the java version. :slight_smile:

Now, with the method that convert the java long in an array of (eight) bytes, all works like a charm.