Add Galileo protocol

This commit is contained in:
Anton Tananaev 2013-03-19 22:15:35 +13:00
parent d4f33f724b
commit 572dfddfb6
6 changed files with 255 additions and 9 deletions

View File

@ -197,4 +197,8 @@
<entry key='cellocator.enable'>true</entry>
<entry key='cellocator.port'>5033</entry>
<!-- Galileo server configuration -->
<entry key='galileo.enable'>true</entry>
<entry key='galileo.port'>5034</entry>
</properties>

View File

@ -139,6 +139,7 @@ public class ServerManager {
initSyrusServer("syrus");
initVt300Server("vt300");
initCellocatorServer("cellocator");
initGalileoServer("galileo");
// Initialize web server
if (Boolean.valueOf(properties.getProperty("http.enable"))) {
@ -732,4 +733,18 @@ public class ServerManager {
}
}
private void initGalileoServer(String protocol) throws SQLException {
if (isProtocolEnabled(properties, protocol)) {
TrackerServer server = new TrackerServer(this, new ServerBootstrap(), protocol) {
@Override
protected void addSpecificHandlers(ChannelPipeline pipeline) {
pipeline.addLast("frameDecoder", new GalileoFrameDecoder());
pipeline.addLast("objectDecoder", new GalileoProtocolDecoder(ServerManager.this));
}
};
server.setEndianness(ByteOrder.LITTLE_ENDIAN);
serverList.add(server);
}
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 2013 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.protocol;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
public class GalileoFrameDecoder extends FrameDecoder {
private static final int MESSAGE_MINIMUM_LENGTH = 5;
@Override
protected Object decode(
ChannelHandlerContext ctx,
Channel channel,
ChannelBuffer buf) throws Exception {
// Check minimum length
if (buf.readableBytes() < MESSAGE_MINIMUM_LENGTH) {
return null;
}
// Read packet
int length = buf.getUnsignedShort(buf.readerIndex() + 1) & 0x7fff;
if (buf.readableBytes() >= (length + MESSAGE_MINIMUM_LENGTH)) {
return buf.readBytes(length + MESSAGE_MINIMUM_LENGTH);
}
return null;
}
}

View File

@ -0,0 +1,169 @@
/*
* Copyright 2013 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.protocol;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
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.ServerManager;
import org.traccar.helper.Log;
import org.traccar.model.Position;
public class GalileoProtocolDecoder extends BaseProtocolDecoder {
public GalileoProtocolDecoder(ServerManager serverManager) {
super(serverManager);
}
private static final Map<Integer, Integer> tagLengthMap = new HashMap<Integer, Integer>();
static {
int[] l1 = {0x01,0x02,0x35,0x43,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd5};
int[] l2 = {0x04,0x10,0x34,0x40,0x41,0x42,0x45,0x46,0x50,0x51,0x52,0x53,0x58,0x59,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0xd6,0xd7,0xd8,0xd9,0xda};
int[] l4 = {0x20,0x33,0x44,0x90,0xc0,0xc1,0xc2,0xc3,0xd3,0xd4,0xdb,0xdc,0xdd,0xde,0xdf};
for (int i : l1) { tagLengthMap.put(i, 1); }
for (int i : l2) { tagLengthMap.put(i, 2); }
for (int i : l4) { tagLengthMap.put(i, 4); }
}
private static int getTagLength(int tag) {
return tagLengthMap.get(tag);
}
private String readImei(ChannelBuffer buf) {
int b = buf.readUnsignedByte();
StringBuilder imei = new StringBuilder();
imei.append(b & 0x0F);
for (int i = 0; i < 7; i++) {
b = buf.readUnsignedByte();
imei.append((b & 0xF0) >> 4);
imei.append(b & 0x0F);
}
return imei.toString();
}
private static final int TAG_IMEI = 0x03;
private static final int TAG_DATE = 0x20;
private static final int TAG_COORDINATES = 0x30;
private static final int TAG_SPEED_COURSE = 0x33;
private static final int TAG_ALTITUDE = 0x34;
private static final int TAG_STATUS = 0x40;
private static final int TAG_POWER = 0x41;
private static final int TAG_BATTERY = 0x42;
private static final int TAG_MILAGE = 0xd4;
private void sendReply(Channel channel, int checksum) {
ChannelBuffer reply = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 3);
reply.writeByte(0x02);
reply.writeShort((short) checksum);
if (channel != null) {
channel.write(reply);
}
}
@Override
protected Object decode(
ChannelHandlerContext ctx, Channel channel, Object msg)
throws Exception {
ChannelBuffer buf = (ChannelBuffer) msg;
buf.readUnsignedByte(); // header
int length = buf.readUnsignedShort() & 0x7fff + 3;
// Create new position
Position position = new Position();
StringBuilder extendedInfo = new StringBuilder("<protocol>galileo</protocol>");
while (buf.readerIndex() < length) {
int tag = buf.readUnsignedByte();
switch (tag) {
case TAG_IMEI:
String imei = buf.toString(buf.readerIndex(), 15, Charset.defaultCharset());
buf.skipBytes(imei.length());
try {
position.setDeviceId(getDataManager().getDeviceByImei(imei).getId());
} catch(Exception error) {
Log.warning("Unknown device - " + imei);
}
break;
case TAG_DATE:
position.setTime(new Date(buf.readUnsignedInt() * 1000));
break;
case TAG_COORDINATES:
position.setValid((buf.readUnsignedByte() & 0xf0) == 0x00);
position.setLatitude(buf.readInt() / 1000000.0);
position.setLongitude(buf.readInt() / 1000000.0);
break;
case TAG_SPEED_COURSE:
position.setSpeed(buf.readUnsignedShort() * 0.0539957);
position.setCourse(buf.readUnsignedShort() * 0.1);
break;
case TAG_ALTITUDE:
position.setAltitude((double) buf.readShort());
break;
case TAG_STATUS:
extendedInfo.append("<status>");
extendedInfo.append(buf.readUnsignedShort());
extendedInfo.append("</status>");
break;
case TAG_POWER:
position.setPower((double) buf.readUnsignedShort());
break;
case TAG_BATTERY:
extendedInfo.append("<battery>");
extendedInfo.append(buf.readUnsignedShort());
extendedInfo.append("</battery>");
break;
case TAG_MILAGE:
extendedInfo.append("<milage>");
extendedInfo.append(buf.readUnsignedInt());
extendedInfo.append("</milage>");
break;
default:
buf.skipBytes(getTagLength(tag));
break;
}
}
sendReply(channel, buf.readUnsignedShort());
position.setExtendedInfo(extendedInfo.toString());
return position;
}
}

View File

@ -26,14 +26,8 @@ import org.traccar.ServerManager;
import org.traccar.helper.Log;
import org.traccar.model.Position;
/**
* T55 tracker protocol decoder
*/
public class Gt02ProtocolDecoder extends BaseProtocolDecoder {
/**
* Initialize
*/
public Gt02ProtocolDecoder(ServerManager serverManager) {
super(serverManager);
}
@ -53,9 +47,6 @@ public class Gt02ProtocolDecoder extends BaseProtocolDecoder {
private static final int MSG_HEARTBEAT = 0x1A;
private static final int MSG_DATA = 0x10;
/**
* Decode message
*/
@Override
protected Object decode(
ChannelHandlerContext ctx, Channel channel, Object msg)

View File

@ -0,0 +1,20 @@
package org.traccar.protocol;
import org.jboss.netty.buffer.ChannelBuffers;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
public class GalileoProtocolDecoderTest {
@Test
public void testDecode() throws Exception {
GalileoProtocolDecoder decoder = new GalileoProtocolDecoder(null);
decoder.setDataManager(new TestDataManager());
/*byte[] buf1 = {0x00};
assertNotNull(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(buf1)));*/
}
}