diff options
Diffstat (limited to 'src')
28 files changed, 558 insertions, 145 deletions
diff --git a/src/org/traccar/BasePipelineFactory.java b/src/org/traccar/BasePipelineFactory.java index 31845290f..2b5028f33 100644 --- a/src/org/traccar/BasePipelineFactory.java +++ b/src/org/traccar/BasePipelineFactory.java @@ -44,6 +44,7 @@ public abstract class BasePipelineFactory implements ChannelPipelineFactory { private int timeout; private FilterHandler filterHandler; + private CoordinatesHandler coordinatesHandler; private DistanceHandler distanceHandler; private ReverseGeocoderHandler reverseGeocoderHandler; private LocationProviderHandler locationProviderHandler; @@ -115,6 +116,10 @@ public abstract class BasePipelineFactory implements ChannelPipelineFactory { filterHandler = new FilterHandler(); } + if (Context.getConfig().getBoolean("coordinates.filter")) { + coordinatesHandler = new CoordinatesHandler(); + } + if (Context.getReverseGeocoder() != null) { reverseGeocoderHandler = new ReverseGeocoderHandler( Context.getReverseGeocoder(), Context.getConfig().getBoolean("geocoder.processInvalidPositions")); @@ -188,6 +193,10 @@ public abstract class BasePipelineFactory implements ChannelPipelineFactory { pipeline.addLast("filter", filterHandler); } + if (coordinatesHandler != null) { + pipeline.addLast("coordinatesHandler", coordinatesHandler); + } + if (Context.getDataManager() != null) { pipeline.addLast("dataHandler", new DefaultDataHandler()); } diff --git a/src/org/traccar/CoordinatesHandler.java b/src/org/traccar/CoordinatesHandler.java new file mode 100644 index 000000000..2dcb3c632 --- /dev/null +++ b/src/org/traccar/CoordinatesHandler.java @@ -0,0 +1,51 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar; + +import org.traccar.helper.DistanceCalculator; +import org.traccar.model.Position; + +public class CoordinatesHandler extends BaseDataHandler { + + private final int coordinatesError; + + public CoordinatesHandler() { + Config config = Context.getConfig(); + coordinatesError = config.getInteger("coordinates.error", 50); + } + + private Position getLastPosition(long deviceId) { + if (Context.getIdentityManager() != null) { + return Context.getIdentityManager().getLastPosition(deviceId); + } + return null; + } + + @Override + protected Position handlePosition(Position position) { + Position last = getLastPosition(position.getDeviceId()); + if (last != null) { + double distance = DistanceCalculator.distance( + position.getLatitude(), position.getLongitude(), last.getLatitude(), last.getLongitude()); + if (distance < coordinatesError) { + position.setLatitude(last.getLatitude()); + position.setLongitude(last.getLongitude()); + } + } + return position; + } + +} diff --git a/src/org/traccar/MainEventHandler.java b/src/org/traccar/MainEventHandler.java index c01760283..3f7e68b2a 100644 --- a/src/org/traccar/MainEventHandler.java +++ b/src/org/traccar/MainEventHandler.java @@ -25,6 +25,7 @@ import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler; import org.jboss.netty.handler.timeout.IdleStateEvent; import org.traccar.helper.Log; import org.traccar.model.Position; +import org.traccar.protocol.TeltonikaProtocolDecoder; import java.sql.SQLException; import java.text.SimpleDateFormat; @@ -78,7 +79,8 @@ public class MainEventHandler extends IdleStateAwareChannelHandler { Log.info(formatChannel(e.getChannel()) + " disconnected"); closeChannel(e.getChannel()); - if (ctx.getPipeline().get("httpDecoder") == null) { + if (ctx.getPipeline().get("httpDecoder") == null + && !(ctx.getPipeline().get("objectDecoder") instanceof TeltonikaProtocolDecoder)) { Context.getConnectionManager().removeActiveDevice(e.getChannel()); } } diff --git a/src/org/traccar/model/Position.java b/src/org/traccar/model/Position.java index e667f097d..d2409a75d 100644 --- a/src/org/traccar/model/Position.java +++ b/src/org/traccar/model/Position.java @@ -54,6 +54,7 @@ public class Position extends Message { public static final String KEY_APPROXIMATE = "approximate"; public static final String KEY_THROTTLE = "throttle"; public static final String KEY_MOTION = "motion"; + public static final String KEY_ARMED = "armed"; public static final String KEY_OBD_SPEED = "obd-speed"; public static final String KEY_OBD_ODOMETER = "obd-odometer"; @@ -65,15 +66,25 @@ public class Position extends Message { public static final String PREFIX_ADC = "adc"; public static final String PREFIX_IO = "io"; public static final String PREFIX_COUNT = "count"; + public static final String PREFIX_BUTTON = "button"; + public static final String ALARM_GENERAL = "general"; public static final String ALARM_SOS = "sos"; public static final String ALARM_VIBRATION = "vibration"; public static final String ALARM_MOVEMENT = "movement"; + public static final String ALARM_LOW_SPEED = "lowspeed"; public static final String ALARM_OVERSPEED = "overspeed"; public static final String ALARM_FALL_DOWN = "fallDown"; public static final String ALARM_LOW_BATTERY = "lowBattery"; public static final String ALARM_MOTION = "motion"; public static final String ALARM_FAULT = "fault"; + public static final String ALARM_POWER_OFF = "powerOff"; + public static final String ALARM_GEOFENCE = "geofence"; + public static final String ALARM_GEOFENCE_ENTER = "geofenceEnter"; + public static final String ALARM_GEOFENCE_EXIT = "geofenceExit"; + public static final String ALARM_GPS_ANTENNA_CUT = "gpsAntennaCut"; + public static final String ALARM_ACCIDENT = "accident"; + private String protocol; diff --git a/src/org/traccar/notification/NotificationFormatter.java b/src/org/traccar/notification/NotificationFormatter.java index 37bd7848c..449426df0 100644 --- a/src/org/traccar/notification/NotificationFormatter.java +++ b/src/org/traccar/notification/NotificationFormatter.java @@ -53,9 +53,9 @@ public final class NotificationFormatter { + "Point: http://www.openstreetmap.org/?mlat=%3$f&mlon=%4$f#map=16/%3$f/%4$f%n" + "Time: %2$tc%n"; - public static final String TITLE_TEMPLATE_TYPE_DEVICE_OVERSPEED = "%1$s: exeeds the speed"; + public static final String TITLE_TEMPLATE_TYPE_DEVICE_OVERSPEED = "%1$s: exceeds the speed"; public static final String MESSAGE_TEMPLATE_TYPE_DEVICE_OVERSPEED = "Device: %1$s%n" - + "Exeeds the speed: %5$f%n" + + "Exceeds the speed: %5$f%n" + "Point: http://www.openstreetmap.org/?mlat=%3$f&mlon=%4$f#map=16/%3$f/%4$f%n" + "Time: %2$tc%n"; diff --git a/src/org/traccar/protocol/AutoFonProtocolDecoder.java b/src/org/traccar/protocol/AutoFonProtocolDecoder.java index dd0f54af0..90e8ca103 100644 --- a/src/org/traccar/protocol/AutoFonProtocolDecoder.java +++ b/src/org/traccar/protocol/AutoFonProtocolDecoder.java @@ -169,7 +169,9 @@ public class AutoFonProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(deviceSession.getDeviceId()); short status = buf.readUnsignedByte(); - position.set(Position.KEY_ALARM, BitUtil.check(status, 7)); + if (BitUtil.check(status, 7)) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } position.set(Position.KEY_BATTERY, BitUtil.to(status, 7)); buf.skipBytes(2); // remaining time diff --git a/src/org/traccar/protocol/Avl301ProtocolDecoder.java b/src/org/traccar/protocol/Avl301ProtocolDecoder.java index 4d2dfe126..818dd94df 100644 --- a/src/org/traccar/protocol/Avl301ProtocolDecoder.java +++ b/src/org/traccar/protocol/Avl301ProtocolDecoder.java @@ -123,7 +123,7 @@ public class Avl301ProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_LAC, buf.readUnsignedShort()); position.set(Position.KEY_CID, buf.readUnsignedMedium()); - position.set(Position.KEY_ALARM, true); + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); int flags = buf.readUnsignedByte(); position.set("acc", (flags & 0x2) != 0); diff --git a/src/org/traccar/protocol/BlackKiteProtocolDecoder.java b/src/org/traccar/protocol/BlackKiteProtocolDecoder.java index 92179072a..c2c051884 100644 --- a/src/org/traccar/protocol/BlackKiteProtocolDecoder.java +++ b/src/org/traccar/protocol/BlackKiteProtocolDecoder.java @@ -122,7 +122,9 @@ public class BlackKiteProtocolDecoder extends BaseProtocolDecoder { case TAG_STATUS: int status = buf.readUnsignedShort(); position.set(Position.KEY_IGNITION, BitUtil.check(status, 9)); - position.set(Position.KEY_ALARM, BitUtil.check(status, 15)); + if (BitUtil.check(status, 15)) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } position.set(Position.KEY_POWER, BitUtil.check(status, 2)); break; diff --git a/src/org/traccar/protocol/CarTrackProtocolDecoder.java b/src/org/traccar/protocol/CarTrackProtocolDecoder.java index e0fd60b15..0d21e77e6 100644 --- a/src/org/traccar/protocol/CarTrackProtocolDecoder.java +++ b/src/org/traccar/protocol/CarTrackProtocolDecoder.java @@ -99,7 +99,7 @@ public class CarTrackProtocolDecoder extends BaseProtocolDecoder { odometer = odometer.replace("?", "F"); position.set(Position.KEY_ODOMETER, Integer.parseInt(odometer, 16)); - position.set(Position.KEY_ALARM, parser.next()); + parser.next(); // there is no meaningful alarms position.set(Position.PREFIX_ADC + 1, parser.next()); return position; diff --git a/src/org/traccar/protocol/CarcellProtocolDecoder.java b/src/org/traccar/protocol/CarcellProtocolDecoder.java index 7aacfa4d0..e9b6cdf28 100644 --- a/src/org/traccar/protocol/CarcellProtocolDecoder.java +++ b/src/org/traccar/protocol/CarcellProtocolDecoder.java @@ -143,7 +143,9 @@ public class CarcellProtocolDecoder extends BaseProtocolDecoder { parser.next(); // panic button status String painelStatus = parser.next(); - position.set(Position.KEY_ALARM, painelStatus.equals("1")); + if (painelStatus.equals("1")) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } position.set("painel", painelStatus.equals("2")); Double mainVoltage = parser.nextDouble() / 100d; diff --git a/src/org/traccar/protocol/CastelProtocolDecoder.java b/src/org/traccar/protocol/CastelProtocolDecoder.java index 212096018..994c66ea6 100644 --- a/src/org/traccar/protocol/CastelProtocolDecoder.java +++ b/src/org/traccar/protocol/CastelProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2015 - 2016 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -132,150 +132,175 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { } } - @Override - protected Object decode( - Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + private Object decodeSc( + Channel channel, SocketAddress remoteAddress, ChannelBuffer buf, + int version, ChannelBuffer id, int type, DeviceSession deviceSession) { - ChannelBuffer buf = (ChannelBuffer) msg; + if (type == MSG_SC_HEARTBEAT) { - int header = buf.readUnsignedShort(); - buf.readUnsignedShort(); // length + sendResponse(channel, remoteAddress, version, id, MSG_SC_HEARTBEAT_RESPONSE, null); - int version = -1; - if (header == 0x4040) { - version = buf.readUnsignedByte(); - } + } else if (type == MSG_SC_LOGIN || type == MSG_SC_LOGOUT || type == MSG_SC_GPS + || type == MSG_SC_ALARM || type == MSG_SC_CURRENT_LOCATION) { - ChannelBuffer id = buf.readBytes(20); - int type = ChannelBuffers.swapShort(buf.readShort()); - - DeviceSession deviceSession = getDeviceSession( - channel, remoteAddress, id.toString(StandardCharsets.US_ASCII).trim()); - if (deviceSession == null) { - return null; - } + if (type == MSG_SC_LOGIN) { + ChannelBuffer response = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 10); + response.writeInt(0xFFFFFFFF); + response.writeShort(0); + response.writeInt((int) (System.currentTimeMillis() / 1000)); + sendResponse(channel, remoteAddress, version, id, MSG_SC_LOGIN_RESPONSE, response); + } - if (version == -1) { + if (type == MSG_SC_GPS) { + buf.readUnsignedByte(); // historical + } else if (type == MSG_SC_ALARM) { + buf.readUnsignedInt(); // alarm + } else if (type == MSG_SC_CURRENT_LOCATION) { + buf.readUnsignedShort(); + } - if (type == 0x2001) { + buf.readUnsignedInt(); // ACC ON time + buf.readUnsignedInt(); // UTC time + long odometer = buf.readUnsignedInt(); + buf.readUnsignedInt(); // trip odometer + buf.readUnsignedInt(); // total fuel consumption + buf.readUnsignedShort(); // current fuel consumption + long status = buf.readUnsignedInt(); + buf.skipBytes(8); - sendResponse(channel, remoteAddress, id, (short) 0x1001); + int count = buf.readUnsignedByte(); - buf.readUnsignedInt(); // index - buf.readUnsignedInt(); // unix time - buf.readUnsignedByte(); + List<Position> positions = new LinkedList<>(); - return readPosition(deviceSession, buf); + for (int i = 0; i < count; i++) { + Position position = readPosition(deviceSession, buf); + position.set(Position.KEY_ODOMETER, odometer); + position.set(Position.KEY_STATUS, status); + positions.add(position); + } + if (!positions.isEmpty()) { + return positions; } - } else if (version == 4) { + } else if (type == MSG_SC_GPS_SLEEP) { - if (type == MSG_SC_HEARTBEAT) { + buf.readUnsignedInt(); // device time - sendResponse(channel, remoteAddress, version, id, MSG_SC_HEARTBEAT_RESPONSE, null); + return readPosition(deviceSession, buf); - } else if (type == MSG_SC_LOGIN || type == MSG_SC_LOGOUT || type == MSG_SC_GPS - || type == MSG_SC_ALARM || type == MSG_SC_CURRENT_LOCATION) { + } else if (type == MSG_SC_AGPS_REQUEST) { - if (type == MSG_SC_LOGIN) { - ChannelBuffer response = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 10); - response.writeInt(0xFFFFFFFF); - response.writeShort(0); - response.writeInt((int) (System.currentTimeMillis() / 1000)); - sendResponse(channel, remoteAddress, version, id, MSG_SC_LOGIN_RESPONSE, response); - } + return readPosition(deviceSession, buf); - if (type == MSG_SC_GPS) { - buf.readUnsignedByte(); // historical - } else if (type == MSG_SC_ALARM) { - buf.readUnsignedInt(); // alarm - } else if (type == MSG_SC_CURRENT_LOCATION) { - buf.readUnsignedShort(); - } + } - buf.readUnsignedInt(); // ACC ON time - buf.readUnsignedInt(); // UTC time - long odometer = buf.readUnsignedInt(); - buf.readUnsignedInt(); // trip odometer - buf.readUnsignedInt(); // total fuel consumption - buf.readUnsignedShort(); // current fuel consumption - long status = buf.readUnsignedInt(); - buf.skipBytes(8); + return null; + } - int count = buf.readUnsignedByte(); - List<Position> positions = new LinkedList<>(); + private Object decodeCc( + Channel channel, SocketAddress remoteAddress, ChannelBuffer buf, + int version, ChannelBuffer id, int type, DeviceSession deviceSession) { - for (int i = 0; i < count; i++) { - Position position = readPosition(deviceSession, buf); - position.set(Position.KEY_ODOMETER, odometer); - position.set(Position.KEY_STATUS, status); - positions.add(position); - } + if (type == MSG_CC_HEARTBEAT) { - if (!positions.isEmpty()) { - return positions; - } + sendResponse(channel, remoteAddress, version, id, MSG_CC_HEARTBEAT_RESPONSE, null); - } else if (type == MSG_SC_GPS_SLEEP || type == MSG_SC_AGPS_REQUEST) { + buf.readUnsignedByte(); // 0x01 for history + int count = buf.readUnsignedByte(); - return readPosition(deviceSession, buf); + List<Position> positions = new LinkedList<>(); + + for (int i = 0; i < count; i++) { + Position position = readPosition(deviceSession, buf); + + position.set(Position.KEY_STATUS, buf.readUnsignedInt()); + position.set(Position.KEY_BATTERY, buf.readUnsignedByte()); + position.set(Position.KEY_ODOMETER, buf.readUnsignedInt()); + + buf.readUnsignedByte(); // geo-fencing id + buf.readUnsignedByte(); // geo-fencing flags + buf.readUnsignedByte(); // additional flags + + position.set(Position.KEY_LAC, buf.readUnsignedShort()); + position.set(Position.KEY_CID, buf.readUnsignedShort()); + positions.add(position); } - } else { + return positions; - if (type == MSG_CC_HEARTBEAT) { + } else if (type == MSG_CC_LOGIN) { - sendResponse(channel, remoteAddress, version, id, MSG_CC_HEARTBEAT_RESPONSE, null); + sendResponse(channel, remoteAddress, version, id, MSG_CC_LOGIN_RESPONSE, null); - buf.readUnsignedByte(); // 0x01 for history - int count = buf.readUnsignedByte(); + Position position = readPosition(deviceSession, buf); - List<Position> positions = new LinkedList<>(); + position.set(Position.KEY_STATUS, buf.readUnsignedInt()); + position.set(Position.KEY_BATTERY, buf.readUnsignedByte()); + position.set(Position.KEY_ODOMETER, buf.readUnsignedInt()); - for (int i = 0; i < count; i++) { - Position position = readPosition(deviceSession, buf); + buf.readUnsignedByte(); // geo-fencing id + buf.readUnsignedByte(); // geo-fencing flags + buf.readUnsignedByte(); // additional flags - position.set(Position.KEY_STATUS, buf.readUnsignedInt()); - position.set(Position.KEY_BATTERY, buf.readUnsignedByte()); - position.set(Position.KEY_ODOMETER, buf.readUnsignedInt()); + // GSM_CELL_CODE + // STR_Z - firmware version + // STR_Z - hardware version - buf.readUnsignedByte(); // geo-fencing id - buf.readUnsignedByte(); // geo-fencing flags - buf.readUnsignedByte(); // additional flags + return position; - position.set(Position.KEY_LAC, buf.readUnsignedShort()); - position.set(Position.KEY_CID, buf.readUnsignedShort()); + } - positions.add(position); - } + return null; + } - return positions; + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { - } else if (type == MSG_CC_LOGIN) { + ChannelBuffer buf = (ChannelBuffer) msg; - sendResponse(channel, remoteAddress, version, id, MSG_CC_LOGIN_RESPONSE, null); + int header = buf.readUnsignedShort(); + buf.readUnsignedShort(); // length - Position position = readPosition(deviceSession, buf); + int version = -1; + if (header == 0x4040) { + version = buf.readUnsignedByte(); + } - position.set(Position.KEY_STATUS, buf.readUnsignedInt()); - position.set(Position.KEY_BATTERY, buf.readUnsignedByte()); - position.set(Position.KEY_ODOMETER, buf.readUnsignedInt()); + ChannelBuffer id = buf.readBytes(20); + int type = ChannelBuffers.swapShort(buf.readShort()); - buf.readUnsignedByte(); // geo-fencing id - buf.readUnsignedByte(); // geo-fencing flags - buf.readUnsignedByte(); // additional flags + DeviceSession deviceSession = getDeviceSession( + channel, remoteAddress, id.toString(StandardCharsets.US_ASCII).trim()); + if (deviceSession == null) { + return null; + } + + if (version == -1) { + + if (type == 0x2001) { + + sendResponse(channel, remoteAddress, id, (short) 0x1001); - // GSM_CELL_CODE - // STR_Z - firmware version - // STR_Z - hardware version + buf.readUnsignedInt(); // index + buf.readUnsignedInt(); // unix time + buf.readUnsignedByte(); - return position; + return readPosition(deviceSession, buf); } + } else if (version == 4) { + + return decodeSc(channel, remoteAddress, buf, version, id, type, deviceSession); + + } else { + + return decodeCc(channel, remoteAddress, buf, version, id, type, deviceSession); + } return null; diff --git a/src/org/traccar/protocol/Gps103ProtocolDecoder.java b/src/org/traccar/protocol/Gps103ProtocolDecoder.java index 821cf2d21..b153984cb 100644 --- a/src/org/traccar/protocol/Gps103ProtocolDecoder.java +++ b/src/org/traccar/protocol/Gps103ProtocolDecoder.java @@ -102,6 +102,25 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder { .any() .compile(); + private String decodeAlarm(String value) { + switch (value) { + case "tracker": + return null; + case "help me": + return Position.ALARM_SOS; + case "low battery": + return Position.ALARM_LOW_BATTERY; + case "stockade": + return Position.ALARM_GEOFENCE; + case "move": + return Position.ALARM_MOVEMENT; + case "speed": + return Position.ALARM_OVERSPEED; + default: + return null; + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -195,7 +214,7 @@ public class Gps103ProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(deviceSession.getDeviceId()); String alarm = parser.next(); - position.set(Position.KEY_ALARM, alarm); + position.set(Position.KEY_ALARM, decodeAlarm(alarm)); if (channel != null && alarm.equals("help me")) { channel.write("**,imei:" + imei + ",E;", remoteAddress); } diff --git a/src/org/traccar/protocol/GranitProtocolDecoder.java b/src/org/traccar/protocol/GranitProtocolDecoder.java index 0c7ea4d1d..3a2d24fa2 100644 --- a/src/org/traccar/protocol/GranitProtocolDecoder.java +++ b/src/org/traccar/protocol/GranitProtocolDecoder.java @@ -71,7 +71,9 @@ public class GranitProtocolDecoder extends BaseProtocolDecoder { private static void decodeStructure(ChannelBuffer buf, Position position) { short flags = buf.readUnsignedByte(); position.setValid(BitUtil.check(flags, 7)); - position.set(Position.KEY_ALARM, BitUtil.check(flags, 1)); + if (BitUtil.check(flags, 1)) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } short satDel = buf.readUnsignedByte(); position.set(Position.KEY_SATELLITES, BitUtil.from(satDel, 4)); diff --git a/src/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/org/traccar/protocol/Gt06ProtocolDecoder.java index 3e875086e..d69f425ab 100644 --- a/src/org/traccar/protocol/Gt06ProtocolDecoder.java +++ b/src/org/traccar/protocol/Gt06ProtocolDecoder.java @@ -154,7 +154,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { private void decodeStatus(Position position, ChannelBuffer buf) { - position.set(Position.KEY_ALARM, true); + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); int flags = buf.readUnsignedByte(); diff --git a/src/org/traccar/protocol/H02ProtocolDecoder.java b/src/org/traccar/protocol/H02ProtocolDecoder.java index bb18a68e2..fc6c9f17c 100644 --- a/src/org/traccar/protocol/H02ProtocolDecoder.java +++ b/src/org/traccar/protocol/H02ProtocolDecoder.java @@ -65,20 +65,15 @@ public class H02ProtocolDecoder extends BaseProtocolDecoder { private void processStatus(Position position, long status) { if (!BitUtil.check(status, 0) || !BitUtil.check(status, 1) - || !BitUtil.check(status, 3) || !BitUtil.check(status, 4) || !BitUtil.check(status, 7)) { + || !BitUtil.check(status, 2)) { if (!BitUtil.check(status, 0)) { position.set(Position.KEY_ALARM, Position.ALARM_VIBRATION); } else if (!BitUtil.check(status, 1)) { - position.set(Position.KEY_ALARM, "robbery"); - } else if (!BitUtil.check(status, 3)) { - position.set(Position.KEY_ALARM, "illegal ignition"); - } else if (!BitUtil.check(status, 4)) { - position.set(Position.KEY_ALARM, "entering"); - } else if (!BitUtil.check(status, 7)) { - position.set(Position.KEY_ALARM, "out"); + position.set(Position.KEY_ALARM, Position.ALARM_SOS); + } else if (!BitUtil.check(status, 2)) { + position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED); } - } position.set(Position.KEY_IGNITION, BitUtil.check(status, 10)); position.set(Position.KEY_STATUS, status); diff --git a/src/org/traccar/protocol/Jt600ProtocolDecoder.java b/src/org/traccar/protocol/Jt600ProtocolDecoder.java index 7e0b54456..372b4cac1 100644 --- a/src/org/traccar/protocol/Jt600ProtocolDecoder.java +++ b/src/org/traccar/protocol/Jt600ProtocolDecoder.java @@ -151,7 +151,7 @@ public class Jt600ProtocolDecoder extends BaseProtocolDecoder { Position position = new Position(); position.setProtocol(getProtocolName()); - position.set(Position.KEY_ALARM, true); + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next()); if (deviceSession == null) { diff --git a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java index 9c7e9ea23..41e248791 100644 --- a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java +++ b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java @@ -151,6 +151,27 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { return server; } + private String decodeAlarm(short value) { + switch (value) { + case 0x01: + return Position.ALARM_SOS; + case 0x10: + return Position.ALARM_LOW_BATTERY; + case 0x11: + return Position.ALARM_OVERSPEED; + case 0x12: + return Position.ALARM_MOVEMENT; + case 0x13: + return Position.ALARM_GEOFENCE_ENTER; + case 0x50: + return Position.ALARM_POWER_OFF; + case 0x53: + return Position.ALARM_GPS_ANTENNA_CUT; + default: + return null; + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -196,7 +217,7 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { // Custom data if (command == MSG_ALARM) { - position.set(Position.KEY_ALARM, buf.readUnsignedByte()); + position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedByte())); } else if (command == MSG_POSITION_LOGGED) { buf.skipBytes(6); } diff --git a/src/org/traccar/protocol/MxtProtocolDecoder.java b/src/org/traccar/protocol/MxtProtocolDecoder.java index 56024057e..1dbfc3696 100644 --- a/src/org/traccar/protocol/MxtProtocolDecoder.java +++ b/src/org/traccar/protocol/MxtProtocolDecoder.java @@ -82,7 +82,9 @@ public class MxtProtocolDecoder extends BaseProtocolDecoder { long flags = buf.readUnsignedInt(); position.set(Position.KEY_IGNITION, BitUtil.check(flags, 0)); - position.set(Position.KEY_ALARM, BitUtil.check(flags, 1)); + if (BitUtil.check(flags, 1)) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } position.set(Position.KEY_INPUT, BitUtil.between(flags, 2, 7)); position.set(Position.KEY_OUTPUT, BitUtil.between(flags, 7, 10)); position.setCourse(BitUtil.between(flags, 10, 13) * 45); diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/org/traccar/protocol/NavisProtocolDecoder.java index fad24301c..72c5f53c3 100644 --- a/src/org/traccar/protocol/NavisProtocolDecoder.java +++ b/src/org/traccar/protocol/NavisProtocolDecoder.java @@ -95,7 +95,11 @@ public class NavisProtocolDecoder extends BaseProtocolDecoder { buf.skipBytes(6); // event time - position.set(Position.KEY_ALARM, buf.readUnsignedByte()); + short armedStatus = buf.readUnsignedByte(); + position.set(Position.KEY_ARMED, armedStatus & 0x7F); + if (BitUtil.check(armedStatus, 7)) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } position.set(Position.KEY_STATUS, buf.readUnsignedByte()); position.set(Position.KEY_GSM, buf.readUnsignedByte()); diff --git a/src/org/traccar/protocol/NoranProtocolDecoder.java b/src/org/traccar/protocol/NoranProtocolDecoder.java index c2161d9c9..aaecfc1db 100644 --- a/src/org/traccar/protocol/NoranProtocolDecoder.java +++ b/src/org/traccar/protocol/NoranProtocolDecoder.java @@ -90,7 +90,23 @@ public class NoranProtocolDecoder extends BaseProtocolDecoder { position.setValid(BitUtil.check(buf.readUnsignedByte(), 0)); - position.set(Position.KEY_ALARM, buf.readUnsignedByte()); + short alarm = buf.readUnsignedByte(); + switch (alarm) { + case 1: + position.set(Position.KEY_ALARM, Position.ALARM_SOS); + break; + case 2: + position.set(Position.KEY_ALARM, Position.ALARM_OVERSPEED); + break; + case 3: + position.set(Position.KEY_ALARM, Position.ALARM_GEOFENCE_EXIT); + break; + case 9: + position.set(Position.KEY_ALARM, Position.ALARM_POWER_OFF); + break; + default: + break; + } if (newFormat) { position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedInt())); diff --git a/src/org/traccar/protocol/ObdDongleProtocol.java b/src/org/traccar/protocol/ObdDongleProtocol.java new file mode 100644 index 000000000..e87f9a99a --- /dev/null +++ b/src/org/traccar/protocol/ObdDongleProtocol.java @@ -0,0 +1,43 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.protocol; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; +import org.traccar.BaseProtocol; +import org.traccar.TrackerServer; + +import java.util.List; + +public class ObdDongleProtocol extends BaseProtocol { + + public ObdDongleProtocol() { + super("obddongle"); + } + + @Override + public void initTrackerServers(List<TrackerServer> serverList) { + serverList.add(new TrackerServer(new ServerBootstrap(), this.getName()) { + @Override + protected void addSpecificHandlers(ChannelPipeline pipeline) { + pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1099, 20, 2, 3, 0)); + pipeline.addLast("objectDecoder", new ObdDongleProtocolDecoder(ObdDongleProtocol.this)); + } + }); + } + +} diff --git a/src/org/traccar/protocol/ObdDongleProtocolDecoder.java b/src/org/traccar/protocol/ObdDongleProtocolDecoder.java new file mode 100644 index 000000000..84ff1450a --- /dev/null +++ b/src/org/traccar/protocol/ObdDongleProtocolDecoder.java @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.DeviceSession; +import org.traccar.helper.BitUtil; +import org.traccar.helper.UnitsConverter; +import org.traccar.model.Position; + +import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Date; + +public class ObdDongleProtocolDecoder extends BaseProtocolDecoder { + + public ObdDongleProtocolDecoder(ObdDongleProtocol protocol) { + super(protocol); + } + + public static final int MSG_TYPE_CONNECT = 0x01; + public static final int MSG_TYPE_CONNACK = 0x02; + public static final int MSG_TYPE_PUBLISH = 0x03; + public static final int MSG_TYPE_PUBACK = 0x04; + public static final int MSG_TYPE_PINGREQ = 0x0C; + public static final int MSG_TYPE_PINGRESP = 0x0D; + public static final int MSG_TYPE_DISCONNECT = 0x0E; + + private static void sendResponse(Channel channel, int type, int index, String imei, ChannelBuffer content) { + if (channel != null) { + ChannelBuffer response = ChannelBuffers.dynamicBuffer(); + response.writeShort(0x5555); // header + response.writeShort(index); + response.writeBytes(imei.getBytes(StandardCharsets.US_ASCII)); + response.writeByte(type); + response.writeShort(content.readableBytes()); + response.writeBytes(content); + response.writeByte(0); // checksum + response.writeShort(0xAAAA); + channel.write(response); + } + } + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ChannelBuffer buf = (ChannelBuffer) msg; + + buf.skipBytes(2); // header + int index = buf.readUnsignedShort(); + + String imei = buf.readBytes(15).toString(StandardCharsets.US_ASCII); + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, imei); + if (deviceSession == null) { + return null; + } + + int type = buf.readUnsignedByte(); + + buf.readUnsignedShort(); // data length + + if (type == MSG_TYPE_CONNECT) { + + ChannelBuffer response = ChannelBuffers.dynamicBuffer(); + response.writeByte(1); + response.writeShort(0); + response.writeInt(0); + sendResponse(channel, MSG_TYPE_CONNACK, index, imei, response); + + } else if (type == MSG_TYPE_PUBLISH) { + + int typeMajor = buf.readUnsignedByte(); + int typeMinor = buf.readUnsignedByte(); + + buf.readUnsignedByte(); // event id + + Position position = new Position(); + position.setProtocol(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + position.setTime(new Date(buf.readUnsignedInt() * 1000)); + + int flags = buf.readUnsignedByte(); + + position.setValid(!BitUtil.check(flags, 6)); + + position.set(Position.KEY_SATELLITES, BitUtil.to(flags, 4)); + + double longitude = ((BitUtil.to(buf.readUnsignedShort(), 1) << 24) + buf.readUnsignedMedium()) * 0.00001; + position.setLongitude(BitUtil.check(flags, 5) ? longitude : -longitude); + + double latitude = buf.readUnsignedMedium() * 0.00001; + position.setLatitude(BitUtil.check(flags, 4) ? latitude : -latitude); + + int speedCourse = buf.readUnsignedMedium(); + position.setSpeed(UnitsConverter.knotsFromMph(BitUtil.from(speedCourse, 10) * 0.1)); + position.setCourse(BitUtil.to(speedCourse, 10)); + + ChannelBuffer response = ChannelBuffers.dynamicBuffer(); + response.writeByte(typeMajor); + response.writeByte(typeMinor); + sendResponse(channel, MSG_TYPE_PUBACK, index, imei, response); + + return position; + + } + + return null; + } + +} diff --git a/src/org/traccar/protocol/ProgressProtocolDecoder.java b/src/org/traccar/protocol/ProgressProtocolDecoder.java index e524626fa..0032a9a1b 100644 --- a/src/org/traccar/protocol/ProgressProtocolDecoder.java +++ b/src/org/traccar/protocol/ProgressProtocolDecoder.java @@ -104,7 +104,7 @@ public class ProgressProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_ARCHIVE, true); int subtype = buf.readUnsignedShort(); if (subtype == MSG_ALARM) { - position.set(Position.KEY_ALARM, true); + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); } if (buf.readUnsignedShort() > buf.readableBytes()) { lastIndex += 1; diff --git a/src/org/traccar/protocol/SuntechProtocolDecoder.java b/src/org/traccar/protocol/SuntechProtocolDecoder.java index 5169e7c67..503f4d6f8 100644 --- a/src/org/traccar/protocol/SuntechProtocolDecoder.java +++ b/src/org/traccar/protocol/SuntechProtocolDecoder.java @@ -68,7 +68,7 @@ public class SuntechProtocolDecoder extends BaseProtocolDecoder { if (parser.hasNext()) { String type = parser.next(); if (type.equals("Alert") || type.equals("Emergency")) { - position.set(Position.KEY_ALARM, true); + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); } } diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java index d982b07b3..00ab90ce0 100644 --- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java +++ b/src/org/traccar/protocol/TeltonikaProtocolDecoder.java @@ -67,6 +67,32 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { } + private void decodeParameter(Position position, int id, long value) { + switch (id) { + case 9: + position.set(Position.PREFIX_ADC + 1, value); + break; + case 66: + position.set(Position.KEY_POWER, value); + break; + case 68: + position.set(Position.KEY_BATTERY, value); + break; + case 85: + position.set(Position.KEY_RPM, value); + break; + case 182: + position.set(Position.KEY_HDOP, value); + break; + case 239: + position.set(Position.KEY_IGNITION, value == 1); + break; + default: + position.set(Position.PREFIX_IO + id, value); + break; + } + } + private void decodeLocation(Position position, ChannelBuffer buf, int codec) { int globalMask = 0x0f; @@ -153,12 +179,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { if (BitUtil.check(globalMask, 1)) { int cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { - int id = buf.readUnsignedByte(); - if (id == 1) { - position.set(Position.KEY_POWER, buf.readUnsignedByte()); - } else { - position.set(Position.PREFIX_IO + id, buf.readUnsignedByte()); - } + decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedByte()); } } @@ -166,7 +187,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { if (BitUtil.check(globalMask, 2)) { int cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { - position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedShort()); + decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedShort()); } } @@ -174,7 +195,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { if (BitUtil.check(globalMask, 3)) { int cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { - position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readUnsignedInt()); + decodeParameter(position, buf.readUnsignedByte(), buf.readUnsignedInt()); } } @@ -182,7 +203,7 @@ public class TeltonikaProtocolDecoder extends BaseProtocolDecoder { if (codec == CODEC_FM4X00) { int cnt = buf.readUnsignedByte(); for (int j = 0; j < cnt; j++) { - position.set(Position.PREFIX_IO + buf.readUnsignedByte(), buf.readLong()); + decodeParameter(position, buf.readUnsignedByte(), buf.readLong()); } } diff --git a/src/org/traccar/protocol/Tk103ProtocolDecoder.java b/src/org/traccar/protocol/Tk103ProtocolDecoder.java index a76c208b5..ac99a1440 100644 --- a/src/org/traccar/protocol/Tk103ProtocolDecoder.java +++ b/src/org/traccar/protocol/Tk103ProtocolDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2015 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2012 - 2016 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,6 +51,7 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder { .number("(?:([01]{8})|(x{8}))?,?") // state .number("(?:L(x+))?") // odometer .any() + .number("([+-]ddd.d)?") // temperature .text(")").optional() .compile(); @@ -75,6 +76,25 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder { .any() .compile(); + private String decodeAlarm(int value) { + switch (value) { + case 1: + return Position.ALARM_ACCIDENT; + case 2: + return Position.ALARM_SOS; + case 3: + return Position.ALARM_VIBRATION; + case 4: + return Position.ALARM_LOW_SPEED; + case 5: + return Position.ALARM_OVERSPEED; + case 6: + return Position.ALARM_GEOFENCE_EXIT; + default: + return null; + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -160,7 +180,7 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder { int alarm = sentence.indexOf("BO01"); if (alarm != -1) { - position.set(Position.KEY_ALARM, Integer.parseInt(sentence.substring(alarm + 4, alarm + 5))); + position.set(Position.KEY_ALARM, decodeAlarm(Integer.parseInt(sentence.substring(alarm + 4, alarm + 5)))); } DateBuilder dateBuilder = new DateBuilder(); @@ -206,6 +226,10 @@ public class Tk103ProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_ODOMETER, parser.nextLong(16)); } + if (parser.hasNext()) { + position.set(Position.PREFIX_TEMP + 1, parser.nextDouble()); + } + return position; } diff --git a/src/org/traccar/protocol/TotemProtocolDecoder.java b/src/org/traccar/protocol/TotemProtocolDecoder.java index 7b196f5ad..72c0f6306 100644 --- a/src/org/traccar/protocol/TotemProtocolDecoder.java +++ b/src/org/traccar/protocol/TotemProtocolDecoder.java @@ -159,6 +159,23 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { .any() .compile(); + private String decodeAlarm(Short value) { + switch (value) { + case 0x01: + return Position.ALARM_SOS; + case 0x10: + return Position.ALARM_LOW_BATTERY; + case 0x11: + return Position.ALARM_OVERSPEED; + case 0x42: + return Position.ALARM_GEOFENCE_EXIT; + case 0x43: + return Position.ALARM_GEOFENCE_ENTER; + default: + return null; + } + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -193,9 +210,9 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(deviceSession.getDeviceId()); if (pattern == PATTERN1 || pattern == PATTERN2) { - - position.set(Position.KEY_ALARM, parser.next()); - + if (parser.hasNext()) { + position.set(Position.KEY_ALARM, decodeAlarm(Short.parseShort(parser.next(), 16))); + } DateBuilder dateBuilder = new DateBuilder(); int year = 0; if (pattern == PATTERN2) { @@ -238,9 +255,9 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_ODOMETER, parser.next()); } else if (pattern == PATTERN3) { - - position.set(Position.KEY_ALARM, parser.next()); - + if (parser.hasNext()) { + position.set(Position.KEY_ALARM, decodeAlarm(Short.parseShort(parser.next(), 16))); + } DateBuilder dateBuilder = new DateBuilder() .setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()) .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); @@ -304,11 +321,9 @@ public class TotemProtocolDecoder extends BaseProtocolDecoder { position.setLongitude(parser.nextCoordinate()); } - if (channel != null) { channel.write("ACK OK\r\n"); } - return position; } diff --git a/src/org/traccar/protocol/UlbotechProtocolDecoder.java b/src/org/traccar/protocol/UlbotechProtocolDecoder.java index c17341b5f..36fb23f9a 100644 --- a/src/org/traccar/protocol/UlbotechProtocolDecoder.java +++ b/src/org/traccar/protocol/UlbotechProtocolDecoder.java @@ -115,6 +115,25 @@ public class UlbotechProtocolDecoder extends BaseProtocolDecoder { } } + private String decodeAlarm(int alarm) { + if (BitUtil.check(alarm, 0)) { + return Position.ALARM_POWER_OFF; + } + if (BitUtil.check(alarm, 1)) { + return Position.ALARM_MOTION; + } + if (BitUtil.check(alarm, 2)) { + return Position.ALARM_OVERSPEED; + } + if (BitUtil.check(alarm, 4)) { + return Position.ALARM_GEOFENCE; + } + if (BitUtil.check(alarm, 10)) { + return Position.ALARM_SOS; + } + return null; + } + @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { @@ -181,7 +200,7 @@ public class UlbotechProtocolDecoder extends BaseProtocolDecoder { int status = buf.readUnsignedShort(); position.set(Position.KEY_IGNITION, BitUtil.check(status, 9)); position.set(Position.KEY_STATUS, status); - position.set(Position.KEY_ALARM, buf.readUnsignedShort()); + position.set(Position.KEY_ALARM, decodeAlarm(buf.readUnsignedShort())); break; case DATA_ODOMETER: |