From 72e8ab6966cb70dd58dcdf671dab11a7673aeabf Mon Sep 17 00:00:00 2001 From: Edward Valley Date: Mon, 26 Aug 2019 06:08:50 -0400 Subject: Add a ring buffer and response check --- src/main/java/org/traccar/WebDataHandler.java | 89 +++++++++++++++++++++++---- src/main/java/org/traccar/config/Keys.java | 7 +++ 2 files changed, 85 insertions(+), 11 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index 64396de03..193efd230 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -27,9 +27,11 @@ import org.traccar.model.Position; import org.traccar.model.Group; import javax.inject.Inject; +import javax.ws.rs.core.Response; import javax.ws.rs.client.Client; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.InvocationCallback; import java.util.HashMap; import java.util.Map; import java.io.UnsupportedEncodingException; @@ -39,6 +41,14 @@ import java.util.Calendar; import java.util.Formatter; import java.util.Locale; import java.util.TimeZone; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.collections.Buffer; +import org.apache.commons.collections.BufferUtils; +import org.apache.commons.collections.buffer.CircularFifoBuffer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @ChannelHandler.Sharable public class WebDataHandler extends BaseDataHandler { @@ -46,6 +56,8 @@ public class WebDataHandler extends BaseDataHandler { private static final String KEY_POSITION = "position"; private static final String KEY_DEVICE = "device"; + private static final Logger LOGGER = LoggerFactory.getLogger(WebDataHandler.class); + private final IdentityManager identityManager; private final ObjectMapper objectMapper; private final Client client; @@ -54,6 +66,13 @@ public class WebDataHandler extends BaseDataHandler { private final String header; private final boolean json; + private final Integer queueSize; + + private Buffer positionsQueue = null; + private AtomicBoolean sendInProgress; + + private Invocation.Builder requestBuilder; + @Inject public WebDataHandler( Config config, IdentityManager identityManager, ObjectMapper objectMapper, Client client) { @@ -63,6 +82,12 @@ public class WebDataHandler extends BaseDataHandler { this.url = config.getString(Keys.FORWARD_URL); this.header = config.getString(Keys.FORWARD_HEADER); this.json = config.getBoolean(Keys.FORWARD_JSON); + Integer queueSize = (config.getInteger(Keys.FORWARD_QUEUE_SIZE, 0)); + this.queueSize = (queueSize > 0) ? queueSize : 0; + if (this.queueSize > 0) { + this.positionsQueue = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(this.queueSize)); + } + this.sendInProgress = new AtomicBoolean(false); } private static String formatSentence(Position position) { @@ -152,9 +177,7 @@ public class WebDataHandler extends BaseDataHandler { return request; } - @Override - protected Position handlePosition(Position position) { - + protected void sendPosition(Position position) { String url; if (json) { url = this.url; @@ -166,19 +189,63 @@ public class WebDataHandler extends BaseDataHandler { } } - Invocation.Builder requestBuilder = client.target(url).request(); - - if (header != null && !header.isEmpty()) { - for (String line: header.split("\\r?\\n")) { - String[] values = line.split(":", 2); - requestBuilder.header(values[0].trim(), values[1].trim()); + if (!json || requestBuilder == null) { + requestBuilder = client.target(url).request(); + if (header != null && !header.isEmpty()) { + for (String line: header.split("\\r?\\n")) { + String[] values = line.split(":", 2); + requestBuilder.header(values[0].trim(), values[1].trim()); + } } } + InvocationCallback callback = new InvocationCallback() { + public void completed(Response response) { + if (positionsQueue != null) { + if (response.getStatus() == 200) { + positionsQueue.remove(); + } + logQueueStatus(); + sendInProgress.set(false); + sendQueuedPositions(); + } + } + public void failed(Throwable throwable) { + if (positionsQueue != null) { + logQueueStatus(); + sendInProgress.set(false); + sendQueuedPositions(); + } + } + }; + if (json) { - requestBuilder.async().post(Entity.json(prepareJsonPayload(position))); + requestBuilder.async().post(Entity.json(prepareJsonPayload(position)), callback); + } else { + requestBuilder.async().get(callback); + } + } + + protected void logQueueStatus() { + LOGGER.info(String.format("Position forwarding queue: %d/%d", + positionsQueue.size(), queueSize)); + } + + protected void sendQueuedPositions() { + if (!positionsQueue.isEmpty() && !sendInProgress.get()) { + sendInProgress.set(true); + sendPosition((Position) positionsQueue.get()); + } + } + + @Override + protected Position handlePosition(Position position) { + + if (positionsQueue == null) { + sendPosition(position); } else { - requestBuilder.async().get(); + positionsQueue.add(position); + sendQueuedPositions(); } return position; diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 2c5dcefd5..10eda01e2 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -100,6 +100,13 @@ public final class Keys { public static final ConfigKey FORWARD_JSON = new ConfigKey( "forward.json", Boolean.class); + /** + * Position forwarding queue size. A ring buffer of the specified size is used to queue positions. + * If negative, zero, or not specified, queueing is disabled. (Legacy behaviour) + */ + public static final ConfigKey FORWARD_QUEUE_SIZE = new ConfigKey( + "forward.queue.size", Integer.class); + /** * Boolean flag to enable or disable position filtering. */ -- cgit v1.2.3 From 169c40cc7207a962f027aea85bd8f9c04b33738f Mon Sep 17 00:00:00 2001 From: Edward Valley Date: Sat, 31 Aug 2019 18:27:13 -0400 Subject: Refactor code to have concurrency --- src/main/java/org/traccar/WebDataHandler.java | 141 ++++++++++++++++---------- src/main/java/org/traccar/config/Keys.java | 7 ++ 2 files changed, 93 insertions(+), 55 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index 193efd230..dfd6f0e5b 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -41,7 +41,7 @@ import java.util.Calendar; import java.util.Formatter; import java.util.Locale; import java.util.TimeZone; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.collections.Buffer; import org.apache.commons.collections.BufferUtils; @@ -67,27 +67,33 @@ public class WebDataHandler extends BaseDataHandler { private final boolean json; private final Integer queueSize; + private final Integer queueConcurrency; private Buffer positionsQueue = null; - private AtomicBoolean sendInProgress; - - private Invocation.Builder requestBuilder; + private AtomicInteger pendingRequests; @Inject public WebDataHandler( Config config, IdentityManager identityManager, ObjectMapper objectMapper, Client client) { + this.identityManager = identityManager; this.objectMapper = objectMapper; this.client = client; this.url = config.getString(Keys.FORWARD_URL); this.header = config.getString(Keys.FORWARD_HEADER); this.json = config.getBoolean(Keys.FORWARD_JSON); + Integer queueSize = (config.getInteger(Keys.FORWARD_QUEUE_SIZE, 0)); this.queueSize = (queueSize > 0) ? queueSize : 0; + + Integer queueConcurrency = (config.getInteger(Keys.FORWARD_QUEUE_CONCURRENCY, 1)); + this.queueConcurrency = (queueConcurrency > 0) ? queueConcurrency : 1; + if (this.queueSize > 0) { this.positionsQueue = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(this.queueSize)); } - this.sendInProgress = new AtomicBoolean(false); + + this.pendingRequests = new AtomicInteger(0); } private static String formatSentence(Position position) { @@ -177,80 +183,105 @@ public class WebDataHandler extends BaseDataHandler { return request; } - protected void sendPosition(Position position) { - String url; - if (json) { - url = this.url; - } else { - try { - url = formatRequest(position); - } catch (UnsupportedEncodingException | JsonProcessingException e) { - throw new RuntimeException("Forwarding formatting error", e); + @Override + protected Position handlePosition(Position position) { + + class AsyncRequestAndCallback implements InvocationCallback { + + private Map jsonPayload; + private Invocation.Builder requestBuilder; + + AsyncRequestAndCallback(Position position) { + + String formattedUrl; + try { + formattedUrl = (json) ? url : formatRequest(position); + } catch (UnsupportedEncodingException | JsonProcessingException e) { + throw new RuntimeException("Forwarding formatting error", e); + } + + requestBuilder = client.target(formattedUrl).request(); + if (header != null && !header.isEmpty()) { + for (String line: header.split("\\r?\\n")) { + String[] values = line.split(":", 2); + requestBuilder.header(values[0].trim(), values[1].trim()); + } + } + + if (json) { + jsonPayload = prepareJsonPayload(position); + } + + pendingRequests.incrementAndGet(); + + send(); } - } - if (!json || requestBuilder == null) { - requestBuilder = client.target(url).request(); - if (header != null && !header.isEmpty()) { - for (String line: header.split("\\r?\\n")) { - String[] values = line.split(":", 2); - requestBuilder.header(values[0].trim(), values[1].trim()); + private void send() { + if (json) { + requestBuilder.async().post(Entity.json(jsonPayload), this); + } else { + requestBuilder.async().get(this); + } + } + + private void retry() { + try { + Thread.sleep(1000); + send(); + } catch (Exception e) { + } + } + + private void next() { + if (!positionsQueue.isEmpty()) { + new AsyncRequestAndCallback((Position) positionsQueue.remove()); } } - } - InvocationCallback callback = new InvocationCallback() { public void completed(Response response) { if (positionsQueue != null) { - if (response.getStatus() == 200) { - positionsQueue.remove(); + boolean ok = (response.getStatus() == 200); + boolean retry = (positionsQueue.size() < queueSize); + if (!ok && retry) { + retry(); + } else { + pendingRequests.decrementAndGet(); + while (!positionsQueue.isEmpty() && pendingRequests.get() < queueConcurrency) { + next(); + } } - logQueueStatus(); - sendInProgress.set(false); - sendQueuedPositions(); } } + public void failed(Throwable throwable) { if (positionsQueue != null) { - logQueueStatus(); - sendInProgress.set(false); - sendQueuedPositions(); + if (positionsQueue.size() < queueSize) { + retry(); + } else if (pendingRequests.decrementAndGet() == 0) { + next(); + } } } - }; - - if (json) { - requestBuilder.async().post(Entity.json(prepareJsonPayload(position)), callback); - } else { - requestBuilder.async().get(callback); - } - } - - protected void logQueueStatus() { - LOGGER.info(String.format("Position forwarding queue: %d/%d", - positionsQueue.size(), queueSize)); - } - protected void sendQueuedPositions() { - if (!positionsQueue.isEmpty() && !sendInProgress.get()) { - sendInProgress.set(true); - sendPosition((Position) positionsQueue.get()); } - } - @Override - protected Position handlePosition(Position position) { - - if (positionsQueue == null) { - sendPosition(position); + if (positionsQueue == null || pendingRequests.get() == 0) { + new AsyncRequestAndCallback(position); } else { positionsQueue.add(position); - sendQueuedPositions(); } + logQueueStatus(); + return position; } + private void logQueueStatus() { + LOGGER.info(String.format("Position forwarding queue: %d/%d/%d", + pendingRequests.get(), positionsQueue.size(), queueSize)); + } + private Map prepareJsonPayload(Position position) { Map data = new HashMap<>(); diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 10eda01e2..6102f7604 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -107,6 +107,13 @@ public final class Keys { public static final ConfigKey FORWARD_QUEUE_SIZE = new ConfigKey( "forward.queue.size", Integer.class); + /** + * Position forwarding queue concurrency. Defines how many HTTP requests can be pending at any time. + * If queueing is enabled, and this value is less than one, it's ignored and forced to be one. + */ + public static final ConfigKey FORWARD_QUEUE_CONCURRENCY = new ConfigKey( + "forward.queue.concurrency", Integer.class); + /** * Boolean flag to enable or disable position filtering. */ -- cgit v1.2.3 From 229c042edf74979d5893c047d2b5de7fd8cc8df0 Mon Sep 17 00:00:00 2001 From: Edward Valley Date: Sun, 1 Dec 2019 16:33:08 -0500 Subject: Implement wait and retry logic --- src/main/java/org/traccar/WebDataHandler.java | 102 +++++++++++--------------- src/main/java/org/traccar/config/Keys.java | 34 +++++++-- 2 files changed, 68 insertions(+), 68 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index dfd6f0e5b..19c5a58a8 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -43,21 +43,12 @@ import java.util.Locale; import java.util.TimeZone; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.commons.collections.Buffer; -import org.apache.commons.collections.BufferUtils; -import org.apache.commons.collections.buffer.CircularFifoBuffer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - @ChannelHandler.Sharable public class WebDataHandler extends BaseDataHandler { private static final String KEY_POSITION = "position"; private static final String KEY_DEVICE = "device"; - private static final Logger LOGGER = LoggerFactory.getLogger(WebDataHandler.class); - private final IdentityManager identityManager; private final ObjectMapper objectMapper; private final Client client; @@ -66,11 +57,13 @@ public class WebDataHandler extends BaseDataHandler { private final String header; private final boolean json; - private final Integer queueSize; - private final Integer queueConcurrency; + private final Boolean retryEnabled; + private final Integer retryDelayMin; + private final Integer retryDelayMax; + private final Integer deliveryPendingLimit; - private Buffer positionsQueue = null; - private AtomicInteger pendingRequests; + private AtomicInteger deliveryFaliuresInRow; + private AtomicInteger deliveryPendingCurrent; @Inject public WebDataHandler( @@ -83,17 +76,19 @@ public class WebDataHandler extends BaseDataHandler { this.header = config.getString(Keys.FORWARD_HEADER); this.json = config.getBoolean(Keys.FORWARD_JSON); - Integer queueSize = (config.getInteger(Keys.FORWARD_QUEUE_SIZE, 0)); - this.queueSize = (queueSize > 0) ? queueSize : 0; + this.retryEnabled = config.getBoolean(Keys.FORWARD_RETRY_ENABLE); - Integer queueConcurrency = (config.getInteger(Keys.FORWARD_QUEUE_CONCURRENCY, 1)); - this.queueConcurrency = (queueConcurrency > 0) ? queueConcurrency : 1; + Integer retryDelayMin = config.getInteger(Keys.FORWARD_RETRY_DELAY_MIN, 1); + this.retryDelayMin = (retryDelayMin > 0 && retryDelayMin < 3600) ? retryDelayMin : 1; - if (this.queueSize > 0) { - this.positionsQueue = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(this.queueSize)); - } + Integer retryDelayMax = config.getInteger(Keys.FORWARD_RETRY_DELAY_MAX, 10); + this.retryDelayMax = (retryDelayMax > retryDelayMin && retryDelayMax < 3600) ? retryDelayMax : retryDelayMin; + + Integer deliveryPendingLimit = config.getInteger(Keys.FORWARD_RETRY_PENDING_LIMIT, 100); + this.deliveryPendingLimit = (retryDelayMax > 0) ? deliveryPendingLimit : 100; - this.pendingRequests = new AtomicInteger(0); + this.deliveryFaliuresInRow = new AtomicInteger(0); + this.deliveryPendingCurrent = new AtomicInteger(0); } private static String formatSentence(Position position) { @@ -188,6 +183,7 @@ public class WebDataHandler extends BaseDataHandler { class AsyncRequestAndCallback implements InvocationCallback { + private Integer delay = retryDelayMin; private Map jsonPayload; private Invocation.Builder requestBuilder; @@ -212,7 +208,7 @@ public class WebDataHandler extends BaseDataHandler { jsonPayload = prepareJsonPayload(position); } - pendingRequests.incrementAndGet(); + deliveryPendingCurrent.incrementAndGet(); send(); } @@ -227,61 +223,47 @@ public class WebDataHandler extends BaseDataHandler { private void retry() { try { - Thread.sleep(1000); - send(); + deliveryFaliuresInRow.incrementAndGet(); + if (!retryEnabled || deliveryPendingCurrent.get() > deliveryPendingLimit) { + deliveryPendingCurrent.decrementAndGet(); + } else { + Integer i = 0; + for ( ; i < delay; i++) { + Thread.sleep(1000); + if (deliveryFaliuresInRow.get() == 0) { + delay = retryDelayMin; + break; + } + } + if (i >= delay && delay < retryDelayMax) { + delay++; + } + send(); + } } catch (Exception e) { } } - private void next() { - if (!positionsQueue.isEmpty()) { - new AsyncRequestAndCallback((Position) positionsQueue.remove()); - } - } - public void completed(Response response) { - if (positionsQueue != null) { - boolean ok = (response.getStatus() == 200); - boolean retry = (positionsQueue.size() < queueSize); - if (!ok && retry) { - retry(); - } else { - pendingRequests.decrementAndGet(); - while (!positionsQueue.isEmpty() && pendingRequests.get() < queueConcurrency) { - next(); - } - } + if (response.getStatus() == 200) { + deliveryFaliuresInRow.set(0); + deliveryPendingCurrent.decrementAndGet(); + } else { + retry(); } } public void failed(Throwable throwable) { - if (positionsQueue != null) { - if (positionsQueue.size() < queueSize) { - retry(); - } else if (pendingRequests.decrementAndGet() == 0) { - next(); - } - } + retry(); } } - if (positionsQueue == null || pendingRequests.get() == 0) { - new AsyncRequestAndCallback(position); - } else { - positionsQueue.add(position); - } - - logQueueStatus(); + new AsyncRequestAndCallback(position); return position; } - private void logQueueStatus() { - LOGGER.info(String.format("Position forwarding queue: %d/%d/%d", - pendingRequests.get(), positionsQueue.size(), queueSize)); - } - private Map prepareJsonPayload(Position position) { Map data = new HashMap<>(); diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 6102f7604..029316142 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -101,18 +101,36 @@ public final class Keys { "forward.json", Boolean.class); /** - * Position forwarding queue size. A ring buffer of the specified size is used to queue positions. - * If negative, zero, or not specified, queueing is disabled. (Legacy behaviour) + * Position forwarding retrying enable. When enabled, additional attempts are made to deliver positions. + * If initial delivery fails, because of an unreachable server or an HTTP response different from '200 OK', + * the software waits for 'forward.retry.delay.min' seconds to retry delivery. On subsecuent failures, this + * delay is incremented by 1 second up to 'forward.retry.delay.max'. On successful delivery, the delay is reset + * to 'forward.retry.delay.min'. Pending positions to be delivered are limited to 'forward.retry.pending.limit'. + * If this limit is reached, positions are discarded before next retry. */ - public static final ConfigKey FORWARD_QUEUE_SIZE = new ConfigKey( - "forward.queue.size", Integer.class); + public static final ConfigKey FORWARD_RETRY_ENABLE = new ConfigKey( + "forward.retry.enable", Boolean.class); /** - * Position forwarding queue concurrency. Defines how many HTTP requests can be pending at any time. - * If queueing is enabled, and this value is less than one, it's ignored and forced to be one. + * Position forwarding retry minimum delay in seconds. + * Can be set to anything between 1 and 3600 seconds. Defaults to 1 second. */ - public static final ConfigKey FORWARD_QUEUE_CONCURRENCY = new ConfigKey( - "forward.queue.concurrency", Integer.class); + public static final ConfigKey FORWARD_RETRY_DELAY_MIN = new ConfigKey( + "forward.retry.delay.min", Integer.class); + + /** + * Position forwarding retry maximum delay in seconds. + * Can be set to anything between 1 and 3600 seconds. Defaults to 10 seconds. + */ + public static final ConfigKey FORWARD_RETRY_DELAY_MAX = new ConfigKey( + "forward.retry.delay.max", Integer.class); + + /** + * Position forwarding retry pending limit. + * Can be set to anything greater than 0. Defaults to 100 positions. + */ + public static final ConfigKey FORWARD_RETRY_PENDING_LIMIT = new ConfigKey( + "forward.retry.pending.limit", Integer.class); /** * Boolean flag to enable or disable position filtering. -- cgit v1.2.3 From 628a80f49f286dcb51034c0e5fbc2f59fe295a08 Mon Sep 17 00:00:00 2001 From: Edward Valley Date: Sun, 1 Dec 2019 16:39:21 -0500 Subject: Fix orthographic typo. --- src/main/java/org/traccar/config/Keys.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 029316142..ec4eb1801 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -103,7 +103,7 @@ public final class Keys { /** * Position forwarding retrying enable. When enabled, additional attempts are made to deliver positions. * If initial delivery fails, because of an unreachable server or an HTTP response different from '200 OK', - * the software waits for 'forward.retry.delay.min' seconds to retry delivery. On subsecuent failures, this + * the software waits for 'forward.retry.delay.min' seconds to retry delivery. On subsequent failures, this * delay is incremented by 1 second up to 'forward.retry.delay.max'. On successful delivery, the delay is reset * to 'forward.retry.delay.min'. Pending positions to be delivered are limited to 'forward.retry.pending.limit'. * If this limit is reached, positions are discarded before next retry. -- cgit v1.2.3 From 0c40b37a389ae681152f320e47731ee3012f17eb Mon Sep 17 00:00:00 2001 From: jcardus Date: Tue, 21 Jan 2020 18:24:03 +0000 Subject: Here geocoder url config parameter (#4472) * here geocoder url config parameter * here geocoder url config parameter * added new parameter apiKey and kept app_code for retro compatibility added default url for here * fixed ident removed url from here geocode test * fixed ident intellij uses 2 spaces, this project uses 4. * fixed ident intellij uses 2 spaces, this project uses 4. * url should be null not "" * wrong file --- src/main/java/org/traccar/MainModule.java | 2 +- src/main/java/org/traccar/geocoder/HereGeocoder.java | 12 ++++++++---- src/test/java/org/traccar/geocoder/GeocoderTest.java | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index 9adea61b0..0957d9fe3 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -170,7 +170,7 @@ public class MainModule extends AbstractModule { case "ban": return new BanGeocoder(cacheSize, addressFormat); case "here": - return new HereGeocoder(id, key, language, cacheSize, addressFormat); + return new HereGeocoder(url, id, key, language, cacheSize, addressFormat); case "mapmyindia": return new MapmyIndiaGeocoder(url, key, cacheSize, addressFormat); default: diff --git a/src/main/java/org/traccar/geocoder/HereGeocoder.java b/src/main/java/org/traccar/geocoder/HereGeocoder.java index 756260b52..aaf11d74d 100644 --- a/src/main/java/org/traccar/geocoder/HereGeocoder.java +++ b/src/main/java/org/traccar/geocoder/HereGeocoder.java @@ -19,20 +19,24 @@ import javax.json.JsonObject; public class HereGeocoder extends JsonGeocoder { - private static String formatUrl(String id, String key, String language) { - String url = "https://reverse.geocoder.api.here.com/6.2/reversegeocode.json"; + private static String formatUrl(String url, String id, String key, String language) { + if (url == null) { + url = "https://reverse.geocoder.ls.hereapi.com/6.2/reversegeocode.json"; + } url += "?mode=retrieveAddresses&maxresults=1"; url += "&prox=%f,%f,0"; url += "&app_id=" + id; url += "&app_code=" + key; + url += "&apiKey=" + key; if (language != null) { url += "&language=" + language; } return url; } - public HereGeocoder(String id, String key, String language, int cacheSize, AddressFormat addressFormat) { - super(formatUrl(id, key, language), cacheSize, addressFormat); + public HereGeocoder( + String url, String id, String key, String language, int cacheSize, AddressFormat addressFormat) { + super(formatUrl(url, id, key, language), cacheSize, addressFormat); } @Override diff --git a/src/test/java/org/traccar/geocoder/GeocoderTest.java b/src/test/java/org/traccar/geocoder/GeocoderTest.java index 85d9bf62f..9f59d0b23 100644 --- a/src/test/java/org/traccar/geocoder/GeocoderTest.java +++ b/src/test/java/org/traccar/geocoder/GeocoderTest.java @@ -73,7 +73,7 @@ public class GeocoderTest { @Ignore @Test public void testHere() { - Geocoder geocoder = new HereGeocoder("", "", null, 0, new AddressFormat()); + Geocoder geocoder = new HereGeocoder(null, "", "", null, 0, new AddressFormat()); String address = geocoder.getAddress(48.8575, 2.2944, null); assertEquals("6 Avenue Gustave Eiffel, Paris, Île-de-France, FRA", address); } -- cgit v1.2.3 From 720916a476f25f12156cdd7e07cbee4f48d1b1ad Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 21 Jan 2020 22:46:34 -0800 Subject: Implement server response --- .../org/traccar/protocol/BlueProtocolDecoder.java | 33 ++++++++++++++++++++-- .../traccar/protocol/BlueProtocolDecoderTest.java | 3 ++ 2 files changed, 34 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/BlueProtocolDecoder.java b/src/main/java/org/traccar/protocol/BlueProtocolDecoder.java index 98a8ae565..61edcd101 100644 --- a/src/main/java/org/traccar/protocol/BlueProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/BlueProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2020 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. @@ -16,11 +16,14 @@ package org.traccar.protocol; import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; +import org.traccar.NetworkMessage; import org.traccar.Protocol; import org.traccar.helper.BitUtil; +import org.traccar.helper.Checksum; import org.traccar.helper.DateBuilder; import org.traccar.model.Position; @@ -41,6 +44,28 @@ public class BlueProtocolDecoder extends BaseProtocolDecoder { return negative ? -coordinate : coordinate; } + private void sendResponse(Channel channel, int deviceIndex) { + if (channel != null) { + + ByteBuf response = Unpooled.buffer(); + response.writeByte(0xaa); + response.writeShort(2 + 1 + 1 + 6 + 1); + response.writeByte(0x86); // version + response.writeByte(0); + + response.writeByte(6); // data length + response.writeByte(0xa4); // type + response.writeByte(0); // server index + response.writeByte(deviceIndex); + response.writeByte(0); + response.writeByte(0); + + response.writeByte(Checksum.xor(response.nioBuffer(1, response.writerIndex() - 1))); + + channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -66,7 +91,7 @@ public class BlueProtocolDecoder extends BaseProtocolDecoder { int frameEnd = buf.readerIndex() + buf.readUnsignedByte(); int type = buf.readUnsignedByte(); - buf.readUnsignedByte(); // reference id + int index = buf.readUnsignedByte(); buf.readUnsignedByte(); buf.readUnsignedByte(); // flags @@ -102,6 +127,10 @@ public class BlueProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // status 5 buf.readUnsignedByte(); // status 6 + } else if (type == 0x84) { + + sendResponse(channel, index); + } buf.readerIndex(frameEnd); diff --git a/src/test/java/org/traccar/protocol/BlueProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/BlueProtocolDecoderTest.java index 1d1716238..9f3254824 100644 --- a/src/test/java/org/traccar/protocol/BlueProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/BlueProtocolDecoderTest.java @@ -10,6 +10,9 @@ public class BlueProtocolDecoderTest extends ProtocolTest { BlueProtocolDecoder decoder = new BlueProtocolDecoder(null); + verifyPosition(decoder, binary( + "aa00550000813f6f840b840380001032000000002001030040008005ee1938113b26f300000000000000140114082833044d27602112030002000000b70000020000000000000000650000001601f4000000000000e4")); + verifyPosition(decoder, binary( "aa0055860080e3e79e0b840f800010320000000020010f0040008005ee197f113b26e800000000000000130c11091a2b005ac7a621120f0002000000b7000002000000000000001a3a0000000001f40000000000003f")); -- cgit v1.2.3 From cdbb912a1552d2e8eb6590dbffb6799ee187b50b Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 22 Jan 2020 08:41:12 -0800 Subject: Fix frame decoder --- src/main/java/org/traccar/protocol/BlueProtocol.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/BlueProtocol.java b/src/main/java/org/traccar/protocol/BlueProtocol.java index 79f0714ec..d5dc5c421 100644 --- a/src/main/java/org/traccar/protocol/BlueProtocol.java +++ b/src/main/java/org/traccar/protocol/BlueProtocol.java @@ -26,7 +26,7 @@ public class BlueProtocol extends BaseProtocol { addServer(new TrackerServer(false, getName()) { @Override protected void addProtocolHandlers(PipelineBuilder pipeline) { - pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 1, 2, 3, 0)); + pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 1, 2, -2, 0)); pipeline.addLast(new BlueProtocolDecoder(BlueProtocol.this)); } }); -- cgit v1.2.3 From eb2697434dbbb8c12cad26df94e3a367880ac4db Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 22 Jan 2020 23:52:41 -0800 Subject: Fix frame decoding issues --- src/main/java/org/traccar/protocol/OmnicommFrameDecoder.java | 4 ++-- src/test/java/org/traccar/protocol/OmnicommFrameDecoderTest.java | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/OmnicommFrameDecoder.java b/src/main/java/org/traccar/protocol/OmnicommFrameDecoder.java index 1caf6ceb9..314f19757 100644 --- a/src/main/java/org/traccar/protocol/OmnicommFrameDecoder.java +++ b/src/main/java/org/traccar/protocol/OmnicommFrameDecoder.java @@ -27,11 +27,11 @@ public class OmnicommFrameDecoder extends BaseFrameDecoder { protected Object decode( ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { - if (buf.readableBytes() < 10) { + if (buf.readableBytes() < 6) { return null; } - int endIndex = buf.getUnsignedShortLE(2) + buf.readerIndex() + 6; + int endIndex = buf.getUnsignedShortLE(buf.readerIndex() + 2) + buf.readerIndex() + 6; if (buf.writerIndex() < endIndex) { return null; } diff --git a/src/test/java/org/traccar/protocol/OmnicommFrameDecoderTest.java b/src/test/java/org/traccar/protocol/OmnicommFrameDecoderTest.java index 06c6e24eb..ae21de107 100644 --- a/src/test/java/org/traccar/protocol/OmnicommFrameDecoderTest.java +++ b/src/test/java/org/traccar/protocol/OmnicommFrameDecoderTest.java @@ -10,6 +10,10 @@ public class OmnicommFrameDecoderTest extends ProtocolTest { OmnicommFrameDecoder decoder = new OmnicommFrameDecoder(); + verifyFrame( + binary("c08600004566"), + decoder.decode(null, null, binary("c08600004566"))); + verifyFrame( binary("c080080061a61915340100001dec"), decoder.decode(null, null, binary("c080080061a61915340100001dec"))); -- cgit v1.2.3 From 1117d4abe4fe3545f9169b05269363c9655061b1 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 23 Jan 2020 08:49:30 -0800 Subject: Fix logging issue (fix #4473) --- .../java/org/traccar/helper/ServletHelper.java | 26 ++++++++++++++++++---- .../java/org/traccar/helper/ServletHelperTest.java | 13 +++++++++-- 2 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/helper/ServletHelper.java b/src/main/java/org/traccar/helper/ServletHelper.java index e3481e249..b6c587ec3 100644 --- a/src/main/java/org/traccar/helper/ServletHelper.java +++ b/src/main/java/org/traccar/helper/ServletHelper.java @@ -1,8 +1,22 @@ +/* + * Copyright 2020 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.helper; import javax.servlet.http.HttpServletRequest; - public final class ServletHelper { private ServletHelper() { @@ -14,10 +28,14 @@ public final class ServletHelper { String remoteAddress = request.getHeader("X-FORWARDED-FOR"); if (remoteAddress != null && !remoteAddress.isEmpty()) { - return remoteAddress.substring(0, remoteAddress.indexOf(",")); // removes the additional data + int separatorIndex = remoteAddress.indexOf(","); + if (separatorIndex > 0) { + return remoteAddress.substring(0, separatorIndex); // remove the additional data + } else { + return remoteAddress; + } } else { - remoteAddress = request.getRemoteAddr(); - return remoteAddress; + return request.getRemoteAddr(); } } else { return null; diff --git a/src/test/java/org/traccar/helper/ServletHelperTest.java b/src/test/java/org/traccar/helper/ServletHelperTest.java index 7359bf3dd..e419b6491 100644 --- a/src/test/java/org/traccar/helper/ServletHelperTest.java +++ b/src/test/java/org/traccar/helper/ServletHelperTest.java @@ -11,7 +11,7 @@ import static org.junit.Assert.assertEquals; public class ServletHelperTest { @Test - public void testIpBehindReverseProxy() { + public void testRetrieveRemoteAddressProxyMultiple() { MockRequest request = new MockRequest(); request.setRemoteAddress("147.120.1.5"); request.addHeader("X-FORWARDED-FOR", "231.23.45.65, 10.20.10.33, 10.20.20.34"); @@ -20,7 +20,16 @@ public class ServletHelperTest { } @Test - public void testNormalIp() { + public void testRetrieveRemoteAddressProxySingle() { + MockRequest request = new MockRequest(); + request.setRemoteAddress("147.120.1.5"); + request.addHeader("X-FORWARDED-FOR", "231.23.45.65"); + + assertEquals("231.23.45.65", ServletHelper.retrieveRemoteAddress(request)); + } + + @Test + public void testRetrieveRemoteAddressNoProxy() { MockRequest request = new MockRequest(); request.setRemoteAddress("231.23.45.65"); -- cgit v1.2.3 From e7866cd4bd5a4552f0d562671ce6a713d18824b8 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 24 Jan 2020 19:49:23 -0800 Subject: Support VT600 and VT900 --- src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java | 4 ++-- src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java index cbfc3660a..bd66cdc4b 100644 --- a/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2012 - 2020 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. @@ -47,7 +47,7 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { } private static final Pattern PATTERN = new PatternBuilder() - .number("(dd)(dd)(dd).?d*,") // time (hhmmss) + .number("(d+)(dd)(dd).?d*,") // time (hhmmss) .expression("([AV]),") // validity .number("(d+)(dd.d+),") // latitude .expression("([NS]),") diff --git a/src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java index da5a81144..94f4c8202 100644 --- a/src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java @@ -10,6 +10,12 @@ public class MeiligaoProtocolDecoderTest extends ProtocolTest { MeiligaoProtocolDecoder decoder = new MeiligaoProtocolDecoder(null); + verifyPosition(decoder, binary( + "2424011e143190975469ff99993130343634382e3030302c562c303735332e353338332c4e2c30393832322e313737382c452c302e30302c302c3230303132302c2c2a31417c302e307c307c363430307c303030302c303030302c303130312c303238467c30323038303030353137444630304633363838467c30387c30303030314242367c30307c2520205e59454e53414241494348414924534f4e474b52414e244d522e5e5e3f3b363030373634333130303530303337333835333d3135303531393637303631343d3f2b2020202020202020202020202032342020202020202020202020203120202020202020202020202030303034313131202030303130302020202020202020202020202020202020202020203f7b850d0a")); + + verifyPosition(decoder, binary( + "2424008d143190975469ff99993130343634312e3030302c562c303735332e353338332c4e2c30393832322e313737382c452c302e30302c302c3230303132302c2c2a31337c302e307c307c323430307c303030302c303030302c303130302c303238397c30323038303030353137444630304633363838467c30387c30303030314242367c3030be980d0a")); + verifyNull(decoder, binary( "24240012254748594772ff080002ffff0d0a")); -- cgit v1.2.3 From f4134fb1a1749e4556b6fdcfd539d4e8a78a2e93 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 24 Jan 2020 21:29:46 -0800 Subject: Support engine data --- .../protocol/PacificTrackProtocolDecoder.java | 54 ++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/PacificTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/PacificTrackProtocolDecoder.java index 15e08d7b1..d49a73a86 100644 --- a/src/main/java/org/traccar/protocol/PacificTrackProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/PacificTrackProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2020 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. @@ -63,7 +63,7 @@ public class PacificTrackProtocolDecoder extends BaseProtocolDecoder { while (buf.isReadable()) { int segmentId = readBitExt(buf); - int segmentLength = readBitExt(buf); + int segmentEnd = readBitExt(buf) + buf.readerIndex(); switch (segmentId) { case 0x01: @@ -83,12 +83,60 @@ public class PacificTrackProtocolDecoder extends BaseProtocolDecoder { position.setSpeed(UnitsConverter.knotsFromKph(BitUtil.to(speedAndCourse, 12) * 0.1)); position.set(Position.KEY_INDEX, buf.readUnsignedShort()); break; + case 0x92: + while (buf.readerIndex() < segmentEnd) { + int field = buf.readUnsignedByte(); + int fieldPrefix = BitUtil.from(field, 5); + if (fieldPrefix < 0b100) { + switch (BitUtil.between(field, 2, 5)) { + case 0b000: + position.set("bus", BitUtil.to(field, 2)); + case 0b001: + position.set("currentGear", BitUtil.to(field, 2)); + break; + default: + break; + } + } else if (fieldPrefix < 0b101) { + switch (BitUtil.to(field, 5)) { + case 0b00000: + position.set(Position.KEY_OBD_SPEED, buf.readUnsignedByte()); + break; + case 0b00001: + position.set(Position.KEY_RPM, buf.readUnsignedByte() * 32); + break; + default: + buf.readUnsignedByte(); + break; + } + } else if (fieldPrefix < 0b110) { + buf.readUnsignedShort(); + } else if (fieldPrefix < 0b111) { + switch (BitUtil.to(field, 5)) { + case 0b00000: + position.set(Position.KEY_ODOMETER, buf.readUnsignedInt() * 100); + break; + case 0b00001: + position.set(Position.KEY_HOURS, buf.readUnsignedInt() * 180); + break; + case 0b00010: + position.set("idleHours", buf.readUnsignedInt() * 180); + break; + default: + buf.readUnsignedInt(); + break; + } + } else { + buf.skipBytes(buf.readUnsignedByte()); + } + } + break; case 0x100: String imei = ByteBufUtil.hexDump(buf.readSlice(8)).substring(0, 15); deviceSession = getDeviceSession(channel, remoteAddress, imei); break; default: - buf.skipBytes(segmentLength); + buf.readerIndex(segmentEnd); break; } } -- cgit v1.2.3 From a9855cd2df5e364c66bb419eb0ab7fb4d66f2643 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 24 Jan 2020 21:32:41 -0800 Subject: Decode fuel data --- src/main/java/org/traccar/protocol/BceProtocolDecoder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java index 30f9bb1f3..c71cdffd9 100644 --- a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java @@ -83,10 +83,10 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { buf.skipBytes(4); } if (BitUtil.check(mask, 12)) { - buf.skipBytes(2); + position.set("fuel1", buf.readUnsignedShort()); } if (BitUtil.check(mask, 13)) { - buf.skipBytes(2); + position.set("fuel2", buf.readUnsignedShort()); } if (BitUtil.check(mask, 14)) { -- cgit v1.2.3 From c8198d40db6e623ee45eff121cdf8cfaa2d58281 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 25 Jan 2020 09:47:45 -0800 Subject: Support driver license --- src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java | 8 ++++++++ src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java | 3 +++ 2 files changed, 11 insertions(+) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java index c435b6cec..946652b03 100644 --- a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java @@ -730,6 +730,14 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { decodeStatus(position, buf); } + if (type == MSG_GPS_LBS_1 && buf.readableBytes() > 75 + 6) { + position.set(Position.KEY_ODOMETER, buf.readUnsignedInt()); + String data = buf.readCharSequence(buf.readUnsignedByte(), StandardCharsets.US_ASCII).toString(); + buf.readUnsignedByte(); // alarm + buf.readUnsignedByte(); // swiped + position.set("driverLicense", data.trim()); + } + if (type == MSG_GPS_LBS_1 && buf.readableBytes() == 2 + 6) { int mask = buf.readUnsignedShort(); position.set(Position.KEY_IGNITION, BitUtil.check(mask, 8 + 7)); diff --git a/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java index fd5d55a50..672711f22 100644 --- a/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java @@ -17,6 +17,9 @@ public class Gt06ProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, binary( "78780D01086471700328358100093F040D0A")); + verifyAttributes(decoder, binary( + "7878711213081f081d0fc6017ba3fa0ac62a923e550e02080503f300b26d000000004b20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202030300017c7470d0a")); + verifyAttributes(decoder, binary( "797900B2700000000102003500010400330012000000000000000000000000000000000000003400061354A48DFF00003400061154A48E56000011000A000000000000000000000001000803537601000282180002000802140743044211890003000A89340752000038689636001800020182002B000116002C000454A4FF350009000100000A0001010028000100002E000400000000002A00010000290004000000000030000A000101680014016802D00000B38F0D0A")); -- cgit v1.2.3 From 2d5a5e600e576cd4e31046be104cc98f799ad091 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 26 Jan 2020 21:24:14 -0800 Subject: Decode BLE location --- .../java/org/traccar/protocol/Minifinder2ProtocolDecoder.java | 9 +++++++++ .../org/traccar/protocol/Minifinder2ProtocolDecoderTest.java | 3 +++ 2 files changed, 12 insertions(+) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java index b6f257d2c..b8ab134c5 100644 --- a/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Minifinder2ProtocolDecoder.java @@ -154,6 +154,15 @@ public class Minifinder2ProtocolDecoder extends BaseProtocolDecoder { mac.substring(0, mac.length() - 1), rssi)); } break; + case 0x23: + if (endIndex > buf.readerIndex()) { + buf.skipBytes(6); // mac + } + if (endIndex > buf.readerIndex()) { + position.setLatitude(buf.readIntLE() * 0.0000001); + position.setLongitude(buf.readIntLE() * 0.0000001); + } + break; case 0x24: position.setTime(new Date(buf.readUnsignedIntLE() * 1000)); long status = buf.readUnsignedIntLE(); diff --git a/src/test/java/org/traccar/protocol/Minifinder2ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Minifinder2ProtocolDecoderTest.java index c0ce67cb6..5898b74a8 100644 --- a/src/test/java/org/traccar/protocol/Minifinder2ProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/Minifinder2ProtocolDecoderTest.java @@ -13,6 +13,9 @@ public class Minifinder2ProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, binary( "ab10150076f1320003100133353534363530373130323933303602105a")); + verifyNotNull(decoder, binary( + "ab1024009b3f9742011001383635323039303336333430303235113154cfc95d0a00000080d0c95d0a000000")); + verifyPosition(decoder, binary( "ab103f007e2533000110013335353436353037313032393330360930e09d245d210100000924b49e245d01025b201620e6c03b1ef367420400000000aa026d00c90e0000100110")); -- cgit v1.2.3 From 7113e04b9a5cabb509ff0219da18098f4b55924f Mon Sep 17 00:00:00 2001 From: Edward Valley Date: Thu, 30 Jan 2020 03:49:55 -0500 Subject: Changes after review --- src/main/java/org/traccar/WebDataHandler.java | 69 +++++++++++++-------------- src/main/java/org/traccar/config/Keys.java | 9 ++-- 2 files changed, 36 insertions(+), 42 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index 19c5a58a8..2d6d98f5d 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -18,6 +18,9 @@ package org.traccar; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.netty.channel.ChannelHandler; +import io.netty.util.Timeout; +import io.netty.util.TimerTask; + import org.traccar.config.Config; import org.traccar.config.Keys; import org.traccar.database.IdentityManager; @@ -41,6 +44,7 @@ import java.util.Calendar; import java.util.Formatter; import java.util.Locale; import java.util.TimeZone; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @ChannelHandler.Sharable @@ -57,12 +61,11 @@ public class WebDataHandler extends BaseDataHandler { private final String header; private final boolean json; - private final Boolean retryEnabled; - private final Integer retryDelayMin; - private final Integer retryDelayMax; - private final Integer deliveryPendingLimit; + private final boolean retryEnabled; + private final int retryDelayMin; + private final int retryDelayMax; + private final int deliveryPendingLimit; - private AtomicInteger deliveryFaliuresInRow; private AtomicInteger deliveryPendingCurrent; @Inject @@ -77,17 +80,10 @@ public class WebDataHandler extends BaseDataHandler { this.json = config.getBoolean(Keys.FORWARD_JSON); this.retryEnabled = config.getBoolean(Keys.FORWARD_RETRY_ENABLE); + this.retryDelayMin = config.getInteger(Keys.FORWARD_RETRY_DELAY_MIN, 1); + this.retryDelayMax = config.getInteger(Keys.FORWARD_RETRY_DELAY_MAX, 10); + this.deliveryPendingLimit = config.getInteger(Keys.FORWARD_RETRY_PENDING_LIMIT, 100); - Integer retryDelayMin = config.getInteger(Keys.FORWARD_RETRY_DELAY_MIN, 1); - this.retryDelayMin = (retryDelayMin > 0 && retryDelayMin < 3600) ? retryDelayMin : 1; - - Integer retryDelayMax = config.getInteger(Keys.FORWARD_RETRY_DELAY_MAX, 10); - this.retryDelayMax = (retryDelayMax > retryDelayMin && retryDelayMax < 3600) ? retryDelayMax : retryDelayMin; - - Integer deliveryPendingLimit = config.getInteger(Keys.FORWARD_RETRY_PENDING_LIMIT, 100); - this.deliveryPendingLimit = (retryDelayMax > 0) ? deliveryPendingLimit : 100; - - this.deliveryFaliuresInRow = new AtomicInteger(0); this.deliveryPendingCurrent = new AtomicInteger(0); } @@ -183,15 +179,15 @@ public class WebDataHandler extends BaseDataHandler { class AsyncRequestAndCallback implements InvocationCallback { - private Integer delay = retryDelayMin; - private Map jsonPayload; + private int delay = retryDelayMin; + private Map payload; private Invocation.Builder requestBuilder; AsyncRequestAndCallback(Position position) { String formattedUrl; try { - formattedUrl = (json) ? url : formatRequest(position); + formattedUrl = json ? url : formatRequest(position); } catch (UnsupportedEncodingException | JsonProcessingException e) { throw new RuntimeException("Forwarding formatting error", e); } @@ -205,7 +201,7 @@ public class WebDataHandler extends BaseDataHandler { } if (json) { - jsonPayload = prepareJsonPayload(position); + payload = prepareJsonPayload(position); } deliveryPendingCurrent.incrementAndGet(); @@ -215,7 +211,7 @@ public class WebDataHandler extends BaseDataHandler { private void send() { if (json) { - requestBuilder.async().post(Entity.json(jsonPayload), this); + requestBuilder.async().post(Entity.json(payload), this); } else { requestBuilder.async().get(this); } @@ -223,36 +219,35 @@ public class WebDataHandler extends BaseDataHandler { private void retry() { try { - deliveryFaliuresInRow.incrementAndGet(); - if (!retryEnabled || deliveryPendingCurrent.get() > deliveryPendingLimit) { - deliveryPendingCurrent.decrementAndGet(); - } else { - Integer i = 0; - for ( ; i < delay; i++) { - Thread.sleep(1000); - if (deliveryFaliuresInRow.get() == 0) { - delay = retryDelayMin; - break; + if (retryEnabled && deliveryPendingCurrent.get() <= deliveryPendingLimit) { + GlobalTimer.getTimer().newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) { + if (!timeout.isCancelled()) { + if (delay < retryDelayMax) { + delay++; + } + send(); + } } - } - if (i >= delay && delay < retryDelayMax) { - delay++; - } - send(); + }, delay, TimeUnit.SECONDS); + return; } } catch (Exception e) { } + deliveryPendingCurrent.decrementAndGet(); } + @Override public void completed(Response response) { if (response.getStatus() == 200) { - deliveryFaliuresInRow.set(0); deliveryPendingCurrent.decrementAndGet(); } else { retry(); } } + @Override public void failed(Throwable throwable) { retry(); } diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index ec4eb1801..999a1d6df 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -104,23 +104,22 @@ public final class Keys { * Position forwarding retrying enable. When enabled, additional attempts are made to deliver positions. * If initial delivery fails, because of an unreachable server or an HTTP response different from '200 OK', * the software waits for 'forward.retry.delay.min' seconds to retry delivery. On subsequent failures, this - * delay is incremented by 1 second up to 'forward.retry.delay.max'. On successful delivery, the delay is reset - * to 'forward.retry.delay.min'. Pending positions to be delivered are limited to 'forward.retry.pending.limit'. - * If this limit is reached, positions are discarded before next retry. + * delay is incremented by 1 second up to 'forward.retry.delay.max'. Positions pending to be delivered + * are limited to 'forward.retry.pending.limit'. If this limit is reached, positions get discarded. */ public static final ConfigKey FORWARD_RETRY_ENABLE = new ConfigKey( "forward.retry.enable", Boolean.class); /** * Position forwarding retry minimum delay in seconds. - * Can be set to anything between 1 and 3600 seconds. Defaults to 1 second. + * Can be set to anything greater than 0. Defaults to 1 second. */ public static final ConfigKey FORWARD_RETRY_DELAY_MIN = new ConfigKey( "forward.retry.delay.min", Integer.class); /** * Position forwarding retry maximum delay in seconds. - * Can be set to anything between 1 and 3600 seconds. Defaults to 10 seconds. + * Can be set to anything greater than 0. Defaults to 10 seconds. */ public static final ConfigKey FORWARD_RETRY_DELAY_MAX = new ConfigKey( "forward.retry.delay.max", Integer.class); -- cgit v1.2.3 From 3c71ac47b4515fb799e67a18b18d722bea4d2241 Mon Sep 17 00:00:00 2001 From: Edward Valley Date: Thu, 30 Jan 2020 05:33:24 -0500 Subject: Log position forwarding failures --- src/main/java/org/traccar/WebDataHandler.java | 36 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index 2d6d98f5d..e2f7c1e8b 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -20,6 +20,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.netty.channel.ChannelHandler; import io.netty.util.Timeout; import io.netty.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.traccar.config.Config; import org.traccar.config.Keys; @@ -53,6 +55,8 @@ public class WebDataHandler extends BaseDataHandler { private static final String KEY_POSITION = "position"; private static final String KEY_DEVICE = "device"; + private static final Logger LOGGER = LoggerFactory.getLogger(WebDataHandler.class); + private final IdentityManager identityManager; private final ObjectMapper objectMapper; private final Client client; @@ -219,19 +223,29 @@ public class WebDataHandler extends BaseDataHandler { private void retry() { try { - if (retryEnabled && deliveryPendingCurrent.get() <= deliveryPendingLimit) { - GlobalTimer.getTimer().newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) { - if (!timeout.isCancelled()) { - if (delay < retryDelayMax) { - delay++; + String message = "Position forwarding failed."; + if (!retryEnabled) { + LOGGER.warn(message); + } else { + int pending = deliveryPendingCurrent.get(); + if (pending <= deliveryPendingLimit) { + LOGGER.warn(message + " Pending: " + pending + + ". Retrying in " + delay + " seconds."); + GlobalTimer.getTimer().newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) { + if (!timeout.isCancelled()) { + if (delay < retryDelayMax) { + delay++; + } + send(); } - send(); } - } - }, delay, TimeUnit.SECONDS); - return; + }, delay, TimeUnit.SECONDS); + return; + } + LOGGER.warn(message + " Pending: " + pending + + ". Delivery will not be retried."); } } catch (Exception e) { } -- cgit v1.2.3 From 3bf277a340c57c485af7f3c0ab46b27e070b0998 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 30 Jan 2020 22:16:59 -0800 Subject: Add new RST test case --- src/main/java/org/traccar/protocol/RstProtocolDecoder.java | 2 +- src/test/java/org/traccar/protocol/RstProtocolDecoderTest.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/RstProtocolDecoder.java b/src/main/java/org/traccar/protocol/RstProtocolDecoder.java index 8981c117b..05601ed51 100644 --- a/src/main/java/org/traccar/protocol/RstProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/RstProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2020 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. diff --git a/src/test/java/org/traccar/protocol/RstProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/RstProtocolDecoderTest.java index 66286776a..fb6dca3e6 100644 --- a/src/test/java/org/traccar/protocol/RstProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/RstProtocolDecoderTest.java @@ -11,6 +11,9 @@ public class RstProtocolDecoderTest extends ProtocolTest { RstProtocolDecoder decoder = new RstProtocolDecoder(null); + verifyPosition(decoder, text( + "RST;L;RST-MINIv2;V7.02;008068078;61;1;27-01-2020 21:36:33;27-01-2020 21:36:33;-16.696159;-49.284275;0;67;786;1;15;0;00;B0;00;19;06;12.42;4.16;79;20;FE;0000;01;E0;00800020;0;467;FIM;")); + verifyAttribute(decoder, text( "RST;A;RST-MINIv2;V7.00;008033985;1;7;30-08-2019 11:31:38;30-08-2019 11:31:15;-23.645868;-46.637741;0;226;828;0;10;0;00;20;00;1A;02;0.02;3.40;0;0;FE;0000;04;80;11;0;FIM;"), Position.KEY_BATTERY, 3.40); -- cgit v1.2.3 From c00fd59ecf8739e47a4f2460bbb4802f4cead1a1 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 30 Jan 2020 22:37:36 -0800 Subject: Decode cell towers info --- .../org/traccar/protocol/HuaShengProtocolDecoder.java | 16 +++++++++++++++- .../traccar/protocol/HuaShengProtocolDecoderTest.java | 3 +++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java index 9449e2d5c..920898039 100644 --- a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2020 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. @@ -25,6 +25,8 @@ import org.traccar.Protocol; import org.traccar.helper.BitUtil; import org.traccar.helper.DateBuilder; import org.traccar.helper.UnitsConverter; +import org.traccar.model.CellTower; +import org.traccar.model.Network; import org.traccar.model.Position; import java.net.SocketAddress; @@ -161,6 +163,18 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder { position.set( Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString()); break; + case 0x0020: + Network network = new Network(); + String[] cells = buf.readCharSequence( + length, StandardCharsets.US_ASCII).toString().split("\\+"); + for (String cell : cells) { + String[] values = cell.split("@"); + network.addCellTower(CellTower.from( + Integer.parseInt(values[0]), Integer.parseInt(values[1]), + Integer.parseInt(values[2], 16), Integer.parseInt(values[3], 16))); + } + position.setNetwork(network); + break; default: buf.skipBytes(length); break; diff --git a/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java index 6033bc744..b624f69ab 100644 --- a/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java @@ -16,6 +16,9 @@ public class HuaShengProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, binary( "c000000077aa0200000000000e000100143347315f48312e315f56312e30372e54000300133335353835353035303434303635380004000b3531323030303000050005010006000400070004000800050000090018383936313032353431343533333239313833360d000a000f796573696e7465726e6574c0")); + verifyNotNull(decoder, binary( + "c000000077aa00000000000070020000003230303132373035313635330000000000000000000000000000000000010015ffffffff000000000000019dffffffffff0005000a1f00000e455a00200019313238354031406666666540386233663930634030000f0013333536373236313038313335343530c0")); + verifyPosition(decoder, binary( "c000000060aa000000000000fa8000000031393037303431363434323700e9900affd61c1b00000000003a000000010015ffffff0000000000000004c2ffffffffff0005000a0d080000ca6a000900155741555a5a5a344730454e313133373233c0")); -- cgit v1.2.3 From fdf16e5ee51cf7537920d04e1fd4bffbdbd5fa42 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 31 Jan 2020 22:53:51 -0800 Subject: Respond with original length --- .../java/org/traccar/protocol/TopinProtocolDecoder.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java b/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java index ea72b7cb8..0f22bc7fd 100644 --- a/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2020 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. @@ -44,11 +44,11 @@ public class TopinProtocolDecoder extends BaseProtocolDecoder { public static final int MSG_WIFI_OFFLINE = 0x17; public static final int MSG_WIFI = 0x69; - private void sendResponse(Channel channel, int type, ByteBuf content) { + private void sendResponse(Channel channel, int length, int type, ByteBuf content) { if (channel != null) { ByteBuf response = Unpooled.buffer(); response.writeShort(0x7878); - response.writeByte(1 + content.readableBytes()); + response.writeByte(length); response.writeByte(type); response.writeBytes(content); response.writeByte('\r'); @@ -75,7 +75,7 @@ public class TopinProtocolDecoder extends BaseProtocolDecoder { deviceSession = getDeviceSession(channel, remoteAddress, imei); ByteBuf content = Unpooled.buffer(); content.writeByte(deviceSession != null ? 0x01 : 0x44); - sendResponse(channel, type, content); + sendResponse(channel, length, type, content); return null; } else { deviceSession = getDeviceSession(channel, remoteAddress); @@ -95,7 +95,7 @@ public class TopinProtocolDecoder extends BaseProtocolDecoder { ByteBuf content = Unpooled.buffer(); content.writeBytes(time); - sendResponse(channel, type, content); + sendResponse(channel, length, type, content); return position; @@ -127,7 +127,7 @@ public class TopinProtocolDecoder extends BaseProtocolDecoder { if (length >= 7) { content.writeByte(signal); } - sendResponse(channel, type, content); + sendResponse(channel, length, type, content); return position; @@ -160,7 +160,7 @@ public class TopinProtocolDecoder extends BaseProtocolDecoder { ByteBuf content = Unpooled.buffer(); content.writeBytes(time); - sendResponse(channel, type, content); + sendResponse(channel, length, type, content); return position; -- cgit v1.2.3 From 230227fde27da2db785d97c6894160b256ad6c10 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 1 Feb 2020 21:35:24 -0800 Subject: Decode device time --- .../java/org/traccar/protocol/TopinProtocolDecoder.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java b/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java index 0f22bc7fd..eee0e9ae8 100644 --- a/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TopinProtocolDecoder.java @@ -23,6 +23,8 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; import org.traccar.NetworkMessage; import org.traccar.Protocol; +import org.traccar.helper.BcdUtil; +import org.traccar.helper.DateBuilder; import org.traccar.model.CellTower; import org.traccar.model.Network; import org.traccar.model.Position; @@ -136,9 +138,17 @@ public class TopinProtocolDecoder extends BaseProtocolDecoder { Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); - getLastLocation(position, null); - ByteBuf time = buf.readSlice(6); + DateBuilder dateBuilder = new DateBuilder() + .setYear(BcdUtil.readInteger(time, 2)) + .setMonth(BcdUtil.readInteger(time, 2)) + .setDay(BcdUtil.readInteger(time, 2)) + .setHour(BcdUtil.readInteger(time, 2)) + .setMinute(BcdUtil.readInteger(time, 2)) + .setSecond(BcdUtil.readInteger(time, 2)); + time.resetReaderIndex(); + + getLastLocation(position, dateBuilder.getDate()); Network network = new Network(); for (int i = 0; i < length; i++) { -- cgit v1.2.3 From 75e5eded6c877577044e9db22cae255cac8d04a1 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Feb 2020 15:07:56 -0800 Subject: Move files to new locations --- .../handler/protocol/Arnavi4FrameDecoder.java | 74 --------- .../traccar/handler/protocol/Arnavi4Protocol.java | 45 ----- .../handler/protocol/Arnavi4ProtocolDecoder.java | 182 --------------------- .../org/traccar/protocol/Arnavi4FrameDecoder.java | 74 +++++++++ .../java/org/traccar/protocol/Arnavi4Protocol.java | 45 +++++ .../traccar/protocol/Arnavi4ProtocolDecoder.java | 182 +++++++++++++++++++++ .../handler/protocol/Arnavi4FrameDecoderTest.java | 50 ------ .../protocol/Arnavi4ProtocolDecoderTest.java | 40 ----- .../traccar/protocol/Arnavi4FrameDecoderTest.java | 50 ++++++ .../protocol/Arnavi4ProtocolDecoderTest.java | 40 +++++ 10 files changed, 391 insertions(+), 391 deletions(-) delete mode 100644 src/main/java/org/traccar/handler/protocol/Arnavi4FrameDecoder.java delete mode 100644 src/main/java/org/traccar/handler/protocol/Arnavi4Protocol.java delete mode 100644 src/main/java/org/traccar/handler/protocol/Arnavi4ProtocolDecoder.java create mode 100644 src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java create mode 100644 src/main/java/org/traccar/protocol/Arnavi4Protocol.java create mode 100644 src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java delete mode 100644 src/test/java/org/traccar/handler/protocol/Arnavi4FrameDecoderTest.java delete mode 100644 src/test/java/org/traccar/handler/protocol/Arnavi4ProtocolDecoderTest.java create mode 100644 src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java create mode 100644 src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/handler/protocol/Arnavi4FrameDecoder.java b/src/main/java/org/traccar/handler/protocol/Arnavi4FrameDecoder.java deleted file mode 100644 index b13f3fd7d..000000000 --- a/src/main/java/org/traccar/handler/protocol/Arnavi4FrameDecoder.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017 Ivan Muratov (binakot@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 Arnavi4FrameDecoder extends FrameDecoder { - - private static final int MIN_LENGTH = 4; - private static final int HEADER_LENGTH = 10; - private static final int PACKET_WRAPPER_LENGTH = 8; - private static final int COMMAND_ANSWER_PACKET_LENGTH = 4; - private static final int COMMAND_ANSWER_PARCEL_NUMBER = 0xfd; - private static final byte PACKAGE_END_SIGN = 0x5d; - - private boolean firstPacket = true; - - @Override - protected Object decode( - ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - - if (buf.readableBytes() < MIN_LENGTH) { - return null; - } - - int length; - if (firstPacket) { - firstPacket = false; - length = HEADER_LENGTH; - } else { - int index = buf.getUnsignedByte(1); // parcel number - if (index == COMMAND_ANSWER_PARCEL_NUMBER) { - length = COMMAND_ANSWER_PACKET_LENGTH; - } else { - int pos = 2; // start sign + parcel number - while (pos + PACKET_WRAPPER_LENGTH < buf.readableBytes() - && buf.getByte(pos) != PACKAGE_END_SIGN) { - - int dataLength = buf.getUnsignedShort(pos + 1); - pos += PACKET_WRAPPER_LENGTH + dataLength; // packet type + data length + unixtime + data + crc - } - - if (buf.getByte(pos) != PACKAGE_END_SIGN) { // end sign - return null; - } - - length = pos + 1; - } - } - - if (buf.readableBytes() >= length) { - return buf.readBytes(length); - } - - return null; - } - -} diff --git a/src/main/java/org/traccar/handler/protocol/Arnavi4Protocol.java b/src/main/java/org/traccar/handler/protocol/Arnavi4Protocol.java deleted file mode 100644 index 381a9b457..000000000 --- a/src/main/java/org/traccar/handler/protocol/Arnavi4Protocol.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2017 Ivan Muratov (binakot@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.traccar.BaseProtocol; -import org.traccar.TrackerServer; - -import java.nio.ByteOrder; -import java.util.List; - -public class Arnavi4Protocol extends BaseProtocol { - - public Arnavi4Protocol() { - super("arnavi4"); - } - - @Override - public void initTrackerServers(List serverList) { - TrackerServer server = new TrackerServer(new ServerBootstrap(), getName()) { - @Override - protected void addSpecificHandlers(ChannelPipeline pipeline) { - pipeline.addLast("frameDecoder", new Arnavi4FrameDecoder()); - pipeline.addLast("objectDecoder", new Arnavi4ProtocolDecoder(Arnavi4Protocol.this)); - } - }; - server.setEndianness(ByteOrder.LITTLE_ENDIAN); - serverList.add(server); - } - -} diff --git a/src/main/java/org/traccar/handler/protocol/Arnavi4ProtocolDecoder.java b/src/main/java/org/traccar/handler/protocol/Arnavi4ProtocolDecoder.java deleted file mode 100644 index 06abb563f..000000000 --- a/src/main/java/org/traccar/handler/protocol/Arnavi4ProtocolDecoder.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2017 Ivan Muratov (binakot@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.Checksum; -import org.traccar.model.Position; - -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { - - private static final byte HEADER_START_SIGN = (byte) 0xff; - private static final byte HEADER_VERSION_1 = 0x22; - private static final byte HEADER_VERSION_2 = 0x23; - - private static final byte RECORD_PING = 0x00; - private static final byte RECORD_DATA = 0x01; - private static final byte RECORD_TEXT = 0x03; - private static final byte RECORD_FILE = 0x04; - private static final byte RECORD_BINARY = 0x06; - - private static final byte TAG_LATITUDE = 3; - private static final byte TAG_LONGITUDE = 4; - private static final byte TAG_COORD_PARAMS = 5; - - public Arnavi4ProtocolDecoder(Arnavi4Protocol protocol) { - super(protocol); - } - - private void sendResponse(Channel channel, byte version, int index) { - if (channel != null) { - final ChannelBuffer response; - if (version == HEADER_VERSION_1) { - response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); - response.writeByte(0x7b); - response.writeByte(0x00); - response.writeByte((byte) index); - response.writeByte(0x7d); - } else if (version == HEADER_VERSION_2) { - response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 9); - response.writeByte(0x7b); - response.writeByte(0x04); - response.writeByte(0x00); - byte[] timeBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); - response.writeByte(Checksum.modulo256(timeBytes)); - response.writeBytes(timeBytes); - response.writeByte(0x7d); - } else { - return; // Ignore unsupported header's versions - } - channel.write(response); - } - } - - private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, int length, Date time) { - - final Position position = new Position(); - position.setProtocol(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - - position.setTime(time); - - int readBytes = 0; - while (readBytes < length) { - short tag = buf.readUnsignedByte(); - switch (tag) { - case TAG_LATITUDE: - position.setLatitude(buf.readFloat()); - position.setValid(true); - break; - - case TAG_LONGITUDE: - position.setLongitude(buf.readFloat()); - position.setValid(true); - break; - - case TAG_COORD_PARAMS: - position.setCourse(buf.readUnsignedByte() * 2); - position.setAltitude(buf.readUnsignedByte() * 10); - byte satellites = buf.readByte(); - position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); // gps+glonass - position.setSpeed(buf.readUnsignedByte()); - break; - - default: - buf.readBytes(4); // Skip unsupported tags - break; - } - - readBytes += 5; // 1 byte tag + 4 bytes value - } - - return position; - } - - @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - - ChannelBuffer buf = (ChannelBuffer) msg; - - byte startSign = buf.readByte(); - - if (startSign == HEADER_START_SIGN) { - - byte version = buf.readByte(); - - String imei = String.valueOf(buf.readLong()); - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); - - if (deviceSession != null) { - sendResponse(channel, version, 0); - } - - return null; - } - - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - if (deviceSession == null) { - return null; - } - - List positions = new LinkedList<>(); - - int index = buf.readUnsignedByte(); - - byte recordType = buf.readByte(); - while (buf.readableBytes() > 0) { - switch (recordType) { - case RECORD_PING: - case RECORD_DATA: - case RECORD_TEXT: - case RECORD_FILE: - case RECORD_BINARY: - int length = buf.readUnsignedShort(); - Date time = new Date(buf.readUnsignedInt() * 1000); - - if (recordType == RECORD_DATA) { - positions.add(decodePosition(deviceSession, buf, length, time)); - } else { - buf.readBytes(length); // Skip other types of record - } - - buf.readUnsignedByte(); // crc - break; - - default: - return null; // Ignore unsupported types of record - } - - recordType = buf.readByte(); - } - - sendResponse(channel, HEADER_VERSION_1, index); - - return positions; - } - -} diff --git a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java new file mode 100644 index 000000000..b13f3fd7d --- /dev/null +++ b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Ivan Muratov (binakot@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 Arnavi4FrameDecoder extends FrameDecoder { + + private static final int MIN_LENGTH = 4; + private static final int HEADER_LENGTH = 10; + private static final int PACKET_WRAPPER_LENGTH = 8; + private static final int COMMAND_ANSWER_PACKET_LENGTH = 4; + private static final int COMMAND_ANSWER_PARCEL_NUMBER = 0xfd; + private static final byte PACKAGE_END_SIGN = 0x5d; + + private boolean firstPacket = true; + + @Override + protected Object decode( + ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { + + if (buf.readableBytes() < MIN_LENGTH) { + return null; + } + + int length; + if (firstPacket) { + firstPacket = false; + length = HEADER_LENGTH; + } else { + int index = buf.getUnsignedByte(1); // parcel number + if (index == COMMAND_ANSWER_PARCEL_NUMBER) { + length = COMMAND_ANSWER_PACKET_LENGTH; + } else { + int pos = 2; // start sign + parcel number + while (pos + PACKET_WRAPPER_LENGTH < buf.readableBytes() + && buf.getByte(pos) != PACKAGE_END_SIGN) { + + int dataLength = buf.getUnsignedShort(pos + 1); + pos += PACKET_WRAPPER_LENGTH + dataLength; // packet type + data length + unixtime + data + crc + } + + if (buf.getByte(pos) != PACKAGE_END_SIGN) { // end sign + return null; + } + + length = pos + 1; + } + } + + if (buf.readableBytes() >= length) { + return buf.readBytes(length); + } + + return null; + } + +} diff --git a/src/main/java/org/traccar/protocol/Arnavi4Protocol.java b/src/main/java/org/traccar/protocol/Arnavi4Protocol.java new file mode 100644 index 000000000..381a9b457 --- /dev/null +++ b/src/main/java/org/traccar/protocol/Arnavi4Protocol.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Ivan Muratov (binakot@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.traccar.BaseProtocol; +import org.traccar.TrackerServer; + +import java.nio.ByteOrder; +import java.util.List; + +public class Arnavi4Protocol extends BaseProtocol { + + public Arnavi4Protocol() { + super("arnavi4"); + } + + @Override + public void initTrackerServers(List serverList) { + TrackerServer server = new TrackerServer(new ServerBootstrap(), getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new Arnavi4FrameDecoder()); + pipeline.addLast("objectDecoder", new Arnavi4ProtocolDecoder(Arnavi4Protocol.this)); + } + }; + server.setEndianness(ByteOrder.LITTLE_ENDIAN); + serverList.add(server); + } + +} diff --git a/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java new file mode 100644 index 000000000..06abb563f --- /dev/null +++ b/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -0,0 +1,182 @@ +/* + * Copyright 2017 Ivan Muratov (binakot@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.Checksum; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { + + private static final byte HEADER_START_SIGN = (byte) 0xff; + private static final byte HEADER_VERSION_1 = 0x22; + private static final byte HEADER_VERSION_2 = 0x23; + + private static final byte RECORD_PING = 0x00; + private static final byte RECORD_DATA = 0x01; + private static final byte RECORD_TEXT = 0x03; + private static final byte RECORD_FILE = 0x04; + private static final byte RECORD_BINARY = 0x06; + + private static final byte TAG_LATITUDE = 3; + private static final byte TAG_LONGITUDE = 4; + private static final byte TAG_COORD_PARAMS = 5; + + public Arnavi4ProtocolDecoder(Arnavi4Protocol protocol) { + super(protocol); + } + + private void sendResponse(Channel channel, byte version, int index) { + if (channel != null) { + final ChannelBuffer response; + if (version == HEADER_VERSION_1) { + response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); + response.writeByte(0x7b); + response.writeByte(0x00); + response.writeByte((byte) index); + response.writeByte(0x7d); + } else if (version == HEADER_VERSION_2) { + response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 9); + response.writeByte(0x7b); + response.writeByte(0x04); + response.writeByte(0x00); + byte[] timeBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); + response.writeByte(Checksum.modulo256(timeBytes)); + response.writeBytes(timeBytes); + response.writeByte(0x7d); + } else { + return; // Ignore unsupported header's versions + } + channel.write(response); + } + } + + private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, int length, Date time) { + + final Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setTime(time); + + int readBytes = 0; + while (readBytes < length) { + short tag = buf.readUnsignedByte(); + switch (tag) { + case TAG_LATITUDE: + position.setLatitude(buf.readFloat()); + position.setValid(true); + break; + + case TAG_LONGITUDE: + position.setLongitude(buf.readFloat()); + position.setValid(true); + break; + + case TAG_COORD_PARAMS: + position.setCourse(buf.readUnsignedByte() * 2); + position.setAltitude(buf.readUnsignedByte() * 10); + byte satellites = buf.readByte(); + position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); // gps+glonass + position.setSpeed(buf.readUnsignedByte()); + break; + + default: + buf.readBytes(4); // Skip unsupported tags + break; + } + + readBytes += 5; // 1 byte tag + 4 bytes value + } + + return position; + } + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ChannelBuffer buf = (ChannelBuffer) msg; + + byte startSign = buf.readByte(); + + if (startSign == HEADER_START_SIGN) { + + byte version = buf.readByte(); + + String imei = String.valueOf(buf.readLong()); + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); + + if (deviceSession != null) { + sendResponse(channel, version, 0); + } + + return null; + } + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession == null) { + return null; + } + + List positions = new LinkedList<>(); + + int index = buf.readUnsignedByte(); + + byte recordType = buf.readByte(); + while (buf.readableBytes() > 0) { + switch (recordType) { + case RECORD_PING: + case RECORD_DATA: + case RECORD_TEXT: + case RECORD_FILE: + case RECORD_BINARY: + int length = buf.readUnsignedShort(); + Date time = new Date(buf.readUnsignedInt() * 1000); + + if (recordType == RECORD_DATA) { + positions.add(decodePosition(deviceSession, buf, length, time)); + } else { + buf.readBytes(length); // Skip other types of record + } + + buf.readUnsignedByte(); // crc + break; + + default: + return null; // Ignore unsupported types of record + } + + recordType = buf.readByte(); + } + + sendResponse(channel, HEADER_VERSION_1, index); + + return positions; + } + +} diff --git a/src/test/java/org/traccar/handler/protocol/Arnavi4FrameDecoderTest.java b/src/test/java/org/traccar/handler/protocol/Arnavi4FrameDecoderTest.java deleted file mode 100644 index b634f0cdc..000000000 --- a/src/test/java/org/traccar/handler/protocol/Arnavi4FrameDecoderTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.traccar.protocol; - -import org.junit.Assert; -import org.junit.Test; -import org.traccar.ProtocolTest; - -import java.nio.ByteOrder; - -public class Arnavi4FrameDecoderTest extends ProtocolTest { - - @Test - public void testDecodeValidPackets() throws Exception { - - Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); - - Assert.assertEquals( // Valid HEADER v1 packet with IMEI - binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"))); - - Assert.assertEquals( // Valid PACKAGE with one DATA packet - binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); - - Assert.assertEquals( // Valid PACKAGE with two DATA packet - binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); - - Assert.assertEquals( // Valid PACKAGE with one TEXT packet. - binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b5d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b5d"))); - - Assert.assertEquals( // Valid PACKAGE with two TEXT packet. - binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"))); - - Assert.assertEquals( // Valid PACKAGE with one BINARY packet. - binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); - - Assert.assertEquals( // Valid PACKAGE with two BINARY packet. - binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); - - Assert.assertEquals( // Valid PACKAGE with answer to server on file transfer - binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"))); - - } - -} \ No newline at end of file diff --git a/src/test/java/org/traccar/handler/protocol/Arnavi4ProtocolDecoderTest.java b/src/test/java/org/traccar/handler/protocol/Arnavi4ProtocolDecoderTest.java deleted file mode 100644 index d789b1c9c..000000000 --- a/src/test/java/org/traccar/handler/protocol/Arnavi4ProtocolDecoderTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.traccar.protocol; - -import org.junit.Test; -import org.traccar.ProtocolTest; - -import java.nio.ByteOrder; - -public class Arnavi4ProtocolDecoderTest extends ProtocolTest { - - @Test - public void testHeader1Decode() throws Exception { - - Arnavi4ProtocolDecoder decoder; - - decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); - - verifyNull(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid HEADER v1 packet with IMEI - "ff22f30c45f5c90f0300")); - - verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with one DATA packet - "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); - } - - @Test - public void testHeader2Decode() throws Exception { - - Arnavi4ProtocolDecoder decoder; - - decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); - - verifyNull(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid HEADER v2 packet with IMEI - "ff23f30c45f5c90f0300")); - - verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with two DATA packet - "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); - } - -} diff --git a/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java new file mode 100644 index 000000000..b634f0cdc --- /dev/null +++ b/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java @@ -0,0 +1,50 @@ +package org.traccar.protocol; + +import org.junit.Assert; +import org.junit.Test; +import org.traccar.ProtocolTest; + +import java.nio.ByteOrder; + +public class Arnavi4FrameDecoderTest extends ProtocolTest { + + @Test + public void testDecodeValidPackets() throws Exception { + + Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); + + Assert.assertEquals( // Valid HEADER v1 packet with IMEI + binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"))); + + Assert.assertEquals( // Valid PACKAGE with one DATA packet + binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); + + Assert.assertEquals( // Valid PACKAGE with two DATA packet + binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); + + Assert.assertEquals( // Valid PACKAGE with one TEXT packet. + binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b5d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b5d"))); + + Assert.assertEquals( // Valid PACKAGE with two TEXT packet. + binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"))); + + Assert.assertEquals( // Valid PACKAGE with one BINARY packet. + binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); + + Assert.assertEquals( // Valid PACKAGE with two BINARY packet. + binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); + + Assert.assertEquals( // Valid PACKAGE with answer to server on file transfer + binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"), + decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"))); + + } + +} \ No newline at end of file diff --git a/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java new file mode 100644 index 000000000..d789b1c9c --- /dev/null +++ b/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java @@ -0,0 +1,40 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +import java.nio.ByteOrder; + +public class Arnavi4ProtocolDecoderTest extends ProtocolTest { + + @Test + public void testHeader1Decode() throws Exception { + + Arnavi4ProtocolDecoder decoder; + + decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); + + verifyNull(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid HEADER v1 packet with IMEI + "ff22f30c45f5c90f0300")); + + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with one DATA packet + "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); + } + + @Test + public void testHeader2Decode() throws Exception { + + Arnavi4ProtocolDecoder decoder; + + decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); + + verifyNull(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid HEADER v2 packet with IMEI + "ff23f30c45f5c90f0300")); + + verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with two DATA packet + "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); + } + +} -- cgit v1.2.3 From ee1dbcf048a922b6023b0714989b454b7dfe9587 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Feb 2020 15:36:54 -0800 Subject: Fix merge issues --- src/main/java/org/traccar/helper/Checksum.java | 8 +++ .../org/traccar/protocol/Arnavi4FrameDecoder.java | 21 ++++---- .../java/org/traccar/protocol/Arnavi4Protocol.java | 22 +++------ .../traccar/protocol/Arnavi4ProtocolDecoder.java | 57 ++++++++++------------ src/test/java/org/traccar/helper/ChecksumTest.java | 10 ++++ .../traccar/protocol/Arnavi4FrameDecoderTest.java | 4 +- .../protocol/Arnavi4ProtocolDecoderTest.java | 4 +- 7 files changed, 63 insertions(+), 63 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/helper/Checksum.java b/src/main/java/org/traccar/helper/Checksum.java index adfa697c5..d41dc2992 100644 --- a/src/main/java/org/traccar/helper/Checksum.java +++ b/src/main/java/org/traccar/helper/Checksum.java @@ -168,6 +168,14 @@ public final class Checksum { return checksum; } + public static int modulo256(ByteBuffer buf) { + int checksum = 0; + while (buf.hasRemaining()) { + checksum = (checksum + buf.get()) & 0xFF; + } + return checksum; + } + public static String sum(String msg) { byte checksum = 0; for (byte b : msg.getBytes(StandardCharsets.US_ASCII)) { diff --git a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java index b13f3fd7d..fae2d3fde 100644 --- a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -15,12 +15,12 @@ */ 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; +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import org.traccar.BaseFrameDecoder; -public class Arnavi4FrameDecoder extends FrameDecoder { +public class Arnavi4FrameDecoder extends BaseFrameDecoder { private static final int MIN_LENGTH = 4; private static final int HEADER_LENGTH = 10; @@ -32,8 +32,7 @@ public class Arnavi4FrameDecoder extends FrameDecoder { private boolean firstPacket = true; @Override - protected Object decode( - ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { + protected Object decode(ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { if (buf.readableBytes() < MIN_LENGTH) { return null; @@ -44,19 +43,19 @@ public class Arnavi4FrameDecoder extends FrameDecoder { firstPacket = false; length = HEADER_LENGTH; } else { - int index = buf.getUnsignedByte(1); // parcel number + int index = buf.getUnsignedByte(1); if (index == COMMAND_ANSWER_PARCEL_NUMBER) { length = COMMAND_ANSWER_PACKET_LENGTH; } else { - int pos = 2; // start sign + parcel number + int pos = 2; while (pos + PACKET_WRAPPER_LENGTH < buf.readableBytes() && buf.getByte(pos) != PACKAGE_END_SIGN) { int dataLength = buf.getUnsignedShort(pos + 1); - pos += PACKET_WRAPPER_LENGTH + dataLength; // packet type + data length + unixtime + data + crc + pos += PACKET_WRAPPER_LENGTH + dataLength; } - if (buf.getByte(pos) != PACKAGE_END_SIGN) { // end sign + if (buf.getByte(pos) != PACKAGE_END_SIGN) { return null; } diff --git a/src/main/java/org/traccar/protocol/Arnavi4Protocol.java b/src/main/java/org/traccar/protocol/Arnavi4Protocol.java index 381a9b457..8a9337b56 100644 --- a/src/main/java/org/traccar/protocol/Arnavi4Protocol.java +++ b/src/main/java/org/traccar/protocol/Arnavi4Protocol.java @@ -1,4 +1,5 @@ /* + * Copyright 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Ivan Muratov (binakot@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,31 +16,20 @@ */ package org.traccar.protocol; -import org.jboss.netty.bootstrap.ServerBootstrap; -import org.jboss.netty.channel.ChannelPipeline; import org.traccar.BaseProtocol; +import org.traccar.PipelineBuilder; import org.traccar.TrackerServer; -import java.nio.ByteOrder; -import java.util.List; - public class Arnavi4Protocol extends BaseProtocol { public Arnavi4Protocol() { - super("arnavi4"); - } - - @Override - public void initTrackerServers(List serverList) { - TrackerServer server = new TrackerServer(new ServerBootstrap(), getName()) { + TrackerServer server = new TrackerServer(false, getName()) { @Override - protected void addSpecificHandlers(ChannelPipeline pipeline) { - pipeline.addLast("frameDecoder", new Arnavi4FrameDecoder()); - pipeline.addLast("objectDecoder", new Arnavi4ProtocolDecoder(Arnavi4Protocol.this)); + protected void addProtocolHandlers(PipelineBuilder pipeline) { + pipeline.addLast(new Arnavi4FrameDecoder()); + pipeline.addLast(new Arnavi4ProtocolDecoder(Arnavi4Protocol.this)); } }; - server.setEndianness(ByteOrder.LITTLE_ENDIAN); - serverList.add(server); } } diff --git a/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 06abb563f..94ad8bb1f 100644 --- a/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -15,17 +15,17 @@ */ package org.traccar.protocol; -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.jboss.netty.channel.Channel; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; +import org.traccar.NetworkMessage; import org.traccar.helper.Checksum; import org.traccar.model.Position; import java.net.SocketAddress; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.Date; import java.util.LinkedList; import java.util.List; @@ -52,30 +52,24 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { private void sendResponse(Channel channel, byte version, int index) { if (channel != null) { - final ChannelBuffer response; + ByteBuf response = Unpooled.buffer(); + response.writeByte(0x7b); if (version == HEADER_VERSION_1) { - response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 4); - response.writeByte(0x7b); response.writeByte(0x00); response.writeByte((byte) index); - response.writeByte(0x7d); } else if (version == HEADER_VERSION_2) { - response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 9); - response.writeByte(0x7b); response.writeByte(0x04); response.writeByte(0x00); - byte[] timeBytes = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)).array(); - response.writeByte(Checksum.modulo256(timeBytes)); - response.writeBytes(timeBytes); - response.writeByte(0x7d); - } else { - return; // Ignore unsupported header's versions + ByteBuffer time = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)); + response.writeByte(Checksum.modulo256(time)); + response.writeBytes(time); } - channel.write(response); + response.writeByte(0x7d); + channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); } } - private Position decodePosition(DeviceSession deviceSession, ChannelBuffer buf, int length, Date time) { + private Position decodePosition(DeviceSession deviceSession, ByteBuf buf, int length, Date time) { final Position position = new Position(); position.setProtocol(getProtocolName()); @@ -88,12 +82,12 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { short tag = buf.readUnsignedByte(); switch (tag) { case TAG_LATITUDE: - position.setLatitude(buf.readFloat()); + position.setLatitude(buf.readFloatLE()); position.setValid(true); break; case TAG_LONGITUDE: - position.setLongitude(buf.readFloat()); + position.setLongitude(buf.readFloatLE()); position.setValid(true); break; @@ -101,26 +95,25 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { position.setCourse(buf.readUnsignedByte() * 2); position.setAltitude(buf.readUnsignedByte() * 10); byte satellites = buf.readByte(); - position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); // gps+glonass + position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); position.setSpeed(buf.readUnsignedByte()); break; default: - buf.readBytes(4); // Skip unsupported tags + buf.skipBytes(4); break; } - readBytes += 5; // 1 byte tag + 4 bytes value + readBytes += 1 + 4; } return position; } @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - ChannelBuffer buf = (ChannelBuffer) msg; + ByteBuf buf = (ByteBuf) msg; byte startSign = buf.readByte(); @@ -128,7 +121,7 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { byte version = buf.readByte(); - String imei = String.valueOf(buf.readLong()); + String imei = String.valueOf(buf.readLongLE()); DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); if (deviceSession != null) { @@ -155,20 +148,20 @@ public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { case RECORD_TEXT: case RECORD_FILE: case RECORD_BINARY: - int length = buf.readUnsignedShort(); - Date time = new Date(buf.readUnsignedInt() * 1000); + int length = buf.readUnsignedShortLE(); + Date time = new Date(buf.readUnsignedIntLE() * 1000); if (recordType == RECORD_DATA) { positions.add(decodePosition(deviceSession, buf, length, time)); } else { - buf.readBytes(length); // Skip other types of record + buf.readBytes(length); } - buf.readUnsignedByte(); // crc + buf.readUnsignedByte(); // checksum break; default: - return null; // Ignore unsupported types of record + return null; } recordType = buf.readByte(); diff --git a/src/test/java/org/traccar/helper/ChecksumTest.java b/src/test/java/org/traccar/helper/ChecksumTest.java index 5737b9ff5..ff48527bc 100644 --- a/src/test/java/org/traccar/helper/ChecksumTest.java +++ b/src/test/java/org/traccar/helper/ChecksumTest.java @@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.junit.Test; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import static org.junit.Assert.assertEquals; @@ -36,4 +37,13 @@ public class ChecksumTest { assertEquals(0, Checksum.luhn(63070019470771L)); } + @Test + public void testModulo256() { + assertEquals(0x00, Checksum.modulo256(ByteBuffer.wrap(new byte[] {0x00}))); + assertEquals(0x00, Checksum.modulo256(ByteBuffer.wrap(new byte[] {0x00, 0x00, 0x00}))); + assertEquals(0xca, Checksum.modulo256(ByteBuffer.wrap(new byte[] {0x77, 0x77, 0x77, 0x77, 0x77, 0x77}))); + + + } + } diff --git a/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java index b634f0cdc..ef14b3427 100644 --- a/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java +++ b/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java @@ -8,7 +8,7 @@ import java.nio.ByteOrder; public class Arnavi4FrameDecoderTest extends ProtocolTest { - @Test + /*@Test public void testDecodeValidPackets() throws Exception { Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); @@ -45,6 +45,6 @@ public class Arnavi4FrameDecoderTest extends ProtocolTest { binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"), decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"))); - } + }*/ } \ No newline at end of file diff --git a/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java index d789b1c9c..191d69a42 100644 --- a/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java @@ -7,7 +7,7 @@ import java.nio.ByteOrder; public class Arnavi4ProtocolDecoderTest extends ProtocolTest { - @Test + /*@Test public void testHeader1Decode() throws Exception { Arnavi4ProtocolDecoder decoder; @@ -35,6 +35,6 @@ public class Arnavi4ProtocolDecoderTest extends ProtocolTest { verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with two DATA packet "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); - } + }*/ } -- cgit v1.2.3 From c6ce16f71d3cb8c04c080ebd57c5dd53e2b9229a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Feb 2020 15:55:32 -0800 Subject: Fix unit tests --- .../org/traccar/protocol/Arnavi4FrameDecoder.java | 2 +- .../traccar/protocol/Arnavi4FrameDecoderTest.java | 57 ++++++++++------------ .../protocol/Arnavi4ProtocolDecoderTest.java | 14 +++--- 3 files changed, 34 insertions(+), 39 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java index fae2d3fde..6a6f820b0 100644 --- a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -51,7 +51,7 @@ public class Arnavi4FrameDecoder extends BaseFrameDecoder { while (pos + PACKET_WRAPPER_LENGTH < buf.readableBytes() && buf.getByte(pos) != PACKAGE_END_SIGN) { - int dataLength = buf.getUnsignedShort(pos + 1); + int dataLength = buf.getUnsignedShortLE(pos + 1); pos += PACKET_WRAPPER_LENGTH + dataLength; } diff --git a/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java index ef14b3427..aa3f85820 100644 --- a/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java +++ b/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java @@ -1,50 +1,47 @@ package org.traccar.protocol; -import org.junit.Assert; import org.junit.Test; import org.traccar.ProtocolTest; -import java.nio.ByteOrder; - public class Arnavi4FrameDecoderTest extends ProtocolTest { - /*@Test + @Test public void testDecodeValidPackets() throws Exception { Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); - Assert.assertEquals( // Valid HEADER v1 packet with IMEI - binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "ff22f30c45f5c90f0300"))); + verifyFrame( + binary("ff22f30c45f5c90f0300"), + decoder.decode(null, null, binary("ff22f30c45f5c90f0300"))); - Assert.assertEquals( // Valid PACKAGE with one DATA packet - binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); + verifyFrame( + binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + decoder.decode(null, null, binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); - Assert.assertEquals( // Valid PACKAGE with two DATA packet - binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); + verifyFrame( + binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + decoder.decode(null, null, binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); - Assert.assertEquals( // Valid PACKAGE with one TEXT packet. - binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b5d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b5d"))); + verifyFrame( + binary("5b01030700e3f16b50747261636361721b5d"), + decoder.decode(null, null, binary("5b01030700e3f16b50747261636361721b5d"))); - Assert.assertEquals( // Valid PACKAGE with two TEXT packet. - binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"))); + verifyFrame( + binary("5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"), + decoder.decode(null, null, binary("5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"))); - Assert.assertEquals( // Valid PACKAGE with one BINARY packet. - binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); + verifyFrame( + binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), + decoder.decode(null, null, binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); - Assert.assertEquals( // Valid PACKAGE with two BINARY packet. - binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); + verifyFrame( + binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), + decoder.decode(null, null, binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); - Assert.assertEquals( // Valid PACKAGE with answer to server on file transfer - binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"), - decoder.decode(null, null, binary(ByteOrder.LITTLE_ENDIAN, "5bfd005d"))); + verifyFrame( + binary("5bfd005d"), + decoder.decode(null, null, binary("5bfd005d"))); - }*/ + } -} \ No newline at end of file +} diff --git a/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java index 191d69a42..2628188b9 100644 --- a/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java @@ -3,21 +3,19 @@ package org.traccar.protocol; import org.junit.Test; import org.traccar.ProtocolTest; -import java.nio.ByteOrder; - public class Arnavi4ProtocolDecoderTest extends ProtocolTest { - /*@Test + @Test public void testHeader1Decode() throws Exception { Arnavi4ProtocolDecoder decoder; decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); - verifyNull(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid HEADER v1 packet with IMEI + verifyNull(decoder, binary( "ff22f30c45f5c90f0300")); - verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with one DATA packet + verifyPositions(decoder, binary( "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); } @@ -29,12 +27,12 @@ public class Arnavi4ProtocolDecoderTest extends ProtocolTest { decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); - verifyNull(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid HEADER v2 packet with IMEI + verifyNull(decoder, binary( "ff23f30c45f5c90f0300")); - verifyPositions(decoder, binary(ByteOrder.LITTLE_ENDIAN, // Valid PACKAGE packet with two DATA packet + verifyPositions(decoder, binary( "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); - }*/ + } } -- cgit v1.2.3 From 00f8b1ff552f49ebcb5c1d13c85bd84911a2ac8d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Feb 2020 16:06:09 -0800 Subject: Refactor frame decoder --- .../org/traccar/protocol/Arnavi4FrameDecoder.java | 28 +++++++++------------- .../traccar/protocol/Arnavi4ProtocolDecoder.java | 1 + 2 files changed, 12 insertions(+), 17 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java index 6a6f820b0..8a2681b55 100644 --- a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java +++ b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java @@ -1,4 +1,5 @@ /* + * Copyright 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Ivan Muratov (binakot@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,11 +23,9 @@ import org.traccar.BaseFrameDecoder; public class Arnavi4FrameDecoder extends BaseFrameDecoder { - private static final int MIN_LENGTH = 4; private static final int HEADER_LENGTH = 10; private static final int PACKET_WRAPPER_LENGTH = 8; - private static final int COMMAND_ANSWER_PACKET_LENGTH = 4; - private static final int COMMAND_ANSWER_PARCEL_NUMBER = 0xfd; + private static final int RESULT_TYPE = 0xfd; private static final byte PACKAGE_END_SIGN = 0x5d; private boolean firstPacket = true; @@ -34,7 +33,7 @@ public class Arnavi4FrameDecoder extends BaseFrameDecoder { @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { - if (buf.readableBytes() < MIN_LENGTH) { + if (buf.readableBytes() < 4) { return null; } @@ -43,23 +42,18 @@ public class Arnavi4FrameDecoder extends BaseFrameDecoder { firstPacket = false; length = HEADER_LENGTH; } else { - int index = buf.getUnsignedByte(1); - if (index == COMMAND_ANSWER_PARCEL_NUMBER) { - length = COMMAND_ANSWER_PACKET_LENGTH; + int type = buf.getUnsignedByte(1); + if (type == RESULT_TYPE) { + length = 4; } else { - int pos = 2; - while (pos + PACKET_WRAPPER_LENGTH < buf.readableBytes() - && buf.getByte(pos) != PACKAGE_END_SIGN) { - - int dataLength = buf.getUnsignedShortLE(pos + 1); - pos += PACKET_WRAPPER_LENGTH + dataLength; + int index = 2; + while (index + PACKET_WRAPPER_LENGTH < buf.readableBytes() && buf.getByte(index) != PACKAGE_END_SIGN) { + index += PACKET_WRAPPER_LENGTH + buf.getUnsignedShortLE(index + 1); } - - if (buf.getByte(pos) != PACKAGE_END_SIGN) { + if (buf.getByte(index) != PACKAGE_END_SIGN) { return null; } - - length = pos + 1; + length = index + 1; } } diff --git a/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java index 94ad8bb1f..3e0fa5d9f 100644 --- a/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java @@ -1,4 +1,5 @@ /* + * Copyright 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Ivan Muratov (binakot@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); -- cgit v1.2.3 From 71735f0c9b17ad1c64a4335a196b4c765b4499c1 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Feb 2020 16:26:46 -0800 Subject: Rename classes --- .../org/traccar/protocol/Arnavi4FrameDecoder.java | 67 -------- .../java/org/traccar/protocol/Arnavi4Protocol.java | 35 ---- .../traccar/protocol/Arnavi4ProtocolDecoder.java | 176 -------------------- .../protocol/ArnaviBinaryProtocolDecoder.java | 177 +++++++++++++++++++++ .../org/traccar/protocol/ArnaviFrameDecoder.java | 81 ++++++++++ .../java/org/traccar/protocol/ArnaviProtocol.java | 2 +- .../traccar/protocol/ArnaviProtocolDecoder.java | 105 ------------ .../protocol/ArnaviTextProtocolDecoder.java | 105 ++++++++++++ .../traccar/protocol/Arnavi4FrameDecoderTest.java | 47 ------ .../protocol/Arnavi4ProtocolDecoderTest.java | 38 ----- .../protocol/ArnaviBinaryProtocolDecoderTest.java | 38 +++++ .../traccar/protocol/ArnaviFrameDecoderTest.java | 51 ++++++ .../protocol/ArnaviProtocolDecoderTest.java | 42 ----- .../protocol/ArnaviTextProtocolDecoderTest.java | 42 +++++ 14 files changed, 495 insertions(+), 511 deletions(-) delete mode 100644 src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java delete mode 100644 src/main/java/org/traccar/protocol/Arnavi4Protocol.java delete mode 100644 src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java create mode 100644 src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java create mode 100644 src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java delete mode 100644 src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java create mode 100644 src/main/java/org/traccar/protocol/ArnaviTextProtocolDecoder.java delete mode 100644 src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java delete mode 100644 src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java create mode 100644 src/test/java/org/traccar/protocol/ArnaviBinaryProtocolDecoderTest.java create mode 100644 src/test/java/org/traccar/protocol/ArnaviFrameDecoderTest.java delete mode 100644 src/test/java/org/traccar/protocol/ArnaviProtocolDecoderTest.java create mode 100644 src/test/java/org/traccar/protocol/ArnaviTextProtocolDecoderTest.java (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java deleted file mode 100644 index 8a2681b55..000000000 --- a/src/main/java/org/traccar/protocol/Arnavi4FrameDecoder.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2020 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Ivan Muratov (binakot@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.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import org.traccar.BaseFrameDecoder; - -public class Arnavi4FrameDecoder extends BaseFrameDecoder { - - private static final int HEADER_LENGTH = 10; - private static final int PACKET_WRAPPER_LENGTH = 8; - private static final int RESULT_TYPE = 0xfd; - private static final byte PACKAGE_END_SIGN = 0x5d; - - private boolean firstPacket = true; - - @Override - protected Object decode(ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { - - if (buf.readableBytes() < 4) { - return null; - } - - int length; - if (firstPacket) { - firstPacket = false; - length = HEADER_LENGTH; - } else { - int type = buf.getUnsignedByte(1); - if (type == RESULT_TYPE) { - length = 4; - } else { - int index = 2; - while (index + PACKET_WRAPPER_LENGTH < buf.readableBytes() && buf.getByte(index) != PACKAGE_END_SIGN) { - index += PACKET_WRAPPER_LENGTH + buf.getUnsignedShortLE(index + 1); - } - if (buf.getByte(index) != PACKAGE_END_SIGN) { - return null; - } - length = index + 1; - } - } - - if (buf.readableBytes() >= length) { - return buf.readBytes(length); - } - - return null; - } - -} diff --git a/src/main/java/org/traccar/protocol/Arnavi4Protocol.java b/src/main/java/org/traccar/protocol/Arnavi4Protocol.java deleted file mode 100644 index 8a9337b56..000000000 --- a/src/main/java/org/traccar/protocol/Arnavi4Protocol.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2020 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Ivan Muratov (binakot@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.traccar.BaseProtocol; -import org.traccar.PipelineBuilder; -import org.traccar.TrackerServer; - -public class Arnavi4Protocol extends BaseProtocol { - - public Arnavi4Protocol() { - TrackerServer server = new TrackerServer(false, getName()) { - @Override - protected void addProtocolHandlers(PipelineBuilder pipeline) { - pipeline.addLast(new Arnavi4FrameDecoder()); - pipeline.addLast(new Arnavi4ProtocolDecoder(Arnavi4Protocol.this)); - } - }; - } - -} diff --git a/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java deleted file mode 100644 index 3e0fa5d9f..000000000 --- a/src/main/java/org/traccar/protocol/Arnavi4ProtocolDecoder.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2020 Anton Tananaev (anton@traccar.org) - * Copyright 2017 Ivan Muratov (binakot@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.Unpooled; -import io.netty.channel.Channel; -import org.traccar.BaseProtocolDecoder; -import org.traccar.DeviceSession; -import org.traccar.NetworkMessage; -import org.traccar.helper.Checksum; -import org.traccar.model.Position; - -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -public class Arnavi4ProtocolDecoder extends BaseProtocolDecoder { - - private static final byte HEADER_START_SIGN = (byte) 0xff; - private static final byte HEADER_VERSION_1 = 0x22; - private static final byte HEADER_VERSION_2 = 0x23; - - private static final byte RECORD_PING = 0x00; - private static final byte RECORD_DATA = 0x01; - private static final byte RECORD_TEXT = 0x03; - private static final byte RECORD_FILE = 0x04; - private static final byte RECORD_BINARY = 0x06; - - private static final byte TAG_LATITUDE = 3; - private static final byte TAG_LONGITUDE = 4; - private static final byte TAG_COORD_PARAMS = 5; - - public Arnavi4ProtocolDecoder(Arnavi4Protocol protocol) { - super(protocol); - } - - private void sendResponse(Channel channel, byte version, int index) { - if (channel != null) { - ByteBuf response = Unpooled.buffer(); - response.writeByte(0x7b); - if (version == HEADER_VERSION_1) { - response.writeByte(0x00); - response.writeByte((byte) index); - } else if (version == HEADER_VERSION_2) { - response.writeByte(0x04); - response.writeByte(0x00); - ByteBuffer time = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)); - response.writeByte(Checksum.modulo256(time)); - response.writeBytes(time); - } - response.writeByte(0x7d); - channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); - } - } - - private Position decodePosition(DeviceSession deviceSession, ByteBuf buf, int length, Date time) { - - final Position position = new Position(); - position.setProtocol(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - - position.setTime(time); - - int readBytes = 0; - while (readBytes < length) { - short tag = buf.readUnsignedByte(); - switch (tag) { - case TAG_LATITUDE: - position.setLatitude(buf.readFloatLE()); - position.setValid(true); - break; - - case TAG_LONGITUDE: - position.setLongitude(buf.readFloatLE()); - position.setValid(true); - break; - - case TAG_COORD_PARAMS: - position.setCourse(buf.readUnsignedByte() * 2); - position.setAltitude(buf.readUnsignedByte() * 10); - byte satellites = buf.readByte(); - position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); - position.setSpeed(buf.readUnsignedByte()); - break; - - default: - buf.skipBytes(4); - break; - } - - readBytes += 1 + 4; - } - - return position; - } - - @Override - protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - - ByteBuf buf = (ByteBuf) msg; - - byte startSign = buf.readByte(); - - if (startSign == HEADER_START_SIGN) { - - byte version = buf.readByte(); - - String imei = String.valueOf(buf.readLongLE()); - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); - - if (deviceSession != null) { - sendResponse(channel, version, 0); - } - - return null; - } - - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - if (deviceSession == null) { - return null; - } - - List positions = new LinkedList<>(); - - int index = buf.readUnsignedByte(); - - byte recordType = buf.readByte(); - while (buf.readableBytes() > 0) { - switch (recordType) { - case RECORD_PING: - case RECORD_DATA: - case RECORD_TEXT: - case RECORD_FILE: - case RECORD_BINARY: - int length = buf.readUnsignedShortLE(); - Date time = new Date(buf.readUnsignedIntLE() * 1000); - - if (recordType == RECORD_DATA) { - positions.add(decodePosition(deviceSession, buf, length, time)); - } else { - buf.readBytes(length); - } - - buf.readUnsignedByte(); // checksum - break; - - default: - return null; - } - - recordType = buf.readByte(); - } - - sendResponse(channel, HEADER_VERSION_1, index); - - return positions; - } - -} diff --git a/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java new file mode 100644 index 000000000..0924cfc40 --- /dev/null +++ b/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java @@ -0,0 +1,177 @@ +/* + * Copyright 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2017 Ivan Muratov (binakot@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.Unpooled; +import io.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.NetworkMessage; +import org.traccar.Protocol; +import org.traccar.helper.Checksum; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +public class ArnaviBinaryProtocolDecoder extends BaseProtocolDecoder { + + private static final byte HEADER_START_SIGN = (byte) 0xff; + private static final byte HEADER_VERSION_1 = 0x22; + private static final byte HEADER_VERSION_2 = 0x23; + + private static final byte RECORD_PING = 0x00; + private static final byte RECORD_DATA = 0x01; + private static final byte RECORD_TEXT = 0x03; + private static final byte RECORD_FILE = 0x04; + private static final byte RECORD_BINARY = 0x06; + + private static final byte TAG_LATITUDE = 3; + private static final byte TAG_LONGITUDE = 4; + private static final byte TAG_COORD_PARAMS = 5; + + public ArnaviBinaryProtocolDecoder(Protocol protocol) { + super(protocol); + } + + private void sendResponse(Channel channel, byte version, int index) { + if (channel != null) { + ByteBuf response = Unpooled.buffer(); + response.writeByte(0x7b); + if (version == HEADER_VERSION_1) { + response.writeByte(0x00); + response.writeByte((byte) index); + } else if (version == HEADER_VERSION_2) { + response.writeByte(0x04); + response.writeByte(0x00); + ByteBuffer time = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)); + response.writeByte(Checksum.modulo256(time)); + response.writeBytes(time); + } + response.writeByte(0x7d); + channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); + } + } + + private Position decodePosition(DeviceSession deviceSession, ByteBuf buf, int length, Date time) { + + final Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setTime(time); + + int readBytes = 0; + while (readBytes < length) { + short tag = buf.readUnsignedByte(); + switch (tag) { + case TAG_LATITUDE: + position.setLatitude(buf.readFloatLE()); + position.setValid(true); + break; + + case TAG_LONGITUDE: + position.setLongitude(buf.readFloatLE()); + position.setValid(true); + break; + + case TAG_COORD_PARAMS: + position.setCourse(buf.readUnsignedByte() * 2); + position.setAltitude(buf.readUnsignedByte() * 10); + byte satellites = buf.readByte(); + position.set(Position.KEY_SATELLITES, satellites & 0x0F + (satellites >> 4) & 0x0F); + position.setSpeed(buf.readUnsignedByte()); + break; + + default: + buf.skipBytes(4); + break; + } + + readBytes += 1 + 4; + } + + return position; + } + + @Override + protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ByteBuf buf = (ByteBuf) msg; + + byte startSign = buf.readByte(); + + if (startSign == HEADER_START_SIGN) { + + byte version = buf.readByte(); + + String imei = String.valueOf(buf.readLongLE()); + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); + + if (deviceSession != null) { + sendResponse(channel, version, 0); + } + + return null; + } + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession == null) { + return null; + } + + List positions = new LinkedList<>(); + + int index = buf.readUnsignedByte(); + + byte recordType = buf.readByte(); + while (buf.readableBytes() > 0) { + switch (recordType) { + case RECORD_PING: + case RECORD_DATA: + case RECORD_TEXT: + case RECORD_FILE: + case RECORD_BINARY: + int length = buf.readUnsignedShortLE(); + Date time = new Date(buf.readUnsignedIntLE() * 1000); + + if (recordType == RECORD_DATA) { + positions.add(decodePosition(deviceSession, buf, length, time)); + } else { + buf.readBytes(length); + } + + buf.readUnsignedByte(); // checksum + break; + + default: + return null; + } + + recordType = buf.readByte(); + } + + sendResponse(channel, HEADER_VERSION_1, index); + + return positions; + } + +} diff --git a/src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java b/src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java new file mode 100644 index 000000000..3db11113d --- /dev/null +++ b/src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java @@ -0,0 +1,81 @@ +/* + * Copyright 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2017 Ivan Muratov (binakot@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.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import org.traccar.BaseFrameDecoder; +import org.traccar.helper.BufferUtil; + +public class ArnaviFrameDecoder extends BaseFrameDecoder { + + private static final int HEADER_LENGTH = 10; + private static final int PACKET_WRAPPER_LENGTH = 8; + private static final int RESULT_TYPE = 0xfd; + private static final byte PACKAGE_END_SIGN = 0x5d; + + private boolean firstPacket = true; + + @Override + protected Object decode(ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { + + if (buf.readableBytes() < 4) { + return null; + } + + if (buf.getByte(buf.readerIndex()) == '$') { + + int index = BufferUtil.indexOf("\r\n", buf); + if (index > 0) { + ByteBuf frame = buf.readRetainedSlice(index - buf.readerIndex()); + buf.skipBytes(2); + return frame; + } + + } else { + + int length; + if (firstPacket) { + firstPacket = false; + length = HEADER_LENGTH; + } else { + int type = buf.getUnsignedByte(1); + if (type == RESULT_TYPE) { + length = 4; + } else { + int index = 2; + while (index + PACKET_WRAPPER_LENGTH < buf.readableBytes() && buf.getByte(index) != PACKAGE_END_SIGN) { + index += PACKET_WRAPPER_LENGTH + buf.getUnsignedShortLE(index + 1); + } + if (buf.getByte(index) != PACKAGE_END_SIGN) { + return null; + } + length = index + 1; + } + } + + if (buf.readableBytes() >= length) { + return buf.readRetainedSlice(length); + } + + } + + return null; + } + +} diff --git a/src/main/java/org/traccar/protocol/ArnaviProtocol.java b/src/main/java/org/traccar/protocol/ArnaviProtocol.java index afe491865..11101097b 100644 --- a/src/main/java/org/traccar/protocol/ArnaviProtocol.java +++ b/src/main/java/org/traccar/protocol/ArnaviProtocol.java @@ -31,7 +31,7 @@ public class ArnaviProtocol extends BaseProtocol { pipeline.addLast(new LineBasedFrameDecoder(1024)); pipeline.addLast(new StringDecoder()); pipeline.addLast(new StringEncoder()); - pipeline.addLast(new ArnaviProtocolDecoder(ArnaviProtocol.this)); + pipeline.addLast(new ArnaviTextProtocolDecoder(ArnaviProtocol.this)); } }); } diff --git a/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java deleted file mode 100644 index 7996cf429..000000000 --- a/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2015 - 2019 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 io.netty.channel.Channel; -import org.traccar.BaseProtocolDecoder; -import org.traccar.DeviceSession; -import org.traccar.Protocol; -import org.traccar.helper.DateBuilder; -import org.traccar.helper.Parser; -import org.traccar.helper.PatternBuilder; -import org.traccar.model.Position; - -import java.net.SocketAddress; -import java.util.regex.Pattern; - -public class ArnaviProtocolDecoder extends BaseProtocolDecoder { - - public ArnaviProtocolDecoder(Protocol protocol) { - super(protocol); - } - - private static final Pattern PATTERN = new PatternBuilder() - .text("$AV,") - .number("Vd,") // type - .number("(d+),") // device id - .number("(d+),") // index - .number("(d+),") // power - .number("(d+),") // battery - .number("-?d+,") - .expression("[01],") // movement - .expression("([01]),") // ignition - .number("(d+),") // input - .number("d+,d+,") // input 1 - .number("d+,d+,").optional() // input 2 - .expression("[01],") // fix type - .number("(d+),") // satellites - .groupBegin() - .number("(d+.d+)?,") // altitude - .number("(?:d+.d+)?,") // geoid height - .groupEnd("?") - .number("(dd)(dd)(dd),") // time (hhmmss) - .number("(dd)(dd.d+)([NS]),") // latitude - .number("(ddd)(dd.d+)([EW]),") // longitude - .number("(d+.d+),") // speed - .number("(d+.d+),") // course - .number("(dd)(dd)(dd)") // date (ddmmyy) - .any() - .compile(); - - @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - - Parser parser = new Parser(PATTERN, (String) msg); - if (!parser.matches()) { - return null; - } - - Position position = new Position(getProtocolName()); - - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); - if (deviceSession == null) { - return null; - } - position.setDeviceId(deviceSession.getDeviceId()); - - position.set(Position.KEY_INDEX, parser.nextInt()); - position.set(Position.KEY_POWER, parser.nextInt() * 0.01); - position.set(Position.KEY_BATTERY, parser.nextInt() * 0.01); - position.set(Position.KEY_IGNITION, parser.nextInt() == 1); - position.set(Position.KEY_INPUT, parser.nextInt()); - position.set(Position.KEY_SATELLITES, parser.nextInt()); - - position.setAltitude(parser.nextDouble(0)); - - DateBuilder dateBuilder = new DateBuilder() - .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); - - position.setValid(true); - position.setLatitude(parser.nextCoordinate()); - position.setLongitude(parser.nextCoordinate()); - position.setSpeed(parser.nextDouble()); - position.setCourse(parser.nextDouble()); - - dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()); - position.setTime(dateBuilder.getDate()); - - return position; - } - -} diff --git a/src/main/java/org/traccar/protocol/ArnaviTextProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviTextProtocolDecoder.java new file mode 100644 index 000000000..8c4f743bc --- /dev/null +++ b/src/main/java/org/traccar/protocol/ArnaviTextProtocolDecoder.java @@ -0,0 +1,105 @@ +/* + * Copyright 2015 - 2019 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 io.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.Protocol; +import org.traccar.helper.DateBuilder; +import org.traccar.helper.Parser; +import org.traccar.helper.PatternBuilder; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.util.regex.Pattern; + +public class ArnaviTextProtocolDecoder extends BaseProtocolDecoder { + + public ArnaviTextProtocolDecoder(Protocol protocol) { + super(protocol); + } + + private static final Pattern PATTERN = new PatternBuilder() + .text("$AV,") + .number("Vd,") // type + .number("(d+),") // device id + .number("(d+),") // index + .number("(d+),") // power + .number("(d+),") // battery + .number("-?d+,") + .expression("[01],") // movement + .expression("([01]),") // ignition + .number("(d+),") // input + .number("d+,d+,") // input 1 + .number("d+,d+,").optional() // input 2 + .expression("[01],") // fix type + .number("(d+),") // satellites + .groupBegin() + .number("(d+.d+)?,") // altitude + .number("(?:d+.d+)?,") // geoid height + .groupEnd("?") + .number("(dd)(dd)(dd),") // time (hhmmss) + .number("(dd)(dd.d+)([NS]),") // latitude + .number("(ddd)(dd.d+)([EW]),") // longitude + .number("(d+.d+),") // speed + .number("(d+.d+),") // course + .number("(dd)(dd)(dd)") // date (ddmmyy) + .any() + .compile(); + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + Parser parser = new Parser(PATTERN, (String) msg); + if (!parser.matches()) { + return null; + } + + Position position = new Position(getProtocolName()); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); + if (deviceSession == null) { + return null; + } + position.setDeviceId(deviceSession.getDeviceId()); + + position.set(Position.KEY_INDEX, parser.nextInt()); + position.set(Position.KEY_POWER, parser.nextInt() * 0.01); + position.set(Position.KEY_BATTERY, parser.nextInt() * 0.01); + position.set(Position.KEY_IGNITION, parser.nextInt() == 1); + position.set(Position.KEY_INPUT, parser.nextInt()); + position.set(Position.KEY_SATELLITES, parser.nextInt()); + + position.setAltitude(parser.nextDouble(0)); + + DateBuilder dateBuilder = new DateBuilder() + .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); + + position.setValid(true); + position.setLatitude(parser.nextCoordinate()); + position.setLongitude(parser.nextCoordinate()); + position.setSpeed(parser.nextDouble()); + position.setCourse(parser.nextDouble()); + + dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()); + position.setTime(dateBuilder.getDate()); + + return position; + } + +} diff --git a/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java deleted file mode 100644 index aa3f85820..000000000 --- a/src/test/java/org/traccar/protocol/Arnavi4FrameDecoderTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.traccar.protocol; - -import org.junit.Test; -import org.traccar.ProtocolTest; - -public class Arnavi4FrameDecoderTest extends ProtocolTest { - - @Test - public void testDecodeValidPackets() throws Exception { - - Arnavi4FrameDecoder decoder = new Arnavi4FrameDecoder(); - - verifyFrame( - binary("ff22f30c45f5c90f0300"), - decoder.decode(null, null, binary("ff22f30c45f5c90f0300"))); - - verifyFrame( - binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - decoder.decode(null, null, binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); - - verifyFrame( - binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - decoder.decode(null, null, binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); - - verifyFrame( - binary("5b01030700e3f16b50747261636361721b5d"), - decoder.decode(null, null, binary("5b01030700e3f16b50747261636361721b5d"))); - - verifyFrame( - binary("5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"), - decoder.decode(null, null, binary("5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"))); - - verifyFrame( - binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), - decoder.decode(null, null, binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); - - verifyFrame( - binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), - decoder.decode(null, null, binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); - - verifyFrame( - binary("5bfd005d"), - decoder.decode(null, null, binary("5bfd005d"))); - - } - -} diff --git a/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java deleted file mode 100644 index 2628188b9..000000000 --- a/src/test/java/org/traccar/protocol/Arnavi4ProtocolDecoderTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.traccar.protocol; - -import org.junit.Test; -import org.traccar.ProtocolTest; - -public class Arnavi4ProtocolDecoderTest extends ProtocolTest { - - @Test - public void testHeader1Decode() throws Exception { - - Arnavi4ProtocolDecoder decoder; - - decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); - - verifyNull(decoder, binary( - "ff22f30c45f5c90f0300")); - - verifyPositions(decoder, binary( - "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); - } - - @Test - public void testHeader2Decode() throws Exception { - - Arnavi4ProtocolDecoder decoder; - - decoder = new Arnavi4ProtocolDecoder(new Arnavi4Protocol()); - - verifyNull(decoder, binary( - "ff23f30c45f5c90f0300")); - - verifyPositions(decoder, binary( - "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), - position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); - } - -} diff --git a/src/test/java/org/traccar/protocol/ArnaviBinaryProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ArnaviBinaryProtocolDecoderTest.java new file mode 100644 index 000000000..f2940de59 --- /dev/null +++ b/src/test/java/org/traccar/protocol/ArnaviBinaryProtocolDecoderTest.java @@ -0,0 +1,38 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class ArnaviBinaryProtocolDecoderTest extends ProtocolTest { + + @Test + public void testHeader1Decode() throws Exception { + + ArnaviBinaryProtocolDecoder decoder; + + decoder = new ArnaviBinaryProtocolDecoder(null); + + verifyNull(decoder, binary( + "ff22f30c45f5c90f0300")); + + verifyPositions(decoder, binary( + "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); + } + + @Test + public void testHeader2Decode() throws Exception { + + ArnaviBinaryProtocolDecoder decoder; + + decoder = new ArnaviBinaryProtocolDecoder(null); + + verifyNull(decoder, binary( + "ff23f30c45f5c90f0300")); + + verifyPositions(decoder, binary( + "5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + position("2017-07-07 05:09:55.000", true, 45.05597, 39.03347)); + } + +} diff --git a/src/test/java/org/traccar/protocol/ArnaviFrameDecoderTest.java b/src/test/java/org/traccar/protocol/ArnaviFrameDecoderTest.java new file mode 100644 index 000000000..90eb20296 --- /dev/null +++ b/src/test/java/org/traccar/protocol/ArnaviFrameDecoderTest.java @@ -0,0 +1,51 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class ArnaviFrameDecoderTest extends ProtocolTest { + + @Test + public void testDecodeValidPackets() throws Exception { + + ArnaviFrameDecoder decoder = new ArnaviFrameDecoder(); + + verifyFrame( + binary("2441562c563344492c38353136342c3231342c2d312c31392c30303030344634462c30303030303935452c30433030303030322c3836333037313031333034313631382c38393939373031353630333832353236363232462c2a3039"), + decoder.decode(null, null, binary("2441562c563344492c38353136342c3231342c2d312c31392c30303030344634462c30303030303935452c30433030303030322c3836333037313031333034313631382c38393939373031353630333832353236363232462c2a30390d0a"))); + + verifyFrame( + binary("ff22f30c45f5c90f0300"), + decoder.decode(null, null, binary("ff22f30c45f5c90f0300"))); + + verifyFrame( + binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + decoder.decode(null, null, binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); + + verifyFrame( + binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"), + decoder.decode(null, null, binary("5b01012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa3701000029012800a3175f5903513934420447221c42055402781E0900f0c5215b4e0084005c00007c005d0000a300fa37010000295d"))); + + verifyFrame( + binary("5b01030700e3f16b50747261636361721b5d"), + decoder.decode(null, null, binary("5b01030700e3f16b50747261636361721b5d"))); + + verifyFrame( + binary("5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"), + decoder.decode(null, null, binary("5b01030700e3f16b50747261636361721b030700e3f16b50747261636361721b5d"))); + + verifyFrame( + binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), + decoder.decode(null, null, binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); + + verifyFrame( + binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"), + decoder.decode(null, null, binary("5b01061400e3f16b5003298b5e4204cbd514420500191000080400ff021b061400e3f16b5003298b5e4204cbd514420500191000080400ff021b5d"))); + + verifyFrame( + binary("5bfd005d"), + decoder.decode(null, null, binary("5bfd005d"))); + + } + +} diff --git a/src/test/java/org/traccar/protocol/ArnaviProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ArnaviProtocolDecoderTest.java deleted file mode 100644 index 6b075facc..000000000 --- a/src/test/java/org/traccar/protocol/ArnaviProtocolDecoderTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.traccar.protocol; - -import org.junit.Test; -import org.traccar.ProtocolTest; - -public class ArnaviProtocolDecoderTest extends ProtocolTest { - - @Test - public void testDecode() throws Exception { - - ArnaviProtocolDecoder decoder = new ArnaviProtocolDecoder(null); - - verifyPosition(decoder, text( - "$AV,V4,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,80.0,56.1,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E")); - - verifyNull(decoder, text( - "$AV,V3DI,85164,20707,-1,19,0008C56A,000879AC,0C000002,863071013041618,89997077111301204297,*0B")); - - verifyNull(decoder, text( - "$AV,V6SD,85164,20708,-1,3,6,37,33,*52")); - - verifyAttributes(decoder, text( - "$AV,V4,85164,20709,1148,418,-1,0,1,192,0,0,0,0,0,0,,,000023,0000.0000N,00000.0000E,0.0,0.0,060180,0,0,32767,*4F")); - - verifyNull(decoder, text( - "$AV,V3GSMINFO,85164,-1,20450,KMOBILE,1,2,1,23,0,40101,cc3,1,ce19,401,16,65304,5613,72,,SF*7F")); - - verifyAttributes(decoder, text( - "$AV,V4,85164,20451,1146,418,-1,1,1,192,0,0,0,0,0,0,,,104340,0000.0000N,00000.0000E,0.0,0.0,060219,11,0,32767,,SF*47")); - - verifyNull(decoder, text( - "$AV,V6SD,85164,20452,-1,3,3,5,6769,,SF*5D")); - - verifyPosition(decoder, text( - "$AV,V2,32768,12487,2277,203,-1,0,0,193,0,0,1,13,200741,5950.6773N,03029.1043E,0.0,0.0,121012,*6E")); - - verifyPosition(decoder, text( - "$AV,V3,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E")); - - } - -} diff --git a/src/test/java/org/traccar/protocol/ArnaviTextProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ArnaviTextProtocolDecoderTest.java new file mode 100644 index 000000000..065a28580 --- /dev/null +++ b/src/test/java/org/traccar/protocol/ArnaviTextProtocolDecoderTest.java @@ -0,0 +1,42 @@ +package org.traccar.protocol; + +import org.junit.Test; +import org.traccar.ProtocolTest; + +public class ArnaviTextProtocolDecoderTest extends ProtocolTest { + + @Test + public void testDecode() throws Exception { + + ArnaviTextProtocolDecoder decoder = new ArnaviTextProtocolDecoder(null); + + verifyPosition(decoder, text( + "$AV,V4,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,80.0,56.1,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E")); + + verifyNull(decoder, text( + "$AV,V3DI,85164,20707,-1,19,0008C56A,000879AC,0C000002,863071013041618,89997077111301204297,*0B")); + + verifyNull(decoder, text( + "$AV,V6SD,85164,20708,-1,3,6,37,33,*52")); + + verifyAttributes(decoder, text( + "$AV,V4,85164,20709,1148,418,-1,0,1,192,0,0,0,0,0,0,,,000023,0000.0000N,00000.0000E,0.0,0.0,060180,0,0,32767,*4F")); + + verifyNull(decoder, text( + "$AV,V3GSMINFO,85164,-1,20450,KMOBILE,1,2,1,23,0,40101,cc3,1,ce19,401,16,65304,5613,72,,SF*7F")); + + verifyAttributes(decoder, text( + "$AV,V4,85164,20451,1146,418,-1,1,1,192,0,0,0,0,0,0,,,104340,0000.0000N,00000.0000E,0.0,0.0,060219,11,0,32767,,SF*47")); + + verifyNull(decoder, text( + "$AV,V6SD,85164,20452,-1,3,3,5,6769,,SF*5D")); + + verifyPosition(decoder, text( + "$AV,V2,32768,12487,2277,203,-1,0,0,193,0,0,1,13,200741,5950.6773N,03029.1043E,0.0,0.0,121012,*6E")); + + verifyPosition(decoder, text( + "$AV,V3,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E")); + + } + +} -- cgit v1.2.3 From 8b48d8b52f9c29a892dfe4381b3a7226226a76eb Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Feb 2020 16:31:10 -0800 Subject: Switch between binary and text --- .../java/org/traccar/protocol/ArnaviProtocol.java | 11 ++--- .../traccar/protocol/ArnaviProtocolDecoder.java | 49 ++++++++++++++++++++++ .../protocol/ArnaviTextProtocolDecoder.java | 7 +++- .../protocol/ArnaviTextProtocolDecoderTest.java | 18 ++++---- 4 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/ArnaviProtocol.java b/src/main/java/org/traccar/protocol/ArnaviProtocol.java index 11101097b..aecb42c8c 100644 --- a/src/main/java/org/traccar/protocol/ArnaviProtocol.java +++ b/src/main/java/org/traccar/protocol/ArnaviProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -15,9 +15,6 @@ */ package org.traccar.protocol; -import io.netty.handler.codec.LineBasedFrameDecoder; -import io.netty.handler.codec.string.StringDecoder; -import io.netty.handler.codec.string.StringEncoder; import org.traccar.BaseProtocol; import org.traccar.PipelineBuilder; import org.traccar.TrackerServer; @@ -28,10 +25,8 @@ public class ArnaviProtocol extends BaseProtocol { addServer(new TrackerServer(false, getName()) { @Override protected void addProtocolHandlers(PipelineBuilder pipeline) { - pipeline.addLast(new LineBasedFrameDecoder(1024)); - pipeline.addLast(new StringDecoder()); - pipeline.addLast(new StringEncoder()); - pipeline.addLast(new ArnaviTextProtocolDecoder(ArnaviProtocol.this)); + pipeline.addLast(new ArnaviFrameDecoder()); + pipeline.addLast(new ArnaviProtocolDecoder(ArnaviProtocol.this)); } }); } diff --git a/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java new file mode 100644 index 000000000..68a70c944 --- /dev/null +++ b/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java @@ -0,0 +1,49 @@ +/* + * Copyright 2020 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 io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.Protocol; + +import java.net.SocketAddress; + +public class ArnaviProtocolDecoder extends BaseProtocolDecoder { + + private final ArnaviTextProtocolDecoder textProtocolDecoder; + private final ArnaviBinaryProtocolDecoder binaryProtocolDecoder; + + public ArnaviProtocolDecoder(Protocol protocol) { + super(protocol); + textProtocolDecoder = new ArnaviTextProtocolDecoder(protocol); + binaryProtocolDecoder = new ArnaviBinaryProtocolDecoder(protocol); + } + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ByteBuf buf = (ByteBuf) msg; + + if (buf.getByte(buf.readerIndex()) == '$') { + return textProtocolDecoder.decode(channel, remoteAddress, msg); + } else { + return binaryProtocolDecoder.decode(channel, remoteAddress, msg); + } + } + +} diff --git a/src/main/java/org/traccar/protocol/ArnaviTextProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviTextProtocolDecoder.java index 8c4f743bc..b99869e6e 100644 --- a/src/main/java/org/traccar/protocol/ArnaviTextProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/ArnaviTextProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -15,6 +15,7 @@ */ package org.traccar.protocol; +import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; @@ -25,6 +26,7 @@ import org.traccar.helper.PatternBuilder; import org.traccar.model.Position; import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; import java.util.regex.Pattern; public class ArnaviTextProtocolDecoder extends BaseProtocolDecoder { @@ -65,7 +67,8 @@ public class ArnaviTextProtocolDecoder extends BaseProtocolDecoder { protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - Parser parser = new Parser(PATTERN, (String) msg); + ByteBuf buf = (ByteBuf) msg; + Parser parser = new Parser(PATTERN, buf.toString(StandardCharsets.US_ASCII)); if (!parser.matches()) { return null; } diff --git a/src/test/java/org/traccar/protocol/ArnaviTextProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ArnaviTextProtocolDecoderTest.java index 065a28580..79179d4f3 100644 --- a/src/test/java/org/traccar/protocol/ArnaviTextProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/ArnaviTextProtocolDecoderTest.java @@ -10,31 +10,31 @@ public class ArnaviTextProtocolDecoderTest extends ProtocolTest { ArnaviTextProtocolDecoder decoder = new ArnaviTextProtocolDecoder(null); - verifyPosition(decoder, text( + verifyPosition(decoder, buffer( "$AV,V4,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,80.0,56.1,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E")); - verifyNull(decoder, text( + verifyNull(decoder, buffer( "$AV,V3DI,85164,20707,-1,19,0008C56A,000879AC,0C000002,863071013041618,89997077111301204297,*0B")); - verifyNull(decoder, text( + verifyNull(decoder, buffer( "$AV,V6SD,85164,20708,-1,3,6,37,33,*52")); - verifyAttributes(decoder, text( + verifyAttributes(decoder, buffer( "$AV,V4,85164,20709,1148,418,-1,0,1,192,0,0,0,0,0,0,,,000023,0000.0000N,00000.0000E,0.0,0.0,060180,0,0,32767,*4F")); - verifyNull(decoder, text( + verifyNull(decoder, buffer( "$AV,V3GSMINFO,85164,-1,20450,KMOBILE,1,2,1,23,0,40101,cc3,1,ce19,401,16,65304,5613,72,,SF*7F")); - verifyAttributes(decoder, text( + verifyAttributes(decoder, buffer( "$AV,V4,85164,20451,1146,418,-1,1,1,192,0,0,0,0,0,0,,,104340,0000.0000N,00000.0000E,0.0,0.0,060219,11,0,32767,,SF*47")); - verifyNull(decoder, text( + verifyNull(decoder, buffer( "$AV,V6SD,85164,20452,-1,3,3,5,6769,,SF*5D")); - verifyPosition(decoder, text( + verifyPosition(decoder, buffer( "$AV,V2,32768,12487,2277,203,-1,0,0,193,0,0,1,13,200741,5950.6773N,03029.1043E,0.0,0.0,121012,*6E")); - verifyPosition(decoder, text( + verifyPosition(decoder, buffer( "$AV,V3,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E")); } -- cgit v1.2.3 From 574566c160357f2e2cac45368ec363ab59952a6d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 2 Feb 2020 16:33:57 -0800 Subject: Fix checkstyle issue --- src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java b/src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java index 3db11113d..473e8b2c7 100644 --- a/src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java +++ b/src/main/java/org/traccar/protocol/ArnaviFrameDecoder.java @@ -59,7 +59,8 @@ public class ArnaviFrameDecoder extends BaseFrameDecoder { length = 4; } else { int index = 2; - while (index + PACKET_WRAPPER_LENGTH < buf.readableBytes() && buf.getByte(index) != PACKAGE_END_SIGN) { + while (index + PACKET_WRAPPER_LENGTH < buf.readableBytes() + && buf.getByte(index) != PACKAGE_END_SIGN) { index += PACKET_WRAPPER_LENGTH + buf.getUnsignedShortLE(index + 1); } if (buf.getByte(index) != PACKAGE_END_SIGN) { -- cgit v1.2.3 From 117189248da9cac8426d8fa4fb50f8a8d63f56b0 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 3 Feb 2020 22:02:24 -0800 Subject: Fix Arnavi response --- src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java index 0924cfc40..d25c02414 100644 --- a/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java @@ -63,7 +63,8 @@ public class ArnaviBinaryProtocolDecoder extends BaseProtocolDecoder { response.writeByte(0x04); response.writeByte(0x00); ByteBuffer time = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)); - response.writeByte(Checksum.modulo256(time)); + time.position(0); + response.writeByte(Checksum.modulo256(time.slice())); response.writeBytes(time); } response.writeByte(0x7d); -- cgit v1.2.3 From b73cafaba31fb6165a6539bb795600642bd3899d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 3 Feb 2020 22:28:53 -0800 Subject: Decode input and output --- .../traccar/protocol/MeitrackProtocolDecoder.java | 28 +++++++++++----------- .../protocol/MeitrackProtocolDecoderTest.java | 3 +++ 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java index 55260ef0c..529496928 100644 --- a/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java @@ -70,7 +70,8 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { .number("(d+)|") // mnc .number("(x+)|") // lac .number("(x+),") // cid - .number("(x+),") // state + .number("(xx)") // input + .number("(xx),") // output .number("(x+)?|") // adc1 .number("(x+)?|") // adc2 .number("(x+)?|") // adc3 @@ -149,39 +150,38 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { } position.setDeviceId(deviceSession.getDeviceId()); - int event = parser.nextInt(0); + int event = parser.nextInt(); position.set(Position.KEY_EVENT, event); position.set(Position.KEY_ALARM, decodeAlarm(event)); - position.setLatitude(parser.nextDouble(0)); - position.setLongitude(parser.nextDouble(0)); + position.setLatitude(parser.nextDouble()); + position.setLongitude(parser.nextDouble()); position.setTime(parser.nextDateTime()); position.setValid(parser.next().equals("A")); position.set(Position.KEY_SATELLITES, parser.nextInt()); - int rssi = parser.nextInt(0); + int rssi = parser.nextInt(); - position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble(0))); - position.setCourse(parser.nextDouble(0)); + position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble())); + position.setCourse(parser.nextDouble()); position.set(Position.KEY_HDOP, parser.nextDouble()); - position.setAltitude(parser.nextDouble(0)); + position.setAltitude(parser.nextDouble()); - position.set(Position.KEY_ODOMETER, parser.nextInt(0)); + position.set(Position.KEY_ODOMETER, parser.nextInt()); position.set("runtime", parser.next()); position.setNetwork(new Network(CellTower.from( - parser.nextInt(0), parser.nextInt(0), parser.nextHexInt(0), parser.nextHexInt(0), rssi))); + parser.nextInt(), parser.nextInt(), parser.nextHexInt(), parser.nextHexInt(), rssi))); - position.set(Position.KEY_STATUS, parser.next()); + position.set(Position.KEY_OUTPUT, parser.nextHexInt()); + position.set(Position.KEY_INPUT, parser.nextHexInt()); for (int i = 1; i <= 3; i++) { - if (parser.hasNext()) { - position.set(Position.PREFIX_ADC + i, parser.nextHexInt(0)); - } + position.set(Position.PREFIX_ADC + i, parser.nextHexInt()); } String deviceModel = Context.getIdentityManager().getById(deviceSession.getDeviceId()).getModel(); diff --git a/src/test/java/org/traccar/protocol/MeitrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MeitrackProtocolDecoderTest.java index 3e05d5243..9f9da26ca 100644 --- a/src/test/java/org/traccar/protocol/MeitrackProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/MeitrackProtocolDecoderTest.java @@ -10,6 +10,9 @@ public class MeitrackProtocolDecoderTest extends ProtocolTest { MeitrackProtocolDecoder decoder = new MeitrackProtocolDecoder(null); + verifyPosition(decoder, buffer( + "$$O160,863835028611502,AAA,35,7.887840,98.375193,200202020238,A,12,4,0,279,0.6,45,32121,442492,520|3|12DF|015273E2,0000,0000|0000|0000|018D|04F0,00000001,,1,0000*F3")); + verifyNull(decoder, binary( "242441313038362c3836343530373033313231393937342c4430302c3138303232343037323631345f4331453130395f4e31553144312e6a70672c31342c302cffd8ffdb008400140e0f120f0d14121012171514181e32211e1c1c1e3d2c2e243249404c4b47404645505a736250556d5645466488656d777b8182814e608d978c7d96737e817c011517171e1a1e3b21213b7c5346537c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7cffc000110801e0028003012100021101031101ffdd0004000affc401a20000010501010101010100000000000000000102030405060708090a0b100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa0100030101010101010101010000000000000102030405060708090a0b1100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00cca69ac8d06e3348569884db4845021b498a60371494008692980119a8ca7a5342101a5cd5221a0ab312ed1ee68b943e80dce2a467ffd0c806a48e592270f13b230e841a0096eeea7bb09e6c85b667033552800069c2980e14f15422418a916ad099228a95455089505584140993a2d5fb598a7cae72bd8fa536ae892e8e69e2b9d971168a459fffd1ece8a0028a006b534f4a68ce5b9130a89ab444919a61a6c634d34d21894952310d25002514084a4a00ffd2d2349564086929082929805250025140094940c4a4a04251400949408292819fffd3cca31591a098a5c62801a45464531098a69a6210d371400629a6980628eb400c64cd3791c1aa16c491479393563343105424fcc4d007ffd4c3463c0a94500381a5e3b8cd000c99e57f2a8f3835402834e0d4d08914d4aa6ac4c954d4aad4c4c955aa647a6496236ab51b552132e412e383d3f955b0722b09ab32a0c5a2a0d0ffd5ece8a0028a0061a6d5193dc8daa36ab422334c34c634")); -- cgit v1.2.3 From 20c2c9eaf19a30bf7cd3182ad3f09af6336404f9 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 4 Feb 2020 21:20:53 -0800 Subject: Add content length --- .../java/org/traccar/protocol/GlobalstarProtocolDecoder.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java index 26af8d5af..14b1ff8c5 100644 --- a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2020 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. @@ -23,6 +23,7 @@ import io.netty.channel.Channel; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import org.traccar.BaseHttpProtocolDecoder; @@ -50,6 +51,7 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedList; @@ -103,20 +105,22 @@ public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder { ByteBuf content = Unpooled.buffer(); transformer.transform(new DOMSource(document), new StreamResult(new ByteBufOutputStream(content))); - FullHttpResponse response = new DefaultFullHttpResponse( - HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); if (channel != null) { + FullHttpResponse response = new DefaultFullHttpResponse( + HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); + response.headers().add(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); } } - @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { FullHttpRequest request = (FullHttpRequest) msg; + sendResponse(channel, "test"); + Document document = documentBuilder.parse(new ByteBufferBackedInputStream(request.content().nioBuffer())); NodeList nodes = (NodeList) messageExpression.evaluate(document, XPathConstants.NODESET); -- cgit v1.2.3 From 211dffbcc7d6e43238e7560af968a018b410d60c Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 4 Feb 2020 21:29:04 -0800 Subject: Fix build issue --- src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java | 1 - 1 file changed, 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java index 14b1ff8c5..e2406881a 100644 --- a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java @@ -51,7 +51,6 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedList; -- cgit v1.2.3 From 7e9c68727d65c858264a493003f73195e4f51210 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 4 Feb 2020 22:04:48 -0800 Subject: Support old Java versions --- src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java index d25c02414..e957a6911 100644 --- a/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/ArnaviBinaryProtocolDecoder.java @@ -27,6 +27,7 @@ import org.traccar.helper.Checksum; import org.traccar.model.Position; import java.net.SocketAddress; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.util.Date; import java.util.LinkedList; @@ -63,7 +64,7 @@ public class ArnaviBinaryProtocolDecoder extends BaseProtocolDecoder { response.writeByte(0x04); response.writeByte(0x00); ByteBuffer time = ByteBuffer.allocate(4).putInt((int) (System.currentTimeMillis() / 1000)); - time.position(0); + ((Buffer) time).position(0); response.writeByte(Checksum.modulo256(time.slice())); response.writeBytes(time); } -- cgit v1.2.3 From 2c0563a4f7d4c89551c23c13f17249b5f1b4665a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 4 Feb 2020 22:33:53 -0800 Subject: Implement support for iButton --- .../java/org/traccar/protocol/SuntechProtocolDecoder.java | 15 +++++++++++++-- .../org/traccar/protocol/SuntechProtocolDecoderTest.java | 4 ++++ 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java index 915f764e1..7e520ab3a 100644 --- a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java @@ -614,10 +614,21 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_OUTPUT, buf.readUnsignedByte()); } + int alertId = 0; if (BitUtil.check(mask, 19)) { - int value = buf.readUnsignedByte(); + alertId = buf.readUnsignedByte(); if (type == 0x82) { - position.set(Position.KEY_ALARM, decodeAlert(value)); + position.set(Position.KEY_ALARM, decodeAlert(alertId)); + } + } + + if (BitUtil.check(mask, 20)) { + buf.readUnsignedShort(); // alert mod + } + + if (BitUtil.check(mask, 21)) { + if (alertId == 59) { + position.set(Position.KEY_DRIVER_UNIQUE_ID, ByteBufUtil.hexDump(buf.readSlice(8))); } } diff --git a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java index ad9be942f..82f0a29e1 100644 --- a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java @@ -62,6 +62,10 @@ public class SuntechProtocolDecoderTest extends ProtocolTest { SuntechProtocolDecoder decoder = new SuntechProtocolDecoder(null); + verifyAttribute(decoder, binary( + "82004d05800000553fffff360100100114020410293902ccccf102dc007b00053c00476fa18469e87f000000000b0100003b00081d00000113f3f8010000049e00000000000000001d00000113f3f801"), + Position.KEY_DRIVER_UNIQUE_ID, "1d00000113f3f801"); + verifyPosition(decoder, buffer( "ST410STT;007638094;426;01;24153;724;4;-65;365;0;24161;724;4;365;0;0;24162;724;4;365;0;0;24363;724;4;365;0;0;24151;724;4;365;0;0;24991;724;4;365;0;0;24373;724;4;365;0;0;3.98;1;0176;2;016;20200106;19:18:04;-15.571860;-056.062637;000.852;238.28;6;1;201")); -- cgit v1.2.3 From eaacf2e139b15e8d8c25f15b2d1559245184fffa Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 5 Feb 2020 21:29:55 -0800 Subject: Cell info attributes --- src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java index 946652b03..6f4f9f75e 100644 --- a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java @@ -259,9 +259,16 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { int mcc = buf.readUnsignedShort(); int mnc = BitUtil.check(mcc, 15) ? buf.readUnsignedShort() : buf.readUnsignedByte(); + int lac = buf.readUnsignedShort(); + int cid = buf.readUnsignedMedium(); + + position.set("mcc", mcc); + position.set("mnc", mnc); + position.set("lac", lac); + position.set("cid", cid); position.setNetwork(new Network(CellTower.from( - BitUtil.to(mcc, 15), mnc, buf.readUnsignedShort(), buf.readUnsignedMedium()))); + BitUtil.to(mcc, 15), mnc, lac, cid))); if (length > 9) { buf.skipBytes(length - 9); -- cgit v1.2.3 From e193ae4656a6e0555565b35e8c657ae0777b156b Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 6 Feb 2020 23:16:11 -0800 Subject: Decode additional data --- .../org/traccar/protocol/BlueProtocolDecoder.java | 30 +++++++++++++++++++++- .../traccar/protocol/BlueProtocolDecoderTest.java | 13 ++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/BlueProtocolDecoder.java b/src/main/java/org/traccar/protocol/BlueProtocolDecoder.java index 61edcd101..f35ac6fbe 100644 --- a/src/main/java/org/traccar/protocol/BlueProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/BlueProtocolDecoder.java @@ -66,6 +66,19 @@ public class BlueProtocolDecoder extends BaseProtocolDecoder { } } + private String decodeAlarm(int value) { + switch (value) { + case 1: + return Position.ALARM_SOS; + case 8: + return Position.ALARM_OVERSPEED; + case 19: + return Position.ALARM_LOW_POWER; + default: + return null; + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -123,10 +136,25 @@ public class BlueProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // status 2 buf.readUnsignedByte(); // status 3 - buf.readUnsignedByte(); // status 4 + + status = buf.readUnsignedByte(); // status 4 + int ignition = BitUtil.between(status, 2, 4); + if (ignition == 0b01) { + position.set(Position.KEY_IGNITION, false); + } + if (ignition == 0b10) { + position.set(Position.KEY_IGNITION, true); + } + buf.readUnsignedByte(); // status 5 buf.readUnsignedByte(); // status 6 + position.set(Position.KEY_STATUS, buf.readUnsignedShort()); + + } else if (type == 0x81) { + + position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedByte())); + } else if (type == 0x84) { sendResponse(channel, index); diff --git a/src/test/java/org/traccar/protocol/BlueProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/BlueProtocolDecoderTest.java index 9f3254824..4aa50e56b 100644 --- a/src/test/java/org/traccar/protocol/BlueProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/BlueProtocolDecoderTest.java @@ -2,6 +2,7 @@ package org.traccar.protocol; import org.junit.Test; import org.traccar.ProtocolTest; +import org.traccar.model.Position; public class BlueProtocolDecoderTest extends ProtocolTest { @@ -10,6 +11,18 @@ public class BlueProtocolDecoderTest extends ProtocolTest { BlueProtocolDecoder decoder = new BlueProtocolDecoder(null); + verifyAttribute(decoder, binary( + "AA0056860080E3E79E0C811F80000114020207170520011F00407F8005EE1938113B270000000000000000140202071705005AC7A621121F0002000100B7000080110000000000001A3A0000000001F400000000000078"), + Position.KEY_ALARM, Position.ALARM_SOS); + + verifyAttribute(decoder, binary( + "AA004A860080E3E79E20015FBE40148005EE193B113B263700000000000000140202080C09005AC7A621125F0002000000BB000000000000000000001A3A0007000001F400000000000008"), + Position.KEY_IGNITION, true); + + verifyAttribute(decoder, binary( + "AA004A860080E3E79E200160BE40148005EE193B113B263700000000000000140202080C13005AC7A62112600002000000B7000000110000000000001A3A0007000001F400000000000012"), + Position.KEY_STATUS, 0x11); + verifyPosition(decoder, binary( "aa00550000813f6f840b840380001032000000002001030040008005ee1938113b26f300000000000000140114082833044d27602112030002000000b70000020000000000000000650000001601f4000000000000e4")); -- cgit v1.2.3 From d9d79d6e4900b144a66a3e85fdd78c4b9b0c9bd3 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 9 Feb 2020 09:43:06 -0800 Subject: Add content type --- src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java index e2406881a..08f0c088d 100644 --- a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java @@ -107,7 +107,9 @@ public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder { if (channel != null) { FullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); - response.headers().add(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); + response.headers() + .add(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()) + .add(HttpHeaderNames.CONTENT_TYPE, "text/xml"); channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); } } -- cgit v1.2.3 From 9f074b062271e5e46612ef0149dd8e2269c22222 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 10 Feb 2020 22:45:25 -0800 Subject: Revert "Cell info attributes" This reverts commit eaacf2e1 --- src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java index 6f4f9f75e..946652b03 100644 --- a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java @@ -259,16 +259,9 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { int mcc = buf.readUnsignedShort(); int mnc = BitUtil.check(mcc, 15) ? buf.readUnsignedShort() : buf.readUnsignedByte(); - int lac = buf.readUnsignedShort(); - int cid = buf.readUnsignedMedium(); - - position.set("mcc", mcc); - position.set("mnc", mnc); - position.set("lac", lac); - position.set("cid", cid); position.setNetwork(new Network(CellTower.from( - BitUtil.to(mcc, 15), mnc, lac, cid))); + BitUtil.to(mcc, 15), mnc, buf.readUnsignedShort(), buf.readUnsignedMedium()))); if (length > 9) { buf.skipBytes(length - 9); -- cgit v1.2.3 From f144438bdcf1385d8f3e9dbd42b9b90e28f750e4 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 10 Feb 2020 22:57:09 -0800 Subject: Support wifi networks --- .../org/traccar/protocol/HuaShengProtocolDecoder.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java index 920898039..eac06bbfe 100644 --- a/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java @@ -28,6 +28,7 @@ import org.traccar.helper.UnitsConverter; import org.traccar.model.CellTower; import org.traccar.model.Network; import org.traccar.model.Position; +import org.traccar.model.WifiAccessPoint; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; @@ -139,6 +140,8 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_ODOMETER, buf.readUnsignedShort() * 1000); + Network network = new Network(); + while (buf.readableBytes() > 4) { int subtype = buf.readUnsignedShort(); int length = buf.readUnsignedShort() - 4; @@ -164,7 +167,6 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder { Position.KEY_VIN, buf.readCharSequence(length, StandardCharsets.US_ASCII).toString()); break; case 0x0020: - Network network = new Network(); String[] cells = buf.readCharSequence( length, StandardCharsets.US_ASCII).toString().split("\\+"); for (String cell : cells) { @@ -173,7 +175,14 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder { Integer.parseInt(values[0]), Integer.parseInt(values[1]), Integer.parseInt(values[2], 16), Integer.parseInt(values[3], 16))); } - position.setNetwork(network); + break; + case 0x0021: + String[] points = buf.readCharSequence( + length, StandardCharsets.US_ASCII).toString().split("\\+"); + for (String point : points) { + String[] values = point.split("@"); + network.addWifiAccessPoint(WifiAccessPoint.from(values[0], Integer.parseInt(values[1]))); + } break; default: buf.skipBytes(length); @@ -181,6 +190,10 @@ public class HuaShengProtocolDecoder extends BaseProtocolDecoder { } } + if (network.getCellTowers() != null || network.getWifiAccessPoints() != null) { + position.setNetwork(network); + } + sendResponse(channel, MSG_POSITION_RSP, index, null); return position; -- cgit v1.2.3 From 83618b94c380b2f31b65eba20ee295c824cd2726 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 10 Feb 2020 23:10:23 -0800 Subject: Fix response message --- .../org/traccar/protocol/GatorProtocolDecoder.java | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java index 043839be9..cce23288a 100644 --- a/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2013 - 2020 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. @@ -23,6 +23,7 @@ import org.traccar.DeviceSession; import org.traccar.NetworkMessage; import org.traccar.Protocol; import org.traccar.helper.BcdUtil; +import org.traccar.helper.Checksum; import org.traccar.helper.DateBuilder; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; @@ -58,16 +59,16 @@ public class GatorProtocolDecoder extends BaseProtocolDecoder { return String.format("%02d%02d%02d%02d%02d", d1, d2, d3, d4, d5); } - private void sendResponse(Channel channel, SocketAddress remoteAddress, byte calibration) { + private void sendResponse(Channel channel, SocketAddress remoteAddress, int type, int checksum) { if (channel != null) { ByteBuf response = Unpooled.buffer(); - response.writeByte(0x24); response.writeByte(0x24); // header - response.writeByte(MSG_HEARTBEAT); // size - response.writeShort(5); - response.writeByte(calibration); - response.writeByte(0); // main order - response.writeByte(0); // slave order - response.writeByte(1); // calibration + response.writeShort(0x2424); // header + response.writeByte(MSG_HEARTBEAT); + response.writeShort(5); // length + response.writeByte(checksum); + response.writeByte(type); + response.writeByte(0); // subtype + response.writeByte(Checksum.sum(response.nioBuffer(2, response.writerIndex()))); response.writeByte(0x0D); channel.writeAndFlush(new NetworkMessage(response, remoteAddress)); } @@ -87,7 +88,7 @@ public class GatorProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()); - sendResponse(channel, remoteAddress, buf.getByte(buf.writerIndex() - 2)); + sendResponse(channel, remoteAddress, type, buf.getByte(buf.writerIndex() - 2)); if (type == MSG_POSITION_DATA || type == MSG_ROLLCALL_RESPONSE || type == MSG_ALARM_DATA || type == MSG_BLIND_AREA) { -- cgit v1.2.3 From c860f15e6a541c72d901d928941912edb943883e Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 15 Feb 2020 11:01:15 -0800 Subject: Fix checksum calculation --- src/main/java/org/traccar/protocol/GatorProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java index cce23288a..087861635 100644 --- a/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java @@ -68,7 +68,7 @@ public class GatorProtocolDecoder extends BaseProtocolDecoder { response.writeByte(checksum); response.writeByte(type); response.writeByte(0); // subtype - response.writeByte(Checksum.sum(response.nioBuffer(2, response.writerIndex()))); + response.writeByte(Checksum.xor(response.nioBuffer(2, response.writerIndex()))); response.writeByte(0x0D); channel.writeAndFlush(new NetworkMessage(response, remoteAddress)); } -- cgit v1.2.3 From 8bf4c171e1771eb89506a87ba8435776ee61286e Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 15 Feb 2020 11:11:01 -0800 Subject: Fix ADC decoding --- src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java | 2 +- src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java index 7e520ab3a..978d768be 100644 --- a/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java @@ -397,7 +397,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { if (isIncludeAdc(deviceSession.getDeviceId())) { for (int i = 1; i <= 3; i++) { - if (!values[index++].isEmpty()) { + if (index < values.length && !values[index++].isEmpty()) { position.set(Position.PREFIX_ADC + i, Double.parseDouble(values[index - 1])); } } diff --git a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java index 82f0a29e1..692a13131 100644 --- a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java @@ -13,6 +13,11 @@ public class SuntechProtocolDecoderTest extends ProtocolTest { decoder.setHbm(true); decoder.setIncludeAdc(true); + + verifyAttribute(decoder, buffer( + "ST600STT;008594432;20;492;20200212;18:58:30;060bb0e1;334;20;36bb;45;+19.337897;-099.064489;000.398;000.00;12;1;5049883;13.61;100100;2;1198;013762;4.2;1;4.68"), + Position.PREFIX_ADC + 1, 4.68); + decoder.setIncludeTemp(true); verifyAttribute(decoder, buffer( -- cgit v1.2.3 From 81858280f7477da619aaf1adca972827847b47cb Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 15 Feb 2020 11:16:43 -0800 Subject: Decode driving behavior --- src/main/java/org/traccar/protocol/BceProtocolDecoder.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java index c71cdffd9..68d4447ec 100644 --- a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -217,9 +217,9 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedShortLE(); } if (BitUtil.check(mask, 6)) { - buf.readUnsignedByte(); // maximum acceleration - buf.readUnsignedByte(); // maximum deceleration - buf.readUnsignedByte(); // maximum cornering + position.set("maxAcceleration", buf.readUnsignedByte()); + position.set("maxBraking", buf.readUnsignedByte()); + position.set("maxCornering", buf.readUnsignedByte()); } if (BitUtil.check(mask, 7)) { buf.skipBytes(16); -- cgit v1.2.3 From f8c83c4f7f517b7482bdf7f29a3704903b876855 Mon Sep 17 00:00:00 2001 From: Edward Valley Date: Sat, 15 Feb 2020 20:23:08 -0500 Subject: Changes after review --- src/main/java/org/traccar/MainModule.java | 7 +++ src/main/java/org/traccar/WebDataHandler.java | 64 +++++++++++++-------------- src/main/java/org/traccar/config/Keys.java | 32 +++++++------- 3 files changed, 54 insertions(+), 49 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index 3acd19b6a..24448ef51 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -73,6 +73,7 @@ import org.traccar.reports.model.TripsConfig; import javax.annotation.Nullable; import javax.ws.rs.client.Client; +import io.netty.util.Timer; public class MainModule extends AbstractModule { @@ -375,6 +376,12 @@ public class MainModule extends AbstractModule { return new DriverEventHandler(identityManager); } + @Singleton + @Provides + public static Timer provideGlobalTimer() { + return GlobalTimer.getTimer(); + } + @Override protected void configure() { binder().requireExplicitBindings(); diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index e2f7c1e8b..58b9ca73b 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -18,6 +18,7 @@ package org.traccar; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.netty.channel.ChannelHandler; +import io.netty.util.Timer; import io.netty.util.Timeout; import io.netty.util.TimerTask; import org.slf4j.Logger; @@ -66,11 +67,11 @@ public class WebDataHandler extends BaseDataHandler { private final boolean json; private final boolean retryEnabled; - private final int retryDelayMin; - private final int retryDelayMax; - private final int deliveryPendingLimit; + private final int retryDelay; + private final int retryCount; + private final int retryLimit; - private AtomicInteger deliveryPendingCurrent; + private AtomicInteger deliveryPending; @Inject public WebDataHandler( @@ -84,11 +85,11 @@ public class WebDataHandler extends BaseDataHandler { this.json = config.getBoolean(Keys.FORWARD_JSON); this.retryEnabled = config.getBoolean(Keys.FORWARD_RETRY_ENABLE); - this.retryDelayMin = config.getInteger(Keys.FORWARD_RETRY_DELAY_MIN, 1); - this.retryDelayMax = config.getInteger(Keys.FORWARD_RETRY_DELAY_MAX, 10); - this.deliveryPendingLimit = config.getInteger(Keys.FORWARD_RETRY_PENDING_LIMIT, 100); + this.retryDelay = config.getInteger(Keys.FORWARD_RETRY_DELAY, 100); + this.retryCount = config.getInteger(Keys.FORWARD_RETRY_COUNT, 10); + this.retryLimit = config.getInteger(Keys.FORWARD_RETRY_LIMIT, 100); - this.deliveryPendingCurrent = new AtomicInteger(0); + this.deliveryPending = new AtomicInteger(0); } private static String formatSentence(Position position) { @@ -183,7 +184,7 @@ public class WebDataHandler extends BaseDataHandler { class AsyncRequestAndCallback implements InvocationCallback { - private int delay = retryDelayMin; + private int retries = 0; private Map payload; private Invocation.Builder requestBuilder; @@ -208,7 +209,7 @@ public class WebDataHandler extends BaseDataHandler { payload = prepareJsonPayload(position); } - deliveryPendingCurrent.incrementAndGet(); + deliveryPending.incrementAndGet(); send(); } @@ -222,40 +223,37 @@ public class WebDataHandler extends BaseDataHandler { } private void retry() { + boolean ok = false; try { - String message = "Position forwarding failed."; - if (!retryEnabled) { - LOGGER.warn(message); - } else { - int pending = deliveryPendingCurrent.get(); - if (pending <= deliveryPendingLimit) { - LOGGER.warn(message + " Pending: " + pending - + ". Retrying in " + delay + " seconds."); - GlobalTimer.getTimer().newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) { + if (retryEnabled && deliveryPending.get() <= retryLimit && retries < retryCount) { + Main.getInjector().getInstance(Timer.class).newTimeout(new TimerTask() { + @Override + public void run(Timeout timeout) { + boolean ok = false; + try { if (!timeout.isCancelled()) { - if (delay < retryDelayMax) { - delay++; - } send(); + ok = true; + } + } finally { + if (!ok) { + deliveryPending.decrementAndGet(); } } - }, delay, TimeUnit.SECONDS); - return; - } - LOGGER.warn(message + " Pending: " + pending - + ". Delivery will not be retried."); + } + }, retryDelay * (int) Math.pow(2, retries++), TimeUnit.MILLISECONDS); + ok = true; } - } catch (Exception e) { + } finally { + int pending = ok ? deliveryPending.get() : deliveryPending.decrementAndGet(); + LOGGER.warn("Position forwarding failed: " + pending + " pending"); } - deliveryPendingCurrent.decrementAndGet(); } @Override public void completed(Response response) { - if (response.getStatus() == 200) { - deliveryPendingCurrent.decrementAndGet(); + if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) { + deliveryPending.decrementAndGet(); } else { retry(); } diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 999a1d6df..d88b36d28 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -101,35 +101,35 @@ public final class Keys { "forward.json", Boolean.class); /** - * Position forwarding retrying enable. When enabled, additional attempts are made to deliver positions. - * If initial delivery fails, because of an unreachable server or an HTTP response different from '200 OK', - * the software waits for 'forward.retry.delay.min' seconds to retry delivery. On subsequent failures, this - * delay is incremented by 1 second up to 'forward.retry.delay.max'. Positions pending to be delivered - * are limited to 'forward.retry.pending.limit'. If this limit is reached, positions get discarded. + * Position forwarding retrying enable. When enabled, additional attempts are made to deliver positions. If initial + * delivery fails, because of an unreachable server or an HTTP response different from '2xx', the software waits + * for 'forward.retry.delay' milliseconds to retry delivery. On subsequent failures, this delay is duplicated. + * If forwarding is retried for 'forward.retry.count', retrying is canceled and the position is dropped. Positions + * pending to be delivered are limited to 'forward.retry.limit'. If this limit is reached, positions get discarded. */ public static final ConfigKey FORWARD_RETRY_ENABLE = new ConfigKey( "forward.retry.enable", Boolean.class); /** - * Position forwarding retry minimum delay in seconds. - * Can be set to anything greater than 0. Defaults to 1 second. + * Position forwarding retry first delay in milliseconds. + * Can be set to anything greater than 0. Defaults to 100 milliseconds. */ - public static final ConfigKey FORWARD_RETRY_DELAY_MIN = new ConfigKey( - "forward.retry.delay.min", Integer.class); + public static final ConfigKey FORWARD_RETRY_DELAY = new ConfigKey( + "forward.retry.delay", Integer.class); /** - * Position forwarding retry maximum delay in seconds. - * Can be set to anything greater than 0. Defaults to 10 seconds. + * Position forwarding retry maximum retries. + * Can be set to anything greater than 0. Defaults to 10 retries. */ - public static final ConfigKey FORWARD_RETRY_DELAY_MAX = new ConfigKey( - "forward.retry.delay.max", Integer.class); + public static final ConfigKey FORWARD_RETRY_COUNT = new ConfigKey( + "forward.retry.count", Integer.class); /** - * Position forwarding retry pending limit. + * Position forwarding retry pending positions limit. * Can be set to anything greater than 0. Defaults to 100 positions. */ - public static final ConfigKey FORWARD_RETRY_PENDING_LIMIT = new ConfigKey( - "forward.retry.pending.limit", Integer.class); + public static final ConfigKey FORWARD_RETRY_LIMIT = new ConfigKey( + "forward.retry.limit", Integer.class); /** * Boolean flag to enable or disable position filtering. -- cgit v1.2.3 From b6fe2bd75a3541d6fe63a6b6161ed04b773e37a6 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 15 Feb 2020 21:50:18 -0800 Subject: Provide default URL --- src/main/java/org/traccar/geocoder/OpenCageGeocoder.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/geocoder/OpenCageGeocoder.java b/src/main/java/org/traccar/geocoder/OpenCageGeocoder.java index 822b6e91e..56161e52c 100644 --- a/src/main/java/org/traccar/geocoder/OpenCageGeocoder.java +++ b/src/main/java/org/traccar/geocoder/OpenCageGeocoder.java @@ -1,6 +1,6 @@ /* * Copyright 2014 - 2015 Stefaan Van Dooren (stefaan.vandooren@gmail.com) - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -21,8 +21,16 @@ import javax.json.JsonObject; public class OpenCageGeocoder extends JsonGeocoder { + private static String formatUrl(String url, String key) { + if (url == null) { + url = "https://api.opencagedata.com/geocode/v1"; + } + url += "/json?q=%f,%f&no_annotations=1&key=" + key; + return url; + } + public OpenCageGeocoder(String url, String key, int cacheSize, AddressFormat addressFormat) { - super(url + "/json?q=%f,%f&no_annotations=1&key=" + key, cacheSize, addressFormat); + super(formatUrl(url, key), cacheSize, addressFormat); } @Override -- cgit v1.2.3 From d199eb36f3b70d80f0a2cffead5777c7998c4e31 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 15 Feb 2020 22:01:58 -0800 Subject: Provide default URLs --- src/main/java/org/traccar/geocoder/FactualGeocoder.java | 12 ++++++++++-- src/main/java/org/traccar/geocoder/GisgraphyGeocoder.java | 12 ++++++++---- src/main/java/org/traccar/geocoder/MapQuestGeocoder.java | 12 ++++++++++-- src/test/java/org/traccar/geocoder/GeocoderTest.java | 2 +- 4 files changed, 29 insertions(+), 9 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/geocoder/FactualGeocoder.java b/src/main/java/org/traccar/geocoder/FactualGeocoder.java index c7a68c293..f540eb8fe 100644 --- a/src/main/java/org/traccar/geocoder/FactualGeocoder.java +++ b/src/main/java/org/traccar/geocoder/FactualGeocoder.java @@ -1,6 +1,6 @@ /* * Copyright 2014 - 2015 Stefaan Van Dooren (stefaan.vandooren@gmail.com) - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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,8 +20,16 @@ import javax.json.JsonObject; public class FactualGeocoder extends JsonGeocoder { + private static String formatUrl(String url, String key) { + if (url == null) { + url = "https://api.factual.com/geotag"; + } + url += "?latitude=%f&longitude=%f&KEY=" + key; + return url; + } + public FactualGeocoder(String url, String key, int cacheSize, AddressFormat addressFormat) { - super(url + "?latitude=%f&longitude=%f&KEY=" + key, cacheSize, addressFormat); + super(formatUrl(url, key), cacheSize, addressFormat); } @Override diff --git a/src/main/java/org/traccar/geocoder/GisgraphyGeocoder.java b/src/main/java/org/traccar/geocoder/GisgraphyGeocoder.java index 3a173f985..b4881a006 100644 --- a/src/main/java/org/traccar/geocoder/GisgraphyGeocoder.java +++ b/src/main/java/org/traccar/geocoder/GisgraphyGeocoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -19,12 +19,16 @@ import javax.json.JsonObject; public class GisgraphyGeocoder extends JsonGeocoder { - public GisgraphyGeocoder(AddressFormat addressFormat) { - this("http://services.gisgraphy.com/reversegeocoding/search", 0, addressFormat); + private static String formatUrl(String url) { + if (url == null) { + url = "http://services.gisgraphy.com/reversegeocoding/search"; + } + url += "?format=json&lat=%f&lng=%f&from=1&to=1"; + return url; } public GisgraphyGeocoder(String url, int cacheSize, AddressFormat addressFormat) { - super(url + "?format=json&lat=%f&lng=%f&from=1&to=1", cacheSize, addressFormat); + super(formatUrl(url), cacheSize, addressFormat); } @Override diff --git a/src/main/java/org/traccar/geocoder/MapQuestGeocoder.java b/src/main/java/org/traccar/geocoder/MapQuestGeocoder.java index 4029e3f07..8dc3f76f0 100644 --- a/src/main/java/org/traccar/geocoder/MapQuestGeocoder.java +++ b/src/main/java/org/traccar/geocoder/MapQuestGeocoder.java @@ -1,6 +1,6 @@ /* * Copyright 2014 - 2015 Stefaan Van Dooren (stefaan.vandooren@gmail.com) - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -21,8 +21,16 @@ import javax.json.JsonObject; public class MapQuestGeocoder extends JsonGeocoder { + private static String formatUrl(String url, String key) { + if (url == null) { + url = "http://www.mapquestapi.com/geocoding/v1/reverse"; + } + url += "?key=" + key + "&location=%f,%f"; + return url; + } + public MapQuestGeocoder(String url, String key, int cacheSize, AddressFormat addressFormat) { - super(url + "?key=" + key + "&location=%f,%f", cacheSize, addressFormat); + super(formatUrl(url, key), cacheSize, addressFormat); } @Override diff --git a/src/test/java/org/traccar/geocoder/GeocoderTest.java b/src/test/java/org/traccar/geocoder/GeocoderTest.java index 9f59d0b23..e70719b89 100644 --- a/src/test/java/org/traccar/geocoder/GeocoderTest.java +++ b/src/test/java/org/traccar/geocoder/GeocoderTest.java @@ -32,7 +32,7 @@ public class GeocoderTest { @Ignore @Test public void testGisgraphy() { - Geocoder geocoder = new GisgraphyGeocoder(new AddressFormat()); + Geocoder geocoder = new GisgraphyGeocoder(null, 0, new AddressFormat()); String address = geocoder.getAddress(48.8530000, 2.3400000, null); assertEquals("Rue du Jardinet, Paris, Île-de-France, FR", address); } -- cgit v1.2.3 From 4512941667653c15a28e0917024c04b73238005a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 18 Feb 2020 21:27:12 -0800 Subject: Convert decoded values --- src/main/java/org/traccar/protocol/BceProtocolDecoder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java index 68d4447ec..54136382c 100644 --- a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java @@ -113,7 +113,7 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte()); } if (BitUtil.check(mask, 4)) { - position.set(Position.KEY_RPM, buf.readUnsignedShortLE()); + position.set(Position.KEY_RPM, buf.readUnsignedShortLE() * 0.0125); } if (BitUtil.check(mask, 5)) { position.set(Position.KEY_HOURS, buf.readUnsignedIntLE()); @@ -122,7 +122,7 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE()); } if (BitUtil.check(mask, 7)) { - position.set(Position.KEY_COOLANT_TEMP, (int) buf.readByte()); + position.set(Position.KEY_COOLANT_TEMP, buf.readByte() - 40); } if (BitUtil.check(mask, 8)) { position.set("fuel2", buf.readUnsignedByte()); -- cgit v1.2.3 From 0f4695199a9a6c212bbe7021aa11db775eb2b7e5 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 18 Feb 2020 21:39:04 -0800 Subject: Support UDP protocol --- src/main/java/org/traccar/protocol/EskyProtocol.java | 10 +++++++++- src/main/java/org/traccar/protocol/EskyProtocolDecoder.java | 11 +++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/EskyProtocol.java b/src/main/java/org/traccar/protocol/EskyProtocol.java index aaa92da58..fb047c207 100644 --- a/src/main/java/org/traccar/protocol/EskyProtocol.java +++ b/src/main/java/org/traccar/protocol/EskyProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -33,6 +33,14 @@ public class EskyProtocol extends BaseProtocol { pipeline.addLast(new EskyProtocolDecoder(EskyProtocol.this)); } }); + addServer(new TrackerServer(true, getName()) { + @Override + protected void addProtocolHandlers(PipelineBuilder pipeline) { + pipeline.addLast(new StringEncoder()); + pipeline.addLast(new StringDecoder()); + pipeline.addLast(new EskyProtocolDecoder(EskyProtocol.this)); + } + }); } } diff --git a/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java b/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java index 641b2e28f..d9de110f4 100644 --- a/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -16,8 +16,10 @@ package org.traccar.protocol; import io.netty.channel.Channel; +import io.netty.channel.socket.DatagramChannel; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; +import org.traccar.NetworkMessage; import org.traccar.Protocol; import org.traccar.helper.Parser; import org.traccar.helper.PatternBuilder; @@ -35,7 +37,7 @@ public class EskyProtocolDecoder extends BaseProtocolDecoder { private static final Pattern PATTERN = new PatternBuilder() .expression("..;") // header - .number("d+;") // index + .number("(d+);") // index .number("(d+);") // imei .text("R;") // data type .number("(d+)[+;]") // satellites @@ -63,6 +65,11 @@ public class EskyProtocolDecoder extends BaseProtocolDecoder { return null; } + int index = parser.nextInt(); + if (channel instanceof DatagramChannel) { + channel.writeAndFlush(new NetworkMessage("ACK," + index + "#", remoteAddress)); + } + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); if (deviceSession == null) { return null; -- cgit v1.2.3 From 1bbd6f12b34eaed8699fe943130142d9f2638df8 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 19 Feb 2020 23:00:06 -0800 Subject: Remove test confirmation --- src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java index 08f0c088d..382509793 100644 --- a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java @@ -120,8 +120,6 @@ public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder { FullHttpRequest request = (FullHttpRequest) msg; - sendResponse(channel, "test"); - Document document = documentBuilder.parse(new ByteBufferBackedInputStream(request.content().nioBuffer())); NodeList nodes = (NodeList) messageExpression.evaluate(document, XPathConstants.NODESET); -- cgit v1.2.3 From deb519ebd6798450509afaf4067e140edd7eb0d0 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 22 Feb 2020 11:34:57 -0800 Subject: Fix concurrency issues --- .../org/traccar/api/ExtendedObjectResource.java | 2 +- .../org/traccar/database/BaseObjectManager.java | 60 +++++++++-- .../java/org/traccar/database/CommandsManager.java | 29 ++++- .../java/org/traccar/database/DeviceManager.java | 118 +++++++++++++++------ .../java/org/traccar/database/DriversManager.java | 51 ++++++--- .../traccar/database/ExtendedObjectManager.java | 78 +++++++++----- .../java/org/traccar/database/GroupsManager.java | 5 +- .../org/traccar/database/SimpleObjectManager.java | 30 +++--- .../java/org/traccar/database/UsersManager.java | 6 +- 9 files changed, 276 insertions(+), 103 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/api/ExtendedObjectResource.java b/src/main/java/org/traccar/api/ExtendedObjectResource.java index 007a7b1bd..9e554217e 100644 --- a/src/main/java/org/traccar/api/ExtendedObjectResource.java +++ b/src/main/java/org/traccar/api/ExtendedObjectResource.java @@ -55,8 +55,8 @@ public class ExtendedObjectResource extends BaseObjectResou Context.getPermissionsManager().checkDevice(getUserId(), deviceId); result.retainAll(manager.getDeviceItems(deviceId)); } - return manager.getItems(result); + return manager.getItems(result); } } diff --git a/src/main/java/org/traccar/database/BaseObjectManager.java b/src/main/java/org/traccar/database/BaseObjectManager.java index 8bf9ef860..e274e5aba 100644 --- a/src/main/java/org/traccar/database/BaseObjectManager.java +++ b/src/main/java/org/traccar/database/BaseObjectManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +23,8 @@ import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +34,8 @@ public class BaseObjectManager { private static final Logger LOGGER = LoggerFactory.getLogger(BaseObjectManager.class); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final DataManager dataManager; private Map items; @@ -43,6 +47,22 @@ public class BaseObjectManager { refreshItems(); } + protected final void readLock() { + lock.readLock().lock(); + } + + protected final void readUnlock() { + lock.readLock().unlock(); + } + + protected final void writeLock() { + lock.writeLock().lock(); + } + + protected final void writeUnlock() { + lock.writeLock().unlock(); + } + protected final DataManager getDataManager() { return dataManager; } @@ -52,12 +72,18 @@ public class BaseObjectManager { } public T getById(long itemId) { - return items.get(itemId); + try { + readLock(); + return items.get(itemId); + } finally { + readUnlock(); + } } public void refreshItems() { if (dataManager != null) { try { + writeLock(); Collection databaseItems = dataManager.getObjects(baseClass); if (items == null) { items = new ConcurrentHashMap<>(databaseItems.size()); @@ -78,12 +104,19 @@ public class BaseObjectManager { } } catch (SQLException error) { LOGGER.warn("Error refreshing items", error); + } finally { + writeUnlock(); } } } protected void addNewItem(T item) { - items.put(item.getId(), item); + try { + writeLock(); + items.put(item.getId(), item); + } finally { + writeUnlock(); + } } public void addItem(T item) throws SQLException { @@ -92,7 +125,12 @@ public class BaseObjectManager { } protected void updateCachedItem(T item) { - items.put(item.getId(), item); + try { + writeLock(); + items.put(item.getId(), item); + } finally { + writeUnlock(); + } } public void updateItem(T item) throws SQLException { @@ -101,7 +139,12 @@ public class BaseObjectManager { } protected void removeCachedItem(long itemId) { - items.remove(itemId); + try { + writeLock(); + items.remove(itemId); + } finally { + writeUnlock(); + } } public void removeItem(long itemId) throws SQLException { @@ -121,7 +164,12 @@ public class BaseObjectManager { } public Set getAllItems() { - return items.keySet(); + try { + readLock(); + return items.keySet(); + } finally { + readUnlock(); + } } } diff --git a/src/main/java/org/traccar/database/CommandsManager.java b/src/main/java/org/traccar/database/CommandsManager.java index dc9512d9e..de6eeeba8 100644 --- a/src/main/java/org/traccar/database/CommandsManager.java +++ b/src/main/java/org/traccar/database/CommandsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -142,14 +142,33 @@ public class CommandsManager extends ExtendedObjectManager { } private Queue getDeviceQueue(long deviceId) { - if (!deviceQueues.containsKey(deviceId)) { - deviceQueues.put(deviceId, new ConcurrentLinkedQueue()); + Queue deviceQueue; + try { + readLock(); + deviceQueue = deviceQueues.get(deviceId); + } finally { + readUnlock(); + } + if (deviceQueue != null) { + return deviceQueue; + } else { + try { + writeLock(); + return deviceQueues.computeIfAbsent(deviceId, key -> new ConcurrentLinkedQueue<>()); + } finally { + writeUnlock(); + } } - return deviceQueues.get(deviceId); } public void sendQueuedCommands(ActiveDevice activeDevice) { - Queue deviceQueue = deviceQueues.get(activeDevice.getDeviceId()); + Queue deviceQueue; + try { + readLock(); + deviceQueue = deviceQueues.get(activeDevice.getDeviceId()); + } finally { + readUnlock(); + } if (deviceQueue != null) { Command command = deviceQueue.poll(); while (command != null) { diff --git a/src/main/java/org/traccar/database/DeviceManager.java b/src/main/java/org/traccar/database/DeviceManager.java index fa95adeb2..fe17f7ced 100644 --- a/src/main/java/org/traccar/database/DeviceManager.java +++ b/src/main/java/org/traccar/database/DeviceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2020 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. @@ -58,11 +58,16 @@ public class DeviceManager extends BaseObjectManager implements Identity public DeviceManager(DataManager dataManager) { super(dataManager, Device.class); this.config = Context.getConfig(); - if (devicesByPhone == null) { - devicesByPhone = new ConcurrentHashMap<>(); - } - if (devicesByUniqueId == null) { - devicesByUniqueId = new ConcurrentHashMap<>(); + try { + writeLock(); + if (devicesByPhone == null) { + devicesByPhone = new ConcurrentHashMap<>(); + } + if (devicesByUniqueId == null) { + devicesByUniqueId = new ConcurrentHashMap<>(); + } + } finally { + writeUnlock(); } dataRefreshDelay = config.getLong("database.refreshDelay", DEFAULT_REFRESH_DELAY) * 1000; lookupGroupsAttribute = config.getBoolean("deviceManager.lookupGroupsAttribute"); @@ -108,11 +113,20 @@ public class DeviceManager extends BaseObjectManager implements Identity @Override public Device getByUniqueId(String uniqueId) throws SQLException { - boolean forceUpdate = !devicesByUniqueId.containsKey(uniqueId) && !config.getBoolean("database.ignoreUnknown"); - + boolean forceUpdate; + try { + readLock(); + forceUpdate = !devicesByUniqueId.containsKey(uniqueId) && !config.getBoolean("database.ignoreUnknown"); + } finally { + readUnlock(); + } updateDeviceCache(forceUpdate); - - return devicesByUniqueId.get(uniqueId); + try { + readLock(); + return devicesByUniqueId.get(uniqueId); + } finally { + readUnlock(); + } } @Override @@ -134,7 +148,12 @@ public class DeviceManager extends BaseObjectManager implements Identity } public Device getDeviceByPhone(String phone) { - return devicesByPhone.get(phone); + try { + readLock(); + return devicesByPhone.get(phone); + } finally { + readUnlock(); + } } @Override @@ -176,8 +195,7 @@ public class DeviceManager extends BaseObjectManager implements Identity } public Set getAllManagedItems(long userId) { - Set result = new HashSet<>(); - result.addAll(getAllUserItems(userId)); + Set result = new HashSet<>(getAllUserItems(userId)); for (long managedUserId : Context.getUsersManager().getUserItems(userId)) { result.addAll(getAllUserItems(managedUserId)); } @@ -186,34 +204,68 @@ public class DeviceManager extends BaseObjectManager implements Identity @Override public Set getManagedItems(long userId) { - Set result = new HashSet<>(); - result.addAll(getUserItems(userId)); + Set result = new HashSet<>(getUserItems(userId)); for (long managedUserId : Context.getUsersManager().getUserItems(userId)) { result.addAll(getUserItems(managedUserId)); } return result; } - private void putUniqueDeviceId(Device device) { - if (devicesByUniqueId == null) { - devicesByUniqueId = new ConcurrentHashMap<>(getAllItems().size()); + private void addByUniqueId(Device device) { + try { + writeLock(); + if (devicesByUniqueId == null) { + devicesByUniqueId = new ConcurrentHashMap<>(); + } + devicesByUniqueId.put(device.getUniqueId(), device); + } finally { + writeUnlock(); + } + } + + private void removeByUniqueId(String deviceUniqueId) { + try { + writeLock(); + if (devicesByUniqueId != null) { + devicesByUniqueId.remove(deviceUniqueId); + } + } finally { + writeUnlock(); + } + } + + private void addByPhone(Device device) { + try { + writeLock(); + if (devicesByPhone == null) { + devicesByPhone = new ConcurrentHashMap<>(); + } + devicesByPhone.put(device.getPhone(), device); + } finally { + writeUnlock(); } - devicesByUniqueId.put(device.getUniqueId(), device); } - private void putPhone(Device device) { - if (devicesByPhone == null) { - devicesByPhone = new ConcurrentHashMap<>(getAllItems().size()); + private void removeByPhone(String phone) { + if (phone == null || phone.isEmpty()) { + return; + } + try { + writeLock(); + if (devicesByPhone != null) { + devicesByPhone.remove(phone); + } + } finally { + writeUnlock(); } - devicesByPhone.put(device.getPhone(), device); } @Override protected void addNewItem(Device device) { super.addNewItem(device); - putUniqueDeviceId(device); + addByUniqueId(device); if (device.getPhone() != null && !device.getPhone().isEmpty()) { - putPhone(device); + addByPhone(device); } if (Context.getGeofenceManager() != null) { Position lastPosition = getLastPosition(device.getId()); @@ -234,18 +286,16 @@ public class DeviceManager extends BaseObjectManager implements Identity cachedDevice.setDisabled(device.getDisabled()); cachedDevice.setAttributes(device.getAttributes()); if (!device.getUniqueId().equals(cachedDevice.getUniqueId())) { - devicesByUniqueId.remove(cachedDevice.getUniqueId()); + removeByUniqueId(cachedDevice.getUniqueId()); cachedDevice.setUniqueId(device.getUniqueId()); - putUniqueDeviceId(cachedDevice); + addByUniqueId(cachedDevice); } if (device.getPhone() != null && !device.getPhone().isEmpty() && !device.getPhone().equals(cachedDevice.getPhone())) { String phone = cachedDevice.getPhone(); - if (phone != null && !phone.isEmpty()) { - devicesByPhone.remove(phone); - } + removeByPhone(phone); cachedDevice.setPhone(device.getPhone()); - putPhone(cachedDevice); + addByPhone(cachedDevice); } } @@ -256,10 +306,8 @@ public class DeviceManager extends BaseObjectManager implements Identity String deviceUniqueId = cachedDevice.getUniqueId(); String phone = cachedDevice.getPhone(); super.removeCachedItem(deviceId); - devicesByUniqueId.remove(deviceUniqueId); - if (phone != null && !phone.isEmpty()) { - devicesByPhone.remove(phone); - } + removeByUniqueId(deviceUniqueId); + removeByPhone(phone); } positions.remove(deviceId); } diff --git a/src/main/java/org/traccar/database/DriversManager.java b/src/main/java/org/traccar/database/DriversManager.java index 930951460..d111cd643 100644 --- a/src/main/java/org/traccar/database/DriversManager.java +++ b/src/main/java/org/traccar/database/DriversManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,22 +27,44 @@ public class DriversManager extends ExtendedObjectManager { public DriversManager(DataManager dataManager) { super(dataManager, Driver.class); - if (driversByUniqueId == null) { - driversByUniqueId = new ConcurrentHashMap<>(); + try { + writeLock(); + if (driversByUniqueId == null) { + driversByUniqueId = new ConcurrentHashMap<>(); + } + } finally { + writeUnlock(); } } - private void putUniqueDriverId(Driver driver) { - if (driversByUniqueId == null) { - driversByUniqueId = new ConcurrentHashMap<>(getAllItems().size()); + private void addByUniqueId(Driver driver) { + try { + writeLock(); + if (driversByUniqueId == null) { + driversByUniqueId = new ConcurrentHashMap<>(); + } + driversByUniqueId.put(driver.getUniqueId(), driver); + } finally { + writeUnlock(); + } + } + + private void removeByUniqueId(String driverUniqueId) { + try { + writeLock(); + if (driversByUniqueId == null) { + driversByUniqueId = new ConcurrentHashMap<>(); + } + driversByUniqueId.remove(driverUniqueId); + } finally { + writeUnlock(); } - driversByUniqueId.put(driver.getUniqueId(), driver); } @Override protected void addNewItem(Driver driver) { super.addNewItem(driver); - putUniqueDriverId(driver); + addByUniqueId(driver); } @Override @@ -50,9 +72,9 @@ public class DriversManager extends ExtendedObjectManager { Driver cachedDriver = getById(driver.getId()); cachedDriver.setName(driver.getName()); if (!driver.getUniqueId().equals(cachedDriver.getUniqueId())) { - driversByUniqueId.remove(cachedDriver.getUniqueId()); + removeByUniqueId(cachedDriver.getUniqueId()); cachedDriver.setUniqueId(driver.getUniqueId()); - putUniqueDriverId(cachedDriver); + addByUniqueId(cachedDriver); } cachedDriver.setAttributes(driver.getAttributes()); } @@ -63,11 +85,16 @@ public class DriversManager extends ExtendedObjectManager { if (cachedDriver != null) { String driverUniqueId = cachedDriver.getUniqueId(); super.removeCachedItem(driverId); - driversByUniqueId.remove(driverUniqueId); + removeByUniqueId(driverUniqueId); } } public Driver getDriverByUniqueId(String uniqueId) { - return driversByUniqueId.get(uniqueId); + try { + readLock(); + return driversByUniqueId.get(uniqueId); + } finally { + readUnlock(); + } } } diff --git a/src/main/java/org/traccar/database/ExtendedObjectManager.java b/src/main/java/org/traccar/database/ExtendedObjectManager.java index ceb85b537..93e5820fb 100644 --- a/src/main/java/org/traccar/database/ExtendedObjectManager.java +++ b/src/main/java/org/traccar/database/ExtendedObjectManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,24 +45,45 @@ public abstract class ExtendedObjectManager extends SimpleO } public final Set getGroupItems(long groupId) { - if (!groupItems.containsKey(groupId)) { - groupItems.put(groupId, new HashSet()); + try { + readLock(); + Set result = groupItems.get(groupId); + if (result != null) { + return new HashSet<>(result); + } else { + return new HashSet<>(); + } + } finally { + readUnlock(); } - return groupItems.get(groupId); } public final Set getDeviceItems(long deviceId) { - if (!deviceItems.containsKey(deviceId)) { - deviceItems.put(deviceId, new HashSet()); + try { + readLock(); + Set result = deviceItems.get(deviceId); + if (result != null) { + return new HashSet<>(result); + } else { + return new HashSet<>(); + } + } finally { + readUnlock(); } - return deviceItems.get(deviceId); } public Set getAllDeviceItems(long deviceId) { - if (!deviceItemsWithGroups.containsKey(deviceId)) { - deviceItemsWithGroups.put(deviceId, new HashSet()); + try { + readLock(); + Set result = deviceItemsWithGroups.get(deviceId); + if (result != null) { + return new HashSet<>(result); + } else { + return new HashSet<>(); + } + } finally { + readUnlock(); } - return deviceItemsWithGroups.get(deviceId); } @Override @@ -74,41 +95,48 @@ public abstract class ExtendedObjectManager extends SimpleO public void refreshExtendedPermissions() { if (getDataManager() != null) { try { - Collection databaseGroupPermissions = getDataManager().getPermissions(Group.class, getBaseClass()); - groupItems.clear(); - for (Permission groupPermission : databaseGroupPermissions) { - getGroupItems(groupPermission.getOwnerId()).add(groupPermission.getPropertyId()); - } - Collection databaseDevicePermissions = getDataManager().getPermissions(Device.class, getBaseClass()); + writeLock(); + + groupItems.clear(); deviceItems.clear(); deviceItemsWithGroups.clear(); + for (Permission groupPermission : databaseGroupPermissions) { + groupItems + .computeIfAbsent(groupPermission.getOwnerId(), key -> new HashSet<>()) + .add(groupPermission.getPropertyId()); + } + for (Permission devicePermission : databaseDevicePermissions) { - getDeviceItems(devicePermission.getOwnerId()).add(devicePermission.getPropertyId()); - getAllDeviceItems(devicePermission.getOwnerId()).add(devicePermission.getPropertyId()); + deviceItems + .computeIfAbsent(devicePermission.getOwnerId(), key -> new HashSet<>()) + .add(devicePermission.getPropertyId()); + deviceItemsWithGroups + .computeIfAbsent(devicePermission.getOwnerId(), key -> new HashSet<>()) + .add(devicePermission.getPropertyId()); } for (Device device : Context.getDeviceManager().getAllDevices()) { long groupId = device.getGroupId(); - while (groupId != 0) { - getAllDeviceItems(device.getId()).addAll(getGroupItems(groupId)); + while (groupId > 0) { + deviceItemsWithGroups + .computeIfAbsent(device.getId(), key -> new HashSet<>()) + .addAll(groupItems.getOrDefault(groupId, new HashSet<>())); Group group = Context.getGroupsManager().getById(groupId); - if (group != null) { - groupId = group.getGroupId(); - } else { - groupId = 0; - } + groupId = group != null ? group.getGroupId() : 0; } } } catch (SQLException | ClassNotFoundException error) { LOGGER.warn("Refresh permissions error", error); + } finally { + writeUnlock(); } } } diff --git a/src/main/java/org/traccar/database/GroupsManager.java b/src/main/java/org/traccar/database/GroupsManager.java index d8404c614..81f1968aa 100644 --- a/src/main/java/org/traccar/database/GroupsManager.java +++ b/src/main/java/org/traccar/database/GroupsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -95,8 +95,7 @@ public class GroupsManager extends BaseObjectManager implements Managable @Override public Set getManagedItems(long userId) { - Set result = new HashSet<>(); - result.addAll(getUserItems(userId)); + Set result = getUserItems(userId); for (long managedUserId : Context.getUsersManager().getUserItems(userId)) { result.addAll(getUserItems(managedUserId)); } diff --git a/src/main/java/org/traccar/database/SimpleObjectManager.java b/src/main/java/org/traccar/database/SimpleObjectManager.java index 15dda4520..eb8284d4e 100644 --- a/src/main/java/org/traccar/database/SimpleObjectManager.java +++ b/src/main/java/org/traccar/database/SimpleObjectManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,16 +42,22 @@ public abstract class SimpleObjectManager extends BaseObjec @Override public final Set getUserItems(long userId) { - if (!userItems.containsKey(userId)) { - userItems.put(userId, new HashSet()); + try { + readLock(); + Set result = userItems.get(userId); + if (result != null) { + return new HashSet<>(result); + } else { + return new HashSet<>(); + } + } finally { + readUnlock(); } - return userItems.get(userId); } @Override public Set getManagedItems(long userId) { - Set result = new HashSet<>(); - result.addAll(getUserItems(userId)); + Set result = getUserItems(userId); for (long managedUserId : Context.getUsersManager().getUserItems(userId)) { result.addAll(getUserItems(managedUserId)); } @@ -71,16 +77,16 @@ public abstract class SimpleObjectManager extends BaseObjec public final void refreshUserItems() { if (getDataManager() != null) { try { - if (userItems != null) { - userItems.clear(); - } else { - userItems = new ConcurrentHashMap<>(); - } + writeLock(); + userItems = new ConcurrentHashMap<>(); for (Permission permission : getDataManager().getPermissions(User.class, getBaseClass())) { - getUserItems(permission.getOwnerId()).add(permission.getPropertyId()); + Set items = userItems.computeIfAbsent(permission.getOwnerId(), key -> new HashSet<>()); + items.add(permission.getPropertyId()); } } catch (SQLException | ClassNotFoundException error) { LOGGER.warn("Error getting permissions", error); + } finally { + writeUnlock(); } } } diff --git a/src/main/java/org/traccar/database/UsersManager.java b/src/main/java/org/traccar/database/UsersManager.java index 576a9e6c7..b741a85b6 100644 --- a/src/main/java/org/traccar/database/UsersManager.java +++ b/src/main/java/org/traccar/database/UsersManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,6 @@ */ package org.traccar.database; -import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -73,8 +72,7 @@ public class UsersManager extends SimpleObjectManager { @Override public Set getManagedItems(long userId) { - Set result = new HashSet<>(); - result.addAll(getUserItems(userId)); + Set result = getUserItems(userId); result.add(userId); return result; } -- cgit v1.2.3 From 8d6e45331cb4ba86faaabfe7d1f9e7ccfd6e824d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 22 Feb 2020 16:59:43 -0800 Subject: Support health monitoring --- setup/default.xml | 1 + setup/traccar.service | 3 + src/main/java/org/traccar/Main.java | 59 ++++++++------ .../java/org/traccar/api/HealthCheckService.java | 90 ++++++++++++++++++++++ 4 files changed, 130 insertions(+), 23 deletions(-) create mode 100644 src/main/java/org/traccar/api/HealthCheckService.java (limited to 'src/main/java/org') diff --git a/setup/default.xml b/setup/default.xml index 1d82ad926..561b57a57 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -14,6 +14,7 @@ 8082 ./web max-age=3600,public + true false google diff --git a/setup/traccar.service b/setup/traccar.service index fe746dda8..6ae24ab8a 100644 --- a/setup/traccar.service +++ b/setup/traccar.service @@ -8,6 +8,9 @@ WorkingDirectory=/opt/traccar ExecStart=/opt/traccar/jre/bin/java -jar tracker-server.jar conf/traccar.xml SyslogIdentifier=traccar SuccessExitStatus=143 +WatchdogSec=100 +Restart=on-failure +RestartSec=10 [Install] WantedBy=multi-user.target diff --git a/src/main/java/org/traccar/Main.java b/src/main/java/org/traccar/Main.java index 6ebd1d399..f5690b26d 100644 --- a/src/main/java/org/traccar/Main.java +++ b/src/main/java/org/traccar/Main.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2012 - 2020 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. @@ -19,6 +19,7 @@ import com.google.inject.Guice; import com.google.inject.Injector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.traccar.api.HealthCheckService; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; @@ -105,6 +106,27 @@ public final class Main { } } + private static void scheduleHealthCheck() { + HealthCheckService service = new HealthCheckService(); + if (service.isEnabled()) { + new Timer().scheduleAtFixedRate( + service.createTask(), service.getPeriod(), service.getPeriod()); + } + } + + private static void scheduleDatabaseCleanup() { + new Timer().scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + try { + Context.getDataManager().clearHistory(); + } catch (SQLException error) { + LOGGER.warn("Clear history error", error); + } + } + }, 0, CLEAN_PERIOD); + } + public static void run(String configFile) { try { Context.init(configFile); @@ -118,35 +140,26 @@ public final class Main { Context.getWebServer().start(); } - new Timer().scheduleAtFixedRate(new TimerTask() { + new Timer().schedule(new TimerTask() { @Override public void run() { - try { - Context.getDataManager().clearHistory(); - } catch (SQLException error) { - LOGGER.warn("Clear history error", error); - } + Context.getWebServer().stop(); } - }, 0, CLEAN_PERIOD); + }, 10 * 60 * 1000); - Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - LOGGER.error("Thread exception", e); - } - }); + scheduleHealthCheck(); + scheduleDatabaseCleanup(); - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - LOGGER.info("Shutting down server..."); + Thread.setDefaultUncaughtExceptionHandler((t, e) -> LOGGER.error("Thread exception", e)); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + LOGGER.info("Shutting down server..."); - if (Context.getWebServer() != null) { - Context.getWebServer().stop(); - } - Context.getServerManager().stop(); + if (Context.getWebServer() != null) { + Context.getWebServer().stop(); } - }); + Context.getServerManager().stop(); + })); } catch (Exception e) { LOGGER.error("Main method error", e); throw new RuntimeException(e); diff --git a/src/main/java/org/traccar/api/HealthCheckService.java b/src/main/java/org/traccar/api/HealthCheckService.java new file mode 100644 index 000000000..cd2856dfa --- /dev/null +++ b/src/main/java/org/traccar/api/HealthCheckService.java @@ -0,0 +1,90 @@ +/* + * Copyright 2020 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.api; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.traccar.Context; + +import java.util.TimerTask; + +public class HealthCheckService { + + private static final Logger LOGGER = LoggerFactory.getLogger(HealthCheckService.class); + + private SystemD systemD; + + private boolean enabled; + private long period; + + public HealthCheckService() { + if (Context.getConfig().getBoolean("web.healthCheck") + && System.getProperty("os.name").toLowerCase().startsWith("linux")) { + try { + systemD = Native.load("systemd", SystemD.class); + String watchdogTimer = System.getenv("WATCHDOG_USEC"); + if (watchdogTimer != null && !watchdogTimer.isEmpty()) { + period = Long.parseLong(watchdogTimer) / 1000 * 4 / 5; + } + if (period > 0) { + LOGGER.info("Health check enabled with period {}", period); + enabled = true; + } + } catch (UnsatisfiedLinkError e) { + LOGGER.warn("No systemd support", e); + } + } + } + + public boolean isEnabled() { + return enabled; + } + + public long getPeriod() { + return period; + } + + private String getUrl() { + String address = Context.getConfig().getString("web.address", "localhost"); + int port = Context.getConfig().getInteger("web.port", 8082); + return "http://" + address + ":" + port + "/api/server"; + } + + public TimerTask createTask() { + return new TimerTask() { + @Override + public void run() { + LOGGER.debug("Health check running"); + int status = Context.getClient().target(getUrl()).request().get().getStatus(); + if (status == 200) { + int result = systemD.sd_notify(0, "WATCHDOG=1"); + if (result < 0) { + LOGGER.warn("Health check notify error {}", result); + } + } else { + LOGGER.warn("Health check failed with status {}", status); + } + } + }; + } + + interface SystemD extends Library { + int sd_notify(int unset_environment, String state); + } + +} -- cgit v1.2.3 From 43abeeb1dad9e15681d87b299752d057914ae29e Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 22 Feb 2020 17:43:09 -0800 Subject: Fix style check --- gradle/checkstyle.xml | 4 ++++ src/main/java/org/traccar/api/HealthCheckService.java | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/gradle/checkstyle.xml b/gradle/checkstyle.xml index 72950c7bd..e4df54d8c 100644 --- a/gradle/checkstyle.xml +++ b/gradle/checkstyle.xml @@ -5,6 +5,8 @@ + + @@ -51,6 +53,8 @@ + + diff --git a/src/main/java/org/traccar/api/HealthCheckService.java b/src/main/java/org/traccar/api/HealthCheckService.java index cd2856dfa..1e8f0d731 100644 --- a/src/main/java/org/traccar/api/HealthCheckService.java +++ b/src/main/java/org/traccar/api/HealthCheckService.java @@ -84,7 +84,8 @@ public class HealthCheckService { } interface SystemD extends Library { - int sd_notify(int unset_environment, String state); + @SuppressWarnings("checkstyle:MethodName") + int sd_notify(@SuppressWarnings("checkstyle:ParameterName") int unset_environment, String state); } } -- cgit v1.2.3 From b23b1efe6b3dba788f3acb87b403522097114208 Mon Sep 17 00:00:00 2001 From: alexthefifth <10274240+alexthefifth@users.noreply.github.com> Date: Sun, 23 Feb 2020 15:08:41 -0500 Subject: Do not require password (default when programming MT600 via USB) --- src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java index 7ad99b37e..3ce6438f8 100644 --- a/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java @@ -38,7 +38,7 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder { private static final Pattern PATTERN_HEADER = new PatternBuilder() .number("#(d+)") // imei .expression("#[^#]*") // user - .number("#d+") // password + .number("#d*") // password .groupBegin() .number("#([01])") // door .number("#(d+)") // fuel voltage -- cgit v1.2.3 From 7db2926c38edafb4cbd9b2cda1a98b5567836bc1 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 23 Feb 2020 17:34:08 -0800 Subject: Remove debugging code --- src/main/java/org/traccar/Main.java | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/Main.java b/src/main/java/org/traccar/Main.java index f5690b26d..47d6e91df 100644 --- a/src/main/java/org/traccar/Main.java +++ b/src/main/java/org/traccar/Main.java @@ -140,13 +140,6 @@ public final class Main { Context.getWebServer().start(); } - new Timer().schedule(new TimerTask() { - @Override - public void run() { - Context.getWebServer().stop(); - } - }, 10 * 60 * 1000); - scheduleHealthCheck(); scheduleDatabaseCleanup(); -- cgit v1.2.3 From 1049b01a22e28acb69ea530de824608b72c8222c Mon Sep 17 00:00:00 2001 From: Edward Valley Date: Tue, 25 Feb 2020 18:27:26 -0500 Subject: Changes after review --- src/main/java/org/traccar/MainModule.java | 2 +- src/main/java/org/traccar/WebDataHandler.java | 142 +++++++++++++------------- 2 files changed, 74 insertions(+), 70 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index 24448ef51..1d5508f5a 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -378,7 +378,7 @@ public class MainModule extends AbstractModule { @Singleton @Provides - public static Timer provideGlobalTimer() { + public static Timer provideTimer() { return GlobalTimer.getTimer(); } diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index 58b9ca73b..39e54616b 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -53,11 +53,11 @@ import java.util.concurrent.atomic.AtomicInteger; @ChannelHandler.Sharable public class WebDataHandler extends BaseDataHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(WebDataHandler.class); + private static final String KEY_POSITION = "position"; private static final String KEY_DEVICE = "device"; - private static final Logger LOGGER = LoggerFactory.getLogger(WebDataHandler.class); - private final IdentityManager identityManager; private final ObjectMapper objectMapper; private final Client client; @@ -179,94 +179,98 @@ public class WebDataHandler extends BaseDataHandler { return request; } - @Override - protected Position handlePosition(Position position) { + class AsyncRequestAndCallback implements InvocationCallback, TimerTask { - class AsyncRequestAndCallback implements InvocationCallback { + private int retries = 0; + private Map payload; + private Invocation.Builder requestBuilder; - private int retries = 0; - private Map payload; - private Invocation.Builder requestBuilder; + AsyncRequestAndCallback(Position position) { - AsyncRequestAndCallback(Position position) { - - String formattedUrl; - try { - formattedUrl = json ? url : formatRequest(position); - } catch (UnsupportedEncodingException | JsonProcessingException e) { - throw new RuntimeException("Forwarding formatting error", e); - } + String formattedUrl; + try { + formattedUrl = json ? url : formatRequest(position); + } catch (UnsupportedEncodingException | JsonProcessingException e) { + throw new RuntimeException("Forwarding formatting error", e); + } - requestBuilder = client.target(formattedUrl).request(); - if (header != null && !header.isEmpty()) { - for (String line: header.split("\\r?\\n")) { - String[] values = line.split(":", 2); - requestBuilder.header(values[0].trim(), values[1].trim()); - } + requestBuilder = client.target(formattedUrl).request(); + if (header != null && !header.isEmpty()) { + for (String line: header.split("\\r?\\n")) { + String[] values = line.split(":", 2); + requestBuilder.header(values[0].trim(), values[1].trim()); } + } - if (json) { - payload = prepareJsonPayload(position); - } + if (json) { + payload = prepareJsonPayload(position); + } - deliveryPending.incrementAndGet(); + deliveryPending.incrementAndGet(); + } - send(); + private void send() { + if (json) { + requestBuilder.async().post(Entity.json(payload), this); + } else { + requestBuilder.async().get(this); } + } - private void send() { - if (json) { - requestBuilder.async().post(Entity.json(payload), this); - } else { - requestBuilder.async().get(this); + private void retry() { + boolean scheduled = false; + try { + if (retryEnabled && deliveryPending.get() <= retryLimit && retries < retryCount) { + schedule(); + scheduled = true; } + } finally { + int pending = scheduled ? deliveryPending.get() : deliveryPending.decrementAndGet(); + LOGGER.warn("Position forwarding failed: " + pending + " pending"); } + } - private void retry() { - boolean ok = false; - try { - if (retryEnabled && deliveryPending.get() <= retryLimit && retries < retryCount) { - Main.getInjector().getInstance(Timer.class).newTimeout(new TimerTask() { - @Override - public void run(Timeout timeout) { - boolean ok = false; - try { - if (!timeout.isCancelled()) { - send(); - ok = true; - } - } finally { - if (!ok) { - deliveryPending.decrementAndGet(); - } - } - } - }, retryDelay * (int) Math.pow(2, retries++), TimeUnit.MILLISECONDS); - ok = true; - } - } finally { - int pending = ok ? deliveryPending.get() : deliveryPending.decrementAndGet(); - LOGGER.warn("Position forwarding failed: " + pending + " pending"); - } + private void schedule() { + Main.getInjector().getInstance(Timer.class).newTimeout( + this, retryDelay * (int) Math.pow(2, retries++), TimeUnit.MILLISECONDS); + } + + @Override + public void completed(Response response) { + if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) { + deliveryPending.decrementAndGet(); + } else { + retry(); } + } + + @Override + public void failed(Throwable throwable) { + retry(); + } - @Override - public void completed(Response response) { - if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) { + @Override + public void run(Timeout timeout) { + boolean sent = false; + try { + if (!timeout.isCancelled()) { + send(); + sent = true; + } + } finally { + if (!sent) { deliveryPending.decrementAndGet(); - } else { - retry(); } } + } - @Override - public void failed(Throwable throwable) { - retry(); - } + } - } + @Override + protected Position handlePosition(Position position) { - new AsyncRequestAndCallback(position); + AsyncRequestAndCallback request = new AsyncRequestAndCallback(position); + request.send(); return position; } -- cgit v1.2.3 From 886a1ac0550c5aecb13222668f4ca35758ec92d1 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 25 Feb 2020 21:40:33 -0800 Subject: Decode ignition value --- src/main/java/org/traccar/protocol/EskyProtocolDecoder.java | 6 +++++- src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java b/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java index d9de110f4..f0ae0bc91 100644 --- a/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java @@ -21,6 +21,7 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; import org.traccar.NetworkMessage; import org.traccar.Protocol; +import org.traccar.helper.BitUtil; import org.traccar.helper.Parser; import org.traccar.helper.PatternBuilder; import org.traccar.helper.UnitsConverter; @@ -88,7 +89,10 @@ public class EskyProtocolDecoder extends BaseProtocolDecoder { position.setCourse(parser.nextDouble()); if (parser.hasNext(3)) { - position.set(Position.KEY_INPUT, parser.nextHexInt()); + int input = parser.nextHexInt(); + position.set(Position.KEY_IGNITION, !BitUtil.check(input, 0)); + position.set(Position.PREFIX_IN + 1, !BitUtil.check(input, 1)); + position.set(Position.PREFIX_IN + 2, !BitUtil.check(input, 2)); position.set(Position.KEY_EVENT, parser.nextInt()); position.set(Position.KEY_ODOMETER, parser.nextInt()); } diff --git a/src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java index da7df0ab2..4db80c7ce 100644 --- a/src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java @@ -2,6 +2,7 @@ package org.traccar.protocol; import org.junit.Test; import org.traccar.ProtocolTest; +import org.traccar.model.Position; public class EskyProtocolDecoderTest extends ProtocolTest { @@ -10,6 +11,10 @@ public class EskyProtocolDecoderTest extends ProtocolTest { EskyProtocolDecoder decoder = new EskyProtocolDecoder(null); + verifyAttribute(decoder, text( + "ET;0;860337031078319;R;6+190317162511+41.32536+19.83144+0.14+0+0x0+0+18460312+0+1233+192"), + Position.KEY_IGNITION, true); + verifyPosition(decoder, text( "EO;0;861311006461908;R;6;180420104751;2.97896;101.65091;0.75;320;3398;1;|")); -- cgit v1.2.3 From e4f6e74e57ab743b65d49ae00f6624a20ca0291e Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 25 Feb 2020 22:26:18 -0800 Subject: Encode LDAP user names --- .../java/org/traccar/database/LdapProvider.java | 36 ++++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/database/LdapProvider.java b/src/main/java/org/traccar/database/LdapProvider.java index d8b5c9f52..447904b35 100644 --- a/src/main/java/org/traccar/database/LdapProvider.java +++ b/src/main/java/org/traccar/database/LdapProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -81,7 +81,7 @@ public class LdapProvider { if (this.adminFilter != null) { try { InitialDirContext context = initContext(); - String searchString = adminFilter.replace(":login", accountName); + String searchString = adminFilter.replace(":login", encodeForLdap(accountName)); SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration results = context.search(searchBase, searchString, searchControls); @@ -107,7 +107,7 @@ public class LdapProvider { private SearchResult lookupUser(String accountName) throws NamingException { InitialDirContext context = initContext(); - String searchString = searchFilter.replace(":login", accountName); + String searchString = searchFilter.replace(":login", encodeForLdap(accountName)); SearchControls searchControls = new SearchControls(); String[] attributeFilter = {idAttribute, nameAttribute, mailAttribute}; @@ -176,4 +176,34 @@ public class LdapProvider { return false; } + public String encodeForLdap(String input) { + if( input == null ) { + return null; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < input.length(); i++) { + char c = input.charAt(i); + switch (c) { + case '\\': + sb.append("\\5c"); + break; + case '*': + sb.append("\\2a"); + break; + case '(': + sb.append("\\28"); + break; + case ')': + sb.append("\\29"); + break; + case '\0': + sb.append("\\00"); + break; + default: + sb.append(c); + } + } + return sb.toString(); + } + } -- cgit v1.2.3 From 0dcb514f3a0cb66e8c3e4e7b60c9374b2579f7d2 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 25 Feb 2020 22:32:54 -0800 Subject: Fix style issue --- src/main/java/org/traccar/database/LdapProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/database/LdapProvider.java b/src/main/java/org/traccar/database/LdapProvider.java index 447904b35..a8220ea8e 100644 --- a/src/main/java/org/traccar/database/LdapProvider.java +++ b/src/main/java/org/traccar/database/LdapProvider.java @@ -177,7 +177,7 @@ public class LdapProvider { } public String encodeForLdap(String input) { - if( input == null ) { + if (input == null) { return null; } StringBuilder sb = new StringBuilder(); -- cgit v1.2.3 From a48c68d4b5fb522081c9182713a4088a66317964 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 28 Feb 2020 09:12:30 -0800 Subject: Fix ITS status decoding --- src/main/java/org/traccar/protocol/ItsProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java b/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java index e8d77f1a8..6a107d67d 100644 --- a/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java @@ -51,7 +51,7 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder { .groupEnd() .number("(d{15}),") // imei .groupBegin() - .expression("(..),") // status + .expression("([^,]{2}),") // status .or() .expression("[^,]*,") // vehicle registration .number("([01]),").optional() // valid -- cgit v1.2.3 From 1ab53d1f4911e349370542b23a5fa3fe69be7dcc Mon Sep 17 00:00:00 2001 From: Andreas Date: Sun, 1 Mar 2020 23:18:44 +0100 Subject: add support for pushover.net --- .../traccar/notification/NotificatorManager.java | 4 + .../traccar/notificators/NotificatorPushover.java | 89 ++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/main/java/org/traccar/notificators/NotificatorPushover.java (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notification/NotificatorManager.java b/src/main/java/org/traccar/notification/NotificatorManager.java index 191748379..c5f1ad8a0 100644 --- a/src/main/java/org/traccar/notification/NotificatorManager.java +++ b/src/main/java/org/traccar/notification/NotificatorManager.java @@ -32,6 +32,7 @@ import org.traccar.notificators.Notificator; import org.traccar.notificators.NotificatorSms; import org.traccar.notificators.NotificatorWeb; import org.traccar.notificators.NotificatorTelegram; +import org.traccar.notificators.NotificatorPushover; public final class NotificatorManager { @@ -61,6 +62,9 @@ public final class NotificatorManager { case "telegram": defaultNotificator = NotificatorTelegram.class.getCanonicalName(); break; + case "pushover": + defaultNotificator = NotificatorPushover.class.getCanonicalName(); + break; default: break; } diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java new file mode 100644 index 000000000..21da1f8d5 --- /dev/null +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -0,0 +1,89 @@ +/* + * Copyright 2019 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.notificators; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.traccar.Context; +import org.traccar.model.Event; +import org.traccar.model.Position; +import org.traccar.notification.NotificationFormatter; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.InvocationCallback; + +public class NotificatorPushover extends Notificator { + + private static final Logger LOGGER = LoggerFactory.getLogger(NotificatorPushover.class); + + private String url; + private String token; + private String user; + private String device; + private String title; + + public static class Message { + @JsonProperty("token") + private String token; + @JsonProperty("user") + private String user; + @JsonProperty("device") + private String device; + @JsonProperty("title") + private String title; + @JsonProperty("message") + private String message; + } + + public NotificatorPushover() { + url = "https://api.pushover.net/1/messages.json"; + // see https://pushover.net/api + token = Context.getConfig().getString("notificator.pushover.token"); // (required) token from pushover.net + user = Context.getConfig().getString("notificator.pushover.user"); // (required) user from pushover.net + device = Context.getConfig().getString("notificator.pushover.device",""); // optional: your user's device name to send the message directly to that device, rather than all of the user's devices (multiple devices may be separated by a comma) + title = Context.getConfig().getString("notificator.pushover.title",""); // optional: your message's title, otherwise your app's name is used + } + + @Override + public void sendSync(long userId, Event event, Position position) { + + Message message = new Message(); + message.token = token; + message.user = user; + message.device = device; + message.title = title; + message.message = NotificationFormatter.formatShortMessage(userId, event, position); + + Context.getClient().target(url).request() + .async().post(Entity.json(message), new InvocationCallback() { + @Override + public void completed(Object o) { + } + + @Override + public void failed(Throwable throwable) { + LOGGER.warn("Pushover API error", throwable); + } + }); + } + + @Override + public void sendAsync(long userId, Event event, Position position) { + sendSync(userId, event, position); + } + +} -- cgit v1.2.3 From 39a2742121de3e016655e9fc5d5ba886e1ab900b Mon Sep 17 00:00:00 2001 From: Andreas Date: Sun, 1 Mar 2020 23:36:54 +0100 Subject: comment too long --- src/main/java/org/traccar/notificators/NotificatorPushover.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index 21da1f8d5..29455b1a6 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -54,7 +54,8 @@ public class NotificatorPushover extends Notificator { // see https://pushover.net/api token = Context.getConfig().getString("notificator.pushover.token"); // (required) token from pushover.net user = Context.getConfig().getString("notificator.pushover.user"); // (required) user from pushover.net - device = Context.getConfig().getString("notificator.pushover.device",""); // optional: your user's device name to send the message directly to that device, rather than all of the user's devices (multiple devices may be separated by a comma) + device = Context.getConfig().getString("notificator.pushover.device",""); // optional: your user's device name to send the message directly + // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) title = Context.getConfig().getString("notificator.pushover.title",""); // optional: your message's title, otherwise your app's name is used } -- cgit v1.2.3 From 4a7a3b59c39bcfe9a6d7ed11b27074d7c1f6b418 Mon Sep 17 00:00:00 2001 From: Andreas Date: Sun, 1 Mar 2020 23:44:23 +0100 Subject: comment too long --- src/main/java/org/traccar/notificators/NotificatorPushover.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index 29455b1a6..734e38eb9 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -54,9 +54,11 @@ public class NotificatorPushover extends Notificator { // see https://pushover.net/api token = Context.getConfig().getString("notificator.pushover.token"); // (required) token from pushover.net user = Context.getConfig().getString("notificator.pushover.user"); // (required) user from pushover.net - device = Context.getConfig().getString("notificator.pushover.device",""); // optional: your user's device name to send the message directly + device = Context.getConfig().getString("notificator.pushover.device",""); // optional: + // your user's device name to send the message directly // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) - title = Context.getConfig().getString("notificator.pushover.title",""); // optional: your message's title, otherwise your app's name is used + title = Context.getConfig().getString("notificator.pushover.title",""); // optional: your message's title, + // otherwise your app's name is used } @Override -- cgit v1.2.3 From 535b0ffa9a3e435cd58d4f7ade9a4d8c6eb03623 Mon Sep 17 00:00:00 2001 From: Andreas Date: Sun, 1 Mar 2020 23:47:33 +0100 Subject: add whitespace --- src/main/java/org/traccar/notificators/NotificatorPushover.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index 734e38eb9..ff992ec8d 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -54,10 +54,10 @@ public class NotificatorPushover extends Notificator { // see https://pushover.net/api token = Context.getConfig().getString("notificator.pushover.token"); // (required) token from pushover.net user = Context.getConfig().getString("notificator.pushover.user"); // (required) user from pushover.net - device = Context.getConfig().getString("notificator.pushover.device",""); // optional: + device = Context.getConfig().getString("notificator.pushover.device", ""); // optional: // your user's device name to send the message directly // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) - title = Context.getConfig().getString("notificator.pushover.title",""); // optional: your message's title, + title = Context.getConfig().getString("notificator.pushover.title", ""); // optional: your message's title, // otherwise your app's name is used } -- cgit v1.2.3 From 96d7a6c1f8b2563c3b3fb3d4a8737e8c2d606f6e Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 4 Mar 2020 00:07:10 -0800 Subject: Support TopFlyTech variation --- src/main/java/org/traccar/protocol/T800xProtocolDecoder.java | 11 ++++++----- .../java/org/traccar/protocol/T800xProtocolDecoderTest.java | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java b/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java index 9b146ec90..3331ebb71 100644 --- a/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -177,8 +177,7 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder { } private Position decodePosition( - Channel channel, DeviceSession deviceSession, - ByteBuf buf, int type, int index, ByteBuf imei) { + Channel channel, DeviceSession deviceSession, ByteBuf buf, int type, int index, ByteBuf imei) { Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); @@ -214,8 +213,10 @@ public class T800xProtocolDecoder extends BaseProtocolDecoder { position.set(Position.PREFIX_OUT + (i + 1), BitUtil.check(io, 7 + i)); } - position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort()); - position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShort()); + if (header != 0x2626) { + position.set(Position.PREFIX_ADC + 1, buf.readUnsignedShort()); + position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShort()); + } } diff --git a/src/test/java/org/traccar/protocol/T800xProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/T800xProtocolDecoderTest.java index 28b3fc5c6..48c535c96 100644 --- a/src/test/java/org/traccar/protocol/T800xProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/T800xProtocolDecoderTest.java @@ -11,6 +11,9 @@ public class T800xProtocolDecoderTest extends ProtocolTest { T800xProtocolDecoder decoder = new T800xProtocolDecoder(null); + verifyPosition(decoder, binary( + "262602005308090865284040309670000f000f0f0000005a47c000050100000020000000008bfd0020022505185300004041dcc9d6c243b3c6410000012712400000000009e2ffffffffffffffffffffffff09")); + verifyPosition(decoder, binary( "2727040049001b0866425039645728c916190604005240000000007739d2c25b681f420000000080000081000020174105000005458216001e000000f01e00001e30d0000000000000")); -- cgit v1.2.3 From 455f96fb074cb02825c8303d0aa8eff0a848e9fd Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 4 Mar 2020 00:25:05 -0800 Subject: Decode GSM signal --- .../traccar/protocol/SolarPoweredProtocolDecoder.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/SolarPoweredProtocolDecoder.java b/src/main/java/org/traccar/protocol/SolarPoweredProtocolDecoder.java index eae37386a..6fe54b0b0 100644 --- a/src/main/java/org/traccar/protocol/SolarPoweredProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SolarPoweredProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2020 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. @@ -77,10 +77,24 @@ public class SolarPoweredProtocolDecoder extends BaseProtocolDecoder { position.setLongitude(-position.getLongitude()); } position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); - position.set(Position.KEY_DEVICE_TEMP, (int) buf.readByte()); + int temperature = buf.readUnsignedByte(); + if (BitUtil.check(temperature, 7)) { + position.set(Position.KEY_DEVICE_TEMP, -BitUtil.to(temperature, 7)); + } else { + position.set(Position.KEY_DEVICE_TEMP, BitUtil.to(temperature, 7)); + } position.set(Position.KEY_BATTERY, buf.readUnsignedByte() * 0.02); position.setCourse(buf.readUnsignedByte()); break; + case 0x83: + buf.readUnsignedInt(); // uptime + buf.readUnsignedInt(); // gps count + buf.readUnsignedInt(); // gsm count + buf.readUnsignedByte(); // positioning time + buf.readUnsignedByte(); // registration time + buf.readUnsignedByte(); // connection time + position.set(Position.KEY_RSSI, buf.readUnsignedByte()); + break; default: buf.skipBytes(length); break; -- cgit v1.2.3 From 83148e8750ba9689b4dc53f586e0ce1e23cf2032 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 4 Mar 2020 00:32:44 -0800 Subject: Convert sensor data --- src/main/java/org/traccar/protocol/BceProtocolDecoder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java index 54136382c..1b354c861 100644 --- a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java @@ -217,9 +217,9 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedShortLE(); } if (BitUtil.check(mask, 6)) { - position.set("maxAcceleration", buf.readUnsignedByte()); - position.set("maxBraking", buf.readUnsignedByte()); - position.set("maxCornering", buf.readUnsignedByte()); + position.set("maxAcceleration", buf.readUnsignedByte() * 0.02); + position.set("maxBraking", buf.readUnsignedByte() * 0.02); + position.set("maxCornering", buf.readUnsignedByte() * 0.02); } if (BitUtil.check(mask, 7)) { buf.skipBytes(16); -- cgit v1.2.3 From dd23d3becaf50ad4cdaf0064712f1f104e1c5967 Mon Sep 17 00:00:00 2001 From: Vitaliy Gergel Date: Wed, 4 Mar 2020 16:38:50 +0200 Subject: Allowing custom content type header in location forward --- src/main/java/org/traccar/WebDataHandler.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index 39e54616b..c8bb9b461 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -33,6 +33,8 @@ import org.traccar.model.Position; import org.traccar.model.Group; import javax.inject.Inject; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.client.Client; import javax.ws.rs.client.Entity; @@ -184,6 +186,7 @@ public class WebDataHandler extends BaseDataHandler { private int retries = 0; private Map payload; private Invocation.Builder requestBuilder; + private MediaType mediaType = MediaType.APPLICATION_JSON_TYPE; AsyncRequestAndCallback(Position position) { @@ -198,7 +201,12 @@ public class WebDataHandler extends BaseDataHandler { if (header != null && !header.isEmpty()) { for (String line: header.split("\\r?\\n")) { String[] values = line.split(":", 2); - requestBuilder.header(values[0].trim(), values[1].trim()); + String headerName = values[0].trim(); + String headerValue = values[1].trim(); + requestBuilder.header(headerName, headerValue); + if (headerName.equals(HttpHeaders.CONTENT_TYPE)) { + mediaType = MediaType.valueOf(headerValue); + } } } @@ -211,7 +219,11 @@ public class WebDataHandler extends BaseDataHandler { private void send() { if (json) { - requestBuilder.async().post(Entity.json(payload), this); + try { + requestBuilder.async().post(Entity.entity(objectMapper.writeValueAsString(payload), mediaType), this); + } catch (JsonProcessingException e) { + throw new RuntimeException("Failed to serialize payload to json: " + payload); + } } else { requestBuilder.async().get(this); } -- cgit v1.2.3 From e7c04c8dfaa67e5bef2d3b9c5ba8924e85045ffc Mon Sep 17 00:00:00 2001 From: Vitaliy Gergel Date: Wed, 4 Mar 2020 21:18:14 +0200 Subject: Fix code review comments and repace url variables for post request as well --- src/main/java/org/traccar/WebDataHandler.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index c8bb9b461..858b00aad 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -192,7 +192,7 @@ public class WebDataHandler extends BaseDataHandler { String formattedUrl; try { - formattedUrl = json ? url : formatRequest(position); + formattedUrl = formatRequest(position); } catch (UnsupportedEncodingException | JsonProcessingException e) { throw new RuntimeException("Forwarding formatting error", e); } @@ -203,9 +203,10 @@ public class WebDataHandler extends BaseDataHandler { String[] values = line.split(":", 2); String headerName = values[0].trim(); String headerValue = values[1].trim(); - requestBuilder.header(headerName, headerValue); if (headerName.equals(HttpHeaders.CONTENT_TYPE)) { mediaType = MediaType.valueOf(headerValue); + } else { + requestBuilder.header(headerName, headerValue); } } } @@ -220,9 +221,10 @@ public class WebDataHandler extends BaseDataHandler { private void send() { if (json) { try { - requestBuilder.async().post(Entity.entity(objectMapper.writeValueAsString(payload), mediaType), this); + Entity entity = Entity.entity(objectMapper.writeValueAsString(payload), mediaType); + requestBuilder.async().post(entity, this); } catch (JsonProcessingException e) { - throw new RuntimeException("Failed to serialize payload to json: " + payload); + throw new RuntimeException("Failed to serialize location to json", e); } } else { requestBuilder.async().get(this); -- cgit v1.2.3 From 0270f5b639166b385ac779c0d2caa41d7c408771 Mon Sep 17 00:00:00 2001 From: Vitaliy Gergel Date: Wed, 4 Mar 2020 21:54:55 +0200 Subject: Adding property to enable URL parameter in json mode --- src/main/java/org/traccar/WebDataHandler.java | 4 +++- src/main/java/org/traccar/config/Keys.java | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index 858b00aad..1af1af48a 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -67,6 +67,7 @@ public class WebDataHandler extends BaseDataHandler { private final String url; private final String header; private final boolean json; + private final boolean jsonUrlVariables; private final boolean retryEnabled; private final int retryDelay; @@ -85,6 +86,7 @@ public class WebDataHandler extends BaseDataHandler { this.url = config.getString(Keys.FORWARD_URL); this.header = config.getString(Keys.FORWARD_HEADER); this.json = config.getBoolean(Keys.FORWARD_JSON); + this.jsonUrlVariables = config.getBoolean(Keys.FORWARD_JSON_URL_VARIABLES); this.retryEnabled = config.getBoolean(Keys.FORWARD_RETRY_ENABLE); this.retryDelay = config.getInteger(Keys.FORWARD_RETRY_DELAY, 100); @@ -192,7 +194,7 @@ public class WebDataHandler extends BaseDataHandler { String formattedUrl; try { - formattedUrl = formatRequest(position); + formattedUrl = (json && !jsonUrlVariables) ? url : formatRequest(position); } catch (UnsupportedEncodingException | JsonProcessingException e) { throw new RuntimeException("Forwarding formatting error", e); } diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index d88b36d28..a5b7b780c 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -100,6 +100,13 @@ public final class Keys { public static final ConfigKey FORWARD_JSON = new ConfigKey( "forward.json", Boolean.class); + /** + * Boolean value to enable URL parameters in json mode. For example, {uniqueId} for device identifier, + * {latitude} and {longitude} for coordinates. + */ + public static final ConfigKey FORWARD_JSON_URL_VARIABLES = new ConfigKey( + "forward.json.url.variables", Boolean.class); + /** * Position forwarding retrying enable. When enabled, additional attempts are made to deliver positions. If initial * delivery fails, because of an unreachable server or an HTTP response different from '2xx', the software waits -- cgit v1.2.3 From e39eaf2e9878fe8e575b525dd2ca747e3f5342fe Mon Sep 17 00:00:00 2001 From: Andreas Date: Wed, 4 Mar 2020 21:40:43 +0100 Subject: add Pushover attrs in web interface --- .../traccar/notificators/NotificatorPushover.java | 95 +++++++++++++++++++--- traccar-web | 2 +- 2 files changed, 85 insertions(+), 12 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index ff992ec8d..ae48bd46a 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -23,6 +23,10 @@ import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.notification.NotificationFormatter; +import org.traccar.model.User; +import org.traccar.notification.PropertiesProvider; +import java.util.Properties; + import javax.ws.rs.client.Entity; import javax.ws.rs.client.InvocationCallback; @@ -30,9 +34,36 @@ public class NotificatorPushover extends Notificator { private static final Logger LOGGER = LoggerFactory.getLogger(NotificatorPushover.class); - private String url; + private static Properties getProperties(PropertiesProvider provider) { + Properties properties = new Properties(); + // (required) token from pushover.net + String token = provider.getString("notificator.pushover.token"); + if (token != null) { + properties.put("notificator.pushover.token", token); + } + // (required) user from pushover.net + String user = provider.getString("notificator.pushover.user"); + if (user != null) { + properties.put("notificator.pushover.user", user); + } + // optional: your user's device name to send the message directly + // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) + String device = provider.getString("notificator.pushover.device"); + if (device != null) { + properties.put("notificator.pushover.device", device); + } + // optional: your message's title, otherwise your app's name is used + String title = provider.getString("notificator.pushover.title"); + if (title != null) { + properties.put("notificator.pushover.title", title); + } + return properties; + } + + + private final String url; private String token; - private String user; + private String puser; private String device; private String title; @@ -50,23 +81,65 @@ public class NotificatorPushover extends Notificator { } public NotificatorPushover() { - url = "https://api.pushover.net/1/messages.json"; // see https://pushover.net/api - token = Context.getConfig().getString("notificator.pushover.token"); // (required) token from pushover.net - user = Context.getConfig().getString("notificator.pushover.user"); // (required) user from pushover.net - device = Context.getConfig().getString("notificator.pushover.device", ""); // optional: - // your user's device name to send the message directly - // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) - title = Context.getConfig().getString("notificator.pushover.title", ""); // optional: your message's title, - // otherwise your app's name is used + url = "https://api.pushover.net/1/messages.json"; } @Override public void sendSync(long userId, Event event, Position position) { + User user = Context.getPermissionsManager().getUser(userId); + + token = null; + puser = null; + device = null; + title = null; + + Properties properties = null; + + properties = getProperties(new PropertiesProvider(Context.getConfig())); + if (properties != null) { + token = properties.getProperty("notificator.pushover.token"); + puser = properties.getProperty("notificator.pushover.user"); + device = properties.getProperty("notificator.pushover.device"); + title = properties.getProperty("notificator.pushover.title"); + } + + properties = getProperties(new PropertiesProvider(user)); + if (properties != null) { + if (properties.getProperty("notificator.pushover.token") != null) { + token = properties.getProperty("notificator.pushover.token"); + } + if (properties.getProperty("notificator.pushover.user") != null) { + puser = properties.getProperty("notificator.pushover.user"); + } + if (properties.getProperty("notificator.pushover.device") != null) { + device = properties.getProperty("notificator.pushover.device"); + } + if (properties.getProperty("notificator.pushover.title") != null) { + title = properties.getProperty("notificator.pushover.title"); + } + } + + if (token == null) { + LOGGER.warn("Pushover token not found"); + return; + } + + if (puser == null) { + LOGGER.warn("Pushover user not found"); + return; + } + + if (device == null) + device = ""; + + if (title == null) + title = ""; + Message message = new Message(); message.token = token; - message.user = user; + message.user = puser; message.device = device; message.title = title; message.message = NotificationFormatter.formatShortMessage(userId, event, position); diff --git a/traccar-web b/traccar-web index e8479d77f..a587d6257 160000 --- a/traccar-web +++ b/traccar-web @@ -1 +1 @@ -Subproject commit e8479d77f13acc3b3738a180a7990b06c495f1ba +Subproject commit a587d6257dd9de70252a5b00299ccbfd7b5cb272 -- cgit v1.2.3 From b27e8213f380f3ae8c2b9503e0aaecb55c784271 Mon Sep 17 00:00:00 2001 From: Andreas Date: Wed, 4 Mar 2020 21:47:19 +0100 Subject: correction for travis-ci --- .../java/org/traccar/notificators/NotificatorPushover.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index ae48bd46a..f289e464a 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -116,11 +116,11 @@ public class NotificatorPushover extends Notificator { if (properties.getProperty("notificator.pushover.device") != null) { device = properties.getProperty("notificator.pushover.device"); } - if (properties.getProperty("notificator.pushover.title") != null) { + if (properties.getProperty("notificator.pushover.title") != null) { title = properties.getProperty("notificator.pushover.title"); } - } - + } + if (token == null) { LOGGER.warn("Pushover token not found"); return; @@ -131,11 +131,13 @@ public class NotificatorPushover extends Notificator { return; } - if (device == null) + if (device == null) { device = ""; + } - if (title == null) + if (title == null) { title = ""; + } Message message = new Message(); message.token = token; -- cgit v1.2.3 From 6b7bec4554134517b2f1835d0eb86365e4a8fe42 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 4 Mar 2020 22:35:29 -0800 Subject: Fix RPM decoding --- src/main/java/org/traccar/protocol/BceProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java index 1b354c861..a259e027a 100644 --- a/src/main/java/org/traccar/protocol/BceProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java @@ -113,7 +113,7 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_FUEL_LEVEL, buf.readUnsignedByte()); } if (BitUtil.check(mask, 4)) { - position.set(Position.KEY_RPM, buf.readUnsignedShortLE() * 0.0125); + position.set(Position.KEY_RPM, buf.readUnsignedShortLE() * 0.125); } if (BitUtil.check(mask, 5)) { position.set(Position.KEY_HOURS, buf.readUnsignedIntLE()); -- cgit v1.2.3 From bc81692c898481cd71ddc54bf05c099796132b5f Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 4 Mar 2020 22:40:46 -0800 Subject: Decode ignition value --- src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java | 7 ++++++- .../java/org/traccar/protocol/StarLinkProtocolDecoderTest.java | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java b/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java index bad6f03a9..2d1613e03 100644 --- a/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -140,6 +140,11 @@ public class StarLinkProtocolDecoder extends BaseProtocolDecoder { event = Integer.parseInt(data[i]); position.set(Position.KEY_ALARM, decodeAlarm(event)); position.set(Position.KEY_EVENT, event); + if (event == 24) { + position.set(Position.KEY_IGNITION, true); + } else if (event == 25) { + position.set(Position.KEY_IGNITION, false); + } break; case "#PDT#": position.setFixTime(dateFormat.parse(data[i])); diff --git a/src/test/java/org/traccar/protocol/StarLinkProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/StarLinkProtocolDecoderTest.java index 97246a665..459dad978 100644 --- a/src/test/java/org/traccar/protocol/StarLinkProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/StarLinkProtocolDecoderTest.java @@ -2,6 +2,7 @@ package org.traccar.protocol; import org.junit.Test; import org.traccar.ProtocolTest; +import org.traccar.model.Position; public class StarLinkProtocolDecoderTest extends ProtocolTest { @@ -10,6 +11,14 @@ public class StarLinkProtocolDecoderTest extends ProtocolTest { StarLinkProtocolDecoder decoder = new StarLinkProtocolDecoder(null); + decoder.setFormat("#IMEI#,#EDT#,#PDT#,#LAT#,#LONG#,#SPD#,#IGN#,#ODO#,#DUR#,#TDUR#,#LAC#,#CID#,#VIN#,#VBAT#,#EID#,#EDSC#,#DRV#,#SATU#,#CSS#,#OUT1#,#OUT2#"); + + verifyAttribute(decoder, text( + "$SLU862549048472545,06,25,862549048472545,200304085936,200304085937,+4126.1828,+00209.8472,013.9,0,000000,,1,2120,6306,14.452,03.980,33,External Device,0,9,67,0,0,7,0,137,13,2,5625,-11,-20,99*1F"), + Position.KEY_IGNITION, false); + + decoder.setFormat("#EDT#,#EID#,#PDT#,#LAT#,#LONG#,#SPD#,#HEAD#,#ODO#,#IN1#,#IN2#,#IN3#,#IN4#,#OUT1#,#OUT2#,#OUT3#,#OUT4#,#LAC#,#CID#,#VIN#,#VBAT#,#DEST#,#IGN#,#ENG#"); + verifyAttributes(decoder, text( "$SLU068328,06,55,170518122023,16,,,,,,000000,1,1,0,0,0,0,0,0,10443,32722,12.664,03.910,,0,0,,01000001FDB3A9*BF")); -- cgit v1.2.3 From 7f1e024bca381f93cf1d9e61dadc3bb2f4943da7 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 4 Mar 2020 22:55:06 -0800 Subject: Decode additional attributes --- .../traccar/protocol/OmnicommProtocolDecoder.java | 31 +++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/OmnicommProtocolDecoder.java b/src/main/java/org/traccar/protocol/OmnicommProtocolDecoder.java index cd8b74c9a..6e9cf52a5 100644 --- a/src/main/java/org/traccar/protocol/OmnicommProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/OmnicommProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2020 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. @@ -111,16 +111,29 @@ public class OmnicommProtocolDecoder extends BaseProtocolDecoder { Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); + if (message.hasGeneral()) { + OmnicommMessageOuterClass.OmnicommMessage.General data = message.getGeneral(); + position.set(Position.KEY_POWER, data.getUboard() * 0.1); + position.set(Position.KEY_BATTERY_LEVEL, data.getBatLife()); + } + if (message.hasNAV()) { - OmnicommMessageOuterClass.OmnicommMessage.NAV nav = message.getNAV(); + OmnicommMessageOuterClass.OmnicommMessage.NAV data = message.getNAV(); position.setValid(true); - position.setTime(new Date((nav.getGPSTime() + 1230768000) * 1000L)); // from 2009-01-01 12:00 - position.setLatitude(nav.getLAT() * 0.0000001); - position.setLongitude(nav.getLON() * 0.0000001); - position.setSpeed(UnitsConverter.knotsFromKph(nav.getGPSVel() * 0.1)); - position.setCourse(nav.getGPSDir()); - position.setAltitude(nav.getGPSAlt() * 0.1); - position.set(Position.KEY_SATELLITES, nav.getGPSNSat()); + position.setTime(new Date((data.getGPSTime() + 1230768000) * 1000L)); // from 2009-01-01 12:00 + position.setLatitude(data.getLAT() * 0.0000001); + position.setLongitude(data.getLON() * 0.0000001); + position.setSpeed(UnitsConverter.knotsFromKph(data.getGPSVel() * 0.1)); + position.setCourse(data.getGPSDir()); + position.setAltitude(data.getGPSAlt() * 0.1); + position.set(Position.KEY_SATELLITES, data.getGPSNSat()); + } + + if (message.hasLLSDt()) { + OmnicommMessageOuterClass.OmnicommMessage.LLSDt data = message.getLLSDt(); + position.set("fuel1Temp", data.getTLLS1()); + position.set("fuel1", data.getCLLS1()); + position.set("fuel1State", data.getFLLS1()); } if (position.getFixTime() != null) { -- cgit v1.2.3 From 0443367a581100b4f9abd3d96a50793d80c93e45 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 5 Mar 2020 09:22:58 -0800 Subject: Fix coordinates decoding (fix #4496) --- src/main/java/org/traccar/protocol/TelicProtocolDecoder.java | 6 +++--- src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java b/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java index 457687b2e..efe155a88 100644 --- a/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2014 - 2020 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. @@ -42,8 +42,8 @@ public class TelicProtocolDecoder extends BaseProtocolDecoder { .number("(dd)(dd)(dd)") // date (ddmmyy) .number("(dd)(dd)(dd),") // time (hhmmss) .groupBegin() - .number("(-?d{9}),") // longitude - .number("(-?d{8}),") // latitude + .number("(-?d{7,}),") // longitude + .number("(-?d{6,}),") // latitude .or() .number("(-?d+),") // longitude .number("(-?d+),") // latitude diff --git a/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java index b743cef96..7616e7e8d 100644 --- a/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java @@ -13,6 +13,9 @@ public class TelicProtocolDecoderTest extends ProtocolTest { verifyNull(decoder, text( "0026355565071347499|206|01|001002008")); + verifyPosition(decoder, text( + "023035467909228696525,280220174140,0,280220174135,-80333933,25796530,3,1,0,5,3,3,-21,319064,26202,0000,00,0,206,0,0407,0,0,18,0,3,0")); + verifyPosition(decoder, text( "052028495198,160917073641,0,160917073642,43879,511958,3,24,223,17,,,-3,142379,,0010,00,64,205,0,0499")); -- cgit v1.2.3 From 9bb835a9d45737d5090d1b78ee69310d59cb0a43 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 5 Mar 2020 09:26:06 -0800 Subject: Another minor fix --- src/main/java/org/traccar/protocol/TelicProtocolDecoder.java | 4 ++-- src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java b/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java index efe155a88..a4f9e2989 100644 --- a/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java @@ -42,8 +42,8 @@ public class TelicProtocolDecoder extends BaseProtocolDecoder { .number("(dd)(dd)(dd)") // date (ddmmyy) .number("(dd)(dd)(dd),") // time (hhmmss) .groupBegin() - .number("(-?d{7,}),") // longitude - .number("(-?d{6,}),") // latitude + .number("(-?d{8,}),") // longitude + .number("(-?d{7,}),") // latitude .or() .number("(-?d+),") // longitude .number("(-?d+),") // latitude diff --git a/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java index 7616e7e8d..3e3bafb34 100644 --- a/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java @@ -26,7 +26,8 @@ public class TelicProtocolDecoderTest extends ProtocolTest { "002135556507134749999,010817171138,0,010817171138,004560973,50667173,3,0,0,11,1,1,100,958071,20601,000000,00,4142,0000,0000,0208,10395,0")); verifyPosition(decoder, text( - "442045993198,290317131935,0,290317131935,269158,465748,3,26,183,,,,184,85316567,226,01,00,68,218")); + "442045993198,290317131935,0,290317131935,269158,465748,3,26,183,,,,184,85316567,226,01,00,68,218"), + position("2017-03-29 13:19:35.000", true, 46.57480, 26.91580)); verifyPosition(decoder, text( "673091036017,290317131801,0,290317131801,262214,450536,3,40,199,8,,,154,19969553,,0011,00,59,240,0,0406")); -- cgit v1.2.3 From e46cb0260f224ec296feb7087cdfb05371e6f550 Mon Sep 17 00:00:00 2001 From: Andreas Date: Thu, 5 Mar 2020 21:01:51 +0100 Subject: implement device in ui --- .../traccar/notificators/NotificatorPushover.java | 45 ++-------------------- traccar-web | 2 +- 2 files changed, 5 insertions(+), 42 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index f289e464a..6cad6f766 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -36,36 +36,20 @@ public class NotificatorPushover extends Notificator { private static Properties getProperties(PropertiesProvider provider) { Properties properties = new Properties(); - // (required) token from pushover.net - String token = provider.getString("notificator.pushover.token"); - if (token != null) { - properties.put("notificator.pushover.token", token); - } - // (required) user from pushover.net - String user = provider.getString("notificator.pushover.user"); - if (user != null) { - properties.put("notificator.pushover.user", user); - } // optional: your user's device name to send the message directly // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) String device = provider.getString("notificator.pushover.device"); if (device != null) { properties.put("notificator.pushover.device", device); } - // optional: your message's title, otherwise your app's name is used - String title = provider.getString("notificator.pushover.title"); - if (title != null) { - properties.put("notificator.pushover.title", title); - } return properties; } private final String url; - private String token; - private String puser; + private final String token; + private final String puser; private String device; - private String title; public static class Message { @JsonProperty("token") @@ -74,8 +58,6 @@ public class NotificatorPushover extends Notificator { private String user; @JsonProperty("device") private String device; - @JsonProperty("title") - private String title; @JsonProperty("message") private String message; } @@ -83,6 +65,8 @@ public class NotificatorPushover extends Notificator { public NotificatorPushover() { // see https://pushover.net/api url = "https://api.pushover.net/1/messages.json"; + token = Context.getConfig().getString("notificator.pushover.token"); // (required) token from pushover.net + puser = Context.getConfig().getString("notificator.pushover.user"); // (required) user from pushover.net } @Override @@ -90,35 +74,19 @@ public class NotificatorPushover extends Notificator { User user = Context.getPermissionsManager().getUser(userId); - token = null; - puser = null; device = null; - title = null; - Properties properties = null; properties = getProperties(new PropertiesProvider(Context.getConfig())); if (properties != null) { - token = properties.getProperty("notificator.pushover.token"); - puser = properties.getProperty("notificator.pushover.user"); device = properties.getProperty("notificator.pushover.device"); - title = properties.getProperty("notificator.pushover.title"); } properties = getProperties(new PropertiesProvider(user)); if (properties != null) { - if (properties.getProperty("notificator.pushover.token") != null) { - token = properties.getProperty("notificator.pushover.token"); - } - if (properties.getProperty("notificator.pushover.user") != null) { - puser = properties.getProperty("notificator.pushover.user"); - } if (properties.getProperty("notificator.pushover.device") != null) { device = properties.getProperty("notificator.pushover.device"); } - if (properties.getProperty("notificator.pushover.title") != null) { - title = properties.getProperty("notificator.pushover.title"); - } } if (token == null) { @@ -135,15 +103,10 @@ public class NotificatorPushover extends Notificator { device = ""; } - if (title == null) { - title = ""; - } - Message message = new Message(); message.token = token; message.user = puser; message.device = device; - message.title = title; message.message = NotificationFormatter.formatShortMessage(userId, event, position); Context.getClient().target(url).request() diff --git a/traccar-web b/traccar-web index a587d6257..071f08898 160000 --- a/traccar-web +++ b/traccar-web @@ -1 +1 @@ -Subproject commit a587d6257dd9de70252a5b00299ccbfd7b5cb272 +Subproject commit 071f088980c867638f1092c48c6909a4433a0755 -- cgit v1.2.3 From 3c82764799784d3d30d969dbfef9a075f4874278 Mon Sep 17 00:00:00 2001 From: Vitaliy Gergel Date: Thu, 5 Mar 2020 22:22:59 +0200 Subject: Rename forward.urlVariables property --- src/main/java/org/traccar/WebDataHandler.java | 6 +++--- src/main/java/org/traccar/config/Keys.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java index 1af1af48a..d6bfb126b 100644 --- a/src/main/java/org/traccar/WebDataHandler.java +++ b/src/main/java/org/traccar/WebDataHandler.java @@ -67,7 +67,7 @@ public class WebDataHandler extends BaseDataHandler { private final String url; private final String header; private final boolean json; - private final boolean jsonUrlVariables; + private final boolean urlVariables; private final boolean retryEnabled; private final int retryDelay; @@ -86,7 +86,7 @@ public class WebDataHandler extends BaseDataHandler { this.url = config.getString(Keys.FORWARD_URL); this.header = config.getString(Keys.FORWARD_HEADER); this.json = config.getBoolean(Keys.FORWARD_JSON); - this.jsonUrlVariables = config.getBoolean(Keys.FORWARD_JSON_URL_VARIABLES); + this.urlVariables = config.getBoolean(Keys.FORWARD_URL_VARIABLES); this.retryEnabled = config.getBoolean(Keys.FORWARD_RETRY_ENABLE); this.retryDelay = config.getInteger(Keys.FORWARD_RETRY_DELAY, 100); @@ -194,7 +194,7 @@ public class WebDataHandler extends BaseDataHandler { String formattedUrl; try { - formattedUrl = (json && !jsonUrlVariables) ? url : formatRequest(position); + formattedUrl = (json && !urlVariables) ? url : formatRequest(position); } catch (UnsupportedEncodingException | JsonProcessingException e) { throw new RuntimeException("Forwarding formatting error", e); } diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index a5b7b780c..200ef8aa3 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -104,8 +104,8 @@ public final class Keys { * Boolean value to enable URL parameters in json mode. For example, {uniqueId} for device identifier, * {latitude} and {longitude} for coordinates. */ - public static final ConfigKey FORWARD_JSON_URL_VARIABLES = new ConfigKey( - "forward.json.url.variables", Boolean.class); + public static final ConfigKey FORWARD_URL_VARIABLES = new ConfigKey( + "forward.urlVariables", Boolean.class); /** * Position forwarding retrying enable. When enabled, additional attempts are made to deliver positions. If initial -- cgit v1.2.3 From 7eecff54effb04d27fdd1d67ed75a1e2dbc3c693 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 5 Mar 2020 22:21:45 -0800 Subject: Support OKO AVTO format --- .../org/traccar/protocol/OkoProtocolDecoder.java | 23 +++++++++++++++------- .../traccar/protocol/OkoProtocolDecoderTest.java | 6 ++++++ 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/OkoProtocolDecoder.java b/src/main/java/org/traccar/protocol/OkoProtocolDecoder.java index 5adf61494..4d9c9afc4 100644 --- a/src/main/java/org/traccar/protocol/OkoProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/OkoProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -36,7 +36,7 @@ public class OkoProtocolDecoder extends BaseProtocolDecoder { private static final Pattern PATTERN = new PatternBuilder() .text("{") .number("(d{15}),").optional() // imei - .number("(dd)(dd)(dd).d+,") // time + .number("(dd)(dd)(dd)(?:.d+)?,") // time .expression("([AV]),") // validity .number("(dd)(dd.d+),") // latitude .expression("([NS]),") @@ -46,14 +46,23 @@ public class OkoProtocolDecoder extends BaseProtocolDecoder { .number("(d+.?d*)?,") // course .number("(dd)(dd)(dd),") // date (ddmmyy) .number("(d+),") // satellites - .number("(d+.d+),") // adc + .number("(d+.d+|xx),") // adc .number("(xx),") // event - .number("(d+.d+),") // power + .number("(d+.d+|xx),") // power .number("d,") // memory status - .number("(xx)") // io + .number("(xx)?") // io .any() .compile(); + private double decodeVoltage(Parser parser) { + String value = parser.next(); + if (value.contains(".")) { + return Double.parseDouble(value); + } else { + return Integer.parseInt(value, 16) * 0.1; + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -89,9 +98,9 @@ public class OkoProtocolDecoder extends BaseProtocolDecoder { position.setTime(dateBuilder.getDate()); position.set(Position.KEY_SATELLITES, parser.nextInt()); - position.set(Position.PREFIX_ADC + 1, parser.nextDouble()); + position.set(Position.PREFIX_ADC + 1, decodeVoltage(parser)); position.set(Position.KEY_EVENT, parser.next()); - position.set(Position.KEY_POWER, parser.nextDouble()); + position.set(Position.KEY_POWER, decodeVoltage(parser)); position.set(Position.KEY_INPUT, parser.nextHexInt()); return position; diff --git a/src/test/java/org/traccar/protocol/OkoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/OkoProtocolDecoderTest.java index e2f72c161..d6b8e9a4a 100644 --- a/src/test/java/org/traccar/protocol/OkoProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/OkoProtocolDecoderTest.java @@ -10,6 +10,12 @@ public class OkoProtocolDecoderTest extends ProtocolTest { OkoProtocolDecoder decoder = new OkoProtocolDecoder(null); + verifyPosition(decoder, text( + "{868204000482330,125138,A,5026.821,N,03032.472,E,0.0,171,240200,7,00,F9,7D,1,,,,,,,91,,,187.7,M,2,,}")); + + verifyPosition(decoder, text( + "{123456789098765,132810.000,A,4926.4243,N,03203.6831,E,0.08,83.52,131010,07,5C,FB,7A,1,27,,,,,,CB,128,15grn,197.6,M,3,01FE,02AC}")); + verifyPosition(decoder, text( "{861694033681089,045403.00,A,4924.14181,N,03207.43787,E,0.080,,151117,07,0.00,01,24.8,1,02,5n4}")); -- cgit v1.2.3 From d2835b2c6152b448179c0ecae6c9aadc4dce60a6 Mon Sep 17 00:00:00 2001 From: Andreas Date: Fri, 6 Mar 2020 16:51:15 +0100 Subject: simplify code --- .../traccar/notificators/NotificatorPushover.java | 42 +++++----------------- 1 file changed, 8 insertions(+), 34 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index 6cad6f766..5c86503f3 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -21,11 +21,8 @@ import org.slf4j.LoggerFactory; import org.traccar.Context; import org.traccar.model.Event; import org.traccar.model.Position; -import org.traccar.notification.NotificationFormatter; - import org.traccar.model.User; -import org.traccar.notification.PropertiesProvider; -import java.util.Properties; +import org.traccar.notification.NotificationFormatter; import javax.ws.rs.client.Entity; import javax.ws.rs.client.InvocationCallback; @@ -34,22 +31,9 @@ public class NotificatorPushover extends Notificator { private static final Logger LOGGER = LoggerFactory.getLogger(NotificatorPushover.class); - private static Properties getProperties(PropertiesProvider provider) { - Properties properties = new Properties(); - // optional: your user's device name to send the message directly - // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) - String device = provider.getString("notificator.pushover.device"); - if (device != null) { - properties.put("notificator.pushover.device", device); - } - return properties; - } - - private final String url; private final String token; private final String puser; - private String device; public static class Message { @JsonProperty("token") @@ -72,21 +56,15 @@ public class NotificatorPushover extends Notificator { @Override public void sendSync(long userId, Event event, Position position) { - User user = Context.getPermissionsManager().getUser(userId); - - device = null; - Properties properties = null; + final User user = Context.getPermissionsManager().getUser(userId); - properties = getProperties(new PropertiesProvider(Context.getConfig())); - if (properties != null) { - device = properties.getProperty("notificator.pushover.device"); - } + String device = ""; - properties = getProperties(new PropertiesProvider(user)); - if (properties != null) { - if (properties.getProperty("notificator.pushover.device") != null) { - device = properties.getProperty("notificator.pushover.device"); - } + if (user.getAttributes().containsKey("notificator.pushover.device")) { + // optional: your user's device name to send the message directly + // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) + // i.e.: device1,device2 (no space) + device = user.getString("notificator.pushover.device").replaceAll(" *, *", ","); } if (token == null) { @@ -99,10 +77,6 @@ public class NotificatorPushover extends Notificator { return; } - if (device == null) { - device = ""; - } - Message message = new Message(); message.token = token; message.user = puser; -- cgit v1.2.3 From c1b640ef2736b5f3a16440c8fbb12db6ad3bdb56 Mon Sep 17 00:00:00 2001 From: Andreas Date: Fri, 6 Mar 2020 19:41:04 +0100 Subject: change copyright date --- src/main/java/org/traccar/notificators/NotificatorPushover.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index 5c86503f3..52646bdfb 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2020 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. -- cgit v1.2.3 From fa837208bed12dd08e1a540a2279180dec102974 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 6 Mar 2020 21:29:27 -0800 Subject: Support Traxsit GPS1 format --- .../org/traccar/protocol/SigfoxProtocolDecoder.java | 18 +++++++++++++----- .../traccar/protocol/SigfoxProtocolDecoderTest.java | 3 +++ 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java index 304f61836..bda0600cc 100644 --- a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -83,7 +83,14 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder { } JsonObject json = Json.createReader(new StringReader(content)).readObject(); - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, json.getString("device")); + String deviceId; + if (json.containsKey("device")) { + deviceId = json.getString("device"); + } else { + deviceId = json.getString("deviceId"); + } + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, deviceId); if (deviceSession == null) { sendResponse(channel, HttpResponseStatus.BAD_REQUEST); return null; @@ -99,7 +106,8 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder { } if (json.containsKey("location") - || json.containsKey("lat") && json.containsKey("lng") && !json.containsKey("data")) { + || json.containsKey("lat") && json.containsKey("lng") && !json.containsKey("data") + || json.containsKey("latitude") && json.containsKey("longitude") && !json.containsKey("data")) { JsonObject location; if (json.containsKey("location")) { @@ -109,8 +117,8 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder { } position.setValid(true); - position.setLatitude(getJsonDouble(location, "lat")); - position.setLongitude(getJsonDouble(location, "lng")); + position.setLatitude(getJsonDouble(location, location.containsKey("lat") ? "lat" : "latitude")); + position.setLongitude(getJsonDouble(location, location.containsKey("lng") ? "lng" : "longitude")); } else { diff --git a/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java index 4ab343876..2bf6276b3 100644 --- a/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java @@ -12,6 +12,9 @@ public class SigfoxProtocolDecoderTest extends ProtocolTest { SigfoxProtocolDecoder decoder = new SigfoxProtocolDecoder(null); + verifyPosition(decoder, request(HttpMethod.POST, "/", + buffer("{\"deviceId\":\"3377BC\",\"snr\":\"16.46\",\"rssi\":\"-123.00\",\"station\":\"-123.00\",\"seqNum\":\"3042\",\"newPosition\":true,\"latitude\":51.9189749,\"longitude\":-8.3979322,\"positionTime\":\"1582801850\",\"moving\":false,\"magChange\":false,\"magStatus\":false,\"temperature\":-2,\"battery\":\"null\",\"batteryPercentage\":\"null\",\"lastSeen\":\"1582801850\",\"fwVersion\":\"null\",\"dlConfig\":\"null\",\"recievedPayload\":\"09495a9085f5c94c\"}"))); + verifyPosition(decoder, request(HttpMethod.POST, "/", buffer("{ \"device\" : \"33827B\", \"data\" : \"1f03198e63807f08836402ff\", \"time\" : \"1574346702\", \"snr\" : \"8.82\", \"station\" : \"140A\", \"avgSnr\" : \"11.28\", \"lat\" : \"52.0\", \"lng\" : \"-8.0\", \"rssi\" : \"-141.00\", \"seqNumber\" : \"3662\"}"))); -- cgit v1.2.3 From 38efcf3dbc8a46b9797e5fb654fc1c68815b3b36 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 7 Mar 2020 09:50:49 -0800 Subject: Update response message --- src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java index 382509793..ab89f10c8 100644 --- a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java @@ -97,7 +97,7 @@ public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder { rootElement.appendChild(state); Element stateMessage = document.createElement("stateMessage"); - stateMessage.appendChild(document.createTextNode("Messages received and stored successfully")); + stateMessage.appendChild(document.createTextNode("Store OK")); rootElement.appendChild(stateMessage); Transformer transformer = TransformerFactory.newInstance().newTransformer(); -- cgit v1.2.3 From 9caf803986d14661e2e1842b80ee3aa58c8d5c6d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 7 Mar 2020 11:45:52 -0800 Subject: Remove comments --- src/main/java/org/traccar/notificators/NotificatorPushover.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index 52646bdfb..141d652ca 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -47,10 +47,9 @@ public class NotificatorPushover extends Notificator { } public NotificatorPushover() { - // see https://pushover.net/api url = "https://api.pushover.net/1/messages.json"; - token = Context.getConfig().getString("notificator.pushover.token"); // (required) token from pushover.net - puser = Context.getConfig().getString("notificator.pushover.user"); // (required) user from pushover.net + token = Context.getConfig().getString("notificator.pushover.token"); + puser = Context.getConfig().getString("notificator.pushover.user"); } @Override @@ -61,9 +60,6 @@ public class NotificatorPushover extends Notificator { String device = ""; if (user.getAttributes().containsKey("notificator.pushover.device")) { - // optional: your user's device name to send the message directly - // to that device, rather than all of the user's devices (multiple devices may be separated by a comma) - // i.e.: device1,device2 (no space) device = user.getString("notificator.pushover.device").replaceAll(" *, *", ","); } -- cgit v1.2.3 From 26cc87fd06b94400ee769e8c2985778b3b6e8ff6 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 11 Mar 2020 21:09:09 -0700 Subject: Decode additional attributes --- .../java/org/traccar/protocol/SigfoxProtocolDecoder.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java index bda0600cc..c2c3d0fc3 100644 --- a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java @@ -101,10 +101,16 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder { if (json.containsKey("time")) { position.setTime(new Date(getJsonInt(json, "time") * 1000L)); + } else if (json.containsKey("positionTime")) { + position.setTime(new Date(getJsonInt(json, "positionTime") * 1000L)); } else { position.setTime(new Date()); } + if (json.containsKey("lastSeen")) { + position.setDeviceTime(new Date(getJsonInt(json, "lastSeen") * 1000L)); + } + if (json.containsKey("location") || json.containsKey("lat") && json.containsKey("lng") && !json.containsKey("data") || json.containsKey("latitude") && json.containsKey("longitude") && !json.containsKey("data")) { @@ -120,6 +126,16 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder { position.setLatitude(getJsonDouble(location, location.containsKey("lat") ? "lat" : "latitude")); position.setLongitude(getJsonDouble(location, location.containsKey("lng") ? "lng" : "longitude")); + if (location.containsKey("moving")) { + position.set(Position.KEY_MOTION, location.getBoolean("moving")); + } + if (location.containsKey("magStatus")) { + position.set(Position.KEY_BLOCKED, location.getBoolean("magStatus")); + } + if (location.containsKey("temperature")) { + position.set(Position.KEY_DEVICE_TEMP, location.getJsonNumber("temperature").doubleValue()); + } + } else { String data = json.getString(json.containsKey("data") ? "data" : "payload"); -- cgit v1.2.3 From 578a8544bc0d31569fabbc8c3aa26a53d161d5ed Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 11 Mar 2020 21:17:02 -0700 Subject: Fix response index --- .../java/org/traccar/protocol/EskyProtocolDecoder.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java b/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java index f0ae0bc91..1a4f9b906 100644 --- a/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java @@ -38,7 +38,7 @@ public class EskyProtocolDecoder extends BaseProtocolDecoder { private static final Pattern PATTERN = new PatternBuilder() .expression("..;") // header - .number("(d+);") // index + .number("d+;") .number("(d+);") // imei .text("R;") // data type .number("(d+)[+;]") // satellites @@ -61,16 +61,12 @@ public class EskyProtocolDecoder extends BaseProtocolDecoder { protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - Parser parser = new Parser(PATTERN, (String) msg); + String sentence = (String) msg; + Parser parser = new Parser(PATTERN, sentence); if (!parser.matches()) { return null; } - int index = parser.nextInt(); - if (channel instanceof DatagramChannel) { - channel.writeAndFlush(new NetworkMessage("ACK," + index + "#", remoteAddress)); - } - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); if (deviceSession == null) { return null; @@ -99,6 +95,11 @@ public class EskyProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_BATTERY, parser.nextInt() * 0.001); + int index = sentence.lastIndexOf('+'); + if (index > 0 && channel instanceof DatagramChannel) { + channel.writeAndFlush(new NetworkMessage("ACK," + sentence.substring(index + 1) + "#", remoteAddress)); + } + return position; } -- cgit v1.2.3 From e2071c06c0962c083f4f4d5dce5961b08c1920e7 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 14 Mar 2020 16:22:47 -0700 Subject: Decode more alarms --- .../traccar/protocol/FifotrackProtocolDecoder.java | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java index 40e146e0b..9bc7cb504 100644 --- a/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2020 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. @@ -116,6 +116,32 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder { return Position.ALARM_POWER_CUT; case 16: return Position.ALARM_POWER_RESTORED; + case 17: + return Position.ALARM_LOW_BATTERY; + case 18: + return Position.ALARM_OVERSPEED; + case 20: + return Position.ALARM_GPS_ANTENNA_CUT; + case 21: + return Position.ALARM_VIBRATION; + case 23: + return Position.ALARM_ACCELERATION; + case 24: + return Position.ALARM_BRAKING; + case 27: + return Position.ALARM_FATIGUE_DRIVING; + case 30: + case 32: + return Position.ALARM_JAMMING; + case 33: + return Position.ALARM_GEOFENCE_EXIT; + case 34: + return Position.ALARM_GEOFENCE_ENTER; + case 35: + return Position.ALARM_IDLE; + case 40: + case 41: + return Position.ALARM_TEMPERATURE; default: return null; } -- cgit v1.2.3 From 57c977d8369c96787c778ac2c27769ec53f24a6e Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 14:47:36 -0700 Subject: Improve type casting --- src/main/java/org/traccar/BaseProtocolDecoder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/BaseProtocolDecoder.java b/src/main/java/org/traccar/BaseProtocolDecoder.java index e6e02c2d6..634ceafd5 100644 --- a/src/main/java/org/traccar/BaseProtocolDecoder.java +++ b/src/main/java/org/traccar/BaseProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2012 - 2020 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. @@ -227,9 +227,9 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { if (decodedMessage instanceof Position) { position = (Position) decodedMessage; } else if (decodedMessage instanceof Collection) { - Collection positions = (Collection) decodedMessage; + Collection positions = (Collection) decodedMessage; if (!positions.isEmpty()) { - position = (Position) positions.iterator().next(); + position = positions.iterator().next(); } } } -- cgit v1.2.3 From c43208bf5339244cd9a47348ec9daa1805099718 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 15:03:43 -0700 Subject: Remove extra method --- src/main/java/org/traccar/BaseProtocol.java | 7 +------ src/main/java/org/traccar/protocol/WondexProtocol.java | 11 +++++++++-- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/BaseProtocol.java b/src/main/java/org/traccar/BaseProtocol.java index c0fd1e27f..6d459f7d4 100644 --- a/src/main/java/org/traccar/BaseProtocol.java +++ b/src/main/java/org/traccar/BaseProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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,11 +68,6 @@ public abstract class BaseProtocol implements Protocol { supportedTextCommands.addAll(Arrays.asList(commands)); } - public void setSupportedCommands(String... commands) { - supportedDataCommands.addAll(Arrays.asList(commands)); - supportedTextCommands.addAll(Arrays.asList(commands)); - } - @Override public Collection getSupportedDataCommands() { Set commands = new HashSet<>(supportedDataCommands); diff --git a/src/main/java/org/traccar/protocol/WondexProtocol.java b/src/main/java/org/traccar/protocol/WondexProtocol.java index 035dd9160..6401fde85 100644 --- a/src/main/java/org/traccar/protocol/WondexProtocol.java +++ b/src/main/java/org/traccar/protocol/WondexProtocol.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -25,7 +25,7 @@ import io.netty.handler.codec.string.StringEncoder; public class WondexProtocol extends BaseProtocol { public WondexProtocol() { - setSupportedCommands( + setSupportedDataCommands( Command.TYPE_GET_DEVICE_STATUS, Command.TYPE_GET_MODEM_STATUS, Command.TYPE_REBOOT_DEVICE, @@ -33,6 +33,13 @@ public class WondexProtocol extends BaseProtocol { Command.TYPE_GET_VERSION, Command.TYPE_IDENTIFICATION); setTextCommandEncoder(new WondexProtocolEncoder(this)); + setSupportedTextCommands( + Command.TYPE_GET_DEVICE_STATUS, + Command.TYPE_GET_MODEM_STATUS, + Command.TYPE_REBOOT_DEVICE, + Command.TYPE_POSITION_SINGLE, + Command.TYPE_GET_VERSION, + Command.TYPE_IDENTIFICATION); addServer(new TrackerServer(false, getName()) { @Override protected void addProtocolHandlers(PipelineBuilder pipeline) { -- cgit v1.2.3 From f98c3aa5b65e9fa06bcea38d96959b43f6a38245 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 15:39:12 -0700 Subject: Simplify data commands --- src/main/java/org/traccar/BaseProtocol.java | 15 +++++++++------ src/main/java/org/traccar/Protocol.java | 4 +++- src/main/java/org/traccar/database/ActiveDevice.java | 8 ++------ 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/BaseProtocol.java b/src/main/java/org/traccar/BaseProtocol.java index 6d459f7d4..bd3391822 100644 --- a/src/main/java/org/traccar/BaseProtocol.java +++ b/src/main/java/org/traccar/BaseProtocol.java @@ -15,12 +15,14 @@ */ package org.traccar; +import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; import io.netty.handler.codec.string.StringEncoder; -import org.traccar.database.ActiveDevice; import org.traccar.helper.DataConverter; import org.traccar.model.Command; +import java.net.SocketAddress; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -83,15 +85,16 @@ public abstract class BaseProtocol implements Protocol { } @Override - public void sendDataCommand(ActiveDevice activeDevice, Command command) { + public void sendDataCommand(Channel channel, SocketAddress remoteAddress, Command command) { if (supportedDataCommands.contains(command.getType())) { - activeDevice.write(command); + channel.writeAndFlush(new NetworkMessage(command, remoteAddress)); } else if (command.getType().equals(Command.TYPE_CUSTOM)) { String data = command.getString(Command.KEY_DATA); - if (BasePipelineFactory.getHandler(activeDevice.getChannel().pipeline(), StringEncoder.class) != null) { - activeDevice.write(data); + if (BasePipelineFactory.getHandler(channel.pipeline(), StringEncoder.class) != null) { + channel.writeAndFlush(new NetworkMessage(data, remoteAddress)); } else { - activeDevice.write(Unpooled.wrappedBuffer(DataConverter.parseHex(data))); + ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(data)); + channel.writeAndFlush(new NetworkMessage(buf, remoteAddress)); } } else { throw new RuntimeException("Command " + command.getType() + " is not supported in protocol " + getName()); diff --git a/src/main/java/org/traccar/Protocol.java b/src/main/java/org/traccar/Protocol.java index 3b66f2598..9d257be78 100644 --- a/src/main/java/org/traccar/Protocol.java +++ b/src/main/java/org/traccar/Protocol.java @@ -15,9 +15,11 @@ */ package org.traccar; +import io.netty.channel.Channel; import org.traccar.database.ActiveDevice; import org.traccar.model.Command; +import java.net.SocketAddress; import java.util.Collection; public interface Protocol { @@ -28,7 +30,7 @@ public interface Protocol { Collection getSupportedDataCommands(); - void sendDataCommand(ActiveDevice activeDevice, Command command); + void sendDataCommand(Channel channel, SocketAddress remoteAddress, Command command); Collection getSupportedTextCommands(); diff --git a/src/main/java/org/traccar/database/ActiveDevice.java b/src/main/java/org/traccar/database/ActiveDevice.java index 207fc454b..698cc851e 100644 --- a/src/main/java/org/traccar/database/ActiveDevice.java +++ b/src/main/java/org/traccar/database/ActiveDevice.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -45,11 +45,7 @@ public class ActiveDevice { } public void sendCommand(Command command) { - protocol.sendDataCommand(this, command); - } - - public void write(Object message) { - channel.writeAndFlush(new NetworkMessage(message, remoteAddress)); + protocol.sendDataCommand(channel, remoteAddress, command); } } -- cgit v1.2.3 From f9257e664be8c37cc041e004f403d737dd513d6b Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 15:43:17 -0700 Subject: Remove unused imports --- src/main/java/org/traccar/Protocol.java | 3 +-- src/main/java/org/traccar/database/ActiveDevice.java | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/Protocol.java b/src/main/java/org/traccar/Protocol.java index 9d257be78..aea69b353 100644 --- a/src/main/java/org/traccar/Protocol.java +++ b/src/main/java/org/traccar/Protocol.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 - 2020 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. @@ -16,7 +16,6 @@ package org.traccar; import io.netty.channel.Channel; -import org.traccar.database.ActiveDevice; import org.traccar.model.Command; import java.net.SocketAddress; diff --git a/src/main/java/org/traccar/database/ActiveDevice.java b/src/main/java/org/traccar/database/ActiveDevice.java index 698cc851e..34b3de227 100644 --- a/src/main/java/org/traccar/database/ActiveDevice.java +++ b/src/main/java/org/traccar/database/ActiveDevice.java @@ -16,7 +16,6 @@ package org.traccar.database; import io.netty.channel.Channel; -import org.traccar.NetworkMessage; import org.traccar.Protocol; import org.traccar.model.Command; -- cgit v1.2.3 From 6adcd4a8dd950a5f945c818280974a0302c9fd8b Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 15:46:27 -0700 Subject: Remove duplication --- src/main/java/org/traccar/BaseProtocolDecoder.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/BaseProtocolDecoder.java b/src/main/java/org/traccar/BaseProtocolDecoder.java index 634ceafd5..d014b0871 100644 --- a/src/main/java/org/traccar/BaseProtocolDecoder.java +++ b/src/main/java/org/traccar/BaseProtocolDecoder.java @@ -233,16 +233,18 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { } } } + long deviceId = 0; if (position != null) { - connectionManager.updateDevice( - position.getDeviceId(), Device.STATUS_ONLINE, new Date()); + deviceId = position.getDeviceId(); } else { DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); if (deviceSession != null) { - connectionManager.updateDevice( - deviceSession.getDeviceId(), Device.STATUS_ONLINE, new Date()); + deviceId = deviceSession.getDeviceId(); } } + if (deviceId > 0) { + connectionManager.updateDevice(deviceId, Device.STATUS_ONLINE, new Date()); + } } @Override -- cgit v1.2.3 From 11dcacc2fdfd29f4440c8c46e501ef565f9b1dfd Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 15:58:52 -0700 Subject: Decoder to send queued commands --- src/main/java/org/traccar/BaseProtocolDecoder.java | 12 ++++++++++++ src/main/java/org/traccar/database/CommandsManager.java | 14 ++++++++++---- src/main/java/org/traccar/database/ConnectionManager.java | 4 ---- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/BaseProtocolDecoder.java b/src/main/java/org/traccar/BaseProtocolDecoder.java index d014b0871..8981fe4c8 100644 --- a/src/main/java/org/traccar/BaseProtocolDecoder.java +++ b/src/main/java/org/traccar/BaseProtocolDecoder.java @@ -21,10 +21,12 @@ import io.netty.handler.codec.http.HttpRequestDecoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.config.Config; +import org.traccar.database.CommandsManager; import org.traccar.database.ConnectionManager; import org.traccar.database.IdentityManager; import org.traccar.database.StatisticsManager; import org.traccar.helper.UnitsConverter; +import org.traccar.model.Command; import org.traccar.model.Device; import org.traccar.model.Position; @@ -245,6 +247,16 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { if (deviceId > 0) { connectionManager.updateDevice(deviceId, Device.STATUS_ONLINE, new Date()); } + sendQueuedCommands(channel, remoteAddress, deviceId); + } + + protected void sendQueuedCommands(Channel channel, SocketAddress remoteAddress, long deviceId) { + CommandsManager commandsManager = Context.getCommandsManager(); + if (commandsManager != null) { + for (Command command : commandsManager.readQueuedCommands(deviceId)) { + protocol.sendDataCommand(channel, remoteAddress, command); + } + } } @Override diff --git a/src/main/java/org/traccar/database/CommandsManager.java b/src/main/java/org/traccar/database/CommandsManager.java index de6eeeba8..99114db5e 100644 --- a/src/main/java/org/traccar/database/CommandsManager.java +++ b/src/main/java/org/traccar/database/CommandsManager.java @@ -161,21 +161,27 @@ public class CommandsManager extends ExtendedObjectManager { } } - public void sendQueuedCommands(ActiveDevice activeDevice) { + public Collection readQueuedCommands(long deviceId) { + return readQueuedCommands(deviceId, Integer.MAX_VALUE); + } + + public Collection readQueuedCommands(long deviceId, int count) { Queue deviceQueue; try { readLock(); - deviceQueue = deviceQueues.get(activeDevice.getDeviceId()); + deviceQueue = deviceQueues.get(deviceId); } finally { readUnlock(); } + Collection result = new ArrayList<>(); if (deviceQueue != null) { Command command = deviceQueue.poll(); - while (command != null) { - activeDevice.sendCommand(command); + while (command != null && result.size() < count) { + result.add(command); command = deviceQueue.poll(); } } + return result; } } diff --git a/src/main/java/org/traccar/database/ConnectionManager.java b/src/main/java/org/traccar/database/ConnectionManager.java index dd0071143..4d43bc71b 100644 --- a/src/main/java/org/traccar/database/ConnectionManager.java +++ b/src/main/java/org/traccar/database/ConnectionManager.java @@ -139,10 +139,6 @@ public class ConnectionManager { } updateDevice(device); - - if (status.equals(Device.STATUS_ONLINE) && !oldStatus.equals(Device.STATUS_ONLINE)) { - Context.getCommandsManager().sendQueuedCommands(getActiveDevice(deviceId)); - } } public Map updateDeviceState(long deviceId) { -- cgit v1.2.3 From 606afeb37451f921fe3aecffab439cc2bcc7a175 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 16:02:37 -0700 Subject: Queue HTTP commands --- src/main/java/org/traccar/database/ActiveDevice.java | 6 ++++++ src/main/java/org/traccar/database/CommandsManager.java | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/database/ActiveDevice.java b/src/main/java/org/traccar/database/ActiveDevice.java index 34b3de227..e3ece6ad9 100644 --- a/src/main/java/org/traccar/database/ActiveDevice.java +++ b/src/main/java/org/traccar/database/ActiveDevice.java @@ -16,6 +16,8 @@ package org.traccar.database; import io.netty.channel.Channel; +import io.netty.handler.codec.http.HttpRequestDecoder; +import org.traccar.BasePipelineFactory; import org.traccar.Protocol; import org.traccar.model.Command; @@ -43,6 +45,10 @@ public class ActiveDevice { return deviceId; } + public boolean supportsLiveCommands() { + return BasePipelineFactory.getHandler(channel.pipeline(), HttpRequestDecoder.class) == null; + } + public void sendCommand(Command command) { protocol.sendDataCommand(channel, remoteAddress, command); } diff --git a/src/main/java/org/traccar/database/CommandsManager.java b/src/main/java/org/traccar/database/CommandsManager.java index 99114db5e..485402807 100644 --- a/src/main/java/org/traccar/database/CommandsManager.java +++ b/src/main/java/org/traccar/database/CommandsManager.java @@ -76,7 +76,12 @@ public class CommandsManager extends ExtendedObjectManager { } else { ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(deviceId); if (activeDevice != null) { - activeDevice.sendCommand(command); + if (activeDevice.supportsLiveCommands()) { + activeDevice.sendCommand(command); + } else { + getDeviceQueue(deviceId).add(command); + return false; + } } else if (!queueing) { throw new RuntimeException("Device is not online"); } else { -- cgit v1.2.3 From 83494fe445a9c7cb4f6b7de1e97e0d257f8bc7c2 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 16:13:52 -0700 Subject: Support HTTP response content --- src/main/java/org/traccar/BaseHttpProtocolDecoder.java | 15 ++++++++++++--- .../org/traccar/protocol/LeafSpyProtocolDecoder.java | 7 +------ .../org/traccar/protocol/PiligrimProtocolDecoder.java | 17 ++++------------- 3 files changed, 17 insertions(+), 22 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/BaseHttpProtocolDecoder.java b/src/main/java/org/traccar/BaseHttpProtocolDecoder.java index 57a68acac..b762be12c 100644 --- a/src/main/java/org/traccar/BaseHttpProtocolDecoder.java +++ b/src/main/java/org/traccar/BaseHttpProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2020 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. @@ -15,6 +15,8 @@ */ package org.traccar; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.HttpHeaderNames; @@ -29,9 +31,16 @@ public abstract class BaseHttpProtocolDecoder extends BaseProtocolDecoder { } public void sendResponse(Channel channel, HttpResponseStatus status) { + sendResponse(channel, status, null); + } + + public void sendResponse(Channel channel, HttpResponseStatus status, ByteBuf buf) { if (channel != null) { - HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); - response.headers().add(HttpHeaderNames.CONTENT_LENGTH, 0); + if (buf == null) { + buf = Unpooled.buffer(0); + } + HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf); + response.headers().add(HttpHeaderNames.CONTENT_LENGTH, buf.readableBytes()); channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); } } diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java index 5b352a961..8b47701fd 100644 --- a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java @@ -122,13 +122,8 @@ public class LeafSpyProtocolDecoder extends BaseHttpProtocolDecoder { } if (position.getDeviceId() != 0) { - if (channel != null) { - HttpResponse response = new DefaultFullHttpResponse( - HttpVersion.HTTP_1_1, - HttpResponseStatus.OK, + sendResponse(channel, 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/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java b/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java index 47aa86da7..26ce2fe53 100644 --- a/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2014 - 2020 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. @@ -18,15 +18,11 @@ package org.traccar.protocol; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; -import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.QueryStringDecoder; -import org.traccar.BaseProtocolDecoder; +import org.traccar.BaseHttpProtocolDecoder; import org.traccar.DeviceSession; -import org.traccar.NetworkMessage; import org.traccar.Protocol; import org.traccar.helper.BitUtil; import org.traccar.helper.DateBuilder; @@ -37,19 +33,14 @@ import java.nio.charset.StandardCharsets; import java.util.LinkedList; import java.util.List; -public class PiligrimProtocolDecoder extends BaseProtocolDecoder { +public class PiligrimProtocolDecoder extends BaseHttpProtocolDecoder { public PiligrimProtocolDecoder(Protocol protocol) { super(protocol); } private void sendResponse(Channel channel, String message) { - if (channel != null) { - FullHttpResponse response = new DefaultFullHttpResponse( - HttpVersion.HTTP_1_1, HttpResponseStatus.OK, - Unpooled.copiedBuffer(message, StandardCharsets.US_ASCII)); - channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); - } + sendResponse(channel, HttpResponseStatus.OK, Unpooled.copiedBuffer(message, StandardCharsets.US_ASCII)); } public static final int MSG_GPS = 0xF1; -- cgit v1.2.3 From 0164474c700337c686fea93e2ca4875adaaf35d5 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 16:17:07 -0700 Subject: Remove unused imports --- src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java index 8b47701fd..ad0c9bd32 100644 --- a/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/LeafSpyProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2019 Jesse Hills (jesserockz@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,16 +19,12 @@ package org.traccar.protocol; 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.model.Position; -import org.traccar.NetworkMessage; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -- cgit v1.2.3 From f85af44e180c87993d2d8d760f64af775f99531f Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 15 Mar 2020 16:22:35 -0700 Subject: Support commands for OsmAnd --- .../traccar/protocol/OsmAndProtocolDecoder.java | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java b/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java index 3bc71de81..ec9bbc240 100644 --- a/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2013 - 2020 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. @@ -15,15 +15,19 @@ */ package org.traccar.protocol; +import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.QueryStringDecoder; import org.traccar.BaseHttpProtocolDecoder; +import org.traccar.Context; import org.traccar.DeviceSession; import org.traccar.Protocol; +import org.traccar.database.CommandsManager; import org.traccar.helper.DateUtil; import org.traccar.model.CellTower; +import org.traccar.model.Command; import org.traccar.model.Network; import org.traccar.model.Position; import org.traccar.model.WifiAccessPoint; @@ -173,7 +177,18 @@ public class OsmAndProtocolDecoder extends BaseHttpProtocolDecoder { } if (position.getDeviceId() != 0) { - sendResponse(channel, HttpResponseStatus.OK); + String response = null; + CommandsManager commandsManager = Context.getCommandsManager(); + if (commandsManager != null) { + for (Command command : commandsManager.readQueuedCommands(position.getDeviceId(), 1)) { + response = command.getString(Command.KEY_DATA); + } + } + if (response != null) { + sendResponse(channel, HttpResponseStatus.OK, Unpooled.copiedBuffer(response, StandardCharsets.UTF_8)); + } else { + sendResponse(channel, HttpResponseStatus.OK); + } return position; } else { sendResponse(channel, HttpResponseStatus.BAD_REQUEST); @@ -181,4 +196,8 @@ public class OsmAndProtocolDecoder extends BaseHttpProtocolDecoder { } } + @Override + protected void sendQueuedCommands(Channel channel, SocketAddress remoteAddress, long deviceId) { + } + } -- cgit v1.2.3 From 2816e5ed49e6d237f2a4e48a98cd4a5f1a893246 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 23 Mar 2020 20:59:09 -0700 Subject: Support position for single device --- src/main/java/org/traccar/api/resource/PositionResource.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/api/resource/PositionResource.java b/src/main/java/org/traccar/api/resource/PositionResource.java index c031b842f..67aa6dd32 100644 --- a/src/main/java/org/traccar/api/resource/PositionResource.java +++ b/src/main/java/org/traccar/api/resource/PositionResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2020 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. @@ -34,6 +34,7 @@ import javax.ws.rs.core.Response; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; @Path("positions") @@ -63,8 +64,12 @@ public class PositionResource extends BaseResource { return Context.getDeviceManager().getInitialState(getUserId()); } else { Context.getPermissionsManager().checkDevice(getUserId(), deviceId); - return Context.getDataManager().getPositions( - deviceId, DateUtil.parseDate(from), DateUtil.parseDate(to)); + if (from != null && to != null) { + return Context.getDataManager().getPositions( + deviceId, DateUtil.parseDate(from), DateUtil.parseDate(to)); + } else { + return Collections.singleton(Context.getDeviceManager().getLastPosition(deviceId)); + } } } -- cgit v1.2.3 From f3d465abe7f255ec44e976caade642e4c2fd7598 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 23 Mar 2020 21:13:35 -0700 Subject: Support null values --- .../traccar/protocol/SigfoxProtocolDecoder.java | 70 +++++++++++++++------- .../protocol/SigfoxProtocolDecoderTest.java | 6 ++ 2 files changed, 53 insertions(+), 23 deletions(-) (limited to 'src/main/java/org') diff --git a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java index c2c3d0fc3..5fc81085b 100644 --- a/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java @@ -48,6 +48,31 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder { super(protocol); } + private boolean jsonContains(JsonObject json, String key) { + if (json.containsKey(key)) { + JsonValue value = json.get(key); + if (value.getValueType() == JsonValue.ValueType.STRING) { + return !((JsonString) value).getString().equals("null"); + + } else { + return true; + } + } + return false; + } + + private boolean getJsonBoolean(JsonObject json, String key) { + JsonValue value = json.get(key); + if (value != null) { + if (value.getValueType() == JsonValue.ValueType.STRING) { + return Boolean.parseBoolean(((JsonString) value).getString()); + } else { + return value.getValueType() == JsonValue.ValueType.TRUE; + } + } + return false; + } + private int getJsonInt(JsonObject json, String key) { JsonValue value = json.get(key); if (value != null) { @@ -99,46 +124,36 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder { Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); - if (json.containsKey("time")) { + if (jsonContains(json, "time")) { position.setTime(new Date(getJsonInt(json, "time") * 1000L)); - } else if (json.containsKey("positionTime")) { + } else if (jsonContains(json, "positionTime")) { position.setTime(new Date(getJsonInt(json, "positionTime") * 1000L)); } else { position.setTime(new Date()); } - if (json.containsKey("lastSeen")) { + if (jsonContains(json, "lastSeen")) { position.setDeviceTime(new Date(getJsonInt(json, "lastSeen") * 1000L)); } - if (json.containsKey("location") - || json.containsKey("lat") && json.containsKey("lng") && !json.containsKey("data") - || json.containsKey("latitude") && json.containsKey("longitude") && !json.containsKey("data")) { + if (jsonContains(json, "location") + || jsonContains(json, "lat") && jsonContains(json, "lng") && !jsonContains(json, "data") + || jsonContains(json, "latitude") && jsonContains(json, "longitude") && !jsonContains(json, "data")) { JsonObject location; - if (json.containsKey("location")) { + if (jsonContains(json, "location")) { location = json.getJsonObject("location"); } else { location = json; } position.setValid(true); - position.setLatitude(getJsonDouble(location, location.containsKey("lat") ? "lat" : "latitude")); - position.setLongitude(getJsonDouble(location, location.containsKey("lng") ? "lng" : "longitude")); - - if (location.containsKey("moving")) { - position.set(Position.KEY_MOTION, location.getBoolean("moving")); - } - if (location.containsKey("magStatus")) { - position.set(Position.KEY_BLOCKED, location.getBoolean("magStatus")); - } - if (location.containsKey("temperature")) { - position.set(Position.KEY_DEVICE_TEMP, location.getJsonNumber("temperature").doubleValue()); - } + position.setLatitude(getJsonDouble(location, jsonContains(location, "lat") ? "lat" : "latitude")); + position.setLongitude(getJsonDouble(location, jsonContains(location, "lng") ? "lng" : "longitude")); - } else { + } else if (jsonContains(json, "data") || jsonContains(json, "payload")) { - String data = json.getString(json.containsKey("data") ? "data" : "payload"); + String data = json.getString(jsonContains(json, "data") ? "data" : "payload"); ByteBuf buf = Unpooled.wrappedBuffer(DataConverter.parseHex(data)); try { int event = buf.readUnsignedByte(); @@ -229,10 +244,19 @@ public class SigfoxProtocolDecoder extends BaseHttpProtocolDecoder { getLastLocation(position, position.getDeviceTime()); } - if (json.containsKey("rssi")) { + if (jsonContains(json, "moving")) { + position.set(Position.KEY_MOTION, getJsonBoolean(json, "moving")); + } + if (jsonContains(json, "magStatus")) { + position.set(Position.KEY_BLOCKED, getJsonBoolean(json, "magStatus")); + } + if (jsonContains(json, "temperature")) { + position.set(Position.KEY_DEVICE_TEMP, getJsonDouble(json, "temperature")); + } + if (jsonContains(json, "rssi")) { position.set(Position.KEY_RSSI, getJsonDouble(json, "rssi")); } - if (json.containsKey("seqNumber")) { + if (jsonContains(json, "seqNumber")) { position.set(Position.KEY_INDEX, getJsonInt(json, "seqNumber")); } diff --git a/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java index 2bf6276b3..0ee34a4fc 100644 --- a/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java @@ -12,6 +12,12 @@ public class SigfoxProtocolDecoderTest extends ProtocolTest { SigfoxProtocolDecoder decoder = new SigfoxProtocolDecoder(null); + verifyAttributes(decoder, request(HttpMethod.POST, "/", + buffer("{\"messageType\":\"accelerometer\",\"deviceId\":\"testdev001\",\"snr\":\"1234\",\"rssi\":\"-120.00\",\"station\":\"5678\",\"seqNum\":\"9123\",\"newPosition\":false,\"latitude\":\"null\",\"longitude\":\"null\",\"positionTime\":\"null\",\"moving\":true,\"magChange\":\"true\",\"magStatus\":\"true\",\"temperature\":\"7.5\",\"battery\":\"null\",\"batteryPercentage\":\"null\",\"lastSeen\":\"1582560425\",\"fwVersion\":\"null\",\"dlConfig\":\"null\",\"recievedPayload\":\"cb020051\"}"))); + + verifyAttributes(decoder, request(HttpMethod.POST, "/", + buffer("{\"messageType\":\"downlinkAcknowledgement\",\"deviceId\":\"testdev002\",\"snr\":\"1234\",\"rssi\":\"-120.00\",\"station\":\"5678\",\"seqNum\":\"9123\",\"newPosition\":false,\"latitude\":\"null\",\"longitude\":\"null\",\"positionTime\":\"null\",\"moving\":false,\"magChange\":\"true\",\"magStatus\":\"true\",\"temperature\":\"8.5\",\"battery\":\"3.6\",\"batteryPercentage\":\"100\",\"lastSeen\":\"1582560425\",\"fwVersion\":\"1.15\",\"dlConfig\":\"808c180202140216\",\"recievedPayload\":\"cf808c180202140216b4010f\"}"))); + verifyPosition(decoder, request(HttpMethod.POST, "/", buffer("{\"deviceId\":\"3377BC\",\"snr\":\"16.46\",\"rssi\":\"-123.00\",\"station\":\"-123.00\",\"seqNum\":\"3042\",\"newPosition\":true,\"latitude\":51.9189749,\"longitude\":-8.3979322,\"positionTime\":\"1582801850\",\"moving\":false,\"magChange\":false,\"magStatus\":false,\"temperature\":-2,\"battery\":\"null\",\"batteryPercentage\":\"null\",\"lastSeen\":\"1582801850\",\"fwVersion\":\"null\",\"dlConfig\":\"null\",\"recievedPayload\":\"09495a9085f5c94c\"}"))); -- cgit v1.2.3