diff options
-rw-r--r-- | src/org/traccar/protocol/CityeasyProtocolDecoder.java | 112 | ||||
-rw-r--r-- | test/org/traccar/protocol/CityeasyProtocolDecoderTest.java | 10 |
2 files changed, 74 insertions, 48 deletions
diff --git a/src/org/traccar/protocol/CityeasyProtocolDecoder.java b/src/org/traccar/protocol/CityeasyProtocolDecoder.java index c346a7006..ba6a3e62d 100644 --- a/src/org/traccar/protocol/CityeasyProtocolDecoder.java +++ b/src/org/traccar/protocol/CityeasyProtocolDecoder.java @@ -16,15 +16,19 @@ package org.traccar.protocol; import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; +import org.traccar.helper.ChannelBufferTools; +import org.traccar.helper.Crc; import org.traccar.model.Event; import org.traccar.model.Position; import java.net.SocketAddress; +import java.nio.charset.Charset; import java.util.Calendar; import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class CityeasyProtocolDecoder extends BaseProtocolDecoder { @@ -32,6 +36,22 @@ public class CityeasyProtocolDecoder extends BaseProtocolDecoder { super(protocol); } + private static final Pattern pattern = Pattern.compile( + "(\\d{4})(\\d{2})(\\d{2})" + // Date + "(\\d{2})(\\d{2})(\\d{2})," + // Time + "([AV])," + // Validity + "(\\d+)," + // Satellites + "([NS]),(\\d+\\.\\d+)," + // Latitude + "([EW]),(\\d+\\.\\d+)," + // Longitude + "(\\d+\\.\\d)," + // Speed + "(\\d+\\.\\d)," + // HDOP + "(\\d+\\.\\d);" + // Altitude + "(\\d+)," + // MCC + "(\\d+)," + // MNC + "(\\d+)," + // LAC + "(\\d+)" + // Cell + ".*"); + private static final int MSG_LOCATION_REPORT = 0x0003; private static final int MSG_LOCATION_INQUIRY_RESPONSE = 0x0004; @@ -42,72 +62,72 @@ public class CityeasyProtocolDecoder extends BaseProtocolDecoder { ChannelBuffer buf = (ChannelBuffer) msg; - /*buf.skipBytes(2); // header - buf.readByte(); // size - - // Zero for location messages - buf.readByte(); // voltage - buf.readByte(); // gsm signal - - String imei = readImei(buf); - long index = buf.readUnsignedShort(); - int type = buf.readUnsignedByte(); + buf.skipBytes(2); // header + buf.readUnsignedShort(); // length - if (type == MSG_HEARTBEAT) { - if (channel != null) { - byte[] response = {0x54, 0x68, 0x1A, 0x0D, 0x0A}; - channel.write(ChannelBuffers.wrappedBuffer(response)); - } + String imei = ChannelBufferTools.readHexString(buf, 14); + imei += Crc.luhnChecksum(Long.valueOf(imei)); + if (!identify(imei, channel)) { + return null; } - else if (type == MSG_DATA) { + int type = buf.readUnsignedShort(); - // Create new position - Position position = new Position(); - position.setProtocol(getProtocolName()); - position.set(Event.KEY_INDEX, index); + if (type == MSG_LOCATION_REPORT || type == MSG_LOCATION_INQUIRY_RESPONSE) { - // Get device id - if (!identify(imei, channel)) { + String sentence = buf.toString(buf.readerIndex(), buf.readableBytes() - 8, Charset.defaultCharset()); + Matcher parser = pattern.matcher(sentence); + if (!parser.matches()) { return null; } + + Position position = new Position(); + position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); + Integer index = 1; + // Date and time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); - time.set(Calendar.YEAR, 2000 + buf.readUnsignedByte()); - time.set(Calendar.MONTH, buf.readUnsignedByte() - 1); - time.set(Calendar.DAY_OF_MONTH, buf.readUnsignedByte()); - time.set(Calendar.HOUR_OF_DAY, buf.readUnsignedByte()); - time.set(Calendar.MINUTE, buf.readUnsignedByte()); - time.set(Calendar.SECOND, buf.readUnsignedByte()); + time.set(Calendar.YEAR, Integer.parseInt(parser.group(index++))); + time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1); + time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++))); + time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parser.group(index++))); + time.set(Calendar.MINUTE, Integer.parseInt(parser.group(index++))); + time.set(Calendar.SECOND, Integer.parseInt(parser.group(index++))); position.setTime(time.getTime()); + position.setValid(parser.group(index++).equals("A")); + position.set(Event.KEY_SATELLITES, parser.group(index++)); + // Latitude - double latitude = buf.readUnsignedInt() / (60.0 * 30000.0); + String hemisphere = parser.group(index++); + double latitude = Double.parseDouble(parser.group(index++)); + if (hemisphere.compareTo("S") == 0) { + latitude = -latitude; + } + position.setLatitude(latitude); // Longitude - double longitude = buf.readUnsignedInt() / (60.0 * 30000.0); - - // Speed - position.setSpeed(buf.readUnsignedByte()); - - // Course - position.setCourse(buf.readUnsignedShort()); + hemisphere = parser.group(index++); + double longitude = Double.parseDouble(parser.group(index++)); + if (hemisphere.compareTo("W") == 0) { + longitude = -longitude; + } + position.setLongitude(longitude); - buf.skipBytes(3); // reserved + position.setSpeed(Double.parseDouble(parser.group(index++))); + position.set(Event.KEY_HDOP, Double.parseDouble(parser.group(index++))); + position.setAltitude(Double.parseDouble(parser.group(index++))); - // Flags - long flags = buf.readUnsignedInt(); - position.setValid((flags & 0x1) == 0x1); - if ((flags & 0x2) == 0) latitude = -latitude; - if ((flags & 0x4) == 0) longitude = -longitude; + position.set(Event.KEY_MCC, Integer.parseInt(parser.group(index++))); + position.set(Event.KEY_MNC, Integer.parseInt(parser.group(index++))); + position.set(Event.KEY_LAC, Integer.parseInt(parser.group(index++))); + position.set(Event.KEY_CELL, Integer.parseInt(parser.group(index++))); - position.setLatitude(latitude); - position.setLongitude(longitude); return position; - }*/ + } return null; } diff --git a/test/org/traccar/protocol/CityeasyProtocolDecoderTest.java b/test/org/traccar/protocol/CityeasyProtocolDecoderTest.java index 1efd68dff..cdb34b817 100644 --- a/test/org/traccar/protocol/CityeasyProtocolDecoderTest.java +++ b/test/org/traccar/protocol/CityeasyProtocolDecoderTest.java @@ -14,8 +14,14 @@ public class CityeasyProtocolDecoderTest extends ProtocolDecoderTest { CityeasyProtocolDecoder decoder = new CityeasyProtocolDecoder(new CityeasyProtocol()); - //verify(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(ChannelBufferTools.convertHexString( - // "5454006135200000000001000332303134313131303039353430392C412C342C4E2C32322E3533373232382C452C3131342E3032323737342C302E312C312E392C35302E363B3436302C302C31303137332C343635322C34310000000B63130D0A")))); + assertNull(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(ChannelBufferTools.convertHexString( + "545400153520000000000100010000000111000D0A")))); + + verify(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(ChannelBufferTools.convertHexString( + "5454006135200000000001000332303134313131303039353430392C412C342C4E2C32322E3533373232382C452C3131342E3032323737342C302E312C312E392C35302E363B3436302C302C31303137332C343635322C34310000000B63130D0A")))); + + verify(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(ChannelBufferTools.convertHexString( + "5454006135200000000001000432303134313131303039353330362C412C352C4E2C32322E3533373233352C452C3131342E3032323838312C302E322C312E362C35342E313B3436302C302C31303137332C343635322C343100000045EC620D0A")))); } |