@@ -28,10 +28,10 @@ public abstract class BaseDataHandler extends OneToOneDecoder { if (msg instanceof Position) { return handlePosition((Position) msg); } - + return msg; } - + protected abstract Position handlePosition(Position position); } @@ -82,13 +82,13 @@ public abstract class BasePipelineFactory implements ChannelPipelineFactory { public BasePipelineFactory(TrackerServer server, String protocol) { this.server = server; - + resetDelay = Context.getConfig().getInteger(protocol + ".resetDelay", 0); if (Context.getConfig().getBoolean("filter.enable")) { filterHandler = new FilterHandler(); } - + if (Context.getReverseGeocoder() != null) { reverseGeocoderHandler = new ReverseGeocoderHandler( Context.getReverseGeocoder(), Context.getConfig().getBoolean("geocode.processInvalidPositions")); @@ -21,21 +21,21 @@ import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; import org.traccar.model.Command; public abstract class BaseProtocolEncoder extends OneToOneEncoder { - + protected String getUniqueId(long deviceId) { return Context.getIdentityManager().getDeviceById(deviceId).getUniqueId(); } @Override protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { - + if (msg instanceof Command) { return encodeCommand((Command) msg); } - + return msg; } - + protected abstract Object encodeCommand(Command command); - + } @@ -22,23 +22,23 @@ import java.util.Properties; public class Config { private final Properties properties = new Properties(); - + public void load(String file) throws IOException { properties.loadFromXML(new FileInputStream(file)); } - + public boolean hasKey(String key) { return properties.containsKey(key); } - + public boolean getBoolean(String key) { return Boolean.valueOf(properties.getProperty(key)); } - + public int getInteger(String key) { return getInteger(key, 0); } - + public int getInteger(String key, int defaultValue) { if (properties.containsKey(key)) { return Integer.valueOf(properties.getProperty(key)); @@ -46,11 +46,11 @@ public class Config { return defaultValue; } } - + public long getLong(String key) { return getLong(key, 0); } - + public long getLong(String key, long defaultValue) { if (properties.containsKey(key)) { return Long.valueOf(properties.getProperty(key)); @@ -58,11 +58,11 @@ public class Config { return defaultValue; } } - + public String getString(String key) { return properties.getProperty(key); } - + public String getString(String key, String defaultValue) { if (properties.containsKey(key)) { return properties.getProperty(key); @@ -70,5 +70,5 @@ public class Config { return defaultValue; } } - + } @@ -32,9 +32,9 @@ import org.traccar.helper.Log; import org.traccar.web.WebServer; public class Context { - + private static Config config; - + public static Config getConfig() { return config; } @@ -44,9 +44,9 @@ public class Context { public static boolean isLoggerEnabled() { return loggerEnabled; } - + private static IdentityManager identityManager; - + public static IdentityManager getIdentityManager() { return identityManager; } @@ -86,9 +86,9 @@ public class Context { public static ServerManager getServerManager() { return serverManager; } - + private static final AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); - + public static AsyncHttpClient getAsyncHttpClient() { return asyncHttpClient; } @@ -114,7 +114,7 @@ public class Context { String type = config.getString("geocoder.type", "google"); String url = config.getString("geocoder.url"); String key = config.getString("geocoder.key"); - + int cacheSize = config.getInteger("geocoder.cacheSize"); switch (type) { case "google": @@ -28,7 +28,7 @@ import java.util.List; public class DetectorHandler extends SimpleChannelHandler { private final List<TrackerServer> serverList; - + private boolean showFailed; DetectorHandler(List<TrackerServer> serverList) { @@ -49,7 +49,7 @@ public abstract class ExtendedObjectDecoder implements ChannelUpstreamHandler { } } } - + protected abstract Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception; } @@ -47,7 +47,7 @@ public class FilterHandler extends BaseDataHandler { this.filterFuture = filterFuture; this.filterLimit = filterLimit; } - + public FilterHandler() { Config config = Context.getConfig(); @@ -58,24 +58,24 @@ public class FilterHandler extends BaseDataHandler { filterDistance = config.getInteger("filter.distance"); filterLimit = config.getLong("filter.limit") * 1000; } - + private Position getLastPosition(long deviceId) { if (Context.getConnectionManager() != null) { return Context.getConnectionManager().getLastPosition(deviceId); } return null; } - + private boolean filterInvalid(Position position) { return filterInvalid && !position.getValid(); } - + private boolean filterZero(Position position) { return filterZero && (position.getLatitude() == 0.0) && (position.getLongitude() == 0.0); } - + private boolean filterDuplicate(Position position) { if (filterDuplicate) { Position last = getLastPosition(position.getDeviceId()); @@ -92,7 +92,7 @@ public class FilterHandler extends BaseDataHandler { private boolean filterFuture(Position position) { return filterFuture && (position.getFixTime().getTime() > System.currentTimeMillis() + FILTER_FUTURE_LIMIT); } - + private boolean filterDistance(Position position) { if (filterDistance != 0) { Position last = getLastPosition(position.getDeviceId()); @@ -108,7 +108,7 @@ public class FilterHandler extends BaseDataHandler { return false; } } - + private boolean filterLimit(Position position) { if (filterLimit != 0) { Position last = getLastPosition(position.getDeviceId()); @@ -121,20 +121,20 @@ public class FilterHandler extends BaseDataHandler { return false; } } - + private boolean filter(Position p) { - + boolean result = filterInvalid(p) || filterZero(p) || filterDuplicate(p) || filterFuture(p) || filterDistance(p); - + if (filterLimit(p)) { result = false; } - + if (result) { Log.info("Position filtered from " + p.getDeviceId()); } @@ -42,7 +42,7 @@ public class GlobalChannelFactory { } return channelFactory; } - + public static DatagramChannelFactory getDatagramFactory() { if (datagramChannelFactory == null) { datagramChannelFactory = new NioDatagramChannelFactory(); @@ -27,14 +27,14 @@ public class GlobalTimer { private GlobalTimer() { } - + public static void release() { if (instance != null) { instance.stop(); } instance = null; } - + public static Timer getTimer() { if(instance == null) { instance = new HashedWheelTimer(); @@ -19,7 +19,7 @@ import java.util.Locale; import org.traccar.helper.Log; public class Main { - + public static void main(String[] args) throws Exception { Locale.setDefault(Locale.ENGLISH); @@ -29,7 +29,7 @@ public class MainEventHandler extends IdleStateAwareChannelHandler { @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { - + if (e.getMessage() != null) { if (e.getMessage() instanceof Position) { @@ -50,7 +50,7 @@ public class MainEventHandler extends IdleStateAwareChannelHandler { } } } - + private static String formatChannel(Channel channel) { return String.format("[%08X]", channel.getId()); } @@ -64,7 +64,7 @@ public class MainEventHandler extends IdleStateAwareChannelHandler { public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) { Log.info(formatChannel(e.getChannel()) + " disconnected"); e.getChannel().close(); - + Context.getConnectionManager().removeActiveDevice(e.getChannel()); } @@ -29,7 +29,7 @@ public class RemoteAddressHandler extends ExtendedObjectDecoder { throws Exception { String hostAddress = ((InetSocketAddress) remoteAddress).getAddress().getHostAddress(); - + if (msg instanceof Position) { Position position = (Position) msg; position.set(Event.KEY_IP, hostAddress); @@ -43,7 +43,7 @@ public class ServerManager { if (packageUrl.getProtocol().equals("jar")) { String jarFileName = URLDecoder.decode(packageUrl.getFile(), "UTF-8"); JarFile jf = new JarFile(jarFileName.substring(5, jarFileName.indexOf("!"))); - + Enumeration<JarEntry> jarEntries = jf.entries(); while(jarEntries.hasMoreElements()){ String entryName = jarEntries.nextElement().getName(); @@ -59,7 +59,7 @@ public class ServerManager { names.add(entryName.substring(0, entryName.lastIndexOf('.'))); } } - + for (String name : names) { Class protocolClass = Class.forName(packageName + '.' + name); if (BaseProtocol.class.isAssignableFrom(protocolClass)) { @@ -31,7 +31,7 @@ public class WebDataHandler extends BaseDataHandler { public WebDataHandler(String url) { this.url = url; } - + private static String formatSentence(Position position) { StringBuilder s = new StringBuilder("$GPRMC,"); @@ -40,14 +40,14 @@ public class WebDataHandler extends BaseDataHandler { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ENGLISH); calendar.setTimeInMillis(position.getFixTime().getTime()); - + f.format("%1$tH%1$tM%1$tS.%1$tL,A,", calendar); - + double lat = position.getLatitude(); double lon = position.getLongitude(); f.format("%02d%07.4f,%c,", (int) Math.abs(lat), Math.abs(lat) % 1 * 60, lat < 0 ? 'S' : 'N'); f.format("%03d%07.4f,%c,", (int) Math.abs(lon), Math.abs(lon) % 1 * 60, lon < 0 ? 'W' : 'E'); - + f.format("%.2f,%.2f,", position.getSpeed(), position.getCourse()); f.format("%1$td%1$tm%1$ty,,", calendar); } @@ -69,9 +69,9 @@ public class WebDataHandler extends BaseDataHandler { @Override protected Position handlePosition(Position position) { - + Device device = Context.getIdentityManager().getDeviceById(position.getDeviceId()); - + String request = url .replace("{uniqueId}", device.getUniqueId()) .replace("{deviceId}", String.valueOf(device.getId())) @@ -80,7 +80,7 @@ public class WebDataHandler extends BaseDataHandler { .replace("{longitude}", String.valueOf(position.getLongitude())) .replace("{gprmc}", formatSentence(position)) .replace("{statusCode}", calculateStatus(position)); - + Context.getAsyncHttpClient().prepareGet(request).execute(); return position; @@ -34,7 +34,7 @@ public class ConnectionManager { private final Map<Long, ActiveDevice> activeDevices = new HashMap<>(); private final Map<Long, Position> positions = new HashMap<>(); private final Map<Long, Set<DataCacheListener>> listeners = new HashMap<>(); - + public ConnectionManager(DataManager dataManager) { if (dataManager != null) { try { @@ -50,7 +50,7 @@ public class ConnectionManager { public void setActiveDevice(long deviceId, Protocol protocol, Channel channel, SocketAddress remoteAddress) { activeDevices.put(deviceId, new ActiveDevice(deviceId, protocol, channel, remoteAddress)); } - + public void removeActiveDevice(Channel channel) { for (ActiveDevice activeDevice : activeDevices.values()) { if (activeDevice.getChannel() == channel) { @@ -73,52 +73,52 @@ public class ConnectionManager { } } } - + public Position getLastPosition(long deviceId) { return positions.get(deviceId); } - + public synchronized Collection<Position> getInitialState(Collection<Long> devices) { - + List<Position> result = new LinkedList<>(); - + for (long device : devices) { if (positions.containsKey(device)) { result.add(positions.get(device)); } } - + return result; } - + public static interface DataCacheListener { public void onUpdate(Position position); } - + public void addListener(Collection<Long> devices, DataCacheListener listener) { for (long deviceId : devices) { addListener(deviceId, listener); } } - + public synchronized void addListener(long deviceId, DataCacheListener listener) { if (!listeners.containsKey(deviceId)) { listeners.put(deviceId, new HashSet<DataCacheListener>()); } listeners.get(deviceId).add(listener); } - + public void removeListener(Collection<Long> devices, DataCacheListener listener) { for (long deviceId : devices) { removeListener(deviceId, listener); } } - + public synchronized void removeListener(long deviceId, DataCacheListener listener) { if (!listeners.containsKey(deviceId)) { listeners.put(deviceId, new HashSet<DataCacheListener>()); } listeners.get(deviceId).remove(listener); } - + } @@ -47,11 +47,11 @@ import org.traccar.web.JsonConverter; public class DataManager implements IdentityManager { private static final long DEFAULT_REFRESH_DELAY = 300; - + private final Config config; - + private DataSource dataSource; - + private final Map<Long, Device> devicesById = new HashMap<>(); private final Map<String, Device> devicesByUniqueId = new HashMap<>(); private long devicesLastUpdate; @@ -65,13 +65,13 @@ public class DataManager implements IdentityManager { devicesRefreshDelay = config.getLong("database.refreshDelay", DEFAULT_REFRESH_DELAY) * 1000; } - + public DataSource getDataSource() { return dataSource; } private void initDatabase() throws Exception { - + String jndiName = config.getString("database.jndi"); if (jndiName != null) { @@ -110,7 +110,7 @@ public class DataManager implements IdentityManager { dataSource = ds; } } - + @Override public Device getDeviceById(long id) { return devicesById.get(id); @@ -132,7 +132,7 @@ public class DataManager implements IdentityManager { return devicesByUniqueId.get(uniqueId); } - + private String getQuery(String key) { String query = config.getString(key); if (query == null) { @@ -158,10 +158,10 @@ public class DataManager implements IdentityManager { } } if (exist) { - + String schemaVersionQuery = getQuery("database.selectSchemaVersion"); if (schemaVersionQuery != null) { - + Schema schema = QueryBuilder.create(dataSource, schemaVersionQuery).executeQuerySingle(new Schema()); int version = 0; @@ -174,7 +174,7 @@ public class DataManager implements IdentityManager { throw new RuntimeException(); } } - + return; } @@ -196,7 +196,7 @@ public class DataManager implements IdentityManager { mockData(admin.getId()); } } - + private void mockData(long userId) { if (config.getBoolean("database.mock")) { try { @@ -224,7 +224,7 @@ public class DataManager implements IdentityManager { position.setLatitude(-36.8932371); position.setLongitude(174.7743053); addPosition(position); - + updateLatestPosition(position); } catch (SQLException error) { @@ -256,7 +256,7 @@ public class DataManager implements IdentityManager { .setObject(user) .executeUpdate()); } - + public void updateUser(User user) throws SQLException { QueryBuilder.create(dataSource, getQuery("database.updateUser")) .setObject(user) @@ -289,26 +289,26 @@ public class DataManager implements IdentityManager { .setLong("userId", userId) .executeQuery(new Device()); } - + public void addDevice(Device device) throws SQLException { device.setId(QueryBuilder.create(dataSource, getQuery("database.insertDevice"), true) .setObject(device) .executeUpdate()); } - + public void updateDevice(Device device) throws SQLException { QueryBuilder.create(dataSource, getQuery("database.updateDevice")) .setObject(device) .executeUpdate(); } - + public void removeDevice(Device device) throws SQLException { QueryBuilder.create(dataSource, getQuery("database.deleteDevice")) .setObject(device) .executeUpdate(); AsyncServlet.sessionRefreshDevice(device.getId()); } - + public void linkDevice(long userId, long deviceId) throws SQLException { QueryBuilder.create(dataSource, getQuery("database.linkDevice")) .setLong("userId", userId) @@ -18,9 +18,9 @@ package org.traccar.database; import org.traccar.model.Device; public interface IdentityManager { - + public Device getDeviceById(long id); - + public Device getDeviceByUniqueId(String uniqueId) throws Exception; } @@ -26,25 +26,25 @@ import org.traccar.model.Permission; import org.traccar.model.User; public class PermissionsManager { - + private final DataManager dataManager; - + private final Map<Long, User> users = new HashMap<>(); - + private final Map<Long, Set<Long>> permissions = new HashMap<>(); - + private Set<Long> getNotNull(long userId) { if (!permissions.containsKey(userId)) { permissions.put(userId, new HashSet<Long>()); } return permissions.get(userId); } - + public PermissionsManager(DataManager dataManager) { this.dataManager = dataManager; refresh(); } - + public final void refresh() { users.clear(); permissions.clear(); @@ -59,27 +59,27 @@ public class PermissionsManager { Log.warning(error); } } - + public void checkAdmin(long userId) throws SecurityException { if (!users.containsKey(userId) || !users.get(userId).getAdmin()) { throw new SecurityException("Admin access required"); } } - + public void checkUser(long userId, long otherUserId) throws SecurityException { if (userId != otherUserId) { checkAdmin(userId); } } - + public Collection<Long> allowedDevices(long userId) { return getNotNull(userId); } - + public void checkDevice(long userId, long deviceId) throws SecurityException { if (!getNotNull(userId).contains(deviceId)) { throw new SecurityException("Device access denied"); } } - + } @@ -42,13 +42,13 @@ import org.traccar.model.Factory; import org.traccar.model.MiscFormatter; public class QueryBuilder { - + private final Map<String, List<Integer>> indexMap = new HashMap<>(); private Connection connection; private PreparedStatement statement; private final String query; private final boolean returnGeneratedKeys; - + private QueryBuilder(DataSource dataSource, String query, boolean returnGeneratedKeys) throws SQLException { this.query = query; this.returnGeneratedKeys = returnGeneratedKeys; @@ -67,7 +67,7 @@ public class QueryBuilder { } } } - + private static String parse(String query, Map<String, List<Integer>> paramMap) { int length = query.length(); @@ -135,7 +135,7 @@ public class QueryBuilder { public static QueryBuilder create(DataSource dataSource, String query, boolean returnGeneratedKeys) throws SQLException { return new QueryBuilder(dataSource, query, returnGeneratedKeys); } - + private List<Integer> indexes(String name) { name = name.toLowerCase(); List<Integer> result = indexMap.get(name); @@ -144,7 +144,7 @@ public class QueryBuilder { } return result; } - + public QueryBuilder setBoolean(String name, boolean value) throws SQLException { for (int i : indexes(name)) { try { @@ -157,7 +157,7 @@ public class QueryBuilder { } return this; } - + public QueryBuilder setInteger(String name, int value) throws SQLException { for (int i : indexes(name)) { try { @@ -170,7 +170,7 @@ public class QueryBuilder { } return this; } - + public QueryBuilder setLong(String name, long value) throws SQLException { for (int i : indexes(name)) { try { @@ -183,7 +183,7 @@ public class QueryBuilder { } return this; } - + public QueryBuilder setDouble(String name, double value) throws SQLException { for (int i : indexes(name)) { try { @@ -196,7 +196,7 @@ public class QueryBuilder { } return this; } - + public QueryBuilder setString(String name, String value) throws SQLException { for (int i : indexes(name)) { try { @@ -213,7 +213,7 @@ public class QueryBuilder { } return this; } - + public QueryBuilder setDate(String name, Date value) throws SQLException { for (int i : indexes(name)) { try { @@ -230,11 +230,11 @@ public class QueryBuilder { } return this; } - + public QueryBuilder setObject(Object object) throws SQLException { - + Method[] methods = object.getClass().getMethods(); - + for (Method method : methods) { if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) { String name = method.getName().substring(3); @@ -262,14 +262,14 @@ public class QueryBuilder { } } } - + return this; } - + private interface ResultSetProcessor<T> { public void process(T object, ResultSet resultSet) throws SQLException; } - + public <T extends Factory> T executeQuerySingle(T prototype) throws SQLException { Collection<T> result = executeQuery(prototype); if (!result.isEmpty()) { @@ -278,12 +278,12 @@ public class QueryBuilder { return null; } } - + public <T extends Factory> Collection<T> executeQuery(T prototype) throws SQLException { List<T> result = new LinkedList<>(); - + if (query != null) { - + try { try (ResultSet resultSet = statement.executeQuery()) { @@ -406,7 +406,7 @@ public class QueryBuilder { } public long executeUpdate() throws SQLException { - + if (query != null) { try { statement.executeUpdate(); @@ -423,5 +423,5 @@ public class QueryBuilder { } return 0; } - + } @@ -37,10 +37,10 @@ public class BingMapsReverseGeocoder extends JsonReverseGeocoder { Address address = new Address(); if (location.containsKey("addressLine")) { address.setStreet(location.getString("addressLine")); - } + } if (location.containsKey("locality")) { address.setSettlement(location.getString("locality")); - } + } if (location.containsKey("adminDistrict2")) { address.setDistrict(location.getString("adminDistrict2")); } @@ -32,15 +32,15 @@ public class FactualReverseGeocoder extends JsonReverseGeocoder { JsonObject result = json.getJsonObject("response").getJsonObject("data"); if (result != null) { Address address = new Address(); - if (result.getJsonObject("street_number") != null) { + if (result.getJsonObject("street_number") != null) { address.setHouse(result.getJsonObject("street_number").getString("name")); } if (result.getJsonObject("street_name") != null) { address.setStreet(result.getJsonObject("street_name").getString("name")); - } + } if (result.getJsonObject("locality") != null) { address.setSettlement(result.getJsonObject("locality").getString("name")); - } + } if (result.getJsonObject("county") != null) { address.setDistrict(result.getJsonObject("county").getString("name")); } @@ -44,7 +44,7 @@ public class GoogleReverseGeocoder extends JsonReverseGeocoder { String value = component.getString("short_name"); for (JsonString type : component.getJsonArray("types").getValuesAs(JsonString.class)) { - + switch (type.getString()) { case "street_number": address.setHouse(value); @@ -70,7 +70,7 @@ public class GoogleReverseGeocoder extends JsonReverseGeocoder { default: continue; } - + break; } } @@ -35,15 +35,15 @@ public class MapQuestReverseGeocoder extends JsonReverseGeocoder { JsonArray locations = result.getJsonObject(0).getJsonArray("locations"); if (locations != null) { JsonObject location = locations.getJsonObject(0); - + Address address = new Address(); - + if (location.containsKey("street")) { address.setStreet(location.getString("street")); - } + } if (location.containsKey("adminArea5")) { address.setSettlement(location.getString("adminArea5")); - } + } if (location.containsKey("adminArea4")) { address.setDistrict(location.getString("adminArea4")); } @@ -56,7 +56,7 @@ public class MapQuestReverseGeocoder extends JsonReverseGeocoder { if (location.containsKey("postalCode")) { address.setPostcode(location.getString("postalCode")); } - + return address; } } @@ -22,7 +22,7 @@ public class NominatimReverseGeocoder extends JsonReverseGeocoder { public NominatimReverseGeocoder() { this("http://nominatim.openstreetmap.org/reverse", 0); } - + public NominatimReverseGeocoder(String url, int cacheSize) { super(url + "?format=json&lat=%f&lon=%f&zoom=18&addressdetails=1", cacheSize); } @@ -38,13 +38,13 @@ public class OpenCageReverseGeocoder extends JsonReverseGeocoder { if (location.containsKey("house_number")) { address.setHouse(location.getString("house_number")); - } + } if (location.containsKey("road")) { address.setStreet(location.getString("road")); - } + } if (location.containsKey("city_district")) { address.setSettlement(location.getString("city_district")); - } + } if (location.containsKey("county")) { address.setDistrict(location.getString("county")); } @@ -57,7 +57,7 @@ public class OpenCageReverseGeocoder extends JsonReverseGeocoder { if (location.containsKey("postcode")) { address.setPostcode(location.getString("postcode")); } - + return address; } } @@ -19,25 +19,25 @@ package org.traccar.helper; * Useful functions to work with bits */ public class BitUtil { - + public static boolean check(long number, int index) { return (number & (1 << index)) != 0; } - + public static int range(int number, int index) { return (number >> index); } - + public static int range(int number, int index, int length) { return (number >> index) & ((1 << length) - 1); } - + public static long range(long number, int index) { return (number >> index); } - + public static long range(long number, int index, int length) { return (number >> index) & ((1l << length) - 1); } - + } @@ -55,14 +55,14 @@ public class ChannelBufferTools { return null; } - + /** * Convert hex to integer (length in hex digits) */ public static int readHexInteger(ChannelBuffer buf, int length) { - + int result = 0; - + for (int i = 0; i < length / 2; i++) { int b = buf.readUnsignedByte(); result *= 10; @@ -70,13 +70,13 @@ public class ChannelBufferTools { result *= 10; result += b & 0x0f; } - + if (length % 2 == 1) { int b = buf.getUnsignedByte(buf.readerIndex()); result *= 10; result += b >>> 4; } - + return result; } @@ -84,22 +84,22 @@ public class ChannelBufferTools { * Return hex string */ public static String readHexString(ChannelBuffer buf, int length) { - + StringBuilder result = new StringBuilder(); Formatter formatter = new Formatter(result); - + for (int i = 0; i < length / 2; i++) { formatter.format("%02x", buf.readByte()); } - + if (length % 2 == 1) { int b = buf.getUnsignedByte(buf.readerIndex()); formatter.format("%01x", b >>> 4); } - + return result.toString(); } - + /** * Read BCD coded coordinate (first byte has sign bit) */ @@ -108,16 +108,16 @@ public class ChannelBufferTools { int b2 = buf.readUnsignedByte(); int b3 = buf.readUnsignedByte(); int b4 = buf.readUnsignedByte(); - + double value = (b2 & 0xf) * 10 + (b3 >> 4); value += (((b3 & 0xf) * 10 + (b4 >> 4)) * 10 + (b4 & 0xf)) / 1000.0; value /= 60; value += ((b1 >> 4 & 0x7) * 10 + (b1 & 0xf)) * 10 + (b2 >> 4); - + if ((b1 & 0x80) != 0) { value = -value; } - + return value; } @@ -99,7 +99,7 @@ public class Crc { private static int crc16Unreflected(ByteBuffer buf, int crc_in, int[] table) { int crc16 = crc_in; - + for (int i = 0; i < buf.remaining(); i++) { crc16 = table[((crc16 >> 8) ^ buf.get(i)) & 0xff] ^ (crc16 << 8); } @@ -109,7 +109,7 @@ public class Crc { private static int crc16Reflected(ByteBuffer buf, int crc_in, int[] table) { int crc16 = crc_in; - + for (int i = 0; i < buf.remaining(); i++) { crc16 = table[(crc16 ^ buf.get(i)) & 0xff] ^ (crc16 >> 8); } @@ -144,7 +144,7 @@ public class Crc { } return checksum; } - + public static String nmeaChecksum(String msg) { int checksum = 0; byte bytes[] = msg.getBytes(Charset.defaultCharset()); @@ -174,5 +174,5 @@ public class Crc { return (10 - (checksum % 10)) % 10; } - + } @@ -27,9 +27,9 @@ import java.util.logging.Logger; * Database driver delegate */ public class DriverDelegate implements Driver { - + private final Driver driver; - + public DriverDelegate(Driver driver) { this.driver = driver; } @@ -67,5 +67,5 @@ public class DriverDelegate implements Driver { public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } - + } @@ -36,14 +36,14 @@ import org.jboss.netty.logging.InternalLoggerFactory; import org.traccar.Config; public class Log { - + private static final String LOGGER_NAME = "traccar"; private static final String STACK_PACKAGE = "org.traccar"; private static final int STACK_LIMIT = 3; private static Logger logger = null; - + public static void setupLogger(Config config) throws IOException { Layout layout = new PatternLayout("%d{yyyy-MM-dd HH:mm:ss} %5p: %m%n"); @@ -53,7 +53,7 @@ public class Log { LogManager.resetConfiguration(); LogManager.getRootLogger().addAppender(new NullAppender()); - + logger = Logger.getLogger(LOGGER_NAME); logger.addAppender(appender); logger.setLevel(Level.toLevel(config.getString("logger.level"), Level.ALL)); @@ -77,7 +77,7 @@ public class Log { } return logger; } - + public static void logSystemInfo() { try { OperatingSystemMXBean operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); @@ -104,7 +104,7 @@ public class Log { Log.warning("Failed to get system info"); } } - + public static void error(String msg) { getLogger().error(msg); } @@ -27,7 +27,7 @@ public class Command implements Factory { public void set(String key, long value) { attributes.put(key, value); } public void set(String key, double value) { attributes.put(key, value); } public void set(String key, String value) { if (value != null && !value.isEmpty()) attributes.put(key, value); } - + public static final String TYPE_POSITION_SINGLE = "positionSingle"; public static final String TYPE_POSITION_PERIODIC = "positionPeriodic"; public static final String TYPE_POSITION_STOP = "positionStop"; @@ -39,5 +39,5 @@ public class Command implements Factory { public static final String KEY_UNIQUE_ID = "uniqueId"; public static final String KEY_FREQUENCY = "frequency"; public static final String KEY_DEVICE_PASSWORD = "devicePassword"; - + } @@ -27,7 +27,7 @@ public class Device implements Factory { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } - + private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @@ -35,13 +35,13 @@ public class Device implements Factory { private String uniqueId; public String getUniqueId() { return uniqueId; } public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } - + private String status; - + private Date lastUpdate; - + private long positionId; - + private long dataId; } @@ -16,7 +16,7 @@ package org.traccar.model; public interface Factory { - + public Object create(); - + } @@ -46,18 +46,18 @@ public class MiscFormatter { public static String toXmlString(Map<String, Object> attributes) { StringBuilder result = new StringBuilder(); - + result.append("<").append(xmlRootNode).append(">"); - + for (Map.Entry<String, Object> entry : attributes.entrySet()) { - + result.append("<").append(entry.getKey()).append(">"); result.append(format(entry.getValue())); result.append("</").append(entry.getKey()).append(">"); } result.append("</").append(xmlRootNode).append(">"); - + return result.toString(); } @@ -84,11 +84,11 @@ public class MiscFormatter { return json.build(); } - + public static Map<String, Object> fromJson(JsonObject json) { - + Map<String, Object> attributes = new LinkedHashMap<>(); - + for (Map.Entry<String, JsonValue> entry : json.entrySet()) { switch (entry.getValue().getValueType()) { case STRING: @@ -110,10 +110,10 @@ public class MiscFormatter { break; } } - + return attributes; } - + public static String toJsonString(Map<String, Object> attributes) { return toJson(attributes).toString(); } @@ -21,13 +21,13 @@ public class Permission implements Factory { public Permission create() { return new Permission(); } - + private long userId; public long getUserId() { return userId; } public void setUserId(long userId) { this.userId = userId; } - + private long deviceId; public long getDeviceId() { return deviceId; } public void setDeviceId(long deviceId) { this.deviceId = deviceId; } - + } @@ -27,7 +27,7 @@ public class Position extends Event implements Factory { private Date fixTime; public Date getFixTime() { return fixTime; } public void setFixTime(Date fixTime) { this.fixTime = fixTime; } - + public void setTime(Date time) { setDeviceTime(time); setFixTime(time); @@ -21,9 +21,9 @@ public class Schema implements Factory { public Schema create() { return new Schema(); } - + private int version; public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } - + } @@ -25,7 +25,7 @@ public class Server implements Factory { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } - + private boolean registration; public boolean getRegistration() { return registration; } public void setRegistration(boolean registration) { this.registration = registration; } @@ -61,7 +61,7 @@ public class Server implements Factory { private double longitude; public double getLongitude() { return longitude; } public void setLongitude(double longitude) { this.longitude = longitude; } - + private int zoom; public int getZoom() { return zoom; } public void setZoom(int zoom) { this.zoom = zoom; } @@ -28,21 +28,21 @@ public class User implements Factory { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } - + private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } - + private String email; public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } private boolean readonly; - + private boolean admin; public boolean getAdmin() { return admin; } public void setAdmin(boolean admin) { this.admin = admin; } - + private String map; public String getMap() { return map; } public void setMap(String map) { this.map = map; } @@ -18,7 +18,7 @@ package org.traccar.protocol; import java.nio.ByteOrder; import java.nio.charset.Charset; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; @@ -103,11 +103,11 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder { boolean alarm = (type & 0x8000) != 0; type = type & 0x7FFF; buf.readUnsignedShort(); // length - + if (alarm) { sendSimpleMessage(channel, MSG_TYPE_ACK_ALARM); } - + if (type == MSG_TYPE_TRACKER_ID) { Log.warning("Unsupported authentication type"); return null; @@ -120,7 +120,7 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder { length = buf.readUnsignedShort(); identify(buf.readBytes(length).toString(Charset.defaultCharset()), channel); } - + else if (type == MSG_TYPE_LAST_LOG_INDEX) { long index = buf.readUnsignedInt(); if (index > 0) { @@ -192,7 +192,7 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder { // Satellites position.set(Event.KEY_SATELLITES, buf.readUnsignedByte()); - + // Cell signal position.set(Event.KEY_GSM, buf.readUnsignedByte()); @@ -205,12 +205,12 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder { // Input/Output position.set(Event.KEY_INPUT, buf.readUnsignedByte()); position.set(Event.KEY_OUTPUT, buf.readUnsignedByte()); - + // Analog sensors for (int i = 1; i <= 8; i++) { position.set(Event.PREFIX_ADC + i, buf.readUnsignedShort()); } - + // Counters position.set(Event.PREFIX_COUNT + 1, buf.readUnsignedInt()); position.set(Event.PREFIX_COUNT + 2, buf.readUnsignedInt()); @@ -222,7 +222,7 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder { // Skip CRC buf.readUnsignedInt(); - + if (type == MSG_TYPE_LOG_RECORDS) { requestArchive(channel); } else { @@ -56,13 +56,13 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { if (validateImei(imei)) { return imei; } - + // Try TC65 v2.8 imei = IMEI_BASE_TC65_V28 + ((unitId + 0xA8180) & 0xFFFFFF); if (validateImei(imei)) { return imei; } - + // Try TC65 v2.0 imei = IMEI_BASE_TC65_V20 + unitId; if (validateImei(imei)) { @@ -70,7 +70,7 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { } } - + return unitId; } @@ -148,7 +148,7 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { if ((selector & 0x0040) != 0) { position.set(Event.KEY_INPUT, buf.readUnsignedByte()); } - + // ADC if ((selector & 0x0020) != 0) { position.set(Event.PREFIX_ADC + 1, buf.readUnsignedShort()); @@ -162,13 +162,13 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { position.set(Event.KEY_POWER, buf.readUnsignedShort() / 1000.0); position.set(Event.KEY_BATTERY, buf.readUnsignedShort()); } - + // Pulse rate 1 if ((selector & 0x10000) != 0) { buf.readUnsignedShort(); buf.readUnsignedInt(); } - + // Pulse rate 2 if ((selector & 0x20000) != 0) { buf.readUnsignedShort(); @@ -189,17 +189,17 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { if ((selector & 0x0040) != 0) { position.set(Event.KEY_OUTPUT, buf.readUnsignedByte()); } - + // Button if ((selector & 0x0200) != 0) { buf.skipBytes(6); } - + // Keypad if ((selector & 0x0400) != 0) { buf.readUnsignedByte(); } - + // Altitude if ((selector & 0x0800) != 0) { position.setAltitude(buf.readShort()); @@ -325,8 +325,8 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { break; } } - } - + } + return position; } @@ -22,7 +22,7 @@ import org.traccar.model.Event; import org.traccar.model.Position; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -53,7 +53,7 @@ public class Ardi01ProtocolDecoder extends BaseProtocolDecoder { throws Exception { String sentence = (String) msg; - + // Parse message Matcher parser = pattern.matcher(sentence); if (!parser.matches()) { @@ -81,19 +81,19 @@ public class Ardi01ProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, Integer.valueOf(parser.group(index++))); time.set(Calendar.SECOND, Integer.valueOf(parser.group(index++))); position.setTime(time.getTime()); - + // Location data position.setLongitude(Double.valueOf(parser.group(index++))); position.setLatitude(Double.valueOf(parser.group(index++))); position.setSpeed(UnitsConverter.knotsFromKph(Double.valueOf(parser.group(index++)))); position.setCourse(Double.valueOf(parser.group(index++))); position.setAltitude(Double.valueOf(parser.group(index++))); - + // Satellites int satellites = Integer.valueOf(parser.group(index++)); position.setValid(satellites >= 3); position.set(Event.KEY_SATELLITES, satellites); - + // Event position.set(Event.KEY_EVENT, parser.group(index++)); @@ -23,17 +23,17 @@ import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; public class AtrackFrameDecoder extends LengthFieldBasedFrameDecoder { private static final int KEEPALIVE_LENGTH = 12; - + public AtrackFrameDecoder() { super(1024, 4, 2); } - + @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Keep alive message if (buf.readableBytes() >= KEEPALIVE_LENGTH && buf.getUnsignedShort(buf.readerIndex()) == 0xfe02) { @@ -45,9 +45,9 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder { channel.write(response, remoteAddress); } } - + private static String readString(ChannelBuffer buf) { - + String result = null; int length = 0; while (buf.getByte(buf.readerIndex() + length) != 0) { @@ -58,10 +58,10 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder { buf.skipBytes(length); } buf.readByte(); - + return result; } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) @@ -76,7 +76,7 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder { } return null; } - + buf.skipBytes(2); // prefix buf.readUnsignedShort(); // checksum buf.readUnsignedShort(); // length @@ -30,7 +30,7 @@ public class AutoFon45FrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Check minimum length if (buf.readableBytes() < 12) { return null; @@ -45,7 +45,7 @@ public class AutoFon45FrameDecoder extends FrameDecoder { length = 34; break; } - + // Check length and return buffer if (length != 0 && buf.readableBytes() >= length) { return buf.readBytes(length); @@ -44,7 +44,7 @@ public class AutoFon45ProtocolDecoder extends BaseProtocolDecoder { protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + ChannelBuffer buf = (ChannelBuffer) msg; int type = buf.getUnsignedByte(0); @@ -31,7 +31,7 @@ public class AutoFonFrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Check minimum length if (buf.readableBytes() < 12) { return null; @@ -49,7 +49,7 @@ public class AutoFonFrameDecoder extends FrameDecoder { length = 257; break; } - + // Check length and return buffer if (length != 0 && buf.readableBytes() >= length) { return buf.readBytes(length); @@ -23,7 +23,7 @@ import org.traccar.model.Event; import org.traccar.model.Position; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; public class Avl301ProtocolDecoder extends BaseProtocolDecoder { @@ -48,7 +48,7 @@ public class BceProtocolDecoder extends BaseProtocolDecoder { throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; - + String imei = String.format("%015d", buf.readLong()); if (!identify(imei, channel)) { return null; @@ -70,16 +70,16 @@ public class BlackKiteProtocolDecoder extends BaseProtocolDecoder { throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; - + buf.readUnsignedByte(); // header int length = (buf.readUnsignedShort() & 0x7fff) + 3; - + List<Position> positions = new LinkedList<>(); Set<Integer> tags = new HashSet<>(); boolean hasLocation = false; Position position = new Position(); position.setProtocol(getProtocolName()); - + while (buf.readerIndex() < length) { // Check if new message started @@ -93,7 +93,7 @@ public class BlackKiteProtocolDecoder extends BaseProtocolDecoder { position = new Position(); } tags.add(tag); - + switch (tag) { case TAG_IMEI: @@ -105,30 +105,30 @@ public class BlackKiteProtocolDecoder extends BaseProtocolDecoder { case TAG_DATE: position.setTime(new Date(buf.readUnsignedInt() * 1000)); break; - + case TAG_COORDINATES: hasLocation = true; position.setValid((buf.readUnsignedByte() & 0xf0) == 0x00); position.setLatitude(buf.readInt() / 1000000.0); position.setLongitude(buf.readInt() / 1000000.0); break; - + case TAG_SPEED_COURSE: position.setSpeed(buf.readUnsignedShort() * 0.0539957); position.setCourse(buf.readUnsignedShort() * 0.1); break; - + case TAG_ALTITUDE: position.setAltitude(buf.readShort()); break; - + case TAG_STATUS: int status = buf.readUnsignedShort(); position.set(Event.KEY_IGNITION, BitUtil.check(status, 9)); position.set(Event.KEY_ALARM, BitUtil.check(status, 15)); position.set(Event.KEY_POWER, BitUtil.check(status, 2)); break; - + case TAG_DIGITAL_INPUTS: int input = buf.readUnsignedShort(); for (int i = 0; i < 16; i++) @@ -140,15 +140,15 @@ public class BlackKiteProtocolDecoder extends BaseProtocolDecoder { for (int i = 0; i < 16; i++) position.set(Event.PREFIX_IO + (i + 17), BitUtil.check(output, i)); break; - + case TAG_INPUT_VOLTAGE1: position.set(Event.PREFIX_ADC + 1, buf.readUnsignedShort() / 1000.0); break; - + case TAG_INPUT_VOLTAGE2: position.set(Event.PREFIX_ADC + 2, buf.readUnsignedShort() / 1000.0); break; - + case TAG_INPUT_VOLTAGE3: position.set(Event.PREFIX_ADC + 3, buf.readUnsignedShort() / 1000.0); break; @@ -165,14 +165,14 @@ public class BlackKiteProtocolDecoder extends BaseProtocolDecoder { default: break; - + } } if (hasLocation && position.getFixTime() != null) { positions.add(position); } - + if (!hasDeviceId()) { Log.warning("Unknown device"); return null; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -53,9 +53,9 @@ public class BoxProtocolDecoder extends BaseProtocolDecoder { throws Exception { String sentence = (String) msg; - + if (sentence.startsWith("H,")) { - + int index = sentence.indexOf(',', 2) + 1; String id = sentence.substring(index, sentence.indexOf(',', index)); identify(id, channel); @@ -68,7 +68,7 @@ public class BoxProtocolDecoder extends BaseProtocolDecoder { } } - + else if (sentence.startsWith("L,") && hasDeviceId()) { // Parse message @@ -100,20 +100,20 @@ public class BoxProtocolDecoder extends BaseProtocolDecoder { position.setLongitude(Double.parseDouble(parser.group(index++))); position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(parser.group(index++)))); position.setCourse(Double.parseDouble(parser.group(index++))); - + // Distance position.set(Event.KEY_ODOMETER, parser.group(index++)); - + // Event position.set(Event.KEY_EVENT, parser.group(index++)); - + // Status int status = Integer.parseInt(parser.group(index++)); position.setValid((status & 0x04) == 0); position.set(Event.KEY_STATUS, status); return position; } - + return null; } @@ -204,7 +204,7 @@ public class CalAmpProtocolDecoder extends BaseProtocolDecoder { int accCount = buf.readUnsignedByte(); int accType = accCount >> 6; accCount &= 0x3f; - + if (type != MSG_MINI_EVENT_REPORT) { buf.readUnsignedByte(); // reserved } @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -60,7 +60,7 @@ public class CarTrackProtocolDecoder extends BaseProtocolDecoder { throws Exception { String sentence = (String) msg; - + // Parse message Matcher parser = pattern.matcher(sentence); if (!parser.matches()) { @@ -88,7 +88,7 @@ public class CarTrackProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, Integer.valueOf(parser.group(index++))); time.set(Calendar.SECOND, Integer.valueOf(parser.group(index++))); time.set(Calendar.MILLISECOND, Integer.valueOf(parser.group(index++))); - + // Validity position.setValid(parser.group(index++).compareTo("A") == 0); @@ -121,7 +121,7 @@ public class CarTrackProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MONTH, Integer.valueOf(parser.group(index++)) - 1); time.set(Calendar.YEAR, 2000 + Integer.valueOf(parser.group(index++))); position.setTime(time.getTime()); - + // State position.set(Event.PREFIX_IO + 1, parser.group(index++)); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -108,7 +108,7 @@ public class CarscopProtocolDecoder extends BaseProtocolDecoder { // Course position.setCourse(Double.valueOf(parser.group(index++))); - + // State position.set(Event.KEY_STATUS, parser.group(index++)); @@ -86,9 +86,9 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { int version = buf.readUnsignedByte(); ChannelBuffer id = buf.readBytes(20); int type = ChannelBuffers.swapShort(buf.readShort()); - + if (type == MSG_HEARTBEAT) { - + if (channel != null) { ChannelBuffer response = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 31); response.writeByte(0x40); response.writeByte(0x40); @@ -107,7 +107,7 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { type == MSG_GPS || type == MSG_ALARM || type == MSG_CURRENT_LOCATION) { - + if (!identify(id.toString(Charset.defaultCharset()).trim(), channel, remoteAddress)) { return null; @@ -128,7 +128,7 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { response.writeByte(0x0D); response.writeByte(0x0A); channel.write(response, remoteAddress); } - + } if (type == MSG_GPS) { @@ -138,7 +138,7 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { } else if (type == MSG_CURRENT_LOCATION) { buf.readUnsignedShort(); } - + buf.readUnsignedInt(); // ACC ON time buf.readUnsignedInt(); // UTC time long odometer = buf.readUnsignedInt(); @@ -147,7 +147,7 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedShort(); // current fuel consumption long status = buf.readUnsignedInt(); buf.skipBytes(8); - + int count = buf.readUnsignedByte(); List<Position> positions = new LinkedList<>(); @@ -184,7 +184,7 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { return position; } - + return null; } @@ -23,13 +23,13 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; public class CellocatorFrameDecoder extends FrameDecoder { private static final int MESSAGE_MINIMUM_LENGTH = 15; - + @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Check minimum length int available = buf.readableBytes(); if (available < MESSAGE_MINIMUM_LENGTH) { @@ -63,7 +63,7 @@ public class CellocatorFrameDecoder extends FrameDecoder { if (length > 0 && available >= length) { return buf.readBytes(length); } - + return null; } @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.nio.ByteOrder; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import org.jboss.netty.buffer.ChannelBuffer; @@ -46,7 +46,7 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { } return imei.toString(); } - + static final int MSG_CLIENT_STATUS = 0; static final int MSG_CLIENT_PROGRAMMING = 3; static final int MSG_CLIENT_SERIAL_LOG = 7; @@ -54,9 +54,9 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { static final int MSG_CLIENT_MODULAR = 9; private static final int MSG_SERVER_ACKNOWLEDGE = 4; - + private byte commandCount; - + private void sendReply(Channel channel, long deviceId, byte packetNumber) { ChannelBuffer reply = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 28); reply.writeByte('M'); @@ -81,7 +81,7 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { channel.write(reply); } } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) @@ -92,7 +92,7 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { buf.skipBytes(4); // system code int type = buf.readUnsignedByte(); long deviceUniqueId = buf.readUnsignedInt(); - + if (type != MSG_CLIENT_SERIAL) { buf.readUnsignedShort(); // communication control } @@ -105,7 +105,7 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { if (type == MSG_CLIENT_STATUS) { Position position = new Position(); position.setProtocol(getProtocolName()); - + // Device identifier if (!identify(String.valueOf(deviceUniqueId), channel)) { return null; @@ -118,23 +118,23 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { // Status position.set(Event.KEY_STATUS, buf.getUnsignedByte(buf.readerIndex()) & 0x0f); - + int operator = (buf.readUnsignedByte() & 0xf0) << 4; operator += buf.readUnsignedByte(); - + buf.readUnsignedByte(); // reason data buf.readUnsignedByte(); // reason buf.readUnsignedByte(); // mode buf.readUnsignedInt(); // IO - + operator <<= 8; operator += buf.readUnsignedByte(); position.set("operator", operator); - + buf.readUnsignedInt(); // ADC buf.readUnsignedMedium(); // Odometer buf.skipBytes(6); // multi-purpose data - + buf.readUnsignedShort(); // gps fix buf.readUnsignedByte(); // location status buf.readUnsignedByte(); // mode 1 @@ -148,7 +148,7 @@ public class CellocatorProtocolDecoder extends BaseProtocolDecoder { position.setAltitude(buf.readInt() * 0.01); position.setSpeed(UnitsConverter.knotsFromMps(buf.readInt() * 0.01)); position.setCourse(buf.readUnsignedShort() / Math.PI * 180.0 / 1000.0); - + // Time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -87,7 +87,7 @@ public class EasyTrackProtocolDecoder extends BaseProtocolDecoder { // Validity position.setValid(parser.group(index++).compareTo("A") == 0); - + // Date Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -107,7 +107,7 @@ public class EasyTrackProtocolDecoder extends BaseProtocolDecoder { hemisphere = parser.group(index++).equals("8") ? -1 : 1; position.setLongitude( hemisphere * Integer.parseInt(parser.group(index++), 16) / 600000.0); - + position.setSpeed(Integer.parseInt(parser.group(index++), 16) / 100.0); position.setCourse(Integer.parseInt(parser.group(index++), 16) / 100.0); @@ -125,7 +125,7 @@ public class EasyTrackProtocolDecoder extends BaseProtocolDecoder { // Odometer position.set(Event.KEY_ODOMETER, Integer.parseInt(parser.group(index++), 16)); - + // Altitude String altitude = parser.group(index++); if (altitude != null) { @@ -76,45 +76,45 @@ public class EelinkProtocolDecoder extends BaseProtocolDecoder { int type = buf.readUnsignedByte(); buf.readShort(); // length int index = buf.readUnsignedShort(); - + if (type != MSG_GPS && type != MSG_DATA) { sendResponse(channel, type, index); } - + if (type == MSG_LOGIN) { identify(ChannelBufferTools.readHexString(buf, 16).substring(1), channel); } - + else if (hasDeviceId() && (type == MSG_GPS || type == MSG_ALARM || type == MSG_STATE || type == MSG_SMS)) { - + // Create new position Position position = new Position(); position.setDeviceId(getDeviceId()); - + position.setProtocol(getProtocolName()); position.set(Event.KEY_INDEX, index); - + // Location position.setTime(new Date(buf.readUnsignedInt() * 1000)); position.setLatitude(buf.readInt() / 1800000.0); position.setLongitude(buf.readInt() / 1800000.0); position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); position.setCourse(buf.readUnsignedShort()); - + // Cell position.set(Event.KEY_CELL, ChannelBufferTools.readHexString(buf, 18)); - + // Validity position.setValid((buf.readUnsignedByte() & 0x01) != 0); - + if (type == MSG_ALARM) { position.set(Event.KEY_ALARM, buf.readUnsignedByte()); } - + if (type == MSG_STATE) { position.set(Event.KEY_STATUS, buf.readUnsignedByte()); } @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.nio.charset.Charset; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -23,13 +23,13 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; public class GalileoFrameDecoder extends FrameDecoder { private static final int MESSAGE_MINIMUM_LENGTH = 5; - + @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Check minimum length if (buf.readableBytes() < MESSAGE_MINIMUM_LENGTH) { return null; @@ -40,7 +40,7 @@ public class GalileoFrameDecoder extends FrameDecoder { if (buf.readableBytes() >= (length + MESSAGE_MINIMUM_LENGTH)) { return buf.readBytes(length + MESSAGE_MINIMUM_LENGTH); } - + return null; } @@ -50,9 +50,9 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder { private static final int TAG_ODOMETER = 0xd4; private static final int TAG_REFRIGERATOR = 0x5b; private static final int TAG_PRESSURE = 0x5c; - + private static final Map<Integer, Integer> tagLengthMap = new HashMap<>(); - + static { int[] l1 = {0x01,0x02,0x35,0x43,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd5,0x88,0x8a,0x8b,0x8c,0xa0,0xaf,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae}; int[] l2 = {0x04,0x10,0x34,0x40,0x41,0x42,0x45,0x46,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x60,0x61,0x62,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xd6,0xd7,0xd8,0xd9,0xda}; @@ -87,16 +87,16 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder { throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; - + buf.readUnsignedByte(); // header int length = (buf.readUnsignedShort() & 0x7fff) + 3; - + List<Position> positions = new LinkedList<>(); Set<Integer> tags = new HashSet<>(); boolean hasLocation = false; Position position = new Position(); position.setProtocol(getProtocolName()); - + while (buf.readerIndex() < length) { // Check if new message started @@ -110,7 +110,7 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder { position = new Position(); } tags.add(tag); - + switch (tag) { case TAG_IMEI: @@ -122,49 +122,49 @@ public class GalileoProtocolDecoder extends BaseProtocolDecoder { case TAG_DATE: position.setTime(new Date(buf.readUnsignedInt() * 1000)); break; - + case TAG_COORDINATES: hasLocation = true; position.setValid((buf.readUnsignedByte() & 0xf0) == 0x00); position.setLatitude(buf.readInt() / 1000000.0); position.setLongitude(buf.readInt() / 1000000.0); break; - + case TAG_SPEED_COURSE: position.setSpeed(buf.readUnsignedShort() * 0.0539957); position.setCourse(buf.readUnsignedShort() * 0.1); break; - + case TAG_ALTITUDE: position.setAltitude(buf.readShort()); break; - + case TAG_STATUS: position.set(Event.KEY_STATUS, buf.readUnsignedShort()); break; - + case TAG_POWER: position.set(Event.KEY_POWER, buf.readUnsignedShort()); break; - + case TAG_BATTERY: position.set(Event.KEY_BATTERY, buf.readUnsignedShort()); break; - + case TAG_ODOMETER: position.set(Event.KEY_ODOMETER, buf.readUnsignedInt()); break; - + default: buf.skipBytes(getTagLength(tag)); break; - + } } if (hasLocation && position.getFixTime() != null) { positions.add(position); } - + if (!hasDeviceId()) { Log.warning("Unknown device"); return null; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import org.jboss.netty.buffer.ChannelBuffer; @@ -45,12 +45,12 @@ public class GatorProtocolDecoder extends BaseProtocolDecoder { private static final int PACKET_PICTURE_FRAME = 0x54; private static final int PACKET_CAMERA_RESPONSE = 0x56; private static final int PACKET_PICTURE_DATA = 0x57; - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + ChannelBuffer buf = (ChannelBuffer) msg; buf.skipBytes(2); // header @@ -62,12 +62,12 @@ public class GatorProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()); id = id.replaceFirst("^0+(?!$)", ""); - + if (type == PACKET_POSITION_DATA || type == PACKET_ROLLCALL_RESPONSE || type == PACKET_ALARM_DATA || type == PACKET_BLIND_AREA) { - + // Create new position Position position = new Position(); position.setProtocol(getProtocolName()); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,7 +34,7 @@ public class GlobalSatProtocolDecoder extends BaseProtocolDecoder { public GlobalSatProtocolDecoder(GlobalSatProtocol protocol) { super(protocol); - + format0 = Context.getConfig().getString(getProtocolName() + ".format0", "TSPRXAB27GHKLMnaicz*U!"); format1 = Context.getConfig().getString(getProtocolName() + ".format1", "SARY*U!"); } @@ -169,7 +169,7 @@ public class GlobalSatProtocolDecoder extends BaseProtocolDecoder { } return position; } - + private static final Pattern pattern = Pattern.compile( "\\$" + "(\\d+)," + // IMEI @@ -186,7 +186,7 @@ public class GlobalSatProtocolDecoder extends BaseProtocolDecoder { "(\\d+\\.?\\d*)," + // Course "(\\d+)," + // Satellites "(\\d+\\.?\\d*)"); // HDOP - + private Position decodeAlternative(Channel channel, String sentence) { // Parse message @@ -208,7 +208,7 @@ public class GlobalSatProtocolDecoder extends BaseProtocolDecoder { // Validity position.setValid(parser.group(index++).compareTo("1") != 0); - + // Time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -257,13 +257,13 @@ public class GlobalSatProtocolDecoder extends BaseProtocolDecoder { throws Exception { String sentence = (String) msg; - + if (sentence.startsWith("GS")) { return decodeOriginal(channel, sentence); } else if (sentence.startsWith("$")) { return decodeAlternative(channel, sentence); } - + return null; } @@ -53,7 +53,7 @@ public class GoSafeProtocolDecoder extends BaseProtocolDecoder { throws Exception { String sentence = (String) msg; - + if (channel != null) { channel.write("1234"); } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -96,7 +96,7 @@ public class GotopProtocolDecoder extends BaseProtocolDecoder { // Speed position.setSpeed(UnitsConverter.knotsFromKph(Double.valueOf(parser.group(index++)))); - + // Status position.set(Event.KEY_STATUS, parser.group(index++)); @@ -119,10 +119,10 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.YEAR, 2000 + Integer.valueOf(parser.group(index++))); time.set(Calendar.MONTH, Integer.valueOf(parser.group(index++)) - 1); time.set(Calendar.DAY_OF_MONTH, Integer.valueOf(parser.group(index++))); - + int localHours = Integer.valueOf(parser.group(index++)); int localMinutes = Integer.valueOf(parser.group(index++)); - + String utcHours = parser.group(index++); String utcMinutes = parser.group(index++); @@ -137,7 +137,7 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder { if (milliseconds != null) { time.set(Calendar.MILLISECOND, Integer.valueOf(milliseconds)); } - + // Timezone calculation if (utcHours != null && utcMinutes != null) { int deltaMinutes = (localHours - Integer.valueOf(utcHours)) * 60; @@ -181,11 +181,11 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder { position.setLongitude(longitude); // Speed - String speed = parser.group(index++); + String speed = parser.group(index++); if (speed != null) { position.setSpeed(Double.valueOf(speed)); } - + // Course String course = parser.group(index++); if (course != null) { @@ -39,7 +39,7 @@ public class Gps103ProtocolEncoder extends StringProtocolEncoder implements Stri @Override protected Object encodeCommand(Command command) { - + switch (command.getType()) { case Command.TYPE_POSITION_STOP: return formatCommand(command, "**,imei:{%s},A", Command.KEY_UNIQUE_ID); @@ -56,7 +56,7 @@ public class Gps103ProtocolEncoder extends StringProtocolEncoder implements Stri case Command.TYPE_ALARM_DISARM: return formatCommand(command, "**,imei:{%s},M", Command.KEY_UNIQUE_ID); } - + return null; } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -51,14 +51,14 @@ public class GpsGateProtocolDecoder extends BaseProtocolDecoder { channel.write(message + Crc.nmeaChecksum(message) + "\r\n"); } } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { String sentence = (String) msg; - + // Process login if (sentence.startsWith("$FRLIN,")) { int beginIndex = sentence.indexOf(',', 7); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import org.jboss.netty.buffer.ChannelBuffer; @@ -27,20 +27,20 @@ public class Gt06FrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Check minimum length if (buf.readableBytes() < 5) { return null; } - + int length = 2 + 2; // head and tail - + if (buf.getByte(buf.readerIndex()) == 0x78) { length += 1 + buf.getUnsignedByte(buf.readerIndex() + 2); } else { length += 2 + buf.getUnsignedShort(buf.readerIndex() + 2); } - + // Check length and return buffer if (buf.readableBytes() >= length) { return buf.readBytes(length); @@ -35,7 +35,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { public Gt06ProtocolDecoder(Gt06Protocol protocol) { super(protocol); - + if (Context.getConfig().hasKey(getProtocolName() + ".timezone")) { forceTimeZone = true; timeZone.setRawOffset(Context.getConfig().getInteger(getProtocolName() + ".timezone") * 1000); @@ -98,12 +98,12 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { if (buf.readByte() != 0x78 || buf.readByte() != 0x78) { return null; } - + int length = buf.readUnsignedByte(); // size int dataLength = length - 5; int type = buf.readUnsignedByte(); - + if (type == MSG_LOGIN) { String imei = readImei(buf); @@ -177,7 +177,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { position.setLatitude(latitude); position.setLongitude(longitude); - + if ((union & 0b0100_0000_0000_0000) != 0) { position.set(Event.KEY_IGNITION, (union & 0b1000_0000_0000_0000) != 0); } @@ -218,7 +218,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { position.set(Event.KEY_GSM, buf.readUnsignedByte()); } } - + if (type == MSG_GPS_LBS_1 && buf.readableBytes() == 4 + 6) { position.set(Event.KEY_ODOMETER, buf.readUnsignedInt()); } @@ -232,7 +232,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { sendResponse(channel, type, index); return position; } - + else { buf.skipBytes(dataLength); if (type != MSG_COMMAND_0 && type != MSG_COMMAND_1 && type != MSG_COMMAND_2) { @@ -44,13 +44,13 @@ public class Gt06ProtocolEncoder extends BaseProtocolEncoder { buf.writeByte('\r'); buf.writeByte('\n'); - + return buf; } - + @Override protected Object encodeCommand(Command command) { - + switch (command.getType()) { case Command.TYPE_ENGINE_STOP: return encodeContent("RELAY,1#"); @@ -60,5 +60,5 @@ public class Gt06ProtocolEncoder extends BaseProtocolEncoder { return null; } - + } @@ -23,7 +23,7 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; import org.traccar.helper.ChannelBufferTools; public class H02FrameDecoder extends FrameDecoder { - + private static final int MESSAGE_LENGTH = 32; @Override @@ -31,7 +31,7 @@ public class H02FrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + String marker = buf.toString(buf.readerIndex(), 1, Charset.defaultCharset()); while (!marker.equals("*") && !marker.equals("$") && buf.readableBytes() > 0) { @@ -40,7 +40,7 @@ public class H02FrameDecoder extends FrameDecoder { marker = buf.toString(buf.readerIndex(), 1, Charset.defaultCharset()); } } - + if (marker.equals("*")) { // Return text message @@ -48,14 +48,14 @@ public class H02FrameDecoder extends FrameDecoder { if (index != null) { return buf.readBytes(index + 1 - buf.readerIndex()); } - + } else if (marker.equals("$")) { // Return binary message if (buf.readableBytes() >= MESSAGE_LENGTH) { return buf.readBytes(MESSAGE_LENGTH); } - + } return null; @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.net.SocketAddress; import java.nio.charset.Charset; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,20 +34,20 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder { public H02ProtocolDecoder(H02Protocol protocol) { super(protocol); } - + private static double readCoordinate(ChannelBuffer buf, boolean lon) { - + int degrees = ChannelBufferTools.readHexInteger(buf, 2); if (lon) { degrees = degrees * 10 + (buf.getUnsignedByte(buf.readerIndex()) >> 4); } - + double result = 0; if (lon) { result = buf.readUnsignedByte() & 0x0f; } result = result * 10 + ChannelBufferTools.readHexInteger(buf, lon ? 5 : 6) * 0.0001; - + result /= 60; result += degrees; @@ -61,13 +61,13 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder { position.set(Event.KEY_IGNITION, !BitUtil.check(status, 10)); position.set(Event.KEY_STATUS, status); } - + private Position decodeBinary(ChannelBuffer buf, Channel channel) { - + // Create new position Position position = new Position(); position.setProtocol(getProtocolName()); - + buf.readByte(); // marker // Identification @@ -86,7 +86,7 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MONTH, ChannelBufferTools.readHexInteger(buf, 2) - 1); time.set(Calendar.YEAR, 2000 + ChannelBufferTools.readHexInteger(buf, 2)); position.setTime(time.getTime()); - + // Location double latitude = readCoordinate(buf, false); position.set(Event.KEY_POWER, buf.readByte()); @@ -122,7 +122,7 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder { "(\\d{2})(\\d{2})(\\d{2})," + // Date (DDMMYY) "(\\p{XDigit}{8})" + // Status ".*"); - + private Position decodeText(String sentence, Channel channel) { // Parse message @@ -188,10 +188,10 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder { protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + ChannelBuffer buf = (ChannelBuffer) msg; String marker = buf.toString(0, 1, Charset.defaultCharset()); - + // TODO X mode? if (marker.equals("*")) { @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -79,7 +79,7 @@ public class HaicomProtocolDecoder extends BaseProtocolDecoder { // Firmware version position.set(Event.KEY_VERSION, parser.group(index++)); - + // Date Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -112,7 +112,7 @@ public class HaicomProtocolDecoder extends BaseProtocolDecoder { // Course position.setCourse(Double.valueOf(parser.group(index++)) / 10); - + // Additional data position.set(Event.KEY_STATUS, parser.group(index++)); position.set(Event.KEY_GSM, parser.group(index++)); @@ -24,26 +24,26 @@ import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder; public class IntellitracFrameDecoder extends DelimiterBasedFrameDecoder { private static final int MESSAGE_MINIMUM_LENGTH = 0; - + private static final byte delimiter[] = { (byte) '\r', (byte) '\n' }; - + public IntellitracFrameDecoder(int maxFrameLength) { super(maxFrameLength, ChannelBuffers.wrappedBuffer(delimiter)); } - + // example of sync header: 0xFA 0xF8 0x1B 0x01 0x81 0x60 0x33 0x3C - + @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Check minimum length if (buf.readableBytes() < MESSAGE_MINIMUM_LENGTH) { return null; } - + // Check for sync packet if (buf.getUnsignedShort(buf.readerIndex()) == 0xFAF8) { ChannelBuffer syncMessage = buf.readBytes(8); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -67,7 +67,7 @@ public class IntellitracProtocolDecoder extends BaseProtocolDecoder { throws Exception { String sentence = (String) msg; - + // Parse message Matcher parser = pattern.matcher(sentence); if (!parser.matches()) { @@ -84,7 +84,7 @@ public class IntellitracProtocolDecoder extends BaseProtocolDecoder { return null; } position.setDeviceId(getDeviceId()); - + // Date and time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -95,19 +95,19 @@ public class IntellitracProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, Integer.valueOf(parser.group(index++))); time.set(Calendar.SECOND, Integer.valueOf(parser.group(index++))); position.setTime(time.getTime()); - + // Location data position.setLongitude(Double.valueOf(parser.group(index++))); position.setLatitude(Double.valueOf(parser.group(index++))); position.setSpeed(Double.valueOf(parser.group(index++))); position.setCourse(Double.valueOf(parser.group(index++))); position.setAltitude(Double.valueOf(parser.group(index++))); - + // Satellites int satellites = Integer.valueOf(parser.group(index++)); position.setValid(satellites >= 3); position.set(Event.KEY_SATELLITES, satellites); - + // Report identifier position.set(Event.KEY_INDEX, Long.valueOf(parser.group(index++))); @@ -35,10 +35,10 @@ public class Jt600FrameDecoder extends FrameDecoder { if (available < 10) { return null; } - + // Message identifier char first = (char) buf.getByte(buf.readerIndex()); - + if (first == '$') { // Check length int length = buf.getUnsignedShort(buf.readerIndex() + 7) + 10; @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.nio.charset.Charset; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -90,9 +90,9 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder { // Course position.setCourse(buf.readUnsignedByte() * 2.0); - + if (version == 1) { - + position.set(Event.KEY_SATELLITES, buf.readUnsignedByte()); // Power @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import org.jboss.netty.buffer.ChannelBuffer; @@ -102,33 +102,33 @@ public class KhdProtocolDecoder extends BaseProtocolDecoder { // Flags int flags = buf.readUnsignedByte(); position.setValid((flags & 0x80) != 0); - + if (type == MSG_ALARM) { - + buf.skipBytes(2); } else { // Odometer position.set(Event.KEY_ODOMETER, buf.readUnsignedMedium()); - + // Status buf.skipBytes(4); - + // Other buf.skipBytes(8); } - + // TODO: parse extra data return position; } else if (type == MSG_LOGIN && channel != null) { - + buf.skipBytes(4); // serial number buf.readByte(); // reserved - + ChannelBuffer response = ChannelBuffers.dynamicBuffer(); response.writeByte(0x29); response.writeByte(0x29); // header response.writeByte(MSG_CONFIRMATION); @@ -141,7 +141,7 @@ public class KhdProtocolDecoder extends BaseProtocolDecoder { channel.write(response); } - + return null; } @@ -43,7 +43,7 @@ public class KhdProtocolEncoder extends BaseProtocolEncoder { return buf; } - + @Override protected Object encodeCommand(Command command) { @@ -56,5 +56,5 @@ public class KhdProtocolEncoder extends BaseProtocolEncoder { return null; } - + } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -48,7 +48,7 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder { "(.)," + // Type "[^\\*]+\\*" + "(\\p{XDigit}{2})"); // Checksum - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) @@ -61,7 +61,7 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder { channel.write(sentence + "\r\n"); return null; } - + // Parse message Matcher parser = pattern.matcher(sentence); if (!parser.matches()) { @@ -129,7 +129,7 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder { } else if (type.equals("X") || type.equals("4")) { response = "$AVCFG,00000000,x*2D"; } - + if (response != null && channel != null) { channel.write(response + "\r\n"); } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import org.jboss.netty.buffer.ChannelBuffer; @@ -31,7 +31,7 @@ public class M2mProtocolDecoder extends BaseProtocolDecoder { public M2mProtocolDecoder(M2mProtocol protocol) { super(protocol); } - + private boolean firstPacket = true; @Override @@ -50,7 +50,7 @@ public class M2mProtocolDecoder extends BaseProtocolDecoder { } if (firstPacket) { - + firstPacket = false; // Read IMEI @@ -67,7 +67,7 @@ public class M2mProtocolDecoder extends BaseProtocolDecoder { identify(imei.toString(), channel); } else if (hasDeviceId()) { - + // Create new position Position position = new Position(); position.setProtocol(getProtocolName()); @@ -83,7 +83,7 @@ public class M2mProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, buf.readUnsignedByte() & 0x7f); time.set(Calendar.SECOND, buf.readUnsignedByte() & 0x7f); position.setTime(time.getTime()); - + // Location int degrees = buf.readUnsignedByte(); double latitude = buf.readUnsignedByte(); @@ -100,14 +100,14 @@ public class M2mProtocolDecoder extends BaseProtocolDecoder { longitude += buf.readUnsignedByte() / 10000.0; longitude /= 60; longitude += degrees; - + if ((b & 0x80) != 0) { longitude = -longitude; } if ((b & 0x40) != 0) { latitude = -latitude; } - + position.setLatitude(latitude); position.setLongitude(longitude); position.setSpeed(buf.readUnsignedByte()); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -76,7 +76,7 @@ public class ManPowerProtocolDecoder extends BaseProtocolDecoder { // Alarm message position.set(Event.KEY_STATUS, parser.group(index++)); - + // Date Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -73,7 +73,7 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { ".*"); // Checksum private boolean parseGPRMC(String gprmc, Position position) { - + // Parse message Matcher parser = patternGPRMC.matcher(gprmc); if (!parser.matches()) { @@ -120,7 +120,7 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.DAY_OF_MONTH, Integer.valueOf(parser.group(index++))); time.set(Calendar.MONTH, Integer.valueOf(parser.group(index++)) - 1); time.set(Calendar.YEAR, 2000 + Integer.valueOf(parser.group(index++))); - position.setTime(time.getTime()); + position.setTime(time.getTime()); return true; } @@ -220,7 +220,7 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { return null; } position.setDeviceId(getDeviceId()); - + } } else { @@ -377,7 +377,7 @@ public class MegastekProtocolDecoder extends BaseProtocolDecoder { return position; } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) @@ -21,7 +21,7 @@ import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.frame.FrameDecoder; public class MeiligaoFrameDecoder extends FrameDecoder { - + private static final int MESSAGE_HEADER = 4; @Override @@ -29,12 +29,12 @@ public class MeiligaoFrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Strip not '$' (0x24) bytes from the beginning while (buf.readable() && buf.getUnsignedByte(buf.readerIndex()) != 0x24) { buf.readByte(); } - + // Check length and return buffer if (buf.readableBytes() >= MESSAGE_HEADER) { int length = buf.getUnsignedShort(buf.readerIndex() + 2); @@ -18,7 +18,7 @@ package org.traccar.protocol; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.charset.Charset; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -73,13 +73,13 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { private static final int MSG_SERVER = 0x0002; private static final int MSG_LOGIN = 0x5000; private static final int MSG_LOGIN_RESPONSE = 0x4000; - + private static final int MSG_POSITION = 0x9955; private static final int MSG_POSITION_LOGGED = 0x9016; private static final int MSG_ALARM = 0x9999; private static final int MSG_RFID = 0x9966; - + private boolean identify(ChannelBuffer buf, Channel channel) { String id = ""; @@ -107,14 +107,14 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { return identify(id, channel); } - + private static void sendResponse( Channel channel, ChannelBuffer id, int type, ChannelBuffer msg) { - + if (channel != null) { ChannelBuffer buf = ChannelBuffers.buffer( 2 + 2 + id.readableBytes() + 2 + msg.readableBytes() + 2 + 2); - + buf.writeByte('@'); buf.writeByte('@'); buf.writeShort(buf.capacity()); @@ -128,7 +128,7 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { channel.write(buf); } } - + private String getMeiligaoServer(Channel channel) { String server = Context.getConfig().getString(getProtocolName() + ".server"); if (server == null) { @@ -142,14 +142,14 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + ChannelBuffer buf = (ChannelBuffer) msg; buf.skipBytes(2); // header buf.readShort(); // length ChannelBuffer id = buf.readBytes(7); int command = buf.readUnsignedShort(); ChannelBuffer response; - + switch (command) { case MSG_LOGIN: if (channel != null) { @@ -23,7 +23,7 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; import org.traccar.helper.ChannelBufferTools; public class MeitrackFrameDecoder extends FrameDecoder { - + @Override protected Object decode( ChannelHandlerContext ctx, @@ -33,7 +33,7 @@ public class MeitrackFrameDecoder extends FrameDecoder { if (buf.readableBytes() < 10) { return null; } - + Integer index = ChannelBufferTools.find(buf, buf.readerIndex(), buf.writerIndex(), ","); if (index != null) { @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.nio.charset.Charset; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; @@ -139,7 +139,7 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { position.set("runtime", parser.group(index++)); position.set(Event.KEY_CELL, parser.group(index++)); position.set(Event.KEY_STATUS, parser.group(index++)); - + // ADC String adc1 = parser.group(index++); if (adc1 != null) { @@ -178,10 +178,10 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { private List<Position> decodeBinaryMessage(Channel channel, ChannelBuffer buf) { List<Position> positions = new LinkedList<>(); - + String flag = buf.toString(2, 1, Charset.defaultCharset()); int index = ChannelBufferTools.find(buf, 0, buf.readableBytes(), ","); - + // Identification String imei = buf.toString(index + 1, 15, Charset.defaultCharset()); if (!identify(imei, channel)) { @@ -189,20 +189,20 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { } buf.skipBytes(index + 1 + 15 + 1 + 3 + 1 + 2 + 2 + 4); - + while (buf.readableBytes() >= 0x34) { - + Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); - + // Event position.set(Event.KEY_EVENT, buf.readUnsignedByte()); - + // Location position.setLatitude(buf.readInt() * 0.000001); position.setLongitude(buf.readInt() * 0.000001); - + // Time (946684800 - timestamp for 2000-01-01) position.setTime(new Date((946684800 + buf.readUnsignedInt()) * 1000)); @@ -211,7 +211,7 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { // Satellites position.set(Event.KEY_SATELLITES, buf.readUnsignedByte()); - + // GSM Signal position.set(Event.KEY_GSM, buf.readUnsignedByte()); @@ -234,16 +234,16 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedShort() + "|" + buf.readUnsignedShort() + "|" + buf.readUnsignedShort() + "|" + buf.readUnsignedShort()); position.set(Event.KEY_STATUS, buf.readUnsignedShort()); - + // ADC position.set(Event.PREFIX_ADC + 1, buf.readUnsignedShort()); position.set(Event.KEY_BATTERY, buf.readUnsignedShort() * 0.01); position.set(Event.KEY_POWER, buf.readUnsignedShort()); - + buf.readUnsignedInt(); // geo-fence positions.add(position); } - + // Delete recorded data if (channel != null) { StringBuilder command = new StringBuilder("@@"); @@ -254,21 +254,21 @@ public class MeitrackProtocolDecoder extends BaseProtocolDecoder { command.append(String.format("%02x\r\n", checksum & 0xff).toUpperCase()); channel.write(command.toString()); } - + return positions; } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + ChannelBuffer buf = (ChannelBuffer) msg; - + // Find type Integer index = ChannelBufferTools.find(buf, 0, buf.readableBytes(), ","); index = ChannelBufferTools.find(buf, index + 1, buf.readableBytes(), ","); - + String type = buf.toString(index + 1, 3, Charset.defaultCharset()); if (type.equals("CCC")) { return decodeBinaryMessage(channel, buf); @@ -22,7 +22,7 @@ public class MeitrackProtocolEncoder extends StringProtocolEncoder { @Override protected Object encodeCommand(Command command) { - + switch (command.getType()) { case Command.TYPE_ENGINE_STOP: return formatCommand(command, "@@M33,{%s},C01,0,12222*18\r\n", Command.KEY_UNIQUE_ID); @@ -33,7 +33,7 @@ public class MeitrackProtocolEncoder extends StringProtocolEncoder { case Command.TYPE_ALARM_DISARM: return formatCommand(command, "@@M33,{%s},C01,0,22022*18\r\n", Command.KEY_UNIQUE_ID); } - + return null; } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -47,7 +47,7 @@ public class MiniFinderProtocolDecoder extends BaseProtocolDecoder { "(\\d+)," + // Satellites in use "(\\d+)," + // Satellites in view "0"); - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) @@ -92,7 +92,7 @@ public class MiniFinderProtocolDecoder extends BaseProtocolDecoder { position.setLongitude(Double.valueOf(parser.group(index++))); position.setSpeed(Double.valueOf(parser.group(index++))); position.setCourse(Double.valueOf(parser.group(index++))); - + // Flags String flags = parser.group(index++); position.set(Event.KEY_FLAGS, flags); @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.nio.charset.Charset; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; @@ -38,7 +38,7 @@ import org.traccar.model.Event; import org.traccar.model.Position; public class Mta6ProtocolDecoder extends BaseProtocolDecoder { - + private final boolean simple; public Mta6ProtocolDecoder(Protocol protocol, boolean simple) { @@ -51,7 +51,7 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE); channel.write(response); } - + private void sendResponse(Channel channel, short packetId, short packetCount) { HttpResponse response = new DefaultHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK); @@ -61,15 +61,15 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { end.writeByte(packetId); end.writeByte(packetCount); end.writeByte(0); - + response.setContent(ChannelBuffers.wrappedBuffer(begin, end)); channel.write(response); } - + private static class FloatReader { - + private int previousFloat; - + public float readFloat(ChannelBuffer buf) { switch (buf.getUnsignedByte(buf.readerIndex()) >> 6) { @@ -88,13 +88,13 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { } return Float.intBitsToFloat(previousFloat); } - + } - + private static class TimeReader extends FloatReader { - + private long weekNumber; - + public Date readTime(ChannelBuffer buf) { long weekTime = (long) (readFloat(buf) * 1000); if (weekNumber == 0) { @@ -110,16 +110,16 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { return new Date(offset + weekNumber * 7 * 24 * 60 * 60 * 1000 + weekTime); } - + } private List<Position> parseFormatA(ChannelBuffer buf) { List<Position> positions = new LinkedList<>(); - + FloatReader latitudeReader = new FloatReader(); FloatReader longitudeReader = new FloatReader(); TimeReader timeReader = new TimeReader(); - + try { while (buf.readable()) { Position position = new Position(); @@ -196,7 +196,7 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { } } catch (IndexOutOfBoundsException error) { } - + return positions; } @@ -270,17 +270,17 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { position.setValid(satellites >= 3); position.set(Event.KEY_SATELLITES, satellites); } - + // TODO: process other data return position; } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + HttpRequest request = (HttpRequest) msg; ChannelBuffer buf = request.getContent(); @@ -295,7 +295,7 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { } buf.skipBytes(uniqueId.length()); buf.skipBytes("&bin=".length()); - + // Read header short packetId = buf.readUnsignedByte(); short offset = buf.readUnsignedByte(); // dataOffset @@ -303,13 +303,13 @@ public class Mta6ProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // reserved short parameters = buf.readUnsignedByte(); // TODO: handle timezone buf.skipBytes(offset - 5); - + // Send response if (channel != null) { sendContinue(channel); sendResponse(channel, packetId, packetCount); } - + // Parse data if (packetId == 0x31 || packetId == 0x32 || packetId == 0x36) { if (simple) { @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -80,7 +80,7 @@ public class MtxProtocolDecoder extends BaseProtocolDecoder { return null; } position.setDeviceId(getDeviceId()); - + // Date Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -30,7 +30,7 @@ public class MxtFrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + if (buf.readableBytes() < 2) { return null; } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import org.jboss.netty.buffer.ChannelBuffer; @@ -101,15 +101,15 @@ public class MxtProtocolDecoder extends BaseProtocolDecoder { position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); int inputMask = buf.readUnsignedByte(); - + if (BitUtil.check(infoGroups, 0)) { buf.skipBytes(8); // waypoints } - + if (BitUtil.check(infoGroups, 1)) { buf.skipBytes(8); // wireless accessory } - + if (BitUtil.check(infoGroups, 2)) { position.set(Event.KEY_SATELLITES, buf.readUnsignedByte()); position.set(Event.KEY_HDOP, buf.readUnsignedByte()); @@ -119,24 +119,24 @@ public class MxtProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // input voltage position.set(Event.PREFIX_TEMP + 1, buf.readByte()); } - + if (BitUtil.check(infoGroups, 3)) { position.set(Event.KEY_ODOMETER, buf.readUnsignedInt()); } - + if (BitUtil.check(infoGroups, 4)) { position.set("hours", buf.readUnsignedInt()); } - + if (BitUtil.check(infoGroups, 5)) { buf.readUnsignedInt(); // reason } - + if (BitUtil.check(infoGroups, 6)) { position.set(Event.KEY_POWER, buf.readUnsignedShort() * 0.001); position.set(Event.KEY_BATTERY, buf.readUnsignedShort()); } - + if (BitUtil.check(infoGroups, 7)) { position.set(Event.KEY_RFID, buf.readUnsignedInt()); } @@ -24,24 +24,24 @@ public class NavigilFrameDecoder extends FrameDecoder { private static final int MESSAGE_HEADER = 20; private static final long PREAMBLE = 0x2477F5F6; - + @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Check minimum length if (buf.readableBytes() < MESSAGE_HEADER) { return null; } - + // Check for preamble boolean hasPreamble = false; if (buf.getUnsignedInt(buf.readerIndex()) == PREAMBLE) { hasPreamble = true; } - + // Check length and return buffer int length = buf.getUnsignedShort(buf.readerIndex() + 6); if (buf.readableBytes() >= length) { @@ -32,7 +32,7 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { public NavigilProtocolDecoder(NavigilProtocol protocol) { super(protocol); } - + private static final int LEAP_SECONDS_DELTA = 25; private static final int MESSAGE_ERROR = 2; @@ -50,18 +50,18 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { private static final int MESSAGE_TRACKING_DATA = 18; private static final int MESSAGE_MOTION_ALARM = 19; private static final int MESSAGE_ACKNOWLEDGEMENT = 255; - + private static Date convertTimestamp(long timestamp) { return new Date((timestamp - LEAP_SECONDS_DELTA) * 1000l); } - + private int senderSequenceNumber = 1; - + private void sendAcknowledgment(Channel channel, int sequenceNumber) { ChannelBuffer data = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 4); data.writeShort(sequenceNumber); data.writeShort(0); // OK - + ChannelBuffer header = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 20); header.writeByte(1); header.writeByte(0); header.writeShort(senderSequenceNumber++); @@ -71,12 +71,12 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { header.writeShort(Crc.crc16X25Ccitt(data.toByteBuffer())); header.writeInt(0); header.writeInt((int) (System.currentTimeMillis() / 1000) + LEAP_SECONDS_DELTA); - + if (channel != null) { channel.write(ChannelBuffers.copiedBuffer(header, data)); } } - + private Position parseUnitReport(ChannelBuffer buf, int sequenceNumber) { Position position = new Position(); position.setProtocol(getProtocolName()); @@ -84,34 +84,34 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { position.setValid(true); position.set(Event.KEY_INDEX, sequenceNumber); position.setDeviceId(getDeviceId()); - + buf.readUnsignedShort(); // report trigger buf.readUnsignedShort(); // flags - + position.setLatitude(buf.readInt() * 0.0000001); position.setLongitude(buf.readInt() * 0.0000001); position.setAltitude( buf.readUnsignedShort()); - + buf.readUnsignedShort(); // satellites in fix buf.readUnsignedShort(); // satellites in track buf.readUnsignedShort(); // GPS antenna state - + position.setSpeed(buf.readUnsignedShort() * 0.194384); position.setCourse(buf.readUnsignedShort()); - + buf.readUnsignedInt(); // distance buf.readUnsignedInt(); // delta distance position.set(Event.KEY_BATTERY, buf.readUnsignedShort() * 0.001); - + buf.readUnsignedShort(); // battery charger status - + position.setTime(convertTimestamp(buf.readUnsignedInt())); - + // TODO: a lot of other stuff return position; } - + private Position parseTg2Report(ChannelBuffer buf, int sequenceNumber) { Position position = new Position(); position.setProtocol(getProtocolName()); @@ -119,23 +119,23 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { position.setValid(true); position.set(Event.KEY_INDEX, sequenceNumber); position.setDeviceId(getDeviceId()); - + buf.readUnsignedShort(); // report trigger buf.readUnsignedByte(); // reserved buf.readUnsignedByte(); // assisted GPS age - + position.setTime(convertTimestamp(buf.readUnsignedInt())); - + position.setLatitude(buf.readInt() * 0.0000001); position.setLongitude(buf.readInt() * 0.0000001); position.setAltitude(buf.readUnsignedShort()); - + buf.readUnsignedByte(); // satellites in fix buf.readUnsignedByte(); // satellites in track - + position.setSpeed(buf.readUnsignedShort() * 0.194384); position.setCourse(buf.readUnsignedShort()); - + buf.readUnsignedInt(); // distance buf.readUnsignedShort(); // maximum speed buf.readUnsignedShort(); // minimum speed @@ -144,11 +144,11 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedShort(); // VSAUT2 voltage buf.readUnsignedShort(); // solar voltage position.set(Event.KEY_BATTERY, buf.readUnsignedShort() * 0.001); - + // TODO: a lot of other stuff return position; } - + private Position parsePositionReport(ChannelBuffer buf, int sequenceNumber, long timestamp) { Position position = new Position(); position.setProtocol(getProtocolName()); @@ -156,20 +156,20 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { position.set(Event.KEY_INDEX, sequenceNumber); position.setDeviceId(getDeviceId()); position.setTime(convertTimestamp(timestamp)); - + position.setLatitude(buf.readMedium() * 0.00002); position.setLongitude(buf.readMedium() * 0.00002); - + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); position.setCourse(buf.readUnsignedByte() * 2); - + short flags = buf.readUnsignedByte(); position.setValid((flags & 0x80) == 0x80 && (flags & 0x40) == 0x40); - + buf.readUnsignedByte(); // reserved return position; } - + private Position parsePositionReport2(ChannelBuffer buf, int sequenceNumber, long timestamp) { Position position = new Position(); position.setProtocol(getProtocolName()); @@ -177,22 +177,22 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { position.set(Event.KEY_INDEX, sequenceNumber); position.setDeviceId(getDeviceId()); position.setTime(convertTimestamp(timestamp)); - + position.setLatitude(buf.readInt() * 0.0000001); position.setLongitude(buf.readInt() * 0.0000001); - + buf.readUnsignedByte(); // report trigger position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); - + short flags = buf.readUnsignedByte(); position.setValid((flags & 0x80) == 0x80 && (flags & 0x40) == 0x40); - + int x = buf.readUnsignedByte(); // satellites in fix buf.readUnsignedInt(); // distance return position; } - + private Position parseSnapshot4(ChannelBuffer buf, int sequenceNumber) { Position position = new Position(); position.setProtocol(getProtocolName()); @@ -204,22 +204,22 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // position fix source buf.readUnsignedByte(); // GNSS fix quality buf.readUnsignedByte(); // GNSS assistance age - + long flags = buf.readUnsignedInt(); position.setValid((flags & 0x0400) == 0x0400); - + position.setTime(convertTimestamp(buf.readUnsignedInt())); - + position.setLatitude(buf.readInt() * 0.0000001); position.setLongitude(buf.readInt() * 0.0000001); position.setAltitude(buf.readUnsignedShort()); - + buf.readUnsignedByte(); // satellites in fix buf.readUnsignedByte(); // satellites in track - + position.setSpeed(buf.readUnsignedShort() * 0.194384); position.setCourse(buf.readUnsignedShort() * 0.1); - + buf.readUnsignedByte(); // maximum speed buf.readUnsignedByte(); // minimum speed buf.readUnsignedInt(); // distance @@ -231,7 +231,7 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { // TODO: a lot of other stuff return position; } - + private Position parseTrackingData(ChannelBuffer buf, int sequenceNumber, long timestamp) { Position position = new Position(); position.setProtocol(getProtocolName()); @@ -241,33 +241,33 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { position.setTime(convertTimestamp(timestamp)); buf.readUnsignedByte(); // tracking mode - + short flags = buf.readUnsignedByte(); position.setValid((flags & 0x01) == 0x01); - + buf.readUnsignedShort(); // duration position.setLatitude(buf.readInt() * 0.0000001); position.setLongitude(buf.readInt() * 0.0000001); - + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); position.setCourse(buf.readUnsignedByte() * 2.0); buf.readUnsignedByte(); // satellites in fix - + position.set(Event.KEY_BATTERY, buf.readUnsignedShort() * 0.001); - + buf.readUnsignedInt(); // distance return position; } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + ChannelBuffer buf = (ChannelBuffer) msg; - + buf.readUnsignedByte(); // protocol version buf.readUnsignedByte(); // version id int sequenceNumber = buf.readUnsignedShort(); @@ -275,7 +275,7 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedShort(); // length int flags = buf.readUnsignedShort(); buf.readUnsignedShort(); // checksum - + // Get device identifier if (!identify(String.valueOf(buf.readUnsignedInt()), channel)) { return null; @@ -287,7 +287,7 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { if ((flags & 0x1) == 0x0) { sendAcknowledgment(channel, sequenceNumber); } - + // Parse messages switch (messageId) { case MESSAGE_UNIT_REPORT: @@ -303,7 +303,7 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { case MESSAGE_TRACKING_DATA: return parseTrackingData(buf, sequenceNumber, timestamp); } - + return null; } @@ -18,7 +18,7 @@ package org.traccar.protocol; import java.net.SocketAddress; import java.nio.ByteOrder; import java.nio.charset.Charset; -import java.util.Calendar; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; @@ -57,7 +57,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { } return false; } - + private class ParseResult { private final long id; private final Position position; @@ -300,7 +300,7 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { // Read message type String type = buf.toString(buf.readerIndex(), 3, charset); buf.skipBytes(type.length()); - + switch (type) { case "*>T": return processSingle(channel, buf); @@ -45,20 +45,20 @@ public class NoranProtocolDecoder extends BaseProtocolDecoder { private static final int MSG_SHAKE_HAND_RESPONSE = 0x8000; private static final int MSG_IMAGE_SIZE = 0x0200; private static final int MSG_IMAGE_PACKET = 0x0201; - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + ChannelBuffer buf = (ChannelBuffer) msg; - + buf.readUnsignedShort(); // length int type = buf.readUnsignedShort(); - + if (type == MSG_SHAKE_HAND && channel != null) { - + ChannelBuffer response = ChannelBuffers.dynamicBuffer(ByteOrder.LITTLE_ENDIAN, 13); response.writeBytes(ChannelBuffers.copiedBuffer(ByteOrder.LITTLE_ENDIAN, "\r\n*KW", Charset.defaultCharset())); response.writeByte(0); @@ -66,10 +66,10 @@ public class NoranProtocolDecoder extends BaseProtocolDecoder { response.writeShort(MSG_SHAKE_HAND_RESPONSE); response.writeByte(1); // status response.writeBytes(ChannelBuffers.copiedBuffer(ByteOrder.LITTLE_ENDIAN, "\r\n", Charset.defaultCharset())); - + channel.write(response, remoteAddress); } - + else if (type == MSG_UPLOAD_POSITION || type == MSG_UPLOAD_POSITION_NEW || type == MSG_CONTROL_RESPONSE || @@ -89,7 +89,7 @@ public class NoranProtocolDecoder extends BaseProtocolDecoder { // Create new position Position position = new Position(); position.setProtocol(getProtocolName()); - + if (type == MSG_CONTROL_RESPONSE) { buf.readUnsignedInt(); // GIS ip buf.readUnsignedInt(); // GIS port @@ -21,7 +21,7 @@ import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.handler.codec.frame.FrameDecoder; public class OrionFrameDecoder extends FrameDecoder { - + private static final int TYPE_USERLOG = 0; private static final int TYPE_SYSLOG = 3; @@ -30,16 +30,16 @@ public class OrionFrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + int length = 6; - + if (buf.readableBytes() >= length) { - + int type = buf.getUnsignedByte(buf.readerIndex() + 2) & 0x0f; - + if (type == TYPE_USERLOG) { if (buf.readableBytes() >= length + 5) { - + int index = buf.readerIndex() + 3; int count = buf.getUnsignedByte(index) & 0x0f; index += 5; @@ -53,7 +53,7 @@ public class OrionFrameDecoder extends FrameDecoder { index += logLength; length += logLength; } - + if (buf.readableBytes() >= length) { return buf.readBytes(length); } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; @@ -34,7 +34,7 @@ public class OrionProtocolDecoder extends BaseProtocolDecoder { public OrionProtocolDecoder(OrionProtocol protocol) { super(protocol); } - + private static final int TYPE_USERLOG = 0; private static final int TYPE_SYSLOG = 3; @@ -47,27 +47,27 @@ public class OrionProtocolDecoder extends BaseProtocolDecoder { channel.write(response); } } - + private static double convertCoordinate(int value) { double degrees = value / 1000000; double minutes = (value % 1000000) / 10000.0; return degrees + minutes / 60; } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; - + buf.skipBytes(2); // header int type = buf.readUnsignedByte() & 0x0f; - + if (type == TYPE_USERLOG) { - + int header = buf.readUnsignedByte(); - + if ((header & 0x40) != 0) { sendResponse(channel, buf); } @@ -77,14 +77,14 @@ public class OrionProtocolDecoder extends BaseProtocolDecoder { } List<Position> positions = new LinkedList<>(); - + for (int i = 0; i < (header & 0x0f); i++) { - + // Create new position Position position = new Position(); position.setDeviceId(getDeviceId()); position.setProtocol(getProtocolName()); - + position.set(Event.KEY_EVENT, buf.readUnsignedByte()); buf.readUnsignedByte(); // length position.set(Event.KEY_FLAGS, buf.readUnsignedShort()); @@ -95,7 +95,7 @@ public class OrionProtocolDecoder extends BaseProtocolDecoder { position.setAltitude(buf.readShort()/ 10.0); position.setCourse(buf.readUnsignedShort()); position.setSpeed(buf.readUnsignedShort() * 0.0539957); - + // Date and time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -106,14 +106,14 @@ public class OrionProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, buf.readUnsignedByte()); time.set(Calendar.SECOND, buf.readUnsignedByte()); position.setTime(time.getTime()); - + // Accuracy int satellites = buf.readUnsignedByte(); position.set(Event.KEY_SATELLITES, satellites); position.setValid(satellites >= 3); positions.add(position); } - + return positions; } @@ -35,16 +35,16 @@ import org.traccar.model.Event; import org.traccar.model.Position; public class OsmAndProtocolDecoder extends BaseProtocolDecoder { - + public OsmAndProtocolDecoder(OsmAndProtocol protocol) { super(protocol); } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + HttpRequest request = (HttpRequest) msg; QueryStringDecoder decoder = new QueryStringDecoder(request.getUri()); Map<String, List<String>> params = decoder.getParameters(); @@ -18,7 +18,7 @@ package org.traccar.protocol; import java.nio.ByteOrder; import java.nio.charset.Charset; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; @@ -38,7 +38,7 @@ import org.traccar.model.Event; import org.traccar.model.Position; public class PiligrimProtocolDecoder extends BaseProtocolDecoder { - + public PiligrimProtocolDecoder(PiligrimProtocol protocol) { super(protocol); } @@ -61,26 +61,26 @@ public class PiligrimProtocolDecoder extends BaseProtocolDecoder { protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + HttpRequest request = (HttpRequest) msg; String uri = request.getUri(); - + if (uri.startsWith("/config")) { sendResponse(channel, "CONFIG: OK"); - + } else if (uri.startsWith("/addlog")) { sendResponse(channel, "ADDLOG: OK"); - + } else if (uri.startsWith("/inform")) { sendResponse(channel, "INFORM: OK"); - + } else if (uri.startsWith("/bingps")) { sendResponse(channel, "BINGPS: OK"); - + // Identification QueryStringDecoder decoder = new QueryStringDecoder(request.getUri()); if (!identify(decoder.getParameters().get("imei").get(0), channel)) { @@ -89,19 +89,19 @@ public class PiligrimProtocolDecoder extends BaseProtocolDecoder { List<Position> positions = new LinkedList<>(); ChannelBuffer buf = request.getContent(); - + while (buf.readableBytes() > 2) { buf.readUnsignedByte(); // header int type = buf.readUnsignedByte(); buf.readUnsignedByte(); // length - + if (type == MSG_GPS || type == MSG_GPS_SENSORS) { - + Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); - + // Time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -112,34 +112,34 @@ public class PiligrimProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, buf.readUnsignedByte()); time.set(Calendar.SECOND, buf.readUnsignedByte()); position.setTime(time.getTime()); - + // Latitude double latitude = buf.readUnsignedByte(); latitude += buf.readUnsignedByte() / 60.0; latitude += buf.readUnsignedByte() / 6000.0; latitude += buf.readUnsignedByte() / 600000.0; - + // Longitude double longitude = buf.readUnsignedByte(); longitude += buf.readUnsignedByte() / 60.0; longitude += buf.readUnsignedByte() / 6000.0; longitude += buf.readUnsignedByte() / 600000.0; - + // Hemisphere int flags = buf.readUnsignedByte(); if ((flags & 0x01) != 0) latitude = -latitude; if ((flags & 0x02) != 0) longitude = -longitude; position.setLatitude(latitude); position.setLongitude(longitude); - + // Satellites int satellites = buf.readUnsignedByte(); position.set(Event.KEY_SATELLITES, satellites); position.setValid(satellites >= 3); - + // Speed position.setSpeed(buf.readUnsignedByte()); - + // Course double course = buf.readUnsignedByte() << 1; course += (flags >> 2) & 1; @@ -158,18 +158,18 @@ public class PiligrimProtocolDecoder extends BaseProtocolDecoder { double battery = buf.readUnsignedByte(); battery += buf.readUnsignedByte() << 8; position.set(Event.KEY_BATTERY, battery / 100); - + buf.skipBytes(6); - + } positions.add(position); - + } else if (type == MSG_EVENTS) { - + buf.skipBytes(13); } } - + return positions; } @@ -18,7 +18,7 @@ package org.traccar.protocol; import java.nio.ByteOrder; import java.nio.charset.Charset; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -45,7 +45,7 @@ public class Pt3000ProtocolDecoder extends BaseProtocolDecoder { "(\\d+\\.?\\d*)?," + // Course "(\\d{2})(\\d{2})(\\d{2})" + // Date (DDMMYY) ".+"); - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) @@ -70,7 +70,7 @@ public class Pt3000ProtocolDecoder extends BaseProtocolDecoder { return null; } position.setDeviceId(getDeviceId()); - + // Time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -22,9 +22,9 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; import org.traccar.helper.ChannelBufferTools; public class Pt502FrameDecoder extends FrameDecoder { - + private static final int BINARY_HEADER = 5; - + @Override protected Object decode( ChannelHandlerContext ctx, @@ -36,7 +36,7 @@ public class Pt502FrameDecoder extends FrameDecoder { } if (buf.getUnsignedByte(buf.readerIndex()) == 0xbf && buf.getUnsignedByte(buf.readerIndex() + 1) == 0xfb) { - + int length = buf.getShort(buf.readerIndex() + 3); if (buf.readableBytes() >= length) { buf.skipBytes(BINARY_HEADER); @@ -44,16 +44,16 @@ public class Pt502FrameDecoder extends FrameDecoder { buf.skipBytes(2); return result; } - + } else { - + Integer index = ChannelBufferTools.find(buf, 0, buf.readableBytes(), "\n"); if (index != null) { ChannelBuffer result = buf.readBytes(index - 1); buf.skipBytes(2); return result; } - + } return null; @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.nio.charset.Charset; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -71,14 +71,14 @@ public class RitiProtocolDecoder extends BaseProtocolDecoder { position.set("mode", buf.readUnsignedByte()); position.set("command", buf.readUnsignedByte()); position.set(Event.KEY_POWER, buf.readUnsignedShort()); - + buf.skipBytes(5); buf.readUnsignedShort(); buf.readUnsignedShort(); - + position.set("distance", buf.readUnsignedInt()); position.set(Event.KEY_ODOMETER, buf.readUnsignedInt()); - + // Parse GPRMC Integer end = ChannelBufferTools.find(buf, buf.readerIndex(), buf.readerIndex() + 80, "*"); String gprmc = buf.toString( @@ -28,13 +28,13 @@ import org.traccar.model.Event; import org.traccar.model.Position; public class RuptelaProtocolDecoder extends BaseProtocolDecoder { - + public RuptelaProtocolDecoder(RuptelaProtocol protocol) { super(protocol); } private static final int COMMAND_RECORDS = 0x01; - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) @@ -51,7 +51,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { } int type = buf.readUnsignedByte(); - + if (type == COMMAND_RECORDS) { List<Position> positions = new LinkedList<>(); @@ -68,7 +68,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // timestamp extension buf.readUnsignedByte(); // priority (reserved) - + // Location position.setLongitude(buf.readInt() / 10000000.0); position.setLatitude(buf.readInt() / 10000000.0); @@ -120,7 +120,7 @@ public class RuptelaProtocolDecoder extends BaseProtocolDecoder { return positions; } - + return null; } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -17,7 +17,7 @@ package org.traccar.protocol; import java.net.SocketAddress; import java.nio.charset.Charset; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; @@ -29,7 +29,7 @@ import org.traccar.model.Event; import org.traccar.model.Position; public class SkypatrolProtocolDecoder extends BaseProtocolDecoder { - + private final long defaultMask; public SkypatrolProtocolDecoder(SkypatrolProtocol protocol) { @@ -25,21 +25,21 @@ import org.traccar.helper.ChannelBufferTools; public class Stl060FrameDecoder extends DelimiterBasedFrameDecoder { private static final byte delimiter[] = { (byte) '#' }; - + public Stl060FrameDecoder(int maxFrameLength) { super(maxFrameLength, ChannelBuffers.wrappedBuffer(delimiter)); } - + @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + ChannelBuffer result = (ChannelBuffer) super.decode(ctx, channel, buf); - + if (result != null) { - + Integer beginIndex = ChannelBufferTools.find( result, 0, result.readableBytes(), "$"); if (beginIndex == null) { @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -91,7 +91,7 @@ public class Stl060ProtocolDecoder extends BaseProtocolDecoder { return null; } position.setDeviceId(getDeviceId()); - + // Date Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -66,7 +66,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { Position position = new Position(); position.setProtocol(getProtocolName()); int index = 1; - + String type = parser.group(index++); if (type != null && (type.equals("Alert") || type.equals("Emergency"))) { position.set(Event.KEY_ALARM, true); @@ -77,7 +77,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { return null; } position.setDeviceId(getDeviceId()); - + // Version position.set(Event.KEY_VERSION, parser.group(index++)); @@ -91,7 +91,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, Integer.valueOf(parser.group(index++))); time.set(Calendar.SECOND, Integer.valueOf(parser.group(index++))); position.setTime(time.getTime()); - + // Cell position.set(Event.KEY_CELL, parser.group(index++)); @@ -105,7 +105,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { // Course position.setCourse(Double.valueOf(parser.group(index++))); - + // Battery position.set(Event.KEY_BATTERY, parser.group(index++)); @@ -29,8 +29,8 @@ public class SuntechProtocolEncoder extends StringProtocolEncoder { case Command.TYPE_ENGINE_RESUME: return formatCommand(command, "SA200CMD;{%s};02;Disable1\r", Command.KEY_UNIQUE_ID); } - + return null; } - + } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -63,7 +63,7 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder { "(\\d+\\.?\\d*)?," + // Speed "(\\d+\\.?\\d*)?," + // Course ".+"); - + private static final Pattern patternTRCCR = Pattern.compile( "\\$TRCCR," + "(\\d{4})(\\d{2})(\\d{2})" + // Date (YYYYMMDD) @@ -83,7 +83,7 @@ public class T55ProtocolDecoder extends BaseProtocolDecoder { throws Exception { String sentence = (String) msg; - + if (!sentence.startsWith("$") && sentence.contains("$")) { int index = sentence.indexOf("$"); String id = sentence.substring(0, index); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import java.util.regex.Matcher; @@ -29,7 +29,7 @@ import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; public class TaipProtocolDecoder extends BaseProtocolDecoder { - + private final boolean sendResponse; public TaipProtocolDecoder(TaipProtocol protocol, boolean sendResponse) { @@ -65,18 +65,18 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { return new Date(millis); } - + private Date getTime(long seconds) { Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.set(Calendar.HOUR_OF_DAY, 0); time.set(Calendar.MINUTE, 0); time.set(Calendar.SECOND, 0); time.set(Calendar.MILLISECOND, 0); - + long millis = time.getTimeInMillis() + seconds * 1000; - + long diff = System.currentTimeMillis() - millis; - + if (diff > 12 * 60 * 60 * 1000) { millis += 24 * 60 * 60 * 1000; } else if (diff < -12 * 60 * 60 * 1000) { @@ -85,14 +85,14 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { return new Date(millis); } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { String sentence = (String) msg; - + // Find message start int beginIndex = sentence.indexOf('>'); if (beginIndex != -1) { @@ -134,7 +134,7 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(getDeviceId()); Integer index = 1; - + // Time String week = parser.group(index++); String day = parser.group(index++); @@ -167,11 +167,11 @@ public class TaipProtocolDecoder extends BaseProtocolDecoder { String longitude = parser.group(index) + '.' + parser.group(index + 1); index += 2; position.setLongitude(Double.valueOf(longitude)); - + // Speed and Course position.setSpeed(UnitsConverter.knotsFromMph(Double.valueOf(parser.group(index++)))); position.setCourse(Double.valueOf(parser.group(index++))); - + // Validity position.setValid(Integer.valueOf(parser.group(index++)) != 0); return position; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -74,7 +74,7 @@ public class TelikProtocolDecoder extends BaseProtocolDecoder { // Message type position.set(Event.KEY_TYPE, parser.group(index++)); - + // Time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -85,7 +85,7 @@ public class TelikProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, Integer.valueOf(parser.group(index++))); time.set(Calendar.SECOND, Integer.valueOf(parser.group(index++))); position.setTime(time.getTime()); - + // Location position.setLongitude(Double.valueOf(parser.group(index++)) / 10000); position.setLatitude(Double.valueOf(parser.group(index++)) / 10000); @@ -23,13 +23,13 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; public class TeltonikaFrameDecoder extends FrameDecoder { private static final int MESSAGE_MINIMUM_LENGTH = 12; - + @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + // Check minimum length if (buf.readableBytes() < MESSAGE_MINIMUM_LENGTH) { return null; @@ -47,7 +47,7 @@ public class TeltonikaFrameDecoder extends FrameDecoder { return buf.readBytes(dataLength + 12); } } - + return null; } @@ -30,7 +30,7 @@ import org.traccar.model.Event; import org.traccar.model.Position; public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { - + public TeltonikaProtocolDecoder(TeltonikaProtocol protocol) { super(protocol); } @@ -51,74 +51,74 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { private static final int CODEC_GH3000 = 0x07; private static final int CODEC_FM4X00 = 0x08; private static final int CODEC_12 = 0x0C; - + private List<Position> parseLocation(Channel channel, ChannelBuffer buf) { List<Position> positions = new LinkedList<>(); - + buf.skipBytes(4); // marker buf.readUnsignedInt(); // data length int codec = buf.readUnsignedByte(); // codec - + if (codec == CODEC_12) { // TODO: decode serial port data return null; } - + int count = buf.readUnsignedByte(); - + for (int i = 0; i < count; i++) { Position position = new Position(); position.setProtocol(getProtocolName()); - + position.setDeviceId(getDeviceId()); - + int globalMask = 0x0f; - + if (codec == CODEC_GH3000) { long time = buf.readUnsignedInt() & 0x3fffffff; time += 1167609600; // 2007-01-01 00:00:00 position.setTime(new Date(time * 1000)); - + globalMask = buf.readUnsignedByte(); if (!BitUtil.check(globalMask, 0)) { return null; } - + int locationMask = buf.readUnsignedByte(); - + if (BitUtil.check(locationMask, 0)) { position.setLatitude(buf.readFloat()); position.setLongitude(buf.readFloat()); } - + if (BitUtil.check(locationMask, 1)) { position.setAltitude(buf.readUnsignedShort()); } - + if (BitUtil.check(locationMask, 2)) { position.setCourse(buf.readUnsignedByte() * 360.0 / 256); } - + if (BitUtil.check(locationMask, 3)) { position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte())); } - + if (BitUtil.check(locationMask, 4)) { int satellites = buf.readUnsignedByte(); position.set(Event.KEY_SATELLITES, satellites); position.setValid(satellites >= 3); } - + if (BitUtil.check(locationMask, 5)) { position.set("area", buf.readUnsignedShort()); position.set(Event.KEY_CELL, buf.readUnsignedShort()); } - + if (BitUtil.check(locationMask, 6)) { position.set(Event.KEY_GSM, buf.readUnsignedByte()); } - + if (BitUtil.check(locationMask, 7)) { position.set("operator", buf.readUnsignedInt()); } @@ -146,7 +146,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { buf.readUnsignedByte(); // total IO data records } - + // Read 1 byte data if (BitUtil.check(globalMask, 1)) { int cnt = buf.readUnsignedByte(); @@ -185,29 +185,29 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { } positions.add(position); } - + if (channel != null) { ChannelBuffer response = ChannelBuffers.directBuffer(4); response.writeInt(count); channel.write(response); } - + return positions; } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - + ChannelBuffer buf = (ChannelBuffer) msg; - + if (buf.getUnsignedShort(0) > 0) { parseIdentification(channel, buf); } else { return parseLocation(channel, buf); } - + return null; } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -62,7 +62,7 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder { if (beginIndex != -1) { sentence = sentence.substring(beginIndex + 1); } - + // Send response if (channel != null) { String id = sentence.substring(0, 12); @@ -135,7 +135,7 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder { // Course position.setCourse(Double.parseDouble(parser.group(index++))); - + // State String status = parser.group(index++); // binary status if (status != null) { @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; @@ -78,10 +78,10 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder { // Get status String status = parser.group(2); - + String[] messages = sentence.substring(sentence.indexOf('\n') + 1).split("\r\n"); List<Position> positions = new LinkedList<>(); - + for (String message : messages) { parser = patternPosition.matcher(message); if (parser.matches()) { @@ -90,7 +90,7 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(getDeviceId()); Integer index = 1; - + // Cell position.set(Event.KEY_CELL, parser.group(index++)); @@ -134,7 +134,7 @@ public class Tlt2hProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MONTH, Integer.valueOf(parser.group(index++)) - 1); time.set(Calendar.YEAR, 2000 + Integer.valueOf(parser.group(index++))); position.setTime(time.getTime()); - + // Status position.set(Event.KEY_STATUS, status); positions.add(position); @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -156,10 +156,10 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { return null; } position.setDeviceId(getDeviceId()); - + // Alarm type position.set(Event.KEY_ALARM, parser.group(index++)); - + if (pattern == pattern1 || pattern == pattern2) { // Time @@ -236,7 +236,7 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { // Odometer position.set(Event.KEY_ODOMETER, parser.group(index++)); - + } else if (pattern == pattern3) { // Time @@ -249,7 +249,7 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, Integer.valueOf(parser.group(index++))); time.set(Calendar.SECOND, Integer.valueOf(parser.group(index++))); position.setTime(time.getTime()); - + // IO Status position.set(Event.PREFIX_IO + 1, parser.group(index++)); @@ -297,9 +297,9 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { longitude += Double.valueOf(parser.group(index++)) / 60; if (parser.group(index++).compareTo("W") == 0) longitude = -longitude; position.setLongitude(longitude); - + } - + if (channel != null) { channel.write("ACK OK\r\n"); } @@ -15,18 +15,18 @@ * limitations under the License. */ package org.traccar.protocol; - -import org.traccar.StringProtocolEncoder; + +import org.traccar.StringProtocolEncoder; import org.traccar.model.Command; public class TotemProtocolEncoder extends StringProtocolEncoder{ - + @Override protected Object encodeCommand(Command command) { // Temporary put default password command.set(Command.KEY_DEVICE_PASSWORD, "000000"); - + switch (command.getType()) { //Assuming PIN 8 (Output C) is the power wire, like manual says but it can be PIN 5,7,8 case Command.TYPE_ENGINE_STOP: @@ -34,7 +34,7 @@ public class TotemProtocolEncoder extends StringProtocolEncoder{ case Command.TYPE_ENGINE_RESUME: return formatCommand(command, "*{%s},025,C,0#", Command.KEY_DEVICE_PASSWORD); } - + return null; } } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -28,7 +28,7 @@ import org.traccar.model.Event; import org.traccar.model.Position; public class TrackboxProtocolDecoder extends BaseProtocolDecoder { - + public TrackboxProtocolDecoder(TrackboxProtocol protocol) { super(protocol); } @@ -51,7 +51,7 @@ public class TrackboxProtocolDecoder extends BaseProtocolDecoder { channel.write("=OK=\r\n"); } } - + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) @@ -65,7 +65,7 @@ public class TrackboxProtocolDecoder extends BaseProtocolDecoder { sendResponse(channel); } } - + else { // Parse message Matcher parser = pattern.matcher(sentence); @@ -100,13 +100,13 @@ public class TrackboxProtocolDecoder extends BaseProtocolDecoder { longitude += Double.valueOf(parser.group(index++)) / 60; if (parser.group(index++).compareTo("W") == 0) longitude = -longitude; position.setLongitude(longitude); - + // HDOP position.set(Event.KEY_HDOP, parser.group(index++)); // Altitude position.setAltitude(Double.valueOf(parser.group(index++))); - + // Validity int fix = Integer.valueOf(parser.group(index++)); position.set(Event.KEY_GPS, fix); @@ -130,7 +130,7 @@ public class TrackboxProtocolDecoder extends BaseProtocolDecoder { return position; } - + return null; } @@ -33,7 +33,7 @@ public class TramigoFrameDecoder extends LengthFieldBasedFrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + if (buf.readableBytes() < 20) { return null; } @@ -43,7 +43,7 @@ public class TramigoFrameDecoder extends LengthFieldBasedFrameDecoder { int length = buf.readableBytes(); byte bytes[] = new byte[length]; buf.getBytes(buf.readerIndex(), bytes); - + ChannelBuffer result = (ChannelBuffer) super.decode( ctx, channel, ChannelBuffers.wrappedBuffer(ByteOrder.LITTLE_ENDIAN, bytes)); if (result != null) { @@ -27,7 +27,7 @@ import java.nio.charset.Charset; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.regex.Matcher; @@ -51,60 +51,60 @@ public class TytanProtocolDecoder extends BaseProtocolDecoder { throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; - + buf.readUnsignedByte(); // protocol buf.readUnsignedShort(); // length int index = buf.readUnsignedByte() >> 3; - + if (channel != null) { ChannelBuffer response = ChannelBuffers.copiedBuffer( "^" + index, Charset.defaultCharset()); channel.write(response, remoteAddress); } - + String id = String.valueOf(buf.readUnsignedInt()); if (!identify(id, channel, remoteAddress)) { return null; } List<Position> positions = new LinkedList<>(); - + while (buf.readableBytes() > 2) { - + Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); - + int end = buf.readerIndex() + buf.readUnsignedByte(); - + position.setTime(new Date(buf.readUnsignedInt() * 1000)); - + int flags = buf.readUnsignedByte(); position.set(Event.KEY_SATELLITES, BitUtil.range(flags, 2)); position.setValid(BitUtil.range(flags, 0, 2) > 0); - + // Latitude double lat = buf.readUnsignedMedium(); lat = lat * -180 / 16777216 + 90; position.setLatitude(lat); - + // Longitude double lon = buf.readUnsignedMedium(); lon = lon * 360 / 16777216 - 180; position.setLongitude(lon); - + // Status flags = buf.readUnsignedByte(); position.set(Event.KEY_IGNITION, BitUtil.check(flags, 0)); position.set(Event.KEY_GSM, BitUtil.range(flags, 2, 3)); position.setCourse((BitUtil.range(flags, 5) * 45 + 180) % 360); - + // Speed int speed = buf.readUnsignedByte(); if (speed < 250) { position.setSpeed(UnitsConverter.knotsFromKph(speed)); } - + while (buf.readerIndex() < end) { int type = buf.readUnsignedByte(); @@ -193,7 +193,7 @@ public class TytanProtocolDecoder extends BaseProtocolDecoder { positions.add(position); } - + return positions; } @@ -46,32 +46,32 @@ public class TzoneProtocolDecoder extends BaseProtocolDecoder { } buf.readUnsignedShort(); // model buf.readUnsignedInt(); // firmware - + String imei = ChannelBufferTools.readHexString(buf, 16).substring(1); if (!identify(imei, channel)) { return null; } - + buf.skipBytes(6); // device time Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); - + // GPS info int blockLength = buf.readUnsignedShort(); int blockEnd = buf.readerIndex() + blockLength; - + if (blockLength == 0) { return null; } - + position.set(Event.KEY_SATELLITES, buf.readUnsignedByte()); - + double lat = buf.readUnsignedInt() / 600000.0; double lon = buf.readUnsignedInt() / 600000.0; - + Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); time.set(Calendar.YEAR, 2000 + buf.readUnsignedByte()); @@ -81,40 +81,40 @@ public class TzoneProtocolDecoder extends BaseProtocolDecoder { time.set(Calendar.MINUTE, buf.readUnsignedByte()); time.set(Calendar.SECOND, buf.readUnsignedByte()); position.setTime(time.getTime()); - + position.setSpeed(buf.readUnsignedShort() * 0.01); - + position.set(Event.KEY_ODOMETER, buf.readUnsignedMedium()); - + int flags = buf.readUnsignedShort(); position.setCourse(BitUtil.range(flags, 0, 9)); position.setLatitude(BitUtil.check(flags, 10) ? lat : -lat); position.setLongitude(BitUtil.check(flags, 9) ? -lon : lon); position.setValid(BitUtil.check(flags, 11)); - + buf.readerIndex(blockEnd); - + // LBS info - + blockLength = buf.readUnsignedShort(); blockEnd = buf.readerIndex() + blockLength; - + if (blockLength > 0) { - + position.set(Event.KEY_LAC, buf.readUnsignedShort()); position.set(Event.KEY_CELL, buf.readUnsignedShort()); - + } - + buf.readerIndex(blockEnd); - + // Status info - + blockLength = buf.readUnsignedShort(); blockEnd = buf.readerIndex() + blockLength; - + if (blockLength > 0) { - + position.set(Event.KEY_ALARM, buf.readUnsignedByte()); buf.readUnsignedByte(); // terminal info position.set(Event.PREFIX_IO + 1, buf.readUnsignedShort()); @@ -125,26 +125,26 @@ public class TzoneProtocolDecoder extends BaseProtocolDecoder { position.set(Event.PREFIX_ADC + 1, buf.readUnsignedShort()); position.set(Event.PREFIX_ADC + 2, buf.readUnsignedShort()); position.set(Event.PREFIX_TEMP + 1, buf.readUnsignedShort()); - + } - + buf.readerIndex(blockEnd); - + // Cards - + int index = 1; for (int i = 0; i < 4; i++) { - + blockLength = buf.readUnsignedShort(); blockEnd = buf.readerIndex() + blockLength; - + if (blockLength > 0) { - + int count = buf.readUnsignedByte(); for (int j = 0; j < count; j++) { int length = buf.readUnsignedByte(); - + boolean odd = length % 2 != 0; String num = ChannelBufferTools.readHexString(buf, odd ? length + 1 : length); @@ -154,34 +154,34 @@ public class TzoneProtocolDecoder extends BaseProtocolDecoder { } position.set("card" + index, num); - + } } - + buf.readerIndex(blockEnd); - + } - + // Temperature - + buf.skipBytes(buf.readUnsignedShort()); - + // Lock - + buf.skipBytes(buf.readUnsignedShort()); // Passengers - + blockLength = buf.readUnsignedShort(); blockEnd = buf.readerIndex() + blockLength; - + if (blockLength > 0) { - + position.set("passengers-on", buf.readUnsignedMedium()); position.set("passengers-off", buf.readUnsignedMedium()); - + } - + buf.readerIndex(blockEnd); return position; @@ -28,7 +28,7 @@ public class UlbotechFrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + if (buf.readableBytes() < 2) { return null; } @@ -81,7 +81,7 @@ public class UlbotechProtocolDecoder extends BaseProtocolDecoder { seconds += 946684800l; // 2000-01-01 00:00 seconds -= timeZone; position.setTime(new Date(seconds * 1000)); - + boolean hasLocation = false; while (buf.readableBytes() > 3) { @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -59,7 +59,7 @@ public class V680ProtocolDecoder extends BaseProtocolDecoder { String sentence = (String) msg; sentence = sentence.trim(); - + // Detect device ID if (sentence.length() == 16) { String imei = sentence.substring(1, sentence.length()); @@ -145,7 +145,7 @@ public class V680ProtocolDecoder extends BaseProtocolDecoder { position.setTime(time.getTime()); return position; } - + return null; } @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; @@ -66,9 +66,9 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { channel.write(response.toString()); } } - + private Position decodePosition(String substring) { - + // Parse message Matcher parser = pattern.matcher(substring); if (!hasDeviceId() || !parser.matches()) { @@ -183,7 +183,7 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { else if (sentence.startsWith("#P#")) { sendResponse(channel, "#AP#", null); } - + // Parse message else if (sentence.startsWith("#SD#") || sentence.startsWith("#D#")) { @@ -195,9 +195,9 @@ public class WialonProtocolDecoder extends BaseProtocolDecoder { return position; } } - + else if (sentence.startsWith("#B#")) { - + String[] messages = sentence.substring(sentence.indexOf('#', 1) + 1).split("\\|"); List<Position> positions = new LinkedList<>(); @@ -22,7 +22,7 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder; import org.traccar.helper.ChannelBufferTools; public class WondexFrameDecoder extends FrameDecoder { - + private static final int KEEP_ALIVE_LENGTH = 8; @Override @@ -30,7 +30,7 @@ public class WondexFrameDecoder extends FrameDecoder { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { - + if (buf.readableBytes() < KEEP_ALIVE_LENGTH) { return null; } @@ -51,7 +51,7 @@ public class WondexFrameDecoder extends FrameDecoder { buf.skipBytes(2); return frame; } - + } return null; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -97,23 +97,23 @@ public class WondexProtocolDecoder extends BaseProtocolDecoder { int satellites = Integer.valueOf(parser.group(index++)); position.setValid(satellites >= 3); position.set(Event.KEY_SATELLITES, satellites); - + // Event position.set(Event.KEY_EVENT, parser.group(index++)); - + // Battery position.set(Event.KEY_BATTERY, parser.group(index++)); - + // Odometer position.set(Event.KEY_ODOMETER, parser.group(index++)); - + // Input position.set(Event.KEY_INPUT, parser.group(index++)); - + // ADC position.set(Event.PREFIX_ADC + 1, parser.group(index++)); position.set(Event.PREFIX_ADC + 2, parser.group(index++)); - + // Output position.set(Event.KEY_OUTPUT, parser.group(index++)); return position; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -77,7 +77,7 @@ public class XirgoProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(getDeviceId()); position.set(Event.KEY_EVENT, parser.group(index++)); - + // Date Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -102,7 +102,7 @@ public class XirgoProtocolDecoder extends BaseProtocolDecoder { position.set(Event.KEY_BATTERY, parser.group(index++)); position.set(Event.KEY_GSM, parser.group(index++)); position.set(Event.KEY_ODOMETER, parser.group(index++)); - + // Validity position.setValid(Integer.valueOf(parser.group(index++)) == 1); @@ -23,7 +23,7 @@ import org.traccar.model.Position; import java.text.ParseException; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +16,7 @@ package org.traccar.protocol; import java.net.SocketAddress; -import java.util.Calendar; +import java.util.Calendar; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -68,17 +68,17 @@ public class YwtProtocolDecoder extends BaseProtocolDecoder { if (end == -1) { end = sentence.length(); } - + channel.write("%AT+SN=" + sentence.substring(start, end)); return null; } - + // Parse message Matcher parser = pattern.matcher(sentence); if (!parser.matches()) { return null; } - + // Create new position Position position = new Position(); position.setProtocol(getProtocolName()); @@ -90,7 +90,7 @@ public class YwtProtocolDecoder extends BaseProtocolDecoder { return null; } position.setDeviceId(getDeviceId()); - + // Time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); @@ -113,7 +113,7 @@ public class YwtProtocolDecoder extends BaseProtocolDecoder { Double latitude = Double.valueOf(parser.group(index++)); if (hemisphere.compareTo("S") == 0) latitude = -latitude; position.setLatitude(latitude); - + // Altitude String altitude = parser.group(index++); if (altitude != null) { @@ -125,15 +125,15 @@ public class YwtProtocolDecoder extends BaseProtocolDecoder { // Course position.setCourse(Double.valueOf(parser.group(index++))); - + // Satellites int satellites = Integer.valueOf(parser.group(index++)); position.setValid(satellites >= 3); position.set(Event.KEY_SATELLITES, satellites); - + // Report identifier String reportId = parser.group(index++); - + // Status position.set(Event.KEY_STATUS, parser.group(index++)); @@ -41,20 +41,20 @@ import org.traccar.model.Position; public class AsyncServlet extends BaseServlet { private static final long ASYNC_TIMEOUT = 120000; - + @Override protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { async(req.startAsync(), getUserId(req)); return true; } - + public class AsyncSession { - + private static final boolean DEBUG_ASYNC = false; - + private static final long SESSION_TIMEOUT = 30; private static final long REQUEST_TIMEOUT = 20; - + private boolean destroyed; private final long userId; private final Set<Long> devices = new HashSet<>(); @@ -62,13 +62,13 @@ public class AsyncServlet extends BaseServlet { private Timeout requestTimeout; private final Map<Long, Position> positions = new HashMap<>(); private AsyncContext activeContext; - + private void logEvent(String message) { if (DEBUG_ASYNC) { Log.debug("AsyncSession: " + this.hashCode() + " destroyed: " + destroyed + " " + message); } } - + public AsyncSession(long userId, Collection<Long> devices) { logEvent("create userId: " + userId + " devices: " + devices.size()); this.userId = userId; @@ -78,14 +78,14 @@ public class AsyncServlet extends BaseServlet { for (Position position : initialPositions) { positions.put(position.getDeviceId(), position); } - + Context.getConnectionManager().addListener(devices, dataListener); } - + public boolean hasDevice(long deviceId) { return devices.contains(deviceId); } - + private final ConnectionManager.DataCacheListener dataListener = new ConnectionManager.DataCacheListener() { @Override public void onUpdate(Position position) { @@ -104,7 +104,7 @@ public class AsyncServlet extends BaseServlet { } } }; - + private final TimerTask sessionTimer = new TimerTask() { @Override public void run(Timeout tmt) throws Exception { @@ -118,7 +118,7 @@ public class AsyncServlet extends BaseServlet { } } }; - + private final TimerTask requestTimer = new TimerTask() { @Override public void run(Timeout tmt) throws Exception { @@ -132,7 +132,7 @@ public class AsyncServlet extends BaseServlet { } } }; - + public synchronized void request(AsyncContext context) { logEvent("request context: " + context.hashCode()); if (!destroyed) { @@ -150,7 +150,7 @@ public class AsyncServlet extends BaseServlet { } } } - + private synchronized void response() { logEvent("response context: " + activeContext.hashCode()); if (!destroyed) { @@ -174,17 +174,17 @@ public class AsyncServlet extends BaseServlet { sessionTimer, SESSION_TIMEOUT, TimeUnit.SECONDS); } } - + } - + private static final Map<Long, AsyncSession> asyncSessions = new HashMap<>(); - + public static void sessionRefreshUser(long userId) { synchronized (asyncSessions) { asyncSessions.remove(userId); } } - + public static void sessionRefreshDevice(long deviceId) { synchronized (asyncSessions) { Iterator<Entry<Long, AsyncSession>> iterator = asyncSessions.entrySet().iterator(); @@ -195,19 +195,19 @@ public class AsyncServlet extends BaseServlet { } } } - + private void async(final AsyncContext context, long userId) { - + context.setTimeout(ASYNC_TIMEOUT); HttpServletRequest req = (HttpServletRequest) context.getRequest(); synchronized (asyncSessions) { - + if (Boolean.valueOf(req.getParameter("first")) || !asyncSessions.containsKey(userId)) { Collection<Long> devices = Context.getPermissionsManager().allowedDevices(userId); asyncSessions.put(userId, new AsyncSession(userId, devices)); } - + asyncSessions.get(userId).request(context); } } @@ -29,9 +29,9 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public abstract class BaseServlet extends HttpServlet { - + public static final String USER_KEY = "user"; - + @Override protected final void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String command = req.getPathInfo(); @@ -51,9 +51,9 @@ public abstract class BaseServlet extends HttpServlet { sendResponse(resp.getWriter(), error); } } - + protected abstract boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception; - + public long getUserId(HttpServletRequest req) { Long userId = (Long) req.getSession().getAttribute(USER_KEY); if (userId == null) { @@ -61,25 +61,25 @@ public abstract class BaseServlet extends HttpServlet { } return userId; } - + public void sendResponse(Writer writer, boolean success) throws IOException { JsonObjectBuilder result = Json.createObjectBuilder(); result.add("success", success); writer.write(result.build().toString()); } - + public void sendResponse(Writer writer, JsonStructure json) throws IOException { JsonObjectBuilder result = Json.createObjectBuilder(); result.add("success", true); result.add("data", json); writer.write(result.build().toString()); } - + public void sendResponse(Writer writer, Exception error) throws IOException { JsonObjectBuilder result = Json.createObjectBuilder(); result.add("success", false); result.add("error", Log.exceptionStack(error)); writer.write(result.build().toString()); } - + } @@ -12,7 +12,7 @@ public class CommandServlet extends BaseServlet { @Override protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { - + switch (command) { case "/send": send(req, resp); @@ -43,12 +43,12 @@ public class DeviceServlet extends BaseServlet { } return true; } - + private void get(HttpServletRequest req, HttpServletResponse resp) throws Exception { sendResponse(resp.getWriter(), JsonConverter.arrayToJson( Context.getDataManager().getDevices(getUserId(req)))); } - + private void add(HttpServletRequest req, HttpServletResponse resp) throws Exception { Device device = JsonConverter.objectFromJson(req.getReader(), new Device()); long userId = getUserId(req); @@ -57,14 +57,14 @@ public class DeviceServlet extends BaseServlet { Context.getPermissionsManager().refresh(); sendResponse(resp.getWriter(), JsonConverter.objectToJson(device)); } - + private void update(HttpServletRequest req, HttpServletResponse resp) throws Exception { Device device = JsonConverter.objectFromJson(req.getReader(), new Device()); Context.getPermissionsManager().checkDevice(getUserId(req), device.getId()); Context.getDataManager().updateDevice(device); sendResponse(resp.getWriter(), true); } - + private void remove(HttpServletRequest req, HttpServletResponse resp) throws Exception { Device device = JsonConverter.objectFromJson(req.getReader(), new Device()); Context.getPermissionsManager().checkDevice(getUserId(req), device.getId()); @@ -24,7 +24,7 @@ public class MainServlet extends BaseServlet { @Override protected boolean handle(String command, HttpServletRequest req, HttpServletResponse resp) throws Exception { - + switch (command) { case "/session": session(req, resp); @@ -41,7 +41,7 @@ public class MainServlet extends BaseServlet { default: return false; } - return true; + return true; } private void session(HttpServletRequest req, HttpServletResponse resp) throws Exception { @@ -39,9 +39,9 @@ public class PositionServlet extends BaseServlet { default: return false; } - return true; + return true; } - + private void get(HttpServletRequest req, HttpServletResponse resp) throws Exception { long deviceId = Long.valueOf(req.getParameter("deviceId")); Context.getPermissionsManager().checkDevice(getUserId(req), deviceId); @@ -35,14 +35,14 @@ public class ServerServlet extends BaseServlet { default: return false; } - return true; + return true; } - + private void get(HttpServletRequest req, HttpServletResponse resp) throws Exception { sendResponse(resp.getWriter(), JsonConverter.objectToJson( Context.getDataManager().getServer())); } - + private void update(HttpServletRequest req, HttpServletResponse resp) throws Exception { Server server = JsonConverter.objectFromJson(req.getReader(), new Server()); Context.getPermissionsManager().checkAdmin(getUserId(req)); @@ -41,15 +41,15 @@ public class UserServlet extends BaseServlet { default: return false; } - return true; + return true; } - + private void get(HttpServletRequest req, HttpServletResponse resp) throws Exception { Context.getPermissionsManager().checkAdmin(getUserId(req)); sendResponse(resp.getWriter(), JsonConverter.arrayToJson( Context.getDataManager().getUsers())); } - + private void add(HttpServletRequest req, HttpServletResponse resp) throws Exception { User user = JsonConverter.objectFromJson(req.getReader(), new User()); Context.getPermissionsManager().checkUser(getUserId(req), user.getId()); @@ -57,7 +57,7 @@ public class UserServlet extends BaseServlet { Context.getPermissionsManager().refresh(); sendResponse(resp.getWriter(), JsonConverter.objectToJson(user)); } - + private void update(HttpServletRequest req, HttpServletResponse resp) throws Exception { User user = JsonConverter.objectFromJson(req.getReader(), new User()); if (user.getAdmin()) { @@ -69,7 +69,7 @@ public class UserServlet extends BaseServlet { Context.getPermissionsManager().refresh(); sendResponse(resp.getWriter(), true); } - + private void remove(HttpServletRequest req, HttpServletResponse resp) throws Exception { User user = JsonConverter.objectFromJson(req.getReader(), new User()); Context.getPermissionsManager().checkUser(getUserId(req), user.getId()); @@ -36,7 +36,7 @@ public class WebServer { private final Config config; private final DataSource dataSource; private final HandlerList handlers = new HandlerList(); - + private void initServer() { String address = config.getString("web.address"); @@ -47,7 +47,7 @@ public class WebServer { server = new Server(new InetSocketAddress(address, port)); } } - + public WebServer(Config config, DataSource dataSource) { this.config = config; this.dataSource = dataSource; |