简体   繁体   中英

Java decoding bytes from a GPS device with ByteBuffer

I'm facing issues decoding bytes send from a GPS device to my java UDP listener program. I can extract some of the information but for other info I cannot understand how to do this. The format of the data from the device manual is as follows:

Name       | Type          | Length
length:    | short         | 2
cmd:       | short         | 2
enabled:   | unsigned char | 1
alarm:     | unsigned char | 1
speed:     | char          | 1
direction: | short         | 2
longitude: | double        | 4
latitude:  | double        | 4
datetime:  | long          | 4
userid:    | char          | 11
iostate:   | char          | 1
oilstate:  | char          | 1

In my program I can decode length, command, alarm, speed, direction and device. I am stuck on latitude, longitude and datetime and would require some assistance. The values that I get are completely far from what the proper ones should be. This was working without any issues on python with the struct.unpack function.

The code in the function is as follows:

private void SetupUDP() throws IOException {
        String message;
        // Setup UDP Stuff and listen on all interfaces
        DatagramSocket serverSocket = new DatagramSocket(9876, InetAddress.getByName("0.0.0.0"));
        byte[] receiveData = new byte[1024];
        while(true) {
            // Start receiving UDP packets from devices
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            serverSocket.receive(receivePacket);

            ByteBuffer data = ByteBuffer.wrap(receivePacket.getData());
            data.order(ByteOrder.LITTLE_ENDIAN);
            if (receivePacket.getLength() == 15) {
                short len = data.getShort(0);
                short cmd = data.getShort(2);
                String device = "";
                for (int x=4; x < 14; x++) {
                    byte b = data.get(x);
                    device += (char) b;
                }
                System.out.println(len + " " + cmd + " -- " + device);
            }
            if (receivePacket.getLength() == 34) {
                short len = data.getShort(0);
                short cmd = data.getShort(2);
                byte benabled = data.get(4);
                int enabled = (int) benabled;
                byte balarm = data.get(5);
                // Alarm (OK)
                int alarm =  Math.abs((int) balarm);
                // Speed (OK)
                byte bspeed = data.get(6);
                int speed = (int) bspeed;
                // Direction (OK)
                short direction = data.getShort(7);
                // Coordinates
                double longitude = data.getDouble(9);
                double latitude = data.getDouble(13);
                // Device ID (OK)
                String device = "";
                for (int x=21; x < 31; x++) {
                    byte bdevice = data.get(x);
                    device += (char) bdevice;
                }

                // Datetime (testing)
                int ddatetime = data.get(17);
                Date datetime = new Date(ddatetime * 1000);
                //System.out.println("-->" + datetime + ", " + longitude);
                System.out.println(len + " " + cmd + " " + enabled + " " + alarm + " " + speed + " " + direction + " " + longitude + " " + latitude + " " + datetime + " " + device);
            }
        }
    }

You are reading the latitude and longitude as 8 bytes each, the spec you have says 4. double s in java, and getDouble in ByteBuffer , are 8 bytes, you want getFloat .

This also corrupts the data after as you read too far.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM