mirror of
https://github.com/traccar/traccar.git
synced 2026-06-13 11:25:03 -04:00
Implement OBD dongle protocol
This commit is contained in:
@@ -448,5 +448,6 @@
|
||||
<entry key='l100.port'>5112</entry>
|
||||
<entry key='granit.port'>5113</entry>
|
||||
<entry key='carcell.port'>5114</entry>
|
||||
<entry key='obddongle.port'>5115</entry>
|
||||
|
||||
</properties>
|
||||
|
||||
43
src/org/traccar/protocol/ObdDongleProtocol.java
Normal file
43
src/org/traccar/protocol/ObdDongleProtocol.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2016 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.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
|
||||
import org.traccar.BaseProtocol;
|
||||
import org.traccar.TrackerServer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ObdDongleProtocol extends BaseProtocol {
|
||||
|
||||
public ObdDongleProtocol() {
|
||||
super("obddongle");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initTrackerServers(List<TrackerServer> serverList) {
|
||||
serverList.add(new TrackerServer(new ServerBootstrap(), this.getName()) {
|
||||
@Override
|
||||
protected void addSpecificHandlers(ChannelPipeline pipeline) {
|
||||
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1099, 20, 2, 3, 0));
|
||||
pipeline.addLast("objectDecoder", new ObdDongleProtocolDecoder(ObdDongleProtocol.this));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
128
src/org/traccar/protocol/ObdDongleProtocolDecoder.java
Normal file
128
src/org/traccar/protocol/ObdDongleProtocolDecoder.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2016 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.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.traccar.BaseProtocolDecoder;
|
||||
import org.traccar.DeviceSession;
|
||||
import org.traccar.helper.BitUtil;
|
||||
import org.traccar.helper.UnitsConverter;
|
||||
import org.traccar.model.Position;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
||||
public class ObdDongleProtocolDecoder extends BaseProtocolDecoder {
|
||||
|
||||
public ObdDongleProtocolDecoder(ObdDongleProtocol protocol) {
|
||||
super(protocol);
|
||||
}
|
||||
|
||||
public static final int MSG_TYPE_CONNECT = 0x01;
|
||||
public static final int MSG_TYPE_CONNACK = 0x02;
|
||||
public static final int MSG_TYPE_PUBLISH = 0x03;
|
||||
public static final int MSG_TYPE_PUBACK = 0x04;
|
||||
public static final int MSG_TYPE_PINGREQ = 0x0C;
|
||||
public static final int MSG_TYPE_PINGRESP = 0x0D;
|
||||
public static final int MSG_TYPE_DISCONNECT = 0x0E;
|
||||
|
||||
private static void sendResponse(Channel channel, int type, int index, String imei, ChannelBuffer content) {
|
||||
if (channel != null) {
|
||||
ChannelBuffer response = ChannelBuffers.dynamicBuffer();
|
||||
response.writeShort(0x5555); // header
|
||||
response.writeShort(index);
|
||||
response.writeBytes(imei.getBytes(StandardCharsets.US_ASCII));
|
||||
response.writeByte(type);
|
||||
response.writeShort(content.readableBytes());
|
||||
response.writeBytes(content);
|
||||
response.writeByte(0); // checksum
|
||||
response.writeShort(0xAAAA);
|
||||
channel.write(response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(
|
||||
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
|
||||
|
||||
ChannelBuffer buf = (ChannelBuffer) msg;
|
||||
|
||||
buf.skipBytes(2); // header
|
||||
int index = buf.readUnsignedShort();
|
||||
|
||||
String imei = buf.readBytes(15).toString(StandardCharsets.US_ASCII);
|
||||
DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei);
|
||||
if (deviceSession == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int type = buf.readUnsignedByte();
|
||||
|
||||
buf.readUnsignedShort(); // data length
|
||||
|
||||
if (type == MSG_TYPE_CONNECT) {
|
||||
|
||||
ChannelBuffer response = ChannelBuffers.dynamicBuffer();
|
||||
response.writeByte(1);
|
||||
response.writeShort(0);
|
||||
response.writeInt(0);
|
||||
sendResponse(channel, MSG_TYPE_CONNACK, index, imei, response);
|
||||
|
||||
} else if (type == MSG_TYPE_PUBLISH) {
|
||||
|
||||
int typeMajor = buf.readUnsignedByte();
|
||||
int typeMinor = buf.readUnsignedByte();
|
||||
|
||||
buf.readUnsignedByte(); // event id
|
||||
|
||||
Position position = new Position();
|
||||
position.setProtocol(getProtocolName());
|
||||
position.setDeviceId(deviceSession.getDeviceId());
|
||||
|
||||
position.setTime(new Date(buf.readUnsignedInt() * 1000));
|
||||
|
||||
int flags = buf.readUnsignedByte();
|
||||
|
||||
position.setValid(!BitUtil.check(flags, 6));
|
||||
|
||||
position.set(Position.KEY_SATELLITES, BitUtil.to(flags, 4));
|
||||
|
||||
double longitude = ((BitUtil.to(buf.readUnsignedShort(), 1) << 24) + buf.readUnsignedMedium()) * 0.00001;
|
||||
position.setLongitude(BitUtil.check(flags, 5) ? longitude : -longitude);
|
||||
|
||||
double latitude = buf.readUnsignedMedium() * 0.00001;
|
||||
position.setLatitude(BitUtil.check(flags, 4) ? latitude : -latitude);
|
||||
|
||||
int speedCourse = buf.readUnsignedMedium();
|
||||
position.setSpeed(UnitsConverter.knotsFromMph(BitUtil.from(speedCourse, 10) * 0.1));
|
||||
position.setCourse(BitUtil.to(speedCourse, 10));
|
||||
|
||||
ChannelBuffer response = ChannelBuffers.dynamicBuffer();
|
||||
response.writeByte(typeMajor);
|
||||
response.writeByte(typeMinor);
|
||||
sendResponse(channel, MSG_TYPE_PUBACK, index, imei, response);
|
||||
|
||||
return position;
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
22
test/org/traccar/protocol/ObdDongleProtocolDecoderTest.java
Normal file
22
test/org/traccar/protocol/ObdDongleProtocolDecoderTest.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package org.traccar.protocol;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.traccar.ProtocolTest;
|
||||
|
||||
public class ObdDongleProtocolDecoderTest extends ProtocolTest {
|
||||
|
||||
@Test
|
||||
public void testDecode() throws Exception {
|
||||
|
||||
ObdDongleProtocolDecoder decoder = new ObdDongleProtocolDecoder(new ObdDongleProtocol());
|
||||
|
||||
verifyNothing(decoder, binary(
|
||||
"55550003383634383637303232353131303135010009010011023402010201ABAAAA"));
|
||||
|
||||
verifyPosition(decoder, binary(
|
||||
"5555000338363438363730323235313130313503000100010355AABBCC184F1ABC614E21C1FA08712A84ABAAAA"),
|
||||
position("2015-07-18 20:49:16.000", true, 22.12346, -123.45678));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user