Search code examples
javamathdecodearithmetic-expressionspreon

Simple arithmetic using Preon framework


I'm using Preon Binding for reading a stream of incoming binary data.

The problem we are having is that certain field values require some simple arithmetic for their proper representation, as our "data documentation" says:

  • field lat: Latitude component from the device coordinate. In binary format the latitude must be divided by 1.000.000
  • field direction: Bearing of the device in degrees divided by 3

Can Preon support such arithmetic upon binding, or do I have to specifically do it after decoding (which renders the decoded DTO values non-consistent)?

Other fields (latPositive and lngPositive) provide the math sign (either negative or positive) for their corresponding values (lat and lng fields), I think this could also be supported just by multiplying by -1 in the negative cases, but that would only be possible if some kind of arithmetic is actually supported by Preon.

Mapping basically as follows:

// ok
@BoundString(size = "1")
private String start;

// ??
@BoundNumber(size = "8")
private short size;

// ok
@BoundNumber(size = "8")
private short header;

// ok
@BoundNumber(size = "56", byteOrder = ByteOrder.BigEndian)
private long imei;

// ok
@BoundNumber(size = "8")
private short mask;

// ok
@BoundNumber(size = "5", byteOrder = ByteOrder.BigEndian)
private short day;

// ok
@BoundNumber(size = "4", byteOrder = ByteOrder.BigEndian)
private short month;

// ok
@BoundNumber(size = "5", byteOrder = ByteOrder.BigEndian)
private short year;

// ok
@BoundNumber(size = "5", byteOrder = ByteOrder.BigEndian)
private short hour;

// ok
@BoundNumber(size = "6", byteOrder = ByteOrder.BigEndian)
private short minute;

// ok
@BoundNumber(size = "6", byteOrder = ByteOrder.BigEndian)
private short second;

@Bound
private boolean latPositive;

@BoundNumber(size = "27", byteOrder = ByteOrder.BigEndian)
private int lat;

@Bound
private boolean lngPositive;

@BoundNumber(size = "28", byteOrder = ByteOrder.BigEndian)
private int lng;

// ok
@BoundNumber(size = "8", byteOrder = ByteOrder.BigEndian)
private int speed;

@BoundNumber(size = "7", byteOrder = ByteOrder.BigEndian)
private int direction;

// ok
@Bound
private boolean gpsFix;

// ok
@BoundNumber(size = "13", byteOrder = ByteOrder.BigEndian)
private int altitude;

// ok
@BoundNumber(size = "20", byteOrder = ByteOrder.BigEndian)
private int odometer;

// ok
@BoundNumber(size = "8", byteOrder = ByteOrder.BigEndian)
private int batteryLevel;

PS: Is there a Preon users mailing list available?


Solution

  • This might be too late, but I've been digging into preon lately, so there seem to be two possibilities I've seen in preon:

    a) Use the @Init annotation to specify the transformations to be done in code, e.g.

    public static class Blah {
        @BoundNumber(size="32", byteOrder = ByteOrder.BigEndian)
        private int size;
    
        @Init
        public void go() {
            size = size * 3;
        }
    }
    

    b) Create a CodecDecorator (I would copy something like InitCodecDecorator to start) that understands how to perform arithmetic, add the right annotations and add it to the decoder like so: http://technofovea.com/blog/archives/850

    Or simply add getters and setters that understand the binary contract;