From c927be5b135a154ef63d3ba326a3ed48933903bb Mon Sep 17 00:00:00 2001 From: Jesse Hills Date: Wed, 31 Jul 2019 09:45:54 +1200 Subject: Add leafspy app protocol and decoder --- setup/default.xml | 1 + .../java/org/traccar/protocol/LeafSpyProtocol.java | 40 ++++++ .../traccar/protocol/LeafSpyProtocolDecoder.java | 146 +++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 src/main/java/org/traccar/protocol/LeafSpyProtocol.java create mode 100644 src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java diff --git a/setup/default.xml b/setup/default.xml index 3d968397f..bddface92 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -269,5 +269,6 @@ 5190 5191 5192 + 5193 diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocol.java b/src/main/java/org/traccar/protocol/LeafSpyProtocol.java new file mode 100644 index 000000000..05f63a2d7 --- /dev/null +++ b/src/main/java/org/traccar/protocol/LeafSpyProtocol.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 Jesse Hills (jesserockz@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 io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequestDecoder; +import io.netty.handler.codec.http.HttpResponseEncoder; +import org.traccar.BaseProtocol; +import org.traccar.PipelineBuilder; +import org.traccar.TrackerServer; + +public class LeafSpyProtocol extends BaseProtocol { + + public LeafSpyProtocol() { + addServer(new TrackerServer(false, getName()) { + @Override + protected void addProtocolHandlers(PipelineBuilder pipeline) { + pipeline.addLast(new HttpResponseEncoder()); + pipeline.addLast(new HttpRequestDecoder()); + pipeline.addLast(new HttpObjectAggregator(16384)); + pipeline.addLast(new LeafSpyProtocolDecoder(LeafSpyProtocol.this)); + } + }); + } + +} diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java new file mode 100644 index 000000000..434c8a858 --- /dev/null +++ b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java @@ -0,0 +1,146 @@ +/* + * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 Jesse Hills (jesserockz@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 io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.QueryStringDecoder; +import org.traccar.BaseHttpProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.Protocol; +import org.traccar.helper.DateUtil; +import org.traccar.model.CellTower; +import org.traccar.model.Network; +import org.traccar.model.Position; +import org.traccar.model.WifiAccessPoint; +import org.traccar.NetworkMessage; + +import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class LeafSpyProtocolDecoder extends BaseHttpProtocolDecoder { + + public LeafSpyProtocolDecoder(Protocol protocol) { + super(protocol); + } + + @Override + protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + FullHttpRequest request = (FullHttpRequest) msg; + QueryStringDecoder decoder = new QueryStringDecoder(request.uri()); + Map> params = decoder.parameters(); + if (params.isEmpty()) { + decoder = new QueryStringDecoder(request.content().toString(StandardCharsets.US_ASCII), false); + params = decoder.parameters(); + } + + Position position = new Position(getProtocolName()); + position.setValid(true); + + for (Map.Entry> entry : params.entrySet()) { + for (String value : entry.getValue()) { + switch (entry.getKey()) { + case "pass": + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, value); + if (deviceSession == null) { + sendResponse(channel, HttpResponseStatus.BAD_REQUEST); + return null; + } + position.setDeviceId(deviceSession.getDeviceId()); + break; + case "Lat": + position.setLatitude(Double.parseDouble(value)); + break; + case "Long": + position.setLongitude(Double.parseDouble(value)); + break; + case "RPM": + position.set(Position.KEY_RPM, Integer.parseInt(value)); + position.setSpeed(convertSpeed(Double.parseDouble(value) / 63, "kmh")); + break; + case "Elv": + position.setAltitude(Double.parseDouble(value)); + break; + case "DevBat": + position.set(Position.KEY_BATTERY_LEVEL, Double.parseDouble(value)); + break; + case "user": + position.set(Position.KEY_DRIVER_UNIQUE_ID, value); + break; + case "SOC": + position.set(Position.KEY_CHARGE, Double.parseDouble(value)); + break; + case "Odo": + position.set(Position.KEY_OBD_ODOMETER, Integer.parseInt(value)); + break; + default: + try { + position.set(entry.getKey(), Double.parseDouble(value)); + } catch (NumberFormatException e) { + switch (value) { + case "true": + position.set(entry.getKey(), true); + break; + case "false": + position.set(entry.getKey(), false); + break; + default: + position.set(entry.getKey(), value); + break; + } + } + break; + } + } + } + + if (position.getFixTime() == null) { + position.setTime(new Date()); + } + + if (position.getLatitude() == 0 && position.getLongitude() == 0) { + getLastLocation(position, position.getDeviceTime()); + } + + if (position.getDeviceId() != 0) { + HttpResponse response = new DefaultFullHttpResponse( + HttpVersion.HTTP_1_1, + HttpResponseStatus.OK, + Unpooled.copiedBuffer("\"status\":\"0\"", StandardCharsets.US_ASCII)); + channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); + return position; + } else { + sendResponse(channel, HttpResponseStatus.BAD_REQUEST); + return null; + } + } + +} -- cgit v1.2.3 From c4f588bfb161a1e7fe9d927ad28572553ec5c692 Mon Sep 17 00:00:00 2001 From: Jesse Hills Date: Wed, 31 Jul 2019 09:59:14 +1200 Subject: Remove unused imports --- src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java index 434c8a858..17824177c 100644 --- a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java @@ -16,9 +16,6 @@ */ package org.traccar.protocol; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufInputStream; -import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.handler.codec.http.FullHttpRequest; @@ -30,17 +27,11 @@ import io.netty.handler.codec.http.QueryStringDecoder; import org.traccar.BaseHttpProtocolDecoder; import org.traccar.DeviceSession; import org.traccar.Protocol; -import org.traccar.helper.DateUtil; -import org.traccar.model.CellTower; -import org.traccar.model.Network; import org.traccar.model.Position; -import org.traccar.model.WifiAccessPoint; import org.traccar.NetworkMessage; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; -- cgit v1.2.3 From c5bfaf57bb0423c8e5af757c15abd3b3e729dce6 Mon Sep 17 00:00:00 2001 From: Jesse Hills Date: Thu, 1 Aug 2019 09:19:22 +1200 Subject: Add simple unit test --- .../traccar/protocol/LeafSpyProtocolDecoder.java | 20 +++++++++++--------- .../protocol/LeafSpyProtocolDecoderTest.java | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) create mode 100644 src/test/java/org/traccar/protocol/LeafSpyProtocolDecoderTest.java diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java index 17824177c..47c37a68b 100644 --- a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java @@ -80,17 +80,17 @@ public class LeafSpyProtocolDecoder extends BaseHttpProtocolDecoder { case "Elv": position.setAltitude(Double.parseDouble(value)); break; - case "DevBat": + case "SOC": position.set(Position.KEY_BATTERY_LEVEL, Double.parseDouble(value)); break; case "user": position.set(Position.KEY_DRIVER_UNIQUE_ID, value); break; - case "SOC": - position.set(Position.KEY_CHARGE, Double.parseDouble(value)); + case "ChrgMode": + position.set(Position.KEY_CHARGE, Integer.parseInt(value) != 0); break; case "Odo": - position.set(Position.KEY_OBD_ODOMETER, Integer.parseInt(value)); + position.set(Position.KEY_OBD_ODOMETER, Integer.parseInt(value) * 1000); break; default: try { @@ -122,11 +122,13 @@ public class LeafSpyProtocolDecoder extends BaseHttpProtocolDecoder { } if (position.getDeviceId() != 0) { - HttpResponse response = new DefaultFullHttpResponse( - HttpVersion.HTTP_1_1, - HttpResponseStatus.OK, - Unpooled.copiedBuffer("\"status\":\"0\"", StandardCharsets.US_ASCII)); - channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); + if(channel != null) { + HttpResponse response = new DefaultFullHttpResponse( + HttpVersion.HTTP_1_1, + HttpResponseStatus.OK, + Unpooled.copiedBuffer("\"status\":\"0\"", StandardCharsets.US_ASCII)); + channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); + } return position; } else { sendResponse(channel, HttpResponseStatus.BAD_REQUEST); diff --git a/src/test/java/org/traccar/protocol/LeafSpyProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/LeafSpyProtocolDecoderTest.java new file mode 100644 index 000000000..7fe405ea8 --- /dev/null +++ b/src/test/java/org/traccar/protocol/LeafSpyProtocolDecoderTest.java @@ -0,0 +1,21 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class LeafSpyProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + LeafSpyProtocolDecoder decoder = new LeafSpyProtocolDecoder(null); + + verifyNull(decoder, request( + "/?Lat=60.0&Long=30.0")); + + verifyPosition(decoder, request( + "/?user=driver&pass=123456&DevBat=80&Gids=200&Lat=60.0&Long=30.0&Elv=5&Seq=50&Trip=1&Odo=10000&SOC=99.99&AHr=55.00&BatTemp=15.2&Amb=12.0&Wpr=12&PlugState=0&ChrgMode=0&ChrgPwr=0&VIN=ZE0-000000&PwrSw=1&Tunits=C&RPM=1000")); + + } + +} -- cgit v1.2.3 From 23a03b0bac006fdcc85a82f8323e55cba228451e Mon Sep 17 00:00:00 2001 From: Jesse Hills Date: Thu, 1 Aug 2019 23:07:30 +1200 Subject: Fix lint --- src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java index 47c37a68b..5b352a961 100644 --- a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java @@ -122,7 +122,7 @@ public class LeafSpyProtocolDecoder extends BaseHttpProtocolDecoder { } if (position.getDeviceId() != 0) { - if(channel != null) { + if (channel != null) { HttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, -- cgit v1.2.3