From 8ee694af98493830380e5faf96d43752002ca634 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 28 Jun 2015 10:28:58 +1200 Subject: Implement bit utility class --- src/org/traccar/helper/BitUtil.java | 35 +++++++++++++ src/org/traccar/protocol/BceProtocolDecoder.java | 25 ++++------ src/org/traccar/protocol/Mta6ProtocolDecoder.java | 48 ++++++++---------- .../traccar/protocol/SkypatrolProtocolDecoder.java | 58 ++++++++++------------ .../traccar/protocol/TeltonikaProtocolDecoder.java | 32 +++++------- test/org/traccar/helper/BitUtilTest.java | 23 +++++++++ 6 files changed, 129 insertions(+), 92 deletions(-) create mode 100644 src/org/traccar/helper/BitUtil.java create mode 100644 test/org/traccar/helper/BitUtilTest.java diff --git a/src/org/traccar/helper/BitUtil.java b/src/org/traccar/helper/BitUtil.java new file mode 100644 index 000000000..6e03e6d2a --- /dev/null +++ b/src/org/traccar/helper/BitUtil.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.helper; + +/** + * Useful functions to work with bits + */ +public class BitUtil { + + public static boolean check(long number, int index) { + return (number & (1 << index)) != 0; + } + + public static int range(int number, int index, int length) { + return (number >> index) & ((1 << length) - 1); + } + + public static long range(long number, int index, int length) { + return (number >> index) & ((1l << length) - 1); + } + +} diff --git a/src/org/traccar/protocol/BceProtocolDecoder.java b/src/org/traccar/protocol/BceProtocolDecoder.java index fa951e21d..189cad754 100644 --- a/src/org/traccar/protocol/BceProtocolDecoder.java +++ b/src/org/traccar/protocol/BceProtocolDecoder.java @@ -24,6 +24,7 @@ import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; import org.traccar.BaseProtocolDecoder; +import org.traccar.helper.BitUtil; import org.traccar.model.Event; import org.traccar.model.Position; @@ -41,10 +42,6 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { private static final int MSG_OUTPUT_CONTROL = 0x41; private static final int MSG_OUTPUT_CONTROL_ACK = 0xC1; - private static boolean checkBit(int mask, int bit) { - return (mask & (1 << bit)) != 0; - } - @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, Object msg) @@ -86,11 +83,11 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { do { mask = buf.readUnsignedShort(); masks.add(mask); - } while (checkBit(mask, 15)); + } while (BitUtil.check(mask, 15)); mask = masks.get(0); - if (checkBit(mask, 0)) { + if (BitUtil.check(mask, 0)) { position.setValid(true); position.setLongitude(buf.readFloat()); position.setLatitude(buf.readFloat()); @@ -106,22 +103,22 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { position.set(Event.KEY_ODOMETER, buf.readUnsignedInt()); } - if (checkBit(mask, 1)) { + if (BitUtil.check(mask, 1)) { position.set(Event.KEY_INPUT, buf.readUnsignedShort()); } for (int i = 1; i <= 8; i++) { - if (checkBit(mask, i + 1)) { + if (BitUtil.check(mask, i + 1)) { position.set(Event.PREFIX_ADC + i, buf.readUnsignedShort()); } } - if (checkBit(mask, 10)) buf.skipBytes(4); - if (checkBit(mask, 11)) buf.skipBytes(4); - if (checkBit(mask, 12)) buf.skipBytes(2); - if (checkBit(mask, 13)) buf.skipBytes(2); + if (BitUtil.check(mask, 10)) buf.skipBytes(4); + if (BitUtil.check(mask, 11)) buf.skipBytes(4); + if (BitUtil.check(mask, 12)) buf.skipBytes(2); + if (BitUtil.check(mask, 13)) buf.skipBytes(2); - if (checkBit(mask, 14)) { + if (BitUtil.check(mask, 14)) { position.set(Event.KEY_MCC, buf.readUnsignedShort()); position.set(Event.KEY_MNC, buf.readUnsignedByte()); position.set(Event.KEY_LAC, buf.readUnsignedShort()); @@ -130,7 +127,7 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); } - if (checkBit(mask, 0)) { + if (BitUtil.check(mask, 0)) { positions.add(position); } } diff --git a/src/org/traccar/protocol/Mta6ProtocolDecoder.java b/src/org/traccar/protocol/Mta6ProtocolDecoder.java index 7d4ead62c..459b8bcb8 100644 --- a/src/org/traccar/protocol/Mta6ProtocolDecoder.java +++ b/src/org/traccar/protocol/Mta6ProtocolDecoder.java @@ -21,7 +21,6 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; - import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; @@ -31,8 +30,8 @@ import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpResponseStatus; import org.jboss.netty.handler.codec.http.HttpVersion; - import org.traccar.BaseProtocolDecoder; +import org.traccar.helper.BitUtil; import org.traccar.helper.ChannelBufferTools; import org.traccar.model.Event; import org.traccar.model.Position; @@ -66,11 +65,6 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { channel.write(response); } - private static boolean checkBit(long mask, int bit) { - long checkMask = 1 << bit; - return (mask & checkMask) == checkMask; - } - private static class FloatReader { private int previousFloat; @@ -135,11 +129,11 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { // Skip events short event = buf.readUnsignedByte(); - if (checkBit(event, 7)) { - if (checkBit(event, 6)) { + if (BitUtil.check(event, 7)) { + if (BitUtil.check(event, 6)) { buf.skipBytes(8); } else { - while (checkBit(event, 7)) { + while (BitUtil.check(event, 7)) { event = buf.readUnsignedByte(); } } @@ -149,44 +143,44 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { position.setLongitude(longitudeReader.readFloat(buf) / Math.PI * 180); position.setTime(timeReader.readTime(buf)); - if (checkBit(flags, 0)) { + if (BitUtil.check(flags, 0)) { buf.readUnsignedByte(); // status } - if (checkBit(flags, 1)) { + if (BitUtil.check(flags, 1)) { position.setAltitude(buf.readUnsignedShort()); } - if (checkBit(flags, 2)) { + if (BitUtil.check(flags, 2)) { position.setSpeed(buf.readUnsignedShort() & 0x03ff); position.setCourse(buf.readUnsignedByte()); } - if (checkBit(flags, 3)) { + if (BitUtil.check(flags, 3)) { position.set(Event.KEY_ODOMETER, buf.readUnsignedShort()); } - if (checkBit(flags, 4)) { + if (BitUtil.check(flags, 4)) { position.set(Event.KEY_FUEL, buf.readUnsignedInt() + "|" + buf.readUnsignedInt()); position.set("hours1", buf.readUnsignedShort()); position.set("hours2", buf.readUnsignedShort()); } - if (checkBit(flags, 5)) { + if (BitUtil.check(flags, 5)) { position.set(Event.PREFIX_ADC + 1, buf.readUnsignedShort() & 0x03ff); position.set(Event.PREFIX_ADC + 2, buf.readUnsignedShort() & 0x03ff); position.set(Event.PREFIX_ADC + 3, buf.readUnsignedShort() & 0x03ff); position.set(Event.PREFIX_ADC + 4, buf.readUnsignedShort() & 0x03ff); } - if (checkBit(flags, 6)) { + if (BitUtil.check(flags, 6)) { position.set(Event.PREFIX_TEMP + 1, buf.readByte()); buf.getUnsignedByte(buf.readerIndex()); // control (>> 4) position.set(Event.KEY_INPUT, buf.readUnsignedShort() & 0x0fff); buf.readUnsignedShort(); // old sensor state (& 0x0fff) } - if (checkBit(flags, 7)) { + if (BitUtil.check(flags, 7)) { position.set(Event.KEY_BATTERY, buf.getUnsignedByte(buf.readerIndex()) >> 2); position.set(Event.KEY_POWER, buf.readUnsignedShort() & 0x03ff); buf.readByte(); // microcontroller temperature @@ -214,11 +208,11 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { // Skip events short event = buf.readUnsignedByte(); - if (checkBit(event, 7)) { - if (checkBit(event, 6)) { + if (BitUtil.check(event, 7)) { + if (BitUtil.check(event, 6)) { buf.skipBytes(8); } else { - while (checkBit(event, 7)) { + while (BitUtil.check(event, 7)) { event = buf.readUnsignedByte(); } } @@ -230,41 +224,41 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // status - if (checkBit(flags, 0)) { + if (BitUtil.check(flags, 0)) { position.setAltitude(buf.readUnsignedShort()); position.setSpeed(buf.readUnsignedByte()); position.setCourse(buf.readByte()); position.set(Event.KEY_ODOMETER, new FloatReader().readFloat(buf)); } - if (checkBit(flags, 1)) { + if (BitUtil.check(flags, 1)) { new FloatReader().readFloat(buf); // fuel consumtion position.set("hours", new FloatReader().readFloat(buf)); position.set("tank", buf.readUnsignedByte() * 0.4); } - if (checkBit(flags, 2)) { + if (BitUtil.check(flags, 2)) { position.set("engine", buf.readUnsignedShort() * 0.125); position.set("pedals", buf.readUnsignedByte()); position.set(Event.PREFIX_TEMP + 1, buf.readUnsignedByte() - 40); buf.readUnsignedShort(); // service odometer } - if (checkBit(flags, 3)) { + if (BitUtil.check(flags, 3)) { position.set(Event.KEY_FUEL, buf.readUnsignedShort()); position.set(Event.PREFIX_ADC + 2, buf.readUnsignedShort()); position.set(Event.PREFIX_ADC + 3, buf.readUnsignedShort()); position.set(Event.PREFIX_ADC + 4, buf.readUnsignedShort()); } - if (checkBit(flags, 4)) { + if (BitUtil.check(flags, 4)) { position.set(Event.PREFIX_TEMP + 1, buf.readByte()); buf.getUnsignedByte(buf.readerIndex()); // control (>> 4) position.set(Event.KEY_INPUT, buf.readUnsignedShort() & 0x0fff); buf.readUnsignedShort(); // old sensor state (& 0x0fff) } - if (checkBit(flags, 5)) { + if (BitUtil.check(flags, 5)) { position.set(Event.KEY_BATTERY, buf.getUnsignedByte(buf.readerIndex()) >> 2); position.set(Event.KEY_POWER, buf.readUnsignedShort() & 0x03ff); buf.readByte(); // microcontroller temperature diff --git a/src/org/traccar/protocol/SkypatrolProtocolDecoder.java b/src/org/traccar/protocol/SkypatrolProtocolDecoder.java index acb4fa5ec..5521502f6 100644 --- a/src/org/traccar/protocol/SkypatrolProtocolDecoder.java +++ b/src/org/traccar/protocol/SkypatrolProtocolDecoder.java @@ -18,12 +18,11 @@ package org.traccar.protocol; import java.nio.charset.Charset; import java.util.Calendar; import java.util.TimeZone; - import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; - import org.traccar.BaseProtocolDecoder; +import org.traccar.helper.BitUtil; import org.traccar.helper.Log; import org.traccar.model.Event; import org.traccar.model.Position; @@ -34,11 +33,6 @@ public class SkypatrolProtocolDecoder extends BaseProtocolDecoder { super(protocol); } - private static boolean checkBit(long mask, int bit) { - long checkMask = 1 << bit; - return (mask & checkMask) == checkMask; - } - private static double convertCoordinate(long coordinate) { int sign = 1; if (coordinate > 0x7fffffffl) { @@ -73,23 +67,23 @@ public class SkypatrolProtocolDecoder extends BaseProtocolDecoder { if (apiNumber == 5 && commandType == 2 && messageType == 1 && - checkBit(mask, 0)) { + BitUtil.check(mask, 0)) { // Create new position Position position = new Position(); position.setProtocol(getProtocol()); // Status code - if (checkBit(mask, 1)) { + if (BitUtil.check(mask, 1)) { position.set(Event.KEY_STATUS, buf.readUnsignedInt()); } // Device id String id = null; - if (checkBit(mask, 23)) { + if (BitUtil.check(mask, 23)) { id = buf.toString(buf.readerIndex(), 8, Charset.defaultCharset()).trim(); buf.skipBytes(8); - } else if (checkBit(mask, 2)) { + } else if (BitUtil.check(mask, 2)) { id = buf.toString(buf.readerIndex(), 22, Charset.defaultCharset()).trim(); buf.skipBytes(22); } else { @@ -102,22 +96,22 @@ public class SkypatrolProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(getDeviceId()); // IO data - if (checkBit(mask, 3)) { + if (BitUtil.check(mask, 3)) { buf.readUnsignedShort(); } // ADC 1 - if (checkBit(mask, 4)) { + if (BitUtil.check(mask, 4)) { buf.readUnsignedShort(); } // ADC 2 - if (checkBit(mask, 5)) { + if (BitUtil.check(mask, 5)) { buf.readUnsignedShort(); } // Function category - if (checkBit(mask, 7)) { + if (BitUtil.check(mask, 7)) { buf.readUnsignedByte(); } @@ -125,39 +119,39 @@ public class SkypatrolProtocolDecoder extends BaseProtocolDecoder { time.clear(); // Date - if (checkBit(mask, 8)) { + if (BitUtil.check(mask, 8)) { time.set(Calendar.DAY_OF_MONTH, buf.readUnsignedByte()); time.set(Calendar.MONTH, buf.readUnsignedByte() - 1); time.set(Calendar.YEAR, 2000 + buf.readUnsignedByte()); } // GPS status - if (checkBit(mask, 9)) { + if (BitUtil.check(mask, 9)) { position.setValid(buf.readUnsignedByte() == 1); } // Latitude - if (checkBit(mask, 10)) { + if (BitUtil.check(mask, 10)) { position.setLatitude(convertCoordinate(buf.readUnsignedInt())); } // Longitude - if (checkBit(mask, 11)) { + if (BitUtil.check(mask, 11)) { position.setLongitude(convertCoordinate(buf.readUnsignedInt())); } // Speed - if (checkBit(mask, 12)) { + if (BitUtil.check(mask, 12)) { position.setSpeed(buf.readUnsignedShort() / 10.0); } // Course - if (checkBit(mask, 13)) { + if (BitUtil.check(mask, 13)) { position.setCourse(buf.readUnsignedShort() / 10.0); } // Time - if (checkBit(mask, 14)) { + if (BitUtil.check(mask, 14)) { time.set(Calendar.HOUR_OF_DAY, buf.readUnsignedByte()); time.set(Calendar.MINUTE, buf.readUnsignedByte()); time.set(Calendar.SECOND, buf.readUnsignedByte()); @@ -166,52 +160,52 @@ public class SkypatrolProtocolDecoder extends BaseProtocolDecoder { position.setTime(time.getTime()); // Altitude - if (checkBit(mask, 15)) { + if (BitUtil.check(mask, 15)) { position.setAltitude(buf.readMedium()); } // Satellites - if (checkBit(mask, 16)) { + if (BitUtil.check(mask, 16)) { position.set(Event.KEY_SATELLITES, buf.readUnsignedByte()); } // Battery percentage - if (checkBit(mask, 17)) { + if (BitUtil.check(mask, 17)) { buf.readUnsignedShort(); } // Trip odometer - if (checkBit(mask, 20)) { + if (BitUtil.check(mask, 20)) { position.set("trip", buf.readUnsignedInt()); } // Odometer - if (checkBit(mask, 21)) { + if (BitUtil.check(mask, 21)) { position.set(Event.KEY_ODOMETER, buf.readUnsignedInt()); } // Time of message generation - if (checkBit(mask, 22)) { + if (BitUtil.check(mask, 22)) { buf.skipBytes(6); } // Battery level - if (checkBit(mask, 24)) { + if (BitUtil.check(mask, 24)) { position.set(Event.KEY_POWER, buf.readUnsignedShort() / 1000.0); } // GPS overspeed - if (checkBit(mask, 25)) { + if (BitUtil.check(mask, 25)) { buf.skipBytes(18); } // Cell information - if (checkBit(mask, 26)) { + if (BitUtil.check(mask, 26)) { buf.skipBytes(54); } // Sequence number - if (checkBit(mask, 28)) { + if (BitUtil.check(mask, 28)) { position.set(Event.KEY_INDEX, buf.readUnsignedShort()); } diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java index d3e946f69..792a64b79 100644 --- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java +++ b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java @@ -19,13 +19,12 @@ import java.nio.charset.Charset; import java.util.Date; import java.util.LinkedList; import java.util.List; - import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; - import org.traccar.BaseProtocolDecoder; +import org.traccar.helper.BitUtil; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; import org.traccar.model.Position; @@ -49,11 +48,6 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { } } - private static boolean checkBit(long mask, int bit) { - long checkMask = 1 << bit; - return (mask & checkMask) == checkMask; - } - private static final int CODEC_GH3000 = 0x07; private static final int CODEC_FM4X00 = 0x08; private static final int CODEC_12 = 0x0C; @@ -87,45 +81,45 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { position.setTime(new Date(time * 1000)); globalMask = buf.readUnsignedByte(); - if (!checkBit(globalMask, 0)) { + if (!BitUtil.check(globalMask, 0)) { return null; } int locationMask = buf.readUnsignedByte(); - if (checkBit(locationMask, 0)) { + if (BitUtil.check(locationMask, 0)) { position.setLatitude(buf.readFloat()); position.setLongitude(buf.readFloat()); } - if (checkBit(locationMask, 1)) { + if (BitUtil.check(locationMask, 1)) { position.setAltitude(buf.readUnsignedShort()); } - if (checkBit(locationMask, 2)) { + if (BitUtil.check(locationMask, 2)) { position.setCourse(buf.readUnsignedByte() * 360.0 / 256); } - if (checkBit(locationMask, 3)) { + if (BitUtil.check(locationMask, 3)) { position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); } - if (checkBit(locationMask, 4)) { + if (BitUtil.check(locationMask, 4)) { int satellites = buf.readUnsignedByte(); position.set(Event.KEY_SATELLITES, satellites); position.setValid(satellites >= 3); } - if (checkBit(locationMask, 5)) { + if (BitUtil.check(locationMask, 5)) { position.set("area", buf.readUnsignedShort()); position.set(Event.KEY_CELL, buf.readUnsignedShort()); } - if (checkBit(locationMask, 6)) { + if (BitUtil.check(locationMask, 6)) { position.set(Event.KEY_GSM, buf.readUnsignedByte()); } - if (checkBit(locationMask, 7)) { + if (BitUtil.check(locationMask, 7)) { position.set("operator", buf.readUnsignedInt()); } @@ -154,7 +148,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { } // Read 1 byte data - if (checkBit(globalMask, 1)) { + if (BitUtil.check(globalMask, 1)) { int cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { int id = buf.readUnsignedByte(); @@ -168,7 +162,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { // Read 2 byte data - if (checkBit(globalMask, 2)) { + if (BitUtil.check(globalMask, 2)) { int cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { position.set(Event.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedShort()); @@ -176,7 +170,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { } // Read 4 byte data - if (checkBit(globalMask, 3)) { + if (BitUtil.check(globalMask, 3)) { int cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { position.set(Event.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedInt()); diff --git a/test/org/traccar/helper/BitUtilTest.java b/test/org/traccar/helper/BitUtilTest.java new file mode 100644 index 000000000..dbe3852b7 --- /dev/null +++ b/test/org/traccar/helper/BitUtilTest.java @@ -0,0 +1,23 @@ +package org.traccar.helper; + +import org.junit.Assert; +import org.junit.Test; + +public class BitUtilTest { + + @Test + public void testCheck() { + Assert.assertFalse(BitUtil.check(0, 0)); + Assert.assertTrue(BitUtil.check(1, 0)); + Assert.assertFalse(BitUtil.check(2, 0)); + } + + @Test + public void testRange() { + Assert.assertEquals(0, BitUtil.range(0, 0, 0)); + Assert.assertEquals(1, BitUtil.range(1, 0, 1)); + Assert.assertEquals(2, BitUtil.range(2, 0, 2)); + Assert.assertEquals(2, BitUtil.range(6, 0, 2)); + } + +} -- cgit v1.2.3