diff options
34 files changed, 659 insertions, 101 deletions
diff --git a/src/org/traccar/BaseProtocolDecoder.java b/src/org/traccar/BaseProtocolDecoder.java index 8748a9be6..e5fa76a47 100644 --- a/src/org/traccar/BaseProtocolDecoder.java +++ b/src/org/traccar/BaseProtocolDecoder.java @@ -46,7 +46,16 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { try { Context.getDeviceManager().addDevice(device); + Log.info("Automatically registered device " + uniqueId); + + if (defaultGroupId != 0) { + Context.getPermissionsManager().refreshPermissions(); + if (Context.getGeofenceManager() != null) { + Context.getGeofenceManager().refresh(); + } + } + return device.getId(); } catch (SQLException e) { Log.warning(e); diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java index cd6820778..27e61d32d 100644 --- a/src/org/traccar/Context.java +++ b/src/org/traccar/Context.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.ning.http.client.AsyncHttpClient; import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Properties; import org.apache.velocity.app.VelocityEngine; @@ -208,15 +209,12 @@ public final class Context { String type = config.getString("geocoder.type", "google"); String url = config.getString("geocoder.url"); String key = config.getString("geocoder.key"); + String language = config.getString("geocoder.language"); int cacheSize = config.getInteger("geocoder.cacheSize"); switch (type) { case "nominatim": - if (key != null) { - geocoder = new NominatimGeocoder(url, key, cacheSize); - } else { - geocoder = new NominatimGeocoder(url, cacheSize); - } + geocoder = new NominatimGeocoder(url, key, cacheSize); break; case "gisgraphy": geocoder = new GisgraphyGeocoder(url, cacheSize); @@ -234,17 +232,10 @@ public final class Context { geocoder = new FactualGeocoder(url, key, cacheSize); break; case "geocodefarm": - if (key != null) { - geocoder = new GeocodeFarmGeocoder(key, cacheSize); - } else { - geocoder = new GeocodeFarmGeocoder(cacheSize); - } + geocoder = new GeocodeFarmGeocoder(key, cacheSize); + break; default: - if (key != null) { - geocoder = new GoogleGeocoder(key, cacheSize); - } else { - geocoder = new GoogleGeocoder(cacheSize); - } + geocoder = new GoogleGeocoder(key, language, cacheSize); break; } } @@ -291,9 +282,14 @@ public final class Context { velocityProperties.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogChute"); - String address = config.getString("web.address", InetAddress.getLocalHost().getHostAddress()); - int port = config.getInteger("web.port", 8082); - String webUrl = URIUtil.newURI("http", address, port, "", ""); + String address; + try { + address = config.getString("web.address", InetAddress.getLocalHost().getHostAddress()); + } catch (UnknownHostException e) { + address = "localhost"; + } + + String webUrl = URIUtil.newURI("http", address, config.getInteger("web.port", 8082), "", ""); webUrl = Context.getConfig().getString("web.url", webUrl); velocityProperties.setProperty("web.url", webUrl); diff --git a/src/org/traccar/events/IgnitionEventHandler.java b/src/org/traccar/events/IgnitionEventHandler.java index 187b7ce73..c628cc107 100644 --- a/src/org/traccar/events/IgnitionEventHandler.java +++ b/src/org/traccar/events/IgnitionEventHandler.java @@ -30,10 +30,7 @@ public class IgnitionEventHandler extends BaseEventHandler { @Override protected Collection<Event> analyzePosition(Position position) { Device device = Context.getIdentityManager().getDeviceById(position.getDeviceId()); - if (device == null) { - return null; - } - if (!Context.getIdentityManager().isLatestPosition(position) || !position.getValid()) { + if (device == null || !Context.getIdentityManager().isLatestPosition(position)) { return null; } diff --git a/src/org/traccar/geocoder/GeocodeFarmGeocoder.java b/src/org/traccar/geocoder/GeocodeFarmGeocoder.java index 585095606..db23aab79 100644 --- a/src/org/traccar/geocoder/GeocodeFarmGeocoder.java +++ b/src/org/traccar/geocoder/GeocodeFarmGeocoder.java @@ -19,14 +19,15 @@ import javax.json.JsonObject; public class GeocodeFarmGeocoder extends JsonGeocoder { - private static final String URL = "https://www.geocode.farm/v3/json/reverse/"; - - public GeocodeFarmGeocoder(int cacheSize) { - super(URL + "?lat=%f&lon=%f&country=us&lang=en&count=1", cacheSize); + private static String formatUrl(String key) { + String url = "https://www.geocode.farm/v3/json/reverse/"; + if (key != null) { + url += "&key=" + key; + } + return url; } - public GeocodeFarmGeocoder(String key, int cacheSize) { - super(URL + "?lat=%f&lon=%f&country=us&lang=en&count=1&key=" + key, cacheSize); + super(formatUrl(key), cacheSize); } @Override diff --git a/src/org/traccar/geocoder/GoogleGeocoder.java b/src/org/traccar/geocoder/GoogleGeocoder.java index 0506e701a..b38870c8f 100644 --- a/src/org/traccar/geocoder/GoogleGeocoder.java +++ b/src/org/traccar/geocoder/GoogleGeocoder.java @@ -21,16 +21,19 @@ import javax.json.JsonString; public class GoogleGeocoder extends JsonGeocoder { - public GoogleGeocoder() { - this(0); - } - - public GoogleGeocoder(int cacheSize) { - super("http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f", cacheSize); + private static String formatUrl(String key, String language) { + String url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f"; + if (key != null) { + url += "&key=" + key; + } + if (language != null) { + url += "&language=" + language; + } + return url; } - public GoogleGeocoder(String key, int cacheSize) { - super("https://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&key=" + key, cacheSize); + public GoogleGeocoder(String key, String language, int cacheSize) { + super(formatUrl(key, language), cacheSize); } @Override diff --git a/src/org/traccar/geocoder/NominatimGeocoder.java b/src/org/traccar/geocoder/NominatimGeocoder.java index b0ee39c6a..c10a1414e 100644 --- a/src/org/traccar/geocoder/NominatimGeocoder.java +++ b/src/org/traccar/geocoder/NominatimGeocoder.java @@ -19,16 +19,18 @@ import javax.json.JsonObject; public class NominatimGeocoder extends JsonGeocoder { - public NominatimGeocoder() { - this("http://nominatim.openstreetmap.org/reverse", 0); - } - - public NominatimGeocoder(String url, int cacheSize) { - super(url + "?format=json&lat=%f&lon=%f&zoom=18&addressdetails=1", cacheSize); + private static String formatUrl(String url, String key) { + if (url == null) { + url = "http://nominatim.openstreetmap.org/reverse"; + } + if (key != null) { + url += "&key=" + key; + } + return url; } public NominatimGeocoder(String url, String key, int cacheSize) { - super(url + "?format=json&lat=%f&lon=%f&zoom=18&addressdetails=1&key=" + key, cacheSize); + super(formatUrl(url, key), cacheSize); } @Override diff --git a/src/org/traccar/model/Position.java b/src/org/traccar/model/Position.java index 288901430..350524f32 100644 --- a/src/org/traccar/model/Position.java +++ b/src/org/traccar/model/Position.java @@ -76,6 +76,7 @@ public class Position extends Message { public static final String ALARM_LOW_SPEED = "lowspeed"; public static final String ALARM_OVERSPEED = "overspeed"; public static final String ALARM_FALL_DOWN = "fallDown"; + public static final String ALARM_LOW_POWER = "lowPower"; public static final String ALARM_LOW_BATTERY = "lowBattery"; public static final String ALARM_FAULT = "fault"; public static final String ALARM_POWER_OFF = "powerOff"; @@ -98,6 +99,7 @@ public class Position extends Message { public static final String ALARM_BONNET = "bonnet"; public static final String ALARM_FOOT_BRAKE = "footBrake"; public static final String ALARM_OIL_LEAK = "oilLeak"; + public static final String ALARM_TAMPERING = "tampering"; private String protocol; diff --git a/src/org/traccar/protocol/At2000ProtocolDecoder.java b/src/org/traccar/protocol/At2000ProtocolDecoder.java index dc799054d..182066629 100644 --- a/src/org/traccar/protocol/At2000ProtocolDecoder.java +++ b/src/org/traccar/protocol/At2000ProtocolDecoder.java @@ -102,6 +102,10 @@ public class At2000ProtocolDecoder extends BaseProtocolDecoder { return null; } + if (buf.capacity() <= BLOCK_LENGTH) { + return null; // empty message + } + byte[] data = new byte[buf.capacity() - BLOCK_LENGTH]; buf.readBytes(data); buf = ChannelBuffers.wrappedBuffer(ByteOrder.LITTLE_ENDIAN, cipher.update(data)); diff --git a/src/org/traccar/protocol/CellocatorProtocol.java b/src/org/traccar/protocol/CellocatorProtocol.java index bfaf03692..7c8510204 100644 --- a/src/org/traccar/protocol/CellocatorProtocol.java +++ b/src/org/traccar/protocol/CellocatorProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.ChannelPipeline; import org.traccar.BaseProtocol; import org.traccar.TrackerServer; +import org.traccar.model.Command; import java.nio.ByteOrder; import java.util.List; @@ -28,6 +29,8 @@ public class CellocatorProtocol extends BaseProtocol { public CellocatorProtocol() { super("cellocator"); + setSupportedCommands( + Command.TYPE_OUTPUT_CONTROL); } @Override @@ -36,6 +39,7 @@ public class CellocatorProtocol extends BaseProtocol { @Override protected void addSpecificHandlers(ChannelPipeline pipeline) { pipeline.addLast("frameDecoder", new CellocatorFrameDecoder()); + pipeline.addLast("objectEncoder", new CellocatorProtocolEncoder()); pipeline.addLast("objectDecoder", new CellocatorProtocolDecoder(CellocatorProtocol.this)); } }; @@ -45,6 +49,7 @@ public class CellocatorProtocol extends BaseProtocol { server = new TrackerServer(new ConnectionlessBootstrap(), getName()) { @Override protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("objectEncoder", new CellocatorProtocolEncoder()); pipeline.addLast("objectDecoder", new CellocatorProtocolDecoder(CellocatorProtocol.this)); } }; diff --git a/src/org/traccar/protocol/CellocatorProtocolDecoder.java b/src/org/traccar/protocol/CellocatorProtocolDecoder.java index 14325e619..7df8cad8a 100644 --- a/src/org/traccar/protocol/CellocatorProtocolDecoder.java +++ b/src/org/traccar/protocol/CellocatorProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 Anton Tananaev (anton@traccar.org) + * Copyright 2013 - 2017 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -68,6 +68,19 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { } } + private String decodeAlarm(short reason) { + switch (reason) { + case 70: + return Position.ALARM_SOS; + case 80: + return Position.ALARM_POWER_CUT; + case 81: + return Position.ALARM_LOW_POWER; + default: + return null; + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -106,7 +119,8 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { operator += buf.readUnsignedByte(); buf.readUnsignedByte(); // reason data - buf.readUnsignedByte(); // reason + position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedByte())); + buf.readUnsignedByte(); // mode buf.readUnsignedInt(); // IO diff --git a/src/org/traccar/protocol/CellocatorProtocolEncoder.java b/src/org/traccar/protocol/CellocatorProtocolEncoder.java new file mode 100644 index 000000000..bb143d349 --- /dev/null +++ b/src/org/traccar/protocol/CellocatorProtocolEncoder.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * + * 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.traccar.BaseProtocolEncoder; +import org.traccar.helper.Log; +import org.traccar.model.Command; + +import java.nio.ByteOrder; + +public class CellocatorProtocolEncoder extends BaseProtocolEncoder { + + private ChannelBuffer encodeContent(long deviceId, int command, int data1, int data2) { + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 0); + buf.writeByte('M'); + buf.writeByte('C'); + buf.writeByte('G'); + buf.writeByte('P'); + buf.writeByte(0); + buf.writeInt(Integer.parseInt(getUniqueId(deviceId))); + buf.writeByte(0); // command numerator + buf.writeInt(0); // authentication code + buf.writeByte(command); + buf.writeByte(command); + buf.writeByte(data1); + buf.writeByte(data1); + buf.writeByte(data2); + buf.writeByte(data2); + buf.writeInt(0); // command specific data + + byte checksum = 0; + for (int i = 4; i < buf.writerIndex(); i++) { + checksum += buf.getByte(i); + } + buf.writeByte(checksum); + + return buf; + } + + @Override + protected Object encodeCommand(Command command) { + + switch (command.getType()) { + case Command.TYPE_OUTPUT_CONTROL: + int data = Integer.parseInt(command.getString(Command.KEY_DATA)) << 4 + + command.getInteger(Command.KEY_INDEX); + return encodeContent(command.getDeviceId(), 0x03, data, 0); + default: + Log.warning(new UnsupportedOperationException(command.getType())); + break; + } + + return null; + } + +} diff --git a/src/org/traccar/protocol/GalileoProtocolDecoder.java b/src/org/traccar/protocol/GalileoProtocolDecoder.java index 68063c5c3..c9aae8e96 100644 --- a/src/org/traccar/protocol/GalileoProtocolDecoder.java +++ b/src/org/traccar/protocol/GalileoProtocolDecoder.java @@ -55,6 +55,7 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder { private static final int TAG_ADC1 = 0x51; private static final int TAG_ADC2 = 0x52; private static final int TAG_ADC3 = 0x53; + private static final int TAG_ARRAY = 0xea; private static final Map<Integer, Integer> TAG_LENGTH_MAP = new HashMap<>(); @@ -81,7 +82,7 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder { 0x20, 0x33, 0x44, 0x90, 0xc0, 0xc2, 0xc3, 0xd3, 0xd4, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xf0, 0xf9, 0x5a, 0x47, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, - 0xf7, 0xf8 + 0xf7, 0xf8, 0xe2, 0xe9 }; for (int i : l1) { TAG_LENGTH_MAP.put(i, 1); @@ -102,7 +103,11 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder { } private static int getTagLength(int tag) { - return TAG_LENGTH_MAP.get(tag); + Integer length = TAG_LENGTH_MAP.get(tag); + if (length == null) { + throw new IllegalArgumentException("Unknown tag: " + tag); + } + return length; } private void sendReply(Channel channel, int checksum) { @@ -207,6 +212,10 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder { position.set(Position.PREFIX_ADC + 3, buf.readUnsignedShort()); break; + case TAG_ARRAY: + buf.skipBytes(buf.readUnsignedByte()); + break; + default: buf.skipBytes(getTagLength(tag)); break; diff --git a/src/org/traccar/protocol/Gl200ProtocolDecoder.java b/src/org/traccar/protocol/Gl200ProtocolDecoder.java index 59f013313..ef434b779 100644 --- a/src/org/traccar/protocol/Gl200ProtocolDecoder.java +++ b/src/org/traccar/protocol/Gl200ProtocolDecoder.java @@ -107,7 +107,7 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder { .compile(); private static final Pattern PATTERN_LOCATION = new PatternBuilder() - .number("(?:d{1,2})?,") // gps accuracy + .number("(d{1,2})?,") // hdop .number("(d{1,3}.d)?,") // speed .number("(d{1,3})?,") // course .number("(-?d{1,5}.d)?,") // altitude @@ -275,6 +275,7 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder { .number("(?:[0-9A-Z]{2}xxxx)?,") // protocol version .number("(d{15}|x{14}),") // imei .any() + .number("(d{1,2})?,") // hdop .number("(d{1,3}.d)?,") // speed .number("(d{1,3})?,") // course .number("(-?d{1,5}.d)?,") // altitude @@ -399,6 +400,10 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder { } private void decodeLocation(Position position, Parser parser) { + int hdop = parser.nextInt(); + position.setValid(hdop > 0); + position.set(Position.KEY_HDOP, hdop); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble())); position.setCourse(parser.nextDouble()); position.setAltitude(parser.nextDouble()); @@ -451,11 +456,11 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder { position.set("dtcsCodes", parser.next()); position.set(Position.KEY_THROTTLE, parser.next()); position.set(Position.KEY_FUEL, parser.next()); - position.set(Position.KEY_OBD_ODOMETER, parser.next()); + position.set(Position.KEY_OBD_ODOMETER, parser.nextInt() * 1000); decodeLocation(position, parser); - position.set(Position.KEY_ODOMETER, parser.next()); + position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); if (parser.hasNext(6)) { DateBuilder dateBuilder = new DateBuilder() @@ -510,7 +515,7 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); position.set(Position.KEY_BATTERY, parser.next()); - position.set(Position.KEY_ODOMETER, parser.next()); + position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); position.set(Position.KEY_HOURS, parser.next()); position.set(Position.PREFIX_ADC + 1, parser.next()); position.set(Position.PREFIX_ADC + 2, parser.next()); @@ -666,7 +671,7 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder { decodeLocation(position, parser); - position.set(Position.KEY_ODOMETER, parser.next()); + position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); position.set(Position.KEY_BATTERY, parser.next()); position.set(Position.KEY_ODOMETER, parser.nextDouble() * 1000); @@ -703,12 +708,15 @@ public class Gl200ProtocolDecoder extends BaseProtocolDecoder { position.setProtocol(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); + int hdop = parser.nextInt(); + position.setValid(hdop > 0); + position.set(Position.KEY_HDOP, hdop); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble())); position.setCourse(parser.nextDouble()); position.setAltitude(parser.nextDouble()); if (parser.hasNext(2)) { - position.setValid(true); position.setLongitude(parser.nextDouble()); position.setLatitude(parser.nextDouble()); } else { diff --git a/src/org/traccar/protocol/H02FrameDecoder.java b/src/org/traccar/protocol/H02FrameDecoder.java index f1d305ab6..391fccc87 100644 --- a/src/org/traccar/protocol/H02FrameDecoder.java +++ b/src/org/traccar/protocol/H02FrameDecoder.java @@ -50,7 +50,12 @@ public class H02FrameDecoder extends FrameDecoder { // Return text message int index = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) '#'); if (index != -1) { - return buf.readBytes(index + 1 - buf.readerIndex()); + ChannelBuffer result = buf.readBytes(index + 1 - buf.readerIndex()); + while (buf.readable() + && (buf.getByte(buf.readerIndex()) == '\r' || buf.getByte(buf.readerIndex()) == '\n')) { + buf.readByte(); // skip new line + } + return result; } break; @@ -81,7 +86,7 @@ public class H02FrameDecoder extends FrameDecoder { default: - throw new IllegalArgumentException(); + return null; } return null; diff --git a/src/org/traccar/protocol/H02ProtocolDecoder.java b/src/org/traccar/protocol/H02ProtocolDecoder.java index 37f6294be..a717ddc4d 100644 --- a/src/org/traccar/protocol/H02ProtocolDecoder.java +++ b/src/org/traccar/protocol/H02ProtocolDecoder.java @@ -75,7 +75,7 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED); } - position.set(Position.KEY_IGNITION, !BitUtil.check(status, 10)); + position.set(Position.KEY_IGNITION, BitUtil.check(status, 10)); position.set(Position.KEY_STATUS, status); } @@ -165,16 +165,10 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder { .expression("([EW]),") .number("(d+.?d*),") // speed .number("(d+.?d*)?,") // course - .number("(?:(dd)(dd)(dd))?,") // date (ddmmyy) - .any() - .number("(x{8})") // status - .groupBegin() - .number(", *(x+),") // mcc - .number(" *(x+),") // mnc - .number(" *(x+),") // lac - .number(" *(x+)") // cid - .groupEnd("?") + .number("(?:(dd)(dd)(dd))?") // date (ddmmyy) .any() + .number(",(x{8})") // status + .expression("(?:#|,.*)") .compile(); private static final Pattern PATTERN_NBR = new PatternBuilder() diff --git a/src/org/traccar/protocol/TaipProtocolDecoder.java b/src/org/traccar/protocol/TaipProtocolDecoder.java index 7927c28e6..c53538223 100644 --- a/src/org/traccar/protocol/TaipProtocolDecoder.java +++ b/src/org/traccar/protocol/TaipProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2015 Anton Tananaev (anton@traccar.org) + * Copyright 2013 - 2017 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,7 +48,8 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { .groupEnd("?") .number("(d{5})") // seconds .or() - .text("RGP") // type + .expression("(?:RGP|RCQ|RBR)") // type + .number("(?:dd)?") .number("(dd)(dd)(dd)") // date .number("(dd)(dd)(dd)") // time .groupEnd() @@ -56,6 +57,13 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { .number("([-+]ddd)(d{5})") // longitude .number("(ddd)") // speed .number("(ddd)") // course + .groupBegin() + .number("(xx)") // input + .number("(xx)") // satellites + .number("(ddd)") // battery + .number("(x{8})") // odometer + .number("[01]") // gps power + .groupEnd("?") .number("(d)") // fix mode .any() .compile(); @@ -93,15 +101,10 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { Position position = new Position(); position.setProtocol(getProtocolName()); - String week = parser.next(); - String day = parser.next(); - String seconds = parser.next(); - if (seconds != null) { - if (week != null && day != null) { - position.setTime(getTime(Integer.parseInt(week), Integer.parseInt(day), Integer.parseInt(seconds))); - } else { - position.setTime(getTime(Integer.parseInt(seconds))); - } + if (parser.hasNext(2)) { + position.setTime(getTime(parser.nextInt(), parser.nextInt(), parser.nextInt())); + } else if (parser.hasNext()) { + position.setTime(getTime(parser.nextInt())); } if (parser.hasNext(6)) { @@ -115,6 +118,14 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_DEG)); position.setSpeed(UnitsConverter.knotsFromMph(parser.nextDouble())); position.setCourse(parser.nextDouble()); + + if (parser.hasNext(4)) { + position.set(Position.KEY_INPUT, parser.nextInt(16)); + position.set(Position.KEY_SATELLITES, parser.nextInt(16)); + position.set(Position.KEY_BATTERY, parser.nextInt()); + position.set(Position.KEY_ODOMETER, parser.nextLong(16)); + } + position.setValid(parser.nextInt() != 0); String[] attributes = null; diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java index e647a33a0..9c1e0a2ff 100644 --- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java +++ b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java @@ -73,6 +73,12 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { private void decodeParameter(Position position, int id, ChannelBuffer buf, int length) { switch (id) { + case 1: + case 2: + case 3: + case 4: + position.set("di" + id, buf.readUnsignedByte()); + break; case 9: position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort()); break; @@ -82,6 +88,9 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { case 67: position.set(Position.KEY_BATTERY, buf.readUnsignedShort() + "mV"); break; + case 70: + position.set("pcbTemp", (length == 4 ? buf.readInt() : buf.readShort()) * 0.1); + break; case 72: position.set(Position.PREFIX_TEMP + 1, buf.readInt() * 0.1); break; diff --git a/src/org/traccar/protocol/TmgProtocolDecoder.java b/src/org/traccar/protocol/TmgProtocolDecoder.java index 9fa8759a0..3b73a1516 100644 --- a/src/org/traccar/protocol/TmgProtocolDecoder.java +++ b/src/org/traccar/protocol/TmgProtocolDecoder.java @@ -35,7 +35,7 @@ public class TmgProtocolDecoder extends BaseProtocolDecoder { private static final Pattern PATTERN = new PatternBuilder() .text("$") - .expression("...,") // type + .expression("(...),") // type .expression("[LH],") // history .number("(d+),") // imei .number("(dd)(dd)(dddd),") // date @@ -53,7 +53,7 @@ public class TmgProtocolDecoder extends BaseProtocolDecoder { .number("(d+),") // visible satellites .number("([^,]*),") // operator .number("(d+),") // rssi - .number("x+,") // cid + .number("[^,]*,") // cid .expression("([01]),") // ignition .number("(d+.?d*),") // battery .number("(d+.?d*),") // power @@ -72,6 +72,8 @@ public class TmgProtocolDecoder extends BaseProtocolDecoder { return null; } + String type = parser.next(); + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); if (deviceSession == null) { return null; @@ -81,6 +83,31 @@ public class TmgProtocolDecoder extends BaseProtocolDecoder { position.setProtocol(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); + switch (type) { + case "rmv": + position.set(Position.KEY_ALARM, Position.ALARM_POWER_CUT); + break; + case "ebl": + position.set(Position.KEY_ALARM, Position.ALARM_LOW_POWER); + break; + case "ibl": + position.set(Position.KEY_ALARM, Position.ALARM_LOW_BATTERY); + break; + case "tmp": + case "smt": + case "btt": + position.set(Position.KEY_ALARM, Position.ALARM_TAMPERING); + break; + case "ion": + position.set(Position.KEY_IGNITION, true); + break; + case "iof": + position.set(Position.KEY_IGNITION, false); + break; + default: + break; + } + DateBuilder dateBuilder = new DateBuilder() .setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()) .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); diff --git a/swagger.json b/swagger.json index 0f298f161..0857138e2 100644 --- a/swagger.json +++ b/swagger.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "3.9", + "version": "3.10", "title": "traccar" }, "host": "demo.traccar.org", @@ -384,10 +384,82 @@ } } }, + "/permissions/calendars": { + "post": { + "summary": "Link a Calendar to a User", + "parameters": [ + { + "$ref": "#/parameters/CalendarPermission" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/CalendarPermission" + } + } + } + }, + "delete": { + "summary": "Remove a Calendar from a User", + "parameters": [ + { + "$ref": "#/parameters/CalendarPermission" + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/permissions/users": { + "post": { + "summary": "Link a User to a manager User", + "parameters": [ + { + "$ref": "#/parameters/UserPermission" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/UserPermission" + } + } + } + }, + "delete": { + "summary": "Remove a User from a manager User", + "parameters": [ + { + "$ref": "#/parameters/UserPermission" + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, "/positions": { "get": { "summary" : "Fetches a list of Positions", "description" : "Without any params, it returns a list of last known positions for all the user's Devices. _from_ and _to_ fields are not required with _id_", + "consumes": [ + "application/json", + "text/csv", + "application/gpx+xml" + ], + "produces": [ + "application/json", + "text/csv", + "application/gpx+xml" + ], "parameters": [ { "name": "deviceId", @@ -474,6 +546,14 @@ "consumes": [ "application/x-www-form-urlencoded" ], + "parameters": [ + { + "name": "token", + "in": "query", + "required": false, + "type": "string" + } + ], "responses": { "200": { "description": "OK", @@ -534,6 +614,15 @@ "/users": { "get": { "summary": "Fetch a list of Users", + "parameters": [ + { + "name": "userId", + "in": "query", + "description": "Can only be used by admin or manager users", + "required": false, + "type": "string" + } + ], "responses": { "200": { "description": "OK", @@ -786,6 +875,14 @@ "get": { "summary": "Fetch a list of Positions within the time period for the Devices or Groups", "description": "At least one _deviceId_ or one _groupId_ must be passed", + "consumes": [ + "application/json", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], + "produces": [ + "application/json", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], "parameters": [ { "$ref": "#/parameters/deviceIdArray" @@ -817,6 +914,14 @@ "get": { "summary": "Fetch a list of Events within the time period for the Devices or Groups", "description": "At least one _deviceId_ or one _groupId_ must be passed", + "consumes": [ + "application/json", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], + "produces": [ + "application/json", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], "parameters": [ { "$ref": "#/parameters/deviceIdArray" @@ -857,6 +962,14 @@ "get": { "summary": "Fetch a list of ReportSummary within the time period for the Devices or Groups", "description": "At least one _deviceId_ or one _groupId_ must be passed", + "consumes": [ + "application/json", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], + "produces": [ + "application/json", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], "parameters": [ { "$ref": "#/parameters/deviceIdArray" @@ -888,6 +1001,14 @@ "get": { "summary": "Fetch a list of ReportTrips within the time period for the Devices or Groups", "description": "At least one _deviceId_ or one _groupId_ must be passed", + "consumes": [ + "application/json", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], + "produces": [ + "application/json", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], "parameters": [ { "$ref": "#/parameters/deviceIdArray" @@ -1010,6 +1131,81 @@ } } } + }, + "/calendars": { + "get": { + "summary": "Fetch a list of Calendars", + "description": "Without params, it returns a list of Calendars the user has access to", + "parameters": [ + { + "$ref": "#/parameters/all" + }, + { + "$ref": "#/parameters/userId" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Calendar" + } + } + } + } + }, + "post": { + "summary": "Create a Calendar", + "parameters": [ + { + "$ref": "#/parameters/Calendar" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Calendar" + } + } + } + } + }, + "/calendars/{id}": { + "put": { + "summary": "Update a Calendar", + "parameters": [ + { + "$ref": "#/parameters/entityId" + }, + { + "$ref": "#/parameters/Calendar" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Calendar" + } + } + } + }, + "delete": { + "summary": "Delete a Calendar", + "parameters": [ + { + "$ref": "#/parameters/entityId" + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } } }, "definitions": { @@ -1064,6 +1260,12 @@ "address": { "type": "string" }, + "accuracy": { + "type": "number" + }, + "network": { + "type": "string" + }, "attributes": {} } }, @@ -1122,6 +1324,12 @@ "deviceLimit": { "type": "integer" }, + "userLimit": { + "type": "integer" + }, + "deviceReadonly": { + "type": "boolean" + }, "token": { "type": "string" }, @@ -1279,6 +1487,26 @@ } } }, + "CalendarPermission": { + "properties": { + "userId": { + "type": "integer" + }, + "calendarId": { + "type": "integer" + } + } + }, + "UserPermission": { + "properties": { + "userId": { + "type": "integer" + }, + "managedUserId": { + "type": "integer" + } + } + }, "GroupGeofence": { "properties": { "groupId": { @@ -1320,6 +1548,9 @@ "area": { "type": "string" }, + "calendarId": { + "type": "integer" + }, "attributes": {} } }, @@ -1334,6 +1565,12 @@ "userId": { "type": "integer" }, + "web": { + "type": "boolean" + }, + "mail": { + "type": "boolean" + }, "attributes": {} } }, @@ -1490,6 +1727,21 @@ "description": "in meters" } } + }, + "Calendar": { + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "data": { + "type": "string", + "description": "base64 encoded in iCalendar format" + }, + "atributes": {} + } } }, "parameters": { @@ -1502,7 +1754,7 @@ "all": { "name": "all", "in": "query", - "description": "Can only be used by admin users to fetch all entities", + "description": "Can only be used by admins or managers to fetch all entities", "type": "boolean" }, "userId": { @@ -1573,6 +1825,22 @@ "$ref": "#/definitions/GeofencePermission" } }, + "CalendarPermission": { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/CalendarPermission" + } + }, + "UserPermission": { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/UserPermission" + } + }, "User": { "name": "body", "in": "body", @@ -1597,6 +1865,14 @@ "$ref": "#/definitions/AttributeAlias" } }, + "Calendar": { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Calendar" + } + }, "deviceIdArray": { "name": "deviceId", "in": "query", diff --git a/test/org/traccar/FilterHandlerTest.java b/test/org/traccar/FilterHandlerTest.java index 11b4163a1..452592048 100644 --- a/test/org/traccar/FilterHandlerTest.java +++ b/test/org/traccar/FilterHandlerTest.java @@ -1,14 +1,14 @@ package org.traccar; -import java.util.Date; import org.junit.After; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import org.junit.Before; import org.junit.Test; -import org.traccar.database.IdentityManager; import org.traccar.model.Position; -import org.traccar.model.Device; + +import java.util.Date; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; public class FilterHandlerTest extends BaseTest { diff --git a/test/org/traccar/ProtocolTest.java b/test/org/traccar/ProtocolTest.java index 955e0b788..f4072ad24 100644 --- a/test/org/traccar/ProtocolTest.java +++ b/test/org/traccar/ProtocolTest.java @@ -6,10 +6,8 @@ import org.jboss.netty.handler.codec.http.DefaultHttpRequest; import org.jboss.netty.handler.codec.http.HttpMethod; import org.jboss.netty.handler.codec.http.HttpVersion; import org.junit.Assert; -import org.traccar.database.IdentityManager; import org.traccar.model.CellTower; import org.traccar.model.Command; -import org.traccar.model.Device; import org.traccar.model.Position; import javax.xml.bind.DatatypeConverter; @@ -147,7 +145,7 @@ public class ProtocolTest extends BaseTest { } else { Assert.assertNotNull(position.getFixTime()); - Assert.assertTrue("year > 2000", position.getFixTime().after(new Date(946684800000L))); + Assert.assertTrue("year > 1999", position.getFixTime().after(new Date(915148800000L))); Assert.assertTrue("time < +25 hours", position.getFixTime().getTime() < System.currentTimeMillis() + 25 * 3600000); diff --git a/test/org/traccar/geocoder/GeocoderTest.java b/test/org/traccar/geocoder/GeocoderTest.java index 012f8bacd..a5aecc8cf 100644 --- a/test/org/traccar/geocoder/GeocoderTest.java +++ b/test/org/traccar/geocoder/GeocoderTest.java @@ -1,17 +1,15 @@ package org.traccar.geocoder; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; public class GeocoderTest { - private boolean enable = false; - + @Ignore @Test public void test() throws InterruptedException { - if (enable) { - testGeocodeFarm(); - } + testGoogle(); } private String address; @@ -31,9 +29,9 @@ public class GeocoderTest { } public void testGoogle() throws InterruptedException { - Geocoder geocoder = new GoogleGeocoder(); + Geocoder geocoder = new GoogleGeocoder(null, null, 0); - geocoder.getAddress(new AddressFormat(), 37.4217550, -122.0846330, new Geocoder.ReverseGeocoderCallback() { + geocoder.getAddress(new AddressFormat(), 31.776797, 35.211489, new Geocoder.ReverseGeocoderCallback() { @Override public void onSuccess(String address) { setAddress(address); @@ -43,11 +41,11 @@ public class GeocoderTest { public void onFailure(Throwable e) { } }); - Assert.assertEquals("1600 Amphitheatre Pkwy, Mountain View, CA, US", waitAddress()); + Assert.assertEquals("1 Ibn Shaprut St, Jerusalem, Jerusalem District, IL", waitAddress()); } public void testNominatim() throws InterruptedException { - Geocoder geocoder = new NominatimGeocoder(); + Geocoder geocoder = new NominatimGeocoder(null, null, 0); geocoder.getAddress(new AddressFormat(), 40.7337807, -73.9974401, new Geocoder.ReverseGeocoderCallback() { @Override @@ -96,7 +94,7 @@ public class GeocoderTest { } public void testGeocodeFarm() throws InterruptedException { - Geocoder geocoder = new GeocodeFarmGeocoder(0); + Geocoder geocoder = new GeocodeFarmGeocoder(null, 0); geocoder.getAddress(new AddressFormat(), 34.116302, -118.051519, new Geocoder.ReverseGeocoderCallback() { @Override diff --git a/test/org/traccar/protocol/At2000ProtocolDecoderTest.java b/test/org/traccar/protocol/At2000ProtocolDecoderTest.java index 596d2870d..0b1a9f471 100644 --- a/test/org/traccar/protocol/At2000ProtocolDecoderTest.java +++ b/test/org/traccar/protocol/At2000ProtocolDecoderTest.java @@ -19,6 +19,14 @@ public class At2000ProtocolDecoderTest extends ProtocolTest { decoder = new At2000ProtocolDecoder(new At2000Protocol()); verifyNothing(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "01012f00000000000000000000000000003335373435343037313632373539388b57ec3a6ec7e3310a1ceb0a70fd751b8f2e7be6df1d6dcd80129f66fff0ea1c")); + + verifyNothing(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "89000000000000000000000000000000")); + + decoder = new At2000ProtocolDecoder(new At2000Protocol()); + + verifyNothing(decoder, binary(ByteOrder.LITTLE_ENDIAN, "01012f0000000000000000000000000000333537343534303731363036313936ddf189075add9a32d97b54073025963e65849a3a59940d05fd8db655fc84bc6d")); verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, diff --git a/test/org/traccar/protocol/CellocatorProtocolDecoderTest.java b/test/org/traccar/protocol/CellocatorProtocolDecoderTest.java index fe03bc3d5..cdda0fca7 100644 --- a/test/org/traccar/protocol/CellocatorProtocolDecoderTest.java +++ b/test/org/traccar/protocol/CellocatorProtocolDecoderTest.java @@ -13,6 +13,12 @@ public class CellocatorProtocolDecoderTest extends ProtocolTest { CellocatorProtocolDecoder decoder = new CellocatorProtocolDecoder(new CellocatorProtocol()); verifyPosition(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "4D434750008AD01500080103011804000000460020000000005E750000000000000000000000C34300040204DA4DA30367195703E803000000000000000001030F0802E10778")); + + verifyPosition(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "4D434750008AD01500080102011804000000360060000000005E750000000000000000000000C24300040204DA4DA30367195703E80300000000000000003B020F0802E107DF")); + + verifyPosition(decoder, binary(ByteOrder.LITTLE_ENDIAN, "4D4347500006000000081A02021204000000210062300000006B00E100000000000000000000E5A100040206614EA303181A57034E1200000000000000001525071403D60749")); verifyPosition(decoder, binary(ByteOrder.LITTLE_ENDIAN, diff --git a/test/org/traccar/protocol/CellocatorProtocolEncoderTest.java b/test/org/traccar/protocol/CellocatorProtocolEncoderTest.java new file mode 100644 index 000000000..89850fb5f --- /dev/null +++ b/test/org/traccar/protocol/CellocatorProtocolEncoderTest.java @@ -0,0 +1,26 @@ +package org.traccar.protocol; + +import org.junit.Ignore; +import org.junit.Test; +import org.traccar.ProtocolTest; +import org.traccar.model.Command; + +public class CellocatorProtocolEncoderTest extends ProtocolTest { + + @Ignore + @Test + public void testEncode() throws Exception { + + CellocatorProtocolEncoder encoder = new CellocatorProtocolEncoder(); + + Command command = new Command(); + command.setDeviceId(1); + command.setType(Command.TYPE_OUTPUT_CONTROL); + command.set(Command.KEY_INDEX, 0); + command.set(Command.KEY_DATA, "1"); + + verifyCommand(encoder, command, binary("4D434750000000000000000000000303101000000000000026")); + + } + +} diff --git a/test/org/traccar/protocol/GalileoFrameDecoderTest.java b/test/org/traccar/protocol/GalileoFrameDecoderTest.java new file mode 100644 index 000000000..1decd73d3 --- /dev/null +++ b/test/org/traccar/protocol/GalileoFrameDecoderTest.java @@ -0,0 +1,26 @@ +package org.traccar.protocol; + +import org.junit.Assert; +import org.junit.Test; +import org.traccar.ProtocolTest; + +import java.nio.ByteOrder; + +public class GalileoFrameDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + GalileoFrameDecoder decoder = new GalileoFrameDecoder(); + + Assert.assertEquals( + binary(ByteOrder.LITTLE_ENDIAN, "011780011102e603383633353931303238393630323437043200801c"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "011780011102e603383633353931303238393630323437043200801c"))); + + Assert.assertEquals( + binary(ByteOrder.LITTLE_ENDIAN, "01d48304320010020520a5829f58300f50dc8a024c0965013300000000344102350740003a41e14b426610431b4459fa672a4500004601a050364c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e293000000043200100105202d829f58300f50dc8a024c0965013300000000344102350740003a41d04b426110431b445702882a4500004601a050374c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29400000004320010000520b5819f58300f50dc8a024c0965013300000000344102350740003a419e4b426a10431c4456fab72a4500004601a050434c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010ff04203d819f58300f50dc8a024c0965013300000000344102350740003a41874b426310431c4454fe572a4500004601a050334c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29600000004320010fe0420c5809f58300f50dc8a024c0965013300000000344102350840003a41a24b426710431c4457fea72a4500004601a050214c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fd04204d809f58300f50dc8a024c0965013300000000344102350840003a41a34b426310431c4455f6772a4500004601a0502e4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29900000004320010fc0420d57f9f58300f50dc8a024c0965013300000000344102350840003a41bd4b426510431d4458fe672a4500004601a0501f4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fb04205d7f9f58300f50dc8a024c0965013300000000344102350840003a41b54b426310431d4456fa772a4500004601a0502d4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010fa0420e57e9f58300f50dc8a024c0965013300000000344102350840003a41b24b426210431e4454fa872a4500004601a050fe4b510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29000000004320010f904206d7e9f58300f50dc8a024c0965013300000000344102350a40003a41af4b426710431f4458fea72a4500004601a0500a4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e28900000067c5"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "01d48304320010020520a5829f58300f50dc8a024c0965013300000000344102350740003a41e14b426610431b4459fa672a4500004601a050364c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e293000000043200100105202d829f58300f50dc8a024c0965013300000000344102350740003a41d04b426110431b445702882a4500004601a050374c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29400000004320010000520b5819f58300f50dc8a024c0965013300000000344102350740003a419e4b426a10431c4456fab72a4500004601a050434c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010ff04203d819f58300f50dc8a024c0965013300000000344102350740003a41874b426310431c4454fe572a4500004601a050334c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29600000004320010fe0420c5809f58300f50dc8a024c0965013300000000344102350840003a41a24b426710431c4457fea72a4500004601a050214c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fd04204d809f58300f50dc8a024c0965013300000000344102350840003a41a34b426310431c4455f6772a4500004601a0502e4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29900000004320010fc0420d57f9f58300f50dc8a024c0965013300000000344102350840003a41bd4b426510431d4458fe672a4500004601a0501f4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fb04205d7f9f58300f50dc8a024c0965013300000000344102350840003a41b54b426310431d4456fa772a4500004601a0502d4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010fa0420e57e9f58300f50dc8a024c0965013300000000344102350840003a41b24b426210431e4454fa872a4500004601a050fe4b510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29000000004320010f904206d7e9f58300f50dc8a024c0965013300000000344102350a40003a41af4b426710431f4458fea72a4500004601a0500a4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e28900000067c5"))); + + } + +} diff --git a/test/org/traccar/protocol/GalileoProtocolDecoderTest.java b/test/org/traccar/protocol/GalileoProtocolDecoderTest.java index c18a652f7..28d40829a 100644 --- a/test/org/traccar/protocol/GalileoProtocolDecoderTest.java +++ b/test/org/traccar/protocol/GalileoProtocolDecoderTest.java @@ -24,6 +24,9 @@ public class GalileoProtocolDecoderTest extends ProtocolTest { verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, "011e8304320010270220dbd2f051300a90cf740328ac59033300000000347600351240012a41e92e42500f431f440006c814450f00460020500000510000520000530000540000550000560000570000580000600000610000620000a000a100a200a300a400a500a600a700a800a900aa00ab00ac00ad00ae00af00b00000b10000b20000b30000b40000b50000b60000b70000b80000b90000c000000000c100000000c200000000c300000000c400c500c600c700c800c900ca00cb00cc00cd00ce00cf00d000d100d200d471020000d60000d70000d80000d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f30000000004320010260220bdd2f051300590cf740328ac59033300000000347600351440090a41f02e427b0f431f44ff0db814450f00460000500000510000520000530000540000550000560000570000580000600000610000620000a000a100a200a300a400a500a600a700a800a900aa00ab00ac00ad00ae00af00b00000b10000b20000b30000b40000b50000b60000b70000b80000b90000c000000000c100000000c200000000c300000000c400c500c600c700c800c900ca00cb00cc00cd00ce00cf00d000d100d200d471020000d60000d70000d80000d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f300000000043200102502208ed2f051300ed8d0740304ac5903330000000034a500350a40012a41ec2e422d0f431f440016b814450f00460020500000510000520000530000540000550000560000570000580000600000610000620000a000a100a200a300a400a500a600a700a800a900aa00ab00ac00ad00ae00af00b00000b10000b20000b30000b40000b50000b60000b70000b80000b90000c000000000c100000000c200000000c300000000c400c500c600c700c800c900ca00cb00cc00cd00ce00cf00d000d100d200d44d020000d60000d70000d80000d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f300000000622e")); + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, + "01d48304320010020520a5829f58300f50dc8a024c0965013300000000344102350740003a41e14b426610431b4459fa672a4500004601a050364c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e293000000043200100105202d829f58300f50dc8a024c0965013300000000344102350740003a41d04b426110431b445702882a4500004601a050374c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29400000004320010000520b5819f58300f50dc8a024c0965013300000000344102350740003a419e4b426a10431c4456fab72a4500004601a050434c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010ff04203d819f58300f50dc8a024c0965013300000000344102350740003a41874b426310431c4454fe572a4500004601a050334c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29600000004320010fe0420c5809f58300f50dc8a024c0965013300000000344102350840003a41a24b426710431c4457fea72a4500004601a050214c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fd04204d809f58300f50dc8a024c0965013300000000344102350840003a41a34b426310431c4455f6772a4500004601a0502e4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29900000004320010fc0420d57f9f58300f50dc8a024c0965013300000000344102350840003a41bd4b426510431d4458fe672a4500004601a0501f4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fb04205d7f9f58300f50dc8a024c0965013300000000344102350840003a41b54b426310431d4456fa772a4500004601a0502d4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010fa0420e57e9f58300f50dc8a024c0965013300000000344102350840003a41b24b426210431e4454fa872a4500004601a050fe4b510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29000000004320010f904206d7e9f58300f50dc8a024c0965013300000000344102350a40003a41af4b426710431f4458fea72a4500004601a0500a4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e28900000067c5")); + } } diff --git a/test/org/traccar/protocol/Gl200ProtocolDecoderTest.java b/test/org/traccar/protocol/Gl200ProtocolDecoderTest.java index a4b8985f1..e2ac176f0 100644 --- a/test/org/traccar/protocol/Gl200ProtocolDecoderTest.java +++ b/test/org/traccar/protocol/Gl200ProtocolDecoderTest.java @@ -10,6 +10,15 @@ public class Gl200ProtocolDecoderTest extends ProtocolTest { Gl200ProtocolDecoder decoder = new Gl200ProtocolDecoder(new Gl200Protocol()); + verifyNothing(decoder, text( + "+RESP:GTGSM,400201,862365030034940,STR,0234,0030,0870,2469,19,,0234,0030,0870,35ee,18,,0234,0030,0870,16ac,12,,0234,0030,0870,16b2,11,,0234,0030,0870,360f,6,,0234,0030,0870,165d,6,,0234,0030,0870,35ef,17,,20170215220049,008D$")); + + verifyPosition(decoder, text( + "+RESP:GTSTR,400201,862365030034940,GL500,0,0,2,21.1,86,0,1.6,0,5.8,0.622831,51.582688,20170215090422,0234,0030,0870,35EF,,,,20170215220049,008C$")); + + verifyPositions(decoder, text( + "+RESP:GTFRI,2C0402,867162020000816,,0,0,1,2,0.3,337,245.7,-82.373387,34.634011,20170215003054,,,,,,63,20170215003241,3EAB$")); + verifyNotNull(decoder, text( "+RESP:GTWIF,210102,354524044608058,,4,c413e200ff14,-39,,,,c413e2010e55,-39,,,,c8d3ff04a837,-43,,,,42490f997c6d,-57,,,,,,,,100,20170201020055,0001$")); diff --git a/test/org/traccar/protocol/H02FrameDecoderTest.java b/test/org/traccar/protocol/H02FrameDecoderTest.java index 1505e25ac..3ced35d53 100644 --- a/test/org/traccar/protocol/H02FrameDecoderTest.java +++ b/test/org/traccar/protocol/H02FrameDecoderTest.java @@ -12,6 +12,10 @@ public class H02FrameDecoderTest extends ProtocolTest { H02FrameDecoder decoder = new H02FrameDecoder(0); Assert.assertEquals( + binary("2a48512c3335353438383032303131333931312c56312c3031323934352c412c353233312e37393238332c4e2c30313332342e31303731382c452c302e30352c302c3137303231372c464646464646464623"), + decoder.decode(null, null, binary("2a48512c3335353438383032303131333931312c56312c3031323934352c412c353233312e37393238332c4e2c30313332342e31303731382c452c302e30352c302c3137303231372c4646464646464646230d0a"))); + + Assert.assertEquals( binary("2441060116601245431311165035313006004318210e000000fffffbffff0024"), decoder.decode(null, null, binary("2441060116601245431311165035313006004318210e000000fffffbffff0024"))); diff --git a/test/org/traccar/protocol/H02ProtocolDecoderTest.java b/test/org/traccar/protocol/H02ProtocolDecoderTest.java index 55bad63c8..90a1470c6 100644 --- a/test/org/traccar/protocol/H02ProtocolDecoderTest.java +++ b/test/org/traccar/protocol/H02ProtocolDecoderTest.java @@ -10,6 +10,12 @@ public class H02ProtocolDecoderTest extends ProtocolTest { H02ProtocolDecoder decoder = new H02ProtocolDecoder(new H02Protocol()); + verifyPosition(decoder, buffer( + "*HQ,4109179024,V19,103732,V,3853.2770,S,06205.8678,W,000.00,000,100217,,5492932630888,8954314165044716555?,FFFFFBFF#")); + + verifyAttributes(decoder, buffer( + "*HQ,4109179024,NBR,103732,722,310,0,6,8106,32010,23,8101,22007,25,8106,12010,23,8106,22105,22,8101,22012,16,8106,42010,5,100217,FFFFFBFF,5#")); + verifyNothing(decoder, buffer( "*HQ,355488020930796,V3,002339,62160,06,024852,035421,148,0,024852,035425,143,,022251,036482,137,,024852,000335,133,,024852,031751,133,,024852,035423,133,,02A1,0,X,010104,EFE7FBFF#")); diff --git a/test/org/traccar/protocol/TaipProtocolDecoderTest.java b/test/org/traccar/protocol/TaipProtocolDecoderTest.java index 871ec84b3..74956f51c 100644 --- a/test/org/traccar/protocol/TaipProtocolDecoderTest.java +++ b/test/org/traccar/protocol/TaipProtocolDecoderTest.java @@ -11,6 +11,12 @@ public class TaipProtocolDecoderTest extends ProtocolTest { TaipProtocolDecoder decoder = new TaipProtocolDecoder(new TaipProtocol(), false); verifyPosition(decoder, text( + ">RCQ09000000000000-3460365-058381460000007F0000000000000115000FFFF1099;#0000;ID=555224;*05<")); + + verifyPosition(decoder, text( + ">RBR00130217040848-3462200-05846708000175FF0022900003B3C13010800001118410+24061A;ID=555224;*07<")); + + verifyPosition(decoder, text( ">REV451891352379+0307152+1016143700000012;SV=8;BL=4416;VO=8055;ID=356612026322000<")); verifyPosition(decoder, text( diff --git a/test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java b/test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java index 22c9c4b4b..289a4f28d 100644 --- a/test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java +++ b/test/org/traccar/protocol/TeltonikaProtocolDecoderTest.java @@ -14,6 +14,9 @@ public class TeltonikaProtocolDecoderTest extends ProtocolTest { "000F313233343536373839303132333435")); verifyPositions(decoder, false, binary( + "0000000000000000080100000113fc208dff00209cca800f14f650006f00d60400040004030101150316030001460000015d000100000000")); // invalid length and checksum + + verifyPositions(decoder, false, binary( "000000000000009f080400000159738f76b8012e13b796110ab27600d700000b00004e01000000014e000000000000000000000159738f6ee8012e13b796110ab27600d700000a00004e01000000014e01000b00791c179300000159738f6b00012e13b796110ab27600d700000a00004e01000000014e000000000000000000000159738f5f48012e13b796110ab27600d700000b00004e01000000014e01000b00791c17930400009671")); verifyPositions(decoder, false, binary( diff --git a/test/org/traccar/protocol/TmgProtocolDecoderTest.java b/test/org/traccar/protocol/TmgProtocolDecoderTest.java index fb2576f95..cbfe82abc 100644 --- a/test/org/traccar/protocol/TmgProtocolDecoderTest.java +++ b/test/org/traccar/protocol/TmgProtocolDecoderTest.java @@ -11,6 +11,21 @@ public class TmgProtocolDecoderTest extends ProtocolTest { TmgProtocolDecoder decoder = new TmgProtocolDecoder(new TmgProtocol()); verifyPosition(decoder, text( + "$ion,H,868324023777431,27012017,101057,4,2830.2952,N,07705.2532,E,0.0,202.38,225.9,1.22,8,20,N.A,0,N.A,1,4.09,00.0,00000111,00000000,1101,00.0-00.0,00.0-0.0,4.42,01.02,#")); + + verifyPosition(decoder, text( + "$iof,H,868324023777431,27012017,101111,4,2830.2952,N,07705.2532,E,0.0,202.38,225.9,0.87,11,21,N.A,25,N.A,0,4.09,00.0,00000111,00000000,1110,00.0-00.0,00.0-0.0,4.42,01.02,#")); + + verifyPosition(decoder, text( + "$rmv,L,868324023777431,27012017,101141,4,2830.2952,N,07705.2532,E,0.0,202.38,225.9,0.86,12,21,VODAFONE - DELH,24,3220,0,4.11,00.0,00000111,00000000,1110,00.0-00.0,00.0-0.0,4.42,01.02,#")); + + verifyPosition(decoder, text( + "$rnc,H,868324023777431,27012017,101013,4,2830.2923,N,07705.2551,E,0.0,9.65,226.0,0.88,12,21,VODAFONE - DELH,28,3220,0,4.14,07.4,00000111,00000000,1111,00.0-00.0,00.0-0.0,4.42,01.02,#")); + + verifyPosition(decoder, text( + "$ebl,H,868324023777431,27012017,101046,4,2830.2923,N,07705.2551,E,0.0,9.65,226.0,0.97,11,21,VODAFONE - DELH,25,3220,0,4.11,00.0,00000111,00000000,1110,00.0-00.0,00.0-0.0,4.42,01.02,#")); + + verifyPosition(decoder, text( "$nor,L,868324023777431,17012017,001023,4,2830.2977,N,07705.2478,E,0.0,207.07,229.2,0.97,11,22,IDEA CELLULAR L,18,DCDE,0,4.09,12.9,00000111,00000000,1111,00.0-00.0,00.0-0.0,3.59,01.02,#")); verifyPosition(decoder, text( diff --git a/tools/swagger2html.py b/tools/swagger2html.py index a3488835c..1121f04c9 100755 --- a/tools/swagger2html.py +++ b/tools/swagger2html.py @@ -224,11 +224,17 @@ def make_responses_table(responses): except KeyError as e: handleException('KeyError', e) +def sorted_by_method(section): + sorting_function = lambda x: [ 'GET', 'POST', 'PUT', 'DELETE' ].index( + x['title'].split(' ')[0] + ) + return sorted(sorted(section), key=sorting_function) + def make_paths(sections, json_data): md = '<h2><a name="paths"></a>Paths</h2>\n' for key in sorted(sections): md += '<h3><a name="paths_{0}"></a>{0}</h3>\n'.format(key) - for section in sections[key]: + for section in sorted_by_method(sections[key]): md += '<h4><a name="{}"></a><code>{}</code></h4>\n'.format( section['href'], section['title'] ) @@ -256,7 +262,7 @@ def make_contents(path_section, json_data): for key in sorted(path_section): md += ' <li><a href="#paths_{0}">{0}</a>\n'.format(key) md += ' <ul>\n' - for section in path_section[key]: + for section in sorted_by_method(path_section[key]): md += ' <li><a href="#{}">{}</a></li>\n'.format( section['href'], section['title'] ) |