aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/traccar/BaseDataHandler.java (renamed from src/org/traccar/BaseDataHandler.java)0
-rw-r--r--src/main/java/org/traccar/BaseFrameDecoder.java (renamed from src/org/traccar/BaseFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/BaseHttpProtocolDecoder.java (renamed from src/org/traccar/BaseHttpProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/BasePipelineFactory.java (renamed from src/org/traccar/BasePipelineFactory.java)0
-rw-r--r--src/main/java/org/traccar/BaseProtocol.java (renamed from src/org/traccar/BaseProtocol.java)0
-rw-r--r--src/main/java/org/traccar/BaseProtocolDecoder.java (renamed from src/org/traccar/BaseProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/BaseProtocolEncoder.java (renamed from src/org/traccar/BaseProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/CharacterDelimiterFrameDecoder.java (renamed from src/org/traccar/CharacterDelimiterFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/Context.java (renamed from src/org/traccar/Context.java)0
-rw-r--r--src/main/java/org/traccar/DeviceSession.java (renamed from src/org/traccar/DeviceSession.java)0
-rw-r--r--src/main/java/org/traccar/EventLoopGroupFactory.java (renamed from src/org/traccar/EventLoopGroupFactory.java)0
-rw-r--r--src/main/java/org/traccar/ExtendedObjectDecoder.java (renamed from src/org/traccar/ExtendedObjectDecoder.java)0
-rw-r--r--src/main/java/org/traccar/GlobalTimer.java (renamed from src/org/traccar/GlobalTimer.java)0
-rw-r--r--src/main/java/org/traccar/Main.java (renamed from src/org/traccar/Main.java)0
-rw-r--r--src/main/java/org/traccar/MainEventHandler.java (renamed from src/org/traccar/MainEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/MainModule.java (renamed from src/org/traccar/MainModule.java)0
-rw-r--r--src/main/java/org/traccar/NetworkMessage.java (renamed from src/org/traccar/NetworkMessage.java)0
-rw-r--r--src/main/java/org/traccar/PipelineBuilder.java (renamed from src/org/traccar/PipelineBuilder.java)0
-rw-r--r--src/main/java/org/traccar/Protocol.java (renamed from src/org/traccar/Protocol.java)0
-rw-r--r--src/main/java/org/traccar/ServerManager.java (renamed from src/org/traccar/ServerManager.java)0
-rw-r--r--src/main/java/org/traccar/StringProtocolEncoder.java (renamed from src/org/traccar/StringProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/TrackerServer.java (renamed from src/org/traccar/TrackerServer.java)0
-rw-r--r--src/main/java/org/traccar/WebDataHandler.java (renamed from src/org/traccar/WebDataHandler.java)0
-rw-r--r--src/main/java/org/traccar/WindowsService.java (renamed from src/org/traccar/WindowsService.java)0
-rw-r--r--src/main/java/org/traccar/WrapperContext.java (renamed from src/org/traccar/WrapperContext.java)0
-rw-r--r--src/main/java/org/traccar/WrapperInboundHandler.java (renamed from src/org/traccar/WrapperInboundHandler.java)0
-rw-r--r--src/main/java/org/traccar/WrapperOutboundHandler.java (renamed from src/org/traccar/WrapperOutboundHandler.java)0
-rw-r--r--src/main/java/org/traccar/api/AsyncSocket.java (renamed from src/org/traccar/api/AsyncSocket.java)0
-rw-r--r--src/main/java/org/traccar/api/AsyncSocketServlet.java (renamed from src/org/traccar/api/AsyncSocketServlet.java)0
-rw-r--r--src/main/java/org/traccar/api/BaseObjectResource.java (renamed from src/org/traccar/api/BaseObjectResource.java)0
-rw-r--r--src/main/java/org/traccar/api/BaseResource.java (renamed from src/org/traccar/api/BaseResource.java)0
-rw-r--r--src/main/java/org/traccar/api/CorsResponseFilter.java (renamed from src/org/traccar/api/CorsResponseFilter.java)0
-rw-r--r--src/main/java/org/traccar/api/ExtendedObjectResource.java (renamed from src/org/traccar/api/ExtendedObjectResource.java)0
-rw-r--r--src/main/java/org/traccar/api/MediaFilter.java (renamed from src/org/traccar/api/MediaFilter.java)0
-rw-r--r--src/main/java/org/traccar/api/ObjectMapperProvider.java (renamed from src/org/traccar/api/ObjectMapperProvider.java)0
-rw-r--r--src/main/java/org/traccar/api/ResourceErrorHandler.java (renamed from src/org/traccar/api/ResourceErrorHandler.java)0
-rw-r--r--src/main/java/org/traccar/api/SecurityRequestFilter.java (renamed from src/org/traccar/api/SecurityRequestFilter.java)0
-rw-r--r--src/main/java/org/traccar/api/SimpleObjectResource.java (renamed from src/org/traccar/api/SimpleObjectResource.java)0
-rw-r--r--src/main/java/org/traccar/api/UserPrincipal.java (renamed from src/org/traccar/api/UserPrincipal.java)0
-rw-r--r--src/main/java/org/traccar/api/UserSecurityContext.java (renamed from src/org/traccar/api/UserSecurityContext.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/AttributeResource.java (renamed from src/org/traccar/api/resource/AttributeResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/CalendarResource.java (renamed from src/org/traccar/api/resource/CalendarResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/CommandResource.java (renamed from src/org/traccar/api/resource/CommandResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/DeviceResource.java (renamed from src/org/traccar/api/resource/DeviceResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/DriverResource.java (renamed from src/org/traccar/api/resource/DriverResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/EventResource.java (renamed from src/org/traccar/api/resource/EventResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/GeofenceResource.java (renamed from src/org/traccar/api/resource/GeofenceResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/GroupResource.java (renamed from src/org/traccar/api/resource/GroupResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/MaintenanceResource.java (renamed from src/org/traccar/api/resource/MaintenanceResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/NotificationResource.java (renamed from src/org/traccar/api/resource/NotificationResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/PermissionsResource.java (renamed from src/org/traccar/api/resource/PermissionsResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/PositionResource.java (renamed from src/org/traccar/api/resource/PositionResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/ReportResource.java (renamed from src/org/traccar/api/resource/ReportResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/ServerResource.java (renamed from src/org/traccar/api/resource/ServerResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/SessionResource.java (renamed from src/org/traccar/api/resource/SessionResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/StatisticsResource.java (renamed from src/org/traccar/api/resource/StatisticsResource.java)0
-rw-r--r--src/main/java/org/traccar/api/resource/UserResource.java (renamed from src/org/traccar/api/resource/UserResource.java)0
-rw-r--r--src/main/java/org/traccar/config/Config.java (renamed from src/org/traccar/config/Config.java)0
-rw-r--r--src/main/java/org/traccar/config/ConfigKey.java (renamed from src/org/traccar/config/ConfigKey.java)0
-rw-r--r--src/main/java/org/traccar/config/ConfigSuffix.java (renamed from src/org/traccar/config/ConfigSuffix.java)0
-rw-r--r--src/main/java/org/traccar/config/Keys.java (renamed from src/org/traccar/config/Keys.java)0
-rw-r--r--src/main/java/org/traccar/database/ActiveDevice.java (renamed from src/org/traccar/database/ActiveDevice.java)0
-rw-r--r--src/main/java/org/traccar/database/AttributesManager.java (renamed from src/org/traccar/database/AttributesManager.java)0
-rw-r--r--src/main/java/org/traccar/database/BaseObjectManager.java (renamed from src/org/traccar/database/BaseObjectManager.java)0
-rw-r--r--src/main/java/org/traccar/database/CalendarManager.java (renamed from src/org/traccar/database/CalendarManager.java)0
-rw-r--r--src/main/java/org/traccar/database/CommandsManager.java (renamed from src/org/traccar/database/CommandsManager.java)0
-rw-r--r--src/main/java/org/traccar/database/ConnectionManager.java (renamed from src/org/traccar/database/ConnectionManager.java)0
-rw-r--r--src/main/java/org/traccar/database/DataManager.java (renamed from src/org/traccar/database/DataManager.java)0
-rw-r--r--src/main/java/org/traccar/database/DeviceManager.java (renamed from src/org/traccar/database/DeviceManager.java)0
-rw-r--r--src/main/java/org/traccar/database/DriversManager.java (renamed from src/org/traccar/database/DriversManager.java)0
-rw-r--r--src/main/java/org/traccar/database/ExtendedObjectManager.java (renamed from src/org/traccar/database/ExtendedObjectManager.java)0
-rw-r--r--src/main/java/org/traccar/database/GeofenceManager.java (renamed from src/org/traccar/database/GeofenceManager.java)0
-rw-r--r--src/main/java/org/traccar/database/GroupTree.java (renamed from src/org/traccar/database/GroupTree.java)0
-rw-r--r--src/main/java/org/traccar/database/GroupsManager.java (renamed from src/org/traccar/database/GroupsManager.java)0
-rw-r--r--src/main/java/org/traccar/database/IdentityManager.java (renamed from src/org/traccar/database/IdentityManager.java)0
-rw-r--r--src/main/java/org/traccar/database/LdapProvider.java (renamed from src/org/traccar/database/LdapProvider.java)0
-rw-r--r--src/main/java/org/traccar/database/MailManager.java (renamed from src/org/traccar/database/MailManager.java)0
-rw-r--r--src/main/java/org/traccar/database/MaintenancesManager.java (renamed from src/org/traccar/database/MaintenancesManager.java)0
-rw-r--r--src/main/java/org/traccar/database/ManagableObjects.java (renamed from src/org/traccar/database/ManagableObjects.java)0
-rw-r--r--src/main/java/org/traccar/database/MediaManager.java (renamed from src/org/traccar/database/MediaManager.java)0
-rw-r--r--src/main/java/org/traccar/database/NotificationManager.java (renamed from src/org/traccar/database/NotificationManager.java)0
-rw-r--r--src/main/java/org/traccar/database/PermissionsManager.java (renamed from src/org/traccar/database/PermissionsManager.java)0
-rw-r--r--src/main/java/org/traccar/database/QueryBuilder.java (renamed from src/org/traccar/database/QueryBuilder.java)0
-rw-r--r--src/main/java/org/traccar/database/QueryExtended.java (renamed from src/org/traccar/database/QueryExtended.java)0
-rw-r--r--src/main/java/org/traccar/database/QueryIgnore.java (renamed from src/org/traccar/database/QueryIgnore.java)0
-rw-r--r--src/main/java/org/traccar/database/SimpleObjectManager.java (renamed from src/org/traccar/database/SimpleObjectManager.java)0
-rw-r--r--src/main/java/org/traccar/database/StatisticsManager.java (renamed from src/org/traccar/database/StatisticsManager.java)0
-rw-r--r--src/main/java/org/traccar/database/UsersManager.java (renamed from src/org/traccar/database/UsersManager.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/Address.java (renamed from src/org/traccar/geocoder/Address.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/AddressFormat.java (renamed from src/org/traccar/geocoder/AddressFormat.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/BanGeocoder.java (renamed from src/org/traccar/geocoder/BanGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/BingMapsGeocoder.java (renamed from src/org/traccar/geocoder/BingMapsGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/FactualGeocoder.java (renamed from src/org/traccar/geocoder/FactualGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/GeocodeFarmGeocoder.java (renamed from src/org/traccar/geocoder/GeocodeFarmGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/GeocodeXyzGeocoder.java (renamed from src/org/traccar/geocoder/GeocodeXyzGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/Geocoder.java (renamed from src/org/traccar/geocoder/Geocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/GeocoderException.java (renamed from src/org/traccar/geocoder/GeocoderException.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/GisgraphyGeocoder.java (renamed from src/org/traccar/geocoder/GisgraphyGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/GoogleGeocoder.java (renamed from src/org/traccar/geocoder/GoogleGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/HereGeocoder.java (renamed from src/org/traccar/geocoder/HereGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/JsonGeocoder.java (renamed from src/org/traccar/geocoder/JsonGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/MapQuestGeocoder.java (renamed from src/org/traccar/geocoder/MapQuestGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/MapmyIndiaGeocoder.java (renamed from src/org/traccar/geocoder/MapmyIndiaGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/NominatimGeocoder.java (renamed from src/org/traccar/geocoder/NominatimGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geocoder/OpenCageGeocoder.java (renamed from src/org/traccar/geocoder/OpenCageGeocoder.java)0
-rw-r--r--src/main/java/org/traccar/geofence/GeofenceCircle.java (renamed from src/org/traccar/geofence/GeofenceCircle.java)0
-rw-r--r--src/main/java/org/traccar/geofence/GeofenceGeometry.java (renamed from src/org/traccar/geofence/GeofenceGeometry.java)0
-rw-r--r--src/main/java/org/traccar/geofence/GeofencePolygon.java (renamed from src/org/traccar/geofence/GeofencePolygon.java)0
-rw-r--r--src/main/java/org/traccar/geofence/GeofencePolyline.java (renamed from src/org/traccar/geofence/GeofencePolyline.java)0
-rw-r--r--src/main/java/org/traccar/geolocation/GeolocationException.java (renamed from src/org/traccar/geolocation/GeolocationException.java)0
-rw-r--r--src/main/java/org/traccar/geolocation/GeolocationProvider.java (renamed from src/org/traccar/geolocation/GeolocationProvider.java)0
-rw-r--r--src/main/java/org/traccar/geolocation/GoogleGeolocationProvider.java (renamed from src/org/traccar/geolocation/GoogleGeolocationProvider.java)0
-rw-r--r--src/main/java/org/traccar/geolocation/MozillaGeolocationProvider.java (renamed from src/org/traccar/geolocation/MozillaGeolocationProvider.java)0
-rw-r--r--src/main/java/org/traccar/geolocation/OpenCellIdGeolocationProvider.java (renamed from src/org/traccar/geolocation/OpenCellIdGeolocationProvider.java)0
-rw-r--r--src/main/java/org/traccar/geolocation/UniversalGeolocationProvider.java (renamed from src/org/traccar/geolocation/UniversalGeolocationProvider.java)0
-rw-r--r--src/main/java/org/traccar/geolocation/UnwiredGeolocationProvider.java (renamed from src/org/traccar/geolocation/UnwiredGeolocationProvider.java)0
-rw-r--r--src/main/java/org/traccar/handler/ComputedAttributesHandler.java (renamed from src/org/traccar/handler/ComputedAttributesHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/CopyAttributesHandler.java (renamed from src/org/traccar/handler/CopyAttributesHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/DefaultDataHandler.java (renamed from src/org/traccar/handler/DefaultDataHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/DistanceHandler.java (renamed from src/org/traccar/handler/DistanceHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/EngineHoursHandler.java (renamed from src/org/traccar/handler/EngineHoursHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/FilterHandler.java (renamed from src/org/traccar/handler/FilterHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/GeocoderHandler.java (renamed from src/org/traccar/handler/GeocoderHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/GeolocationHandler.java (renamed from src/org/traccar/handler/GeolocationHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/HemisphereHandler.java (renamed from src/org/traccar/handler/HemisphereHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/MotionHandler.java (renamed from src/org/traccar/handler/MotionHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/NetworkMessageHandler.java (renamed from src/org/traccar/handler/NetworkMessageHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/OpenChannelHandler.java (renamed from src/org/traccar/handler/OpenChannelHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/RemoteAddressHandler.java (renamed from src/org/traccar/handler/RemoteAddressHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/StandardLoggingHandler.java (renamed from src/org/traccar/handler/StandardLoggingHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/AlertEventHandler.java (renamed from src/org/traccar/handler/events/AlertEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/BaseEventHandler.java (renamed from src/org/traccar/handler/events/BaseEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/CommandResultEventHandler.java (renamed from src/org/traccar/handler/events/CommandResultEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/DriverEventHandler.java (renamed from src/org/traccar/handler/events/DriverEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/FuelDropEventHandler.java (renamed from src/org/traccar/handler/events/FuelDropEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/GeofenceEventHandler.java (renamed from src/org/traccar/handler/events/GeofenceEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/IgnitionEventHandler.java (renamed from src/org/traccar/handler/events/IgnitionEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java (renamed from src/org/traccar/handler/events/MaintenanceEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/MotionEventHandler.java (renamed from src/org/traccar/handler/events/MotionEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/handler/events/OverspeedEventHandler.java (renamed from src/org/traccar/handler/events/OverspeedEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/helper/BcdUtil.java (renamed from src/org/traccar/helper/BcdUtil.java)0
-rw-r--r--src/main/java/org/traccar/helper/BitBuffer.java (renamed from src/org/traccar/helper/BitBuffer.java)0
-rw-r--r--src/main/java/org/traccar/helper/BitUtil.java (renamed from src/org/traccar/helper/BitUtil.java)0
-rw-r--r--src/main/java/org/traccar/helper/BufferUtil.java (renamed from src/org/traccar/helper/BufferUtil.java)0
-rw-r--r--src/main/java/org/traccar/helper/Checksum.java (renamed from src/org/traccar/helper/Checksum.java)0
-rw-r--r--src/main/java/org/traccar/helper/DataConverter.java (renamed from src/org/traccar/helper/DataConverter.java)0
-rw-r--r--src/main/java/org/traccar/helper/DateBuilder.java (renamed from src/org/traccar/helper/DateBuilder.java)0
-rw-r--r--src/main/java/org/traccar/helper/DateUtil.java (renamed from src/org/traccar/helper/DateUtil.java)0
-rw-r--r--src/main/java/org/traccar/helper/DistanceCalculator.java (renamed from src/org/traccar/helper/DistanceCalculator.java)0
-rw-r--r--src/main/java/org/traccar/helper/Hashing.java (renamed from src/org/traccar/helper/Hashing.java)0
-rw-r--r--src/main/java/org/traccar/helper/LocationTree.java (renamed from src/org/traccar/helper/LocationTree.java)0
-rw-r--r--src/main/java/org/traccar/helper/Log.java (renamed from src/org/traccar/helper/Log.java)0
-rw-r--r--src/main/java/org/traccar/helper/LogAction.java (renamed from src/org/traccar/helper/LogAction.java)0
-rw-r--r--src/main/java/org/traccar/helper/ObdDecoder.java (renamed from src/org/traccar/helper/ObdDecoder.java)0
-rw-r--r--src/main/java/org/traccar/helper/Parser.java (renamed from src/org/traccar/helper/Parser.java)0
-rw-r--r--src/main/java/org/traccar/helper/PatternBuilder.java (renamed from src/org/traccar/helper/PatternBuilder.java)0
-rw-r--r--src/main/java/org/traccar/helper/PatternUtil.java (renamed from src/org/traccar/helper/PatternUtil.java)0
-rw-r--r--src/main/java/org/traccar/helper/SanitizerModule.java (renamed from src/org/traccar/helper/SanitizerModule.java)0
-rw-r--r--src/main/java/org/traccar/helper/UnitsConverter.java (renamed from src/org/traccar/helper/UnitsConverter.java)0
-rw-r--r--src/main/java/org/traccar/model/Attribute.java (renamed from src/org/traccar/model/Attribute.java)0
-rw-r--r--src/main/java/org/traccar/model/BaseModel.java (renamed from src/org/traccar/model/BaseModel.java)0
-rw-r--r--src/main/java/org/traccar/model/Calendar.java (renamed from src/org/traccar/model/Calendar.java)0
-rw-r--r--src/main/java/org/traccar/model/CellTower.java (renamed from src/org/traccar/model/CellTower.java)0
-rw-r--r--src/main/java/org/traccar/model/Command.java (renamed from src/org/traccar/model/Command.java)0
-rw-r--r--src/main/java/org/traccar/model/Device.java (renamed from src/org/traccar/model/Device.java)0
-rw-r--r--src/main/java/org/traccar/model/DeviceAccumulators.java (renamed from src/org/traccar/model/DeviceAccumulators.java)0
-rw-r--r--src/main/java/org/traccar/model/DeviceState.java (renamed from src/org/traccar/model/DeviceState.java)0
-rw-r--r--src/main/java/org/traccar/model/Driver.java (renamed from src/org/traccar/model/Driver.java)0
-rw-r--r--src/main/java/org/traccar/model/Event.java (renamed from src/org/traccar/model/Event.java)0
-rw-r--r--src/main/java/org/traccar/model/ExtendedModel.java (renamed from src/org/traccar/model/ExtendedModel.java)0
-rw-r--r--src/main/java/org/traccar/model/Geofence.java (renamed from src/org/traccar/model/Geofence.java)0
-rw-r--r--src/main/java/org/traccar/model/Group.java (renamed from src/org/traccar/model/Group.java)0
-rw-r--r--src/main/java/org/traccar/model/GroupedModel.java (renamed from src/org/traccar/model/GroupedModel.java)0
-rw-r--r--src/main/java/org/traccar/model/Maintenance.java (renamed from src/org/traccar/model/Maintenance.java)0
-rw-r--r--src/main/java/org/traccar/model/ManagedUser.java (renamed from src/org/traccar/model/ManagedUser.java)0
-rw-r--r--src/main/java/org/traccar/model/Message.java (renamed from src/org/traccar/model/Message.java)0
-rw-r--r--src/main/java/org/traccar/model/MiscFormatter.java (renamed from src/org/traccar/model/MiscFormatter.java)0
-rw-r--r--src/main/java/org/traccar/model/Network.java (renamed from src/org/traccar/model/Network.java)0
-rw-r--r--src/main/java/org/traccar/model/Notification.java (renamed from src/org/traccar/model/Notification.java)0
-rw-r--r--src/main/java/org/traccar/model/Permission.java (renamed from src/org/traccar/model/Permission.java)0
-rw-r--r--src/main/java/org/traccar/model/Position.java (renamed from src/org/traccar/model/Position.java)0
-rw-r--r--src/main/java/org/traccar/model/ScheduledModel.java (renamed from src/org/traccar/model/ScheduledModel.java)0
-rw-r--r--src/main/java/org/traccar/model/Server.java (renamed from src/org/traccar/model/Server.java)0
-rw-r--r--src/main/java/org/traccar/model/Statistics.java (renamed from src/org/traccar/model/Statistics.java)0
-rw-r--r--src/main/java/org/traccar/model/Typed.java (renamed from src/org/traccar/model/Typed.java)0
-rw-r--r--src/main/java/org/traccar/model/User.java (renamed from src/org/traccar/model/User.java)0
-rw-r--r--src/main/java/org/traccar/model/WifiAccessPoint.java (renamed from src/org/traccar/model/WifiAccessPoint.java)0
-rw-r--r--src/main/java/org/traccar/notification/EventForwarder.java (renamed from src/org/traccar/notification/EventForwarder.java)0
-rw-r--r--src/main/java/org/traccar/notification/FullMessage.java (renamed from src/org/traccar/notification/FullMessage.java)0
-rw-r--r--src/main/java/org/traccar/notification/JsonTypeEventForwarder.java (renamed from src/org/traccar/notification/JsonTypeEventForwarder.java)36
-rw-r--r--src/main/java/org/traccar/notification/MessageException.java (renamed from src/org/traccar/notification/MessageException.java)0
-rw-r--r--src/main/java/org/traccar/notification/NotificationFormatter.java (renamed from src/org/traccar/notification/NotificationFormatter.java)0
-rw-r--r--src/main/java/org/traccar/notification/NotificatorManager.java (renamed from src/org/traccar/notification/NotificatorManager.java)0
-rw-r--r--src/main/java/org/traccar/notification/PropertiesProvider.java (renamed from src/org/traccar/notification/PropertiesProvider.java)0
-rw-r--r--src/main/java/org/traccar/notificators/Notificator.java (renamed from src/org/traccar/notificators/Notificator.java)0
-rw-r--r--src/main/java/org/traccar/notificators/NotificatorFirebase.java (renamed from src/org/traccar/notificators/NotificatorFirebase.java)0
-rw-r--r--src/main/java/org/traccar/notificators/NotificatorMail.java (renamed from src/org/traccar/notificators/NotificatorMail.java)0
-rw-r--r--src/main/java/org/traccar/notificators/NotificatorNull.java (renamed from src/org/traccar/notificators/NotificatorNull.java)0
-rw-r--r--src/main/java/org/traccar/notificators/NotificatorSms.java (renamed from src/org/traccar/notificators/NotificatorSms.java)0
-rw-r--r--src/main/java/org/traccar/notificators/NotificatorWeb.java (renamed from src/org/traccar/notificators/NotificatorWeb.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AdmProtocol.java (renamed from src/org/traccar/protocol/AdmProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AdmProtocolDecoder.java (renamed from src/org/traccar/protocol/AdmProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AdmProtocolEncoder.java (renamed from src/org/traccar/protocol/AdmProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AisProtocol.java (renamed from src/org/traccar/protocol/AisProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AisProtocolDecoder.java (renamed from src/org/traccar/protocol/AisProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AlematicsFrameDecoder.java (renamed from src/org/traccar/protocol/AlematicsFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AlematicsProtocol.java (renamed from src/org/traccar/protocol/AlematicsProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AlematicsProtocolDecoder.java (renamed from src/org/traccar/protocol/AlematicsProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AnytrekProtocol.java (renamed from src/org/traccar/protocol/AnytrekProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AnytrekProtocolDecoder.java (renamed from src/org/traccar/protocol/AnytrekProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ApelProtocol.java (renamed from src/org/traccar/protocol/ApelProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ApelProtocolDecoder.java (renamed from src/org/traccar/protocol/ApelProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AplicomFrameDecoder.java (renamed from src/org/traccar/protocol/AplicomFrameDecoder.java)124
-rw-r--r--src/main/java/org/traccar/protocol/AplicomProtocol.java (renamed from src/org/traccar/protocol/AplicomProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AplicomProtocolDecoder.java (renamed from src/org/traccar/protocol/AplicomProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AppelloProtocol.java (renamed from src/org/traccar/protocol/AppelloProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AppelloProtocolDecoder.java (renamed from src/org/traccar/protocol/AppelloProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AppletProtocol.java (renamed from src/org/traccar/protocol/AppletProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AppletProtocolDecoder.java (renamed from src/org/traccar/protocol/AppletProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AquilaProtocol.java (renamed from src/org/traccar/protocol/AquilaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AquilaProtocolDecoder.java (renamed from src/org/traccar/protocol/AquilaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Ardi01Protocol.java (renamed from src/org/traccar/protocol/Ardi01Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Ardi01ProtocolDecoder.java (renamed from src/org/traccar/protocol/Ardi01ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ArknavProtocol.java (renamed from src/org/traccar/protocol/ArknavProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ArknavProtocolDecoder.java (renamed from src/org/traccar/protocol/ArknavProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ArknavX8Protocol.java (renamed from src/org/traccar/protocol/ArknavX8Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ArknavX8ProtocolDecoder.java (renamed from src/org/traccar/protocol/ArknavX8ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ArnaviProtocol.java (renamed from src/org/traccar/protocol/ArnaviProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java (renamed from src/org/traccar/protocol/ArnaviProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AstraProtocol.java (renamed from src/org/traccar/protocol/AstraProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AstraProtocolDecoder.java (renamed from src/org/traccar/protocol/AstraProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/At2000FrameDecoder.java (renamed from src/org/traccar/protocol/At2000FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/At2000Protocol.java (renamed from src/org/traccar/protocol/At2000Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/At2000ProtocolDecoder.java (renamed from src/org/traccar/protocol/At2000ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AtrackFrameDecoder.java (renamed from src/org/traccar/protocol/AtrackFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AtrackProtocol.java (renamed from src/org/traccar/protocol/AtrackProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java (renamed from src/org/traccar/protocol/AtrackProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AtrackProtocolEncoder.java (renamed from src/org/traccar/protocol/AtrackProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AuroProtocol.java (renamed from src/org/traccar/protocol/AuroProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AuroProtocolDecoder.java (renamed from src/org/traccar/protocol/AuroProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AustinNbProtocol.java (renamed from src/org/traccar/protocol/AustinNbProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AustinNbProtocolDecoder.java (renamed from src/org/traccar/protocol/AustinNbProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AutoFonFrameDecoder.java (renamed from src/org/traccar/protocol/AutoFonFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AutoFonProtocol.java (renamed from src/org/traccar/protocol/AutoFonProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AutoFonProtocolDecoder.java (renamed from src/org/traccar/protocol/AutoFonProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AutoGradeProtocol.java (renamed from src/org/traccar/protocol/AutoGradeProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AutoGradeProtocolDecoder.java (renamed from src/org/traccar/protocol/AutoGradeProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AutoTrackProtocol.java (renamed from src/org/traccar/protocol/AutoTrackProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AutoTrackProtocolDecoder.java (renamed from src/org/traccar/protocol/AutoTrackProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AvemaProtocol.java (renamed from src/org/traccar/protocol/AvemaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/AvemaProtocolDecoder.java (renamed from src/org/traccar/protocol/AvemaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Avl301Protocol.java (renamed from src/org/traccar/protocol/Avl301Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Avl301ProtocolDecoder.java (renamed from src/org/traccar/protocol/Avl301ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/BceFrameDecoder.java (renamed from src/org/traccar/protocol/BceFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/BceProtocol.java (renamed from src/org/traccar/protocol/BceProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/BceProtocolDecoder.java (renamed from src/org/traccar/protocol/BceProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/BceProtocolEncoder.java (renamed from src/org/traccar/protocol/BceProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/BlackKiteProtocol.java (renamed from src/org/traccar/protocol/BlackKiteProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/BlackKiteProtocolDecoder.java (renamed from src/org/traccar/protocol/BlackKiteProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/BoxProtocol.java (renamed from src/org/traccar/protocol/BoxProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/BoxProtocolDecoder.java (renamed from src/org/traccar/protocol/BoxProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/C2stekProtocol.java (renamed from src/org/traccar/protocol/C2stekProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/C2stekProtocolDecoder.java (renamed from src/org/traccar/protocol/C2stekProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CalAmpProtocol.java (renamed from src/org/traccar/protocol/CalAmpProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CalAmpProtocolDecoder.java (renamed from src/org/traccar/protocol/CalAmpProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CarTrackProtocol.java (renamed from src/org/traccar/protocol/CarTrackProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CarTrackProtocolDecoder.java (renamed from src/org/traccar/protocol/CarTrackProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CarcellProtocol.java (renamed from src/org/traccar/protocol/CarcellProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CarcellProtocolDecoder.java (renamed from src/org/traccar/protocol/CarcellProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CarcellProtocolEncoder.java (renamed from src/org/traccar/protocol/CarcellProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CarscopProtocol.java (renamed from src/org/traccar/protocol/CarscopProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CarscopProtocolDecoder.java (renamed from src/org/traccar/protocol/CarscopProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CastelProtocol.java (renamed from src/org/traccar/protocol/CastelProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CastelProtocolDecoder.java (renamed from src/org/traccar/protocol/CastelProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CastelProtocolEncoder.java (renamed from src/org/traccar/protocol/CastelProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CautelaProtocol.java (renamed from src/org/traccar/protocol/CautelaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CautelaProtocolDecoder.java (renamed from src/org/traccar/protocol/CautelaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CellocatorFrameDecoder.java (renamed from src/org/traccar/protocol/CellocatorFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CellocatorProtocol.java (renamed from src/org/traccar/protocol/CellocatorProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java (renamed from src/org/traccar/protocol/CellocatorProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CellocatorProtocolEncoder.java (renamed from src/org/traccar/protocol/CellocatorProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CguardProtocol.java (renamed from src/org/traccar/protocol/CguardProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CguardProtocolDecoder.java (renamed from src/org/traccar/protocol/CguardProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CityeasyProtocol.java (renamed from src/org/traccar/protocol/CityeasyProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CityeasyProtocolDecoder.java (renamed from src/org/traccar/protocol/CityeasyProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CityeasyProtocolEncoder.java (renamed from src/org/traccar/protocol/CityeasyProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ContinentalProtocol.java (renamed from src/org/traccar/protocol/ContinentalProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ContinentalProtocolDecoder.java (renamed from src/org/traccar/protocol/ContinentalProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CradlepointProtocol.java (renamed from src/org/traccar/protocol/CradlepointProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/CradlepointProtocolDecoder.java (renamed from src/org/traccar/protocol/CradlepointProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/DishaProtocol.java (renamed from src/org/traccar/protocol/DishaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/DishaProtocolDecoder.java (renamed from src/org/traccar/protocol/DishaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/DmtHttpProtocol.java (renamed from src/org/traccar/protocol/DmtHttpProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java (renamed from src/org/traccar/protocol/DmtHttpProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/DmtProtocol.java (renamed from src/org/traccar/protocol/DmtProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/DmtProtocolDecoder.java (renamed from src/org/traccar/protocol/DmtProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/DwayProtocol.java (renamed from src/org/traccar/protocol/DwayProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/DwayProtocolDecoder.java (renamed from src/org/traccar/protocol/DwayProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EasyTrackProtocol.java (renamed from src/org/traccar/protocol/EasyTrackProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EasyTrackProtocolDecoder.java (renamed from src/org/traccar/protocol/EasyTrackProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EelinkProtocol.java (renamed from src/org/traccar/protocol/EelinkProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java (renamed from src/org/traccar/protocol/EelinkProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EelinkProtocolEncoder.java (renamed from src/org/traccar/protocol/EelinkProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EgtsFrameDecoder.java (renamed from src/org/traccar/protocol/EgtsFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EgtsProtocol.java (renamed from src/org/traccar/protocol/EgtsProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EgtsProtocolDecoder.java (renamed from src/org/traccar/protocol/EgtsProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EnforaProtocol.java (renamed from src/org/traccar/protocol/EnforaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EnforaProtocolDecoder.java (renamed from src/org/traccar/protocol/EnforaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EnforaProtocolEncoder.java (renamed from src/org/traccar/protocol/EnforaProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EsealProtocol.java (renamed from src/org/traccar/protocol/EsealProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EsealProtocolDecoder.java (renamed from src/org/traccar/protocol/EsealProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EsealProtocolEncoder.java (renamed from src/org/traccar/protocol/EsealProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EskyFrameDecoder.java (renamed from src/org/traccar/protocol/EskyFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EskyProtocol.java (renamed from src/org/traccar/protocol/EskyProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/EskyProtocolDecoder.java (renamed from src/org/traccar/protocol/EskyProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ExtremTracProtocol.java (renamed from src/org/traccar/protocol/ExtremTracProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ExtremTracProtocolDecoder.java (renamed from src/org/traccar/protocol/ExtremTracProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FifotrackProtocol.java (renamed from src/org/traccar/protocol/FifotrackProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java (renamed from src/org/traccar/protocol/FifotrackProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FlespiProtocol.java (renamed from src/org/traccar/protocol/FlespiProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java (renamed from src/org/traccar/protocol/FlespiProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FlexCommProtocol.java (renamed from src/org/traccar/protocol/FlexCommProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FlexCommProtocolDecoder.java (renamed from src/org/traccar/protocol/FlexCommProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FlextrackProtocol.java (renamed from src/org/traccar/protocol/FlextrackProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FlextrackProtocolDecoder.java (renamed from src/org/traccar/protocol/FlextrackProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FoxProtocol.java (renamed from src/org/traccar/protocol/FoxProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FoxProtocolDecoder.java (renamed from src/org/traccar/protocol/FoxProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FreedomProtocol.java (renamed from src/org/traccar/protocol/FreedomProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FreedomProtocolDecoder.java (renamed from src/org/traccar/protocol/FreedomProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FreematicsProtocol.java (renamed from src/org/traccar/protocol/FreematicsProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/FreematicsProtocolDecoder.java (renamed from src/org/traccar/protocol/FreematicsProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GalileoFrameDecoder.java (renamed from src/org/traccar/protocol/GalileoFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GalileoProtocol.java (renamed from src/org/traccar/protocol/GalileoProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GalileoProtocolDecoder.java (renamed from src/org/traccar/protocol/GalileoProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GalileoProtocolEncoder.java (renamed from src/org/traccar/protocol/GalileoProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GatorProtocol.java (renamed from src/org/traccar/protocol/GatorProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GatorProtocolDecoder.java (renamed from src/org/traccar/protocol/GatorProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GenxProtocol.java (renamed from src/org/traccar/protocol/GenxProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GenxProtocolDecoder.java (renamed from src/org/traccar/protocol/GenxProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gl100Protocol.java (renamed from src/org/traccar/protocol/Gl100Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gl100ProtocolDecoder.java (renamed from src/org/traccar/protocol/Gl100ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gl200BinaryProtocolDecoder.java (renamed from src/org/traccar/protocol/Gl200BinaryProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gl200FrameDecoder.java (renamed from src/org/traccar/protocol/Gl200FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gl200Protocol.java (renamed from src/org/traccar/protocol/Gl200Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gl200ProtocolDecoder.java (renamed from src/org/traccar/protocol/Gl200ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gl200ProtocolEncoder.java (renamed from src/org/traccar/protocol/Gl200ProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java (renamed from src/org/traccar/protocol/Gl200TextProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GlobalSatProtocol.java (renamed from src/org/traccar/protocol/GlobalSatProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GlobalSatProtocolDecoder.java (renamed from src/org/traccar/protocol/GlobalSatProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GnxProtocol.java (renamed from src/org/traccar/protocol/GnxProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GnxProtocolDecoder.java (renamed from src/org/traccar/protocol/GnxProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GoSafeProtocol.java (renamed from src/org/traccar/protocol/GoSafeProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java (renamed from src/org/traccar/protocol/GoSafeProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GotopProtocol.java (renamed from src/org/traccar/protocol/GotopProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GotopProtocolDecoder.java (renamed from src/org/traccar/protocol/GotopProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gps056FrameDecoder.java (renamed from src/org/traccar/protocol/Gps056FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gps056Protocol.java (renamed from src/org/traccar/protocol/Gps056Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gps056ProtocolDecoder.java (renamed from src/org/traccar/protocol/Gps056ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gps103Protocol.java (renamed from src/org/traccar/protocol/Gps103Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gps103ProtocolDecoder.java (renamed from src/org/traccar/protocol/Gps103ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gps103ProtocolEncoder.java (renamed from src/org/traccar/protocol/Gps103ProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GpsGateProtocol.java (renamed from src/org/traccar/protocol/GpsGateProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GpsGateProtocolDecoder.java (renamed from src/org/traccar/protocol/GpsGateProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GpsMarkerProtocol.java (renamed from src/org/traccar/protocol/GpsMarkerProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GpsMarkerProtocolDecoder.java (renamed from src/org/traccar/protocol/GpsMarkerProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GpsmtaProtocol.java (renamed from src/org/traccar/protocol/GpsmtaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GpsmtaProtocolDecoder.java (renamed from src/org/traccar/protocol/GpsmtaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GranitFrameDecoder.java (renamed from src/org/traccar/protocol/GranitFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GranitProtocol.java (renamed from src/org/traccar/protocol/GranitProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GranitProtocolDecoder.java (renamed from src/org/traccar/protocol/GranitProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GranitProtocolEncoder.java (renamed from src/org/traccar/protocol/GranitProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/GranitProtocolSmsEncoder.java (renamed from src/org/traccar/protocol/GranitProtocolSmsEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gt02Protocol.java (renamed from src/org/traccar/protocol/Gt02Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gt02ProtocolDecoder.java (renamed from src/org/traccar/protocol/Gt02ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gt06FrameDecoder.java (renamed from src/org/traccar/protocol/Gt06FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gt06Protocol.java (renamed from src/org/traccar/protocol/Gt06Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java (renamed from src/org/traccar/protocol/Gt06ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java (renamed from src/org/traccar/protocol/Gt06ProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gt30Protocol.java (renamed from src/org/traccar/protocol/Gt30Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Gt30ProtocolDecoder.java (renamed from src/org/traccar/protocol/Gt30ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/H02FrameDecoder.java (renamed from src/org/traccar/protocol/H02FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/H02Protocol.java (renamed from src/org/traccar/protocol/H02Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/H02ProtocolDecoder.java (renamed from src/org/traccar/protocol/H02ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/H02ProtocolEncoder.java (renamed from src/org/traccar/protocol/H02ProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HaicomProtocol.java (renamed from src/org/traccar/protocol/HaicomProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HaicomProtocolDecoder.java (renamed from src/org/traccar/protocol/HaicomProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HomtecsProtocol.java (renamed from src/org/traccar/protocol/HomtecsProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HomtecsProtocolDecoder.java (renamed from src/org/traccar/protocol/HomtecsProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HuaShengFrameDecoder.java (renamed from src/org/traccar/protocol/HuaShengFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HuaShengProtocol.java (renamed from src/org/traccar/protocol/HuaShengProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java (renamed from src/org/traccar/protocol/HuaShengProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoFrameDecoder.java (renamed from src/org/traccar/protocol/HuabaoFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoProtocol.java (renamed from src/org/traccar/protocol/HuabaoProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java (renamed from src/org/traccar/protocol/HuabaoProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HuabaoProtocolEncoder.java (renamed from src/org/traccar/protocol/HuabaoProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HunterProProtocol.java (renamed from src/org/traccar/protocol/HunterProProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/HunterProProtocolDecoder.java (renamed from src/org/traccar/protocol/HunterProProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/IdplProtocol.java (renamed from src/org/traccar/protocol/IdplProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/IdplProtocolDecoder.java (renamed from src/org/traccar/protocol/IdplProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/IntellitracFrameDecoder.java (renamed from src/org/traccar/protocol/IntellitracFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/IntellitracProtocol.java (renamed from src/org/traccar/protocol/IntellitracProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/IntellitracProtocolDecoder.java (renamed from src/org/traccar/protocol/IntellitracProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ItsProtocol.java (renamed from src/org/traccar/protocol/ItsProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ItsProtocolDecoder.java (renamed from src/org/traccar/protocol/ItsProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Ivt401Protocol.java (renamed from src/org/traccar/protocol/Ivt401Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Ivt401ProtocolDecoder.java (renamed from src/org/traccar/protocol/Ivt401ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/JpKorjarFrameDecoder.java (renamed from src/org/traccar/protocol/JpKorjarFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/JpKorjarProtocol.java (renamed from src/org/traccar/protocol/JpKorjarProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/JpKorjarProtocolDecoder.java (renamed from src/org/traccar/protocol/JpKorjarProtocolDecoder.java)178
-rw-r--r--src/main/java/org/traccar/protocol/Jt600FrameDecoder.java (renamed from src/org/traccar/protocol/Jt600FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Jt600Protocol.java (renamed from src/org/traccar/protocol/Jt600Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java (renamed from src/org/traccar/protocol/Jt600ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Jt600ProtocolEncoder.java (renamed from src/org/traccar/protocol/Jt600ProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/KenjiProtocol.java (renamed from src/org/traccar/protocol/KenjiProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/KenjiProtocolDecoder.java (renamed from src/org/traccar/protocol/KenjiProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/KhdProtocol.java (renamed from src/org/traccar/protocol/KhdProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/KhdProtocolDecoder.java (renamed from src/org/traccar/protocol/KhdProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/KhdProtocolEncoder.java (renamed from src/org/traccar/protocol/KhdProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/L100FrameDecoder.java (renamed from src/org/traccar/protocol/L100FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/L100Protocol.java (renamed from src/org/traccar/protocol/L100Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/L100ProtocolDecoder.java (renamed from src/org/traccar/protocol/L100ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/LaipacProtocol.java (renamed from src/org/traccar/protocol/LaipacProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java (renamed from src/org/traccar/protocol/LaipacProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/M2cProtocol.java (renamed from src/org/traccar/protocol/M2cProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/M2cProtocolDecoder.java (renamed from src/org/traccar/protocol/M2cProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/M2mProtocol.java (renamed from src/org/traccar/protocol/M2mProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/M2mProtocolDecoder.java (renamed from src/org/traccar/protocol/M2mProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MaestroProtocol.java (renamed from src/org/traccar/protocol/MaestroProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MaestroProtocolDecoder.java (renamed from src/org/traccar/protocol/MaestroProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ManPowerProtocol.java (renamed from src/org/traccar/protocol/ManPowerProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ManPowerProtocolDecoder.java (renamed from src/org/traccar/protocol/ManPowerProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MegastekFrameDecoder.java (renamed from src/org/traccar/protocol/MegastekFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MegastekProtocol.java (renamed from src/org/traccar/protocol/MegastekProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MegastekProtocolDecoder.java (renamed from src/org/traccar/protocol/MegastekProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoFrameDecoder.java (renamed from src/org/traccar/protocol/MeiligaoFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoProtocol.java (renamed from src/org/traccar/protocol/MeiligaoProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java (renamed from src/org/traccar/protocol/MeiligaoProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java (renamed from src/org/traccar/protocol/MeiligaoProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MeitrackFrameDecoder.java (renamed from src/org/traccar/protocol/MeitrackFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MeitrackProtocol.java (renamed from src/org/traccar/protocol/MeitrackProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java (renamed from src/org/traccar/protocol/MeitrackProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MeitrackProtocolEncoder.java (renamed from src/org/traccar/protocol/MeitrackProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MilesmateProtocol.java (renamed from src/org/traccar/protocol/MilesmateProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MilesmateProtocolDecoder.java (renamed from src/org/traccar/protocol/MilesmateProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MiniFinderProtocol.java (renamed from src/org/traccar/protocol/MiniFinderProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MiniFinderProtocolDecoder.java (renamed from src/org/traccar/protocol/MiniFinderProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MiniFinderProtocolEncoder.java (renamed from src/org/traccar/protocol/MiniFinderProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Mta6Protocol.java (renamed from src/org/traccar/protocol/Mta6Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Mta6ProtocolDecoder.java (renamed from src/org/traccar/protocol/Mta6ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MtxProtocol.java (renamed from src/org/traccar/protocol/MtxProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MtxProtocolDecoder.java (renamed from src/org/traccar/protocol/MtxProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MxtFrameDecoder.java (renamed from src/org/traccar/protocol/MxtFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MxtProtocol.java (renamed from src/org/traccar/protocol/MxtProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/MxtProtocolDecoder.java (renamed from src/org/traccar/protocol/MxtProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NavigilFrameDecoder.java (renamed from src/org/traccar/protocol/NavigilFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NavigilProtocol.java (renamed from src/org/traccar/protocol/NavigilProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NavigilProtocolDecoder.java (renamed from src/org/traccar/protocol/NavigilProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NavisFrameDecoder.java (renamed from src/org/traccar/protocol/NavisFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NavisProtocol.java (renamed from src/org/traccar/protocol/NavisProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NavisProtocolDecoder.java (renamed from src/org/traccar/protocol/NavisProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NeosProtocol.java (renamed from src/org/traccar/protocol/NeosProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NeosProtocolDecoder.java (renamed from src/org/traccar/protocol/NeosProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NoranProtocol.java (renamed from src/org/traccar/protocol/NoranProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NoranProtocolDecoder.java (renamed from src/org/traccar/protocol/NoranProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NoranProtocolEncoder.java (renamed from src/org/traccar/protocol/NoranProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NvsFrameDecoder.java (renamed from src/org/traccar/protocol/NvsFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NvsProtocol.java (renamed from src/org/traccar/protocol/NvsProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NvsProtocolDecoder.java (renamed from src/org/traccar/protocol/NvsProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NyitechProtocol.java (renamed from src/org/traccar/protocol/NyitechProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/NyitechProtocolDecoder.java (renamed from src/org/traccar/protocol/NyitechProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ObdDongleProtocol.java (renamed from src/org/traccar/protocol/ObdDongleProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ObdDongleProtocolDecoder.java (renamed from src/org/traccar/protocol/ObdDongleProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OigoProtocol.java (renamed from src/org/traccar/protocol/OigoProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OigoProtocolDecoder.java (renamed from src/org/traccar/protocol/OigoProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OkoProtocol.java (renamed from src/org/traccar/protocol/OkoProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OkoProtocolDecoder.java (renamed from src/org/traccar/protocol/OkoProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OpenGtsProtocol.java (renamed from src/org/traccar/protocol/OpenGtsProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OpenGtsProtocolDecoder.java (renamed from src/org/traccar/protocol/OpenGtsProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OrionFrameDecoder.java (renamed from src/org/traccar/protocol/OrionFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OrionProtocol.java (renamed from src/org/traccar/protocol/OrionProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OrionProtocolDecoder.java (renamed from src/org/traccar/protocol/OrionProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OsmAndProtocol.java (renamed from src/org/traccar/protocol/OsmAndProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java (renamed from src/org/traccar/protocol/OsmAndProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OwnTracksProtocol.java (renamed from src/org/traccar/protocol/OwnTracksProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/OwnTracksProtocolDecoder.java (renamed from src/org/traccar/protocol/OwnTracksProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PathAwayProtocol.java (renamed from src/org/traccar/protocol/PathAwayProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PathAwayProtocolDecoder.java (renamed from src/org/traccar/protocol/PathAwayProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PiligrimProtocol.java (renamed from src/org/traccar/protocol/PiligrimProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java (renamed from src/org/traccar/protocol/PiligrimProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PretraceProtocol.java (renamed from src/org/traccar/protocol/PretraceProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PretraceProtocolDecoder.java (renamed from src/org/traccar/protocol/PretraceProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PretraceProtocolEncoder.java (renamed from src/org/traccar/protocol/PretraceProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PricolProtocol.java (renamed from src/org/traccar/protocol/PricolProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/PricolProtocolDecoder.java (renamed from src/org/traccar/protocol/PricolProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ProgressProtocol.java (renamed from src/org/traccar/protocol/ProgressProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ProgressProtocolDecoder.java (renamed from src/org/traccar/protocol/ProgressProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Pt3000Protocol.java (renamed from src/org/traccar/protocol/Pt3000Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Pt3000ProtocolDecoder.java (renamed from src/org/traccar/protocol/Pt3000ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Pt502FrameDecoder.java (renamed from src/org/traccar/protocol/Pt502FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Pt502Protocol.java (renamed from src/org/traccar/protocol/Pt502Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Pt502ProtocolDecoder.java (renamed from src/org/traccar/protocol/Pt502ProtocolDecoder.java)424
-rw-r--r--src/main/java/org/traccar/protocol/Pt502ProtocolEncoder.java (renamed from src/org/traccar/protocol/Pt502ProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Pt60Protocol.java (renamed from src/org/traccar/protocol/Pt60Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Pt60ProtocolDecoder.java (renamed from src/org/traccar/protocol/Pt60ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RaveonProtocol.java (renamed from src/org/traccar/protocol/RaveonProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RaveonProtocolDecoder.java (renamed from src/org/traccar/protocol/RaveonProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RecodaProtocol.java (renamed from src/org/traccar/protocol/RecodaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RecodaProtocolDecoder.java (renamed from src/org/traccar/protocol/RecodaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RetranslatorFrameDecoder.java (renamed from src/org/traccar/protocol/RetranslatorFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RetranslatorProtocol.java (renamed from src/org/traccar/protocol/RetranslatorProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RetranslatorProtocolDecoder.java (renamed from src/org/traccar/protocol/RetranslatorProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RitiProtocol.java (renamed from src/org/traccar/protocol/RitiProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RitiProtocolDecoder.java (renamed from src/org/traccar/protocol/RitiProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RoboTrackFrameDecoder.java (renamed from src/org/traccar/protocol/RoboTrackFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RoboTrackProtocol.java (renamed from src/org/traccar/protocol/RoboTrackProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RoboTrackProtocolDecoder.java (renamed from src/org/traccar/protocol/RoboTrackProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RuptelaProtocol.java (renamed from src/org/traccar/protocol/RuptelaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java (renamed from src/org/traccar/protocol/RuptelaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/RuptelaProtocolEncoder.java (renamed from src/org/traccar/protocol/RuptelaProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SabertekFrameDecoder.java (renamed from src/org/traccar/protocol/SabertekFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SabertekProtocol.java (renamed from src/org/traccar/protocol/SabertekProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SabertekProtocolDecoder.java (renamed from src/org/traccar/protocol/SabertekProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SanavProtocol.java (renamed from src/org/traccar/protocol/SanavProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SanavProtocolDecoder.java (renamed from src/org/traccar/protocol/SanavProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SatsolProtocol.java (renamed from src/org/traccar/protocol/SatsolProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SatsolProtocolDecoder.java (renamed from src/org/traccar/protocol/SatsolProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SigfoxProtocol.java (renamed from src/org/traccar/protocol/SigfoxProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java (renamed from src/org/traccar/protocol/SigfoxProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SiwiProtocol.java (renamed from src/org/traccar/protocol/SiwiProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SiwiProtocolDecoder.java (renamed from src/org/traccar/protocol/SiwiProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SkypatrolProtocol.java (renamed from src/org/traccar/protocol/SkypatrolProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SkypatrolProtocolDecoder.java (renamed from src/org/traccar/protocol/SkypatrolProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SmartSoleProtocol.java (renamed from src/org/traccar/protocol/SmartSoleProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SmartSoleProtocolDecoder.java (renamed from src/org/traccar/protocol/SmartSoleProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SmokeyProtocol.java (renamed from src/org/traccar/protocol/SmokeyProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SmokeyProtocolDecoder.java (renamed from src/org/traccar/protocol/SmokeyProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SpotProtocol.java (renamed from src/org/traccar/protocol/SpotProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SpotProtocolDecoder.java (renamed from src/org/traccar/protocol/SpotProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/StarLinkProtocol.java (renamed from src/org/traccar/protocol/StarLinkProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java (renamed from src/org/traccar/protocol/StarLinkProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Stl060FrameDecoder.java (renamed from src/org/traccar/protocol/Stl060FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Stl060Protocol.java (renamed from src/org/traccar/protocol/Stl060Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Stl060ProtocolDecoder.java (renamed from src/org/traccar/protocol/Stl060ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SuntechProtocol.java (renamed from src/org/traccar/protocol/SuntechProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java (renamed from src/org/traccar/protocol/SuntechProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SuntechProtocolEncoder.java (renamed from src/org/traccar/protocol/SuntechProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SupermateProtocol.java (renamed from src/org/traccar/protocol/SupermateProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SupermateProtocolDecoder.java (renamed from src/org/traccar/protocol/SupermateProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/SviasProtocol.java (renamed from src/org/traccar/protocol/SviasProtocol.java)102
-rw-r--r--src/main/java/org/traccar/protocol/SviasProtocolDecoder.java (renamed from src/org/traccar/protocol/SviasProtocolDecoder.java)210
-rw-r--r--src/main/java/org/traccar/protocol/SviasProtocolEncoder.java (renamed from src/org/traccar/protocol/SviasProtocolEncoder.java)96
-rw-r--r--src/main/java/org/traccar/protocol/T55Protocol.java (renamed from src/org/traccar/protocol/T55Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/T55ProtocolDecoder.java (renamed from src/org/traccar/protocol/T55ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/T57FrameDecoder.java (renamed from src/org/traccar/protocol/T57FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/T57Protocol.java (renamed from src/org/traccar/protocol/T57Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/T57ProtocolDecoder.java (renamed from src/org/traccar/protocol/T57ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/T800xProtocol.java (renamed from src/org/traccar/protocol/T800xProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/T800xProtocolDecoder.java (renamed from src/org/traccar/protocol/T800xProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/T800xProtocolEncoder.java (renamed from src/org/traccar/protocol/T800xProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TaipProtocol.java (renamed from src/org/traccar/protocol/TaipProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TaipProtocolDecoder.java (renamed from src/org/traccar/protocol/TaipProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TekFrameDecoder.java (renamed from src/org/traccar/protocol/TekFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TekProtocol.java (renamed from src/org/traccar/protocol/TekProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TekProtocolDecoder.java (renamed from src/org/traccar/protocol/TekProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TelemaxProtocol.java (renamed from src/org/traccar/protocol/TelemaxProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TelemaxProtocolDecoder.java (renamed from src/org/traccar/protocol/TelemaxProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TelicFrameDecoder.java (renamed from src/org/traccar/protocol/TelicFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TelicProtocol.java (renamed from src/org/traccar/protocol/TelicProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TelicProtocolDecoder.java (renamed from src/org/traccar/protocol/TelicProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java (renamed from src/org/traccar/protocol/TeltonikaFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaProtocol.java (renamed from src/org/traccar/protocol/TeltonikaProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java (renamed from src/org/traccar/protocol/TeltonikaProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TeltonikaProtocolEncoder.java (renamed from src/org/traccar/protocol/TeltonikaProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ThinkRaceProtocol.java (renamed from src/org/traccar/protocol/ThinkRaceProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/ThinkRaceProtocolDecoder.java (renamed from src/org/traccar/protocol/ThinkRaceProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tk102Protocol.java (renamed from src/org/traccar/protocol/Tk102Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tk102ProtocolDecoder.java (renamed from src/org/traccar/protocol/Tk102ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tk103FrameDecoder.java (renamed from src/org/traccar/protocol/Tk103FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tk103Protocol.java (renamed from src/org/traccar/protocol/Tk103Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java (renamed from src/org/traccar/protocol/Tk103ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tk103ProtocolEncoder.java (renamed from src/org/traccar/protocol/Tk103ProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tlt2hProtocol.java (renamed from src/org/traccar/protocol/Tlt2hProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java (renamed from src/org/traccar/protocol/Tlt2hProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TlvProtocol.java (renamed from src/org/traccar/protocol/TlvProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TlvProtocolDecoder.java (renamed from src/org/traccar/protocol/TlvProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TmgFrameDecoder.java (renamed from src/org/traccar/protocol/TmgFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TmgProtocol.java (renamed from src/org/traccar/protocol/TmgProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TmgProtocolDecoder.java (renamed from src/org/traccar/protocol/TmgProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TopflytechProtocol.java (renamed from src/org/traccar/protocol/TopflytechProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TopflytechProtocolDecoder.java (renamed from src/org/traccar/protocol/TopflytechProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TotemFrameDecoder.java (renamed from src/org/traccar/protocol/TotemFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TotemProtocol.java (renamed from src/org/traccar/protocol/TotemProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TotemProtocolDecoder.java (renamed from src/org/traccar/protocol/TotemProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TotemProtocolEncoder.java (renamed from src/org/traccar/protocol/TotemProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tr20Protocol.java (renamed from src/org/traccar/protocol/Tr20Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tr20ProtocolDecoder.java (renamed from src/org/traccar/protocol/Tr20ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tr900Protocol.java (renamed from src/org/traccar/protocol/Tr900Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tr900ProtocolDecoder.java (renamed from src/org/traccar/protocol/Tr900ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TrackboxProtocol.java (renamed from src/org/traccar/protocol/TrackboxProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TrackboxProtocolDecoder.java (renamed from src/org/traccar/protocol/TrackboxProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TrakMateProtocol.java (renamed from src/org/traccar/protocol/TrakMateProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TrakMateProtocolDecoder.java (renamed from src/org/traccar/protocol/TrakMateProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TramigoFrameDecoder.java (renamed from src/org/traccar/protocol/TramigoFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TramigoProtocol.java (renamed from src/org/traccar/protocol/TramigoProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java (renamed from src/org/traccar/protocol/TramigoProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TrvProtocol.java (renamed from src/org/traccar/protocol/TrvProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TrvProtocolDecoder.java (renamed from src/org/traccar/protocol/TrvProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tt8850Protocol.java (renamed from src/org/traccar/protocol/Tt8850Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Tt8850ProtocolDecoder.java (renamed from src/org/traccar/protocol/Tt8850ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TytanProtocol.java (renamed from src/org/traccar/protocol/TytanProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TytanProtocolDecoder.java (renamed from src/org/traccar/protocol/TytanProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TzoneProtocol.java (renamed from src/org/traccar/protocol/TzoneProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java (renamed from src/org/traccar/protocol/TzoneProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/UlbotechFrameDecoder.java (renamed from src/org/traccar/protocol/UlbotechFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/UlbotechProtocol.java (renamed from src/org/traccar/protocol/UlbotechProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/UlbotechProtocolDecoder.java (renamed from src/org/traccar/protocol/UlbotechProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/UproProtocol.java (renamed from src/org/traccar/protocol/UproProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/UproProtocolDecoder.java (renamed from src/org/traccar/protocol/UproProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/V680Protocol.java (renamed from src/org/traccar/protocol/V680Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/V680ProtocolDecoder.java (renamed from src/org/traccar/protocol/V680ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/VisiontekProtocol.java (renamed from src/org/traccar/protocol/VisiontekProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/VisiontekProtocolDecoder.java (renamed from src/org/traccar/protocol/VisiontekProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Vt200FrameDecoder.java (renamed from src/org/traccar/protocol/Vt200FrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Vt200Protocol.java (renamed from src/org/traccar/protocol/Vt200Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Vt200ProtocolDecoder.java (renamed from src/org/traccar/protocol/Vt200ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/VtfmsFrameDecoder.java (renamed from src/org/traccar/protocol/VtfmsFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/VtfmsProtocol.java (renamed from src/org/traccar/protocol/VtfmsProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/VtfmsProtocolDecoder.java (renamed from src/org/traccar/protocol/VtfmsProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WatchFrameDecoder.java (renamed from src/org/traccar/protocol/WatchFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WatchProtocol.java (renamed from src/org/traccar/protocol/WatchProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WatchProtocolDecoder.java (renamed from src/org/traccar/protocol/WatchProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WatchProtocolEncoder.java (renamed from src/org/traccar/protocol/WatchProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WialonProtocol.java (renamed from src/org/traccar/protocol/WialonProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WialonProtocolDecoder.java (renamed from src/org/traccar/protocol/WialonProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WialonProtocolEncoder.java (renamed from src/org/traccar/protocol/WialonProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WondexFrameDecoder.java (renamed from src/org/traccar/protocol/WondexFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WondexProtocol.java (renamed from src/org/traccar/protocol/WondexProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WondexProtocolDecoder.java (renamed from src/org/traccar/protocol/WondexProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WondexProtocolEncoder.java (renamed from src/org/traccar/protocol/WondexProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WristbandProtocol.java (renamed from src/org/traccar/protocol/WristbandProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/WristbandProtocolDecoder.java (renamed from src/org/traccar/protocol/WristbandProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/XexunFrameDecoder.java (renamed from src/org/traccar/protocol/XexunFrameDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/XexunProtocol.java (renamed from src/org/traccar/protocol/XexunProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/XexunProtocolDecoder.java (renamed from src/org/traccar/protocol/XexunProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/XexunProtocolEncoder.java (renamed from src/org/traccar/protocol/XexunProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/XirgoProtocol.java (renamed from src/org/traccar/protocol/XirgoProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/XirgoProtocolDecoder.java (renamed from src/org/traccar/protocol/XirgoProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/XirgoProtocolEncoder.java (renamed from src/org/traccar/protocol/XirgoProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Xrb28Protocol.java (renamed from src/org/traccar/protocol/Xrb28Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Xrb28ProtocolDecoder.java (renamed from src/org/traccar/protocol/Xrb28ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Xrb28ProtocolEncoder.java (renamed from src/org/traccar/protocol/Xrb28ProtocolEncoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Xt013Protocol.java (renamed from src/org/traccar/protocol/Xt013Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Xt013ProtocolDecoder.java (renamed from src/org/traccar/protocol/Xt013ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Xt2400Protocol.java (renamed from src/org/traccar/protocol/Xt2400Protocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java (renamed from src/org/traccar/protocol/Xt2400ProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/protocol/YwtProtocol.java (renamed from src/org/traccar/protocol/YwtProtocol.java)0
-rw-r--r--src/main/java/org/traccar/protocol/YwtProtocolDecoder.java (renamed from src/org/traccar/protocol/YwtProtocolDecoder.java)0
-rw-r--r--src/main/java/org/traccar/reports/Events.java (renamed from src/org/traccar/reports/Events.java)0
-rw-r--r--src/main/java/org/traccar/reports/ReportUtils.java (renamed from src/org/traccar/reports/ReportUtils.java)0
-rw-r--r--src/main/java/org/traccar/reports/Route.java (renamed from src/org/traccar/reports/Route.java)0
-rw-r--r--src/main/java/org/traccar/reports/Stops.java (renamed from src/org/traccar/reports/Stops.java)0
-rw-r--r--src/main/java/org/traccar/reports/Summary.java (renamed from src/org/traccar/reports/Summary.java)0
-rw-r--r--src/main/java/org/traccar/reports/Trips.java (renamed from src/org/traccar/reports/Trips.java)0
-rw-r--r--src/main/java/org/traccar/reports/model/BaseReport.java (renamed from src/org/traccar/reports/model/BaseReport.java)0
-rw-r--r--src/main/java/org/traccar/reports/model/DeviceReport.java (renamed from src/org/traccar/reports/model/DeviceReport.java)0
-rw-r--r--src/main/java/org/traccar/reports/model/StopReport.java (renamed from src/org/traccar/reports/model/StopReport.java)0
-rw-r--r--src/main/java/org/traccar/reports/model/SummaryReport.java (renamed from src/org/traccar/reports/model/SummaryReport.java)0
-rw-r--r--src/main/java/org/traccar/reports/model/TripReport.java (renamed from src/org/traccar/reports/model/TripReport.java)0
-rw-r--r--src/main/java/org/traccar/reports/model/TripsConfig.java (renamed from src/org/traccar/reports/model/TripsConfig.java)0
-rw-r--r--src/main/java/org/traccar/sms/HttpSmsClient.java (renamed from src/org/traccar/sms/HttpSmsClient.java)0
-rw-r--r--src/main/java/org/traccar/sms/SmsManager.java (renamed from src/org/traccar/sms/SmsManager.java)2
-rw-r--r--src/main/java/org/traccar/sms/smpp/ClientSmppSessionHandler.java (renamed from src/org/traccar/sms/smpp/ClientSmppSessionHandler.java)0
-rw-r--r--src/main/java/org/traccar/sms/smpp/EnquireLinkTask.java (renamed from src/org/traccar/sms/smpp/EnquireLinkTask.java)0
-rw-r--r--src/main/java/org/traccar/sms/smpp/ReconnectionTask.java (renamed from src/org/traccar/sms/smpp/ReconnectionTask.java)0
-rw-r--r--src/main/java/org/traccar/sms/smpp/SmppClient.java (renamed from src/org/traccar/sms/smpp/SmppClient.java)0
-rw-r--r--src/main/java/org/traccar/sms/smpp/TextMessageEventHandler.java (renamed from src/org/traccar/sms/smpp/TextMessageEventHandler.java)0
-rw-r--r--src/main/java/org/traccar/web/ConsoleServlet.java (renamed from src/org/traccar/web/ConsoleServlet.java)0
-rw-r--r--src/main/java/org/traccar/web/CsvBuilder.java (renamed from src/org/traccar/web/CsvBuilder.java)0
-rw-r--r--src/main/java/org/traccar/web/GpxBuilder.java (renamed from src/org/traccar/web/GpxBuilder.java)0
-rw-r--r--src/main/java/org/traccar/web/WebServer.java (renamed from src/org/traccar/web/WebServer.java)0
-rw-r--r--src/test/java/org/traccar/BaseTest.java34
-rw-r--r--src/test/java/org/traccar/ProtocolTest.java324
-rw-r--r--src/test/java/org/traccar/TestIdentityManager.java72
-rw-r--r--src/test/java/org/traccar/WebDataHandlerTest.java28
-rw-r--r--src/test/java/org/traccar/calendar/CalendarTest.java59
-rw-r--r--src/test/java/org/traccar/config/ConfigTest.java19
-rw-r--r--src/test/java/org/traccar/database/DataManagerTest.java81
-rw-r--r--src/test/java/org/traccar/database/GroupTreeTest.java56
-rw-r--r--src/test/java/org/traccar/geocoder/AddressFormatTest.java33
-rw-r--r--src/test/java/org/traccar/geocoder/GeocoderTest.java88
-rw-r--r--src/test/java/org/traccar/geofence/GeofenceCircleTest.java28
-rw-r--r--src/test/java/org/traccar/geofence/GeofencePolygonTest.java52
-rw-r--r--src/test/java/org/traccar/geofence/GeofencePolylineTest.java47
-rw-r--r--src/test/java/org/traccar/geolocation/GeolocationProviderTest.java41
-rw-r--r--src/test/java/org/traccar/handler/ComputedAttributesTest.java71
-rw-r--r--src/test/java/org/traccar/handler/DistanceHandlerTest.java30
-rw-r--r--src/test/java/org/traccar/handler/FilterHandlerTest.java88
-rw-r--r--src/test/java/org/traccar/handler/MotionHandlerTest.java21
-rw-r--r--src/test/java/org/traccar/handler/events/AlertEventHandlerTest.java30
-rw-r--r--src/test/java/org/traccar/handler/events/CommandResultEventHandlerTest.java28
-rw-r--r--src/test/java/org/traccar/handler/events/IgnitionEventHandlerTest.java27
-rw-r--r--src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java119
-rw-r--r--src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java128
-rw-r--r--src/test/java/org/traccar/helper/BcdUtilTest.java24
-rw-r--r--src/test/java/org/traccar/helper/BitBufferTest.java23
-rw-r--r--src/test/java/org/traccar/helper/BitUtilTest.java38
-rw-r--r--src/test/java/org/traccar/helper/ChecksumTest.java39
-rw-r--r--src/test/java/org/traccar/helper/DateBuilderTest.java27
-rw-r--r--src/test/java/org/traccar/helper/DateUtilTest.java30
-rw-r--r--src/test/java/org/traccar/helper/DistanceCalculatorTest.java24
-rw-r--r--src/test/java/org/traccar/helper/LocationTreeTest.java30
-rw-r--r--src/test/java/org/traccar/helper/LogTest.java14
-rw-r--r--src/test/java/org/traccar/helper/ObdDecoderTest.java26
-rw-r--r--src/test/java/org/traccar/helper/PatternBuilderTest.java20
-rw-r--r--src/test/java/org/traccar/helper/PatternUtilTest.java18
-rw-r--r--src/test/java/org/traccar/model/MiscFormatterTest.java20
-rw-r--r--src/test/java/org/traccar/notification/NotificiationMailTest.java59
-rw-r--r--src/test/java/org/traccar/protocol/AdmProtocolDecoderTest.java38
-rw-r--r--src/test/java/org/traccar/protocol/AdmProtocolEncoderTest.java44
-rw-r--r--src/test/java/org/traccar/protocol/AisProtocolDecoderTest.java31
-rw-r--r--src/test/java/org/traccar/protocol/AlematicsProtocolDecoderTest.java42
-rw-r--r--src/test/java/org/traccar/protocol/AnytrekProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/ApelProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/AplicomFrameDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/AplicomProtocolDecoderTest.java93
-rw-r--r--src/test/java/org/traccar/protocol/AppelloProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/AppletProtocolDecoderTest.java27
-rw-r--r--src/test/java/org/traccar/protocol/AquilaProtocolDecoderTest.java79
-rw-r--r--src/test/java/org/traccar/protocol/Ardi01ProtocolDecoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/ArknavProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/ArknavX8ProtocolDecoderTest.java45
-rw-r--r--src/test/java/org/traccar/protocol/ArnaviProtocolDecoderTest.java42
-rw-r--r--src/test/java/org/traccar/protocol/AstraProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/At2000FrameDecoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/At2000ProtocolDecoderTest.java59
-rw-r--r--src/test/java/org/traccar/protocol/AtrackFrameDecoderTest.java39
-rw-r--r--src/test/java/org/traccar/protocol/AtrackProtocolDecoderTest.java99
-rw-r--r--src/test/java/org/traccar/protocol/AuroProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/AustinNbProtocolDecoderTest.java33
-rw-r--r--src/test/java/org/traccar/protocol/AutoFonProtocolDecoderTest.java41
-rw-r--r--src/test/java/org/traccar/protocol/AutoGradeProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/AutoTrackProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/AvemaProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/Avl301ProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/BceProtocolDecoderTest.java39
-rw-r--r--src/test/java/org/traccar/protocol/BceProtocolEncoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/BlackKiteProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/BoxProtocolDecoderTest.java67
-rw-r--r--src/test/java/org/traccar/protocol/C2stekProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/CalAmpProtocolDecoderTest.java54
-rw-r--r--src/test/java/org/traccar/protocol/CarTrackProtocolDecoderTest.java32
-rw-r--r--src/test/java/org/traccar/protocol/CarscopProtocolDecoderTest.java46
-rw-r--r--src/test/java/org/traccar/protocol/CastelProtocolDecoderTest.java144
-rw-r--r--src/test/java/org/traccar/protocol/CastelProtocolEncoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/CautelaProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/CellocatorProtocolDecoderTest.java33
-rw-r--r--src/test/java/org/traccar/protocol/CellocatorProtocolEncoderTest.java26
-rw-r--r--src/test/java/org/traccar/protocol/CguardProtocolDecoderTest.java78
-rw-r--r--src/test/java/org/traccar/protocol/CityeasyProtocolDecoderTest.java41
-rw-r--r--src/test/java/org/traccar/protocol/CityeasyProtocolEncoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/ContinentalProtocolDecoderTest.java29
-rw-r--r--src/test/java/org/traccar/protocol/CradlepointProtocolDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/DishaProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/DmtHttpProtocolDecoderTest.java19
-rw-r--r--src/test/java/org/traccar/protocol/DmtProtocolDecoderTest.java42
-rw-r--r--src/test/java/org/traccar/protocol/DwayProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/EasyTrackProtocolDecoderTest.java55
-rw-r--r--src/test/java/org/traccar/protocol/EelinkProtocolDecoderTest.java114
-rw-r--r--src/test/java/org/traccar/protocol/EelinkProtocolEncoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/EgtsFrameDecoderTest.java19
-rw-r--r--src/test/java/org/traccar/protocol/EgtsProtocolDecoderTest.java37
-rw-r--r--src/test/java/org/traccar/protocol/EnforaProtocolDecoderTest.java31
-rw-r--r--src/test/java/org/traccar/protocol/EsealProtocolDecoderTest.java33
-rw-r--r--src/test/java/org/traccar/protocol/EsealProtocolEncoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/EskyFrameDecoderTest.java31
-rw-r--r--src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/ExtremTracProtocolDecoderTest.java33
-rw-r--r--src/test/java/org/traccar/protocol/FifotrackProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/FlespiProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/FlexCommProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/FlextrackProtocolDecoderTest.java32
-rw-r--r--src/test/java/org/traccar/protocol/FoxProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/FreedomProtocolDecoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/FreematicsProtocolDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/GalileoFrameDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/GalileoProtocolDecoderTest.java45
-rw-r--r--src/test/java/org/traccar/protocol/GalileoProtocolEncoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/GatorProtocolDecoderTest.java50
-rw-r--r--src/test/java/org/traccar/protocol/GenxProtocolDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/Gl100ProtocolDecoderTest.java56
-rw-r--r--src/test/java/org/traccar/protocol/Gl200BinaryProtocolDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/Gl200FrameDecoderTest.java29
-rw-r--r--src/test/java/org/traccar/protocol/Gl200TextProtocolDecoderTest.java390
-rw-r--r--src/test/java/org/traccar/protocol/GlobalSatProtocolDecoderTest.java56
-rw-r--r--src/test/java/org/traccar/protocol/GnxProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/GoSafeProtocolDecoderTest.java87
-rw-r--r--src/test/java/org/traccar/protocol/GotopProtocolDecoderTest.java37
-rw-r--r--src/test/java/org/traccar/protocol/Gps056FrameDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/Gps056ProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/Gps103ProtocolDecoderTest.java261
-rw-r--r--src/test/java/org/traccar/protocol/Gps103ProtocolEncoderTest.java39
-rw-r--r--src/test/java/org/traccar/protocol/GpsGateProtocolDecoderTest.java52
-rw-r--r--src/test/java/org/traccar/protocol/GpsMarkerProtocolDecoderTest.java32
-rw-r--r--src/test/java/org/traccar/protocol/GpsmtaProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/GranitFrameDecoderTest.java45
-rw-r--r--src/test/java/org/traccar/protocol/GranitProtocolDecoderTest.java49
-rw-r--r--src/test/java/org/traccar/protocol/Gt02ProtocolDecoderTest.java43
-rw-r--r--src/test/java/org/traccar/protocol/Gt06FrameDecoderTest.java51
-rw-r--r--src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java294
-rw-r--r--src/test/java/org/traccar/protocol/Gt06ProtocolEncoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/Gt30ProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/H02FrameDecoderTest.java71
-rw-r--r--src/test/java/org/traccar/protocol/H02ProtocolDecoderTest.java261
-rw-r--r--src/test/java/org/traccar/protocol/H02ProtocolEncoderTest.java72
-rw-r--r--src/test/java/org/traccar/protocol/HaicomProtocolDecoderTest.java28
-rw-r--r--src/test/java/org/traccar/protocol/HomtecsProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/HuaShengFrameDecoderTest.java33
-rw-r--r--src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java45
-rw-r--r--src/test/java/org/traccar/protocol/HuabaoFrameDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/HuabaoProtocolDecoderTest.java69
-rw-r--r--src/test/java/org/traccar/protocol/HuabaoProtocolEncoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/HunterProProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/IdplProtocolDecoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/IntellitracProtocolDecoderTest.java64
-rw-r--r--src/test/java/org/traccar/protocol/ItsProtocolDecoderTest.java54
-rw-r--r--src/test/java/org/traccar/protocol/Ivt401ProtocolDecoderTest.java60
-rw-r--r--src/test/java/org/traccar/protocol/JpKorjarProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/Jt600FrameDecoderTest.java39
-rw-r--r--src/test/java/org/traccar/protocol/Jt600ProtocolDecoderTest.java108
-rw-r--r--src/test/java/org/traccar/protocol/Jt600ProtocolEncoderTest.java37
-rwxr-xr-xsrc/test/java/org/traccar/protocol/KenjiProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java48
-rw-r--r--src/test/java/org/traccar/protocol/KhdProtocolEncoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/L100FrameDecoderTest.java31
-rw-r--r--src/test/java/org/traccar/protocol/L100ProtocolDecoderTest.java51
-rw-r--r--src/test/java/org/traccar/protocol/LaipacProtocolDecoderTest.java125
-rw-r--r--src/test/java/org/traccar/protocol/M2cProtocolDecoderTest.java27
-rw-r--r--src/test/java/org/traccar/protocol/M2mProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/MaestroProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/ManPowerProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/MegastekFrameDecoderTest.java27
-rw-r--r--src/test/java/org/traccar/protocol/MegastekProtocolDecoderTest.java100
-rw-r--r--src/test/java/org/traccar/protocol/MeiligaoFrameDecoderTest.java29
-rw-r--r--src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java137
-rw-r--r--src/test/java/org/traccar/protocol/MeiligaoProtocolEncoderTest.java41
-rw-r--r--src/test/java/org/traccar/protocol/MeitrackFrameDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/MeitrackProtocolDecoderTest.java110
-rw-r--r--src/test/java/org/traccar/protocol/MeitrackProtocolEncoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/MilesmateProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/MiniFinderProtocolDecoderTest.java73
-rw-r--r--src/test/java/org/traccar/protocol/MiniFinderProtocolEncoderTest.java33
-rw-r--r--src/test/java/org/traccar/protocol/MtxProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/MxtProtocolDecoderTest.java45
-rw-r--r--src/test/java/org/traccar/protocol/NavigilProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/NavisFrameDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/NavisProtocolDecoderTest.java79
-rw-r--r--src/test/java/org/traccar/protocol/NeosProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/NoranProtocolDecoderTest.java45
-rw-r--r--src/test/java/org/traccar/protocol/NoranProtocolEncoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/NvsFrameDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/NvsProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/NyitechProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/ObdDongleProtocolDecoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/OigoProtocolDecoderTest.java42
-rw-r--r--src/test/java/org/traccar/protocol/OkoProtocolDecoderTest.java33
-rw-r--r--src/test/java/org/traccar/protocol/OpenGtsProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/OrionProtocolDecoderTest.java30
-rw-r--r--src/test/java/org/traccar/protocol/OsmAndProtocolDecoderTest.java48
-rw-r--r--src/test/java/org/traccar/protocol/OwnTracksProtocolDecoderTest.java27
-rw-r--r--src/test/java/org/traccar/protocol/PathAwayProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java20
-rw-r--r--src/test/java/org/traccar/protocol/PretraceProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/PretraceProtocolEncoderTest.java39
-rw-r--r--src/test/java/org/traccar/protocol/PricolProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/ProgressProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/Pt3000ProtocolDecoderTest.java22
-rw-r--r--src/test/java/org/traccar/protocol/Pt502FrameDecoderTest.java39
-rw-r--r--src/test/java/org/traccar/protocol/Pt502ProtocolDecoderTest.java86
-rw-r--r--src/test/java/org/traccar/protocol/Pt502ProtocolEncoderTest.java69
-rw-r--r--src/test/java/org/traccar/protocol/Pt60ProtocolDecoderTest.java54
-rw-r--r--src/test/java/org/traccar/protocol/RaveonProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/RecodaProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/RetranslatorProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/RitiProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/RoboTrackFrameDecoderTest.java19
-rw-r--r--src/test/java/org/traccar/protocol/RoboTrackProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/RuptelaProtocolDecoderTest.java48
-rw-r--r--src/test/java/org/traccar/protocol/RuptelaProtocolEncoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/SabertekFrameDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/SabertekProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/SanavProtocolDecoderTest.java37
-rw-r--r--src/test/java/org/traccar/protocol/SatsolProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java19
-rw-r--r--src/test/java/org/traccar/protocol/SiwiProtocolDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/SkypatrolProtocolDecoderTest.java34
-rw-r--r--src/test/java/org/traccar/protocol/SmartSoleProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/SmokeyProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/SpotProtocolDecoderTest.java19
-rw-r--r--src/test/java/org/traccar/protocol/StarLinkProtocolDecoderTest.java54
-rw-r--r--src/test/java/org/traccar/protocol/Stl060ProtocolDecoderTest.java28
-rw-r--r--src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java167
-rwxr-xr-xsrc/test/java/org/traccar/protocol/SupermateProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/SviasProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/T55ProtocolDecoderTest.java126
-rw-r--r--src/test/java/org/traccar/protocol/T57FrameDecoderTest.java19
-rw-r--r--src/test/java/org/traccar/protocol/T57ProtocolDecoderTest.java27
-rw-r--r--src/test/java/org/traccar/protocol/T800xProtocolDecoderTest.java48
-rw-r--r--src/test/java/org/traccar/protocol/T800xProtocolEncoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/TaipProtocolDecoderTest.java86
-rw-r--r--src/test/java/org/traccar/protocol/TekFrameDecoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/TekProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/TelemaxProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/TelicFrameDecoderTest.java42
-rw-r--r--src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java94
-rw-r--r--src/test/java/org/traccar/protocol/TeltonikaProtocolDecoderTest.java134
-rw-r--r--src/test/java/org/traccar/protocol/TeltonikaProtocolEncoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/ThinkRaceProtocolDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/Tk102ProtocolDecoderTest.java51
-rw-r--r--src/test/java/org/traccar/protocol/Tk103FrameDecoderTest.java44
-rw-r--r--src/test/java/org/traccar/protocol/Tk103ProtocolDecoderTest.java202
-rw-r--r--src/test/java/org/traccar/protocol/Tk103ProtocolEncoderTest.java282
-rw-r--r--src/test/java/org/traccar/protocol/Tlt2hProtocolDecoderTest.java64
-rw-r--r--src/test/java/org/traccar/protocol/TlvProtocolDecoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/TmgFrameDecoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/TmgProtocolDecoderTest.java54
-rw-r--r--src/test/java/org/traccar/protocol/TopflytechProtocolDecoderTest.java18
-rw-r--r--src/test/java/org/traccar/protocol/TotemFrameDecoderTest.java35
-rw-r--r--src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java116
-rw-r--r--src/test/java/org/traccar/protocol/TotemProtocolEncoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/Tr20ProtocolDecoderTest.java31
-rw-r--r--src/test/java/org/traccar/protocol/Tr900ProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/TrackboxProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/TrakMateProtocolDecoderTest.java27
-rw-r--r--src/test/java/org/traccar/protocol/TramigoFrameDecoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/TramigoProtocolDecoderTest.java63
-rw-r--r--src/test/java/org/traccar/protocol/TrvProtocolDecoderTest.java67
-rw-r--r--src/test/java/org/traccar/protocol/Tt8850ProtocolDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/TytanProtocolDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/TzoneProtocolDecoderTest.java53
-rw-r--r--src/test/java/org/traccar/protocol/UlbotechFrameDecoderTest.java29
-rw-r--r--src/test/java/org/traccar/protocol/UlbotechProtocolDecoderTest.java90
-rw-r--r--src/test/java/org/traccar/protocol/UproProtocolDecoderTest.java65
-rw-r--r--src/test/java/org/traccar/protocol/V680ProtocolDecoderTest.java77
-rw-r--r--src/test/java/org/traccar/protocol/VisiontekProtocolDecoderTest.java40
-rw-r--r--src/test/java/org/traccar/protocol/Vt200FrameDecoderTest.java23
-rw-r--r--src/test/java/org/traccar/protocol/Vt200ProtocolDecoderTest.java60
-rw-r--r--src/test/java/org/traccar/protocol/VtfmsFrameDecoderTest.java21
-rw-r--r--src/test/java/org/traccar/protocol/VtfmsProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/WatchFrameDecoderTest.java35
-rw-r--r--src/test/java/org/traccar/protocol/WatchProtocolDecoderTest.java128
-rw-r--r--src/test/java/org/traccar/protocol/WatchProtocolEncoderTest.java83
-rw-r--r--src/test/java/org/traccar/protocol/WialonProtocolDecoderTest.java67
-rw-r--r--src/test/java/org/traccar/protocol/WondexFrameDecoderTest.java28
-rw-r--r--src/test/java/org/traccar/protocol/WondexProtocolDecoderTest.java62
-rw-r--r--src/test/java/org/traccar/protocol/WondexProtocolEncoderTest.java24
-rw-r--r--src/test/java/org/traccar/protocol/WristbandProtocolDecoderTest.java36
-rw-r--r--src/test/java/org/traccar/protocol/XexunFrameDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/XexunProtocolDecoderTest.java118
-rw-r--r--src/test/java/org/traccar/protocol/XirgoProtocolDecoderTest.java76
-rw-r--r--src/test/java/org/traccar/protocol/XirgoProtocolEncoderTest.java26
-rw-r--r--src/test/java/org/traccar/protocol/Xrb28ProtocolDecoderTest.java33
-rw-r--r--src/test/java/org/traccar/protocol/Xrb28ProtocolEncoderTest.java39
-rw-r--r--src/test/java/org/traccar/protocol/Xt013ProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/Xt2400ProtocolDecoderTest.java25
-rw-r--r--src/test/java/org/traccar/protocol/YwtProtocolDecoderTest.java31
-rw-r--r--src/test/java/org/traccar/reports/ReportUtilsTest.java390
-rw-r--r--src/test/java/org/traccar/web/WebServerTest.java29
967 files changed, 14485 insertions, 586 deletions
diff --git a/src/org/traccar/BaseDataHandler.java b/src/main/java/org/traccar/BaseDataHandler.java
index 48794b0d7..48794b0d7 100644
--- a/src/org/traccar/BaseDataHandler.java
+++ b/src/main/java/org/traccar/BaseDataHandler.java
diff --git a/src/org/traccar/BaseFrameDecoder.java b/src/main/java/org/traccar/BaseFrameDecoder.java
index f90f90e4b..f90f90e4b 100644
--- a/src/org/traccar/BaseFrameDecoder.java
+++ b/src/main/java/org/traccar/BaseFrameDecoder.java
diff --git a/src/org/traccar/BaseHttpProtocolDecoder.java b/src/main/java/org/traccar/BaseHttpProtocolDecoder.java
index 57a68acac..57a68acac 100644
--- a/src/org/traccar/BaseHttpProtocolDecoder.java
+++ b/src/main/java/org/traccar/BaseHttpProtocolDecoder.java
diff --git a/src/org/traccar/BasePipelineFactory.java b/src/main/java/org/traccar/BasePipelineFactory.java
index b3d37f689..b3d37f689 100644
--- a/src/org/traccar/BasePipelineFactory.java
+++ b/src/main/java/org/traccar/BasePipelineFactory.java
diff --git a/src/org/traccar/BaseProtocol.java b/src/main/java/org/traccar/BaseProtocol.java
index c0fd1e27f..c0fd1e27f 100644
--- a/src/org/traccar/BaseProtocol.java
+++ b/src/main/java/org/traccar/BaseProtocol.java
diff --git a/src/org/traccar/BaseProtocolDecoder.java b/src/main/java/org/traccar/BaseProtocolDecoder.java
index aa5be612e..aa5be612e 100644
--- a/src/org/traccar/BaseProtocolDecoder.java
+++ b/src/main/java/org/traccar/BaseProtocolDecoder.java
diff --git a/src/org/traccar/BaseProtocolEncoder.java b/src/main/java/org/traccar/BaseProtocolEncoder.java
index d7625e4b8..d7625e4b8 100644
--- a/src/org/traccar/BaseProtocolEncoder.java
+++ b/src/main/java/org/traccar/BaseProtocolEncoder.java
diff --git a/src/org/traccar/CharacterDelimiterFrameDecoder.java b/src/main/java/org/traccar/CharacterDelimiterFrameDecoder.java
index eeb8834dc..eeb8834dc 100644
--- a/src/org/traccar/CharacterDelimiterFrameDecoder.java
+++ b/src/main/java/org/traccar/CharacterDelimiterFrameDecoder.java
diff --git a/src/org/traccar/Context.java b/src/main/java/org/traccar/Context.java
index 9c20db9e4..9c20db9e4 100644
--- a/src/org/traccar/Context.java
+++ b/src/main/java/org/traccar/Context.java
diff --git a/src/org/traccar/DeviceSession.java b/src/main/java/org/traccar/DeviceSession.java
index 322381807..322381807 100644
--- a/src/org/traccar/DeviceSession.java
+++ b/src/main/java/org/traccar/DeviceSession.java
diff --git a/src/org/traccar/EventLoopGroupFactory.java b/src/main/java/org/traccar/EventLoopGroupFactory.java
index 482559253..482559253 100644
--- a/src/org/traccar/EventLoopGroupFactory.java
+++ b/src/main/java/org/traccar/EventLoopGroupFactory.java
diff --git a/src/org/traccar/ExtendedObjectDecoder.java b/src/main/java/org/traccar/ExtendedObjectDecoder.java
index 681924e87..681924e87 100644
--- a/src/org/traccar/ExtendedObjectDecoder.java
+++ b/src/main/java/org/traccar/ExtendedObjectDecoder.java
diff --git a/src/org/traccar/GlobalTimer.java b/src/main/java/org/traccar/GlobalTimer.java
index a97321ba2..a97321ba2 100644
--- a/src/org/traccar/GlobalTimer.java
+++ b/src/main/java/org/traccar/GlobalTimer.java
diff --git a/src/org/traccar/Main.java b/src/main/java/org/traccar/Main.java
index 6ebd1d399..6ebd1d399 100644
--- a/src/org/traccar/Main.java
+++ b/src/main/java/org/traccar/Main.java
diff --git a/src/org/traccar/MainEventHandler.java b/src/main/java/org/traccar/MainEventHandler.java
index a8b53ff60..a8b53ff60 100644
--- a/src/org/traccar/MainEventHandler.java
+++ b/src/main/java/org/traccar/MainEventHandler.java
diff --git a/src/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java
index 6fe8bad1c..6fe8bad1c 100644
--- a/src/org/traccar/MainModule.java
+++ b/src/main/java/org/traccar/MainModule.java
diff --git a/src/org/traccar/NetworkMessage.java b/src/main/java/org/traccar/NetworkMessage.java
index 14a397e69..14a397e69 100644
--- a/src/org/traccar/NetworkMessage.java
+++ b/src/main/java/org/traccar/NetworkMessage.java
diff --git a/src/org/traccar/PipelineBuilder.java b/src/main/java/org/traccar/PipelineBuilder.java
index 3334040b1..3334040b1 100644
--- a/src/org/traccar/PipelineBuilder.java
+++ b/src/main/java/org/traccar/PipelineBuilder.java
diff --git a/src/org/traccar/Protocol.java b/src/main/java/org/traccar/Protocol.java
index 3b66f2598..3b66f2598 100644
--- a/src/org/traccar/Protocol.java
+++ b/src/main/java/org/traccar/Protocol.java
diff --git a/src/org/traccar/ServerManager.java b/src/main/java/org/traccar/ServerManager.java
index 6a3273402..6a3273402 100644
--- a/src/org/traccar/ServerManager.java
+++ b/src/main/java/org/traccar/ServerManager.java
diff --git a/src/org/traccar/StringProtocolEncoder.java b/src/main/java/org/traccar/StringProtocolEncoder.java
index 1945ae174..1945ae174 100644
--- a/src/org/traccar/StringProtocolEncoder.java
+++ b/src/main/java/org/traccar/StringProtocolEncoder.java
diff --git a/src/org/traccar/TrackerServer.java b/src/main/java/org/traccar/TrackerServer.java
index 3a1e1c4e8..3a1e1c4e8 100644
--- a/src/org/traccar/TrackerServer.java
+++ b/src/main/java/org/traccar/TrackerServer.java
diff --git a/src/org/traccar/WebDataHandler.java b/src/main/java/org/traccar/WebDataHandler.java
index 64396de03..64396de03 100644
--- a/src/org/traccar/WebDataHandler.java
+++ b/src/main/java/org/traccar/WebDataHandler.java
diff --git a/src/org/traccar/WindowsService.java b/src/main/java/org/traccar/WindowsService.java
index 4a8955608..4a8955608 100644
--- a/src/org/traccar/WindowsService.java
+++ b/src/main/java/org/traccar/WindowsService.java
diff --git a/src/org/traccar/WrapperContext.java b/src/main/java/org/traccar/WrapperContext.java
index 372d3c60d..372d3c60d 100644
--- a/src/org/traccar/WrapperContext.java
+++ b/src/main/java/org/traccar/WrapperContext.java
diff --git a/src/org/traccar/WrapperInboundHandler.java b/src/main/java/org/traccar/WrapperInboundHandler.java
index ca33d021f..ca33d021f 100644
--- a/src/org/traccar/WrapperInboundHandler.java
+++ b/src/main/java/org/traccar/WrapperInboundHandler.java
diff --git a/src/org/traccar/WrapperOutboundHandler.java b/src/main/java/org/traccar/WrapperOutboundHandler.java
index 0136c5b22..0136c5b22 100644
--- a/src/org/traccar/WrapperOutboundHandler.java
+++ b/src/main/java/org/traccar/WrapperOutboundHandler.java
diff --git a/src/org/traccar/api/AsyncSocket.java b/src/main/java/org/traccar/api/AsyncSocket.java
index 906d16b5b..906d16b5b 100644
--- a/src/org/traccar/api/AsyncSocket.java
+++ b/src/main/java/org/traccar/api/AsyncSocket.java
diff --git a/src/org/traccar/api/AsyncSocketServlet.java b/src/main/java/org/traccar/api/AsyncSocketServlet.java
index 9318b6fc6..9318b6fc6 100644
--- a/src/org/traccar/api/AsyncSocketServlet.java
+++ b/src/main/java/org/traccar/api/AsyncSocketServlet.java
diff --git a/src/org/traccar/api/BaseObjectResource.java b/src/main/java/org/traccar/api/BaseObjectResource.java
index 7de6a3877..7de6a3877 100644
--- a/src/org/traccar/api/BaseObjectResource.java
+++ b/src/main/java/org/traccar/api/BaseObjectResource.java
diff --git a/src/org/traccar/api/BaseResource.java b/src/main/java/org/traccar/api/BaseResource.java
index cc272df9c..cc272df9c 100644
--- a/src/org/traccar/api/BaseResource.java
+++ b/src/main/java/org/traccar/api/BaseResource.java
diff --git a/src/org/traccar/api/CorsResponseFilter.java b/src/main/java/org/traccar/api/CorsResponseFilter.java
index 227f80609..227f80609 100644
--- a/src/org/traccar/api/CorsResponseFilter.java
+++ b/src/main/java/org/traccar/api/CorsResponseFilter.java
diff --git a/src/org/traccar/api/ExtendedObjectResource.java b/src/main/java/org/traccar/api/ExtendedObjectResource.java
index 007a7b1bd..007a7b1bd 100644
--- a/src/org/traccar/api/ExtendedObjectResource.java
+++ b/src/main/java/org/traccar/api/ExtendedObjectResource.java
diff --git a/src/org/traccar/api/MediaFilter.java b/src/main/java/org/traccar/api/MediaFilter.java
index 53539770f..53539770f 100644
--- a/src/org/traccar/api/MediaFilter.java
+++ b/src/main/java/org/traccar/api/MediaFilter.java
diff --git a/src/org/traccar/api/ObjectMapperProvider.java b/src/main/java/org/traccar/api/ObjectMapperProvider.java
index f81b20917..f81b20917 100644
--- a/src/org/traccar/api/ObjectMapperProvider.java
+++ b/src/main/java/org/traccar/api/ObjectMapperProvider.java
diff --git a/src/org/traccar/api/ResourceErrorHandler.java b/src/main/java/org/traccar/api/ResourceErrorHandler.java
index 1d618b08d..1d618b08d 100644
--- a/src/org/traccar/api/ResourceErrorHandler.java
+++ b/src/main/java/org/traccar/api/ResourceErrorHandler.java
diff --git a/src/org/traccar/api/SecurityRequestFilter.java b/src/main/java/org/traccar/api/SecurityRequestFilter.java
index 33b6b37df..33b6b37df 100644
--- a/src/org/traccar/api/SecurityRequestFilter.java
+++ b/src/main/java/org/traccar/api/SecurityRequestFilter.java
diff --git a/src/org/traccar/api/SimpleObjectResource.java b/src/main/java/org/traccar/api/SimpleObjectResource.java
index a7fcae0e7..a7fcae0e7 100644
--- a/src/org/traccar/api/SimpleObjectResource.java
+++ b/src/main/java/org/traccar/api/SimpleObjectResource.java
diff --git a/src/org/traccar/api/UserPrincipal.java b/src/main/java/org/traccar/api/UserPrincipal.java
index 80e92c2dd..80e92c2dd 100644
--- a/src/org/traccar/api/UserPrincipal.java
+++ b/src/main/java/org/traccar/api/UserPrincipal.java
diff --git a/src/org/traccar/api/UserSecurityContext.java b/src/main/java/org/traccar/api/UserSecurityContext.java
index 55c0621bc..55c0621bc 100644
--- a/src/org/traccar/api/UserSecurityContext.java
+++ b/src/main/java/org/traccar/api/UserSecurityContext.java
diff --git a/src/org/traccar/api/resource/AttributeResource.java b/src/main/java/org/traccar/api/resource/AttributeResource.java
index de69d871c..de69d871c 100644
--- a/src/org/traccar/api/resource/AttributeResource.java
+++ b/src/main/java/org/traccar/api/resource/AttributeResource.java
diff --git a/src/org/traccar/api/resource/CalendarResource.java b/src/main/java/org/traccar/api/resource/CalendarResource.java
index 9399c34a5..9399c34a5 100644
--- a/src/org/traccar/api/resource/CalendarResource.java
+++ b/src/main/java/org/traccar/api/resource/CalendarResource.java
diff --git a/src/org/traccar/api/resource/CommandResource.java b/src/main/java/org/traccar/api/resource/CommandResource.java
index 703638701..703638701 100644
--- a/src/org/traccar/api/resource/CommandResource.java
+++ b/src/main/java/org/traccar/api/resource/CommandResource.java
diff --git a/src/org/traccar/api/resource/DeviceResource.java b/src/main/java/org/traccar/api/resource/DeviceResource.java
index f9c9a139d..f9c9a139d 100644
--- a/src/org/traccar/api/resource/DeviceResource.java
+++ b/src/main/java/org/traccar/api/resource/DeviceResource.java
diff --git a/src/org/traccar/api/resource/DriverResource.java b/src/main/java/org/traccar/api/resource/DriverResource.java
index 91aa54c5e..91aa54c5e 100644
--- a/src/org/traccar/api/resource/DriverResource.java
+++ b/src/main/java/org/traccar/api/resource/DriverResource.java
diff --git a/src/org/traccar/api/resource/EventResource.java b/src/main/java/org/traccar/api/resource/EventResource.java
index e0ccf7020..e0ccf7020 100644
--- a/src/org/traccar/api/resource/EventResource.java
+++ b/src/main/java/org/traccar/api/resource/EventResource.java
diff --git a/src/org/traccar/api/resource/GeofenceResource.java b/src/main/java/org/traccar/api/resource/GeofenceResource.java
index 58f2c188c..58f2c188c 100644
--- a/src/org/traccar/api/resource/GeofenceResource.java
+++ b/src/main/java/org/traccar/api/resource/GeofenceResource.java
diff --git a/src/org/traccar/api/resource/GroupResource.java b/src/main/java/org/traccar/api/resource/GroupResource.java
index fcea15d0a..fcea15d0a 100644
--- a/src/org/traccar/api/resource/GroupResource.java
+++ b/src/main/java/org/traccar/api/resource/GroupResource.java
diff --git a/src/org/traccar/api/resource/MaintenanceResource.java b/src/main/java/org/traccar/api/resource/MaintenanceResource.java
index fa1b359ce..fa1b359ce 100644
--- a/src/org/traccar/api/resource/MaintenanceResource.java
+++ b/src/main/java/org/traccar/api/resource/MaintenanceResource.java
diff --git a/src/org/traccar/api/resource/NotificationResource.java b/src/main/java/org/traccar/api/resource/NotificationResource.java
index 9631a52b7..9631a52b7 100644
--- a/src/org/traccar/api/resource/NotificationResource.java
+++ b/src/main/java/org/traccar/api/resource/NotificationResource.java
diff --git a/src/org/traccar/api/resource/PermissionsResource.java b/src/main/java/org/traccar/api/resource/PermissionsResource.java
index b89d9d376..b89d9d376 100644
--- a/src/org/traccar/api/resource/PermissionsResource.java
+++ b/src/main/java/org/traccar/api/resource/PermissionsResource.java
diff --git a/src/org/traccar/api/resource/PositionResource.java b/src/main/java/org/traccar/api/resource/PositionResource.java
index c031b842f..c031b842f 100644
--- a/src/org/traccar/api/resource/PositionResource.java
+++ b/src/main/java/org/traccar/api/resource/PositionResource.java
diff --git a/src/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java
index d371cf987..d371cf987 100644
--- a/src/org/traccar/api/resource/ReportResource.java
+++ b/src/main/java/org/traccar/api/resource/ReportResource.java
diff --git a/src/org/traccar/api/resource/ServerResource.java b/src/main/java/org/traccar/api/resource/ServerResource.java
index e7cad2a0c..e7cad2a0c 100644
--- a/src/org/traccar/api/resource/ServerResource.java
+++ b/src/main/java/org/traccar/api/resource/ServerResource.java
diff --git a/src/org/traccar/api/resource/SessionResource.java b/src/main/java/org/traccar/api/resource/SessionResource.java
index fd331c766..fd331c766 100644
--- a/src/org/traccar/api/resource/SessionResource.java
+++ b/src/main/java/org/traccar/api/resource/SessionResource.java
diff --git a/src/org/traccar/api/resource/StatisticsResource.java b/src/main/java/org/traccar/api/resource/StatisticsResource.java
index e801d4ff3..e801d4ff3 100644
--- a/src/org/traccar/api/resource/StatisticsResource.java
+++ b/src/main/java/org/traccar/api/resource/StatisticsResource.java
diff --git a/src/org/traccar/api/resource/UserResource.java b/src/main/java/org/traccar/api/resource/UserResource.java
index 0b42d8d92..0b42d8d92 100644
--- a/src/org/traccar/api/resource/UserResource.java
+++ b/src/main/java/org/traccar/api/resource/UserResource.java
diff --git a/src/org/traccar/config/Config.java b/src/main/java/org/traccar/config/Config.java
index d8f2a0e99..d8f2a0e99 100644
--- a/src/org/traccar/config/Config.java
+++ b/src/main/java/org/traccar/config/Config.java
diff --git a/src/org/traccar/config/ConfigKey.java b/src/main/java/org/traccar/config/ConfigKey.java
index 2e54ad392..2e54ad392 100644
--- a/src/org/traccar/config/ConfigKey.java
+++ b/src/main/java/org/traccar/config/ConfigKey.java
diff --git a/src/org/traccar/config/ConfigSuffix.java b/src/main/java/org/traccar/config/ConfigSuffix.java
index 149b2cd00..149b2cd00 100644
--- a/src/org/traccar/config/ConfigSuffix.java
+++ b/src/main/java/org/traccar/config/ConfigSuffix.java
diff --git a/src/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java
index 48cf3e558..48cf3e558 100644
--- a/src/org/traccar/config/Keys.java
+++ b/src/main/java/org/traccar/config/Keys.java
diff --git a/src/org/traccar/database/ActiveDevice.java b/src/main/java/org/traccar/database/ActiveDevice.java
index 207fc454b..207fc454b 100644
--- a/src/org/traccar/database/ActiveDevice.java
+++ b/src/main/java/org/traccar/database/ActiveDevice.java
diff --git a/src/org/traccar/database/AttributesManager.java b/src/main/java/org/traccar/database/AttributesManager.java
index 28816645a..28816645a 100644
--- a/src/org/traccar/database/AttributesManager.java
+++ b/src/main/java/org/traccar/database/AttributesManager.java
diff --git a/src/org/traccar/database/BaseObjectManager.java b/src/main/java/org/traccar/database/BaseObjectManager.java
index 8bf9ef860..8bf9ef860 100644
--- a/src/org/traccar/database/BaseObjectManager.java
+++ b/src/main/java/org/traccar/database/BaseObjectManager.java
diff --git a/src/org/traccar/database/CalendarManager.java b/src/main/java/org/traccar/database/CalendarManager.java
index 44ced1082..44ced1082 100644
--- a/src/org/traccar/database/CalendarManager.java
+++ b/src/main/java/org/traccar/database/CalendarManager.java
diff --git a/src/org/traccar/database/CommandsManager.java b/src/main/java/org/traccar/database/CommandsManager.java
index d6fdd66ca..d6fdd66ca 100644
--- a/src/org/traccar/database/CommandsManager.java
+++ b/src/main/java/org/traccar/database/CommandsManager.java
diff --git a/src/org/traccar/database/ConnectionManager.java b/src/main/java/org/traccar/database/ConnectionManager.java
index 8bae1ea93..8bae1ea93 100644
--- a/src/org/traccar/database/ConnectionManager.java
+++ b/src/main/java/org/traccar/database/ConnectionManager.java
diff --git a/src/org/traccar/database/DataManager.java b/src/main/java/org/traccar/database/DataManager.java
index 8e9071736..8e9071736 100644
--- a/src/org/traccar/database/DataManager.java
+++ b/src/main/java/org/traccar/database/DataManager.java
diff --git a/src/org/traccar/database/DeviceManager.java b/src/main/java/org/traccar/database/DeviceManager.java
index de4607d1f..de4607d1f 100644
--- a/src/org/traccar/database/DeviceManager.java
+++ b/src/main/java/org/traccar/database/DeviceManager.java
diff --git a/src/org/traccar/database/DriversManager.java b/src/main/java/org/traccar/database/DriversManager.java
index 930951460..930951460 100644
--- a/src/org/traccar/database/DriversManager.java
+++ b/src/main/java/org/traccar/database/DriversManager.java
diff --git a/src/org/traccar/database/ExtendedObjectManager.java b/src/main/java/org/traccar/database/ExtendedObjectManager.java
index ceb85b537..ceb85b537 100644
--- a/src/org/traccar/database/ExtendedObjectManager.java
+++ b/src/main/java/org/traccar/database/ExtendedObjectManager.java
diff --git a/src/org/traccar/database/GeofenceManager.java b/src/main/java/org/traccar/database/GeofenceManager.java
index a32847cf9..a32847cf9 100644
--- a/src/org/traccar/database/GeofenceManager.java
+++ b/src/main/java/org/traccar/database/GeofenceManager.java
diff --git a/src/org/traccar/database/GroupTree.java b/src/main/java/org/traccar/database/GroupTree.java
index 8798f55bc..8798f55bc 100644
--- a/src/org/traccar/database/GroupTree.java
+++ b/src/main/java/org/traccar/database/GroupTree.java
diff --git a/src/org/traccar/database/GroupsManager.java b/src/main/java/org/traccar/database/GroupsManager.java
index d8404c614..d8404c614 100644
--- a/src/org/traccar/database/GroupsManager.java
+++ b/src/main/java/org/traccar/database/GroupsManager.java
diff --git a/src/org/traccar/database/IdentityManager.java b/src/main/java/org/traccar/database/IdentityManager.java
index 6228a0f75..6228a0f75 100644
--- a/src/org/traccar/database/IdentityManager.java
+++ b/src/main/java/org/traccar/database/IdentityManager.java
diff --git a/src/org/traccar/database/LdapProvider.java b/src/main/java/org/traccar/database/LdapProvider.java
index d8b5c9f52..d8b5c9f52 100644
--- a/src/org/traccar/database/LdapProvider.java
+++ b/src/main/java/org/traccar/database/LdapProvider.java
diff --git a/src/org/traccar/database/MailManager.java b/src/main/java/org/traccar/database/MailManager.java
index 8a2f002cd..8a2f002cd 100644
--- a/src/org/traccar/database/MailManager.java
+++ b/src/main/java/org/traccar/database/MailManager.java
diff --git a/src/org/traccar/database/MaintenancesManager.java b/src/main/java/org/traccar/database/MaintenancesManager.java
index 4e266cb78..4e266cb78 100644
--- a/src/org/traccar/database/MaintenancesManager.java
+++ b/src/main/java/org/traccar/database/MaintenancesManager.java
diff --git a/src/org/traccar/database/ManagableObjects.java b/src/main/java/org/traccar/database/ManagableObjects.java
index ec9549493..ec9549493 100644
--- a/src/org/traccar/database/ManagableObjects.java
+++ b/src/main/java/org/traccar/database/ManagableObjects.java
diff --git a/src/org/traccar/database/MediaManager.java b/src/main/java/org/traccar/database/MediaManager.java
index edade5766..edade5766 100644
--- a/src/org/traccar/database/MediaManager.java
+++ b/src/main/java/org/traccar/database/MediaManager.java
diff --git a/src/org/traccar/database/NotificationManager.java b/src/main/java/org/traccar/database/NotificationManager.java
index 09df4c571..09df4c571 100644
--- a/src/org/traccar/database/NotificationManager.java
+++ b/src/main/java/org/traccar/database/NotificationManager.java
diff --git a/src/org/traccar/database/PermissionsManager.java b/src/main/java/org/traccar/database/PermissionsManager.java
index ced0df1c0..ced0df1c0 100644
--- a/src/org/traccar/database/PermissionsManager.java
+++ b/src/main/java/org/traccar/database/PermissionsManager.java
diff --git a/src/org/traccar/database/QueryBuilder.java b/src/main/java/org/traccar/database/QueryBuilder.java
index 5528b2320..5528b2320 100644
--- a/src/org/traccar/database/QueryBuilder.java
+++ b/src/main/java/org/traccar/database/QueryBuilder.java
diff --git a/src/org/traccar/database/QueryExtended.java b/src/main/java/org/traccar/database/QueryExtended.java
index 07bc2c211..07bc2c211 100644
--- a/src/org/traccar/database/QueryExtended.java
+++ b/src/main/java/org/traccar/database/QueryExtended.java
diff --git a/src/org/traccar/database/QueryIgnore.java b/src/main/java/org/traccar/database/QueryIgnore.java
index ac835cf2f..ac835cf2f 100644
--- a/src/org/traccar/database/QueryIgnore.java
+++ b/src/main/java/org/traccar/database/QueryIgnore.java
diff --git a/src/org/traccar/database/SimpleObjectManager.java b/src/main/java/org/traccar/database/SimpleObjectManager.java
index 15dda4520..15dda4520 100644
--- a/src/org/traccar/database/SimpleObjectManager.java
+++ b/src/main/java/org/traccar/database/SimpleObjectManager.java
diff --git a/src/org/traccar/database/StatisticsManager.java b/src/main/java/org/traccar/database/StatisticsManager.java
index e59f8e767..e59f8e767 100644
--- a/src/org/traccar/database/StatisticsManager.java
+++ b/src/main/java/org/traccar/database/StatisticsManager.java
diff --git a/src/org/traccar/database/UsersManager.java b/src/main/java/org/traccar/database/UsersManager.java
index 576a9e6c7..576a9e6c7 100644
--- a/src/org/traccar/database/UsersManager.java
+++ b/src/main/java/org/traccar/database/UsersManager.java
diff --git a/src/org/traccar/geocoder/Address.java b/src/main/java/org/traccar/geocoder/Address.java
index fe39da8e1..fe39da8e1 100644
--- a/src/org/traccar/geocoder/Address.java
+++ b/src/main/java/org/traccar/geocoder/Address.java
diff --git a/src/org/traccar/geocoder/AddressFormat.java b/src/main/java/org/traccar/geocoder/AddressFormat.java
index ad19432b9..ad19432b9 100644
--- a/src/org/traccar/geocoder/AddressFormat.java
+++ b/src/main/java/org/traccar/geocoder/AddressFormat.java
diff --git a/src/org/traccar/geocoder/BanGeocoder.java b/src/main/java/org/traccar/geocoder/BanGeocoder.java
index b1f0900a4..b1f0900a4 100644
--- a/src/org/traccar/geocoder/BanGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/BanGeocoder.java
diff --git a/src/org/traccar/geocoder/BingMapsGeocoder.java b/src/main/java/org/traccar/geocoder/BingMapsGeocoder.java
index 32a26ee0c..32a26ee0c 100644
--- a/src/org/traccar/geocoder/BingMapsGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/BingMapsGeocoder.java
diff --git a/src/org/traccar/geocoder/FactualGeocoder.java b/src/main/java/org/traccar/geocoder/FactualGeocoder.java
index c7a68c293..c7a68c293 100644
--- a/src/org/traccar/geocoder/FactualGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/FactualGeocoder.java
diff --git a/src/org/traccar/geocoder/GeocodeFarmGeocoder.java b/src/main/java/org/traccar/geocoder/GeocodeFarmGeocoder.java
index 39a3300a0..39a3300a0 100644
--- a/src/org/traccar/geocoder/GeocodeFarmGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/GeocodeFarmGeocoder.java
diff --git a/src/org/traccar/geocoder/GeocodeXyzGeocoder.java b/src/main/java/org/traccar/geocoder/GeocodeXyzGeocoder.java
index aca360c3d..aca360c3d 100644
--- a/src/org/traccar/geocoder/GeocodeXyzGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/GeocodeXyzGeocoder.java
diff --git a/src/org/traccar/geocoder/Geocoder.java b/src/main/java/org/traccar/geocoder/Geocoder.java
index 587a27520..587a27520 100644
--- a/src/org/traccar/geocoder/Geocoder.java
+++ b/src/main/java/org/traccar/geocoder/Geocoder.java
diff --git a/src/org/traccar/geocoder/GeocoderException.java b/src/main/java/org/traccar/geocoder/GeocoderException.java
index 608916641..608916641 100644
--- a/src/org/traccar/geocoder/GeocoderException.java
+++ b/src/main/java/org/traccar/geocoder/GeocoderException.java
diff --git a/src/org/traccar/geocoder/GisgraphyGeocoder.java b/src/main/java/org/traccar/geocoder/GisgraphyGeocoder.java
index 3a173f985..3a173f985 100644
--- a/src/org/traccar/geocoder/GisgraphyGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/GisgraphyGeocoder.java
diff --git a/src/org/traccar/geocoder/GoogleGeocoder.java b/src/main/java/org/traccar/geocoder/GoogleGeocoder.java
index 9494cab45..9494cab45 100644
--- a/src/org/traccar/geocoder/GoogleGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/GoogleGeocoder.java
diff --git a/src/org/traccar/geocoder/HereGeocoder.java b/src/main/java/org/traccar/geocoder/HereGeocoder.java
index 756260b52..756260b52 100644
--- a/src/org/traccar/geocoder/HereGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/HereGeocoder.java
diff --git a/src/org/traccar/geocoder/JsonGeocoder.java b/src/main/java/org/traccar/geocoder/JsonGeocoder.java
index ed59a1d8d..ed59a1d8d 100644
--- a/src/org/traccar/geocoder/JsonGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/JsonGeocoder.java
diff --git a/src/org/traccar/geocoder/MapQuestGeocoder.java b/src/main/java/org/traccar/geocoder/MapQuestGeocoder.java
index 4029e3f07..4029e3f07 100644
--- a/src/org/traccar/geocoder/MapQuestGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/MapQuestGeocoder.java
diff --git a/src/org/traccar/geocoder/MapmyIndiaGeocoder.java b/src/main/java/org/traccar/geocoder/MapmyIndiaGeocoder.java
index 2b70708a1..2b70708a1 100644
--- a/src/org/traccar/geocoder/MapmyIndiaGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/MapmyIndiaGeocoder.java
diff --git a/src/org/traccar/geocoder/NominatimGeocoder.java b/src/main/java/org/traccar/geocoder/NominatimGeocoder.java
index 8db25bf15..8db25bf15 100644
--- a/src/org/traccar/geocoder/NominatimGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/NominatimGeocoder.java
diff --git a/src/org/traccar/geocoder/OpenCageGeocoder.java b/src/main/java/org/traccar/geocoder/OpenCageGeocoder.java
index 822b6e91e..822b6e91e 100644
--- a/src/org/traccar/geocoder/OpenCageGeocoder.java
+++ b/src/main/java/org/traccar/geocoder/OpenCageGeocoder.java
diff --git a/src/org/traccar/geofence/GeofenceCircle.java b/src/main/java/org/traccar/geofence/GeofenceCircle.java
index f6fca63ca..f6fca63ca 100644
--- a/src/org/traccar/geofence/GeofenceCircle.java
+++ b/src/main/java/org/traccar/geofence/GeofenceCircle.java
diff --git a/src/org/traccar/geofence/GeofenceGeometry.java b/src/main/java/org/traccar/geofence/GeofenceGeometry.java
index 857ba3414..857ba3414 100644
--- a/src/org/traccar/geofence/GeofenceGeometry.java
+++ b/src/main/java/org/traccar/geofence/GeofenceGeometry.java
diff --git a/src/org/traccar/geofence/GeofencePolygon.java b/src/main/java/org/traccar/geofence/GeofencePolygon.java
index 2048ba26d..2048ba26d 100644
--- a/src/org/traccar/geofence/GeofencePolygon.java
+++ b/src/main/java/org/traccar/geofence/GeofencePolygon.java
diff --git a/src/org/traccar/geofence/GeofencePolyline.java b/src/main/java/org/traccar/geofence/GeofencePolyline.java
index d84f512e3..d84f512e3 100644
--- a/src/org/traccar/geofence/GeofencePolyline.java
+++ b/src/main/java/org/traccar/geofence/GeofencePolyline.java
diff --git a/src/org/traccar/geolocation/GeolocationException.java b/src/main/java/org/traccar/geolocation/GeolocationException.java
index 5847cc807..5847cc807 100644
--- a/src/org/traccar/geolocation/GeolocationException.java
+++ b/src/main/java/org/traccar/geolocation/GeolocationException.java
diff --git a/src/org/traccar/geolocation/GeolocationProvider.java b/src/main/java/org/traccar/geolocation/GeolocationProvider.java
index d9dec6bbb..d9dec6bbb 100644
--- a/src/org/traccar/geolocation/GeolocationProvider.java
+++ b/src/main/java/org/traccar/geolocation/GeolocationProvider.java
diff --git a/src/org/traccar/geolocation/GoogleGeolocationProvider.java b/src/main/java/org/traccar/geolocation/GoogleGeolocationProvider.java
index 5901b47cd..5901b47cd 100644
--- a/src/org/traccar/geolocation/GoogleGeolocationProvider.java
+++ b/src/main/java/org/traccar/geolocation/GoogleGeolocationProvider.java
diff --git a/src/org/traccar/geolocation/MozillaGeolocationProvider.java b/src/main/java/org/traccar/geolocation/MozillaGeolocationProvider.java
index c6a73a52b..c6a73a52b 100644
--- a/src/org/traccar/geolocation/MozillaGeolocationProvider.java
+++ b/src/main/java/org/traccar/geolocation/MozillaGeolocationProvider.java
diff --git a/src/org/traccar/geolocation/OpenCellIdGeolocationProvider.java b/src/main/java/org/traccar/geolocation/OpenCellIdGeolocationProvider.java
index 768aaf6a2..768aaf6a2 100644
--- a/src/org/traccar/geolocation/OpenCellIdGeolocationProvider.java
+++ b/src/main/java/org/traccar/geolocation/OpenCellIdGeolocationProvider.java
diff --git a/src/org/traccar/geolocation/UniversalGeolocationProvider.java b/src/main/java/org/traccar/geolocation/UniversalGeolocationProvider.java
index f71620d8a..f71620d8a 100644
--- a/src/org/traccar/geolocation/UniversalGeolocationProvider.java
+++ b/src/main/java/org/traccar/geolocation/UniversalGeolocationProvider.java
diff --git a/src/org/traccar/geolocation/UnwiredGeolocationProvider.java b/src/main/java/org/traccar/geolocation/UnwiredGeolocationProvider.java
index 963bcb688..963bcb688 100644
--- a/src/org/traccar/geolocation/UnwiredGeolocationProvider.java
+++ b/src/main/java/org/traccar/geolocation/UnwiredGeolocationProvider.java
diff --git a/src/org/traccar/handler/ComputedAttributesHandler.java b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java
index 153da29b9..153da29b9 100644
--- a/src/org/traccar/handler/ComputedAttributesHandler.java
+++ b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java
diff --git a/src/org/traccar/handler/CopyAttributesHandler.java b/src/main/java/org/traccar/handler/CopyAttributesHandler.java
index 6a0966d33..6a0966d33 100644
--- a/src/org/traccar/handler/CopyAttributesHandler.java
+++ b/src/main/java/org/traccar/handler/CopyAttributesHandler.java
diff --git a/src/org/traccar/handler/DefaultDataHandler.java b/src/main/java/org/traccar/handler/DefaultDataHandler.java
index 9d8ea044d..9d8ea044d 100644
--- a/src/org/traccar/handler/DefaultDataHandler.java
+++ b/src/main/java/org/traccar/handler/DefaultDataHandler.java
diff --git a/src/org/traccar/handler/DistanceHandler.java b/src/main/java/org/traccar/handler/DistanceHandler.java
index a336a884e..a336a884e 100644
--- a/src/org/traccar/handler/DistanceHandler.java
+++ b/src/main/java/org/traccar/handler/DistanceHandler.java
diff --git a/src/org/traccar/handler/EngineHoursHandler.java b/src/main/java/org/traccar/handler/EngineHoursHandler.java
index 92da84e6b..92da84e6b 100644
--- a/src/org/traccar/handler/EngineHoursHandler.java
+++ b/src/main/java/org/traccar/handler/EngineHoursHandler.java
diff --git a/src/org/traccar/handler/FilterHandler.java b/src/main/java/org/traccar/handler/FilterHandler.java
index dceaede01..dceaede01 100644
--- a/src/org/traccar/handler/FilterHandler.java
+++ b/src/main/java/org/traccar/handler/FilterHandler.java
diff --git a/src/org/traccar/handler/GeocoderHandler.java b/src/main/java/org/traccar/handler/GeocoderHandler.java
index b96f01b3a..b96f01b3a 100644
--- a/src/org/traccar/handler/GeocoderHandler.java
+++ b/src/main/java/org/traccar/handler/GeocoderHandler.java
diff --git a/src/org/traccar/handler/GeolocationHandler.java b/src/main/java/org/traccar/handler/GeolocationHandler.java
index c7b39e491..c7b39e491 100644
--- a/src/org/traccar/handler/GeolocationHandler.java
+++ b/src/main/java/org/traccar/handler/GeolocationHandler.java
diff --git a/src/org/traccar/handler/HemisphereHandler.java b/src/main/java/org/traccar/handler/HemisphereHandler.java
index aff3d8a64..aff3d8a64 100644
--- a/src/org/traccar/handler/HemisphereHandler.java
+++ b/src/main/java/org/traccar/handler/HemisphereHandler.java
diff --git a/src/org/traccar/handler/MotionHandler.java b/src/main/java/org/traccar/handler/MotionHandler.java
index e8051dd75..e8051dd75 100644
--- a/src/org/traccar/handler/MotionHandler.java
+++ b/src/main/java/org/traccar/handler/MotionHandler.java
diff --git a/src/org/traccar/handler/NetworkMessageHandler.java b/src/main/java/org/traccar/handler/NetworkMessageHandler.java
index b1d926bfa..b1d926bfa 100644
--- a/src/org/traccar/handler/NetworkMessageHandler.java
+++ b/src/main/java/org/traccar/handler/NetworkMessageHandler.java
diff --git a/src/org/traccar/handler/OpenChannelHandler.java b/src/main/java/org/traccar/handler/OpenChannelHandler.java
index d09d617ab..d09d617ab 100644
--- a/src/org/traccar/handler/OpenChannelHandler.java
+++ b/src/main/java/org/traccar/handler/OpenChannelHandler.java
diff --git a/src/org/traccar/handler/RemoteAddressHandler.java b/src/main/java/org/traccar/handler/RemoteAddressHandler.java
index c09b8c39a..c09b8c39a 100644
--- a/src/org/traccar/handler/RemoteAddressHandler.java
+++ b/src/main/java/org/traccar/handler/RemoteAddressHandler.java
diff --git a/src/org/traccar/handler/StandardLoggingHandler.java b/src/main/java/org/traccar/handler/StandardLoggingHandler.java
index 88010458f..88010458f 100644
--- a/src/org/traccar/handler/StandardLoggingHandler.java
+++ b/src/main/java/org/traccar/handler/StandardLoggingHandler.java
diff --git a/src/org/traccar/handler/events/AlertEventHandler.java b/src/main/java/org/traccar/handler/events/AlertEventHandler.java
index 0b7c8d23e..0b7c8d23e 100644
--- a/src/org/traccar/handler/events/AlertEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/AlertEventHandler.java
diff --git a/src/org/traccar/handler/events/BaseEventHandler.java b/src/main/java/org/traccar/handler/events/BaseEventHandler.java
index 41f677f6c..41f677f6c 100644
--- a/src/org/traccar/handler/events/BaseEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/BaseEventHandler.java
diff --git a/src/org/traccar/handler/events/CommandResultEventHandler.java b/src/main/java/org/traccar/handler/events/CommandResultEventHandler.java
index cfe676653..cfe676653 100644
--- a/src/org/traccar/handler/events/CommandResultEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/CommandResultEventHandler.java
diff --git a/src/org/traccar/handler/events/DriverEventHandler.java b/src/main/java/org/traccar/handler/events/DriverEventHandler.java
index 994df93fa..994df93fa 100644
--- a/src/org/traccar/handler/events/DriverEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/DriverEventHandler.java
diff --git a/src/org/traccar/handler/events/FuelDropEventHandler.java b/src/main/java/org/traccar/handler/events/FuelDropEventHandler.java
index 59de61bba..59de61bba 100644
--- a/src/org/traccar/handler/events/FuelDropEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/FuelDropEventHandler.java
diff --git a/src/org/traccar/handler/events/GeofenceEventHandler.java b/src/main/java/org/traccar/handler/events/GeofenceEventHandler.java
index 067c97957..067c97957 100644
--- a/src/org/traccar/handler/events/GeofenceEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/GeofenceEventHandler.java
diff --git a/src/org/traccar/handler/events/IgnitionEventHandler.java b/src/main/java/org/traccar/handler/events/IgnitionEventHandler.java
index ec133bafc..ec133bafc 100644
--- a/src/org/traccar/handler/events/IgnitionEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/IgnitionEventHandler.java
diff --git a/src/org/traccar/handler/events/MaintenanceEventHandler.java b/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java
index 93ae74142..93ae74142 100644
--- a/src/org/traccar/handler/events/MaintenanceEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java
diff --git a/src/org/traccar/handler/events/MotionEventHandler.java b/src/main/java/org/traccar/handler/events/MotionEventHandler.java
index 9ec02ccfb..9ec02ccfb 100644
--- a/src/org/traccar/handler/events/MotionEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/MotionEventHandler.java
diff --git a/src/org/traccar/handler/events/OverspeedEventHandler.java b/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java
index 157bb64e0..157bb64e0 100644
--- a/src/org/traccar/handler/events/OverspeedEventHandler.java
+++ b/src/main/java/org/traccar/handler/events/OverspeedEventHandler.java
diff --git a/src/org/traccar/helper/BcdUtil.java b/src/main/java/org/traccar/helper/BcdUtil.java
index c87529e32..c87529e32 100644
--- a/src/org/traccar/helper/BcdUtil.java
+++ b/src/main/java/org/traccar/helper/BcdUtil.java
diff --git a/src/org/traccar/helper/BitBuffer.java b/src/main/java/org/traccar/helper/BitBuffer.java
index f30a4557b..f30a4557b 100644
--- a/src/org/traccar/helper/BitBuffer.java
+++ b/src/main/java/org/traccar/helper/BitBuffer.java
diff --git a/src/org/traccar/helper/BitUtil.java b/src/main/java/org/traccar/helper/BitUtil.java
index b6108edff..b6108edff 100644
--- a/src/org/traccar/helper/BitUtil.java
+++ b/src/main/java/org/traccar/helper/BitUtil.java
diff --git a/src/org/traccar/helper/BufferUtil.java b/src/main/java/org/traccar/helper/BufferUtil.java
index 15c619ec5..15c619ec5 100644
--- a/src/org/traccar/helper/BufferUtil.java
+++ b/src/main/java/org/traccar/helper/BufferUtil.java
diff --git a/src/org/traccar/helper/Checksum.java b/src/main/java/org/traccar/helper/Checksum.java
index adfa697c5..adfa697c5 100644
--- a/src/org/traccar/helper/Checksum.java
+++ b/src/main/java/org/traccar/helper/Checksum.java
diff --git a/src/org/traccar/helper/DataConverter.java b/src/main/java/org/traccar/helper/DataConverter.java
index 7abd4ae93..7abd4ae93 100644
--- a/src/org/traccar/helper/DataConverter.java
+++ b/src/main/java/org/traccar/helper/DataConverter.java
diff --git a/src/org/traccar/helper/DateBuilder.java b/src/main/java/org/traccar/helper/DateBuilder.java
index 6e1b779f0..6e1b779f0 100644
--- a/src/org/traccar/helper/DateBuilder.java
+++ b/src/main/java/org/traccar/helper/DateBuilder.java
diff --git a/src/org/traccar/helper/DateUtil.java b/src/main/java/org/traccar/helper/DateUtil.java
index 20a483e3c..20a483e3c 100644
--- a/src/org/traccar/helper/DateUtil.java
+++ b/src/main/java/org/traccar/helper/DateUtil.java
diff --git a/src/org/traccar/helper/DistanceCalculator.java b/src/main/java/org/traccar/helper/DistanceCalculator.java
index 88d4ef8a4..88d4ef8a4 100644
--- a/src/org/traccar/helper/DistanceCalculator.java
+++ b/src/main/java/org/traccar/helper/DistanceCalculator.java
diff --git a/src/org/traccar/helper/Hashing.java b/src/main/java/org/traccar/helper/Hashing.java
index e91310eda..e91310eda 100644
--- a/src/org/traccar/helper/Hashing.java
+++ b/src/main/java/org/traccar/helper/Hashing.java
diff --git a/src/org/traccar/helper/LocationTree.java b/src/main/java/org/traccar/helper/LocationTree.java
index 3aff3ce33..3aff3ce33 100644
--- a/src/org/traccar/helper/LocationTree.java
+++ b/src/main/java/org/traccar/helper/LocationTree.java
diff --git a/src/org/traccar/helper/Log.java b/src/main/java/org/traccar/helper/Log.java
index f328e8ce9..f328e8ce9 100644
--- a/src/org/traccar/helper/Log.java
+++ b/src/main/java/org/traccar/helper/Log.java
diff --git a/src/org/traccar/helper/LogAction.java b/src/main/java/org/traccar/helper/LogAction.java
index db13337b8..db13337b8 100644
--- a/src/org/traccar/helper/LogAction.java
+++ b/src/main/java/org/traccar/helper/LogAction.java
diff --git a/src/org/traccar/helper/ObdDecoder.java b/src/main/java/org/traccar/helper/ObdDecoder.java
index 1bdcce352..1bdcce352 100644
--- a/src/org/traccar/helper/ObdDecoder.java
+++ b/src/main/java/org/traccar/helper/ObdDecoder.java
diff --git a/src/org/traccar/helper/Parser.java b/src/main/java/org/traccar/helper/Parser.java
index 1471ec237..1471ec237 100644
--- a/src/org/traccar/helper/Parser.java
+++ b/src/main/java/org/traccar/helper/Parser.java
diff --git a/src/org/traccar/helper/PatternBuilder.java b/src/main/java/org/traccar/helper/PatternBuilder.java
index 5c4638189..5c4638189 100644
--- a/src/org/traccar/helper/PatternBuilder.java
+++ b/src/main/java/org/traccar/helper/PatternBuilder.java
diff --git a/src/org/traccar/helper/PatternUtil.java b/src/main/java/org/traccar/helper/PatternUtil.java
index 74813e1d9..74813e1d9 100644
--- a/src/org/traccar/helper/PatternUtil.java
+++ b/src/main/java/org/traccar/helper/PatternUtil.java
diff --git a/src/org/traccar/helper/SanitizerModule.java b/src/main/java/org/traccar/helper/SanitizerModule.java
index af9ac5c2b..af9ac5c2b 100644
--- a/src/org/traccar/helper/SanitizerModule.java
+++ b/src/main/java/org/traccar/helper/SanitizerModule.java
diff --git a/src/org/traccar/helper/UnitsConverter.java b/src/main/java/org/traccar/helper/UnitsConverter.java
index 3dd435df4..3dd435df4 100644
--- a/src/org/traccar/helper/UnitsConverter.java
+++ b/src/main/java/org/traccar/helper/UnitsConverter.java
diff --git a/src/org/traccar/model/Attribute.java b/src/main/java/org/traccar/model/Attribute.java
index 45d40b3ec..45d40b3ec 100644
--- a/src/org/traccar/model/Attribute.java
+++ b/src/main/java/org/traccar/model/Attribute.java
diff --git a/src/org/traccar/model/BaseModel.java b/src/main/java/org/traccar/model/BaseModel.java
index 8bdb916e8..8bdb916e8 100644
--- a/src/org/traccar/model/BaseModel.java
+++ b/src/main/java/org/traccar/model/BaseModel.java
diff --git a/src/org/traccar/model/Calendar.java b/src/main/java/org/traccar/model/Calendar.java
index 56d3eb74c..56d3eb74c 100644
--- a/src/org/traccar/model/Calendar.java
+++ b/src/main/java/org/traccar/model/Calendar.java
diff --git a/src/org/traccar/model/CellTower.java b/src/main/java/org/traccar/model/CellTower.java
index 6d1dfbd7f..6d1dfbd7f 100644
--- a/src/org/traccar/model/CellTower.java
+++ b/src/main/java/org/traccar/model/CellTower.java
diff --git a/src/org/traccar/model/Command.java b/src/main/java/org/traccar/model/Command.java
index 336fc61f4..336fc61f4 100644
--- a/src/org/traccar/model/Command.java
+++ b/src/main/java/org/traccar/model/Command.java
diff --git a/src/org/traccar/model/Device.java b/src/main/java/org/traccar/model/Device.java
index 0c9be932d..0c9be932d 100644
--- a/src/org/traccar/model/Device.java
+++ b/src/main/java/org/traccar/model/Device.java
diff --git a/src/org/traccar/model/DeviceAccumulators.java b/src/main/java/org/traccar/model/DeviceAccumulators.java
index 8a90826c4..8a90826c4 100644
--- a/src/org/traccar/model/DeviceAccumulators.java
+++ b/src/main/java/org/traccar/model/DeviceAccumulators.java
diff --git a/src/org/traccar/model/DeviceState.java b/src/main/java/org/traccar/model/DeviceState.java
index 75d6726ee..75d6726ee 100644
--- a/src/org/traccar/model/DeviceState.java
+++ b/src/main/java/org/traccar/model/DeviceState.java
diff --git a/src/org/traccar/model/Driver.java b/src/main/java/org/traccar/model/Driver.java
index 05f52fd4d..05f52fd4d 100644
--- a/src/org/traccar/model/Driver.java
+++ b/src/main/java/org/traccar/model/Driver.java
diff --git a/src/org/traccar/model/Event.java b/src/main/java/org/traccar/model/Event.java
index ee7fcc679..ee7fcc679 100644
--- a/src/org/traccar/model/Event.java
+++ b/src/main/java/org/traccar/model/Event.java
diff --git a/src/org/traccar/model/ExtendedModel.java b/src/main/java/org/traccar/model/ExtendedModel.java
index 8353d0e66..8353d0e66 100644
--- a/src/org/traccar/model/ExtendedModel.java
+++ b/src/main/java/org/traccar/model/ExtendedModel.java
diff --git a/src/org/traccar/model/Geofence.java b/src/main/java/org/traccar/model/Geofence.java
index 8560d22e9..8560d22e9 100644
--- a/src/org/traccar/model/Geofence.java
+++ b/src/main/java/org/traccar/model/Geofence.java
diff --git a/src/org/traccar/model/Group.java b/src/main/java/org/traccar/model/Group.java
index 91ea2319d..91ea2319d 100644
--- a/src/org/traccar/model/Group.java
+++ b/src/main/java/org/traccar/model/Group.java
diff --git a/src/org/traccar/model/GroupedModel.java b/src/main/java/org/traccar/model/GroupedModel.java
index 6b1aa75b1..6b1aa75b1 100644
--- a/src/org/traccar/model/GroupedModel.java
+++ b/src/main/java/org/traccar/model/GroupedModel.java
diff --git a/src/org/traccar/model/Maintenance.java b/src/main/java/org/traccar/model/Maintenance.java
index 73f67ea96..73f67ea96 100644
--- a/src/org/traccar/model/Maintenance.java
+++ b/src/main/java/org/traccar/model/Maintenance.java
diff --git a/src/org/traccar/model/ManagedUser.java b/src/main/java/org/traccar/model/ManagedUser.java
index 03c5ef48d..03c5ef48d 100644
--- a/src/org/traccar/model/ManagedUser.java
+++ b/src/main/java/org/traccar/model/ManagedUser.java
diff --git a/src/org/traccar/model/Message.java b/src/main/java/org/traccar/model/Message.java
index dad9c20f0..dad9c20f0 100644
--- a/src/org/traccar/model/Message.java
+++ b/src/main/java/org/traccar/model/Message.java
diff --git a/src/org/traccar/model/MiscFormatter.java b/src/main/java/org/traccar/model/MiscFormatter.java
index c6511f063..c6511f063 100644
--- a/src/org/traccar/model/MiscFormatter.java
+++ b/src/main/java/org/traccar/model/MiscFormatter.java
diff --git a/src/org/traccar/model/Network.java b/src/main/java/org/traccar/model/Network.java
index 2d56950f1..2d56950f1 100644
--- a/src/org/traccar/model/Network.java
+++ b/src/main/java/org/traccar/model/Network.java
diff --git a/src/org/traccar/model/Notification.java b/src/main/java/org/traccar/model/Notification.java
index f1983a03a..f1983a03a 100644
--- a/src/org/traccar/model/Notification.java
+++ b/src/main/java/org/traccar/model/Notification.java
diff --git a/src/org/traccar/model/Permission.java b/src/main/java/org/traccar/model/Permission.java
index 1006b1c47..1006b1c47 100644
--- a/src/org/traccar/model/Permission.java
+++ b/src/main/java/org/traccar/model/Permission.java
diff --git a/src/org/traccar/model/Position.java b/src/main/java/org/traccar/model/Position.java
index 4b327cbd2..4b327cbd2 100644
--- a/src/org/traccar/model/Position.java
+++ b/src/main/java/org/traccar/model/Position.java
diff --git a/src/org/traccar/model/ScheduledModel.java b/src/main/java/org/traccar/model/ScheduledModel.java
index 9e6a4b9a6..9e6a4b9a6 100644
--- a/src/org/traccar/model/ScheduledModel.java
+++ b/src/main/java/org/traccar/model/ScheduledModel.java
diff --git a/src/org/traccar/model/Server.java b/src/main/java/org/traccar/model/Server.java
index ad37e7078..ad37e7078 100644
--- a/src/org/traccar/model/Server.java
+++ b/src/main/java/org/traccar/model/Server.java
diff --git a/src/org/traccar/model/Statistics.java b/src/main/java/org/traccar/model/Statistics.java
index cb72c91dd..cb72c91dd 100644
--- a/src/org/traccar/model/Statistics.java
+++ b/src/main/java/org/traccar/model/Statistics.java
diff --git a/src/org/traccar/model/Typed.java b/src/main/java/org/traccar/model/Typed.java
index 313ec7bcd..313ec7bcd 100644
--- a/src/org/traccar/model/Typed.java
+++ b/src/main/java/org/traccar/model/Typed.java
diff --git a/src/org/traccar/model/User.java b/src/main/java/org/traccar/model/User.java
index 976b6aac0..976b6aac0 100644
--- a/src/org/traccar/model/User.java
+++ b/src/main/java/org/traccar/model/User.java
diff --git a/src/org/traccar/model/WifiAccessPoint.java b/src/main/java/org/traccar/model/WifiAccessPoint.java
index 87a77f3c0..87a77f3c0 100644
--- a/src/org/traccar/model/WifiAccessPoint.java
+++ b/src/main/java/org/traccar/model/WifiAccessPoint.java
diff --git a/src/org/traccar/notification/EventForwarder.java b/src/main/java/org/traccar/notification/EventForwarder.java
index c0010ebbd..c0010ebbd 100644
--- a/src/org/traccar/notification/EventForwarder.java
+++ b/src/main/java/org/traccar/notification/EventForwarder.java
diff --git a/src/org/traccar/notification/FullMessage.java b/src/main/java/org/traccar/notification/FullMessage.java
index f66537c6e..f66537c6e 100644
--- a/src/org/traccar/notification/FullMessage.java
+++ b/src/main/java/org/traccar/notification/FullMessage.java
diff --git a/src/org/traccar/notification/JsonTypeEventForwarder.java b/src/main/java/org/traccar/notification/JsonTypeEventForwarder.java
index fcafb964a..55d926fc8 100644
--- a/src/org/traccar/notification/JsonTypeEventForwarder.java
+++ b/src/main/java/org/traccar/notification/JsonTypeEventForwarder.java
@@ -1,18 +1,18 @@
-package org.traccar.notification;
-
-import java.util.Set;
-
-import org.traccar.model.Event;
-import org.traccar.model.Position;
-
-import javax.ws.rs.client.AsyncInvoker;
-import javax.ws.rs.client.Entity;
-
-public class JsonTypeEventForwarder extends EventForwarder {
-
- @Override
- protected void executeRequest(Event event, Position position, Set<Long> users, AsyncInvoker invoker) {
- invoker.post(Entity.json(preparePayload(event, position, users)));
- }
-
-}
+package org.traccar.notification;
+
+import java.util.Set;
+
+import org.traccar.model.Event;
+import org.traccar.model.Position;
+
+import javax.ws.rs.client.AsyncInvoker;
+import javax.ws.rs.client.Entity;
+
+public class JsonTypeEventForwarder extends EventForwarder {
+
+ @Override
+ protected void executeRequest(Event event, Position position, Set<Long> users, AsyncInvoker invoker) {
+ invoker.post(Entity.json(preparePayload(event, position, users)));
+ }
+
+}
diff --git a/src/org/traccar/notification/MessageException.java b/src/main/java/org/traccar/notification/MessageException.java
index 710b927b0..710b927b0 100644
--- a/src/org/traccar/notification/MessageException.java
+++ b/src/main/java/org/traccar/notification/MessageException.java
diff --git a/src/org/traccar/notification/NotificationFormatter.java b/src/main/java/org/traccar/notification/NotificationFormatter.java
index 2f8100226..2f8100226 100644
--- a/src/org/traccar/notification/NotificationFormatter.java
+++ b/src/main/java/org/traccar/notification/NotificationFormatter.java
diff --git a/src/org/traccar/notification/NotificatorManager.java b/src/main/java/org/traccar/notification/NotificatorManager.java
index a4080a38d..a4080a38d 100644
--- a/src/org/traccar/notification/NotificatorManager.java
+++ b/src/main/java/org/traccar/notification/NotificatorManager.java
diff --git a/src/org/traccar/notification/PropertiesProvider.java b/src/main/java/org/traccar/notification/PropertiesProvider.java
index f0078feef..f0078feef 100644
--- a/src/org/traccar/notification/PropertiesProvider.java
+++ b/src/main/java/org/traccar/notification/PropertiesProvider.java
diff --git a/src/org/traccar/notificators/Notificator.java b/src/main/java/org/traccar/notificators/Notificator.java
index 5e40971c6..5e40971c6 100644
--- a/src/org/traccar/notificators/Notificator.java
+++ b/src/main/java/org/traccar/notificators/Notificator.java
diff --git a/src/org/traccar/notificators/NotificatorFirebase.java b/src/main/java/org/traccar/notificators/NotificatorFirebase.java
index 75d325de2..75d325de2 100644
--- a/src/org/traccar/notificators/NotificatorFirebase.java
+++ b/src/main/java/org/traccar/notificators/NotificatorFirebase.java
diff --git a/src/org/traccar/notificators/NotificatorMail.java b/src/main/java/org/traccar/notificators/NotificatorMail.java
index 6b9774c58..6b9774c58 100644
--- a/src/org/traccar/notificators/NotificatorMail.java
+++ b/src/main/java/org/traccar/notificators/NotificatorMail.java
diff --git a/src/org/traccar/notificators/NotificatorNull.java b/src/main/java/org/traccar/notificators/NotificatorNull.java
index 9364336be..9364336be 100644
--- a/src/org/traccar/notificators/NotificatorNull.java
+++ b/src/main/java/org/traccar/notificators/NotificatorNull.java
diff --git a/src/org/traccar/notificators/NotificatorSms.java b/src/main/java/org/traccar/notificators/NotificatorSms.java
index d5c791eae..d5c791eae 100644
--- a/src/org/traccar/notificators/NotificatorSms.java
+++ b/src/main/java/org/traccar/notificators/NotificatorSms.java
diff --git a/src/org/traccar/notificators/NotificatorWeb.java b/src/main/java/org/traccar/notificators/NotificatorWeb.java
index 1d11c0b46..1d11c0b46 100644
--- a/src/org/traccar/notificators/NotificatorWeb.java
+++ b/src/main/java/org/traccar/notificators/NotificatorWeb.java
diff --git a/src/org/traccar/protocol/AdmProtocol.java b/src/main/java/org/traccar/protocol/AdmProtocol.java
index 08f932ceb..08f932ceb 100644
--- a/src/org/traccar/protocol/AdmProtocol.java
+++ b/src/main/java/org/traccar/protocol/AdmProtocol.java
diff --git a/src/org/traccar/protocol/AdmProtocolDecoder.java b/src/main/java/org/traccar/protocol/AdmProtocolDecoder.java
index 52d1439ed..52d1439ed 100644
--- a/src/org/traccar/protocol/AdmProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AdmProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AdmProtocolEncoder.java b/src/main/java/org/traccar/protocol/AdmProtocolEncoder.java
index e76bc2ddc..e76bc2ddc 100644
--- a/src/org/traccar/protocol/AdmProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/AdmProtocolEncoder.java
diff --git a/src/org/traccar/protocol/AisProtocol.java b/src/main/java/org/traccar/protocol/AisProtocol.java
index 3b9cad7c8..3b9cad7c8 100644
--- a/src/org/traccar/protocol/AisProtocol.java
+++ b/src/main/java/org/traccar/protocol/AisProtocol.java
diff --git a/src/org/traccar/protocol/AisProtocolDecoder.java b/src/main/java/org/traccar/protocol/AisProtocolDecoder.java
index 8970f3d4a..8970f3d4a 100644
--- a/src/org/traccar/protocol/AisProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AisProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AlematicsFrameDecoder.java b/src/main/java/org/traccar/protocol/AlematicsFrameDecoder.java
index be7666657..be7666657 100644
--- a/src/org/traccar/protocol/AlematicsFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/AlematicsFrameDecoder.java
diff --git a/src/org/traccar/protocol/AlematicsProtocol.java b/src/main/java/org/traccar/protocol/AlematicsProtocol.java
index 8da2356b9..8da2356b9 100644
--- a/src/org/traccar/protocol/AlematicsProtocol.java
+++ b/src/main/java/org/traccar/protocol/AlematicsProtocol.java
diff --git a/src/org/traccar/protocol/AlematicsProtocolDecoder.java b/src/main/java/org/traccar/protocol/AlematicsProtocolDecoder.java
index 25ccf6856..25ccf6856 100644
--- a/src/org/traccar/protocol/AlematicsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AlematicsProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AnytrekProtocol.java b/src/main/java/org/traccar/protocol/AnytrekProtocol.java
index 4ab5833f7..4ab5833f7 100644
--- a/src/org/traccar/protocol/AnytrekProtocol.java
+++ b/src/main/java/org/traccar/protocol/AnytrekProtocol.java
diff --git a/src/org/traccar/protocol/AnytrekProtocolDecoder.java b/src/main/java/org/traccar/protocol/AnytrekProtocolDecoder.java
index c48f59c90..c48f59c90 100644
--- a/src/org/traccar/protocol/AnytrekProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AnytrekProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ApelProtocol.java b/src/main/java/org/traccar/protocol/ApelProtocol.java
index 382aa16af..382aa16af 100644
--- a/src/org/traccar/protocol/ApelProtocol.java
+++ b/src/main/java/org/traccar/protocol/ApelProtocol.java
diff --git a/src/org/traccar/protocol/ApelProtocolDecoder.java b/src/main/java/org/traccar/protocol/ApelProtocolDecoder.java
index c95a0366a..c95a0366a 100644
--- a/src/org/traccar/protocol/ApelProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ApelProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AplicomFrameDecoder.java b/src/main/java/org/traccar/protocol/AplicomFrameDecoder.java
index 6e81e8202..56fca27c7 100644
--- a/src/org/traccar/protocol/AplicomFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/AplicomFrameDecoder.java
@@ -1,62 +1,62 @@
-/*
- * Copyright 2013 Anton Tananaev (anton@traccar.org)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.traccar.protocol;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandlerContext;
-import org.traccar.BaseFrameDecoder;
-
-public class AplicomFrameDecoder extends BaseFrameDecoder {
-
- @Override
- protected Object decode(
- ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception {
-
- // Skip Alive message
- while (buf.isReadable() && Character.isDigit(buf.getByte(buf.readerIndex()))) {
- buf.readByte();
- }
-
- // Check minimum length
- if (buf.readableBytes() < 11) {
- return null;
- }
-
- // Read flags
- int version = buf.getUnsignedByte(buf.readerIndex() + 1);
- int offset = 1 + 1 + 3;
- if ((version & 0x80) != 0) {
- offset += 4;
- }
-
- // Get data length
- int length = buf.getUnsignedShort(buf.readerIndex() + offset);
- offset += 2;
- if ((version & 0x40) != 0) {
- offset += 3;
- }
- length += offset; // add header
-
- // Return buffer
- if (buf.readableBytes() >= length) {
- return buf.readRetainedSlice(length);
- }
-
- return null;
- }
-
-}
+/*
+ * Copyright 2013 Anton Tananaev (anton@traccar.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import org.traccar.BaseFrameDecoder;
+
+public class AplicomFrameDecoder extends BaseFrameDecoder {
+
+ @Override
+ protected Object decode(
+ ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception {
+
+ // Skip Alive message
+ while (buf.isReadable() && Character.isDigit(buf.getByte(buf.readerIndex()))) {
+ buf.readByte();
+ }
+
+ // Check minimum length
+ if (buf.readableBytes() < 11) {
+ return null;
+ }
+
+ // Read flags
+ int version = buf.getUnsignedByte(buf.readerIndex() + 1);
+ int offset = 1 + 1 + 3;
+ if ((version & 0x80) != 0) {
+ offset += 4;
+ }
+
+ // Get data length
+ int length = buf.getUnsignedShort(buf.readerIndex() + offset);
+ offset += 2;
+ if ((version & 0x40) != 0) {
+ offset += 3;
+ }
+ length += offset; // add header
+
+ // Return buffer
+ if (buf.readableBytes() >= length) {
+ return buf.readRetainedSlice(length);
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/org/traccar/protocol/AplicomProtocol.java b/src/main/java/org/traccar/protocol/AplicomProtocol.java
index 2b9dbf97c..2b9dbf97c 100644
--- a/src/org/traccar/protocol/AplicomProtocol.java
+++ b/src/main/java/org/traccar/protocol/AplicomProtocol.java
diff --git a/src/org/traccar/protocol/AplicomProtocolDecoder.java b/src/main/java/org/traccar/protocol/AplicomProtocolDecoder.java
index 215aa0211..215aa0211 100644
--- a/src/org/traccar/protocol/AplicomProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AplicomProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AppelloProtocol.java b/src/main/java/org/traccar/protocol/AppelloProtocol.java
index 1ca4168e4..1ca4168e4 100644
--- a/src/org/traccar/protocol/AppelloProtocol.java
+++ b/src/main/java/org/traccar/protocol/AppelloProtocol.java
diff --git a/src/org/traccar/protocol/AppelloProtocolDecoder.java b/src/main/java/org/traccar/protocol/AppelloProtocolDecoder.java
index 47e329234..47e329234 100644
--- a/src/org/traccar/protocol/AppelloProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AppelloProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AppletProtocol.java b/src/main/java/org/traccar/protocol/AppletProtocol.java
index 2297dca03..2297dca03 100644
--- a/src/org/traccar/protocol/AppletProtocol.java
+++ b/src/main/java/org/traccar/protocol/AppletProtocol.java
diff --git a/src/org/traccar/protocol/AppletProtocolDecoder.java b/src/main/java/org/traccar/protocol/AppletProtocolDecoder.java
index 7a995cc24..7a995cc24 100644
--- a/src/org/traccar/protocol/AppletProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AppletProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AquilaProtocol.java b/src/main/java/org/traccar/protocol/AquilaProtocol.java
index 5ca1ec091..5ca1ec091 100644
--- a/src/org/traccar/protocol/AquilaProtocol.java
+++ b/src/main/java/org/traccar/protocol/AquilaProtocol.java
diff --git a/src/org/traccar/protocol/AquilaProtocolDecoder.java b/src/main/java/org/traccar/protocol/AquilaProtocolDecoder.java
index 57af5e366..57af5e366 100644
--- a/src/org/traccar/protocol/AquilaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AquilaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Ardi01Protocol.java b/src/main/java/org/traccar/protocol/Ardi01Protocol.java
index f7826430f..f7826430f 100644
--- a/src/org/traccar/protocol/Ardi01Protocol.java
+++ b/src/main/java/org/traccar/protocol/Ardi01Protocol.java
diff --git a/src/org/traccar/protocol/Ardi01ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Ardi01ProtocolDecoder.java
index 85e9ecfde..85e9ecfde 100644
--- a/src/org/traccar/protocol/Ardi01ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Ardi01ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ArknavProtocol.java b/src/main/java/org/traccar/protocol/ArknavProtocol.java
index 3b485e4a5..3b485e4a5 100644
--- a/src/org/traccar/protocol/ArknavProtocol.java
+++ b/src/main/java/org/traccar/protocol/ArknavProtocol.java
diff --git a/src/org/traccar/protocol/ArknavProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArknavProtocolDecoder.java
index 4982e02fc..4982e02fc 100644
--- a/src/org/traccar/protocol/ArknavProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ArknavProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ArknavX8Protocol.java b/src/main/java/org/traccar/protocol/ArknavX8Protocol.java
index a29bc1ad3..a29bc1ad3 100644
--- a/src/org/traccar/protocol/ArknavX8Protocol.java
+++ b/src/main/java/org/traccar/protocol/ArknavX8Protocol.java
diff --git a/src/org/traccar/protocol/ArknavX8ProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArknavX8ProtocolDecoder.java
index b570f5423..b570f5423 100644
--- a/src/org/traccar/protocol/ArknavX8ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ArknavX8ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ArnaviProtocol.java b/src/main/java/org/traccar/protocol/ArnaviProtocol.java
index afe491865..afe491865 100644
--- a/src/org/traccar/protocol/ArnaviProtocol.java
+++ b/src/main/java/org/traccar/protocol/ArnaviProtocol.java
diff --git a/src/org/traccar/protocol/ArnaviProtocolDecoder.java b/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java
index 7996cf429..7996cf429 100644
--- a/src/org/traccar/protocol/ArnaviProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ArnaviProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AstraProtocol.java b/src/main/java/org/traccar/protocol/AstraProtocol.java
index 12b0dfb68..12b0dfb68 100644
--- a/src/org/traccar/protocol/AstraProtocol.java
+++ b/src/main/java/org/traccar/protocol/AstraProtocol.java
diff --git a/src/org/traccar/protocol/AstraProtocolDecoder.java b/src/main/java/org/traccar/protocol/AstraProtocolDecoder.java
index e6f546b9f..e6f546b9f 100644
--- a/src/org/traccar/protocol/AstraProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AstraProtocolDecoder.java
diff --git a/src/org/traccar/protocol/At2000FrameDecoder.java b/src/main/java/org/traccar/protocol/At2000FrameDecoder.java
index 5fa82a5f7..5fa82a5f7 100644
--- a/src/org/traccar/protocol/At2000FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/At2000FrameDecoder.java
diff --git a/src/org/traccar/protocol/At2000Protocol.java b/src/main/java/org/traccar/protocol/At2000Protocol.java
index 5894f3eab..5894f3eab 100644
--- a/src/org/traccar/protocol/At2000Protocol.java
+++ b/src/main/java/org/traccar/protocol/At2000Protocol.java
diff --git a/src/org/traccar/protocol/At2000ProtocolDecoder.java b/src/main/java/org/traccar/protocol/At2000ProtocolDecoder.java
index 43798eb67..43798eb67 100644
--- a/src/org/traccar/protocol/At2000ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/At2000ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AtrackFrameDecoder.java b/src/main/java/org/traccar/protocol/AtrackFrameDecoder.java
index f071e2d97..f071e2d97 100644
--- a/src/org/traccar/protocol/AtrackFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/AtrackFrameDecoder.java
diff --git a/src/org/traccar/protocol/AtrackProtocol.java b/src/main/java/org/traccar/protocol/AtrackProtocol.java
index 8e5cfe9ff..8e5cfe9ff 100644
--- a/src/org/traccar/protocol/AtrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/AtrackProtocol.java
diff --git a/src/org/traccar/protocol/AtrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java
index 71bb6791c..71bb6791c 100644
--- a/src/org/traccar/protocol/AtrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AtrackProtocolEncoder.java b/src/main/java/org/traccar/protocol/AtrackProtocolEncoder.java
index 1e085cb26..1e085cb26 100644
--- a/src/org/traccar/protocol/AtrackProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/AtrackProtocolEncoder.java
diff --git a/src/org/traccar/protocol/AuroProtocol.java b/src/main/java/org/traccar/protocol/AuroProtocol.java
index b8ebdaa75..b8ebdaa75 100644
--- a/src/org/traccar/protocol/AuroProtocol.java
+++ b/src/main/java/org/traccar/protocol/AuroProtocol.java
diff --git a/src/org/traccar/protocol/AuroProtocolDecoder.java b/src/main/java/org/traccar/protocol/AuroProtocolDecoder.java
index d7916147b..d7916147b 100644
--- a/src/org/traccar/protocol/AuroProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AuroProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AustinNbProtocol.java b/src/main/java/org/traccar/protocol/AustinNbProtocol.java
index 32bfc0aae..32bfc0aae 100644
--- a/src/org/traccar/protocol/AustinNbProtocol.java
+++ b/src/main/java/org/traccar/protocol/AustinNbProtocol.java
diff --git a/src/org/traccar/protocol/AustinNbProtocolDecoder.java b/src/main/java/org/traccar/protocol/AustinNbProtocolDecoder.java
index dc6f3d280..dc6f3d280 100644
--- a/src/org/traccar/protocol/AustinNbProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AustinNbProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AutoFonFrameDecoder.java b/src/main/java/org/traccar/protocol/AutoFonFrameDecoder.java
index 69f28133f..69f28133f 100644
--- a/src/org/traccar/protocol/AutoFonFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/AutoFonFrameDecoder.java
diff --git a/src/org/traccar/protocol/AutoFonProtocol.java b/src/main/java/org/traccar/protocol/AutoFonProtocol.java
index 08b5edc7d..08b5edc7d 100644
--- a/src/org/traccar/protocol/AutoFonProtocol.java
+++ b/src/main/java/org/traccar/protocol/AutoFonProtocol.java
diff --git a/src/org/traccar/protocol/AutoFonProtocolDecoder.java b/src/main/java/org/traccar/protocol/AutoFonProtocolDecoder.java
index aa05ca2d7..aa05ca2d7 100644
--- a/src/org/traccar/protocol/AutoFonProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AutoFonProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AutoGradeProtocol.java b/src/main/java/org/traccar/protocol/AutoGradeProtocol.java
index c6dbb681e..c6dbb681e 100644
--- a/src/org/traccar/protocol/AutoGradeProtocol.java
+++ b/src/main/java/org/traccar/protocol/AutoGradeProtocol.java
diff --git a/src/org/traccar/protocol/AutoGradeProtocolDecoder.java b/src/main/java/org/traccar/protocol/AutoGradeProtocolDecoder.java
index 5052450b5..5052450b5 100644
--- a/src/org/traccar/protocol/AutoGradeProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AutoGradeProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AutoTrackProtocol.java b/src/main/java/org/traccar/protocol/AutoTrackProtocol.java
index 6aa7558bf..6aa7558bf 100644
--- a/src/org/traccar/protocol/AutoTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/AutoTrackProtocol.java
diff --git a/src/org/traccar/protocol/AutoTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/AutoTrackProtocolDecoder.java
index 3c1fd256b..3c1fd256b 100644
--- a/src/org/traccar/protocol/AutoTrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AutoTrackProtocolDecoder.java
diff --git a/src/org/traccar/protocol/AvemaProtocol.java b/src/main/java/org/traccar/protocol/AvemaProtocol.java
index dbfab4dea..dbfab4dea 100644
--- a/src/org/traccar/protocol/AvemaProtocol.java
+++ b/src/main/java/org/traccar/protocol/AvemaProtocol.java
diff --git a/src/org/traccar/protocol/AvemaProtocolDecoder.java b/src/main/java/org/traccar/protocol/AvemaProtocolDecoder.java
index 16a31162a..16a31162a 100644
--- a/src/org/traccar/protocol/AvemaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/AvemaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Avl301Protocol.java b/src/main/java/org/traccar/protocol/Avl301Protocol.java
index 71fc7cb26..71fc7cb26 100644
--- a/src/org/traccar/protocol/Avl301Protocol.java
+++ b/src/main/java/org/traccar/protocol/Avl301Protocol.java
diff --git a/src/org/traccar/protocol/Avl301ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Avl301ProtocolDecoder.java
index f6b7db2d6..f6b7db2d6 100644
--- a/src/org/traccar/protocol/Avl301ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Avl301ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/BceFrameDecoder.java b/src/main/java/org/traccar/protocol/BceFrameDecoder.java
index 381a97696..381a97696 100644
--- a/src/org/traccar/protocol/BceFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/BceFrameDecoder.java
diff --git a/src/org/traccar/protocol/BceProtocol.java b/src/main/java/org/traccar/protocol/BceProtocol.java
index 6453a05a9..6453a05a9 100644
--- a/src/org/traccar/protocol/BceProtocol.java
+++ b/src/main/java/org/traccar/protocol/BceProtocol.java
diff --git a/src/org/traccar/protocol/BceProtocolDecoder.java b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java
index ed810bebb..ed810bebb 100644
--- a/src/org/traccar/protocol/BceProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/BceProtocolDecoder.java
diff --git a/src/org/traccar/protocol/BceProtocolEncoder.java b/src/main/java/org/traccar/protocol/BceProtocolEncoder.java
index 1bbf3db12..1bbf3db12 100644
--- a/src/org/traccar/protocol/BceProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/BceProtocolEncoder.java
diff --git a/src/org/traccar/protocol/BlackKiteProtocol.java b/src/main/java/org/traccar/protocol/BlackKiteProtocol.java
index 617a24d7a..617a24d7a 100644
--- a/src/org/traccar/protocol/BlackKiteProtocol.java
+++ b/src/main/java/org/traccar/protocol/BlackKiteProtocol.java
diff --git a/src/org/traccar/protocol/BlackKiteProtocolDecoder.java b/src/main/java/org/traccar/protocol/BlackKiteProtocolDecoder.java
index dca4b908a..dca4b908a 100644
--- a/src/org/traccar/protocol/BlackKiteProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/BlackKiteProtocolDecoder.java
diff --git a/src/org/traccar/protocol/BoxProtocol.java b/src/main/java/org/traccar/protocol/BoxProtocol.java
index dfea15938..dfea15938 100644
--- a/src/org/traccar/protocol/BoxProtocol.java
+++ b/src/main/java/org/traccar/protocol/BoxProtocol.java
diff --git a/src/org/traccar/protocol/BoxProtocolDecoder.java b/src/main/java/org/traccar/protocol/BoxProtocolDecoder.java
index 3635c29e5..3635c29e5 100644
--- a/src/org/traccar/protocol/BoxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/BoxProtocolDecoder.java
diff --git a/src/org/traccar/protocol/C2stekProtocol.java b/src/main/java/org/traccar/protocol/C2stekProtocol.java
index 804621fd3..804621fd3 100644
--- a/src/org/traccar/protocol/C2stekProtocol.java
+++ b/src/main/java/org/traccar/protocol/C2stekProtocol.java
diff --git a/src/org/traccar/protocol/C2stekProtocolDecoder.java b/src/main/java/org/traccar/protocol/C2stekProtocolDecoder.java
index 6a31cb2f4..6a31cb2f4 100644
--- a/src/org/traccar/protocol/C2stekProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/C2stekProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CalAmpProtocol.java b/src/main/java/org/traccar/protocol/CalAmpProtocol.java
index 232e72a8c..232e72a8c 100644
--- a/src/org/traccar/protocol/CalAmpProtocol.java
+++ b/src/main/java/org/traccar/protocol/CalAmpProtocol.java
diff --git a/src/org/traccar/protocol/CalAmpProtocolDecoder.java b/src/main/java/org/traccar/protocol/CalAmpProtocolDecoder.java
index 31416d7f1..31416d7f1 100644
--- a/src/org/traccar/protocol/CalAmpProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CalAmpProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CarTrackProtocol.java b/src/main/java/org/traccar/protocol/CarTrackProtocol.java
index e340fba25..e340fba25 100644
--- a/src/org/traccar/protocol/CarTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/CarTrackProtocol.java
diff --git a/src/org/traccar/protocol/CarTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/CarTrackProtocolDecoder.java
index ce3345826..ce3345826 100644
--- a/src/org/traccar/protocol/CarTrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CarTrackProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CarcellProtocol.java b/src/main/java/org/traccar/protocol/CarcellProtocol.java
index 0c305efcb..0c305efcb 100644
--- a/src/org/traccar/protocol/CarcellProtocol.java
+++ b/src/main/java/org/traccar/protocol/CarcellProtocol.java
diff --git a/src/org/traccar/protocol/CarcellProtocolDecoder.java b/src/main/java/org/traccar/protocol/CarcellProtocolDecoder.java
index 344b2f1ea..344b2f1ea 100644
--- a/src/org/traccar/protocol/CarcellProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CarcellProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CarcellProtocolEncoder.java b/src/main/java/org/traccar/protocol/CarcellProtocolEncoder.java
index e8f0081a0..e8f0081a0 100644
--- a/src/org/traccar/protocol/CarcellProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/CarcellProtocolEncoder.java
diff --git a/src/org/traccar/protocol/CarscopProtocol.java b/src/main/java/org/traccar/protocol/CarscopProtocol.java
index 2c754a97f..2c754a97f 100644
--- a/src/org/traccar/protocol/CarscopProtocol.java
+++ b/src/main/java/org/traccar/protocol/CarscopProtocol.java
diff --git a/src/org/traccar/protocol/CarscopProtocolDecoder.java b/src/main/java/org/traccar/protocol/CarscopProtocolDecoder.java
index 161666adc..161666adc 100644
--- a/src/org/traccar/protocol/CarscopProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CarscopProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CastelProtocol.java b/src/main/java/org/traccar/protocol/CastelProtocol.java
index 9b854afc3..9b854afc3 100644
--- a/src/org/traccar/protocol/CastelProtocol.java
+++ b/src/main/java/org/traccar/protocol/CastelProtocol.java
diff --git a/src/org/traccar/protocol/CastelProtocolDecoder.java b/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java
index 0541adf6f..0541adf6f 100644
--- a/src/org/traccar/protocol/CastelProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CastelProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CastelProtocolEncoder.java b/src/main/java/org/traccar/protocol/CastelProtocolEncoder.java
index e1f78e7c1..e1f78e7c1 100644
--- a/src/org/traccar/protocol/CastelProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/CastelProtocolEncoder.java
diff --git a/src/org/traccar/protocol/CautelaProtocol.java b/src/main/java/org/traccar/protocol/CautelaProtocol.java
index 452bdf8d4..452bdf8d4 100644
--- a/src/org/traccar/protocol/CautelaProtocol.java
+++ b/src/main/java/org/traccar/protocol/CautelaProtocol.java
diff --git a/src/org/traccar/protocol/CautelaProtocolDecoder.java b/src/main/java/org/traccar/protocol/CautelaProtocolDecoder.java
index bddf19b41..bddf19b41 100644
--- a/src/org/traccar/protocol/CautelaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CautelaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CellocatorFrameDecoder.java b/src/main/java/org/traccar/protocol/CellocatorFrameDecoder.java
index 7d5499d92..7d5499d92 100644
--- a/src/org/traccar/protocol/CellocatorFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/CellocatorFrameDecoder.java
diff --git a/src/org/traccar/protocol/CellocatorProtocol.java b/src/main/java/org/traccar/protocol/CellocatorProtocol.java
index a52170dc9..a52170dc9 100644
--- a/src/org/traccar/protocol/CellocatorProtocol.java
+++ b/src/main/java/org/traccar/protocol/CellocatorProtocol.java
diff --git a/src/org/traccar/protocol/CellocatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java
index d23f76a93..d23f76a93 100644
--- a/src/org/traccar/protocol/CellocatorProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CellocatorProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CellocatorProtocolEncoder.java b/src/main/java/org/traccar/protocol/CellocatorProtocolEncoder.java
index 0382dbbc7..0382dbbc7 100644
--- a/src/org/traccar/protocol/CellocatorProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/CellocatorProtocolEncoder.java
diff --git a/src/org/traccar/protocol/CguardProtocol.java b/src/main/java/org/traccar/protocol/CguardProtocol.java
index 9157ca35c..9157ca35c 100644
--- a/src/org/traccar/protocol/CguardProtocol.java
+++ b/src/main/java/org/traccar/protocol/CguardProtocol.java
diff --git a/src/org/traccar/protocol/CguardProtocolDecoder.java b/src/main/java/org/traccar/protocol/CguardProtocolDecoder.java
index d934921f1..d934921f1 100644
--- a/src/org/traccar/protocol/CguardProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CguardProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CityeasyProtocol.java b/src/main/java/org/traccar/protocol/CityeasyProtocol.java
index f4b49c9ff..f4b49c9ff 100644
--- a/src/org/traccar/protocol/CityeasyProtocol.java
+++ b/src/main/java/org/traccar/protocol/CityeasyProtocol.java
diff --git a/src/org/traccar/protocol/CityeasyProtocolDecoder.java b/src/main/java/org/traccar/protocol/CityeasyProtocolDecoder.java
index 9c4c7e11d..9c4c7e11d 100644
--- a/src/org/traccar/protocol/CityeasyProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CityeasyProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CityeasyProtocolEncoder.java b/src/main/java/org/traccar/protocol/CityeasyProtocolEncoder.java
index 350fdf0ab..350fdf0ab 100644
--- a/src/org/traccar/protocol/CityeasyProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/CityeasyProtocolEncoder.java
diff --git a/src/org/traccar/protocol/ContinentalProtocol.java b/src/main/java/org/traccar/protocol/ContinentalProtocol.java
index bc7928fba..bc7928fba 100644
--- a/src/org/traccar/protocol/ContinentalProtocol.java
+++ b/src/main/java/org/traccar/protocol/ContinentalProtocol.java
diff --git a/src/org/traccar/protocol/ContinentalProtocolDecoder.java b/src/main/java/org/traccar/protocol/ContinentalProtocolDecoder.java
index 471afa0d6..471afa0d6 100644
--- a/src/org/traccar/protocol/ContinentalProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ContinentalProtocolDecoder.java
diff --git a/src/org/traccar/protocol/CradlepointProtocol.java b/src/main/java/org/traccar/protocol/CradlepointProtocol.java
index 4a09e0311..4a09e0311 100644
--- a/src/org/traccar/protocol/CradlepointProtocol.java
+++ b/src/main/java/org/traccar/protocol/CradlepointProtocol.java
diff --git a/src/org/traccar/protocol/CradlepointProtocolDecoder.java b/src/main/java/org/traccar/protocol/CradlepointProtocolDecoder.java
index a282131ce..a282131ce 100644
--- a/src/org/traccar/protocol/CradlepointProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/CradlepointProtocolDecoder.java
diff --git a/src/org/traccar/protocol/DishaProtocol.java b/src/main/java/org/traccar/protocol/DishaProtocol.java
index 38f49cc05..38f49cc05 100644
--- a/src/org/traccar/protocol/DishaProtocol.java
+++ b/src/main/java/org/traccar/protocol/DishaProtocol.java
diff --git a/src/org/traccar/protocol/DishaProtocolDecoder.java b/src/main/java/org/traccar/protocol/DishaProtocolDecoder.java
index 3223988ab..3223988ab 100644
--- a/src/org/traccar/protocol/DishaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/DishaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/DmtHttpProtocol.java b/src/main/java/org/traccar/protocol/DmtHttpProtocol.java
index 34568128f..34568128f 100644
--- a/src/org/traccar/protocol/DmtHttpProtocol.java
+++ b/src/main/java/org/traccar/protocol/DmtHttpProtocol.java
diff --git a/src/org/traccar/protocol/DmtHttpProtocolDecoder.java b/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java
index 987361baf..987361baf 100644
--- a/src/org/traccar/protocol/DmtHttpProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java
diff --git a/src/org/traccar/protocol/DmtProtocol.java b/src/main/java/org/traccar/protocol/DmtProtocol.java
index 78a5243c0..78a5243c0 100644
--- a/src/org/traccar/protocol/DmtProtocol.java
+++ b/src/main/java/org/traccar/protocol/DmtProtocol.java
diff --git a/src/org/traccar/protocol/DmtProtocolDecoder.java b/src/main/java/org/traccar/protocol/DmtProtocolDecoder.java
index c04e90f1d..c04e90f1d 100644
--- a/src/org/traccar/protocol/DmtProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/DmtProtocolDecoder.java
diff --git a/src/org/traccar/protocol/DwayProtocol.java b/src/main/java/org/traccar/protocol/DwayProtocol.java
index 05fd8b6e7..05fd8b6e7 100644
--- a/src/org/traccar/protocol/DwayProtocol.java
+++ b/src/main/java/org/traccar/protocol/DwayProtocol.java
diff --git a/src/org/traccar/protocol/DwayProtocolDecoder.java b/src/main/java/org/traccar/protocol/DwayProtocolDecoder.java
index 9b02c898e..9b02c898e 100644
--- a/src/org/traccar/protocol/DwayProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/DwayProtocolDecoder.java
diff --git a/src/org/traccar/protocol/EasyTrackProtocol.java b/src/main/java/org/traccar/protocol/EasyTrackProtocol.java
index 74c636d06..74c636d06 100644
--- a/src/org/traccar/protocol/EasyTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/EasyTrackProtocol.java
diff --git a/src/org/traccar/protocol/EasyTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/EasyTrackProtocolDecoder.java
index 2ddb24f5c..2ddb24f5c 100644
--- a/src/org/traccar/protocol/EasyTrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EasyTrackProtocolDecoder.java
diff --git a/src/org/traccar/protocol/EelinkProtocol.java b/src/main/java/org/traccar/protocol/EelinkProtocol.java
index de4ea971b..de4ea971b 100644
--- a/src/org/traccar/protocol/EelinkProtocol.java
+++ b/src/main/java/org/traccar/protocol/EelinkProtocol.java
diff --git a/src/org/traccar/protocol/EelinkProtocolDecoder.java b/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java
index 2a1db2e32..2a1db2e32 100644
--- a/src/org/traccar/protocol/EelinkProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EelinkProtocolDecoder.java
diff --git a/src/org/traccar/protocol/EelinkProtocolEncoder.java b/src/main/java/org/traccar/protocol/EelinkProtocolEncoder.java
index 8f33441fb..8f33441fb 100644
--- a/src/org/traccar/protocol/EelinkProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/EelinkProtocolEncoder.java
diff --git a/src/org/traccar/protocol/EgtsFrameDecoder.java b/src/main/java/org/traccar/protocol/EgtsFrameDecoder.java
index 84f1f11a7..84f1f11a7 100644
--- a/src/org/traccar/protocol/EgtsFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/EgtsFrameDecoder.java
diff --git a/src/org/traccar/protocol/EgtsProtocol.java b/src/main/java/org/traccar/protocol/EgtsProtocol.java
index 5d4638f37..5d4638f37 100644
--- a/src/org/traccar/protocol/EgtsProtocol.java
+++ b/src/main/java/org/traccar/protocol/EgtsProtocol.java
diff --git a/src/org/traccar/protocol/EgtsProtocolDecoder.java b/src/main/java/org/traccar/protocol/EgtsProtocolDecoder.java
index b9fcb2f44..b9fcb2f44 100644
--- a/src/org/traccar/protocol/EgtsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EgtsProtocolDecoder.java
diff --git a/src/org/traccar/protocol/EnforaProtocol.java b/src/main/java/org/traccar/protocol/EnforaProtocol.java
index f78e4b377..f78e4b377 100644
--- a/src/org/traccar/protocol/EnforaProtocol.java
+++ b/src/main/java/org/traccar/protocol/EnforaProtocol.java
diff --git a/src/org/traccar/protocol/EnforaProtocolDecoder.java b/src/main/java/org/traccar/protocol/EnforaProtocolDecoder.java
index bfa7a116b..bfa7a116b 100644
--- a/src/org/traccar/protocol/EnforaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EnforaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/EnforaProtocolEncoder.java b/src/main/java/org/traccar/protocol/EnforaProtocolEncoder.java
index a46e6367d..a46e6367d 100644
--- a/src/org/traccar/protocol/EnforaProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/EnforaProtocolEncoder.java
diff --git a/src/org/traccar/protocol/EsealProtocol.java b/src/main/java/org/traccar/protocol/EsealProtocol.java
index 7a27c617d..7a27c617d 100644
--- a/src/org/traccar/protocol/EsealProtocol.java
+++ b/src/main/java/org/traccar/protocol/EsealProtocol.java
diff --git a/src/org/traccar/protocol/EsealProtocolDecoder.java b/src/main/java/org/traccar/protocol/EsealProtocolDecoder.java
index 7a1fd7022..7a1fd7022 100644
--- a/src/org/traccar/protocol/EsealProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EsealProtocolDecoder.java
diff --git a/src/org/traccar/protocol/EsealProtocolEncoder.java b/src/main/java/org/traccar/protocol/EsealProtocolEncoder.java
index b9bcc5b0a..b9bcc5b0a 100644
--- a/src/org/traccar/protocol/EsealProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/EsealProtocolEncoder.java
diff --git a/src/org/traccar/protocol/EskyFrameDecoder.java b/src/main/java/org/traccar/protocol/EskyFrameDecoder.java
index da24c1273..da24c1273 100644
--- a/src/org/traccar/protocol/EskyFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/EskyFrameDecoder.java
diff --git a/src/org/traccar/protocol/EskyProtocol.java b/src/main/java/org/traccar/protocol/EskyProtocol.java
index aaa92da58..aaa92da58 100644
--- a/src/org/traccar/protocol/EskyProtocol.java
+++ b/src/main/java/org/traccar/protocol/EskyProtocol.java
diff --git a/src/org/traccar/protocol/EskyProtocolDecoder.java b/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java
index 641b2e28f..641b2e28f 100644
--- a/src/org/traccar/protocol/EskyProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/EskyProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ExtremTracProtocol.java b/src/main/java/org/traccar/protocol/ExtremTracProtocol.java
index 692fd4e99..692fd4e99 100644
--- a/src/org/traccar/protocol/ExtremTracProtocol.java
+++ b/src/main/java/org/traccar/protocol/ExtremTracProtocol.java
diff --git a/src/org/traccar/protocol/ExtremTracProtocolDecoder.java b/src/main/java/org/traccar/protocol/ExtremTracProtocolDecoder.java
index 9fde6f0a0..9fde6f0a0 100644
--- a/src/org/traccar/protocol/ExtremTracProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ExtremTracProtocolDecoder.java
diff --git a/src/org/traccar/protocol/FifotrackProtocol.java b/src/main/java/org/traccar/protocol/FifotrackProtocol.java
index 371e01e55..371e01e55 100644
--- a/src/org/traccar/protocol/FifotrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/FifotrackProtocol.java
diff --git a/src/org/traccar/protocol/FifotrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java
index beaa34125..beaa34125 100644
--- a/src/org/traccar/protocol/FifotrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java
diff --git a/src/org/traccar/protocol/FlespiProtocol.java b/src/main/java/org/traccar/protocol/FlespiProtocol.java
index 2c0729b76..2c0729b76 100644
--- a/src/org/traccar/protocol/FlespiProtocol.java
+++ b/src/main/java/org/traccar/protocol/FlespiProtocol.java
diff --git a/src/org/traccar/protocol/FlespiProtocolDecoder.java b/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java
index 86da3943e..86da3943e 100644
--- a/src/org/traccar/protocol/FlespiProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FlespiProtocolDecoder.java
diff --git a/src/org/traccar/protocol/FlexCommProtocol.java b/src/main/java/org/traccar/protocol/FlexCommProtocol.java
index 9343ebeb8..9343ebeb8 100644
--- a/src/org/traccar/protocol/FlexCommProtocol.java
+++ b/src/main/java/org/traccar/protocol/FlexCommProtocol.java
diff --git a/src/org/traccar/protocol/FlexCommProtocolDecoder.java b/src/main/java/org/traccar/protocol/FlexCommProtocolDecoder.java
index 068c0a05c..068c0a05c 100644
--- a/src/org/traccar/protocol/FlexCommProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FlexCommProtocolDecoder.java
diff --git a/src/org/traccar/protocol/FlextrackProtocol.java b/src/main/java/org/traccar/protocol/FlextrackProtocol.java
index ddd1d58f0..ddd1d58f0 100644
--- a/src/org/traccar/protocol/FlextrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/FlextrackProtocol.java
diff --git a/src/org/traccar/protocol/FlextrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/FlextrackProtocolDecoder.java
index 9dce22ede..9dce22ede 100644
--- a/src/org/traccar/protocol/FlextrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FlextrackProtocolDecoder.java
diff --git a/src/org/traccar/protocol/FoxProtocol.java b/src/main/java/org/traccar/protocol/FoxProtocol.java
index 9bac773b5..9bac773b5 100644
--- a/src/org/traccar/protocol/FoxProtocol.java
+++ b/src/main/java/org/traccar/protocol/FoxProtocol.java
diff --git a/src/org/traccar/protocol/FoxProtocolDecoder.java b/src/main/java/org/traccar/protocol/FoxProtocolDecoder.java
index 449f00022..449f00022 100644
--- a/src/org/traccar/protocol/FoxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FoxProtocolDecoder.java
diff --git a/src/org/traccar/protocol/FreedomProtocol.java b/src/main/java/org/traccar/protocol/FreedomProtocol.java
index bc6b92d5f..bc6b92d5f 100644
--- a/src/org/traccar/protocol/FreedomProtocol.java
+++ b/src/main/java/org/traccar/protocol/FreedomProtocol.java
diff --git a/src/org/traccar/protocol/FreedomProtocolDecoder.java b/src/main/java/org/traccar/protocol/FreedomProtocolDecoder.java
index 1d2dd3133..1d2dd3133 100644
--- a/src/org/traccar/protocol/FreedomProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FreedomProtocolDecoder.java
diff --git a/src/org/traccar/protocol/FreematicsProtocol.java b/src/main/java/org/traccar/protocol/FreematicsProtocol.java
index 999b075a1..999b075a1 100644
--- a/src/org/traccar/protocol/FreematicsProtocol.java
+++ b/src/main/java/org/traccar/protocol/FreematicsProtocol.java
diff --git a/src/org/traccar/protocol/FreematicsProtocolDecoder.java b/src/main/java/org/traccar/protocol/FreematicsProtocolDecoder.java
index ba47699c3..ba47699c3 100644
--- a/src/org/traccar/protocol/FreematicsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/FreematicsProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GalileoFrameDecoder.java b/src/main/java/org/traccar/protocol/GalileoFrameDecoder.java
index c23d26c83..c23d26c83 100644
--- a/src/org/traccar/protocol/GalileoFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/GalileoFrameDecoder.java
diff --git a/src/org/traccar/protocol/GalileoProtocol.java b/src/main/java/org/traccar/protocol/GalileoProtocol.java
index 9b7fe1a4b..9b7fe1a4b 100644
--- a/src/org/traccar/protocol/GalileoProtocol.java
+++ b/src/main/java/org/traccar/protocol/GalileoProtocol.java
diff --git a/src/org/traccar/protocol/GalileoProtocolDecoder.java b/src/main/java/org/traccar/protocol/GalileoProtocolDecoder.java
index 01c55a9ae..01c55a9ae 100644
--- a/src/org/traccar/protocol/GalileoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GalileoProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GalileoProtocolEncoder.java b/src/main/java/org/traccar/protocol/GalileoProtocolEncoder.java
index 3b2145e74..3b2145e74 100644
--- a/src/org/traccar/protocol/GalileoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/GalileoProtocolEncoder.java
diff --git a/src/org/traccar/protocol/GatorProtocol.java b/src/main/java/org/traccar/protocol/GatorProtocol.java
index ca81caefb..ca81caefb 100644
--- a/src/org/traccar/protocol/GatorProtocol.java
+++ b/src/main/java/org/traccar/protocol/GatorProtocol.java
diff --git a/src/org/traccar/protocol/GatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java
index 31500bae6..31500bae6 100644
--- a/src/org/traccar/protocol/GatorProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GatorProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GenxProtocol.java b/src/main/java/org/traccar/protocol/GenxProtocol.java
index c87ba946a..c87ba946a 100644
--- a/src/org/traccar/protocol/GenxProtocol.java
+++ b/src/main/java/org/traccar/protocol/GenxProtocol.java
diff --git a/src/org/traccar/protocol/GenxProtocolDecoder.java b/src/main/java/org/traccar/protocol/GenxProtocolDecoder.java
index 2ae9de7a0..2ae9de7a0 100644
--- a/src/org/traccar/protocol/GenxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GenxProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gl100Protocol.java b/src/main/java/org/traccar/protocol/Gl100Protocol.java
index 063e606db..063e606db 100644
--- a/src/org/traccar/protocol/Gl100Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gl100Protocol.java
diff --git a/src/org/traccar/protocol/Gl100ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gl100ProtocolDecoder.java
index ae0383e5c..ae0383e5c 100644
--- a/src/org/traccar/protocol/Gl100ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gl100ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gl200BinaryProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gl200BinaryProtocolDecoder.java
index c3339bea5..c3339bea5 100644
--- a/src/org/traccar/protocol/Gl200BinaryProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200BinaryProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gl200FrameDecoder.java b/src/main/java/org/traccar/protocol/Gl200FrameDecoder.java
index c192cc28d..c192cc28d 100644
--- a/src/org/traccar/protocol/Gl200FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200FrameDecoder.java
diff --git a/src/org/traccar/protocol/Gl200Protocol.java b/src/main/java/org/traccar/protocol/Gl200Protocol.java
index c5343dae0..c5343dae0 100644
--- a/src/org/traccar/protocol/Gl200Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gl200Protocol.java
diff --git a/src/org/traccar/protocol/Gl200ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gl200ProtocolDecoder.java
index ca1df7a13..ca1df7a13 100644
--- a/src/org/traccar/protocol/Gl200ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gl200ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Gl200ProtocolEncoder.java
index 285106c67..285106c67 100644
--- a/src/org/traccar/protocol/Gl200ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200ProtocolEncoder.java
diff --git a/src/org/traccar/protocol/Gl200TextProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java
index aeb57a116..aeb57a116 100644
--- a/src/org/traccar/protocol/Gl200TextProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gl200TextProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GlobalSatProtocol.java b/src/main/java/org/traccar/protocol/GlobalSatProtocol.java
index 5612515c9..5612515c9 100644
--- a/src/org/traccar/protocol/GlobalSatProtocol.java
+++ b/src/main/java/org/traccar/protocol/GlobalSatProtocol.java
diff --git a/src/org/traccar/protocol/GlobalSatProtocolDecoder.java b/src/main/java/org/traccar/protocol/GlobalSatProtocolDecoder.java
index 3d4ab5760..3d4ab5760 100644
--- a/src/org/traccar/protocol/GlobalSatProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GlobalSatProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GnxProtocol.java b/src/main/java/org/traccar/protocol/GnxProtocol.java
index 3576bf805..3576bf805 100644
--- a/src/org/traccar/protocol/GnxProtocol.java
+++ b/src/main/java/org/traccar/protocol/GnxProtocol.java
diff --git a/src/org/traccar/protocol/GnxProtocolDecoder.java b/src/main/java/org/traccar/protocol/GnxProtocolDecoder.java
index c9c221a69..c9c221a69 100644
--- a/src/org/traccar/protocol/GnxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GnxProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GoSafeProtocol.java b/src/main/java/org/traccar/protocol/GoSafeProtocol.java
index 853b78a16..853b78a16 100644
--- a/src/org/traccar/protocol/GoSafeProtocol.java
+++ b/src/main/java/org/traccar/protocol/GoSafeProtocol.java
diff --git a/src/org/traccar/protocol/GoSafeProtocolDecoder.java b/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java
index 95ef18f20..95ef18f20 100644
--- a/src/org/traccar/protocol/GoSafeProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GoSafeProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GotopProtocol.java b/src/main/java/org/traccar/protocol/GotopProtocol.java
index 07fe02248..07fe02248 100644
--- a/src/org/traccar/protocol/GotopProtocol.java
+++ b/src/main/java/org/traccar/protocol/GotopProtocol.java
diff --git a/src/org/traccar/protocol/GotopProtocolDecoder.java b/src/main/java/org/traccar/protocol/GotopProtocolDecoder.java
index 2ef975fe5..2ef975fe5 100644
--- a/src/org/traccar/protocol/GotopProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GotopProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gps056FrameDecoder.java b/src/main/java/org/traccar/protocol/Gps056FrameDecoder.java
index 0d84bf231..0d84bf231 100644
--- a/src/org/traccar/protocol/Gps056FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gps056FrameDecoder.java
diff --git a/src/org/traccar/protocol/Gps056Protocol.java b/src/main/java/org/traccar/protocol/Gps056Protocol.java
index b6ab10a19..b6ab10a19 100644
--- a/src/org/traccar/protocol/Gps056Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gps056Protocol.java
diff --git a/src/org/traccar/protocol/Gps056ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gps056ProtocolDecoder.java
index 0ba79bb51..0ba79bb51 100644
--- a/src/org/traccar/protocol/Gps056ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gps056ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gps103Protocol.java b/src/main/java/org/traccar/protocol/Gps103Protocol.java
index 6272a3fd1..6272a3fd1 100644
--- a/src/org/traccar/protocol/Gps103Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gps103Protocol.java
diff --git a/src/org/traccar/protocol/Gps103ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gps103ProtocolDecoder.java
index aa02e8ad4..aa02e8ad4 100644
--- a/src/org/traccar/protocol/Gps103ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gps103ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gps103ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Gps103ProtocolEncoder.java
index 47ef2f333..47ef2f333 100644
--- a/src/org/traccar/protocol/Gps103ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Gps103ProtocolEncoder.java
diff --git a/src/org/traccar/protocol/GpsGateProtocol.java b/src/main/java/org/traccar/protocol/GpsGateProtocol.java
index a131b6f48..a131b6f48 100644
--- a/src/org/traccar/protocol/GpsGateProtocol.java
+++ b/src/main/java/org/traccar/protocol/GpsGateProtocol.java
diff --git a/src/org/traccar/protocol/GpsGateProtocolDecoder.java b/src/main/java/org/traccar/protocol/GpsGateProtocolDecoder.java
index cc187225b..cc187225b 100644
--- a/src/org/traccar/protocol/GpsGateProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GpsGateProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GpsMarkerProtocol.java b/src/main/java/org/traccar/protocol/GpsMarkerProtocol.java
index ad23ece48..ad23ece48 100644
--- a/src/org/traccar/protocol/GpsMarkerProtocol.java
+++ b/src/main/java/org/traccar/protocol/GpsMarkerProtocol.java
diff --git a/src/org/traccar/protocol/GpsMarkerProtocolDecoder.java b/src/main/java/org/traccar/protocol/GpsMarkerProtocolDecoder.java
index bbb2c31e2..bbb2c31e2 100644
--- a/src/org/traccar/protocol/GpsMarkerProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GpsMarkerProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GpsmtaProtocol.java b/src/main/java/org/traccar/protocol/GpsmtaProtocol.java
index ce6cc5929..ce6cc5929 100644
--- a/src/org/traccar/protocol/GpsmtaProtocol.java
+++ b/src/main/java/org/traccar/protocol/GpsmtaProtocol.java
diff --git a/src/org/traccar/protocol/GpsmtaProtocolDecoder.java b/src/main/java/org/traccar/protocol/GpsmtaProtocolDecoder.java
index 31f9401b4..31f9401b4 100644
--- a/src/org/traccar/protocol/GpsmtaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GpsmtaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GranitFrameDecoder.java b/src/main/java/org/traccar/protocol/GranitFrameDecoder.java
index bb7f4be44..bb7f4be44 100644
--- a/src/org/traccar/protocol/GranitFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/GranitFrameDecoder.java
diff --git a/src/org/traccar/protocol/GranitProtocol.java b/src/main/java/org/traccar/protocol/GranitProtocol.java
index 6785f2a2e..6785f2a2e 100644
--- a/src/org/traccar/protocol/GranitProtocol.java
+++ b/src/main/java/org/traccar/protocol/GranitProtocol.java
diff --git a/src/org/traccar/protocol/GranitProtocolDecoder.java b/src/main/java/org/traccar/protocol/GranitProtocolDecoder.java
index 8900e5b39..8900e5b39 100644
--- a/src/org/traccar/protocol/GranitProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/GranitProtocolDecoder.java
diff --git a/src/org/traccar/protocol/GranitProtocolEncoder.java b/src/main/java/org/traccar/protocol/GranitProtocolEncoder.java
index 6345ff971..6345ff971 100644
--- a/src/org/traccar/protocol/GranitProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/GranitProtocolEncoder.java
diff --git a/src/org/traccar/protocol/GranitProtocolSmsEncoder.java b/src/main/java/org/traccar/protocol/GranitProtocolSmsEncoder.java
index 7d5518c17..7d5518c17 100644
--- a/src/org/traccar/protocol/GranitProtocolSmsEncoder.java
+++ b/src/main/java/org/traccar/protocol/GranitProtocolSmsEncoder.java
diff --git a/src/org/traccar/protocol/Gt02Protocol.java b/src/main/java/org/traccar/protocol/Gt02Protocol.java
index f412ee720..f412ee720 100644
--- a/src/org/traccar/protocol/Gt02Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gt02Protocol.java
diff --git a/src/org/traccar/protocol/Gt02ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt02ProtocolDecoder.java
index 78a3fd3ee..78a3fd3ee 100644
--- a/src/org/traccar/protocol/Gt02ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gt02ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gt06FrameDecoder.java b/src/main/java/org/traccar/protocol/Gt06FrameDecoder.java
index cc934be42..cc934be42 100644
--- a/src/org/traccar/protocol/Gt06FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06FrameDecoder.java
diff --git a/src/org/traccar/protocol/Gt06Protocol.java b/src/main/java/org/traccar/protocol/Gt06Protocol.java
index 6e5435cd4..6e5435cd4 100644
--- a/src/org/traccar/protocol/Gt06Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gt06Protocol.java
diff --git a/src/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
index 1f8fb66dd..1f8fb66dd 100644
--- a/src/org/traccar/protocol/Gt06ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Gt06ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java
index 05560229f..05560229f 100644
--- a/src/org/traccar/protocol/Gt06ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06ProtocolEncoder.java
diff --git a/src/org/traccar/protocol/Gt30Protocol.java b/src/main/java/org/traccar/protocol/Gt30Protocol.java
index aa4ad20b1..aa4ad20b1 100644
--- a/src/org/traccar/protocol/Gt30Protocol.java
+++ b/src/main/java/org/traccar/protocol/Gt30Protocol.java
diff --git a/src/org/traccar/protocol/Gt30ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt30ProtocolDecoder.java
index abf208a46..abf208a46 100644
--- a/src/org/traccar/protocol/Gt30ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gt30ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/H02FrameDecoder.java b/src/main/java/org/traccar/protocol/H02FrameDecoder.java
index 583ad599f..583ad599f 100644
--- a/src/org/traccar/protocol/H02FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/H02FrameDecoder.java
diff --git a/src/org/traccar/protocol/H02Protocol.java b/src/main/java/org/traccar/protocol/H02Protocol.java
index 251beac5e..251beac5e 100644
--- a/src/org/traccar/protocol/H02Protocol.java
+++ b/src/main/java/org/traccar/protocol/H02Protocol.java
diff --git a/src/org/traccar/protocol/H02ProtocolDecoder.java b/src/main/java/org/traccar/protocol/H02ProtocolDecoder.java
index c4443a00b..c4443a00b 100644
--- a/src/org/traccar/protocol/H02ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/H02ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/H02ProtocolEncoder.java b/src/main/java/org/traccar/protocol/H02ProtocolEncoder.java
index 614a07dd1..614a07dd1 100644
--- a/src/org/traccar/protocol/H02ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/H02ProtocolEncoder.java
diff --git a/src/org/traccar/protocol/HaicomProtocol.java b/src/main/java/org/traccar/protocol/HaicomProtocol.java
index 6e5760bd4..6e5760bd4 100644
--- a/src/org/traccar/protocol/HaicomProtocol.java
+++ b/src/main/java/org/traccar/protocol/HaicomProtocol.java
diff --git a/src/org/traccar/protocol/HaicomProtocolDecoder.java b/src/main/java/org/traccar/protocol/HaicomProtocolDecoder.java
index dd20f2aeb..dd20f2aeb 100644
--- a/src/org/traccar/protocol/HaicomProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HaicomProtocolDecoder.java
diff --git a/src/org/traccar/protocol/HomtecsProtocol.java b/src/main/java/org/traccar/protocol/HomtecsProtocol.java
index 34dbf0f51..34dbf0f51 100644
--- a/src/org/traccar/protocol/HomtecsProtocol.java
+++ b/src/main/java/org/traccar/protocol/HomtecsProtocol.java
diff --git a/src/org/traccar/protocol/HomtecsProtocolDecoder.java b/src/main/java/org/traccar/protocol/HomtecsProtocolDecoder.java
index a93572b5c..a93572b5c 100644
--- a/src/org/traccar/protocol/HomtecsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HomtecsProtocolDecoder.java
diff --git a/src/org/traccar/protocol/HuaShengFrameDecoder.java b/src/main/java/org/traccar/protocol/HuaShengFrameDecoder.java
index bd52aa9e7..bd52aa9e7 100644
--- a/src/org/traccar/protocol/HuaShengFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuaShengFrameDecoder.java
diff --git a/src/org/traccar/protocol/HuaShengProtocol.java b/src/main/java/org/traccar/protocol/HuaShengProtocol.java
index 103f2d501..103f2d501 100644
--- a/src/org/traccar/protocol/HuaShengProtocol.java
+++ b/src/main/java/org/traccar/protocol/HuaShengProtocol.java
diff --git a/src/org/traccar/protocol/HuaShengProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
index 8a937a194..8a937a194 100644
--- a/src/org/traccar/protocol/HuaShengProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuaShengProtocolDecoder.java
diff --git a/src/org/traccar/protocol/HuabaoFrameDecoder.java b/src/main/java/org/traccar/protocol/HuabaoFrameDecoder.java
index b520f6be9..b520f6be9 100644
--- a/src/org/traccar/protocol/HuabaoFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuabaoFrameDecoder.java
diff --git a/src/org/traccar/protocol/HuabaoProtocol.java b/src/main/java/org/traccar/protocol/HuabaoProtocol.java
index 44c9f7ac7..44c9f7ac7 100644
--- a/src/org/traccar/protocol/HuabaoProtocol.java
+++ b/src/main/java/org/traccar/protocol/HuabaoProtocol.java
diff --git a/src/org/traccar/protocol/HuabaoProtocolDecoder.java b/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java
index 6e2e1377b..6e2e1377b 100644
--- a/src/org/traccar/protocol/HuabaoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HuabaoProtocolDecoder.java
diff --git a/src/org/traccar/protocol/HuabaoProtocolEncoder.java b/src/main/java/org/traccar/protocol/HuabaoProtocolEncoder.java
index 7759790c4..7759790c4 100644
--- a/src/org/traccar/protocol/HuabaoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/HuabaoProtocolEncoder.java
diff --git a/src/org/traccar/protocol/HunterProProtocol.java b/src/main/java/org/traccar/protocol/HunterProProtocol.java
index 9f6424a57..9f6424a57 100644
--- a/src/org/traccar/protocol/HunterProProtocol.java
+++ b/src/main/java/org/traccar/protocol/HunterProProtocol.java
diff --git a/src/org/traccar/protocol/HunterProProtocolDecoder.java b/src/main/java/org/traccar/protocol/HunterProProtocolDecoder.java
index 06bc12d59..06bc12d59 100644
--- a/src/org/traccar/protocol/HunterProProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/HunterProProtocolDecoder.java
diff --git a/src/org/traccar/protocol/IdplProtocol.java b/src/main/java/org/traccar/protocol/IdplProtocol.java
index 418178756..418178756 100644
--- a/src/org/traccar/protocol/IdplProtocol.java
+++ b/src/main/java/org/traccar/protocol/IdplProtocol.java
diff --git a/src/org/traccar/protocol/IdplProtocolDecoder.java b/src/main/java/org/traccar/protocol/IdplProtocolDecoder.java
index cf3c03d7f..cf3c03d7f 100644
--- a/src/org/traccar/protocol/IdplProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/IdplProtocolDecoder.java
diff --git a/src/org/traccar/protocol/IntellitracFrameDecoder.java b/src/main/java/org/traccar/protocol/IntellitracFrameDecoder.java
index 8322e65ba..8322e65ba 100644
--- a/src/org/traccar/protocol/IntellitracFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/IntellitracFrameDecoder.java
diff --git a/src/org/traccar/protocol/IntellitracProtocol.java b/src/main/java/org/traccar/protocol/IntellitracProtocol.java
index 3abf40da7..3abf40da7 100644
--- a/src/org/traccar/protocol/IntellitracProtocol.java
+++ b/src/main/java/org/traccar/protocol/IntellitracProtocol.java
diff --git a/src/org/traccar/protocol/IntellitracProtocolDecoder.java b/src/main/java/org/traccar/protocol/IntellitracProtocolDecoder.java
index 897606270..897606270 100644
--- a/src/org/traccar/protocol/IntellitracProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/IntellitracProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ItsProtocol.java b/src/main/java/org/traccar/protocol/ItsProtocol.java
index f53600dc9..f53600dc9 100644
--- a/src/org/traccar/protocol/ItsProtocol.java
+++ b/src/main/java/org/traccar/protocol/ItsProtocol.java
diff --git a/src/org/traccar/protocol/ItsProtocolDecoder.java b/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java
index 482f34e65..482f34e65 100644
--- a/src/org/traccar/protocol/ItsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Ivt401Protocol.java b/src/main/java/org/traccar/protocol/Ivt401Protocol.java
index fb44e4fe9..fb44e4fe9 100644
--- a/src/org/traccar/protocol/Ivt401Protocol.java
+++ b/src/main/java/org/traccar/protocol/Ivt401Protocol.java
diff --git a/src/org/traccar/protocol/Ivt401ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Ivt401ProtocolDecoder.java
index 63556e7a9..63556e7a9 100644
--- a/src/org/traccar/protocol/Ivt401ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Ivt401ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/JpKorjarFrameDecoder.java b/src/main/java/org/traccar/protocol/JpKorjarFrameDecoder.java
index 0eb65c8ef..0eb65c8ef 100644
--- a/src/org/traccar/protocol/JpKorjarFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/JpKorjarFrameDecoder.java
diff --git a/src/org/traccar/protocol/JpKorjarProtocol.java b/src/main/java/org/traccar/protocol/JpKorjarProtocol.java
index fe5b2480d..fe5b2480d 100644
--- a/src/org/traccar/protocol/JpKorjarProtocol.java
+++ b/src/main/java/org/traccar/protocol/JpKorjarProtocol.java
diff --git a/src/org/traccar/protocol/JpKorjarProtocolDecoder.java b/src/main/java/org/traccar/protocol/JpKorjarProtocolDecoder.java
index a8389d1b1..33026918a 100644
--- a/src/org/traccar/protocol/JpKorjarProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/JpKorjarProtocolDecoder.java
@@ -1,89 +1,89 @@
-/*
- * Copyright 2016 Nyash (nyashh@gmail.com)
- * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.traccar.protocol;
-
-import io.netty.channel.Channel;
-import org.traccar.BaseProtocolDecoder;
-import org.traccar.DeviceSession;
-import org.traccar.Protocol;
-import org.traccar.helper.Parser;
-import org.traccar.helper.PatternBuilder;
-import org.traccar.model.CellTower;
-import org.traccar.model.Network;
-import org.traccar.model.Position;
-
-import java.net.SocketAddress;
-import java.util.regex.Pattern;
-
-public class JpKorjarProtocolDecoder extends BaseProtocolDecoder {
-
- public JpKorjarProtocolDecoder(Protocol protocol) {
- super(protocol);
- }
-
- private static final Pattern PATTERN = new PatternBuilder()
- .text("KORJAR.PL,")
- .number("(d+),") // imei
- .number("(dd)(dd)(dd)") // date (yymmdd)
- .number("(dd)(dd)(dd),") // time (hhmmss)
- .number("(d+.d+)([NS]),") // latitude
- .number("(d+.d+)([EW]),") // longitude
- .number("(d+.d+),") // speed
- .number("(d+),") // course
- .number("[FL]:(d+.d+)V,") // battery
- .number("([01]) ") // valid
- .number("(d+) ") // mcc
- .number("(d+) ") // mnc
- .number("(x+) ") // lac
- .number("(x+),") // cid
- .compile();
-
- @Override
- protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
-
- Parser parser = new Parser(PATTERN, (String) msg);
- if (!parser.matches()) {
- return null;
- }
-
- Position position = new Position(getProtocolName());
-
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
- if (deviceSession == null) {
- return null;
- }
- position.setDeviceId(deviceSession.getDeviceId());
-
- position.setTime(parser.nextDateTime());
-
- position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
- position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
- position.setSpeed(parser.nextDouble(0));
- position.setCourse(parser.nextDouble(0));
-
- position.set(Position.KEY_BATTERY, parser.nextDouble(0));
-
- position.setValid(parser.nextInt(0) == 1);
-
- position.setNetwork(new Network(CellTower.from(
- parser.nextInt(0), parser.nextInt(0), parser.nextHexInt(0), parser.nextHexInt(0))));
-
- return position;
- }
-
-}
+/*
+ * Copyright 2016 Nyash (nyashh@gmail.com)
+ * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.Protocol;
+import org.traccar.helper.Parser;
+import org.traccar.helper.PatternBuilder;
+import org.traccar.model.CellTower;
+import org.traccar.model.Network;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.util.regex.Pattern;
+
+public class JpKorjarProtocolDecoder extends BaseProtocolDecoder {
+
+ public JpKorjarProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .text("KORJAR.PL,")
+ .number("(d+),") // imei
+ .number("(dd)(dd)(dd)") // date (yymmdd)
+ .number("(dd)(dd)(dd),") // time (hhmmss)
+ .number("(d+.d+)([NS]),") // latitude
+ .number("(d+.d+)([EW]),") // longitude
+ .number("(d+.d+),") // speed
+ .number("(d+),") // course
+ .number("[FL]:(d+.d+)V,") // battery
+ .number("([01]) ") // valid
+ .number("(d+) ") // mcc
+ .number("(d+) ") // mnc
+ .number("(x+) ") // lac
+ .number("(x+),") // cid
+ .compile();
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ Parser parser = new Parser(PATTERN, (String) msg);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession == null) {
+ return null;
+ }
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setTime(parser.nextDateTime());
+
+ position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
+ position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.DEG_HEM));
+ position.setSpeed(parser.nextDouble(0));
+ position.setCourse(parser.nextDouble(0));
+
+ position.set(Position.KEY_BATTERY, parser.nextDouble(0));
+
+ position.setValid(parser.nextInt(0) == 1);
+
+ position.setNetwork(new Network(CellTower.from(
+ parser.nextInt(0), parser.nextInt(0), parser.nextHexInt(0), parser.nextHexInt(0))));
+
+ return position;
+ }
+
+}
diff --git a/src/org/traccar/protocol/Jt600FrameDecoder.java b/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java
index b5d060ecc..b5d060ecc 100644
--- a/src/org/traccar/protocol/Jt600FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Jt600FrameDecoder.java
diff --git a/src/org/traccar/protocol/Jt600Protocol.java b/src/main/java/org/traccar/protocol/Jt600Protocol.java
index 97c5fa6ce..97c5fa6ce 100644
--- a/src/org/traccar/protocol/Jt600Protocol.java
+++ b/src/main/java/org/traccar/protocol/Jt600Protocol.java
diff --git a/src/org/traccar/protocol/Jt600ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java
index 1351706e2..1351706e2 100644
--- a/src/org/traccar/protocol/Jt600ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Jt600ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Jt600ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Jt600ProtocolEncoder.java
index fe5c63c32..fe5c63c32 100644
--- a/src/org/traccar/protocol/Jt600ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Jt600ProtocolEncoder.java
diff --git a/src/org/traccar/protocol/KenjiProtocol.java b/src/main/java/org/traccar/protocol/KenjiProtocol.java
index 90c0c511c..90c0c511c 100644
--- a/src/org/traccar/protocol/KenjiProtocol.java
+++ b/src/main/java/org/traccar/protocol/KenjiProtocol.java
diff --git a/src/org/traccar/protocol/KenjiProtocolDecoder.java b/src/main/java/org/traccar/protocol/KenjiProtocolDecoder.java
index 63812242a..63812242a 100644
--- a/src/org/traccar/protocol/KenjiProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/KenjiProtocolDecoder.java
diff --git a/src/org/traccar/protocol/KhdProtocol.java b/src/main/java/org/traccar/protocol/KhdProtocol.java
index cec7158ed..cec7158ed 100644
--- a/src/org/traccar/protocol/KhdProtocol.java
+++ b/src/main/java/org/traccar/protocol/KhdProtocol.java
diff --git a/src/org/traccar/protocol/KhdProtocolDecoder.java b/src/main/java/org/traccar/protocol/KhdProtocolDecoder.java
index 0dd5b085a..0dd5b085a 100644
--- a/src/org/traccar/protocol/KhdProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/KhdProtocolDecoder.java
diff --git a/src/org/traccar/protocol/KhdProtocolEncoder.java b/src/main/java/org/traccar/protocol/KhdProtocolEncoder.java
index c66129283..c66129283 100644
--- a/src/org/traccar/protocol/KhdProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/KhdProtocolEncoder.java
diff --git a/src/org/traccar/protocol/L100FrameDecoder.java b/src/main/java/org/traccar/protocol/L100FrameDecoder.java
index 158461895..158461895 100644
--- a/src/org/traccar/protocol/L100FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/L100FrameDecoder.java
diff --git a/src/org/traccar/protocol/L100Protocol.java b/src/main/java/org/traccar/protocol/L100Protocol.java
index 942029307..942029307 100644
--- a/src/org/traccar/protocol/L100Protocol.java
+++ b/src/main/java/org/traccar/protocol/L100Protocol.java
diff --git a/src/org/traccar/protocol/L100ProtocolDecoder.java b/src/main/java/org/traccar/protocol/L100ProtocolDecoder.java
index 9868de435..9868de435 100644
--- a/src/org/traccar/protocol/L100ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/L100ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/LaipacProtocol.java b/src/main/java/org/traccar/protocol/LaipacProtocol.java
index 923b08a16..923b08a16 100644
--- a/src/org/traccar/protocol/LaipacProtocol.java
+++ b/src/main/java/org/traccar/protocol/LaipacProtocol.java
diff --git a/src/org/traccar/protocol/LaipacProtocolDecoder.java b/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java
index 2f3cbb1b9..2f3cbb1b9 100644
--- a/src/org/traccar/protocol/LaipacProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/LaipacProtocolDecoder.java
diff --git a/src/org/traccar/protocol/M2cProtocol.java b/src/main/java/org/traccar/protocol/M2cProtocol.java
index 9de8526c3..9de8526c3 100644
--- a/src/org/traccar/protocol/M2cProtocol.java
+++ b/src/main/java/org/traccar/protocol/M2cProtocol.java
diff --git a/src/org/traccar/protocol/M2cProtocolDecoder.java b/src/main/java/org/traccar/protocol/M2cProtocolDecoder.java
index 1460bb176..1460bb176 100644
--- a/src/org/traccar/protocol/M2cProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/M2cProtocolDecoder.java
diff --git a/src/org/traccar/protocol/M2mProtocol.java b/src/main/java/org/traccar/protocol/M2mProtocol.java
index dda328a59..dda328a59 100644
--- a/src/org/traccar/protocol/M2mProtocol.java
+++ b/src/main/java/org/traccar/protocol/M2mProtocol.java
diff --git a/src/org/traccar/protocol/M2mProtocolDecoder.java b/src/main/java/org/traccar/protocol/M2mProtocolDecoder.java
index 21e4a2fd0..21e4a2fd0 100644
--- a/src/org/traccar/protocol/M2mProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/M2mProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MaestroProtocol.java b/src/main/java/org/traccar/protocol/MaestroProtocol.java
index 87453ce7d..87453ce7d 100644
--- a/src/org/traccar/protocol/MaestroProtocol.java
+++ b/src/main/java/org/traccar/protocol/MaestroProtocol.java
diff --git a/src/org/traccar/protocol/MaestroProtocolDecoder.java b/src/main/java/org/traccar/protocol/MaestroProtocolDecoder.java
index 37b097414..37b097414 100644
--- a/src/org/traccar/protocol/MaestroProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MaestroProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ManPowerProtocol.java b/src/main/java/org/traccar/protocol/ManPowerProtocol.java
index 49d8b1e9f..49d8b1e9f 100644
--- a/src/org/traccar/protocol/ManPowerProtocol.java
+++ b/src/main/java/org/traccar/protocol/ManPowerProtocol.java
diff --git a/src/org/traccar/protocol/ManPowerProtocolDecoder.java b/src/main/java/org/traccar/protocol/ManPowerProtocolDecoder.java
index 2c7b7eb40..2c7b7eb40 100644
--- a/src/org/traccar/protocol/ManPowerProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ManPowerProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MegastekFrameDecoder.java b/src/main/java/org/traccar/protocol/MegastekFrameDecoder.java
index 347fa24b1..347fa24b1 100644
--- a/src/org/traccar/protocol/MegastekFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/MegastekFrameDecoder.java
diff --git a/src/org/traccar/protocol/MegastekProtocol.java b/src/main/java/org/traccar/protocol/MegastekProtocol.java
index e9f5f9fde..e9f5f9fde 100644
--- a/src/org/traccar/protocol/MegastekProtocol.java
+++ b/src/main/java/org/traccar/protocol/MegastekProtocol.java
diff --git a/src/org/traccar/protocol/MegastekProtocolDecoder.java b/src/main/java/org/traccar/protocol/MegastekProtocolDecoder.java
index d81cc0eda..d81cc0eda 100644
--- a/src/org/traccar/protocol/MegastekProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MegastekProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MeiligaoFrameDecoder.java b/src/main/java/org/traccar/protocol/MeiligaoFrameDecoder.java
index 52f9ae26d..52f9ae26d 100644
--- a/src/org/traccar/protocol/MeiligaoFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoFrameDecoder.java
diff --git a/src/org/traccar/protocol/MeiligaoProtocol.java b/src/main/java/org/traccar/protocol/MeiligaoProtocol.java
index c307c7318..c307c7318 100644
--- a/src/org/traccar/protocol/MeiligaoProtocol.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoProtocol.java
diff --git a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java
index cbfc3660a..cbfc3660a 100644
--- a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MeiligaoProtocolEncoder.java b/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java
index 57cbbe0fc..57cbbe0fc 100644
--- a/src/org/traccar/protocol/MeiligaoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/MeiligaoProtocolEncoder.java
diff --git a/src/org/traccar/protocol/MeitrackFrameDecoder.java b/src/main/java/org/traccar/protocol/MeitrackFrameDecoder.java
index d122bca0c..d122bca0c 100644
--- a/src/org/traccar/protocol/MeitrackFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/MeitrackFrameDecoder.java
diff --git a/src/org/traccar/protocol/MeitrackProtocol.java b/src/main/java/org/traccar/protocol/MeitrackProtocol.java
index c887cd3a0..c887cd3a0 100644
--- a/src/org/traccar/protocol/MeitrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/MeitrackProtocol.java
diff --git a/src/org/traccar/protocol/MeitrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java
index 55260ef0c..55260ef0c 100644
--- a/src/org/traccar/protocol/MeitrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MeitrackProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MeitrackProtocolEncoder.java b/src/main/java/org/traccar/protocol/MeitrackProtocolEncoder.java
index abb6ec9d4..abb6ec9d4 100644
--- a/src/org/traccar/protocol/MeitrackProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/MeitrackProtocolEncoder.java
diff --git a/src/org/traccar/protocol/MilesmateProtocol.java b/src/main/java/org/traccar/protocol/MilesmateProtocol.java
index 822711603..822711603 100644
--- a/src/org/traccar/protocol/MilesmateProtocol.java
+++ b/src/main/java/org/traccar/protocol/MilesmateProtocol.java
diff --git a/src/org/traccar/protocol/MilesmateProtocolDecoder.java b/src/main/java/org/traccar/protocol/MilesmateProtocolDecoder.java
index 901ceb8f7..901ceb8f7 100644
--- a/src/org/traccar/protocol/MilesmateProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MilesmateProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MiniFinderProtocol.java b/src/main/java/org/traccar/protocol/MiniFinderProtocol.java
index d4a154053..d4a154053 100644
--- a/src/org/traccar/protocol/MiniFinderProtocol.java
+++ b/src/main/java/org/traccar/protocol/MiniFinderProtocol.java
diff --git a/src/org/traccar/protocol/MiniFinderProtocolDecoder.java b/src/main/java/org/traccar/protocol/MiniFinderProtocolDecoder.java
index 2b7a960c4..2b7a960c4 100644
--- a/src/org/traccar/protocol/MiniFinderProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MiniFinderProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MiniFinderProtocolEncoder.java b/src/main/java/org/traccar/protocol/MiniFinderProtocolEncoder.java
index 7a3d5b226..7a3d5b226 100644
--- a/src/org/traccar/protocol/MiniFinderProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/MiniFinderProtocolEncoder.java
diff --git a/src/org/traccar/protocol/Mta6Protocol.java b/src/main/java/org/traccar/protocol/Mta6Protocol.java
index 632a7df80..632a7df80 100644
--- a/src/org/traccar/protocol/Mta6Protocol.java
+++ b/src/main/java/org/traccar/protocol/Mta6Protocol.java
diff --git a/src/org/traccar/protocol/Mta6ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Mta6ProtocolDecoder.java
index 88419b871..88419b871 100644
--- a/src/org/traccar/protocol/Mta6ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Mta6ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MtxProtocol.java b/src/main/java/org/traccar/protocol/MtxProtocol.java
index 44372ce83..44372ce83 100644
--- a/src/org/traccar/protocol/MtxProtocol.java
+++ b/src/main/java/org/traccar/protocol/MtxProtocol.java
diff --git a/src/org/traccar/protocol/MtxProtocolDecoder.java b/src/main/java/org/traccar/protocol/MtxProtocolDecoder.java
index d1207bedf..d1207bedf 100644
--- a/src/org/traccar/protocol/MtxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MtxProtocolDecoder.java
diff --git a/src/org/traccar/protocol/MxtFrameDecoder.java b/src/main/java/org/traccar/protocol/MxtFrameDecoder.java
index d70e92da1..d70e92da1 100644
--- a/src/org/traccar/protocol/MxtFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/MxtFrameDecoder.java
diff --git a/src/org/traccar/protocol/MxtProtocol.java b/src/main/java/org/traccar/protocol/MxtProtocol.java
index dbe43fe45..dbe43fe45 100644
--- a/src/org/traccar/protocol/MxtProtocol.java
+++ b/src/main/java/org/traccar/protocol/MxtProtocol.java
diff --git a/src/org/traccar/protocol/MxtProtocolDecoder.java b/src/main/java/org/traccar/protocol/MxtProtocolDecoder.java
index 7bde85f87..7bde85f87 100644
--- a/src/org/traccar/protocol/MxtProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/MxtProtocolDecoder.java
diff --git a/src/org/traccar/protocol/NavigilFrameDecoder.java b/src/main/java/org/traccar/protocol/NavigilFrameDecoder.java
index e8b6bea52..e8b6bea52 100644
--- a/src/org/traccar/protocol/NavigilFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/NavigilFrameDecoder.java
diff --git a/src/org/traccar/protocol/NavigilProtocol.java b/src/main/java/org/traccar/protocol/NavigilProtocol.java
index 2c946c39f..2c946c39f 100644
--- a/src/org/traccar/protocol/NavigilProtocol.java
+++ b/src/main/java/org/traccar/protocol/NavigilProtocol.java
diff --git a/src/org/traccar/protocol/NavigilProtocolDecoder.java b/src/main/java/org/traccar/protocol/NavigilProtocolDecoder.java
index db5521201..db5521201 100644
--- a/src/org/traccar/protocol/NavigilProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/NavigilProtocolDecoder.java
diff --git a/src/org/traccar/protocol/NavisFrameDecoder.java b/src/main/java/org/traccar/protocol/NavisFrameDecoder.java
index 8a0bb0b9a..8a0bb0b9a 100644
--- a/src/org/traccar/protocol/NavisFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/NavisFrameDecoder.java
diff --git a/src/org/traccar/protocol/NavisProtocol.java b/src/main/java/org/traccar/protocol/NavisProtocol.java
index d5af6838d..d5af6838d 100644
--- a/src/org/traccar/protocol/NavisProtocol.java
+++ b/src/main/java/org/traccar/protocol/NavisProtocol.java
diff --git a/src/org/traccar/protocol/NavisProtocolDecoder.java b/src/main/java/org/traccar/protocol/NavisProtocolDecoder.java
index 7ba474ae0..7ba474ae0 100644
--- a/src/org/traccar/protocol/NavisProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/NavisProtocolDecoder.java
diff --git a/src/org/traccar/protocol/NeosProtocol.java b/src/main/java/org/traccar/protocol/NeosProtocol.java
index e545a9969..e545a9969 100644
--- a/src/org/traccar/protocol/NeosProtocol.java
+++ b/src/main/java/org/traccar/protocol/NeosProtocol.java
diff --git a/src/org/traccar/protocol/NeosProtocolDecoder.java b/src/main/java/org/traccar/protocol/NeosProtocolDecoder.java
index 6b5596dba..6b5596dba 100644
--- a/src/org/traccar/protocol/NeosProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/NeosProtocolDecoder.java
diff --git a/src/org/traccar/protocol/NoranProtocol.java b/src/main/java/org/traccar/protocol/NoranProtocol.java
index 9f3078d6d..9f3078d6d 100644
--- a/src/org/traccar/protocol/NoranProtocol.java
+++ b/src/main/java/org/traccar/protocol/NoranProtocol.java
diff --git a/src/org/traccar/protocol/NoranProtocolDecoder.java b/src/main/java/org/traccar/protocol/NoranProtocolDecoder.java
index 53dae7fd6..53dae7fd6 100644
--- a/src/org/traccar/protocol/NoranProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/NoranProtocolDecoder.java
diff --git a/src/org/traccar/protocol/NoranProtocolEncoder.java b/src/main/java/org/traccar/protocol/NoranProtocolEncoder.java
index 92826c8b2..92826c8b2 100644
--- a/src/org/traccar/protocol/NoranProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/NoranProtocolEncoder.java
diff --git a/src/org/traccar/protocol/NvsFrameDecoder.java b/src/main/java/org/traccar/protocol/NvsFrameDecoder.java
index e93a58cf6..e93a58cf6 100644
--- a/src/org/traccar/protocol/NvsFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/NvsFrameDecoder.java
diff --git a/src/org/traccar/protocol/NvsProtocol.java b/src/main/java/org/traccar/protocol/NvsProtocol.java
index d319b22f3..d319b22f3 100644
--- a/src/org/traccar/protocol/NvsProtocol.java
+++ b/src/main/java/org/traccar/protocol/NvsProtocol.java
diff --git a/src/org/traccar/protocol/NvsProtocolDecoder.java b/src/main/java/org/traccar/protocol/NvsProtocolDecoder.java
index 5d1159f7d..5d1159f7d 100644
--- a/src/org/traccar/protocol/NvsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/NvsProtocolDecoder.java
diff --git a/src/org/traccar/protocol/NyitechProtocol.java b/src/main/java/org/traccar/protocol/NyitechProtocol.java
index 58974be5c..58974be5c 100644
--- a/src/org/traccar/protocol/NyitechProtocol.java
+++ b/src/main/java/org/traccar/protocol/NyitechProtocol.java
diff --git a/src/org/traccar/protocol/NyitechProtocolDecoder.java b/src/main/java/org/traccar/protocol/NyitechProtocolDecoder.java
index e145205f7..e145205f7 100644
--- a/src/org/traccar/protocol/NyitechProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/NyitechProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ObdDongleProtocol.java b/src/main/java/org/traccar/protocol/ObdDongleProtocol.java
index 10a55759b..10a55759b 100644
--- a/src/org/traccar/protocol/ObdDongleProtocol.java
+++ b/src/main/java/org/traccar/protocol/ObdDongleProtocol.java
diff --git a/src/org/traccar/protocol/ObdDongleProtocolDecoder.java b/src/main/java/org/traccar/protocol/ObdDongleProtocolDecoder.java
index 1c9771ce9..1c9771ce9 100644
--- a/src/org/traccar/protocol/ObdDongleProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ObdDongleProtocolDecoder.java
diff --git a/src/org/traccar/protocol/OigoProtocol.java b/src/main/java/org/traccar/protocol/OigoProtocol.java
index 5056f68aa..5056f68aa 100644
--- a/src/org/traccar/protocol/OigoProtocol.java
+++ b/src/main/java/org/traccar/protocol/OigoProtocol.java
diff --git a/src/org/traccar/protocol/OigoProtocolDecoder.java b/src/main/java/org/traccar/protocol/OigoProtocolDecoder.java
index b9cc71e8c..b9cc71e8c 100644
--- a/src/org/traccar/protocol/OigoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OigoProtocolDecoder.java
diff --git a/src/org/traccar/protocol/OkoProtocol.java b/src/main/java/org/traccar/protocol/OkoProtocol.java
index 9571ccc48..9571ccc48 100644
--- a/src/org/traccar/protocol/OkoProtocol.java
+++ b/src/main/java/org/traccar/protocol/OkoProtocol.java
diff --git a/src/org/traccar/protocol/OkoProtocolDecoder.java b/src/main/java/org/traccar/protocol/OkoProtocolDecoder.java
index 5adf61494..5adf61494 100644
--- a/src/org/traccar/protocol/OkoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OkoProtocolDecoder.java
diff --git a/src/org/traccar/protocol/OpenGtsProtocol.java b/src/main/java/org/traccar/protocol/OpenGtsProtocol.java
index 5ef3260c6..5ef3260c6 100644
--- a/src/org/traccar/protocol/OpenGtsProtocol.java
+++ b/src/main/java/org/traccar/protocol/OpenGtsProtocol.java
diff --git a/src/org/traccar/protocol/OpenGtsProtocolDecoder.java b/src/main/java/org/traccar/protocol/OpenGtsProtocolDecoder.java
index b76cbfa85..b76cbfa85 100644
--- a/src/org/traccar/protocol/OpenGtsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OpenGtsProtocolDecoder.java
diff --git a/src/org/traccar/protocol/OrionFrameDecoder.java b/src/main/java/org/traccar/protocol/OrionFrameDecoder.java
index 948806609..948806609 100644
--- a/src/org/traccar/protocol/OrionFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/OrionFrameDecoder.java
diff --git a/src/org/traccar/protocol/OrionProtocol.java b/src/main/java/org/traccar/protocol/OrionProtocol.java
index 8485ae638..8485ae638 100644
--- a/src/org/traccar/protocol/OrionProtocol.java
+++ b/src/main/java/org/traccar/protocol/OrionProtocol.java
diff --git a/src/org/traccar/protocol/OrionProtocolDecoder.java b/src/main/java/org/traccar/protocol/OrionProtocolDecoder.java
index af819989e..af819989e 100644
--- a/src/org/traccar/protocol/OrionProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OrionProtocolDecoder.java
diff --git a/src/org/traccar/protocol/OsmAndProtocol.java b/src/main/java/org/traccar/protocol/OsmAndProtocol.java
index d3aa2fd6f..d3aa2fd6f 100644
--- a/src/org/traccar/protocol/OsmAndProtocol.java
+++ b/src/main/java/org/traccar/protocol/OsmAndProtocol.java
diff --git a/src/org/traccar/protocol/OsmAndProtocolDecoder.java b/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java
index 3bc71de81..3bc71de81 100644
--- a/src/org/traccar/protocol/OsmAndProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java
diff --git a/src/org/traccar/protocol/OwnTracksProtocol.java b/src/main/java/org/traccar/protocol/OwnTracksProtocol.java
index 0086371d8..0086371d8 100644
--- a/src/org/traccar/protocol/OwnTracksProtocol.java
+++ b/src/main/java/org/traccar/protocol/OwnTracksProtocol.java
diff --git a/src/org/traccar/protocol/OwnTracksProtocolDecoder.java b/src/main/java/org/traccar/protocol/OwnTracksProtocolDecoder.java
index 323d97fa3..323d97fa3 100644
--- a/src/org/traccar/protocol/OwnTracksProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/OwnTracksProtocolDecoder.java
diff --git a/src/org/traccar/protocol/PathAwayProtocol.java b/src/main/java/org/traccar/protocol/PathAwayProtocol.java
index 6b5d75c5e..6b5d75c5e 100644
--- a/src/org/traccar/protocol/PathAwayProtocol.java
+++ b/src/main/java/org/traccar/protocol/PathAwayProtocol.java
diff --git a/src/org/traccar/protocol/PathAwayProtocolDecoder.java b/src/main/java/org/traccar/protocol/PathAwayProtocolDecoder.java
index 02a15e34a..02a15e34a 100644
--- a/src/org/traccar/protocol/PathAwayProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/PathAwayProtocolDecoder.java
diff --git a/src/org/traccar/protocol/PiligrimProtocol.java b/src/main/java/org/traccar/protocol/PiligrimProtocol.java
index d88c1ab72..d88c1ab72 100644
--- a/src/org/traccar/protocol/PiligrimProtocol.java
+++ b/src/main/java/org/traccar/protocol/PiligrimProtocol.java
diff --git a/src/org/traccar/protocol/PiligrimProtocolDecoder.java b/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java
index 47aa86da7..47aa86da7 100644
--- a/src/org/traccar/protocol/PiligrimProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java
diff --git a/src/org/traccar/protocol/PretraceProtocol.java b/src/main/java/org/traccar/protocol/PretraceProtocol.java
index f753cbdb4..f753cbdb4 100644
--- a/src/org/traccar/protocol/PretraceProtocol.java
+++ b/src/main/java/org/traccar/protocol/PretraceProtocol.java
diff --git a/src/org/traccar/protocol/PretraceProtocolDecoder.java b/src/main/java/org/traccar/protocol/PretraceProtocolDecoder.java
index a19384e62..a19384e62 100644
--- a/src/org/traccar/protocol/PretraceProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/PretraceProtocolDecoder.java
diff --git a/src/org/traccar/protocol/PretraceProtocolEncoder.java b/src/main/java/org/traccar/protocol/PretraceProtocolEncoder.java
index 9cf951e3b..9cf951e3b 100644
--- a/src/org/traccar/protocol/PretraceProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/PretraceProtocolEncoder.java
diff --git a/src/org/traccar/protocol/PricolProtocol.java b/src/main/java/org/traccar/protocol/PricolProtocol.java
index 6821cd949..6821cd949 100644
--- a/src/org/traccar/protocol/PricolProtocol.java
+++ b/src/main/java/org/traccar/protocol/PricolProtocol.java
diff --git a/src/org/traccar/protocol/PricolProtocolDecoder.java b/src/main/java/org/traccar/protocol/PricolProtocolDecoder.java
index 190c68258..190c68258 100644
--- a/src/org/traccar/protocol/PricolProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/PricolProtocolDecoder.java
diff --git a/src/org/traccar/protocol/ProgressProtocol.java b/src/main/java/org/traccar/protocol/ProgressProtocol.java
index aac84205d..aac84205d 100644
--- a/src/org/traccar/protocol/ProgressProtocol.java
+++ b/src/main/java/org/traccar/protocol/ProgressProtocol.java
diff --git a/src/org/traccar/protocol/ProgressProtocolDecoder.java b/src/main/java/org/traccar/protocol/ProgressProtocolDecoder.java
index 0025cd9e7..0025cd9e7 100644
--- a/src/org/traccar/protocol/ProgressProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ProgressProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Pt3000Protocol.java b/src/main/java/org/traccar/protocol/Pt3000Protocol.java
index 1ad0026a3..1ad0026a3 100644
--- a/src/org/traccar/protocol/Pt3000Protocol.java
+++ b/src/main/java/org/traccar/protocol/Pt3000Protocol.java
diff --git a/src/org/traccar/protocol/Pt3000ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Pt3000ProtocolDecoder.java
index e7f9e062a..e7f9e062a 100644
--- a/src/org/traccar/protocol/Pt3000ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Pt3000ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Pt502FrameDecoder.java b/src/main/java/org/traccar/protocol/Pt502FrameDecoder.java
index 316cd987f..316cd987f 100644
--- a/src/org/traccar/protocol/Pt502FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Pt502FrameDecoder.java
diff --git a/src/org/traccar/protocol/Pt502Protocol.java b/src/main/java/org/traccar/protocol/Pt502Protocol.java
index 5afb9451d..5afb9451d 100644
--- a/src/org/traccar/protocol/Pt502Protocol.java
+++ b/src/main/java/org/traccar/protocol/Pt502Protocol.java
diff --git a/src/org/traccar/protocol/Pt502ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Pt502ProtocolDecoder.java
index 12210652b..0afec67ad 100644
--- a/src/org/traccar/protocol/Pt502ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Pt502ProtocolDecoder.java
@@ -1,212 +1,212 @@
-/*
- * Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org)
- * Copyright 2012 Luis Parada (luis.parada@gmail.com)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.traccar.protocol;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.Channel;
-import org.traccar.BaseProtocolDecoder;
-import org.traccar.Context;
-import org.traccar.DeviceSession;
-import org.traccar.NetworkMessage;
-import org.traccar.Protocol;
-import org.traccar.helper.DateBuilder;
-import org.traccar.helper.Parser;
-import org.traccar.helper.PatternBuilder;
-import org.traccar.model.Position;
-
-import java.net.SocketAddress;
-import java.nio.charset.StandardCharsets;
-import java.util.regex.Pattern;
-
-public class Pt502ProtocolDecoder extends BaseProtocolDecoder {
-
- private static final int MAX_CHUNK_SIZE = 960;
-
- private ByteBuf photo;
-
- public Pt502ProtocolDecoder(Protocol protocol) {
- super(protocol);
- }
-
- private static final Pattern PATTERN = new PatternBuilder()
- .any().text("$")
- .expression("([^,]+),") // type
- .number("(d+),") // id
- .number("(dd)(dd)(dd).(ddd),") // time (hhmmss.sss)
- .expression("([AV]),") // validity
- .number("(d+)(dd.dddd),") // latitude
- .expression("([NS]),")
- .number("(d+)(dd.dddd),") // longitude
- .expression("([EW]),")
- .number("(d+.d+)?,") // speed
- .number("(d+.d+)?,") // course
- .number("(dd)(dd)(dd),,,") // date (ddmmyy)
- .expression("./")
- .expression("([01])+,") // input
- .expression("([01])+/") // output
- .expression("([^/]+)?/") // adc
- .number("(d+)") // odometer
- .expression("/([^/]+)?/") // rfid
- .number("(xxx)").optional(2) // state
- .any()
- .compile();
-
- private String decodeAlarm(String value) {
- switch (value) {
- case "IN1":
- return Position.ALARM_SOS;
- case "GOF":
- return Position.ALARM_GEOFENCE;
- case "TOW":
- return Position.ALARM_TOW;
- case "HDA":
- return Position.ALARM_ACCELERATION;
- case "HDB":
- return Position.ALARM_BRAKING;
- case "FDA":
- return Position.ALARM_FATIGUE_DRIVING;
- case "SKA":
- return Position.ALARM_VIBRATION;
- case "PMA":
- return Position.ALARM_MOVEMENT;
- case "CPA":
- return Position.ALARM_POWER_CUT;
- default:
- return null;
- }
- }
-
- private Position decodePosition(Channel channel, SocketAddress remoteAddress, String sentence) {
-
- Parser parser = new Parser(PATTERN, sentence);
- if (!parser.matches()) {
- return null;
- }
-
- Position position = new Position(getProtocolName());
- position.set(Position.KEY_ALARM, decodeAlarm(parser.next()));
-
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
- if (deviceSession == null) {
- return null;
- }
- position.setDeviceId(deviceSession.getDeviceId());
-
- DateBuilder dateBuilder = new DateBuilder()
- .setTime(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0), parser.nextInt(0));
-
- position.setValid(parser.next().equals("A"));
- position.setLatitude(parser.nextCoordinate());
- position.setLongitude(parser.nextCoordinate());
- position.setSpeed(parser.nextDouble(0));
- position.setCourse(parser.nextDouble(0));
-
- dateBuilder.setDateReverse(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0));
- position.setTime(dateBuilder.getDate());
-
- position.set(Position.KEY_INPUT, parser.next());
- position.set(Position.KEY_OUTPUT, parser.next());
-
- if (parser.hasNext()) {
- String[] values = parser.next().split(",");
- for (int i = 0; i < values.length; i++) {
- position.set(Position.PREFIX_ADC + (i + 1), Integer.parseInt(values[i], 16));
- }
- }
-
- position.set(Position.KEY_ODOMETER, parser.nextInt(0));
- position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next());
-
- if (parser.hasNext()) {
- int value = parser.nextHexInt(0);
- position.set(Position.KEY_BATTERY, value >> 8);
- position.set(Position.KEY_RSSI, (value >> 4) & 0xf);
- position.set(Position.KEY_SATELLITES, value & 0xf);
- }
-
- return position;
- }
-
- private void requestPhotoFragment(Channel channel) {
- if (channel != null) {
- int offset = photo.writerIndex();
- int size = Math.min(photo.writableBytes(), MAX_CHUNK_SIZE);
- channel.writeAndFlush(new NetworkMessage("#PHD" + offset + "," + size + "\r\n", channel.remoteAddress()));
- }
- }
-
- @Override
- protected Object decode(
- Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
-
- ByteBuf buf = (ByteBuf) msg;
-
- int typeEndIndex = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) ',');
- String type = buf.toString(buf.readerIndex(), typeEndIndex - buf.readerIndex(), StandardCharsets.US_ASCII);
-
- if (type.startsWith("$PHD")) {
-
- int dataIndex = buf.indexOf(typeEndIndex + 1, buf.writerIndex(), (byte) ',') + 1;
- buf.readerIndex(dataIndex);
-
- if (photo != null) {
-
- photo.writeBytes(buf.readSlice(buf.readableBytes()));
-
- if (photo.writableBytes() > 0) {
-
- requestPhotoFragment(channel);
-
- } else {
-
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
- String uniqueId = Context.getIdentityManager().getById(deviceSession.getDeviceId()).getUniqueId();
-
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
-
- getLastLocation(position, null);
-
- position.set(Position.KEY_IMAGE, Context.getMediaManager().writeFile(uniqueId, photo, "jpg"));
- photo.release();
- photo = null;
-
- return position;
-
- }
-
- }
-
- } else {
-
- if (type.startsWith("$PHO")) {
- int size = Integer.parseInt(type.split("-")[0].substring(4));
- if (size > 0) {
- photo = Unpooled.buffer(size);
- requestPhotoFragment(channel);
- }
- }
-
- return decodePosition(channel, remoteAddress, buf.toString(StandardCharsets.US_ASCII));
-
- }
-
- return null;
- }
-
-}
+/*
+ * Copyright 2012 - 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 Luis Parada (luis.parada@gmail.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.Context;
+import org.traccar.DeviceSession;
+import org.traccar.NetworkMessage;
+import org.traccar.Protocol;
+import org.traccar.helper.DateBuilder;
+import org.traccar.helper.Parser;
+import org.traccar.helper.PatternBuilder;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Pattern;
+
+public class Pt502ProtocolDecoder extends BaseProtocolDecoder {
+
+ private static final int MAX_CHUNK_SIZE = 960;
+
+ private ByteBuf photo;
+
+ public Pt502ProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .any().text("$")
+ .expression("([^,]+),") // type
+ .number("(d+),") // id
+ .number("(dd)(dd)(dd).(ddd),") // time (hhmmss.sss)
+ .expression("([AV]),") // validity
+ .number("(d+)(dd.dddd),") // latitude
+ .expression("([NS]),")
+ .number("(d+)(dd.dddd),") // longitude
+ .expression("([EW]),")
+ .number("(d+.d+)?,") // speed
+ .number("(d+.d+)?,") // course
+ .number("(dd)(dd)(dd),,,") // date (ddmmyy)
+ .expression("./")
+ .expression("([01])+,") // input
+ .expression("([01])+/") // output
+ .expression("([^/]+)?/") // adc
+ .number("(d+)") // odometer
+ .expression("/([^/]+)?/") // rfid
+ .number("(xxx)").optional(2) // state
+ .any()
+ .compile();
+
+ private String decodeAlarm(String value) {
+ switch (value) {
+ case "IN1":
+ return Position.ALARM_SOS;
+ case "GOF":
+ return Position.ALARM_GEOFENCE;
+ case "TOW":
+ return Position.ALARM_TOW;
+ case "HDA":
+ return Position.ALARM_ACCELERATION;
+ case "HDB":
+ return Position.ALARM_BRAKING;
+ case "FDA":
+ return Position.ALARM_FATIGUE_DRIVING;
+ case "SKA":
+ return Position.ALARM_VIBRATION;
+ case "PMA":
+ return Position.ALARM_MOVEMENT;
+ case "CPA":
+ return Position.ALARM_POWER_CUT;
+ default:
+ return null;
+ }
+ }
+
+ private Position decodePosition(Channel channel, SocketAddress remoteAddress, String sentence) {
+
+ Parser parser = new Parser(PATTERN, sentence);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.set(Position.KEY_ALARM, decodeAlarm(parser.next()));
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession == null) {
+ return null;
+ }
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ DateBuilder dateBuilder = new DateBuilder()
+ .setTime(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0), parser.nextInt(0));
+
+ position.setValid(parser.next().equals("A"));
+ position.setLatitude(parser.nextCoordinate());
+ position.setLongitude(parser.nextCoordinate());
+ position.setSpeed(parser.nextDouble(0));
+ position.setCourse(parser.nextDouble(0));
+
+ dateBuilder.setDateReverse(parser.nextInt(0), parser.nextInt(0), parser.nextInt(0));
+ position.setTime(dateBuilder.getDate());
+
+ position.set(Position.KEY_INPUT, parser.next());
+ position.set(Position.KEY_OUTPUT, parser.next());
+
+ if (parser.hasNext()) {
+ String[] values = parser.next().split(",");
+ for (int i = 0; i < values.length; i++) {
+ position.set(Position.PREFIX_ADC + (i + 1), Integer.parseInt(values[i], 16));
+ }
+ }
+
+ position.set(Position.KEY_ODOMETER, parser.nextInt(0));
+ position.set(Position.KEY_DRIVER_UNIQUE_ID, parser.next());
+
+ if (parser.hasNext()) {
+ int value = parser.nextHexInt(0);
+ position.set(Position.KEY_BATTERY, value >> 8);
+ position.set(Position.KEY_RSSI, (value >> 4) & 0xf);
+ position.set(Position.KEY_SATELLITES, value & 0xf);
+ }
+
+ return position;
+ }
+
+ private void requestPhotoFragment(Channel channel) {
+ if (channel != null) {
+ int offset = photo.writerIndex();
+ int size = Math.min(photo.writableBytes(), MAX_CHUNK_SIZE);
+ channel.writeAndFlush(new NetworkMessage("#PHD" + offset + "," + size + "\r\n", channel.remoteAddress()));
+ }
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ByteBuf buf = (ByteBuf) msg;
+
+ int typeEndIndex = buf.indexOf(buf.readerIndex(), buf.writerIndex(), (byte) ',');
+ String type = buf.toString(buf.readerIndex(), typeEndIndex - buf.readerIndex(), StandardCharsets.US_ASCII);
+
+ if (type.startsWith("$PHD")) {
+
+ int dataIndex = buf.indexOf(typeEndIndex + 1, buf.writerIndex(), (byte) ',') + 1;
+ buf.readerIndex(dataIndex);
+
+ if (photo != null) {
+
+ photo.writeBytes(buf.readSlice(buf.readableBytes()));
+
+ if (photo.writableBytes() > 0) {
+
+ requestPhotoFragment(channel);
+
+ } else {
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ String uniqueId = Context.getIdentityManager().getById(deviceSession.getDeviceId()).getUniqueId();
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
+
+ position.set(Position.KEY_IMAGE, Context.getMediaManager().writeFile(uniqueId, photo, "jpg"));
+ photo.release();
+ photo = null;
+
+ return position;
+
+ }
+
+ }
+
+ } else {
+
+ if (type.startsWith("$PHO")) {
+ int size = Integer.parseInt(type.split("-")[0].substring(4));
+ if (size > 0) {
+ photo = Unpooled.buffer(size);
+ requestPhotoFragment(channel);
+ }
+ }
+
+ return decodePosition(channel, remoteAddress, buf.toString(StandardCharsets.US_ASCII));
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/org/traccar/protocol/Pt502ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Pt502ProtocolEncoder.java
index ed18208cc..ed18208cc 100644
--- a/src/org/traccar/protocol/Pt502ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Pt502ProtocolEncoder.java
diff --git a/src/org/traccar/protocol/Pt60Protocol.java b/src/main/java/org/traccar/protocol/Pt60Protocol.java
index c502426c5..c502426c5 100644
--- a/src/org/traccar/protocol/Pt60Protocol.java
+++ b/src/main/java/org/traccar/protocol/Pt60Protocol.java
diff --git a/src/org/traccar/protocol/Pt60ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Pt60ProtocolDecoder.java
index 6a3fe2734..6a3fe2734 100644
--- a/src/org/traccar/protocol/Pt60ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Pt60ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/RaveonProtocol.java b/src/main/java/org/traccar/protocol/RaveonProtocol.java
index 44faadb3b..44faadb3b 100644
--- a/src/org/traccar/protocol/RaveonProtocol.java
+++ b/src/main/java/org/traccar/protocol/RaveonProtocol.java
diff --git a/src/org/traccar/protocol/RaveonProtocolDecoder.java b/src/main/java/org/traccar/protocol/RaveonProtocolDecoder.java
index 50acd20a1..50acd20a1 100644
--- a/src/org/traccar/protocol/RaveonProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RaveonProtocolDecoder.java
diff --git a/src/org/traccar/protocol/RecodaProtocol.java b/src/main/java/org/traccar/protocol/RecodaProtocol.java
index 0bc9870bc..0bc9870bc 100644
--- a/src/org/traccar/protocol/RecodaProtocol.java
+++ b/src/main/java/org/traccar/protocol/RecodaProtocol.java
diff --git a/src/org/traccar/protocol/RecodaProtocolDecoder.java b/src/main/java/org/traccar/protocol/RecodaProtocolDecoder.java
index 04098225f..04098225f 100644
--- a/src/org/traccar/protocol/RecodaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RecodaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/RetranslatorFrameDecoder.java b/src/main/java/org/traccar/protocol/RetranslatorFrameDecoder.java
index 4edd09418..4edd09418 100644
--- a/src/org/traccar/protocol/RetranslatorFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/RetranslatorFrameDecoder.java
diff --git a/src/org/traccar/protocol/RetranslatorProtocol.java b/src/main/java/org/traccar/protocol/RetranslatorProtocol.java
index fae81f7d2..fae81f7d2 100644
--- a/src/org/traccar/protocol/RetranslatorProtocol.java
+++ b/src/main/java/org/traccar/protocol/RetranslatorProtocol.java
diff --git a/src/org/traccar/protocol/RetranslatorProtocolDecoder.java b/src/main/java/org/traccar/protocol/RetranslatorProtocolDecoder.java
index 0688c9b0e..0688c9b0e 100644
--- a/src/org/traccar/protocol/RetranslatorProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RetranslatorProtocolDecoder.java
diff --git a/src/org/traccar/protocol/RitiProtocol.java b/src/main/java/org/traccar/protocol/RitiProtocol.java
index de1026672..de1026672 100644
--- a/src/org/traccar/protocol/RitiProtocol.java
+++ b/src/main/java/org/traccar/protocol/RitiProtocol.java
diff --git a/src/org/traccar/protocol/RitiProtocolDecoder.java b/src/main/java/org/traccar/protocol/RitiProtocolDecoder.java
index 46267ca90..46267ca90 100644
--- a/src/org/traccar/protocol/RitiProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RitiProtocolDecoder.java
diff --git a/src/org/traccar/protocol/RoboTrackFrameDecoder.java b/src/main/java/org/traccar/protocol/RoboTrackFrameDecoder.java
index 85ed6c76f..85ed6c76f 100644
--- a/src/org/traccar/protocol/RoboTrackFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/RoboTrackFrameDecoder.java
diff --git a/src/org/traccar/protocol/RoboTrackProtocol.java b/src/main/java/org/traccar/protocol/RoboTrackProtocol.java
index c2c531293..c2c531293 100644
--- a/src/org/traccar/protocol/RoboTrackProtocol.java
+++ b/src/main/java/org/traccar/protocol/RoboTrackProtocol.java
diff --git a/src/org/traccar/protocol/RoboTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/RoboTrackProtocolDecoder.java
index b613f31d7..b613f31d7 100644
--- a/src/org/traccar/protocol/RoboTrackProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RoboTrackProtocolDecoder.java
diff --git a/src/org/traccar/protocol/RuptelaProtocol.java b/src/main/java/org/traccar/protocol/RuptelaProtocol.java
index 1ac62570a..1ac62570a 100644
--- a/src/org/traccar/protocol/RuptelaProtocol.java
+++ b/src/main/java/org/traccar/protocol/RuptelaProtocol.java
diff --git a/src/org/traccar/protocol/RuptelaProtocolDecoder.java b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java
index b043b6201..b043b6201 100644
--- a/src/org/traccar/protocol/RuptelaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/RuptelaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/RuptelaProtocolEncoder.java b/src/main/java/org/traccar/protocol/RuptelaProtocolEncoder.java
index 4242584c9..4242584c9 100644
--- a/src/org/traccar/protocol/RuptelaProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/RuptelaProtocolEncoder.java
diff --git a/src/org/traccar/protocol/SabertekFrameDecoder.java b/src/main/java/org/traccar/protocol/SabertekFrameDecoder.java
index ad5000bf8..ad5000bf8 100644
--- a/src/org/traccar/protocol/SabertekFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/SabertekFrameDecoder.java
diff --git a/src/org/traccar/protocol/SabertekProtocol.java b/src/main/java/org/traccar/protocol/SabertekProtocol.java
index 0ec847b60..0ec847b60 100644
--- a/src/org/traccar/protocol/SabertekProtocol.java
+++ b/src/main/java/org/traccar/protocol/SabertekProtocol.java
diff --git a/src/org/traccar/protocol/SabertekProtocolDecoder.java b/src/main/java/org/traccar/protocol/SabertekProtocolDecoder.java
index 3033aa2cc..3033aa2cc 100644
--- a/src/org/traccar/protocol/SabertekProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SabertekProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SanavProtocol.java b/src/main/java/org/traccar/protocol/SanavProtocol.java
index 6799c57e6..6799c57e6 100644
--- a/src/org/traccar/protocol/SanavProtocol.java
+++ b/src/main/java/org/traccar/protocol/SanavProtocol.java
diff --git a/src/org/traccar/protocol/SanavProtocolDecoder.java b/src/main/java/org/traccar/protocol/SanavProtocolDecoder.java
index 7e1c158e6..7e1c158e6 100644
--- a/src/org/traccar/protocol/SanavProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SanavProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SatsolProtocol.java b/src/main/java/org/traccar/protocol/SatsolProtocol.java
index b69fdd1fe..b69fdd1fe 100644
--- a/src/org/traccar/protocol/SatsolProtocol.java
+++ b/src/main/java/org/traccar/protocol/SatsolProtocol.java
diff --git a/src/org/traccar/protocol/SatsolProtocolDecoder.java b/src/main/java/org/traccar/protocol/SatsolProtocolDecoder.java
index c457d5620..c457d5620 100644
--- a/src/org/traccar/protocol/SatsolProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SatsolProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SigfoxProtocol.java b/src/main/java/org/traccar/protocol/SigfoxProtocol.java
index e2f2cbe1f..e2f2cbe1f 100644
--- a/src/org/traccar/protocol/SigfoxProtocol.java
+++ b/src/main/java/org/traccar/protocol/SigfoxProtocol.java
diff --git a/src/org/traccar/protocol/SigfoxProtocolDecoder.java b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java
index d7836b35d..d7836b35d 100644
--- a/src/org/traccar/protocol/SigfoxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SigfoxProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SiwiProtocol.java b/src/main/java/org/traccar/protocol/SiwiProtocol.java
index 8963721c8..8963721c8 100644
--- a/src/org/traccar/protocol/SiwiProtocol.java
+++ b/src/main/java/org/traccar/protocol/SiwiProtocol.java
diff --git a/src/org/traccar/protocol/SiwiProtocolDecoder.java b/src/main/java/org/traccar/protocol/SiwiProtocolDecoder.java
index 6b97f5fe0..6b97f5fe0 100644
--- a/src/org/traccar/protocol/SiwiProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SiwiProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SkypatrolProtocol.java b/src/main/java/org/traccar/protocol/SkypatrolProtocol.java
index 7c6203d86..7c6203d86 100644
--- a/src/org/traccar/protocol/SkypatrolProtocol.java
+++ b/src/main/java/org/traccar/protocol/SkypatrolProtocol.java
diff --git a/src/org/traccar/protocol/SkypatrolProtocolDecoder.java b/src/main/java/org/traccar/protocol/SkypatrolProtocolDecoder.java
index 3c7ca6dc5..3c7ca6dc5 100644
--- a/src/org/traccar/protocol/SkypatrolProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SkypatrolProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SmartSoleProtocol.java b/src/main/java/org/traccar/protocol/SmartSoleProtocol.java
index bcf43f68b..bcf43f68b 100644
--- a/src/org/traccar/protocol/SmartSoleProtocol.java
+++ b/src/main/java/org/traccar/protocol/SmartSoleProtocol.java
diff --git a/src/org/traccar/protocol/SmartSoleProtocolDecoder.java b/src/main/java/org/traccar/protocol/SmartSoleProtocolDecoder.java
index 04920c969..04920c969 100644
--- a/src/org/traccar/protocol/SmartSoleProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SmartSoleProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SmokeyProtocol.java b/src/main/java/org/traccar/protocol/SmokeyProtocol.java
index 482c8347c..482c8347c 100644
--- a/src/org/traccar/protocol/SmokeyProtocol.java
+++ b/src/main/java/org/traccar/protocol/SmokeyProtocol.java
diff --git a/src/org/traccar/protocol/SmokeyProtocolDecoder.java b/src/main/java/org/traccar/protocol/SmokeyProtocolDecoder.java
index 9da52e97a..9da52e97a 100644
--- a/src/org/traccar/protocol/SmokeyProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SmokeyProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SpotProtocol.java b/src/main/java/org/traccar/protocol/SpotProtocol.java
index bbf0e8d8a..bbf0e8d8a 100644
--- a/src/org/traccar/protocol/SpotProtocol.java
+++ b/src/main/java/org/traccar/protocol/SpotProtocol.java
diff --git a/src/org/traccar/protocol/SpotProtocolDecoder.java b/src/main/java/org/traccar/protocol/SpotProtocolDecoder.java
index da36c2048..da36c2048 100644
--- a/src/org/traccar/protocol/SpotProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SpotProtocolDecoder.java
diff --git a/src/org/traccar/protocol/StarLinkProtocol.java b/src/main/java/org/traccar/protocol/StarLinkProtocol.java
index 5630722ee..5630722ee 100644
--- a/src/org/traccar/protocol/StarLinkProtocol.java
+++ b/src/main/java/org/traccar/protocol/StarLinkProtocol.java
diff --git a/src/org/traccar/protocol/StarLinkProtocolDecoder.java b/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java
index ed5f81c1c..ed5f81c1c 100644
--- a/src/org/traccar/protocol/StarLinkProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/StarLinkProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Stl060FrameDecoder.java b/src/main/java/org/traccar/protocol/Stl060FrameDecoder.java
index f72474e2b..f72474e2b 100644
--- a/src/org/traccar/protocol/Stl060FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Stl060FrameDecoder.java
diff --git a/src/org/traccar/protocol/Stl060Protocol.java b/src/main/java/org/traccar/protocol/Stl060Protocol.java
index 2711e936b..2711e936b 100644
--- a/src/org/traccar/protocol/Stl060Protocol.java
+++ b/src/main/java/org/traccar/protocol/Stl060Protocol.java
diff --git a/src/org/traccar/protocol/Stl060ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Stl060ProtocolDecoder.java
index 7b0055aa1..7b0055aa1 100644
--- a/src/org/traccar/protocol/Stl060ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Stl060ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SuntechProtocol.java b/src/main/java/org/traccar/protocol/SuntechProtocol.java
index 29ae114e7..29ae114e7 100644
--- a/src/org/traccar/protocol/SuntechProtocol.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocol.java
diff --git a/src/org/traccar/protocol/SuntechProtocolDecoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
index 922431021..922431021 100644
--- a/src/org/traccar/protocol/SuntechProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SuntechProtocolEncoder.java b/src/main/java/org/traccar/protocol/SuntechProtocolEncoder.java
index 90fa4aa39..90fa4aa39 100644
--- a/src/org/traccar/protocol/SuntechProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/SuntechProtocolEncoder.java
diff --git a/src/org/traccar/protocol/SupermateProtocol.java b/src/main/java/org/traccar/protocol/SupermateProtocol.java
index 46625ddc7..46625ddc7 100644
--- a/src/org/traccar/protocol/SupermateProtocol.java
+++ b/src/main/java/org/traccar/protocol/SupermateProtocol.java
diff --git a/src/org/traccar/protocol/SupermateProtocolDecoder.java b/src/main/java/org/traccar/protocol/SupermateProtocolDecoder.java
index 40a25bb91..40a25bb91 100644
--- a/src/org/traccar/protocol/SupermateProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SupermateProtocolDecoder.java
diff --git a/src/org/traccar/protocol/SviasProtocol.java b/src/main/java/org/traccar/protocol/SviasProtocol.java
index c6624b7d4..f01f28389 100644
--- a/src/org/traccar/protocol/SviasProtocol.java
+++ b/src/main/java/org/traccar/protocol/SviasProtocol.java
@@ -1,51 +1,51 @@
-/*
- * Copyright 2018 Anton Tananaev (anton@traccar.org)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.traccar.protocol;
-
-import io.netty.handler.codec.string.StringDecoder;
-import io.netty.handler.codec.string.StringEncoder;
-import org.traccar.BaseProtocol;
-import org.traccar.CharacterDelimiterFrameDecoder;
-import org.traccar.PipelineBuilder;
-import org.traccar.TrackerServer;
-
-import org.traccar.model.Command;
-
-public class SviasProtocol extends BaseProtocol {
-
- public SviasProtocol() {
- setSupportedDataCommands(
- Command.TYPE_CUSTOM,
- Command.TYPE_POSITION_SINGLE,
- Command.TYPE_SET_ODOMETER,
- Command.TYPE_ENGINE_STOP,
- Command.TYPE_ENGINE_RESUME,
- Command.TYPE_ALARM_ARM,
- Command.TYPE_ALARM_DISARM,
- Command.TYPE_ALARM_REMOVE);
- addServer(new TrackerServer(false, getName()) {
- @Override
- protected void addProtocolHandlers(PipelineBuilder pipeline) {
- pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, "]"));
- pipeline.addLast(new StringEncoder());
- pipeline.addLast(new StringDecoder());
- pipeline.addLast(new SviasProtocolEncoder());
- pipeline.addLast(new SviasProtocolDecoder(SviasProtocol.this));
- }
- });
- }
-
-}
+/*
+ * Copyright 2018 Anton Tananaev (anton@traccar.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import org.traccar.BaseProtocol;
+import org.traccar.CharacterDelimiterFrameDecoder;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+
+import org.traccar.model.Command;
+
+public class SviasProtocol extends BaseProtocol {
+
+ public SviasProtocol() {
+ setSupportedDataCommands(
+ Command.TYPE_CUSTOM,
+ Command.TYPE_POSITION_SINGLE,
+ Command.TYPE_SET_ODOMETER,
+ Command.TYPE_ENGINE_STOP,
+ Command.TYPE_ENGINE_RESUME,
+ Command.TYPE_ALARM_ARM,
+ Command.TYPE_ALARM_DISARM,
+ Command.TYPE_ALARM_REMOVE);
+ addServer(new TrackerServer(false, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new CharacterDelimiterFrameDecoder(1024, "]"));
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new SviasProtocolEncoder());
+ pipeline.addLast(new SviasProtocolDecoder(SviasProtocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/org/traccar/protocol/SviasProtocolDecoder.java b/src/main/java/org/traccar/protocol/SviasProtocolDecoder.java
index 978483175..7e783f6cd 100644
--- a/src/org/traccar/protocol/SviasProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/SviasProtocolDecoder.java
@@ -1,105 +1,105 @@
-/*
- * Copyright 2018 Anton Tananaev (anton@traccar.org)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.traccar.protocol;
-
-import io.netty.channel.Channel;
-import org.traccar.BaseProtocolDecoder;
-import org.traccar.NetworkMessage;
-import org.traccar.Protocol;
-import org.traccar.helper.BitUtil;
-import org.traccar.helper.PatternBuilder;
-
-import java.net.SocketAddress;
-import java.util.regex.Pattern;
-import org.traccar.DeviceSession;
-import org.traccar.helper.Parser;
-import org.traccar.helper.UnitsConverter;
-import org.traccar.model.Position;
-
-public class SviasProtocolDecoder extends BaseProtocolDecoder {
-
- public SviasProtocolDecoder(Protocol protocol) {
- super(protocol);
- }
-
- private static final Pattern PATTERN = new PatternBuilder()
- .text("[") // delimiter
- .number("d{4},") // hardware version
- .number("d{4},") // software version
- .number("d+,") // index
- .number("(d+),") // imei
- .number("d+,") // hour meter
- .number("(d+)(dd)(dd),") // date (dmmyy)
- .number("(d+)(dd)(dd),") // time (hmmss)
- .number("(-?)(d+)(dd)(d{5}),") // latitude
- .number("(-?)(d+)(dd)(d{5}),") // longitude
- .number("(d+),") // speed
- .number("(d+),") // course
- .number("(d+),") // odometer
- .number("(d+),") // input
- .number("(d+),") // output / status
- .number("(d),")
- .number("(d),")
- .number("(d+),") // power
- .number("(d+),") // battery level
- .number("(d+),") // rssi
- .any()
- .compile();
-
- @Override
- protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg)
- throws Exception {
-
- if (channel != null) {
- channel.writeAndFlush(new NetworkMessage("@", remoteAddress));
- }
-
- Parser parser = new Parser(PATTERN, (String) msg);
- if (!parser.matches()) {
- return null;
- }
-
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
- if (deviceSession == null) {
- return null;
- }
-
- Position position = new Position(getProtocolName());
- position.setDeviceId(deviceSession.getDeviceId());
-
- position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
- position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN_MIN));
- position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN_MIN));
- position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble() * 0.01));
- position.setCourse(parser.nextDouble() * 0.01);
-
- position.set(Position.KEY_ODOMETER, parser.nextInt() * 100);
-
- int input = parser.nextInt();
- int output = parser.nextInt();
-
- position.set(Position.KEY_ALARM, BitUtil.check(input, 0) ? Position.ALARM_SOS : null);
- position.set(Position.KEY_IGNITION, BitUtil.check(input, 4));
- position.setValid(BitUtil.check(output, 0));
-
- position.set(Position.KEY_POWER, parser.nextInt() * 0.001);
- position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
- position.set(Position.KEY_RSSI, parser.nextInt());
-
- return position;
- }
-
-}
+/*
+ * Copyright 2018 Anton Tananaev (anton@traccar.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.NetworkMessage;
+import org.traccar.Protocol;
+import org.traccar.helper.BitUtil;
+import org.traccar.helper.PatternBuilder;
+
+import java.net.SocketAddress;
+import java.util.regex.Pattern;
+import org.traccar.DeviceSession;
+import org.traccar.helper.Parser;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+public class SviasProtocolDecoder extends BaseProtocolDecoder {
+
+ public SviasProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private static final Pattern PATTERN = new PatternBuilder()
+ .text("[") // delimiter
+ .number("d{4},") // hardware version
+ .number("d{4},") // software version
+ .number("d+,") // index
+ .number("(d+),") // imei
+ .number("d+,") // hour meter
+ .number("(d+)(dd)(dd),") // date (dmmyy)
+ .number("(d+)(dd)(dd),") // time (hmmss)
+ .number("(-?)(d+)(dd)(d{5}),") // latitude
+ .number("(-?)(d+)(dd)(d{5}),") // longitude
+ .number("(d+),") // speed
+ .number("(d+),") // course
+ .number("(d+),") // odometer
+ .number("(d+),") // input
+ .number("(d+),") // output / status
+ .number("(d),")
+ .number("(d),")
+ .number("(d+),") // power
+ .number("(d+),") // battery level
+ .number("(d+),") // rssi
+ .any()
+ .compile();
+
+ @Override
+ protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg)
+ throws Exception {
+
+ if (channel != null) {
+ channel.writeAndFlush(new NetworkMessage("@", remoteAddress));
+ }
+
+ Parser parser = new Parser(PATTERN, (String) msg);
+ if (!parser.matches()) {
+ return null;
+ }
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, parser.next());
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.setTime(parser.nextDateTime(Parser.DateTimeFormat.DMY_HMS));
+ position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN_MIN));
+ position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG_MIN_MIN));
+ position.setSpeed(UnitsConverter.knotsFromKph(parser.nextDouble() * 0.01));
+ position.setCourse(parser.nextDouble() * 0.01);
+
+ position.set(Position.KEY_ODOMETER, parser.nextInt() * 100);
+
+ int input = parser.nextInt();
+ int output = parser.nextInt();
+
+ position.set(Position.KEY_ALARM, BitUtil.check(input, 0) ? Position.ALARM_SOS : null);
+ position.set(Position.KEY_IGNITION, BitUtil.check(input, 4));
+ position.setValid(BitUtil.check(output, 0));
+
+ position.set(Position.KEY_POWER, parser.nextInt() * 0.001);
+ position.set(Position.KEY_BATTERY_LEVEL, parser.nextInt());
+ position.set(Position.KEY_RSSI, parser.nextInt());
+
+ return position;
+ }
+
+}
diff --git a/src/org/traccar/protocol/SviasProtocolEncoder.java b/src/main/java/org/traccar/protocol/SviasProtocolEncoder.java
index 9fce57223..8bfbef119 100644
--- a/src/org/traccar/protocol/SviasProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/SviasProtocolEncoder.java
@@ -1,48 +1,48 @@
-/*
- * Copyright 2018 Anton Tananaev (anton@traccar.org)
- * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.traccar.protocol;
-
-import org.traccar.StringProtocolEncoder;
-import org.traccar.model.Command;
-
-public class SviasProtocolEncoder extends StringProtocolEncoder {
-
- @Override
- protected Object encodeCommand(Command command) {
- switch (command.getType()) {
- case Command.TYPE_CUSTOM:
- return formatCommand(command, "{%s}", Command.KEY_DATA);
- case Command.TYPE_POSITION_SINGLE:
- return formatCommand(command, "AT+STR=1*");
- case Command.TYPE_SET_ODOMETER:
- return formatCommand(command, "AT+ODT={%s}*", Command.KEY_DATA);
- case Command.TYPE_ENGINE_STOP:
- return formatCommand(command, "AT+OUT=1,1*");
- case Command.TYPE_ENGINE_RESUME:
- return formatCommand(command, "AT+OUT=1,0*");
- case Command.TYPE_ALARM_ARM:
- return formatCommand(command, "AT+OUT=2,1*");
- case Command.TYPE_ALARM_DISARM:
- return formatCommand(command, "AT+OUT=2,0*");
- case Command.TYPE_ALARM_REMOVE:
- return formatCommand(command, "AT+PNC=600*");
- default:
- return null;
- }
- }
-
-}
+/*
+ * Copyright 2018 Anton Tananaev (anton@traccar.org)
+ * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import org.traccar.StringProtocolEncoder;
+import org.traccar.model.Command;
+
+public class SviasProtocolEncoder extends StringProtocolEncoder {
+
+ @Override
+ protected Object encodeCommand(Command command) {
+ switch (command.getType()) {
+ case Command.TYPE_CUSTOM:
+ return formatCommand(command, "{%s}", Command.KEY_DATA);
+ case Command.TYPE_POSITION_SINGLE:
+ return formatCommand(command, "AT+STR=1*");
+ case Command.TYPE_SET_ODOMETER:
+ return formatCommand(command, "AT+ODT={%s}*", Command.KEY_DATA);
+ case Command.TYPE_ENGINE_STOP:
+ return formatCommand(command, "AT+OUT=1,1*");
+ case Command.TYPE_ENGINE_RESUME:
+ return formatCommand(command, "AT+OUT=1,0*");
+ case Command.TYPE_ALARM_ARM:
+ return formatCommand(command, "AT+OUT=2,1*");
+ case Command.TYPE_ALARM_DISARM:
+ return formatCommand(command, "AT+OUT=2,0*");
+ case Command.TYPE_ALARM_REMOVE:
+ return formatCommand(command, "AT+PNC=600*");
+ default:
+ return null;
+ }
+ }
+
+}
diff --git a/src/org/traccar/protocol/T55Protocol.java b/src/main/java/org/traccar/protocol/T55Protocol.java
index f5ec19094..f5ec19094 100644
--- a/src/org/traccar/protocol/T55Protocol.java
+++ b/src/main/java/org/traccar/protocol/T55Protocol.java
diff --git a/src/org/traccar/protocol/T55ProtocolDecoder.java b/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java
index ba231a635..ba231a635 100644
--- a/src/org/traccar/protocol/T55ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/T55ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/T57FrameDecoder.java b/src/main/java/org/traccar/protocol/T57FrameDecoder.java
index 14ba31453..14ba31453 100644
--- a/src/org/traccar/protocol/T57FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/T57FrameDecoder.java
diff --git a/src/org/traccar/protocol/T57Protocol.java b/src/main/java/org/traccar/protocol/T57Protocol.java
index f67f82318..f67f82318 100644
--- a/src/org/traccar/protocol/T57Protocol.java
+++ b/src/main/java/org/traccar/protocol/T57Protocol.java
diff --git a/src/org/traccar/protocol/T57ProtocolDecoder.java b/src/main/java/org/traccar/protocol/T57ProtocolDecoder.java
index 2a3cca3e4..2a3cca3e4 100644
--- a/src/org/traccar/protocol/T57ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/T57ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/T800xProtocol.java b/src/main/java/org/traccar/protocol/T800xProtocol.java
index 85749d0cf..85749d0cf 100644
--- a/src/org/traccar/protocol/T800xProtocol.java
+++ b/src/main/java/org/traccar/protocol/T800xProtocol.java
diff --git a/src/org/traccar/protocol/T800xProtocolDecoder.java b/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java
index dfb286257..dfb286257 100644
--- a/src/org/traccar/protocol/T800xProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/T800xProtocolDecoder.java
diff --git a/src/org/traccar/protocol/T800xProtocolEncoder.java b/src/main/java/org/traccar/protocol/T800xProtocolEncoder.java
index 1d0f3dabe..1d0f3dabe 100644
--- a/src/org/traccar/protocol/T800xProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/T800xProtocolEncoder.java
diff --git a/src/org/traccar/protocol/TaipProtocol.java b/src/main/java/org/traccar/protocol/TaipProtocol.java
index b8f40a183..b8f40a183 100644
--- a/src/org/traccar/protocol/TaipProtocol.java
+++ b/src/main/java/org/traccar/protocol/TaipProtocol.java
diff --git a/src/org/traccar/protocol/TaipProtocolDecoder.java b/src/main/java/org/traccar/protocol/TaipProtocolDecoder.java
index 8a0cb870b..8a0cb870b 100644
--- a/src/org/traccar/protocol/TaipProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TaipProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TekFrameDecoder.java b/src/main/java/org/traccar/protocol/TekFrameDecoder.java
index 44d2c590e..44d2c590e 100644
--- a/src/org/traccar/protocol/TekFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TekFrameDecoder.java
diff --git a/src/org/traccar/protocol/TekProtocol.java b/src/main/java/org/traccar/protocol/TekProtocol.java
index c1d78e6f5..c1d78e6f5 100644
--- a/src/org/traccar/protocol/TekProtocol.java
+++ b/src/main/java/org/traccar/protocol/TekProtocol.java
diff --git a/src/org/traccar/protocol/TekProtocolDecoder.java b/src/main/java/org/traccar/protocol/TekProtocolDecoder.java
index a9101e65f..a9101e65f 100644
--- a/src/org/traccar/protocol/TekProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TekProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TelemaxProtocol.java b/src/main/java/org/traccar/protocol/TelemaxProtocol.java
index 838da9df1..838da9df1 100644
--- a/src/org/traccar/protocol/TelemaxProtocol.java
+++ b/src/main/java/org/traccar/protocol/TelemaxProtocol.java
diff --git a/src/org/traccar/protocol/TelemaxProtocolDecoder.java b/src/main/java/org/traccar/protocol/TelemaxProtocolDecoder.java
index 9369ab101..9369ab101 100644
--- a/src/org/traccar/protocol/TelemaxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TelemaxProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TelicFrameDecoder.java b/src/main/java/org/traccar/protocol/TelicFrameDecoder.java
index d1fef1b5b..d1fef1b5b 100644
--- a/src/org/traccar/protocol/TelicFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TelicFrameDecoder.java
diff --git a/src/org/traccar/protocol/TelicProtocol.java b/src/main/java/org/traccar/protocol/TelicProtocol.java
index 991befa19..991befa19 100644
--- a/src/org/traccar/protocol/TelicProtocol.java
+++ b/src/main/java/org/traccar/protocol/TelicProtocol.java
diff --git a/src/org/traccar/protocol/TelicProtocolDecoder.java b/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java
index 6d5e8f21e..6d5e8f21e 100644
--- a/src/org/traccar/protocol/TelicProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TelicProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TeltonikaFrameDecoder.java b/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java
index 4d4d79d8d..4d4d79d8d 100644
--- a/src/org/traccar/protocol/TeltonikaFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaFrameDecoder.java
diff --git a/src/org/traccar/protocol/TeltonikaProtocol.java b/src/main/java/org/traccar/protocol/TeltonikaProtocol.java
index eef9662d7..eef9662d7 100644
--- a/src/org/traccar/protocol/TeltonikaProtocol.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaProtocol.java
diff --git a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java b/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java
index 974d2c106..974d2c106 100644
--- a/src/org/traccar/protocol/TeltonikaProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TeltonikaProtocolEncoder.java b/src/main/java/org/traccar/protocol/TeltonikaProtocolEncoder.java
index 944cec024..944cec024 100644
--- a/src/org/traccar/protocol/TeltonikaProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/TeltonikaProtocolEncoder.java
diff --git a/src/org/traccar/protocol/ThinkRaceProtocol.java b/src/main/java/org/traccar/protocol/ThinkRaceProtocol.java
index ca1237cef..ca1237cef 100644
--- a/src/org/traccar/protocol/ThinkRaceProtocol.java
+++ b/src/main/java/org/traccar/protocol/ThinkRaceProtocol.java
diff --git a/src/org/traccar/protocol/ThinkRaceProtocolDecoder.java b/src/main/java/org/traccar/protocol/ThinkRaceProtocolDecoder.java
index 0928b25e0..0928b25e0 100644
--- a/src/org/traccar/protocol/ThinkRaceProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/ThinkRaceProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Tk102Protocol.java b/src/main/java/org/traccar/protocol/Tk102Protocol.java
index 9f2463cd6..9f2463cd6 100644
--- a/src/org/traccar/protocol/Tk102Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tk102Protocol.java
diff --git a/src/org/traccar/protocol/Tk102ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tk102ProtocolDecoder.java
index da0c6928b..da0c6928b 100644
--- a/src/org/traccar/protocol/Tk102ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tk102ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Tk103FrameDecoder.java b/src/main/java/org/traccar/protocol/Tk103FrameDecoder.java
index b61a42563..b61a42563 100644
--- a/src/org/traccar/protocol/Tk103FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tk103FrameDecoder.java
diff --git a/src/org/traccar/protocol/Tk103Protocol.java b/src/main/java/org/traccar/protocol/Tk103Protocol.java
index fa83133e2..fa83133e2 100644
--- a/src/org/traccar/protocol/Tk103Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tk103Protocol.java
diff --git a/src/org/traccar/protocol/Tk103ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java
index 9e28b5051..9e28b5051 100644
--- a/src/org/traccar/protocol/Tk103ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tk103ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Tk103ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Tk103ProtocolEncoder.java
index 98edc8cb5..98edc8cb5 100644
--- a/src/org/traccar/protocol/Tk103ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Tk103ProtocolEncoder.java
diff --git a/src/org/traccar/protocol/Tlt2hProtocol.java b/src/main/java/org/traccar/protocol/Tlt2hProtocol.java
index 12fd92afa..12fd92afa 100644
--- a/src/org/traccar/protocol/Tlt2hProtocol.java
+++ b/src/main/java/org/traccar/protocol/Tlt2hProtocol.java
diff --git a/src/org/traccar/protocol/Tlt2hProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java
index f67ff88db..f67ff88db 100644
--- a/src/org/traccar/protocol/Tlt2hProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tlt2hProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TlvProtocol.java b/src/main/java/org/traccar/protocol/TlvProtocol.java
index 94f5da94f..94f5da94f 100644
--- a/src/org/traccar/protocol/TlvProtocol.java
+++ b/src/main/java/org/traccar/protocol/TlvProtocol.java
diff --git a/src/org/traccar/protocol/TlvProtocolDecoder.java b/src/main/java/org/traccar/protocol/TlvProtocolDecoder.java
index 36cf7859f..36cf7859f 100644
--- a/src/org/traccar/protocol/TlvProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TlvProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TmgFrameDecoder.java b/src/main/java/org/traccar/protocol/TmgFrameDecoder.java
index 205adaa51..205adaa51 100644
--- a/src/org/traccar/protocol/TmgFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TmgFrameDecoder.java
diff --git a/src/org/traccar/protocol/TmgProtocol.java b/src/main/java/org/traccar/protocol/TmgProtocol.java
index 020332ce7..020332ce7 100644
--- a/src/org/traccar/protocol/TmgProtocol.java
+++ b/src/main/java/org/traccar/protocol/TmgProtocol.java
diff --git a/src/org/traccar/protocol/TmgProtocolDecoder.java b/src/main/java/org/traccar/protocol/TmgProtocolDecoder.java
index d27849f8c..d27849f8c 100644
--- a/src/org/traccar/protocol/TmgProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TmgProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TopflytechProtocol.java b/src/main/java/org/traccar/protocol/TopflytechProtocol.java
index 303072bdb..303072bdb 100644
--- a/src/org/traccar/protocol/TopflytechProtocol.java
+++ b/src/main/java/org/traccar/protocol/TopflytechProtocol.java
diff --git a/src/org/traccar/protocol/TopflytechProtocolDecoder.java b/src/main/java/org/traccar/protocol/TopflytechProtocolDecoder.java
index 6de053c32..6de053c32 100644
--- a/src/org/traccar/protocol/TopflytechProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TopflytechProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TotemFrameDecoder.java b/src/main/java/org/traccar/protocol/TotemFrameDecoder.java
index 3fa5abc7a..3fa5abc7a 100644
--- a/src/org/traccar/protocol/TotemFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TotemFrameDecoder.java
diff --git a/src/org/traccar/protocol/TotemProtocol.java b/src/main/java/org/traccar/protocol/TotemProtocol.java
index 66e1ec4f1..66e1ec4f1 100644
--- a/src/org/traccar/protocol/TotemProtocol.java
+++ b/src/main/java/org/traccar/protocol/TotemProtocol.java
diff --git a/src/org/traccar/protocol/TotemProtocolDecoder.java b/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java
index cd7f684b8..cd7f684b8 100644
--- a/src/org/traccar/protocol/TotemProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TotemProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TotemProtocolEncoder.java b/src/main/java/org/traccar/protocol/TotemProtocolEncoder.java
index b5049859d..b5049859d 100644
--- a/src/org/traccar/protocol/TotemProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/TotemProtocolEncoder.java
diff --git a/src/org/traccar/protocol/Tr20Protocol.java b/src/main/java/org/traccar/protocol/Tr20Protocol.java
index 3eee9d9c3..3eee9d9c3 100644
--- a/src/org/traccar/protocol/Tr20Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tr20Protocol.java
diff --git a/src/org/traccar/protocol/Tr20ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tr20ProtocolDecoder.java
index c2e6c381f..c2e6c381f 100644
--- a/src/org/traccar/protocol/Tr20ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tr20ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Tr900Protocol.java b/src/main/java/org/traccar/protocol/Tr900Protocol.java
index b70521b35..b70521b35 100644
--- a/src/org/traccar/protocol/Tr900Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tr900Protocol.java
diff --git a/src/org/traccar/protocol/Tr900ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tr900ProtocolDecoder.java
index 319194c21..319194c21 100644
--- a/src/org/traccar/protocol/Tr900ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tr900ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TrackboxProtocol.java b/src/main/java/org/traccar/protocol/TrackboxProtocol.java
index 5da5abd64..5da5abd64 100644
--- a/src/org/traccar/protocol/TrackboxProtocol.java
+++ b/src/main/java/org/traccar/protocol/TrackboxProtocol.java
diff --git a/src/org/traccar/protocol/TrackboxProtocolDecoder.java b/src/main/java/org/traccar/protocol/TrackboxProtocolDecoder.java
index db8022738..db8022738 100644
--- a/src/org/traccar/protocol/TrackboxProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TrackboxProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TrakMateProtocol.java b/src/main/java/org/traccar/protocol/TrakMateProtocol.java
index bda5df10f..bda5df10f 100644
--- a/src/org/traccar/protocol/TrakMateProtocol.java
+++ b/src/main/java/org/traccar/protocol/TrakMateProtocol.java
diff --git a/src/org/traccar/protocol/TrakMateProtocolDecoder.java b/src/main/java/org/traccar/protocol/TrakMateProtocolDecoder.java
index 4d5cb18f5..4d5cb18f5 100644
--- a/src/org/traccar/protocol/TrakMateProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TrakMateProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TramigoFrameDecoder.java b/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java
index aaaaccb60..aaaaccb60 100644
--- a/src/org/traccar/protocol/TramigoFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/TramigoFrameDecoder.java
diff --git a/src/org/traccar/protocol/TramigoProtocol.java b/src/main/java/org/traccar/protocol/TramigoProtocol.java
index f683ccc5d..f683ccc5d 100644
--- a/src/org/traccar/protocol/TramigoProtocol.java
+++ b/src/main/java/org/traccar/protocol/TramigoProtocol.java
diff --git a/src/org/traccar/protocol/TramigoProtocolDecoder.java b/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java
index e42e2f670..e42e2f670 100644
--- a/src/org/traccar/protocol/TramigoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TrvProtocol.java b/src/main/java/org/traccar/protocol/TrvProtocol.java
index 99a164cf1..99a164cf1 100644
--- a/src/org/traccar/protocol/TrvProtocol.java
+++ b/src/main/java/org/traccar/protocol/TrvProtocol.java
diff --git a/src/org/traccar/protocol/TrvProtocolDecoder.java b/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java
index b63385187..b63385187 100644
--- a/src/org/traccar/protocol/TrvProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Tt8850Protocol.java b/src/main/java/org/traccar/protocol/Tt8850Protocol.java
index 66a13da9e..66a13da9e 100644
--- a/src/org/traccar/protocol/Tt8850Protocol.java
+++ b/src/main/java/org/traccar/protocol/Tt8850Protocol.java
diff --git a/src/org/traccar/protocol/Tt8850ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Tt8850ProtocolDecoder.java
index 1010528c4..1010528c4 100644
--- a/src/org/traccar/protocol/Tt8850ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Tt8850ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TytanProtocol.java b/src/main/java/org/traccar/protocol/TytanProtocol.java
index 32e9acae1..32e9acae1 100644
--- a/src/org/traccar/protocol/TytanProtocol.java
+++ b/src/main/java/org/traccar/protocol/TytanProtocol.java
diff --git a/src/org/traccar/protocol/TytanProtocolDecoder.java b/src/main/java/org/traccar/protocol/TytanProtocolDecoder.java
index 93d3a63d2..93d3a63d2 100644
--- a/src/org/traccar/protocol/TytanProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TytanProtocolDecoder.java
diff --git a/src/org/traccar/protocol/TzoneProtocol.java b/src/main/java/org/traccar/protocol/TzoneProtocol.java
index 6e855d138..6e855d138 100644
--- a/src/org/traccar/protocol/TzoneProtocol.java
+++ b/src/main/java/org/traccar/protocol/TzoneProtocol.java
diff --git a/src/org/traccar/protocol/TzoneProtocolDecoder.java b/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java
index 87b44a4b2..87b44a4b2 100644
--- a/src/org/traccar/protocol/TzoneProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java
diff --git a/src/org/traccar/protocol/UlbotechFrameDecoder.java b/src/main/java/org/traccar/protocol/UlbotechFrameDecoder.java
index f141dc9b7..f141dc9b7 100644
--- a/src/org/traccar/protocol/UlbotechFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/UlbotechFrameDecoder.java
diff --git a/src/org/traccar/protocol/UlbotechProtocol.java b/src/main/java/org/traccar/protocol/UlbotechProtocol.java
index b99ec1cc6..b99ec1cc6 100644
--- a/src/org/traccar/protocol/UlbotechProtocol.java
+++ b/src/main/java/org/traccar/protocol/UlbotechProtocol.java
diff --git a/src/org/traccar/protocol/UlbotechProtocolDecoder.java b/src/main/java/org/traccar/protocol/UlbotechProtocolDecoder.java
index 0a2a59e23..0a2a59e23 100644
--- a/src/org/traccar/protocol/UlbotechProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/UlbotechProtocolDecoder.java
diff --git a/src/org/traccar/protocol/UproProtocol.java b/src/main/java/org/traccar/protocol/UproProtocol.java
index 4e60ffeb6..4e60ffeb6 100644
--- a/src/org/traccar/protocol/UproProtocol.java
+++ b/src/main/java/org/traccar/protocol/UproProtocol.java
diff --git a/src/org/traccar/protocol/UproProtocolDecoder.java b/src/main/java/org/traccar/protocol/UproProtocolDecoder.java
index dc7a9200d..dc7a9200d 100644
--- a/src/org/traccar/protocol/UproProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/UproProtocolDecoder.java
diff --git a/src/org/traccar/protocol/V680Protocol.java b/src/main/java/org/traccar/protocol/V680Protocol.java
index dc0922cd4..dc0922cd4 100644
--- a/src/org/traccar/protocol/V680Protocol.java
+++ b/src/main/java/org/traccar/protocol/V680Protocol.java
diff --git a/src/org/traccar/protocol/V680ProtocolDecoder.java b/src/main/java/org/traccar/protocol/V680ProtocolDecoder.java
index 0342404a6..0342404a6 100644
--- a/src/org/traccar/protocol/V680ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/V680ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/VisiontekProtocol.java b/src/main/java/org/traccar/protocol/VisiontekProtocol.java
index 2c6af45a8..2c6af45a8 100644
--- a/src/org/traccar/protocol/VisiontekProtocol.java
+++ b/src/main/java/org/traccar/protocol/VisiontekProtocol.java
diff --git a/src/org/traccar/protocol/VisiontekProtocolDecoder.java b/src/main/java/org/traccar/protocol/VisiontekProtocolDecoder.java
index c4787bda2..c4787bda2 100644
--- a/src/org/traccar/protocol/VisiontekProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/VisiontekProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Vt200FrameDecoder.java b/src/main/java/org/traccar/protocol/Vt200FrameDecoder.java
index 0fd83e715..0fd83e715 100644
--- a/src/org/traccar/protocol/Vt200FrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/Vt200FrameDecoder.java
diff --git a/src/org/traccar/protocol/Vt200Protocol.java b/src/main/java/org/traccar/protocol/Vt200Protocol.java
index 2a9ef6ab5..2a9ef6ab5 100644
--- a/src/org/traccar/protocol/Vt200Protocol.java
+++ b/src/main/java/org/traccar/protocol/Vt200Protocol.java
diff --git a/src/org/traccar/protocol/Vt200ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Vt200ProtocolDecoder.java
index b1564abd9..b1564abd9 100644
--- a/src/org/traccar/protocol/Vt200ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Vt200ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/VtfmsFrameDecoder.java b/src/main/java/org/traccar/protocol/VtfmsFrameDecoder.java
index 62a189960..62a189960 100644
--- a/src/org/traccar/protocol/VtfmsFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/VtfmsFrameDecoder.java
diff --git a/src/org/traccar/protocol/VtfmsProtocol.java b/src/main/java/org/traccar/protocol/VtfmsProtocol.java
index 2826a86e6..2826a86e6 100644
--- a/src/org/traccar/protocol/VtfmsProtocol.java
+++ b/src/main/java/org/traccar/protocol/VtfmsProtocol.java
diff --git a/src/org/traccar/protocol/VtfmsProtocolDecoder.java b/src/main/java/org/traccar/protocol/VtfmsProtocolDecoder.java
index 17fac4311..17fac4311 100644
--- a/src/org/traccar/protocol/VtfmsProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/VtfmsProtocolDecoder.java
diff --git a/src/org/traccar/protocol/WatchFrameDecoder.java b/src/main/java/org/traccar/protocol/WatchFrameDecoder.java
index f99bd52e2..f99bd52e2 100644
--- a/src/org/traccar/protocol/WatchFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/WatchFrameDecoder.java
diff --git a/src/org/traccar/protocol/WatchProtocol.java b/src/main/java/org/traccar/protocol/WatchProtocol.java
index fe285e70d..fe285e70d 100644
--- a/src/org/traccar/protocol/WatchProtocol.java
+++ b/src/main/java/org/traccar/protocol/WatchProtocol.java
diff --git a/src/org/traccar/protocol/WatchProtocolDecoder.java b/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java
index 70b207e9b..70b207e9b 100644
--- a/src/org/traccar/protocol/WatchProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/WatchProtocolDecoder.java
diff --git a/src/org/traccar/protocol/WatchProtocolEncoder.java b/src/main/java/org/traccar/protocol/WatchProtocolEncoder.java
index 264aec81f..264aec81f 100644
--- a/src/org/traccar/protocol/WatchProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/WatchProtocolEncoder.java
diff --git a/src/org/traccar/protocol/WialonProtocol.java b/src/main/java/org/traccar/protocol/WialonProtocol.java
index 06b54dceb..06b54dceb 100644
--- a/src/org/traccar/protocol/WialonProtocol.java
+++ b/src/main/java/org/traccar/protocol/WialonProtocol.java
diff --git a/src/org/traccar/protocol/WialonProtocolDecoder.java b/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java
index de7073b67..de7073b67 100644
--- a/src/org/traccar/protocol/WialonProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/WialonProtocolDecoder.java
diff --git a/src/org/traccar/protocol/WialonProtocolEncoder.java b/src/main/java/org/traccar/protocol/WialonProtocolEncoder.java
index 9ff1631eb..9ff1631eb 100644
--- a/src/org/traccar/protocol/WialonProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/WialonProtocolEncoder.java
diff --git a/src/org/traccar/protocol/WondexFrameDecoder.java b/src/main/java/org/traccar/protocol/WondexFrameDecoder.java
index 39d83d761..39d83d761 100644
--- a/src/org/traccar/protocol/WondexFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/WondexFrameDecoder.java
diff --git a/src/org/traccar/protocol/WondexProtocol.java b/src/main/java/org/traccar/protocol/WondexProtocol.java
index 8c6283d66..8c6283d66 100644
--- a/src/org/traccar/protocol/WondexProtocol.java
+++ b/src/main/java/org/traccar/protocol/WondexProtocol.java
diff --git a/src/org/traccar/protocol/WondexProtocolDecoder.java b/src/main/java/org/traccar/protocol/WondexProtocolDecoder.java
index b85ae2656..b85ae2656 100644
--- a/src/org/traccar/protocol/WondexProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/WondexProtocolDecoder.java
diff --git a/src/org/traccar/protocol/WondexProtocolEncoder.java b/src/main/java/org/traccar/protocol/WondexProtocolEncoder.java
index f9e8eeb9b..f9e8eeb9b 100644
--- a/src/org/traccar/protocol/WondexProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/WondexProtocolEncoder.java
diff --git a/src/org/traccar/protocol/WristbandProtocol.java b/src/main/java/org/traccar/protocol/WristbandProtocol.java
index 1e5ef2c01..1e5ef2c01 100644
--- a/src/org/traccar/protocol/WristbandProtocol.java
+++ b/src/main/java/org/traccar/protocol/WristbandProtocol.java
diff --git a/src/org/traccar/protocol/WristbandProtocolDecoder.java b/src/main/java/org/traccar/protocol/WristbandProtocolDecoder.java
index 7f2b0af85..7f2b0af85 100644
--- a/src/org/traccar/protocol/WristbandProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/WristbandProtocolDecoder.java
diff --git a/src/org/traccar/protocol/XexunFrameDecoder.java b/src/main/java/org/traccar/protocol/XexunFrameDecoder.java
index 114e94061..114e94061 100644
--- a/src/org/traccar/protocol/XexunFrameDecoder.java
+++ b/src/main/java/org/traccar/protocol/XexunFrameDecoder.java
diff --git a/src/org/traccar/protocol/XexunProtocol.java b/src/main/java/org/traccar/protocol/XexunProtocol.java
index 0005270fb..0005270fb 100644
--- a/src/org/traccar/protocol/XexunProtocol.java
+++ b/src/main/java/org/traccar/protocol/XexunProtocol.java
diff --git a/src/org/traccar/protocol/XexunProtocolDecoder.java b/src/main/java/org/traccar/protocol/XexunProtocolDecoder.java
index 5e2d0c05e..5e2d0c05e 100644
--- a/src/org/traccar/protocol/XexunProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/XexunProtocolDecoder.java
diff --git a/src/org/traccar/protocol/XexunProtocolEncoder.java b/src/main/java/org/traccar/protocol/XexunProtocolEncoder.java
index 515cfbbd0..515cfbbd0 100644
--- a/src/org/traccar/protocol/XexunProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/XexunProtocolEncoder.java
diff --git a/src/org/traccar/protocol/XirgoProtocol.java b/src/main/java/org/traccar/protocol/XirgoProtocol.java
index 4979fda5d..4979fda5d 100644
--- a/src/org/traccar/protocol/XirgoProtocol.java
+++ b/src/main/java/org/traccar/protocol/XirgoProtocol.java
diff --git a/src/org/traccar/protocol/XirgoProtocolDecoder.java b/src/main/java/org/traccar/protocol/XirgoProtocolDecoder.java
index 6d215e672..6d215e672 100644
--- a/src/org/traccar/protocol/XirgoProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/XirgoProtocolDecoder.java
diff --git a/src/org/traccar/protocol/XirgoProtocolEncoder.java b/src/main/java/org/traccar/protocol/XirgoProtocolEncoder.java
index dd5e30cca..dd5e30cca 100644
--- a/src/org/traccar/protocol/XirgoProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/XirgoProtocolEncoder.java
diff --git a/src/org/traccar/protocol/Xrb28Protocol.java b/src/main/java/org/traccar/protocol/Xrb28Protocol.java
index b1f1c34fb..b1f1c34fb 100644
--- a/src/org/traccar/protocol/Xrb28Protocol.java
+++ b/src/main/java/org/traccar/protocol/Xrb28Protocol.java
diff --git a/src/org/traccar/protocol/Xrb28ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Xrb28ProtocolDecoder.java
index 938394d6b..938394d6b 100644
--- a/src/org/traccar/protocol/Xrb28ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Xrb28ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Xrb28ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Xrb28ProtocolEncoder.java
index 617639312..617639312 100644
--- a/src/org/traccar/protocol/Xrb28ProtocolEncoder.java
+++ b/src/main/java/org/traccar/protocol/Xrb28ProtocolEncoder.java
diff --git a/src/org/traccar/protocol/Xt013Protocol.java b/src/main/java/org/traccar/protocol/Xt013Protocol.java
index ebb3c123f..ebb3c123f 100644
--- a/src/org/traccar/protocol/Xt013Protocol.java
+++ b/src/main/java/org/traccar/protocol/Xt013Protocol.java
diff --git a/src/org/traccar/protocol/Xt013ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Xt013ProtocolDecoder.java
index f49fb9563..f49fb9563 100644
--- a/src/org/traccar/protocol/Xt013ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Xt013ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/Xt2400Protocol.java b/src/main/java/org/traccar/protocol/Xt2400Protocol.java
index 9427876c8..9427876c8 100644
--- a/src/org/traccar/protocol/Xt2400Protocol.java
+++ b/src/main/java/org/traccar/protocol/Xt2400Protocol.java
diff --git a/src/org/traccar/protocol/Xt2400ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java
index 819011a50..819011a50 100644
--- a/src/org/traccar/protocol/Xt2400ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Xt2400ProtocolDecoder.java
diff --git a/src/org/traccar/protocol/YwtProtocol.java b/src/main/java/org/traccar/protocol/YwtProtocol.java
index c525b75cf..c525b75cf 100644
--- a/src/org/traccar/protocol/YwtProtocol.java
+++ b/src/main/java/org/traccar/protocol/YwtProtocol.java
diff --git a/src/org/traccar/protocol/YwtProtocolDecoder.java b/src/main/java/org/traccar/protocol/YwtProtocolDecoder.java
index bf5a23fa7..bf5a23fa7 100644
--- a/src/org/traccar/protocol/YwtProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/YwtProtocolDecoder.java
diff --git a/src/org/traccar/reports/Events.java b/src/main/java/org/traccar/reports/Events.java
index 66d9e708d..66d9e708d 100644
--- a/src/org/traccar/reports/Events.java
+++ b/src/main/java/org/traccar/reports/Events.java
diff --git a/src/org/traccar/reports/ReportUtils.java b/src/main/java/org/traccar/reports/ReportUtils.java
index 3a631e0d9..3a631e0d9 100644
--- a/src/org/traccar/reports/ReportUtils.java
+++ b/src/main/java/org/traccar/reports/ReportUtils.java
diff --git a/src/org/traccar/reports/Route.java b/src/main/java/org/traccar/reports/Route.java
index 6adb00aae..6adb00aae 100644
--- a/src/org/traccar/reports/Route.java
+++ b/src/main/java/org/traccar/reports/Route.java
diff --git a/src/org/traccar/reports/Stops.java b/src/main/java/org/traccar/reports/Stops.java
index 98c9cef00..98c9cef00 100644
--- a/src/org/traccar/reports/Stops.java
+++ b/src/main/java/org/traccar/reports/Stops.java
diff --git a/src/org/traccar/reports/Summary.java b/src/main/java/org/traccar/reports/Summary.java
index 9810424d8..9810424d8 100644
--- a/src/org/traccar/reports/Summary.java
+++ b/src/main/java/org/traccar/reports/Summary.java
diff --git a/src/org/traccar/reports/Trips.java b/src/main/java/org/traccar/reports/Trips.java
index 3cda65553..3cda65553 100644
--- a/src/org/traccar/reports/Trips.java
+++ b/src/main/java/org/traccar/reports/Trips.java
diff --git a/src/org/traccar/reports/model/BaseReport.java b/src/main/java/org/traccar/reports/model/BaseReport.java
index 9f2d1188c..9f2d1188c 100644
--- a/src/org/traccar/reports/model/BaseReport.java
+++ b/src/main/java/org/traccar/reports/model/BaseReport.java
diff --git a/src/org/traccar/reports/model/DeviceReport.java b/src/main/java/org/traccar/reports/model/DeviceReport.java
index 932753d15..932753d15 100644
--- a/src/org/traccar/reports/model/DeviceReport.java
+++ b/src/main/java/org/traccar/reports/model/DeviceReport.java
diff --git a/src/org/traccar/reports/model/StopReport.java b/src/main/java/org/traccar/reports/model/StopReport.java
index 245292b63..245292b63 100644
--- a/src/org/traccar/reports/model/StopReport.java
+++ b/src/main/java/org/traccar/reports/model/StopReport.java
diff --git a/src/org/traccar/reports/model/SummaryReport.java b/src/main/java/org/traccar/reports/model/SummaryReport.java
index 6f9e9459f..6f9e9459f 100644
--- a/src/org/traccar/reports/model/SummaryReport.java
+++ b/src/main/java/org/traccar/reports/model/SummaryReport.java
diff --git a/src/org/traccar/reports/model/TripReport.java b/src/main/java/org/traccar/reports/model/TripReport.java
index 3140f3019..3140f3019 100644
--- a/src/org/traccar/reports/model/TripReport.java
+++ b/src/main/java/org/traccar/reports/model/TripReport.java
diff --git a/src/org/traccar/reports/model/TripsConfig.java b/src/main/java/org/traccar/reports/model/TripsConfig.java
index 0f0c615d3..0f0c615d3 100644
--- a/src/org/traccar/reports/model/TripsConfig.java
+++ b/src/main/java/org/traccar/reports/model/TripsConfig.java
diff --git a/src/org/traccar/sms/HttpSmsClient.java b/src/main/java/org/traccar/sms/HttpSmsClient.java
index 8e2b67bf7..8e2b67bf7 100644
--- a/src/org/traccar/sms/HttpSmsClient.java
+++ b/src/main/java/org/traccar/sms/HttpSmsClient.java
diff --git a/src/org/traccar/sms/SmsManager.java b/src/main/java/org/traccar/sms/SmsManager.java
index 1e3d40f6e..3b0cbda7f 100644
--- a/src/org/traccar/sms/SmsManager.java
+++ b/src/main/java/org/traccar/sms/SmsManager.java
@@ -24,6 +24,6 @@ public interface SmsManager {
String destAddress, String message, boolean command) throws InterruptedException, MessageException;
void sendMessageAsync(
- final String destAddress, final String message, final boolean command);
+ String destAddress, String message, boolean command);
}
diff --git a/src/org/traccar/sms/smpp/ClientSmppSessionHandler.java b/src/main/java/org/traccar/sms/smpp/ClientSmppSessionHandler.java
index 6b9de3107..6b9de3107 100644
--- a/src/org/traccar/sms/smpp/ClientSmppSessionHandler.java
+++ b/src/main/java/org/traccar/sms/smpp/ClientSmppSessionHandler.java
diff --git a/src/org/traccar/sms/smpp/EnquireLinkTask.java b/src/main/java/org/traccar/sms/smpp/EnquireLinkTask.java
index 7086709d7..7086709d7 100644
--- a/src/org/traccar/sms/smpp/EnquireLinkTask.java
+++ b/src/main/java/org/traccar/sms/smpp/EnquireLinkTask.java
diff --git a/src/org/traccar/sms/smpp/ReconnectionTask.java b/src/main/java/org/traccar/sms/smpp/ReconnectionTask.java
index c009de8e7..c009de8e7 100644
--- a/src/org/traccar/sms/smpp/ReconnectionTask.java
+++ b/src/main/java/org/traccar/sms/smpp/ReconnectionTask.java
diff --git a/src/org/traccar/sms/smpp/SmppClient.java b/src/main/java/org/traccar/sms/smpp/SmppClient.java
index 874253d36..874253d36 100644
--- a/src/org/traccar/sms/smpp/SmppClient.java
+++ b/src/main/java/org/traccar/sms/smpp/SmppClient.java
diff --git a/src/org/traccar/sms/smpp/TextMessageEventHandler.java b/src/main/java/org/traccar/sms/smpp/TextMessageEventHandler.java
index 37c29972d..37c29972d 100644
--- a/src/org/traccar/sms/smpp/TextMessageEventHandler.java
+++ b/src/main/java/org/traccar/sms/smpp/TextMessageEventHandler.java
diff --git a/src/org/traccar/web/ConsoleServlet.java b/src/main/java/org/traccar/web/ConsoleServlet.java
index 2b38a935a..2b38a935a 100644
--- a/src/org/traccar/web/ConsoleServlet.java
+++ b/src/main/java/org/traccar/web/ConsoleServlet.java
diff --git a/src/org/traccar/web/CsvBuilder.java b/src/main/java/org/traccar/web/CsvBuilder.java
index 3fe7e408f..3fe7e408f 100644
--- a/src/org/traccar/web/CsvBuilder.java
+++ b/src/main/java/org/traccar/web/CsvBuilder.java
diff --git a/src/org/traccar/web/GpxBuilder.java b/src/main/java/org/traccar/web/GpxBuilder.java
index 638d100e5..638d100e5 100644
--- a/src/org/traccar/web/GpxBuilder.java
+++ b/src/main/java/org/traccar/web/GpxBuilder.java
diff --git a/src/org/traccar/web/WebServer.java b/src/main/java/org/traccar/web/WebServer.java
index 70fef4ed3..70fef4ed3 100644
--- a/src/org/traccar/web/WebServer.java
+++ b/src/main/java/org/traccar/web/WebServer.java
diff --git a/src/test/java/org/traccar/BaseTest.java b/src/test/java/org/traccar/BaseTest.java
new file mode 100644
index 000000000..0b2c616ce
--- /dev/null
+++ b/src/test/java/org/traccar/BaseTest.java
@@ -0,0 +1,34 @@
+package org.traccar;
+
+import io.netty.buffer.ByteBuf;
+import org.traccar.database.MediaManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class BaseTest {
+
+ public static class MockMediaManager extends MediaManager {
+ Map<String, ByteBuf> files = new HashMap<>();
+
+ MockMediaManager() {
+ super("");
+ }
+
+ @Override
+ public String writeFile(String uniqueId, ByteBuf buf, String extension) {
+ String fileName = uniqueId + "/mock." + extension;
+ files.put(fileName, buf);
+ return fileName;
+ }
+
+ public ByteBuf readFile(String fileName) {
+ return files.get(fileName);
+ }
+ }
+
+ static {
+ Context.init(new TestIdentityManager(), new MockMediaManager());
+ }
+
+}
diff --git a/src/test/java/org/traccar/ProtocolTest.java b/src/test/java/org/traccar/ProtocolTest.java
new file mode 100644
index 000000000..4d48bb763
--- /dev/null
+++ b/src/test/java/org/traccar/ProtocolTest.java
@@ -0,0 +1,324 @@
+package org.traccar;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import io.netty.handler.codec.http.DefaultFullHttpRequest;
+import io.netty.handler.codec.http.DefaultHttpHeaders;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpVersion;
+import org.traccar.helper.DataConverter;
+import org.traccar.model.CellTower;
+import org.traccar.model.Command;
+import org.traccar.model.Position;
+
+import java.nio.charset.StandardCharsets;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class ProtocolTest extends BaseTest {
+
+ protected Position position(String time, boolean valid, double lat, double lon) throws ParseException {
+
+ Position position = new Position();
+
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ position.setTime(dateFormat.parse(time));
+ position.setValid(valid);
+ position.setLatitude(lat);
+ position.setLongitude(lon);
+
+ return position;
+ }
+
+ private String concatenateStrings(String... strings) {
+ StringBuilder builder = new StringBuilder();
+ for (String s : strings) {
+ builder.append(s);
+ }
+ return builder.toString();
+ }
+
+ protected ByteBuf concatenateBuffers(ByteBuf... buffers) {
+ ByteBuf result = Unpooled.buffer();
+ for (ByteBuf buf : buffers) {
+ result.writeBytes(buf);
+ }
+ return result;
+ }
+
+ protected ByteBuf binary(String... data) {
+ return Unpooled.wrappedBuffer(DataConverter.parseHex(concatenateStrings(data)));
+ }
+
+ protected String text(String... data) {
+ return concatenateStrings(data);
+ }
+
+ protected ByteBuf buffer(String... data) {
+ return Unpooled.copiedBuffer(concatenateStrings(data), StandardCharsets.ISO_8859_1);
+ }
+
+ protected DefaultFullHttpRequest request(String url) {
+ return request(HttpMethod.GET, url);
+ }
+
+ protected DefaultFullHttpRequest request(HttpMethod method, String url) {
+ return new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, method, url);
+ }
+
+ protected DefaultFullHttpRequest request(HttpMethod method, String url, ByteBuf data) {
+ return new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, method, url, data);
+ }
+
+ protected DefaultFullHttpRequest request(HttpMethod method, String url, HttpHeaders headers) {
+ return new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, method, url, Unpooled.buffer(), headers, new DefaultHttpHeaders());
+ }
+
+ protected void verifyNotNull(BaseProtocolDecoder decoder, Object object) throws Exception {
+ assertNotNull(decoder.decode(null, null, object));
+ }
+
+ protected void verifyNull(Object object) {
+ assertNull(object);
+ }
+
+ protected void verifyNull(BaseProtocolDecoder decoder, Object object) throws Exception {
+ assertNull(decoder.decode(null, null, object));
+ }
+
+ protected void verifyAttribute(BaseProtocolDecoder decoder, Object object, String key, Object expected) throws Exception {
+ Position position = (Position) decoder.decode(null, null, object);
+ switch (key) {
+ case "speed":
+ assertEquals(expected, position.getSpeed());
+ break;
+ case "course":
+ assertEquals(expected, position.getCourse());
+ break;
+ default:
+ assertEquals(expected, position.getAttributes().get(key));
+ break;
+ }
+ }
+
+ protected void verifyAttributes(BaseProtocolDecoder decoder, Object object) throws Exception {
+ verifyDecodedPosition(decoder.decode(null, null, object), false, true, null);
+ }
+
+ protected void verifyPosition(BaseProtocolDecoder decoder, Object object) throws Exception {
+ verifyDecodedPosition(decoder.decode(null, null, object), true, false, null);
+ }
+
+ protected void verifyPosition(BaseProtocolDecoder decoder, Object object, Position position) throws Exception {
+ verifyDecodedPosition(decoder.decode(null, null, object), true, false, position);
+ }
+
+ protected void verifyPositions(BaseProtocolDecoder decoder, Object object) throws Exception {
+ verifyDecodedList(decoder.decode(null, null, object), true, null);
+ }
+
+ protected void verifyPositions(BaseProtocolDecoder decoder, boolean checkLocation, Object object) throws Exception {
+ verifyDecodedList(decoder.decode(null, null, object), checkLocation, null);
+ }
+
+ protected void verifyPositions(BaseProtocolDecoder decoder, Object object, Position position) throws Exception {
+ verifyDecodedList(decoder.decode(null, null, object), true, position);
+ }
+
+ private void verifyDecodedList(Object decodedObject, boolean checkLocation, Position expected) {
+
+ assertNotNull("list is null", decodedObject);
+ assertTrue("not a list", decodedObject instanceof List);
+ assertFalse("list is empty", ((List) decodedObject).isEmpty());
+
+ for (Object item : (List) decodedObject) {
+ verifyDecodedPosition(item, checkLocation, false, expected);
+ }
+
+ }
+
+ private void verifyDecodedPosition(Object decodedObject, boolean checkLocation, boolean checkAttributes, Position expected) {
+
+ assertNotNull("position is null", decodedObject);
+ assertTrue("not a position", decodedObject instanceof Position);
+
+ Position position = (Position) decodedObject;
+
+ if (checkLocation) {
+
+ if (expected != null) {
+
+ if (expected.getFixTime() != null) {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ assertEquals("time", dateFormat.format(expected.getFixTime()), dateFormat.format(position.getFixTime()));
+ }
+ assertEquals("valid", expected.getValid(), position.getValid());
+ assertEquals("latitude", expected.getLatitude(), position.getLatitude(), 0.00001);
+ assertEquals("longitude", expected.getLongitude(), position.getLongitude(), 0.00001);
+
+ } else {
+
+ assertNotNull(position.getServerTime());
+ assertNotNull(position.getFixTime());
+ assertTrue("year > 1999", position.getFixTime().after(new Date(915148800000L)));
+ assertTrue("time < +25 hours",
+ position.getFixTime().getTime() < System.currentTimeMillis() + 25 * 3600000);
+
+ assertTrue("latitude >= -90", position.getLatitude() >= -90);
+ assertTrue("latitude <= 90", position.getLatitude() <= 90);
+
+ assertTrue("longitude >= -180", position.getLongitude() >= -180);
+ assertTrue("longitude <= 180", position.getLongitude() <= 180);
+
+ }
+
+ assertTrue("altitude >= -12262", position.getAltitude() >= -12262);
+ assertTrue("altitude <= 18000", position.getAltitude() <= 18000);
+
+ assertTrue("speed >= 0", position.getSpeed() >= 0);
+ assertTrue("speed <= 869", position.getSpeed() <= 869);
+
+ assertTrue("course >= 0", position.getCourse() >= 0);
+ assertTrue("course <= 360", position.getCourse() <= 360);
+
+ assertNotNull("protocol is null", position.getProtocol());
+
+ }
+
+ Map<String, Object> attributes = position.getAttributes();
+
+ if (checkAttributes) {
+ assertFalse("no attributes", attributes.isEmpty());
+ }
+
+ if (attributes.containsKey(Position.KEY_INDEX)) {
+ assertTrue(attributes.get(Position.KEY_INDEX) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_HDOP)) {
+ assertTrue(attributes.get(Position.KEY_HDOP) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_VDOP)) {
+ assertTrue(attributes.get(Position.KEY_VDOP) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_PDOP)) {
+ assertTrue(attributes.get(Position.KEY_PDOP) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_SATELLITES)) {
+ assertTrue(attributes.get(Position.KEY_SATELLITES) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_SATELLITES_VISIBLE)) {
+ assertTrue(attributes.get(Position.KEY_SATELLITES_VISIBLE) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_RSSI)) {
+ assertTrue(attributes.get(Position.KEY_RSSI) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_ODOMETER)) {
+ assertTrue(attributes.get(Position.KEY_ODOMETER) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_RPM)) {
+ assertTrue(attributes.get(Position.KEY_RPM) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_FUEL_LEVEL)) {
+ assertTrue(attributes.get(Position.KEY_FUEL_LEVEL) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_POWER)) {
+ assertTrue(attributes.get(Position.KEY_POWER) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_BATTERY)) {
+ assertTrue(attributes.get(Position.KEY_BATTERY) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_BATTERY_LEVEL)) {
+ int batteryLevel = ((Number) attributes.get(Position.KEY_BATTERY_LEVEL)).intValue();
+ assertTrue(batteryLevel <= 100 && batteryLevel >= 0);
+ }
+
+ if (attributes.containsKey(Position.KEY_CHARGE)) {
+ assertTrue(attributes.get(Position.KEY_CHARGE) instanceof Boolean);
+ }
+
+ if (attributes.containsKey(Position.KEY_IGNITION)) {
+ assertTrue(attributes.get(Position.KEY_IGNITION) instanceof Boolean);
+ }
+
+ if (attributes.containsKey(Position.KEY_MOTION)) {
+ assertTrue(attributes.get(Position.KEY_MOTION) instanceof Boolean);
+ }
+
+ if (attributes.containsKey(Position.KEY_ARCHIVE)) {
+ assertTrue(attributes.get(Position.KEY_ARCHIVE) instanceof Boolean);
+ }
+
+ if (attributes.containsKey(Position.KEY_DRIVER_UNIQUE_ID)) {
+ assertTrue(attributes.get(Position.KEY_DRIVER_UNIQUE_ID) instanceof String);
+ }
+
+ if (attributes.containsKey(Position.KEY_STEPS)) {
+ assertTrue(attributes.get(Position.KEY_STEPS) instanceof Number);
+ }
+
+ if (attributes.containsKey(Position.KEY_ROAMING)) {
+ assertTrue(attributes.get(Position.KEY_ROAMING) instanceof Boolean);
+ }
+
+ if (attributes.containsKey(Position.KEY_HOURS)) {
+ assertTrue(attributes.get(Position.KEY_HOURS) instanceof Number);
+ }
+
+ if (position.getNetwork() != null && position.getNetwork().getCellTowers() != null) {
+ for (CellTower cellTower : position.getNetwork().getCellTowers()) {
+ checkInteger(cellTower.getMobileCountryCode(), 0, 999);
+ checkInteger(cellTower.getMobileNetworkCode(), 0, 999);
+ checkInteger(cellTower.getLocationAreaCode(), 1, 65535);
+ checkInteger(cellTower.getCellId(), 0, 268435455);
+ }
+ }
+
+ }
+
+ private void checkInteger(Object value, int min, int max) {
+ assertNotNull("value is null", value);
+ assertTrue("not int or long", value instanceof Integer || value instanceof Long);
+ long number = ((Number) value).longValue();
+ assertTrue("value too low", number >= min);
+ assertTrue("value too high", number <= max);
+ }
+
+ protected void verifyCommand(
+ BaseProtocolEncoder encoder, Command command, ByteBuf expected) {
+ verifyFrame(expected, encoder.encodeCommand(command));
+ }
+
+ protected void verifyFrame(ByteBuf expected, Object object) {
+ assertNotNull("buffer is null", object);
+ assertTrue("not a buffer", object instanceof ByteBuf);
+ assertEquals(ByteBufUtil.hexDump(expected), ByteBufUtil.hexDump((ByteBuf) object));
+ }
+
+}
diff --git a/src/test/java/org/traccar/TestIdentityManager.java b/src/test/java/org/traccar/TestIdentityManager.java
new file mode 100644
index 000000000..0f7405dbd
--- /dev/null
+++ b/src/test/java/org/traccar/TestIdentityManager.java
@@ -0,0 +1,72 @@
+package org.traccar;
+
+import org.traccar.database.IdentityManager;
+import org.traccar.model.Device;
+import org.traccar.model.Position;
+
+public final class TestIdentityManager implements IdentityManager {
+
+ private static Device createDevice() {
+ Device device = new Device();
+ device.setId(1);
+ device.setName("test");
+ device.setUniqueId("123456789012345");
+ return device;
+ }
+
+ @Override
+ public long addUnknownDevice(String uniqueId) {
+ return 1;
+ }
+
+ @Override
+ public Device getById(long id) {
+ return createDevice();
+ }
+
+ @Override
+ public Device getByUniqueId(String uniqueId) {
+ return createDevice();
+ }
+
+ @Override
+ public Position getLastPosition(long deviceId) {
+ return null;
+ }
+
+ @Override
+ public boolean isLatestPosition(Position position) {
+ return true;
+ }
+
+ @Override
+ public boolean lookupAttributeBoolean(
+ long deviceId, String attributeName, boolean defaultValue, boolean lookupConfig) {
+ return defaultValue;
+ }
+
+ @Override
+ public String lookupAttributeString(
+ long deviceId, String attributeName, String defaultValue, boolean lookupConfig) {
+ return "alarm,result";
+ }
+
+ @Override
+ public int lookupAttributeInteger(
+ long deviceId, String attributeName, int defaultValue, boolean lookupConfig) {
+ return defaultValue;
+ }
+
+ @Override
+ public long lookupAttributeLong(
+ long deviceId, String attributeName, long defaultValue, boolean lookupConfig) {
+ return defaultValue;
+ }
+
+ @Override
+ public double lookupAttributeDouble(
+ long deviceId, String attributeName, double defaultValue, boolean lookupConfig) {
+ return defaultValue;
+ }
+
+}
diff --git a/src/test/java/org/traccar/WebDataHandlerTest.java b/src/test/java/org/traccar/WebDataHandlerTest.java
new file mode 100644
index 000000000..cfbd71f23
--- /dev/null
+++ b/src/test/java/org/traccar/WebDataHandlerTest.java
@@ -0,0 +1,28 @@
+package org.traccar;
+
+import org.junit.Test;
+import org.traccar.config.Config;
+import org.traccar.config.Keys;
+import org.traccar.model.Position;
+
+import static org.junit.Assert.assertEquals;
+
+public class WebDataHandlerTest extends ProtocolTest {
+
+ @Test
+ public void testFormatRequest() throws Exception {
+
+ Config config = new Config();
+ config.setString(Keys.FORWARD_URL, "http://localhost/?fixTime={fixTime}&gprmc={gprmc}&name={name}");
+
+ Position position = position("2016-01-01 01:02:03.000", true, 20, 30);
+
+ WebDataHandler handler = new WebDataHandler(config, Context.getIdentityManager(), null, null);
+
+ assertEquals(
+ "http://localhost/?fixTime=1451610123000&gprmc=$GPRMC,010203.000,A,2000.0000,N,03000.0000,E,0.00,0.00,010116,,*05&name=test",
+ handler.formatRequest(position));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/calendar/CalendarTest.java b/src/test/java/org/traccar/calendar/CalendarTest.java
new file mode 100644
index 000000000..56406d4b8
--- /dev/null
+++ b/src/test/java/org/traccar/calendar/CalendarTest.java
@@ -0,0 +1,59 @@
+package org.traccar.calendar;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.junit.Test;
+import org.traccar.model.Calendar;
+
+import net.fortuna.ical4j.data.ParserException;
+
+import static org.junit.Assert.assertTrue;
+
+public class CalendarTest {
+
+ @Test
+ public void testCalendar() throws IOException, ParserException, ParseException, SQLException {
+ String calendarString = "BEGIN:VCALENDAR\n" +
+ "PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN\n" +
+ "VERSION:2.0\n" +
+ "BEGIN:VTIMEZONE\n" +
+ "TZID:Asia/Yekaterinburg\n" +
+ "BEGIN:STANDARD\n" +
+ "TZOFFSETFROM:+0500\n" +
+ "TZOFFSETTO:+0500\n" +
+ "TZNAME:YEKT\n" +
+ "DTSTART:19700101T000000\n" +
+ "END:STANDARD\n" +
+ "END:VTIMEZONE\n" +
+ "BEGIN:VEVENT\n" +
+ "CREATED:20161213T045151Z\n" +
+ "LAST-MODIFIED:20161213T045242Z\n" +
+ "DTSTAMP:20161213T045242Z\n" +
+ "UID:9d000df0-6354-479d-a407-218dac62c7c9\n" +
+ "SUMMARY:Every night\n" +
+ "RRULE:FREQ=DAILY\n" +
+ "DTSTART;TZID=Asia/Yekaterinburg:20161130T230000\n" +
+ "DTEND;TZID=Asia/Yekaterinburg:20161201T070000\n" +
+ "TRANSP:OPAQUE\n" +
+ "END:VEVENT\n" +
+ "END:VCALENDAR";
+ Calendar calendar = new Calendar();
+ calendar.setData(calendarString.getBytes());
+ DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssX");
+
+ Date date = format.parse("2016-12-13 22:59:59+05");
+ assertTrue(!calendar.checkMoment(date));
+ date = format.parse("2016-12-13 23:00:01+05");
+ assertTrue(calendar.checkMoment(date));
+
+ date = format.parse("2016-12-13 06:59:59+05");
+ assertTrue(calendar.checkMoment(date));
+ date = format.parse("2016-12-13 07:00:01+05");
+ assertTrue(!calendar.checkMoment(date));
+ }
+}
diff --git a/src/test/java/org/traccar/config/ConfigTest.java b/src/test/java/org/traccar/config/ConfigTest.java
new file mode 100644
index 000000000..13d0ffb04
--- /dev/null
+++ b/src/test/java/org/traccar/config/ConfigTest.java
@@ -0,0 +1,19 @@
+package org.traccar.config;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import org.traccar.config.Config;
+
+public class ConfigTest {
+
+ @Test
+ public void testFormat() {
+ assertEquals("DATABASE_URL", Config.getEnvironmentVariableName("database.url"));
+ assertEquals("DATABASE_CHECK_CONNECTION", Config.getEnvironmentVariableName("database.checkConnection"));
+ assertEquals("DATABASE_MAX_POOL_SIZE", Config.getEnvironmentVariableName("database.maxPoolSize"));
+ assertEquals("DEVICE_MANAGER_LOOKUP_GROUPS_ATTRIBUTE", Config.getEnvironmentVariableName("deviceManager.lookupGroupsAttribute"));
+ assertEquals("COMMAND_FALLBACK_TO_SMS", Config.getEnvironmentVariableName("command.fallbackToSms"));
+ assertEquals("STATUS_TIMEOUT", Config.getEnvironmentVariableName("status.timeout"));
+ }
+
+}
diff --git a/src/test/java/org/traccar/database/DataManagerTest.java b/src/test/java/org/traccar/database/DataManagerTest.java
new file mode 100644
index 000000000..23043e96e
--- /dev/null
+++ b/src/test/java/org/traccar/database/DataManagerTest.java
@@ -0,0 +1,81 @@
+package org.traccar.database;
+
+import org.junit.Test;
+import org.traccar.model.Attribute;
+import org.traccar.model.Device;
+import org.traccar.model.Driver;
+import org.traccar.model.Geofence;
+import org.traccar.model.Group;
+import org.traccar.model.ManagedUser;
+import org.traccar.model.Position;
+import org.traccar.model.User;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class DataManagerTest {
+
+ @Test
+ public void constructObjectQuery() {
+ assertEquals("SELECT * FROM tc_users",
+ DataManager.constructObjectQuery(DataManager.ACTION_SELECT_ALL, User.class, false));
+ assertEquals("DELETE FROM tc_groups WHERE id = :id",
+ DataManager.constructObjectQuery(DataManager.ACTION_DELETE, Group.class, false));
+ assertEquals("SELECT * FROM tc_positions WHERE id = :id",
+ DataManager.constructObjectQuery(DataManager.ACTION_SELECT, Position.class, false));
+
+ String insertDevice = DataManager.constructObjectQuery(DataManager.ACTION_INSERT, Device.class, false);
+ assertFalse(insertDevice.contains("class"));
+ assertFalse(insertDevice.contains("id"));
+ assertFalse(insertDevice.contains("status"));
+ assertFalse(insertDevice.contains("geofenceIds"));
+
+ String updateDeviceStatus = DataManager.constructObjectQuery("update", Device.class, true);
+ assertTrue(updateDeviceStatus.contains("lastUpdate"));
+
+ String updateUser = DataManager.constructObjectQuery(DataManager.ACTION_UPDATE, User.class, false);
+ assertFalse(updateUser.contains("class"));
+ assertFalse(updateUser.contains("password"));
+ assertFalse(updateUser.contains("salt"));
+
+ String updateUserPassword = DataManager.constructObjectQuery(DataManager.ACTION_UPDATE, User.class, true);
+ assertFalse(updateUserPassword.contains("name"));
+ assertTrue(updateUserPassword.contains("hashedPassword"));
+ assertTrue(updateUserPassword.contains("salt"));
+
+ String insertPosition = DataManager.constructObjectQuery(DataManager.ACTION_INSERT, Position.class, false);
+ assertFalse(insertPosition.contains("type"));
+ assertFalse(insertPosition.contains("outdated"));
+
+ }
+
+ @Test
+ public void constructPermissionsQuery() {
+ assertEquals("SELECT userId, deviceId FROM tc_user_device",
+ DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, User.class, Device.class));
+
+ assertEquals("SELECT userId, managedUserId FROM tc_user_user",
+ DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, User.class, ManagedUser.class));
+
+ assertEquals("SELECT deviceId, driverId FROM tc_device_driver",
+ DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, Device.class, Driver.class));
+
+ assertEquals("SELECT groupId, geofenceId FROM tc_group_geofence",
+ DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, Group.class, Geofence.class));
+
+ assertEquals("INSERT INTO tc_user_device (userId, deviceId) VALUES (:userId, :deviceId)",
+ DataManager.constructPermissionQuery(DataManager.ACTION_INSERT, User.class, Device.class));
+
+ assertEquals("DELETE FROM tc_user_user WHERE userId = :userId AND managedUserId = :managedUserId",
+ DataManager.constructPermissionQuery(DataManager.ACTION_DELETE, User.class, ManagedUser.class));
+
+ assertEquals("INSERT INTO tc_device_geofence (deviceId, geofenceId) VALUES (:deviceId, :geofenceId)",
+ DataManager.constructPermissionQuery(DataManager.ACTION_INSERT, Device.class, Geofence.class));
+
+ assertEquals("DELETE FROM tc_group_attribute WHERE groupId = :groupId AND attributeId = :attributeId",
+ DataManager.constructPermissionQuery(DataManager.ACTION_DELETE, Group.class, Attribute.class));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/database/GroupTreeTest.java b/src/test/java/org/traccar/database/GroupTreeTest.java
new file mode 100644
index 000000000..b547aab60
--- /dev/null
+++ b/src/test/java/org/traccar/database/GroupTreeTest.java
@@ -0,0 +1,56 @@
+package org.traccar.database;
+
+import org.junit.Test;
+import org.traccar.model.Device;
+import org.traccar.model.Group;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+public class GroupTreeTest {
+
+ private static Group createGroup(long id, String name, long parent) {
+ Group group = new Group();
+ group.setId(id);
+ group.setName(name);
+ group.setGroupId(parent);
+ return group;
+ }
+
+ private static Device createDevice(long id, String name, long parent) {
+ Device device = new Device();
+ device.setId(id);
+ device.setName(name);
+ device.setGroupId(parent);
+ return device;
+ }
+
+ @Test
+ public void testGetDescendants() {
+ Collection<Group> groups = new ArrayList<>();
+ groups.add(createGroup(1, "First", 0));
+ groups.add(createGroup(2, "Second", 1));
+ groups.add(createGroup(3, "Third", 2));
+ groups.add(createGroup(4, "Fourth", 2));
+ groups.add(createGroup(5, "Fifth", 4));
+
+ Collection<Device> devices = new ArrayList<>();
+ devices.add(createDevice(1, "One", 3));
+ devices.add(createDevice(2, "Two", 5));
+ devices.add(createDevice(3, "One", 5));
+
+ GroupTree groupTree = new GroupTree(groups, devices);
+
+ assertEquals(4, groupTree.getGroups(1).size());
+ assertEquals(3, groupTree.getGroups(2).size());
+ assertEquals(0, groupTree.getGroups(3).size());
+ assertEquals(1, groupTree.getGroups(4).size());
+
+ assertEquals(3, groupTree.getDevices(1).size());
+ assertEquals(1, groupTree.getDevices(3).size());
+ assertEquals(2, groupTree.getDevices(4).size());
+ }
+
+}
diff --git a/src/test/java/org/traccar/geocoder/AddressFormatTest.java b/src/test/java/org/traccar/geocoder/AddressFormatTest.java
new file mode 100644
index 000000000..0cc5168ef
--- /dev/null
+++ b/src/test/java/org/traccar/geocoder/AddressFormatTest.java
@@ -0,0 +1,33 @@
+package org.traccar.geocoder;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class AddressFormatTest {
+
+ private void test(Address address, String format, String expected) {
+ assertEquals(expected, new AddressFormat(format).format(address));
+ }
+
+ @Test
+ public void testFormat() {
+
+ Address address = new Address();
+ address.setCountry("NZ");
+ address.setSettlement("Auckland");
+ address.setStreet("Queen St");
+ address.setHouse("1A");
+
+ test(address, "%h %r %t %d %s %c %p", "1A Queen St Auckland NZ");
+ test(address, "%h %r %t", "1A Queen St Auckland");
+ test(address, "%h %r, %t", "1A Queen St, Auckland");
+ test(address, "%h %r, %t %p", "1A Queen St, Auckland");
+ test(address, "%t %d %c", "Auckland NZ");
+ test(address, "%t, %d, %c", "Auckland, NZ");
+ test(address, "%d %c", "NZ");
+ test(address, "%d, %c", "NZ");
+ test(address, "%p", "");
+ }
+
+}
diff --git a/src/test/java/org/traccar/geocoder/GeocoderTest.java b/src/test/java/org/traccar/geocoder/GeocoderTest.java
new file mode 100644
index 000000000..85d9bf62f
--- /dev/null
+++ b/src/test/java/org/traccar/geocoder/GeocoderTest.java
@@ -0,0 +1,88 @@
+package org.traccar.geocoder;
+
+import java.util.Locale;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class GeocoderTest {
+
+ static {
+ Locale.setDefault(Locale.US);
+ }
+
+ @Ignore
+ @Test
+ public void testGoogle() {
+ Geocoder geocoder = new GoogleGeocoder(null, null, 0, new AddressFormat());
+ String address = geocoder.getAddress(31.776797, 35.211489, null);
+ assertEquals("1 Ibn Shaprut St, Jerusalem, Jerusalem District, IL", address);
+ }
+
+ @Ignore
+ @Test
+ public void testNominatim() {
+ Geocoder geocoder = new NominatimGeocoder(null, null, null, 0, new AddressFormat());
+ String address = geocoder.getAddress(40.7337807, -73.9974401, null);
+ assertEquals("35 West 9th Street, NYC, New York, US", address);
+ }
+
+ @Ignore
+ @Test
+ public void testGisgraphy() {
+ Geocoder geocoder = new GisgraphyGeocoder(new AddressFormat());
+ String address = geocoder.getAddress(48.8530000, 2.3400000, null);
+ assertEquals("Rue du Jardinet, Paris, Île-de-France, FR", address);
+ }
+
+ @Ignore
+ @Test
+ public void testOpenCage() {
+ Geocoder geocoder = new OpenCageGeocoder(
+ "http://api.opencagedata.com/geocode/v1", "SECRET", 0, new AddressFormat());
+ String address = geocoder.getAddress(34.116302, -118.051519, null);
+ assertEquals("Charleston Road, California, US", address);
+ }
+
+ @Ignore
+ @Test
+ public void testGeocodeFarm() {
+ Geocoder geocoder = new GeocodeFarmGeocoder(null, null, 0, new AddressFormat());
+ String address = geocoder.getAddress(34.116302, -118.051519, null);
+ assertEquals("Estrella Avenue, Arcadia, California, United States", address);
+ }
+
+ @Ignore
+ @Test
+ public void testGeocodeXyz() {
+ Geocoder geocoder = new GeocodeXyzGeocoder(null, 0, new AddressFormat());
+ String address = geocoder.getAddress(34.116302, -118.051519, null);
+ assertEquals("605 ESTRELLA AVE, ARCADIA, California United States of America, US", address);
+ }
+
+ @Ignore
+ @Test
+ public void testBan() {
+ Geocoder geocoder = new BanGeocoder(0, new AddressFormat("%f [%d], %c"));
+ String address = geocoder.getAddress(48.8575, 2.2944, null);
+ assertEquals("8 Avenue Gustave Eiffel 75007 Paris [75, Paris, Île-de-France], FR", address);
+ }
+
+ @Ignore
+ @Test
+ public void testHere() {
+ Geocoder geocoder = new HereGeocoder("", "", null, 0, new AddressFormat());
+ String address = geocoder.getAddress(48.8575, 2.2944, null);
+ assertEquals("6 Avenue Gustave Eiffel, Paris, Île-de-France, FRA", address);
+ }
+
+ @Ignore
+ @Test
+ public void testMapmyIndia() {
+ Geocoder geocoder = new MapmyIndiaGeocoder("", "", 0, new AddressFormat("%f"));
+ String address = geocoder.getAddress(28.6129602407977, 77.2294557094574, null);
+ assertEquals("New Delhi, Delhi. 1 m from India Gate pin-110001 (India)", address);
+ }
+}
diff --git a/src/test/java/org/traccar/geofence/GeofenceCircleTest.java b/src/test/java/org/traccar/geofence/GeofenceCircleTest.java
new file mode 100644
index 000000000..259a8fb77
--- /dev/null
+++ b/src/test/java/org/traccar/geofence/GeofenceCircleTest.java
@@ -0,0 +1,28 @@
+package org.traccar.geofence;
+
+import java.text.ParseException;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class GeofenceCircleTest {
+
+ @Test
+ public void testCircleWkt() throws ParseException {
+ String test = "CIRCLE (55.75414 37.6204, 100)";
+ GeofenceGeometry geofenceGeometry = new GeofenceCircle();
+ geofenceGeometry.fromWkt(test);
+ assertEquals(geofenceGeometry.toWkt(), test);
+ }
+
+ @Test
+ public void testContainsCircle() throws ParseException {
+ String test = "CIRCLE (55.75414 37.6204, 100)";
+ GeofenceGeometry geofenceGeometry = new GeofenceCircle();
+ geofenceGeometry.fromWkt(test);
+ assertTrue(geofenceGeometry.containsPoint(55.75477, 37.62025));
+ assertTrue(!geofenceGeometry.containsPoint(55.75545, 37.61921));
+ }
+}
diff --git a/src/test/java/org/traccar/geofence/GeofencePolygonTest.java b/src/test/java/org/traccar/geofence/GeofencePolygonTest.java
new file mode 100644
index 000000000..94b73af3a
--- /dev/null
+++ b/src/test/java/org/traccar/geofence/GeofencePolygonTest.java
@@ -0,0 +1,52 @@
+package org.traccar.geofence;
+
+import java.text.ParseException;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class GeofencePolygonTest {
+
+ @Test
+ public void testPolygonWkt() throws ParseException {
+ String test = "POLYGON ((55.75474 37.61823, 55.75513 37.61888, 55.7535 37.6222, 55.75315 37.62165))";
+ GeofenceGeometry geofenceGeometry = new GeofencePolygon();
+ geofenceGeometry.fromWkt(test);
+ assertEquals(geofenceGeometry.toWkt(), test);
+ }
+
+ @Test
+ public void testContainsPolygon() throws ParseException {
+ String test = "POLYGON ((55.75474 37.61823, 55.75513 37.61888, 55.7535 37.6222, 55.75315 37.62165))";
+ GeofenceGeometry geofenceGeometry = new GeofencePolygon();
+ geofenceGeometry.fromWkt(test);
+ assertTrue(geofenceGeometry.containsPoint(55.75476, 37.61915));
+ assertTrue(!geofenceGeometry.containsPoint(55.75545, 37.61921));
+
+ }
+
+ @Test
+ public void testContainsPolygon180() throws ParseException {
+ String test = "POLYGON ((66.9494 179.838, 66.9508 -179.8496, 66.8406 -180.0014))";
+ GeofenceGeometry geofenceGeometry = new GeofencePolygon();
+ geofenceGeometry.fromWkt(test);
+ assertTrue(geofenceGeometry.containsPoint(66.9015, -180.0096));
+ assertTrue(geofenceGeometry.containsPoint(66.9015, 179.991));
+ assertTrue(!geofenceGeometry.containsPoint(66.8368, -179.8792));
+
+ }
+
+ @Test
+ public void testContainsPolygon0() throws ParseException {
+ String test = "POLYGON ((51.1966 -0.6207, 51.1897 0.4147, 50.9377 0.5136, 50.8675 -0.6082))";
+ GeofenceGeometry geofenceGeometry = new GeofencePolygon();
+ geofenceGeometry.fromWkt(test);
+ assertTrue(geofenceGeometry.containsPoint(51.0466, -0.0165));
+ assertTrue(geofenceGeometry.containsPoint(51.0466, 0.018));
+ assertTrue(!geofenceGeometry.containsPoint(50.9477, 0.5836));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/geofence/GeofencePolylineTest.java b/src/test/java/org/traccar/geofence/GeofencePolylineTest.java
new file mode 100644
index 000000000..1e9dcb7c3
--- /dev/null
+++ b/src/test/java/org/traccar/geofence/GeofencePolylineTest.java
@@ -0,0 +1,47 @@
+package org.traccar.geofence;
+
+import java.text.ParseException;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class GeofencePolylineTest {
+
+ @Test
+ public void testPolylineWkt() throws ParseException {
+ String test = "LINESTRING (55.75474 37.61823, 55.75513 37.61888, 55.7535 37.6222, 55.75315 37.62165)";
+ GeofenceGeometry geofenceGeometry = new GeofencePolyline();
+ geofenceGeometry.fromWkt(test);
+ assertEquals(geofenceGeometry.toWkt(), test);
+ }
+
+ @Test
+ public void testContainsPolyline1Interval() throws ParseException {
+ String test = "LINESTRING (56.83777 60.59833, 56.83766 60.5968)";
+ GeofenceGeometry geofenceGeometry = new GeofencePolyline(test, 35);
+ assertTrue(geofenceGeometry.containsPoint(56.83801, 60.59748));
+ ((GeofencePolyline) geofenceGeometry).setDistance(15);
+ assertTrue(!geofenceGeometry.containsPoint(56.83801, 60.59748));
+ }
+
+ @Test
+ public void testContainsPolyline3Intervals() throws ParseException {
+ String test = "LINESTRING (56.836 60.6126, 56.8393 60.6114, 56.83887 60.60811, 56.83782 60.5988)";
+ GeofenceGeometry geofenceGeometry = new GeofencePolyline(test, 15);
+ assertTrue(geofenceGeometry.containsPoint(56.83847, 60.60458));
+ assertTrue(!geofenceGeometry.containsPoint(56.83764, 60.59725));
+ assertTrue(!geofenceGeometry.containsPoint(56.83861, 60.60822));
+
+ }
+
+ @Test
+ public void testContainsPolylineNear180() throws ParseException {
+ String test = "LINESTRING (66.9494 179.838, 66.9508 -179.8496)";
+ GeofenceGeometry geofenceGeometry = new GeofencePolyline(test, 25);
+ assertTrue(geofenceGeometry.containsPoint(66.95, 180.0));
+ assertTrue(!geofenceGeometry.containsPoint(66.96, 180.0));
+ assertTrue(!geofenceGeometry.containsPoint(66.9509, -179.83));
+ }
+}
diff --git a/src/test/java/org/traccar/geolocation/GeolocationProviderTest.java b/src/test/java/org/traccar/geolocation/GeolocationProviderTest.java
new file mode 100644
index 000000000..2729052d6
--- /dev/null
+++ b/src/test/java/org/traccar/geolocation/GeolocationProviderTest.java
@@ -0,0 +1,41 @@
+package org.traccar.geolocation;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.model.CellTower;
+import org.traccar.model.Network;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class GeolocationProviderTest extends BaseTest {
+
+ @Ignore
+ @Test
+ public void test() throws Exception {
+ testLocationProvider();
+ }
+
+ public void testLocationProvider() throws Exception {
+ MozillaGeolocationProvider provider = new MozillaGeolocationProvider(null);
+
+ Network network = new Network(CellTower.from(208, 1, 2, 1234567));
+
+ provider.getLocation(network, new GeolocationProvider.LocationProviderCallback() {
+ @Override
+ public void onSuccess(double latitude, double longitude, double accuracy) {
+ assertEquals(60.07254, latitude, 0.00001);
+ assertEquals(30.30996, longitude, 0.00001);
+ }
+
+ @Override
+ public void onFailure(Throwable e) {
+ fail();
+ }
+ });
+
+ Thread.sleep(Long.MAX_VALUE);
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/ComputedAttributesTest.java b/src/test/java/org/traccar/handler/ComputedAttributesTest.java
new file mode 100644
index 000000000..a76d8169b
--- /dev/null
+++ b/src/test/java/org/traccar/handler/ComputedAttributesTest.java
@@ -0,0 +1,71 @@
+package org.traccar.handler;
+
+import java.util.Date;
+
+import org.junit.Test;
+import org.traccar.config.Config;
+import org.traccar.model.Attribute;
+import org.traccar.model.Position;
+
+import static org.junit.Assert.assertEquals;
+
+public class ComputedAttributesTest {
+
+ @Test
+ public void testComputedAttributes() {
+
+ ComputedAttributesHandler handler = new ComputedAttributesHandler(new Config(), null, null);
+
+ Date date = new Date();
+ Position position = new Position();
+ position.setTime(date);
+ position.setSpeed(42);
+ position.setValid(false);
+ position.set("adc1", 128);
+ position.set("booleanFlag", true);
+ position.set("adc2", 100);
+ position.set("bitFlag", 7);
+ position.set("event", 42);
+ position.set("result", "success");
+ Attribute attribute = new Attribute();
+
+ attribute.setExpression("adc1");
+ assertEquals(128, handler.computeAttribute(attribute, position));
+
+ attribute.setExpression("!booleanFlag");
+ assertEquals(false, handler.computeAttribute(attribute, position));
+
+ attribute.setExpression("adc2 * 2 + 50");
+ assertEquals(250, handler.computeAttribute(attribute, position));
+
+ attribute.setExpression("(bitFlag & 4) != 0");
+ assertEquals(true, handler.computeAttribute(attribute, position));
+
+ attribute.setExpression("if (event == 42) \"lowBattery\"");
+ assertEquals("lowBattery", handler.computeAttribute(attribute, position));
+
+ attribute.setExpression("speed > 5 && valid");
+ assertEquals(false, handler.computeAttribute(attribute, position));
+
+ attribute.setExpression("fixTime");
+ assertEquals(date, handler.computeAttribute(attribute, position));
+
+ attribute.setExpression("math:pow(adc1, 2)");
+ assertEquals(16384.0, handler.computeAttribute(attribute, position));
+
+ // modification tests
+ attribute.setExpression("adc1 = 256");
+ handler.computeAttribute(attribute, position);
+ assertEquals(128, position.getInteger("adc1"));
+
+ attribute.setExpression("result = \"fail\"");
+ handler.computeAttribute(attribute, position);
+ assertEquals("success", position.getString("result"));
+
+ attribute.setExpression("fixTime = \"2017-10-18 10:00:01\"");
+ handler.computeAttribute(attribute, position);
+ assertEquals(date, position.getFixTime());
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/DistanceHandlerTest.java b/src/test/java/org/traccar/handler/DistanceHandlerTest.java
new file mode 100644
index 000000000..f7c6e42cd
--- /dev/null
+++ b/src/test/java/org/traccar/handler/DistanceHandlerTest.java
@@ -0,0 +1,30 @@
+package org.traccar.handler;
+
+import org.junit.Test;
+import org.traccar.config.Config;
+import org.traccar.model.Position;
+
+import static org.junit.Assert.assertEquals;
+
+public class DistanceHandlerTest {
+
+ @Test
+ public void testCalculateDistance() {
+
+ DistanceHandler distanceHandler = new DistanceHandler(new Config(), null);
+
+ Position position = distanceHandler.handlePosition(new Position());
+
+ assertEquals(0.0, position.getAttributes().get(Position.KEY_DISTANCE));
+ assertEquals(0.0, position.getAttributes().get(Position.KEY_TOTAL_DISTANCE));
+
+ position.set(Position.KEY_DISTANCE, 100);
+
+ position = distanceHandler.handlePosition(position);
+
+ assertEquals(100.0, position.getAttributes().get(Position.KEY_DISTANCE));
+ assertEquals(100.0, position.getAttributes().get(Position.KEY_TOTAL_DISTANCE));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/FilterHandlerTest.java b/src/test/java/org/traccar/handler/FilterHandlerTest.java
new file mode 100644
index 000000000..ad8d244a6
--- /dev/null
+++ b/src/test/java/org/traccar/handler/FilterHandlerTest.java
@@ -0,0 +1,88 @@
+package org.traccar.handler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.config.Config;
+import org.traccar.config.Keys;
+import org.traccar.model.Position;
+
+import java.util.Date;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class FilterHandlerTest extends BaseTest {
+
+ private FilterHandler passingHandler = new FilterHandler(new Config());
+ private FilterHandler filteringHandler;
+
+ @Before
+ public void before() {
+ Config config = new Config();
+ config.setString(Keys.FILTER_INVALID, String.valueOf(true));
+ config.setString(Keys.FILTER_ZERO, String.valueOf(true));
+ config.setString(Keys.FILTER_DUPLICATE, String.valueOf(true));
+ config.setString(Keys.FILTER_FUTURE, String.valueOf(5 * 60));
+ config.setString(Keys.FILTER_APPROXIMATE, String.valueOf(true));
+ config.setString(Keys.FILTER_STATIC, String.valueOf(true));
+ config.setString(Keys.FILTER_DISTANCE, String.valueOf(10));
+ config.setString(Keys.FILTER_MAX_SPEED, String.valueOf(500));
+ config.setString(Keys.FILTER_SKIP_LIMIT, String.valueOf(10));
+ config.setString(Keys.FILTER_SKIP_ATTRIBUTES_ENABLE, String.valueOf(true));
+ filteringHandler = new FilterHandler(config);
+ }
+
+ private Position createPosition(
+ long deviceId,
+ Date time,
+ boolean valid,
+ double latitude,
+ double longitude,
+ double altitude,
+ double speed,
+ double course) {
+
+ Position position = new Position();
+ position.setDeviceId(deviceId);
+ position.setTime(time);
+ position.setValid(valid);
+ position.setLatitude(latitude);
+ position.setLongitude(longitude);
+ position.setAltitude(altitude);
+ position.setSpeed(speed);
+ position.setCourse(course);
+ return position;
+ }
+
+ @Test
+ public void testFilter() {
+
+ Position position = createPosition(0, new Date(), true, 10, 10, 10, 10, 10);
+
+ assertNotNull(filteringHandler.handlePosition(position));
+ assertNotNull(passingHandler.handlePosition(position));
+
+ position = createPosition(0, new Date(Long.MAX_VALUE), true, 10, 10, 10, 10, 10);
+
+ assertNull(filteringHandler.handlePosition(position));
+ assertNotNull(passingHandler.handlePosition(position));
+
+ position = createPosition(0, new Date(), false, 10, 10, 10, 10, 10);
+
+ assertNull(filteringHandler.handlePosition(position));
+ assertNotNull(passingHandler.handlePosition(position));
+
+ }
+
+ @Test
+ public void testSkipAttributes() {
+
+ Position position = createPosition(0, new Date(), true, 10, 10, 10, 0, 10);
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+
+ assertNotNull(filteringHandler.handlePosition(position));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/MotionHandlerTest.java b/src/test/java/org/traccar/handler/MotionHandlerTest.java
new file mode 100644
index 000000000..9e0859664
--- /dev/null
+++ b/src/test/java/org/traccar/handler/MotionHandlerTest.java
@@ -0,0 +1,21 @@
+package org.traccar.handler;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.traccar.model.Position;
+
+public class MotionHandlerTest {
+
+ @Test
+ public void testCalculateMotion() {
+
+ MotionHandler motionHandler = new MotionHandler(0.01);
+
+ Position position = motionHandler.handlePosition(new Position());
+
+ assertEquals(false, position.getAttributes().get(Position.KEY_MOTION));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/events/AlertEventHandlerTest.java b/src/test/java/org/traccar/handler/events/AlertEventHandlerTest.java
new file mode 100644
index 000000000..3f0823245
--- /dev/null
+++ b/src/test/java/org/traccar/handler/events/AlertEventHandlerTest.java
@@ -0,0 +1,30 @@
+package org.traccar.handler.events;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.TestIdentityManager;
+import org.traccar.config.Config;
+import org.traccar.model.Event;
+import org.traccar.model.Position;
+
+public class AlertEventHandlerTest extends BaseTest {
+
+ @Test
+ public void testAlertEventHandler() {
+
+ AlertEventHandler alertEventHandler = new AlertEventHandler(new Config(), new TestIdentityManager());
+
+ Position position = new Position();
+ position.set(Position.KEY_ALARM, Position.ALARM_GENERAL);
+ Map<Event, Position> events = alertEventHandler.analyzePosition(position);
+ assertNotNull(events);
+ Event event = events.keySet().iterator().next();
+ assertEquals(Event.TYPE_ALARM, event.getType());
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/events/CommandResultEventHandlerTest.java b/src/test/java/org/traccar/handler/events/CommandResultEventHandlerTest.java
new file mode 100644
index 000000000..0ccf9f6b4
--- /dev/null
+++ b/src/test/java/org/traccar/handler/events/CommandResultEventHandlerTest.java
@@ -0,0 +1,28 @@
+package org.traccar.handler.events;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.model.Event;
+import org.traccar.model.Position;
+
+public class CommandResultEventHandlerTest extends BaseTest {
+
+ @Test
+ public void testCommandResultEventHandler() throws Exception {
+
+ CommandResultEventHandler commandResultEventHandler = new CommandResultEventHandler();
+
+ Position position = new Position();
+ position.set(Position.KEY_RESULT, "Test Result");
+ Map<Event, Position> events = commandResultEventHandler.analyzePosition(position);
+ assertNotNull(events);
+ Event event = events.keySet().iterator().next();
+ assertEquals(Event.TYPE_COMMAND_RESULT, event.getType());
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/events/IgnitionEventHandlerTest.java b/src/test/java/org/traccar/handler/events/IgnitionEventHandlerTest.java
new file mode 100644
index 000000000..dade20fb8
--- /dev/null
+++ b/src/test/java/org/traccar/handler/events/IgnitionEventHandlerTest.java
@@ -0,0 +1,27 @@
+package org.traccar.handler.events;
+
+import static org.junit.Assert.assertNull;
+
+import java.util.Map;
+
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.TestIdentityManager;
+import org.traccar.model.Event;
+import org.traccar.model.Position;
+
+public class IgnitionEventHandlerTest extends BaseTest {
+
+ @Test
+ public void testIgnitionEventHandler() {
+
+ IgnitionEventHandler ignitionEventHandler = new IgnitionEventHandler(new TestIdentityManager());
+
+ Position position = new Position();
+ position.set(Position.KEY_IGNITION, true);
+ position.setValid(true);
+ Map<Event, Position> events = ignitionEventHandler.analyzePosition(position);
+ assertNull(events);
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java b/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java
new file mode 100644
index 000000000..f57c16635
--- /dev/null
+++ b/src/test/java/org/traccar/handler/events/MotionEventHandlerTest.java
@@ -0,0 +1,119 @@
+package org.traccar.handler.events;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.model.DeviceState;
+import org.traccar.model.Event;
+import org.traccar.model.Position;
+import org.traccar.reports.model.TripsConfig;
+
+public class MotionEventHandlerTest extends BaseTest {
+
+ private Date date(String time) throws ParseException {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return dateFormat.parse(time);
+ }
+
+ @Test
+ public void testMotionWithPosition() throws Exception {
+ MotionEventHandler motionEventHandler = new MotionEventHandler(
+ null, null, new TripsConfig(500, 300 * 1000, 300 * 1000, 0, false, false, 0.01));
+
+ Position position = new Position();
+ position.setTime(date("2017-01-01 00:00:00"));
+ position.set(Position.KEY_MOTION, true);
+ position.set(Position.KEY_TOTAL_DISTANCE, 0);
+ DeviceState deviceState = new DeviceState();
+ deviceState.setMotionState(false);
+ deviceState.setMotionPosition(position);
+ Position nextPosition = new Position();
+
+ nextPosition.setTime(date("2017-01-01 00:02:00"));
+ nextPosition.set(Position.KEY_MOTION, true);
+ nextPosition.set(Position.KEY_TOTAL_DISTANCE, 200);
+
+ Map<Event, Position> events = motionEventHandler.updateMotionState(deviceState, nextPosition);
+ assertNull(events);
+
+ nextPosition.set(Position.KEY_TOTAL_DISTANCE, 600);
+ events = motionEventHandler.updateMotionState(deviceState, nextPosition);
+ assertNotNull(events);
+ Event event = events.keySet().iterator().next();
+ assertEquals(Event.TYPE_DEVICE_MOVING, event.getType());
+ assertTrue(deviceState.getMotionState());
+ assertNull(deviceState.getMotionPosition());
+
+ deviceState.setMotionState(false);
+ deviceState.setMotionPosition(position);
+ nextPosition.setTime(date("2017-01-01 00:06:00"));
+ nextPosition.set(Position.KEY_TOTAL_DISTANCE, 200);
+ events = motionEventHandler.updateMotionState(deviceState, nextPosition);
+ assertNotNull(event);
+ event = events.keySet().iterator().next();
+ assertEquals(Event.TYPE_DEVICE_MOVING, event.getType());
+ assertTrue(deviceState.getMotionState());
+ assertNull(deviceState.getMotionPosition());
+ }
+
+ @Test
+ public void testMotionWithStatus() throws Exception {
+ MotionEventHandler motionEventHandler = new MotionEventHandler(
+ null, null, new TripsConfig(500, 300 * 1000, 300 * 1000, 0, false, false, 0.01));
+
+ Position position = new Position();
+ position.setTime(new Date(System.currentTimeMillis() - 360000));
+ position.set(Position.KEY_MOTION, true);
+ DeviceState deviceState = new DeviceState();
+ deviceState.setMotionState(false);
+ deviceState.setMotionPosition(position);
+
+ Map<Event, Position> events = motionEventHandler.updateMotionState(deviceState);
+
+ assertNotNull(events);
+ Event event = events.keySet().iterator().next();
+ assertEquals(Event.TYPE_DEVICE_MOVING, event.getType());
+ assertTrue(deviceState.getMotionState());
+ assertNull(deviceState.getMotionPosition());
+ }
+
+ @Test
+ public void testStopWithPositionIgnition() throws Exception {
+ MotionEventHandler motionEventHandler = new MotionEventHandler(
+ null, null, new TripsConfig(500, 300 * 1000, 300 * 1000, 0, true, false, 0.01));
+
+ Position position = new Position();
+ position.setTime(date("2017-01-01 00:00:00"));
+ position.set(Position.KEY_MOTION, false);
+ position.set(Position.KEY_IGNITION, true);
+ DeviceState deviceState = new DeviceState();
+ deviceState.setMotionState(true);
+ deviceState.setMotionPosition(position);
+
+ Position nextPosition = new Position();
+ nextPosition.setTime(date("2017-01-01 00:02:00"));
+ nextPosition.set(Position.KEY_MOTION, false);
+ nextPosition.set(Position.KEY_IGNITION, false);
+
+ Map<Event, Position> events = motionEventHandler.updateMotionState(deviceState, nextPosition);
+ assertNotNull(events);
+ Event event = events.keySet().iterator().next();
+ assertEquals(Event.TYPE_DEVICE_STOPPED, event.getType());
+ assertFalse(deviceState.getMotionState());
+ assertNull(deviceState.getMotionPosition());
+ }
+
+}
diff --git a/src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java b/src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java
new file mode 100644
index 000000000..515f37b5d
--- /dev/null
+++ b/src/test/java/org/traccar/handler/events/OverspeedEventHandlerTest.java
@@ -0,0 +1,128 @@
+package org.traccar.handler.events;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.config.Config;
+import org.traccar.config.Keys;
+import org.traccar.model.DeviceState;
+import org.traccar.model.Event;
+import org.traccar.model.Position;
+
+public class OverspeedEventHandlerTest extends BaseTest {
+
+ private Date date(String time) throws ParseException {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return dateFormat.parse(time);
+ }
+
+ private void testOverspeedWithPosition(boolean notRepeat, long geofenceId) throws ParseException {
+ Config config = new Config();
+ config.setString(Keys.EVENT_OVERSPEED_NOT_REPEAT, String.valueOf(notRepeat));
+ config.setString(Keys.EVENT_OVERSPEED_MINIMAL_DURATION, String.valueOf(15));
+ config.setString(Keys.EVENT_OVERSPEED_PREFER_LOWEST, String.valueOf(false));
+ OverspeedEventHandler overspeedEventHandler = new OverspeedEventHandler(config, null, null);
+
+ Position position = new Position();
+ position.setTime(date("2017-01-01 00:00:00"));
+ position.setSpeed(50);
+ DeviceState deviceState = new DeviceState();
+ deviceState.setOverspeedState(false);
+
+ Map<Event, Position> events = overspeedEventHandler.updateOverspeedState(deviceState, position, 40, geofenceId);
+ assertNull(events);
+ assertFalse(deviceState.getOverspeedState());
+ assertEquals(position, deviceState.getOverspeedPosition());
+ assertEquals(geofenceId, deviceState.getOverspeedGeofenceId());
+
+ Position nextPosition = new Position();
+ nextPosition.setTime(date("2017-01-01 00:00:10"));
+ nextPosition.setSpeed(55);
+
+ events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId);
+ assertNull(events);
+
+ nextPosition.setTime(date("2017-01-01 00:00:20"));
+
+ events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId);
+ assertNotNull(events);
+ Event event = events.keySet().iterator().next();
+ assertEquals(Event.TYPE_DEVICE_OVERSPEED, event.getType());
+ assertEquals(50, event.getDouble("speed"), 0.1);
+ assertEquals(40, event.getDouble(OverspeedEventHandler.ATTRIBUTE_SPEED_LIMIT), 0.1);
+ assertEquals(geofenceId, event.getGeofenceId());
+
+ assertEquals(notRepeat, deviceState.getOverspeedState());
+ assertNull(deviceState.getOverspeedPosition());
+ assertEquals(0, deviceState.getOverspeedGeofenceId());
+
+ nextPosition.setTime(date("2017-01-01 00:00:30"));
+ events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId);
+ assertNull(events);
+ assertEquals(notRepeat, deviceState.getOverspeedState());
+
+ if (notRepeat) {
+ assertNull(deviceState.getOverspeedPosition());
+ assertEquals(0, deviceState.getOverspeedGeofenceId());
+ } else {
+ assertNotNull(deviceState.getOverspeedPosition());
+ assertEquals(geofenceId, deviceState.getOverspeedGeofenceId());
+ }
+
+ nextPosition.setTime(date("2017-01-01 00:00:40"));
+ nextPosition.setSpeed(30);
+
+ events = overspeedEventHandler.updateOverspeedState(deviceState, nextPosition, 40, geofenceId);
+ assertNull(events);
+ assertFalse(deviceState.getOverspeedState());
+ assertNull(deviceState.getOverspeedPosition());
+ assertEquals(0, deviceState.getOverspeedGeofenceId());
+ }
+
+ private void testOverspeedWithStatus(boolean notRepeat) {
+ Config config = new Config();
+ config.setString(Keys.EVENT_OVERSPEED_NOT_REPEAT, String.valueOf(notRepeat));
+ config.setString(Keys.EVENT_OVERSPEED_MINIMAL_DURATION, String.valueOf(15));
+ config.setString(Keys.EVENT_OVERSPEED_PREFER_LOWEST, String.valueOf(false));
+ OverspeedEventHandler overspeedEventHandler = new OverspeedEventHandler(config, null, null);
+
+ Position position = new Position();
+ position.setTime(new Date(System.currentTimeMillis() - 30000));
+ position.setSpeed(50);
+ DeviceState deviceState = new DeviceState();
+ deviceState.setOverspeedState(false);
+ deviceState.setOverspeedPosition(position);
+
+ Map<Event, Position> events = overspeedEventHandler.updateOverspeedState(deviceState, 40);
+
+ assertNotNull(events);
+ Event event = events.keySet().iterator().next();
+ assertEquals(Event.TYPE_DEVICE_OVERSPEED, event.getType());
+ assertEquals(notRepeat, deviceState.getOverspeedState());
+ }
+
+ @Test
+ public void testOverspeedEventHandler() throws Exception {
+ testOverspeedWithPosition(false, 0);
+ testOverspeedWithPosition(true, 0);
+
+ testOverspeedWithPosition(false, 1);
+ testOverspeedWithPosition(true, 1);
+
+ testOverspeedWithStatus(false);
+ testOverspeedWithStatus(true);
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/BcdUtilTest.java b/src/test/java/org/traccar/helper/BcdUtilTest.java
new file mode 100644
index 000000000..86a32f725
--- /dev/null
+++ b/src/test/java/org/traccar/helper/BcdUtilTest.java
@@ -0,0 +1,24 @@
+package org.traccar.helper;
+
+import io.netty.buffer.Unpooled;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class BcdUtilTest {
+
+ @Test
+ public void testReadInteger() {
+ byte[] buf = {0x01, (byte) 0x90, 0x34};
+ int result = BcdUtil.readInteger(Unpooled.wrappedBuffer(buf), 5);
+ assertEquals(1903, result);
+ }
+
+ @Test
+ public void testReadCoordinate() {
+ byte[] buf = {0x03, (byte) 0x85, 0x22, 0x59, 0x34};
+ double result = BcdUtil.readCoordinate(Unpooled.wrappedBuffer(buf));
+ assertEquals(38.870989, result, 0.00001);
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/BitBufferTest.java b/src/test/java/org/traccar/helper/BitBufferTest.java
new file mode 100644
index 000000000..c2abad36d
--- /dev/null
+++ b/src/test/java/org/traccar/helper/BitBufferTest.java
@@ -0,0 +1,23 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class BitBufferTest {
+
+ @Test
+ public void test() {
+ BitBuffer buffer = new BitBuffer();
+
+ buffer.write(0b100100);
+ buffer.write(0b110110);
+ buffer.write(0b111111);
+ buffer.write(0b111111);
+
+ assertEquals(0b100, buffer.readUnsigned(3));
+ assertEquals(-7, buffer.readSigned(4));
+ assertEquals(0b10110, buffer.readUnsigned(5));
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/BitUtilTest.java b/src/test/java/org/traccar/helper/BitUtilTest.java
new file mode 100644
index 000000000..90431bf55
--- /dev/null
+++ b/src/test/java/org/traccar/helper/BitUtilTest.java
@@ -0,0 +1,38 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class BitUtilTest {
+
+ @Test
+ public void testCheck() {
+ assertFalse(BitUtil.check(0, 0));
+ assertTrue(BitUtil.check(1, 0));
+ assertFalse(BitUtil.check(2, 0));
+ }
+
+ @Test
+ public void testBetween() {
+ assertEquals(0, BitUtil.between(0, 0, 0));
+ assertEquals(1, BitUtil.between(1, 0, 1));
+ assertEquals(2, BitUtil.between(2, 0, 2));
+ assertEquals(2, BitUtil.between(6, 0, 2));
+ }
+
+ @Test
+ public void testFrom() {
+ assertEquals(1, BitUtil.from(1, 0));
+ assertEquals(0, BitUtil.from(1, 1));
+ }
+
+ @Test
+ public void testTo() {
+ assertEquals(2, BitUtil.to(2, 2));
+ assertEquals(0, BitUtil.to(2, 1));
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/ChecksumTest.java b/src/test/java/org/traccar/helper/ChecksumTest.java
new file mode 100644
index 000000000..5737b9ff5
--- /dev/null
+++ b/src/test/java/org/traccar/helper/ChecksumTest.java
@@ -0,0 +1,39 @@
+package org.traccar.helper;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.Assert.assertEquals;
+
+public class ChecksumTest {
+
+ @Test
+ public void testCrc8() {
+ ByteBuf buf = Unpooled.copiedBuffer("123456789", StandardCharsets.US_ASCII);
+
+ assertEquals(0xF7, Checksum.crc8(Checksum.CRC8_EGTS, buf.nioBuffer()));
+ assertEquals(0xD0, Checksum.crc8(Checksum.CRC8_ROHC, buf.nioBuffer()));
+ }
+
+ @Test
+ public void testCrc16() {
+ ByteBuf buf = Unpooled.copiedBuffer("123456789", StandardCharsets.US_ASCII);
+
+ assertEquals(0xBB3D, Checksum.crc16(Checksum.CRC16_IBM, buf.nioBuffer()));
+ assertEquals(0x4B37, Checksum.crc16(Checksum.CRC16_MODBUS, buf.nioBuffer()));
+ assertEquals(0x906e, Checksum.crc16(Checksum.CRC16_X25, buf.nioBuffer()));
+ assertEquals(0x29b1, Checksum.crc16(Checksum.CRC16_CCITT_FALSE, buf.nioBuffer()));
+ assertEquals(0x2189, Checksum.crc16(Checksum.CRC16_KERMIT, buf.nioBuffer()));
+ assertEquals(0x31c3, Checksum.crc16(Checksum.CRC16_XMODEM, buf.nioBuffer()));
+ }
+
+ @Test
+ public void testLuhn() {
+ assertEquals(7, Checksum.luhn(12345678901234L));
+ assertEquals(0, Checksum.luhn(63070019470771L));
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/DateBuilderTest.java b/src/test/java/org/traccar/helper/DateBuilderTest.java
new file mode 100644
index 000000000..b6323cc1d
--- /dev/null
+++ b/src/test/java/org/traccar/helper/DateBuilderTest.java
@@ -0,0 +1,27 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+import static org.junit.Assert.assertEquals;
+
+public class DateBuilderTest {
+
+ @Test
+ public void testDateBuilder() throws ParseException {
+
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ DateBuilder dateBuilder = new DateBuilder()
+ .setDate(2015, 10, 20).setTime(1, 21, 11);
+
+ assertEquals(dateFormat.parse("2015-10-20 01:21:11"), dateBuilder.getDate());
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/DateUtilTest.java b/src/test/java/org/traccar/helper/DateUtilTest.java
new file mode 100644
index 000000000..ec42e71ae
--- /dev/null
+++ b/src/test/java/org/traccar/helper/DateUtilTest.java
@@ -0,0 +1,30 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+import static org.junit.Assert.assertEquals;
+
+public class DateUtilTest {
+
+ @Test
+ public void testCorrectDate() throws ParseException {
+
+ DateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ assertEquals(f.parse("2015-12-31 23:59:59"),
+ DateUtil.correctDate(f.parse("2016-01-01 00:00:01"), f.parse("2016-01-01 23:59:59"), Calendar.DAY_OF_MONTH));
+
+ assertEquals(f.parse("2016-01-01 00:00:02"),
+ DateUtil.correctDate(f.parse("2016-01-01 00:00:01"), f.parse("2016-01-01 00:00:02"), Calendar.DAY_OF_MONTH));
+
+ assertEquals(f.parse("2016-01-01 00:00:02"),
+ DateUtil.correctDate(f.parse("2016-01-01 00:00:01"), f.parse("2015-12-31 00:00:02"), Calendar.DAY_OF_MONTH));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/DistanceCalculatorTest.java b/src/test/java/org/traccar/helper/DistanceCalculatorTest.java
new file mode 100644
index 000000000..a7457b6c4
--- /dev/null
+++ b/src/test/java/org/traccar/helper/DistanceCalculatorTest.java
@@ -0,0 +1,24 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class DistanceCalculatorTest {
+
+ @Test
+ public void testDistance() {
+ assertEquals(
+ DistanceCalculator.distance(0.0, 0.0, 0.05, 0.05), 7863.0, 10.0);
+ }
+
+ @Test
+ public void testDistanceToLine() {
+ assertEquals(DistanceCalculator.distanceToLine(
+ 56.83801, 60.59748, 56.83777, 60.59833, 56.83766, 60.5968), 33.0, 5.0);
+
+ assertEquals(DistanceCalculator.distanceToLine(
+ 56.83753, 60.59508, 56.83777, 60.59833, 56.83766, 60.5968), 105.0, 5.0);
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/LocationTreeTest.java b/src/test/java/org/traccar/helper/LocationTreeTest.java
new file mode 100644
index 000000000..21604144a
--- /dev/null
+++ b/src/test/java/org/traccar/helper/LocationTreeTest.java
@@ -0,0 +1,30 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class LocationTreeTest {
+
+ @Test
+ public void testLocationTree() {
+
+ List<LocationTree.Item> items = new ArrayList<>();
+ items.add(new LocationTree.Item(1, 1, "a"));
+ items.add(new LocationTree.Item(3, 2, "b"));
+ items.add(new LocationTree.Item(1, 3, "c"));
+ items.add(new LocationTree.Item(4, 3, "d"));
+
+ LocationTree tree = new LocationTree(items);
+
+ assertEquals("a", tree.findNearest(new LocationTree.Item(1f, 1f)).getData());
+ assertEquals("d", tree.findNearest(new LocationTree.Item(10f, 10f)).getData());
+ assertEquals("c", tree.findNearest(new LocationTree.Item(1f, 2.5f)).getData());
+ assertEquals("a", tree.findNearest(new LocationTree.Item(1.5f, 1.5f)).getData());
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/LogTest.java b/src/test/java/org/traccar/helper/LogTest.java
new file mode 100644
index 000000000..853eb05c9
--- /dev/null
+++ b/src/test/java/org/traccar/helper/LogTest.java
@@ -0,0 +1,14 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class LogTest {
+
+ @Test
+ public void testLog() {
+ assertEquals("test - Exception (LogTest:11 < ...)", Log.exceptionStack(new Exception("test")));
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/ObdDecoderTest.java b/src/test/java/org/traccar/helper/ObdDecoderTest.java
new file mode 100644
index 000000000..1ffe68c8b
--- /dev/null
+++ b/src/test/java/org/traccar/helper/ObdDecoderTest.java
@@ -0,0 +1,26 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class ObdDecoderTest {
+
+ @Test
+ public void testDecode() {
+
+ assertEquals(83, ObdDecoder.decode(0x01, "057b").getValue());
+ assertEquals(1225, ObdDecoder.decode(0x01, "0C1324").getValue());
+ assertEquals(20, ObdDecoder.decode(0x01, "0D14").getValue());
+ assertEquals(64050, ObdDecoder.decode(0x01, "31fa32").getValue());
+ assertEquals(25, ObdDecoder.decode(0x01, "2F41").getValue());
+
+ }
+
+ @Test
+ public void testDecodeCodes() throws Exception {
+ assertEquals("P0D14", ObdDecoder.decodeCodes("0D14").getValue());
+ assertEquals("dtcs", ObdDecoder.decodeCodes("0D14").getKey());
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/PatternBuilderTest.java b/src/test/java/org/traccar/helper/PatternBuilderTest.java
new file mode 100644
index 000000000..4c76bc463
--- /dev/null
+++ b/src/test/java/org/traccar/helper/PatternBuilderTest.java
@@ -0,0 +1,20 @@
+package org.traccar.helper;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class PatternBuilderTest {
+
+ @Test
+ public void testPatternBuilder() {
+ assertEquals("\\$GPRMC", new PatternBuilder().text("$GPRMC").toString());
+ assertEquals("(\\d{2}\\.[0-9a-fA-F]+)", new PatternBuilder().number("(dd.x+)").toString());
+ assertEquals("a(?:bc)?", new PatternBuilder().text("a").text("b").text("c").optional(2).toString());
+ assertEquals("a|b", new PatternBuilder().expression("a|b").toString());
+ assertEquals("ab\\|", new PatternBuilder().expression("ab|").toString());
+ assertEquals("|", new PatternBuilder().or().toString());
+ assertEquals("\\|\\d|\\d\\|", new PatternBuilder().number("|d|d|").toString());
+ }
+
+}
diff --git a/src/test/java/org/traccar/helper/PatternUtilTest.java b/src/test/java/org/traccar/helper/PatternUtilTest.java
new file mode 100644
index 000000000..77660078a
--- /dev/null
+++ b/src/test/java/org/traccar/helper/PatternUtilTest.java
@@ -0,0 +1,18 @@
+package org.traccar.helper;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class PatternUtilTest {
+
+ @Ignore
+ @Test
+ public void testCheckPattern() {
+
+ assertEquals("ab", PatternUtil.checkPattern("abc", "abd").getPatternMatch());
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/model/MiscFormatterTest.java b/src/test/java/org/traccar/model/MiscFormatterTest.java
new file mode 100644
index 000000000..eb93d5b38
--- /dev/null
+++ b/src/test/java/org/traccar/model/MiscFormatterTest.java
@@ -0,0 +1,20 @@
+package org.traccar.model;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class MiscFormatterTest {
+
+ @Test
+ public void testToString() throws Exception {
+
+ Position position = new Position();
+ position.set("a", "1");
+ position.set("b", "2");
+ position.set("a", "3");
+
+ assertEquals("<info><a>3</a><b>2</b></info>", MiscFormatter.toXmlString(position.getAttributes()));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/notification/NotificiationMailTest.java b/src/test/java/org/traccar/notification/NotificiationMailTest.java
new file mode 100644
index 000000000..b82bec02e
--- /dev/null
+++ b/src/test/java/org/traccar/notification/NotificiationMailTest.java
@@ -0,0 +1,59 @@
+package org.traccar.notification;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import javax.mail.Message;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import java.util.Properties;
+
+public class NotificiationMailTest {
+
+ private static final String FROM = "notification@traccar.org";
+ private static final String TO = "anton@traccar.org";
+
+ private static final String BODY = "Test email body.";
+ private static final String SUBJECT = "Test";
+
+ private static final String SMTP_USERNAME = "username";
+ private static final String SMTP_PASSWORD = "password";
+
+ private static final String HOST = "email-smtp.us-west-2.amazonaws.com";
+
+ private static final int PORT = 25;
+
+ @Ignore
+ @Test
+ public void test() throws Exception {
+
+ Properties props = System.getProperties();
+ props.put("mail.transport.protocol", "smtps");
+ props.put("mail.smtp.port", PORT);
+
+ props.put("mail.smtp.auth", "true");
+ props.put("mail.smtp.starttls.enable", "true");
+ props.put("mail.smtp.starttls.required", "true");
+
+ Session session = Session.getInstance(props);
+
+ MimeMessage msg = new MimeMessage(session);
+ msg.setFrom(new InternetAddress(FROM));
+ msg.setRecipient(Message.RecipientType.TO, new InternetAddress(TO));
+ msg.setSubject(SUBJECT);
+ msg.setContent(BODY, "text/plain");
+
+ Transport transport = session.getTransport();
+
+ try {
+ transport.connect(HOST, SMTP_USERNAME, SMTP_PASSWORD);
+ transport.sendMessage(msg, msg.getAllRecipients());
+ } finally {
+ transport.close();
+ }
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AdmProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AdmProtocolDecoderTest.java
new file mode 100644
index 000000000..599dd6190
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AdmProtocolDecoderTest.java
@@ -0,0 +1,38 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AdmProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AdmProtocolDecoder decoder = new AdmProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "010042033836313331313030323639343838320501000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073"));
+
+ verifyPosition(decoder, binary(
+ "01002e40041c0744009dfe6742c6c860427402000000f4ff077752c8f55b000000000b4132010213430100041e"));
+
+ verifyPosition(decoder, binary(
+ "01002680336510002062A34C423DCF8E42A50B1700005801140767E30F568F2534107D220000"));
+
+ verifyPosition(decoder, binary(
+ "010022003300072020000000000000000044062A330000000000107F10565D4A8310"));
+
+ verifyPosition(decoder, binary(
+ "0100268033641080207AA34C424CCF8E4239030800005B01140755E30F560000F00F70220000"));
+
+ verifyPosition(decoder, binary(
+ "01002680336510002062A34C423DCF8E42A50B1700005801140767E30F568F2534107D220000"));
+
+ verifyPosition(decoder, binary(
+ "01002200333508202000000000000000007F0D9F030000000000E39A1056E24A8210"));
+
+ verifyNotNull(decoder, binary(
+ "01008449443d3120536f66743d30783531204750533d313036382054696d653d30383a35393a32302031302e30392e31372056616c3d30204c61743d36312e36373738204c6f6e3d35302e3832343520563d3020536174436e743d342b3720537461743d30783030313020496e5f616c61726d3d30783030000000000000000000000000"));
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AdmProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/AdmProtocolEncoderTest.java
new file mode 100644
index 000000000..cb0a31ceb
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AdmProtocolEncoderTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 Anatoliy Golubev (darth.naihil@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.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class AdmProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ AdmProtocolEncoder encoder = new AdmProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_GET_DEVICE_STATUS);
+ assertEquals("STATUS\r\n", encoder.encodeCommand(command));
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "INPUT 0");
+ assertEquals("INPUT 0\r\n", encoder.encodeCommand(command));
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AisProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AisProtocolDecoderTest.java
new file mode 100644
index 000000000..9cb9f695a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AisProtocolDecoderTest.java
@@ -0,0 +1,31 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AisProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AisProtocolDecoder decoder = new AisProtocolDecoder(null);
+
+ verifyPositions(decoder, text(
+ "!AIVDM,2,1,8,A,53UlSb01l>Ei=H4KF218PTpv222222222222221?8h=766gB0<Ck11DTp888,0*14s:MTb827ebc7686b,c:1481688227737*4d\\\r\n" +
+ "!AIVDM,2,2,8,A,88888888888,2*24\r\n" +
+ "!AIVDM,1,1,,A,13T=Qr0P001cmmLEf;A00?wN0PSU,0*29\r\n" +
+ "!AIVDM,1,1,,A,35Qf023Ohi1n5gdDRLW5FSQP00u@,0*18\r\n" +
+ "!AIVDM,1,1,,A,B3P@f>0000K6J;5KAIT03wpUkP06,0*5D\\s:MTb827ebc7686b,c:1481688230418*45\\\r\n" +
+ "!AIVDM,1,1,,B,B52Q8a@00Ul`9N5@ssbmCwr5oP06,0*36\r\n" +
+ "!AIVDM,1,1,,A,1815<S@01VQnKGlE0sk:WHcT0@O4,0*78\r\n" +
+ "!AIVDM,1,1,,A,35N7G;5OhQG?oJfE`G`cM9E`0001,0*6C\r\n" +
+ "!AIVDM,1,1,,B,13Ug;r0P011cqHJEevuEiOwf0L3h,0*6A\r\n" +
+ "!AIVDM,1,1,,A,13MKsr?0001dJC2Ee4W;jnal08Qj,0*00\r\n\r\n"));
+
+ verifyPositions(decoder, text(
+ "!AIVDM,1,1,,A,H3FUli4T000000000000001p0400,0*6E\\s:MTb827eba584a8,c:1481688176110*46\\\r\n" +
+ "!AIVDM,1,1,,B,13UhUh0P01QcoRTEdtB>4?v<2D=j,0*54\r\n\r\n"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AlematicsProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AlematicsProtocolDecoderTest.java
new file mode 100644
index 000000000..47ea8137e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AlematicsProtocolDecoderTest.java
@@ -0,0 +1,42 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AlematicsProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AlematicsProtocolDecoder decoder = new AlematicsProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$T,2,64,866050035975497,20180726103446,20180726103514,23.033305,72.558032,0,0,41,5.4,4,0,0,0.000,12.960,0,"));
+
+ verifyPosition(decoder, text(
+ "$T,2,65,866050035975497,20180726103646,20180726103736,23.033305,72.558032,0,0,41,5.4,4,0,0,0.000,12.976,0,0"));
+
+ verifyPosition(decoder, text(
+ "$T,2,552,868259020159698,20170515060949,20170515060949,25.035277,121.561986,0,202,78,1.0,8,1,0,0.000,12.768,1629,38,12770,4109,9"));
+
+ verifyPosition(decoder, text(
+ "$T,2,553,868259020159698,20170515061019,20170515061019,25.035295,121.561981,0,202,79,1.0,8,1,0,0.000,12.768,1629,38,12772,4109,8"));
+
+ verifyPosition(decoder, text(
+ "$T,4,4,868259020159698,20170515061033,20170515061033,25.035303,121.561975,0,202,81,1.7,6,1,0,0.000,12.770,1629,0,$S,A1,1,,12345.67,88.4,301.5,,2593.25,12.4,89.2,,5999.44,789.572,2345.67,,10763,1024,5,"));
+
+ verifyPosition(decoder, text(
+ "$T,2,554,868259020159698,20170515061049,20170515061049,25.035309,121.561976,0,202,82,1.1,7,1,0,0.000,12.768,1629,38,12770,4109,9"));
+
+ verifyPosition(decoder, text(
+ "$T,4,5,868259020159698,20170515061058,20170515061058,25.035308,121.561976,0,202,82,1.2,7,1,0,0.000,12.772,1629,0,$S,A1,1,,12345.67,88.4,301.5,,2593.25,12.4,89.2,,5999.44,789.572,2345.67,,10763,1024,5,"));
+
+ verifyPosition(decoder, text(
+ "$T,50,592,868259020159698,20170515062915,20170515062915,25.035005,121.561555,0,31,89,3.7,5,1,0,0.000,12.752,1629,38,12752,4203,6"));
+
+ verifyPosition(decoder, text(
+ "$T,50,594,868259020159698,20170515062928,20170515062928,25.035151,121.561671,0,31,93,1.8,5,0,0,0.000,12.752,1629,38,12756,4205,6"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AnytrekProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AnytrekProtocolDecoderTest.java
new file mode 100644
index 000000000..e3aa0550b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AnytrekProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AnytrekProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AnytrekProtocolDecoder decoder = new AnytrekProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "78783500300086428703204121160085015111050C0A0D20C6FD24A102FF8EAC0C01001404000000FFFFFFFF131702210000000000000000000D0A"));
+
+ verifyPosition(decoder, binary(
+ "787835003000867279033457792c009801001209080a3408c81b2a7d0305b88b0c00001ccb0000000f00000002b90174f30b000000000000000d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ApelProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ApelProtocolDecoderTest.java
new file mode 100644
index 000000000..c32abe6a8
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ApelProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ApelProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ApelProtocolDecoder decoder = new ApelProtocolDecoder(null);
+
+ /*byte[] buf1 = {0x40,0x4E,0x54,0x43,0x01,0x00,0x00,0x00,0x7B,0x00,0x00,0x00,0x13,0x00,0x44,0x34,0x2A,0x3E,0x53,0x3A,0x38,0x36,0x31,0x37,0x38,0x35,0x30,0x30,0x35,0x32,0x30,0x35,0x30,0x37,0x39};
+ verifyNull(decoder, text( ChannelBuffers.wrappedBuffer(ByteOrder.LITTLE_ENDIAN, buf1)));*/
+
+ //0c002900f12a00000f003235303032363533343135313036340f0033353638393530333632373938313101002000000000
+ //5c00380046e6a95136b693277f11b41a00172709f2ff03160002b9bc630007000000000000000000000000000000c31071090000880500000000000000000000
+ //5c00380072e7a95136b693277f11b41a00172709f2ff03160002b9bc630007000000000000000000000000000000c31071090000880500000000000000000000
+
+ //7900040069ea030000000000
+ //8300c20003006aea03005c003800223aab5107a393276617b41a0030d506e3000414010250bf630007000000000000000000000000000000c3107209000089050000000000006bea03005c003800403aab5107a393276617b41a0030d506e3000414010250bf630007000000000000000000000000000000c3107209000089050000000000006cea03005c0038005e3aab5107a393276617b41a0030d506e3000414010250bf630007000000000000000000000000000000c31072090000890500000000000000000000
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AplicomFrameDecoderTest.java b/src/test/java/org/traccar/protocol/AplicomFrameDecoderTest.java
new file mode 100644
index 000000000..581f7696f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AplicomFrameDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class AplicomFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AplicomFrameDecoder decoder = new AplicomFrameDecoder();
+
+ assertEquals(
+ binary("44C20146B710C158DA009500B09F7700C054CA0EA454CA0EA403BE0BF6015D706B070000142A600000000000000002434946010801000754CA0EA4000000000000008400000000000000000000000000000000300000FE00FE0000000000000000000000000000000000000000000000000000000000000000000040502035000000000000020D0000030D0000040C0000040D0000050C0000050D0000058C0000060C"),
+ decoder.decode(null, null, binary("33353733303030373030393233333644C20146B710C158DA009500B09F7700C054CA0EA454CA0EA403BE0BF6015D706B070000142A600000000000000002434946010801000754CA0EA4000000000000008400000000000000000000000000000000300000FE00FE0000000000000000000000000000000000000000000000000000000000000000000040502035000000000000020D0000030D0000040C0000040D0000050C0000050D0000058C0000060C")));
+
+ assertEquals(
+ binary("44C20146B710C158DA009500B09F7700C054CA0EA454CA0EA403BE0BF6015D706B070000142A600000000000000002434946010801000754CA0EA4000000000000008400000000000000000000000000000000300000FE00FE0000000000000000000000000000000000000000000000000000000000000000000040502035000000000000020D0000030D0000040C0000040D0000050C0000050D0000058C0000060C"),
+ decoder.decode(null, null, binary("44C20146B710C158DA009500B09F7700C054CA0EA454CA0EA403BE0BF6015D706B070000142A600000000000000002434946010801000754CA0EA4000000000000008400000000000000000000000000000000300000FE00FE0000000000000000000000000000000000000000000000000000000000000000000040502035000000000000020D0000030D0000040C0000040D0000050C0000050D0000058C0000060C")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AplicomProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AplicomProtocolDecoderTest.java
new file mode 100644
index 000000000..0b4180bd0
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AplicomProtocolDecoderTest.java
@@ -0,0 +1,93 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AplicomProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AplicomProtocolDecoder decoder = new AplicomProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "434946010A0100075253F85F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FEEA0000FEE90000F0030000F0040000FEF10000FEF20000FEF50000FEFC0000FEC10000FEE500"));
+
+ verifyAttributes(decoder, binary(
+ "44c30144f667c0e462019800b05f7700005b7d3bdd00000000000000000000000000000000805e420fd60a0d57fffffb002141100000011001000c0932200000000000000a18136fcafefffffb002141100000011001000c0932200000000000000a1812e6dbfefffffb002141100000011001000c746578746167204e000008e3980bfefffffb002141100000011001000ce2009000170400890310f290e873fefffffb002141100000011001000ce2009000170400890290f28e409afefffffb002141100000011001000c0932200000000000000a1812e6dbfefffffb002141100000011001000ce2009000170400890280f28d4e2dfefffffb002141100000011001000c0001460000000000000021427a6cfefffffb002141100000011001000c0001460000000000000021606a6efefffffb002141100000011001000c746578746167204e000008badcc4fefffffb002141100000011001000c00014600000000000000218c0843fefffffb002141100000011001000ce2009000170400890270f6d45e09fefffffb002141100000011001000ce2801160600002053cd57a16549efe"));
+
+ verifyAttributes(decoder, binary(
+ "44c30144f667ca8e6b003200b45f7700f05b6565e75b6565e6031f845100c6f0e70c00001483387c0fe60001000a263433233031303138373433303746230d0a"));
+
+ verifyAttributes(decoder, binary(
+ "44c30144f667ca8e6b002d00305f7700d45b307a9a5b307a97031f840a00c6f05b0600000083000000263433233031303138373433303746230d0a"));
+
+ verifyAttributes(decoder, binary(
+ "44c30144f667c4316500e903ffdfbc00f059aebeb659aebeb302e3f5860065fe32120000ae0000000e47000000000000000000000000000127cd0000014c00000000000000ff010a002900000000000000014542016d0001010090070e140144f667c4316559ae620402e3f7f300660714c0010d15ff0f3332373937313100000000000000000000002a01010737341d331fffcf0103020b8601060c0001a5860001a58600000000010b1001ca01ca7d007d007c7cffffffffffff010a240000ffff0000000100010001ffff0000ffffffffffffffffffffffffffff00000002ffff010c06fec6febffeec"));
+
+ verifyAttributes(decoder, binary(
+ "45c20144f667c06ff9005d0161ef17000104596da2dc4b10c0c01d99020d6c04004cba7a010d44463030303235333731363238303030000000000000000000000000000000000000000000000000000001010d44463030303235333731363238303030000000000000031c"));
+
+ verifyAttributes(decoder, binary(
+ "45c20144f667c07287008c01ffff6d01000059368963d0340a0616207d7f4b10c0c019e6000039d7000039d71f40ffff5001574442393036363035533132333435363700014142432d33343520202020202000011231303331373139343039303030303031000000000000000000000000000000000000000000000000000001011231303331373139343039303030303031000000000000005a"));
+
+ verifyAttributes(decoder, binary(
+ "46c30144f667c1711f00340007ff750058b8f77701037c06b8000000330033000000000b760000425e0100640000b3a90185d5823155000131070204000219641004"));
+
+ verifyAttributes(decoder, binary(
+ "46c30144f667c1711f00340007ff75005891601401025707b50236003b003b003500000a9300006bd50100640000a5250167d2f9034c01010107020400021a901004"));
+
+ verifyAttributes(decoder, binary(
+ "48C1014143B4493145004900203F6D014B5557C20003000015060110FF00C800000000000000003D01141E283C500100260404010200000000000000000000000000C8000000000000010200110019001E0064019003E8"));
+
+ verifyAttributes(decoder, binary(
+ "48c10144b9de54e6b2008700205f710a57d23ec957d23b8d00000000300d0106ff00000000000000000000000000000000000000000000000000000000000000010a141e28323c46505a646e7801000f020104ff000000000000000000010102000f020104ff000000000000000000010103000f020104ff000000000000000000010105000f020104ff0000000000000000000101"));
+
+ verifyAttributes(decoder, binary(
+ "45c20145931876ffb2007100ffff6d00000057c6dd1970230d087b1f7d7f0000d0c1000000003580000035801f40ffff5001574442393036363035533132333435363700014142432d333435202020202020000000000000000000000000000000000000000000000001123130343632343639373030303030303100000000"));
+
+ verifyAttributes(decoder, binary(
+ "45c20145931876ffb2007100ffff6d00000057c6dd9170250d087b1f7d7f0000d0c1000000003580000035801f40ffff5001574442393036363035533132333435363700014142432d333435202020202020000000000000000000000000000000000000000000000001123130343632343639373030303030303100000000"));
+
+ verifyAttributes(decoder, binary(
+ "45c20145931876ffb2007100ffff6d00000057c6de0970270d087b1f7d7f0000d0c1000000003580000035801f40ffff5001574442393036363035533132333435363700014142432d333435202020202020000000000000000000000000000000000000000000000001123130343632343639373030303030303100000000"));
+
+ verifyAttributes(decoder, binary(
+ "44c3014645e8ecff3c00ea03ffffbc00f457d68a6557d68a6303bb55fa018843da1100009881000000000000000000000000000000000000000000000000000000000000000000000000000000ff0056007600000000000000014542016d0001010095070e14014645e8ecff3c57d68a6403bb55fa018843dac0010d14ff050102030405060708090a0b0c0d0e0f10112a01010730343f3c1ff5cf01020700007d007d23010103022f2e01060c67452301efcdab8967452301010b10000000007d007d007d7dffffffffffff010a2400000000000000010000000000000000ffffffffffffffff00010001ffff00000000ffff010c02fec6"));
+
+ verifyPosition(decoder, binary(
+ "44c3014645e8e91b66002300a21f0b01f056d3e62856d3e626031f845f00c6ee440800000000000000000017bd1cb30000"));
+
+ verifyPosition(decoder, binary(
+ "44c3014645e8e91b66002300a21f0b00f056d3e64756d3e646031f845f00c6ee440800000000000000000017bd1cb30001"));
+
+ verifyPosition(decoder, binary(
+ "44c3014645e8e91b66001f00221f0b01f456ba1e0d56ba1e0b031f842200c6ef550c000000000017bd1cb30004"));
+
+ verifyAttributes(decoder, binary(
+ "44c3014645e8e9bada003e03fff7070055a4f24200000081000000000000000000000000000000000000000000000000000000000000000000000000000000ff00000001000000000000000044c3014645e8e9bada003e03fff77bff55a4f24300000081000000000000000000000000000000000000000000000000000000000000000000000000000000ff00300002000000000000000044c3014645e8e9bada003e03fff7690655a4f24500000081000000000000000000000000000000000000000000000000000000000000000000000000000000ff003000030000000000000000"));
+
+ verifyPosition(decoder, binary(
+ "44c3014645e8e9d29a002d0022ff6d00f455893b4d55893b4c027a7e1500189d710800009e0000000000000000000000023300000000000000009d"));
+
+ verifyPosition(decoder, binary(
+ "44C20146B710C158DA002100B09F0700C054CA0EA254CA0E9C03BE0BF6015D7069070000142A600000000000000001"));
+
+ verifyPosition(decoder, binary(
+ "44C20143720729D6840043031fff7191C0450ef906450ef90603b20b8003b20b80066465b3870ce30f010ce30ce3003200001520000000030aa200003b13000000320300000bcb17acff0099000186a002"));
+
+ verifyPosition(decoder, binary(
+ "440129D684002b0700C0450ef906450ef90603b20b8003b20b80066465b3870ce30f010ce30ce300003b130300000bcb170a"));
+
+ verifyPosition(decoder, binary(
+ "44c3014645e8e9152e008900b09f7700f4558c07e8558c07e703be0bd8015d6faf0e0000003240000000000000000f4349460107010007558c07e70000000000000002d209df028f05fffe00000000000000002eff13fe11fe1a00011000000000000010ff11ff3cff11008c00080060f41b0043502015000000000000020d0000030d0000040c0000040d0000050c0000050d0000058c"));
+
+ verifyPosition(decoder, binary(
+ "44c20144563508385a009500b09f7700c0555ea99e555ea9b103bb569f01883ff50b00002a30f000000000000013074349460108010007555ea99e000000000000003f0000ae017605b3ff00000000010000006700d900d500000003000000000000006700d900d500000087002500c4ff0000435020150000000040512001000000000000020d0000030d0000040c0000040d0000050c0000050d0000058c0000060c"));
+
+ verifyPosition(decoder, binary(
+ "44C20146B710C158DA009500B09F7700C054CA0EA454CA0EA403BE0BF6015D706B070000142A600000000000000002434946010801000754CA0EA4000000000000008400000000000000000000000000000000300000FE00FE0000000000000000000000000000000000000000000000000000000000000000000040502035000000000000020D0000030D0000040C0000040D0000050C0000050D0000058C0000060C"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AppelloProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AppelloProtocolDecoderTest.java
new file mode 100644
index 000000000..ac0858e82
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AppelloProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AppelloProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AppelloProtocolDecoder decoder = new AppelloProtocolDecoder(null);
+
+ verifyAttributes(decoder, text(
+ "FOLLOWIT,867273024233699,UTCTIME,0.000000,0.000000,0,0,0,0,L,262:3:c703:4bf8:64:255|262:3:c703:9a18:45|262:3:c703:e838:33|262:3:c703:7190:20|262:3:c704:d896:17|,02,44,,31,,4.20,0,0,86/44/24,,,,26,02264DFF6E16:69|4C09D408554E:79|4C09D408554F:79|E0885DE705E5:81|E2885DE705E7:81|246511122CCC:83|,34925"));
+
+ verifyAttributes(decoder, text(
+ "FOLLOWIT,867273024233699,UTCTIME,0.000000,0.000000,0,0,0,0,L,262:3:c703:4bf8:64:1|262:3:c703:9a18:44|262:3:c703:e838:33|262:3:c703:7190:21|262:3:c704:d896:18|262:3:c703:71a6:13|262:3:c703:253d:13|,02,44,,22,,4.20,0,0,86/44/24,,,,30,02264DFF6E16:67|E0885DE705E5:87|B4A5EF284B94:88|E2885DE705E7:85|4C09D408554E:78|3481C4D71B13:43|,24033"));
+
+ verifyAttributes(decoder, text(
+ "FOLLOWIT,860719028336968,UTCTIME,-12.112660,-77.045189,0,0,3,-0,L,716,10,049C,2A47,23,,4.22,,53,999/00/00,,,,,,59826,"));
+
+ verifyPosition(decoder, text(
+ "FOLLOWIT,860719028336968,160211221959,-12.112660,-77.045258,1,0,6,116,F,716,17,4E85,050C,29,,4.22,,39,999/00/00,,,,,,46206,"));
+
+ verifyPosition(decoder, text(
+ "FOLLOWIT,359586019278139,130809160321,22.340218,114.030737,60,120,05,152,F,460,01,2533,720B,31,out,3.90,1,192,20/00/00,12.5,100%,80,45,1CFA68BB754E:60|2CFA68BB754E:100|3CFA68BB754E:100|4CFA68BB754E:100|5CFA68BB754E:100|,46672"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AppletProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AppletProtocolDecoderTest.java
new file mode 100644
index 000000000..ad13c60f6
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AppletProtocolDecoderTest.java
@@ -0,0 +1,27 @@
+package org.traccar.protocol;
+
+import io.netty.handler.codec.http.DefaultHttpHeaders;
+import io.netty.handler.codec.http.HttpMethod;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AppletProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AppletProtocolDecoder decoder = new AppletProtocolDecoder(null);
+
+ DefaultHttpHeaders headers = new DefaultHttpHeaders();
+
+ headers.add("HOST", "192.168.0.1:8080");
+ headers.add("X-Admin-Protocol", "globalplatform-remote-admin/1.0");
+ headers.add("X-Admin-From", "8943170080001406197F");
+ headers.add("User-Agent", "oma-scws-admin-agent/1.1");
+ headers.add("From", "8943170080001406197F");
+
+ verifyNull(decoder, request(HttpMethod.POST, "/pli?=", headers));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AquilaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AquilaProtocolDecoderTest.java
new file mode 100644
index 000000000..793b2c646
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AquilaProtocolDecoderTest.java
@@ -0,0 +1,79 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AquilaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecodeA() throws Exception {
+
+ AquilaProtocolDecoder decoder = new AquilaProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1ZF,170215089,20,18.462809,73.824188,170613182744,A,01,123456,*37"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1ZF,170215089,1,18.462809,73.824188,170613182744,A,19,0,0,256,4,4.860000,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,259,3731,*37"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1ZF,170222318,101,22.846016,75.949104,170321103506,A,0,0,244991,0,10,0.860000,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,12483,294,*3D"));
+
+ verifyNull(decoder, text(
+ "$$CLIENT_1ZF,170222318,15,2_00AP,70.35.195.185,5089,internet,T1:10 S,T2:1 M,Ad1:9164061023,Ad2:9164061023,TOF:0 S,,OSC:75 KM,OST:0 S,GPS:YES,Ignition:ON,*75"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1ZF,170222318,1,22.836912,75.942215,170321110736,A,11,12,247196,103,10,0.810000,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,13325,306,*36"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1ZF,130329214,1,12.962985,77.576484,140127165433,A,22,0,0,140,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1253,420,1,0,1,0,0,1,P(01:410104000102|05:410521|0C:410C0000|0D:410D65|21:4121161C),D(P0121|B2105),-895,745,-145,300,*26"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1NS,101010119,1,22.845943,75.949059,170202184000,A,27,0,0,120,31141,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,399,3709,0,0,0,0,0,0,P(01:|04:|05:|0B:|0C:|0D:|10:|1C:|21:|23:|30:|31:|1F:|11:|00:|00:|),D(),-89,44,-1062,0,*49"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1DT,151028368,1,19.108438,72.925308,160628154920,A,22,0,0,131,3503,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,*1D"));
+
+ verifyNull(decoder, text(
+ "$$CLIENT_1DT,160319372,1,28.549541,77.249802,160628140743,A,23,0,-65025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,*0D"));
+
+ verifyPosition(decoder, text(
+ "$$SRINI_1MS,141214807,1,12.963515,77.533844,150925161628,A,27,0,8,0,68,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,*43"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1ZF,130329214,1,12.962985,77.576484,140127165433,A,22,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,*26"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1WP,141216511,3,12.963123,77.534012,150908163534,A,31,0,0,0,7,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,*28"));
+
+ verifyPosition(decoder, text(
+ "$$CLIENT_1WP,141216511,3,12.963212,77.533989,150908164041,V,31,0,0,0,8,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,*2A"));
+
+ }
+
+ @Test
+ public void testDecodeB() throws Exception {
+
+ AquilaProtocolDecoder decoder = new AquilaProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$Header,nliven,EMR,861693034634154,NM,09112017155133,A,12.976495,N,77.549713,E,906.0,0.0,23,G,KA01I2000,+919844098440*4B"));
+
+ verifyPosition(decoder, text(
+ "$EPB,iTriangle1,EMR,864495034445822,SP,03082018110730,A,22.829292,N,75.935806,E,543.0,0.0,0,G,KA01G1234,+9164061023*13"));
+
+ verifyPosition(decoder, text(
+ "$Header,iTriangle,1_37T02B0164MAIS_2,NR,1,L,864495034490141,KA01I2000,1,19042018,102926,22.846401,N,75.948952,E,0.0,311,5,578.0,3.80,3.67,AirTel,0,1,12.5,4.3,1,C,14,404,93,0456,16db,29,ebd8,0458,28,3843,18ab,25,072e,18ab,22,35da,0458,0000,00,031181,0.0,0.0,0,()*34"));
+
+ verifyPosition(decoder, text(
+ "$Header,nliven,1_37T02B0164MAIS,BR,6,L,861693034634154,KA01I2000,1,09112017,160702,12.976593,N,77.549782,E,25.1,344,15,911.0,1.04,0.68,Airtel,1,1,11.8,3.8,1,C,24,404,45,61b4,9ad9,31,9adb,61b4,35,ffff,0000,33,ffff,0000,31,ffff,0000,0001,00,000014,0.0,0.1,4,()*1E"));
+
+ verifyPosition(decoder, text(
+ "$Header,iTriangle,1_37T02B0164MAIS_2,NR,1,L,864495034490141,KA01I2000,1,31032018,122247,22.845999,N,75.949005,E,0.0,44,16,545.0,1.19,0.65,AirTel,1,1,12.0,4.3,0,C,13,404,93,0456,16db,27,16dd,0456,22,3843,18ab,19,ebd8,0458,14,072c,18ab,0101,00,003735,0.0,0.0,0,()*48"));
+
+ verifyNull(decoder, text(
+ "$Header,nliven,KA01I2000,861693034634154,1_37T02B0164MAIS,AIS140,12.976545,N,77.549759,E*50"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Ardi01ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Ardi01ProtocolDecoderTest.java
new file mode 100644
index 000000000..8498bb7f9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Ardi01ProtocolDecoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Ardi01ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Ardi01ProtocolDecoder decoder = new Ardi01ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "013227003054776,20141010052719,24.4736042,56.8445807,110,289,40,7,5,78,-1"),
+ position("2014-10-10 05:27:19.000", true, 56.84458, 24.47360));
+
+ verifyPosition(decoder, text(
+ "013227003054776,20141010052719,24.4736042,56.8445807,110,289,40,7,5,78,-1"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ArknavProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ArknavProtocolDecoderTest.java
new file mode 100644
index 000000000..18901d9a6
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ArknavProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ArknavProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ArknavProtocolDecoder decoder = new ArknavProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "358266016278447,05*827,000,L001,V,4821.6584,N,01053.8650,E,000.0,000.0,00.0,08:46:04 17-03-16,9.5A,D7,0,79,0,,,,"),
+ position("2016-03-17 08:46:04.000", false, 48.36097, 10.89775));
+
+ verifyPosition(decoder, text(
+ "123456789012345,05*850,000,L001,A,2459.3640,N,12125.2958,E,000.0,224.8,00.8,07:47:26 09-09-05,9.00,D3,0,C4,1,,,,"));
+
+ verifyPosition(decoder, text(
+ "123456789012345,05*850,000,L001,A,2459.3640,N,12125.2958,E,000.0,224.8,00.8,07:47:26 09-09-05,9.00,D3,0,C4,1,,,00000000,"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ArknavX8ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ArknavX8ProtocolDecoderTest.java
new file mode 100644
index 000000000..dfe1435d1
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ArknavX8ProtocolDecoderTest.java
@@ -0,0 +1,45 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ArknavX8ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ArknavX8ProtocolDecoder decoder = new ArknavX8ProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "351856045213782,241111"));
+
+ verifyPosition(decoder, text(
+ "1G,181213092101,A,0347.0756N,09842.7435E,0.0,183,1.1,11008000"));
+
+ verifyAttributes(decoder, text(
+ "2G,181213092101,08,4084.0,00.04,04.01,000396255.0"));
+
+ verifyNull(decoder, text(
+ "2R,090214235955,00,,00.04,03.76,001892024.9"));
+
+ verifyNull(decoder, text(
+ "351856040005407,240101"));
+
+ verifyPosition(decoder, text(
+ "1R,110509053244,A,2457.9141N,12126.3321E,220.0,315,10.0,00000000"));
+
+ verifyNull(decoder, text(
+ "2R,110509053244,837493,,998372,,,"));
+
+ verifyPosition(decoder, text(
+ "1G,110509053245,A,2457.9141N,12126.3192E,3.1,35,2.0,00000001"));
+
+ verifyPosition(decoder, text(
+ "1G,110509053246,A,2457.9121N,12126.3415E,2.0,288,1.7,00000000"));
+
+ verifyPosition(decoder, text(
+ "1M,110509053247,A,2457.9118N,12126.3522E,1.0,55,2.2,00000000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ArnaviProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ArnaviProtocolDecoderTest.java
new file mode 100644
index 000000000..6b075facc
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ArnaviProtocolDecoderTest.java
@@ -0,0 +1,42 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ArnaviProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ArnaviProtocolDecoder decoder = new ArnaviProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$AV,V4,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,80.0,56.1,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E"));
+
+ verifyNull(decoder, text(
+ "$AV,V3DI,85164,20707,-1,19,0008C56A,000879AC,0C000002,863071013041618,89997077111301204297,*0B"));
+
+ verifyNull(decoder, text(
+ "$AV,V6SD,85164,20708,-1,3,6,37,33,*52"));
+
+ verifyAttributes(decoder, text(
+ "$AV,V4,85164,20709,1148,418,-1,0,1,192,0,0,0,0,0,0,,,000023,0000.0000N,00000.0000E,0.0,0.0,060180,0,0,32767,*4F"));
+
+ verifyNull(decoder, text(
+ "$AV,V3GSMINFO,85164,-1,20450,KMOBILE,1,2,1,23,0,40101,cc3,1,ce19,401,16,65304,5613,72,,SF*7F"));
+
+ verifyAttributes(decoder, text(
+ "$AV,V4,85164,20451,1146,418,-1,1,1,192,0,0,0,0,0,0,,,104340,0000.0000N,00000.0000E,0.0,0.0,060219,11,0,32767,,SF*47"));
+
+ verifyNull(decoder, text(
+ "$AV,V6SD,85164,20452,-1,3,3,5,6769,,SF*5D"));
+
+ verifyPosition(decoder, text(
+ "$AV,V2,32768,12487,2277,203,-1,0,0,193,0,0,1,13,200741,5950.6773N,03029.1043E,0.0,0.0,121012,*6E"));
+
+ verifyPosition(decoder, text(
+ "$AV,V3,999999,12487,2277,203,65534,0,0,193,65535,65535,65535,65535,1,13,200741,5950.6773N,03029.1043E,300.0,360.0,121012,65535,65535,65535,SF*6E"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AstraProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AstraProtocolDecoderTest.java
new file mode 100644
index 000000000..453ec9da5
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AstraProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AstraProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AstraProtocolDecoder decoder = new AstraProtocolDecoder(null);
+
+ verifyPositions(decoder, binary(
+ "4b00700529c0c265976b8202cba9ff00676d864554a9c30000000020073401006436000300030008000000000000a0000100001920c43d00009600428302cba9ff00676d864554aa3e000000002007240100643b000300020008000000000000b0000100001920c43d00009600420f0e"));
+
+ verifyPositions(decoder, binary(
+ "4b00320524c1da58769e6d0322617effe874024453065600a800000100080000643e0000000000000000000000069500e7bb"));
+
+ verifyPositions(decoder, binary(
+ "4b013c02213aec35c501ad031368b8ffcd1ad043e5c4500c79000100003101005c490c001c0009020200020015069600ae03136801ffcd1af143e5c452125e000100003101005c491200090011010000020015068500af0313629effcd1f4b43e5c45d1e46000100003101005c491e00080409040500040015068700b0031359d5ffcd35ad43e5c47b2a3b000001003101005c492a1b1a0d0b0f0b00080015068700b103134984ffcd4b1e43e5c4913354000100003101005c49340b0103090606000f0015067700b203132e1affcd5a5a43e5c4af3348000001003101005c4935070a08000a070017001505f700b30313192cffcd7af143e5c4cd3733000001003101005c4937091206050a0800200015058600b403130debffcda88743e5c4eb2c3e000001003101005c493707030601080600290015058600b377"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/At2000FrameDecoderTest.java b/src/test/java/org/traccar/protocol/At2000FrameDecoderTest.java
new file mode 100644
index 000000000..c5829d588
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/At2000FrameDecoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class At2000FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ At2000FrameDecoder decoder = new At2000FrameDecoder();
+
+ verifyFrame(
+ binary("01012f00000000000000000000000000003335363137333036343430373439320fad981997ae8e031fe10c0ea7641903ca32c0331df467233d2a9cd886fbeef8"),
+ decoder.decode(null, null, binary("01012f00000000000000000000000000003335363137333036343430373439320fad981997ae8e031fe10c0ea7641903ca32c0331df467233d2a9cd886fbeef8")));
+
+ verifyFrame(
+ binary("893f0000000000000000000000000000e048b1a31deba3f5dbe8877f574877e6ed4d022b6611a10d80dfc4c0c11fa8aacf4a9de61528327e2b66843dd9c5d3a7cc9ee1d9c71a34bb482145d88b4fda3e"),
+ decoder.decode(null, null, binary("893f0000000000000000000000000000e048b1a31deba3f5dbe8877f574877e6ed4d022b6611a10d80dfc4c0c11fa8aacf4a9de61528327e2b66843dd9c5d3a7cc9ee1d9c71a34bb482145d88b4fda3e")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/At2000ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/At2000ProtocolDecoderTest.java
new file mode 100644
index 000000000..9e2f180d2
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/At2000ProtocolDecoderTest.java
@@ -0,0 +1,59 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assume.assumeTrue;
+
+public class At2000ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ assumeTrue(Boolean.parseBoolean(System.getenv("CI")));
+
+ At2000ProtocolDecoder decoder;
+
+ decoder = new At2000ProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "01012f00000000000000000000000000003335373435343037313632373539388b57ec3a6ec7e3310a1ceb0a70fd751b8f2e7be6df1d6dcd80129f66fff0ea1c"));
+
+ verifyNull(decoder, binary(
+ "89000000000000000000000000000000"));
+
+ decoder = new At2000ProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "01012f0000000000000000000000000000333537343534303731363036313936ddf189075add9a32d97b54073025963e65849a3a59940d05fd8db655fc84bc6d"));
+
+ verifyPositions(decoder, binary(
+ "893b01000000000000000000000000003b40bcdab6387d829146701d8cb53daaa87b84d24b40cb24fd86da5d3f5f02b0f6f603c43c5a513418a0b2bdcaba603dbe737687cfe9082c57668eb6789d2b029a35aeac6a609558b96de5d7ad37917c902efc878ca9aff474f9d5d2417191285b8d5749bd3ffa86cc99096ce24c1f6ac350ae9adf3d5c788f80b4e3d3dc2dbb8abc1414ea1b52fdb55b2bb8af223ec528245f99d451b715e5774c5397db645d9ae441e645f8dae70230b728e81f51240868712d6f426fd694dbad8026fcf487c268939f04593ad86391cc829b1a1bdac8804ff7507544a69dc0b1b3927d7344e8a5b26fa56825283b3e476330b36d15011e1647ebd9f2ef71844ed32c0dc050457bfbd79160e6d1d8cda00a0927c8957631770e98eb20735aa46b0b18502baf4c45d2623ee51a4320cf3018010e7bbf8bc0dd79eb28e88b727ea67e980b8a91"));
+
+ decoder = new At2000ProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "01012f000000000000000000000000000033353734353430373136303631393637f5441a9862260117858237fe3160388490f0df7d46c09112ee087235a92101"));
+
+ verifyPositions(decoder, binary(
+ "89043203000000000000000000000000d01ff1df1b56ba9185bb741ddc253f3cee093b1f8193100cd95777b5288a6f29d1b343a952f882ce8825679f7e27ad88ed7898bff92f716acadfc3c17fa8c1a6b9d0934e8f042433a183776c06c1acd73efb4b9f19030debb4dceb161fb3e6630757d25c3e995b7cf5f446318dcc1677eb215d1af49f11cd7300598bcdc40cc25466ed2391d836c782e44bc04a332e902b2b34f5597a542af4ca670cdfc18d87ce2a225c3e6f2f32359d4914c6df09aa5ee306c229260d4a56da53f93398bc8a6e77095305ee214cf605de20d3876a993fb810486f75bcd514c12442bf4dc3fbe7963b20d5100b5ecff1c1aef4c4b3736a04e245d50f538327db21d55270b279db5ac5a9658876bae3d9b5026b8975bb2bf4d100b8492760d66ae31f27bf9c525c2d794860eabca9c788b91152dbce79f336daaf6a7a9547bf1dd8e3334c891f4548fd6d112ebf45125c2a8abd3a786ebbcfdd03101b524bbf465f14a9a424305ce7de56ffca85b4657fc8c03e4349c0ca6be64d1cf595ee91f8173678ef2267dae54dd00028450c48d9b74c925af0f245d409d8773238dce5832747587f53a12155869c1d464eb0630f94cf8dceb76aa39995411d4ce7743b1501692425afec498535526067e79f568b7f71ee47d8b4929118d57b13d56cdbfd26582d579dee"));
+
+ decoder = new At2000ProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "01012f0000000000000000000000000000333537343534303731363035353033dd529a1eb5df9f3b6d320b38250e03306692957e8c2127d8e381a717f639b4c9"));
+
+ verifyPositions(decoder, binary(
+ "89898701000000000000000000000000ae99e38f13d44f536769eb4930a6826dfebe5b98a6048941e89b17c9cdcb276be4af7c0d188d07c90d6e94aa9efcb465fe7aeaff4d85caf837483b4e9b32fbbacfbc4e175eebf57a27f552a64fc3419565d2dfbea668511a08d5a526342fad0e93b20c4449ad8defab4a9ac68cf7dad86971eb2cd96810d9d6a9c56e07fd90e4c28cfc53a069b63efe37a0523a69b607a2dc011ba17b177c5332c04be1faeeabed24539b3b790fa8a8610ab3633e0140ed79690fcae9dea43c7daad780d95a511d8f4875e621bcfe7516a03b80eb3c473ffd4bc1eda298dfa7d994a2cfeaa5d24c190d52d72fd90975a2e6f9ed3b95017133952262f91787c46839738a80c333dc53ee4d8afe75315d801efe17bc7309f30cfce64906bf70e6844c835781cbb64b49e9315ca3c2cd39d00a03cc7178a4ebc5df230dcdfd44ec588791d488f96bb6ff4007a753f552bda4d1766632aa3ec5eb38feb23ed6efb8f382a7f22b70adc9cb533c09bf749190c36d63b572c1acfc3a59138d51273835ab13c4689df01e3d2c2dd1829e00aac5c56b5d51e60d6731833f82c7464d88df663ca28a20eedeecb60f3704ae78281838caa116184e414db459768321bbfa1e83ad59fe168eb81f3b41cfe0e39c8aa78cbbe5825620bf053a1cb62e04d4cdf17ca2dc9305d47c"));
+
+ decoder = new At2000ProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "01012f00000000000000000000000000003335363137333036343430373439320fad981997ae8e031fe10c0ea7641903ca32c0331df467233d2a9cd886fbeef8"));
+
+ verifyPositions(decoder, binary(
+ "893f0000000000000000000000000000e048b1a31deba3f5dbe8877f574877e6ed4d022b6611a10d80dfc4c0c11fa8aacf4a9de61528327e2b66843dd9c5d3a7cc9ee1d9c71a34bb482145d88b4fda3e"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AtrackFrameDecoderTest.java b/src/test/java/org/traccar/protocol/AtrackFrameDecoderTest.java
new file mode 100644
index 000000000..3a26bb7a7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AtrackFrameDecoderTest.java
@@ -0,0 +1,39 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AtrackFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AtrackFrameDecoder decoder = new AtrackFrameDecoder();
+
+ verifyFrame(
+ binary("40502c414246342c3532362c3939312c3335363936313037353933313136352c313533343338313635362c313533343338313635392c313533343338313635392c2d38383432393138382c34343237313232352c37302c322c3230303536332c392c312c302c302c302c2c323030302c323030302c1a2c25434925434525434e25475125475325464c254d4c25564e25504425464325454c254554254344254154254d46254d5625425625434d25445425474c25474e254756254c43254d4525524c25525025534125534d255452254941254d502c302c3331303236302c31382c392c302c302c3254314b523332453238433730363138352c302c302c302c35342c383930313236303838313231353234373735392c3235322c36302c3132322c34312c3331303236303838313532343737352c302c687474703a2f2f6d6170732e676f6f676c652e636f6d2f6d6170733f713d34342e3237313232352c2d38382e343239313834201a2c3030393830303442303346343030393830303442303346343030393830303442303346333030393830303442303346343030393830303442303346343030393930303442303346343030393830303442303346343030393830303442303346343030393830303442303346343030393830303442303346331a2c3030343846463130303345381a2c302c3335363936313037353933313136352c302c3938302c31322c302c31382c35302c300d0a"),
+ decoder.decode(null, null, binary("40502c414246342c3532362c3939312c3335363936313037353933313136352c313533343338313635362c313533343338313635392c313533343338313635392c2d38383432393138382c34343237313232352c37302c322c3230303536332c392c312c302c302c302c2c323030302c323030302c1a2c25434925434525434e25475125475325464c254d4c25564e25504425464325454c254554254344254154254d46254d5625425625434d25445425474c25474e254756254c43254d4525524c25525025534125534d255452254941254d502c302c3331303236302c31382c392c302c302c3254314b523332453238433730363138352c302c302c302c35342c383930313236303838313231353234373735392c3235322c36302c3132322c34312c3331303236303838313532343737352c302c687474703a2f2f6d6170732e676f6f676c652e636f6d2f6d6170733f713d34342e3237313232352c2d38382e343239313834201a2c3030393830303442303346343030393830303442303346343030393830303442303346333030393830303442303346343030393830303442303346343030393930303442303346343030393830303442303346343030393830303442303346343030393830303442303346343030393830303442303346331a2c3030343846463130303345381a2c302c3335363936313037353933313136352c302c3938302c31322c302c31382c35302c300d0a")));
+
+ verifyFrame(
+ binary("40502c383732442c3731322c36353232312c3335373239383037303432363439382c313533343731353836322c313533343731353836322c313533343732363437342c2d38383531303939352c34343236303637362c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32392c31302c3331303236302c373838383637342c3134342c31360d0a313533343731353932312c313533343731353932322c313533343732363437342c2d38383531313032332c34343236303636382c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32382c31302c3331303236302c373838383637342c3134342c31360d0a313533343731353938322c313533343731353938322c313533343732363437342c2d38383531313034362c34343236303636382c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32392c392c3331303236302c373838383637342c3134342c31360d0a313533343731363034312c313533343731363034322c313533343732363437342c2d38383531313031312c34343236303636332c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32392c31302c3331303236302c373838383637342c3134342c31360d0a313533343731363130322c313533343731363130322c313533343732363437342c2d38383531303938382c34343236303637362c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32392c31302c3331303236302c373838383637342c3134352c31360d0a"),
+ decoder.decode(null, null, binary("40502c383732442c3731322c36353232312c3335373239383037303432363439382c313533343731353836322c313533343731353836322c313533343732363437342c2d38383531303939352c34343236303637362c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32392c31302c3331303236302c373838383637342c3134342c31360d0a313533343731353932312c313533343731353932322c313533343732363437342c2d38383531313032332c34343236303636382c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32382c31302c3331303236302c373838383637342c3134342c31360d0a313533343731353938322c313533343731353938322c313533343732363437342c2d38383531313034362c34343236303636382c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32392c392c3331303236302c373838383637342c3134342c31360d0a313533343731363034312c313533343731363034322c313533343732363437342c2d38383531313031312c34343236303636332c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32392c31302c3331303236302c373838383637342c3134342c31360d0a313533343731363130322c313533343731363130322c313533343732363437342c2d38383531303938382c34343236303637362c3137362c322c35363832372c362c312c302c302c302c2c323030302c323030302c1a2c25434925475125475325434e254345254d562553412c32392c31302c3331303236302c373838383637342c3134352c31360d0a")));
+
+ verifyFrame(
+ binary("40502c373542332c3132302c37393737392c3335383930313034383039313535342c32303138303431323134323531342c32303138303431323134323531342c32303138303431333030303635352c31363432333338392c34383137383730302c3130382c322c362e352c392c302c302c302c302c302c323030302c323030302c1a0d0a"),
+ decoder.decode(null, null, binary("40502c373542332c3132302c37393737392c3335383930313034383039313535342c32303138303431323134323531342c32303138303431323134323531342c32303138303431333030303635352c31363432333338392c34383137383730302c3130382c322c362e352c392c302c302c302c302c302c323030302c323030302c1a0d0a")));
+
+ verifyFrame(
+ binary("244F4B0D0A"),
+ decoder.decode(null, null, binary("244F4B0D0A")));
+
+ verifyFrame(
+ binary("fe0200014104d8f196820001"),
+ decoder.decode(null, null, binary("fe0200014104d8f196820001")));
+
+ verifyFrame(
+ binary("40501e58003301e000014104d8f19682525ecd5d525ee344525ee35effc88815026ab4d70000020000104403de01000b0000000007d007d000"),
+ decoder.decode(null, null, binary("40501e58003301e000014104d8f19682525ecd5d525ee344525ee35effc88815026ab4d70000020000104403de01000b0000000007d007d000")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AtrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AtrackProtocolDecoderTest.java
new file mode 100644
index 000000000..3a9382086
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AtrackProtocolDecoderTest.java
@@ -0,0 +1,99 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AtrackProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AtrackProtocolDecoder decoder = new AtrackProtocolDecoder(null);
+
+ verifyPositions(decoder, buffer(
+ "@P,3A34,146,41431,353816057242284,20180622015809,20180622015809,20180622015809,9720689,4014230,61,2,0,20,1,0,0,0,0,2000,2000,12160,42,624,002,20009,20014,\r\n"));
+
+ verifyPositions(decoder, buffer(
+ "@P,1126,121,104547,358901048091554,20180412143513,20180412143514,20180413060000,16423389,48178700,108,2,6.5,9,0,0,0,0,0,2000,2000,\r\n"));
+
+ verifyPositions(decoder, buffer(
+ "@P,434E,124,104655,358901048091554,20180412143706,20180412143706,20180413060107,16423389,48178700,108,121,6.5,10,0,0,0,0,0,2000,2000,\r\n"));
+
+ verifyPositions(decoder, binary(
+ "4050b5ed004a2523000310c83713f8c05a88b43e5a88b43f5a88b43f021e0ad5fffdc0a800f3020003059100080000000000000007d007d046554c533a463d3230393120743d3137204e3d3039303100"));
+
+ verifyAttributes(decoder, buffer(
+ "$INFO=358683066267395,AX7,Rev.0.61 Build.1624,358683066267395,466924131626767,89886920041316267670,144,0,9,1,12,1,0\r\n"));
+
+ decoder.setLongDate(true);
+
+ verifyPositions(decoder, binary(
+ "0203b494003c00eb00014104d8dd3a3e07de011b0b1f0307de011b0b1f0307de011b0b1f0300307f28030574d30000020000000600160100020000000007d007d000"));
+
+ decoder.setLongDate(false);
+
+ decoder.setCustom(true);
+
+ verifyPositions(decoder, buffer(
+ "@P,9493,402,143,356961075931165,1546830150,1546830151,1546830151,-88429209,44271154,54,10,0,10,1,0,0,0,1858AE010000,2000,2000,\u001A,%CI%FL%ML%VN%PD%FC%EL%ET%AT%MF%MV%BV%DT%GN%GV%ME%RL%RP%SA%SM%TR%IA%MP,0,0,2T1KR32E28C706185,0,1,0,7,251,89,118,41,0,00A5001A040800A5001A040B00A5001A040C00A5001A040900A4001C040D00A50019040900A60019040900A4001B040B00A5001A040900A7001A040E\u001A,008CFE7C03C4\u001A,356961075931165,0,0,12,0,18,5,0\n"));
+
+ verifyPositions(decoder, buffer(
+ "@P,FD34,720,12256,357520076794151,1535445349,1535445354,1535500603,106784149,-6283086,105,2,138,0,3,0,0,0,,2000,2000,,%CI%TR%MV%BV%AT%SA%ET%GQ%GS%PC%RP%OD%AV1%XS%VS,0,0,0,0,0,0,0,0,1011677,0,138,0,0,0\r\n",
+ "1535445376,1535445374,1535500603,106783763,-6282981,105,101,138,6,2,0,0,0,,2000,2000,,%CI%TR%MV%BV%AT%SA%ET%GQ%GS%PC%RP%OD%AV1%XS%VS,0,141,41,60,12,0,0,7,1011677,0,138,0,0,0\r\n",
+ "1535445380,1535445378,1535500603,106783763,-6282981,105,103,138,6,2,0,0,0,,2000,2000,,%CI%TR%MV%BV%AT%SA%ET%GQ%GS%PC%RP%OD%AV1%XS%VS,0,135,41,61,12,0,0,9,1011677,0,138,0,0,0\r\n",
+ "1535445415,1535445415,1535500603,106783763,-6282981,105,2,138,7,2,0,0,0,,2000,2000,,%CI%TR%MV%BV%AT%SA%ET%GQ%GS%PC%RP%OD%AV1%XS%VS,0,135,41,61,12,0,21,10,1011677,0,138,0,0,0\r\n"));
+
+ verifyPositions(decoder, buffer(
+ "@P,0EBB,687,1917,357298070426498,1534718280,1534718279,1534739774,-88643875,44210148,270,2,57128,6,1,130,0,0,,2000,2000,,%CI%GQ%GS%CN%CE%MV%SA,5,10,310260,7888593,137,16\r\n",
+ "1534718283,1534718283,1534739774,-88645243,44210145,269,2,57129,6,1,129,0,0,,2000,2000,,%CI%GQ%GS%CN%CE%MV%SA,5,10,310260,7888593,137,16\r\n",
+ "1534718286,1534718285,1534739774,-88646581,44210136,269,2,57130,6,1,127,0,0,,2000,2000,,%CI%GQ%GS%CN%CE%MV%SA,99,10,0,0,137,16\r\n",
+ "1534718289,1534718288,1534739774,-88647911,44210123,269,2,57131,6,1,127,0,0,,2000,2000,,%CI%GQ%GS%CN%CE%MV%SA,99,10,0,0,137,16\r\n",
+ "1534718292,1534718291,1534739774,-88649229,44210111,269,2,57132,6,1,124,0,0,,2000,2000,,%CI%GQ%GS%CN%CE%MV%SA,99,10,0,0,136,16\r\n"));
+
+ verifyPositions(decoder, binary(
+ "4050b63b02c401af000144a77a21281d5b79d8ef5b79d8ef5b79d8f0fab84831029f35580056020003144d00080100130000000007d007d00025434925434525434e25475125475325464c254d4c25564e25504425464325454c254554254344254154254d46254d5625425625434d25445425474c25474e254756254c43254d4525524c25525025534125534d255452254941254d5000000000000004bbf41f0900003254314b5233324532384337303631383500000000000053005f3839303132363038383132313532343737353900000000fd078e0085002900011a2e3da1882700687474703a2f2f6d6170732e676f6f676c652e636f6d2f6d6170733f713d34332e3938383331322c2d38382e35383631383920000013ff4e04190023ff13041100a3ffdc0402009affde03fc00a4ffe3040c0093ffab03ee004dffbb04130012ff7a04180010ff6e04100037ff4d0402ffd8000c04140000000144a77a21281d0009470c00131b2b005b79d8f05b79d8f05b79d8f0fab8488e029f356f0043020003144d00080100170000000007d007d00025434925434525434e25475125475325464c254d4c25564e25504425464325454c254554254344254154254d46254d5625425625434d25445425474c25474e254756254c43254d4525524c25525025534125534d255452254941254d5000000000000004bbf41f0900003254314b5233324532384337303631383500000000000052005f3839303132363038383132313532343737353900000000fd09190085002900011a2e3da1882700687474703a2f2f6d6170732e676f6f676c652e636f6d2f6d6170733f713d34332e3938383333352c2d38382e35383630393820000013ff4e04190023ff1304110017ff0c0424000cff30041a00a4ffe3040c0093ffab03ee004dffbb04130012ff7a04180010ff6e04100037ff4d0402ffd8000c04140000000144a77a21281d0009470c00171c2b00"));
+
+ verifyPositions(decoder, binary(
+ "405ad77c01670410000144a77a21281d5b74d2335b74d2335b74d233fabaf3bc02a38d3d010c0200030f8e000701001a0000000007d007d00025434925434525434e25475125475325464c254d4c25564e25504425464325454c254554254344254154254d46254d5625425625434d25445425474c25474e254756254c43254d4525524c25525025534125534d255452254941254d5000000000000004bbf41c0900003254314b523332453238433730363138350000000000004800543839303132363038383132313532343737353900000000ec06a50089002900011a2e3da1882700687474703a2f2f6d6170732e676f6f676c652e636f6d2f6d6170733f713d34342e3237323935372c2d38382e34313132303120000075ff4903fb006fff63040a004dff5d04080030ffa10407003b001304060026000503f9001e002504020078ff6204000073ff7d03f9007aff6903f3ffc0001804040000000144a77a21281d00073f0c001a182400"));
+
+ verifyPositions(decoder, buffer(
+ "@P,6254,235,989,356961075931165,1534381563,1534381564,1534381564,-88429188,44271225,70,2,200563,8,1,0,0,0,,2000,2000,,%CI%CE%CN%GQ%GS%FL%ML%VN%PD%FC%EL%ET%CD%AT%MF%MV,0,310260,18,9,0,0,2T1KR32E28C706185,0,0,0,54,8901260881215247759,252,489,123"));
+
+ verifyPositions(decoder, buffer(
+ "@P,27A6,663,707,356961075931165,1534211298,1534211297,1534211437,-88429190,44271135,288,2,200235,8,1,0,0,0,,2000,2000,,%CI%CE%CN%GQ%GS%FL%ML%VN%PD%FC%EL%ET%CD%AT%MF%MV,0,310260,17,9,0,0,2T1KR32E28C706185,0,0,0,80,8901260881215247759,251,59,124\r\n",
+ "1534211353,1534211357,1534211437,-88429190,44271135,288,2,200235,7,1,0,0,0,,2000,2000,,%CI%CE%CN%GQ%GS%FL%ML%VN%PD%FC%EL%ET%CD%AT%MF%MV,0,310260,17,2,0,0,2T1KR32E28C706185,0,0,0,79,8901260881215247759,251,60,124\r\n",
+ "1534211417,1534211417,1534211437,-88429190,44271135,288,2,200235,7,1,0,0,0,,2000,2000,,%CI%CE%CN%GQ%GS%FL%ML%VN%PD%FC%EL%ET%CD%AT%MF%MV,0,310260,17,2,0,0,2T1KR32E28C706185,0,0,0,78,8901260881215247759,251,56,124\r\n"));
+
+ verifyPositions(decoder, buffer(
+ "@P,CA4B,122,1,358683064932578,1533633976,1533633975,1533633975,121562641,25082649,72,0,1638,15,0,0,1,0,,2000,2000,,%CI%MV%BV,143,0\r\n"));
+
+ verifyPositions(decoder, binary(
+ "405025e30096eb730001452efaf6a7d6562fe4f8562fe4f7562fe52c02a006d902273f810064650000e0f5000a0100000000000007d007d000254349255341254d5625425625475125415400090083002a1a000001a8562fe4f8562fe4f7562fe52c02a006d902273f810064020000e0f5000a0100000000000007d007d000254349255341254d5625425625475125415400090083002a1a000001a8"));
+
+ decoder.setCustom(false);
+
+ verifyNull(decoder, binary(
+ "fe0200014104d8f196820001"));
+
+ verifyPositions(decoder, binary(
+ "40503835003300070001441c3d8ed1c400000000000000c9000000c900000000000000000000020000000003de0100000000000007d007d000"),
+ position("1970-01-01 00:00:00.000", true, 0.00000, 0.00000));
+
+ verifyPositions(decoder, binary(
+ "4050993f005c000200014104d8f19682525666c252568c3c52568c63ffc8338402698885000002000009cf03de0100000000000007d007d000525666c252568c5a52568c63ffc8338402698885000002000009cf03de0100000000000007d007d000"));
+
+ verifyPositions(decoder, binary(
+ "40501e58003301e000014104d8f19682525ecd5d525ee344525ee35effc88815026ab4d70000020000104403de01000b0000000007d007d000"));
+
+ verifyPositions(decoder, binary(
+ "40501e58003301e000014104d8f19682525ecd5d525ee344525ee35effc88815026ab4d70000020000104403de01000b0000000007d007d000000000000000"));
+
+ verifyAttributes(decoder, buffer(
+ "$OK\r\n"));
+
+ verifyAttributes(decoder, buffer(
+ "$ERROR=101\r\n"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AuroProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AuroProtocolDecoderTest.java
new file mode 100644
index 000000000..aeea48967
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AuroProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AuroProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AuroProtocolDecoder decoder = new AuroProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "M0028T0000816398975I357325031465123E00001W*****110620150437000068DA#RD01DA240000000001+100408425+013756121100620152137231112240330004400"));
+
+ verifyPosition(decoder, text(
+ "M0029T0000816398975I357325031465123E00001W*****110620150439000068DA#RD01DA240000000001+100407886+013755936100620152138221952123100003400"));
+
+ verifyPosition(decoder, text(
+ "M0030T0000816398975I357325031465123E00001W*****110620150441000068DA#RD01DA240000000000+100408391+013756125100620152140102362238320034400"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AustinNbProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AustinNbProtocolDecoderTest.java
new file mode 100644
index 000000000..fa8f3a071
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AustinNbProtocolDecoderTest.java
@@ -0,0 +1,33 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AustinNbProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AustinNbProtocolDecoder decoder = new AustinNbProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "48666666666;2017-01-01 16:31:01;52,1133308410645;21,1000003814697;310;120;2292;1;ORANGE"));
+
+ verifyPosition(decoder, text(
+ "48666666666;2017-01-01 16:55:00;52,1636123657227;21,0827789306641;0;90;4000;0;ORANGE"));
+
+ verifyPosition(decoder, text(
+ "48666666666;2017-01-01 17:32:01;52,1711120605469;21,0866680145264;70;90;1199;0;ORANGE"));
+
+ verifyPosition(decoder, text(
+ "48601601601;2017-01-01 16:31:01;52,1133308410645;21,1000003814697;310;360;2292;1;ORANGE"));
+
+ verifyPosition(decoder, text(
+ "48601601601;2017-01-01 16:55:00;52,1636123657227;21,0827789306641;0;360;4000;0;ORANGE"));
+
+ verifyPosition(decoder, text(
+ "48601601601;2017-01-01 17:32:01;52,1711120605469;21,0866680145264;70;360;1199;0;ORANGE"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AutoFonProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AutoFonProtocolDecoderTest.java
new file mode 100644
index 000000000..9e17b437f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AutoFonProtocolDecoderTest.java
@@ -0,0 +1,41 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+
+public class AutoFonProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AutoFonProtocolDecoder decoder = new AutoFonProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "10556103592310314825728F"));
+
+ verifyPosition(decoder, binary(
+ "02080000251848470afa010262daa690013aa4046da83745f8812560df010001126a"));
+
+ verifyPosition(decoder, binary(
+ "111E00000000000000000100007101010B0C020302010B0C0005A053FFFFFFFF02010B0C00276047FFFFFFFF1F5600FA000176F218C7850C0B0B0C203A033DBD46035783EF009E00320014FFFF45"));
+
+ //verifyPosition(decoder, binary(
+ // "12060000007501010B0C00089CFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000003E7FFFF02007601010B0C00269CFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000003E7FFFF4A007601010B0C01089CFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000003E7FFFF04007501010B0C01269CFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000003E7FFFF80007601010B0C02089CFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000003E7FFFFA6007501010B0C02231F5600FA000176F218C70000000000000000000000000000000000000003E7FFFF9629"));
+
+ verifyNull(decoder, binary(
+ "41035151305289931441139602662095148807"));
+
+ verifyNull(decoder, binary(
+ "41032125656985547543619173484002123481"));
+
+ verifyPosition(decoder, binary(
+ "023E00001E004D411EFA01772F185285009C48041F1E366C2961380F26B10B00911C"),
+ position("2010-01-27 04:00:08.000", true, 54.73838, 56.10343));
+
+ verifyPosition(decoder, binary(
+ "023E00001E004D411EFA01772F185285009C48041F1E366C2961380F26B10B00911C"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AutoGradeProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AutoGradeProtocolDecoderTest.java
new file mode 100644
index 000000000..f71fcd8eb
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AutoGradeProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AutoGradeProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AutoGradeProtocolDecoder decoder = new AutoGradeProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "(000000001637868324027912356171116A2250.7611N07556.9425E000.9024427197.36\u008eA0000B0000C0000D0000E0000K0000L0000M0000N0000O0000)"));
+
+ verifyPosition(decoder, text(
+ "(000000007322865733022629240170415A1001.1971N07618.1375E0.000145312128.59?A0024B0024C0000D0000E0000K0000L0000M0000N0000O0000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AutoTrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AutoTrackProtocolDecoderTest.java
new file mode 100644
index 000000000..5daafcc40
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AutoTrackProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AutoTrackProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AutoTrackProtocolDecoder decoder = new AutoTrackProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "f1f1f1f1330c00201007090006de7200000000daa3"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/AvemaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/AvemaProtocolDecoderTest.java
new file mode 100644
index 000000000..d3be0b6d6
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/AvemaProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class AvemaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ AvemaProtocolDecoder decoder = new AvemaProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "8,20180927150956,19.154864,49.124862,7,56,0,12,3,0.0,0,0.02,14.01,0,0,26,0,219-2,65534,10255884,0.01"));
+
+ verifyPosition(decoder, text(
+ "1130048939,20120224000129,121.447487,25.168025,0,0,0,0,3,0.0,1,0.02V,14.88V,0,1,24,4,46608,F8BC,F9AD,CID0000028"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Avl301ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Avl301ProtocolDecoderTest.java
new file mode 100644
index 000000000..0972e3fd4
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Avl301ProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+
+public class Avl301ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Avl301ProtocolDecoder decoder = new Avl301ProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "244c0f086058500087335500010d0a"));
+
+ verifyNull(decoder, binary(
+ "24480d1001c3065c0d00010d0a"));
+
+ verifyPosition(decoder, binary(
+ "24242c0f041710001d0e060146944904ff4ac40000148f0651044b001a081001be06590daa00000108a30d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/BceProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/BceProtocolDecoderTest.java
new file mode 100644
index 000000000..400ba7e12
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/BceProtocolDecoderTest.java
@@ -0,0 +1,39 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class BceProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ BceProtocolDecoder decoder = new BceProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "3ab90b71bc1503000300c10bff11"));
+
+ verifyPositions(decoder, binary(
+ "789622d1cb1303003401a53365b70f4a9babc0ffd700c04400f0b6c741e63933428f1c431c015468de43f18221341b007e0ae20001430a698f003f008d000000000031f85900000000f0831c018400000000000000000000000000000000000209000000000000000000000000000000030065f70f4a9babc0ffd700c0440069bcc741e73733427f1c431a01a9378343f1829c391b00a80be2000170056da7003e007c000000000031c04e00000000f0831c01810000000000000000000000000000000000060100000000000000000000000000000003006537104a9babc0ffd700c0440051c1c74129363342721c421801e4809543f18210341b00710ae2000170056da7003e0072000000000031c04800000000b8841c017e00000000000000000000000000000000000306000000000000000000000000000000030069"));
+
+ verifyPositions(decoder, binary(
+ "be76619c834601004200a0003fd769c568ffc3db0079161d420683a9414918b1150000000000d102660167040000000000009f06357f0000a401042ea415e10232000000000000000000000051"));
+
+ verifyPositions(decoder, binary(
+ "be76619c834601004200a0003ff76cc568ffc3db00bd151d423c8ca9410a18af150000000000d1023a0160040000000000009f06427f0000a401042ea416e1003e00000000000000000000009a"));
+
+ verifyPositions(decoder, binary(
+ "be76619c834601004202a5863f57f8b868ffc3db0001712642b70b9d41221946200246d23342d1023e016404000000000000a0065a7f0000a4010496f277e3064300000000000000000000003f97f8b868ffc3db0074712642ae0a9d412919452102fff19042d102a4026304000000000000a006487f0000a4010496f277e3064300000000000000000000003fb7f8b868ffc3db00c6712642000a9d413019442002a6074542d102300165040000000000009f064f7f0000a4010496f277e3064300000000000000000000003fd7f8b868ffc3db002872264245099d413518421f02bea35e42d1021e0164040000000000009f06377f0000a4010496f277e3064300000000000000000000003fe7f8b868ffc3db0061722642e3089d413a28421f02a05ff641d102580163040000000000009f06577f0000a4010496f277e3064300000000000000000000003f17f9b868ffc3db0021732642a3079d414119411d02d69fcc42d102440165040000000000009f06437f0000a4010496f277e3064300000000000000000000003f37f9b868ffc3db00ae732642b4069d414628421b02e0629742d1024c0167040000000000009f06557f0000a4010496f277e3064300000000000000000000003f57f9b868ffc3db0044742642ae059d414c28421a027540a342d102860163040000000000009f065b7f0000a4010496f277e3064300000000000000000000003f97f9b868ffc3db007275264256039d4153284417029e1f2f43d1024a016704000000000000a0064e7f0000a4010496f277e306430000000000000000000000db"));
+
+ verifyPositions(decoder, binary(
+ "2d41abfa2e4501004e02a5a0068609f96a009106260af96a00a006260af96a009106960af96a00a306a60af96a008f06b60af96a009106960cf96a00a03e0715f96affc300804000e6a23a4230ccc441001f47850200000000a0000000bd6542651a110d004b1000000000a401045a56bf4d02480000000000000000061623f96a00a0062623f96a00913ea728f96affc300804000e6a23a4230ccc441001f7f850200000000a0000000bd6542651a110d004a1000000000a401045a56bf4d02480000000000000000069639f96a00a006a639f96a00913e373cf96affc300804000e6a23a4230ccc441001f7f850200000000a0000000ad6534651a110d004a1000000000a401045a56bf4d024800000000000000003ed74ff96affc300804000e6a23a4230ccc441001f7f850200000000a0000000ad6534651a111b004a1000000000a401045a56bf4d01480000000000000000061650f96a00a0062650f96a00913e6763f96affc300804000e6a23a4230ccc441001f7f850200000000a0000000ad6534651a110d004a1000000000a401045a56bf4d01480000000000000000069666f96a00a006a666f96a00913e0777f96affc300804000e6a23a4230ccc441001f7f850200000000a0000000ad6534651a110d004a1000000000a401045a56bf4d0148000000000000000006067df96a00a006167df96a0091063687f96a00a3064687f96a008f065687f96a0091063689f96a00a03e978af96affc300804000e6a23a4230ccc441001f87850200000000a0000000ad6527651a110d004a1000000000a401045a56bf4d024800000000000000000e"));
+
+ verifyPositions(decoder, binary(
+ "be76619c834601003302a5e8327764726bff432fc52a420e2c93410028afd2070000000080024a0005040000000000008e06547f0000a401043cf21f390e54328764726bff432fc52a420e2c93410028afd2070000000080024c0005040000000000008e064f7f0000a401043cf21f390e54329764726bff432fc52a420e2c93410028afd2070000000080024e0002040000000000008d064f7f0000a401043cf21f390e5432a764726bff432fc52a420e2c93410028afd2070000000080024e0004040000000000008e06587f0000a401043cf21f390e5432b764726bff432fc52a420e2c93410028afd207000000008002460005040000000000008e06557f0000a401043cf21f390e5432c764726bff432fc52a420e2c93410028afd2070000000080024e0004040000000000008e06347f0000a401043cf21f390e5432d764726bff432fc52a420e2c93410028afd2070000000080024e0002040000000000008e06547f0000a401043cf21f390e5432e764726bff432fc52a420e2c93410028afd207000000008002540002040000000000008e06477f0000a401043cf21f390e5432f764726bff432fc52a420e2c93410028afd207000000008002540004040000000000008d064f7f0000a401043cf21f390e54320765726bff432fc52a420e2c93410028afd207000000008002540004040000000000008e064d7f0000a401043cf21f390e54321765726bff432fc52a420e2c93410028afd207000000008002540004040000000000008e06467f0000a401043cf21f390e544200a0003f3743c96bffc3db0060c81c42d885ab41002aaf060000000000d102380167040000000000008a064f7f0000a4010412a46b330033000000000000000000000025"));
+
+ verifyPositions(decoder, binary(
+ "ca07629c834601002702a58f3c278ff96a0bc000a0c00140bc3a42508bc541002a70a905000000009000c101a40103d904440e003000000000000000000000000000000000000001013c878ff96a0bc000a0c00140bc3a42508bc541002970a905000000009000c301a40103d904440e003000000000000000000000000000000000000001013cb7d2f96a0bc000a0c00124bc3a426b8fc5410428000404000000009000c401a40103d904440e003500000000000000000000000000000000000001013cc7d2f96a0bc000a0c00124bc3a426b8fc5410428000404000000009000c301a40103d904440e003500000000000000000000000000000000000001013cd7f2f96a0bc000a0c00114bc3a42a48fc5410029027e03000000009000c301a40103d904440e003000000000000000000000000000000000000001013c670dfa6a0bc000a0c001f1bb3a42418dc541002a484904000000009000c001a40103d904440e003a00000000000000000000000000000000000001013c770dfa6a0bc000a0c001f1bb3a42418dc5410028484904000000009000bf01a40103d904440e003a00000000000000000000000000000000000001013c470efa6a0bc000a0c001f1bb3a42418dc5410029484904000000009000bf01a40103d904440e003a00000000000000000000000000000000000001013c5711fa6a0bc000a0c001f1bb3a42418dc5410029484904000000009000c101a40103d904440e003000000000000000000000000000000000000001013f00a0003cc795866b0bc000a0c00144bc3a423a90c541003697cb03000000008000cf01a40103d9040d0f0030000000000000000000000000000000000000010100"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/BceProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/BceProtocolEncoderTest.java
new file mode 100644
index 000000000..bdcc1f9e8
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/BceProtocolEncoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class BceProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ BceProtocolEncoder encoder = new BceProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_OUTPUT_CONTROL);
+ command.set(Command.KEY_INDEX, 1);
+ command.set(Command.KEY_DATA, "1");
+
+ verifyCommand(encoder, command, binary("79df0d86487000000600410aff00550048"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/BlackKiteProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/BlackKiteProtocolDecoderTest.java
new file mode 100644
index 000000000..9a24ece1f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/BlackKiteProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class BlackKiteProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ BlackKiteProtocolDecoder decoder = new BlackKiteProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "01150003313131313131313131313131313131209836055605BA"));
+
+ verifyPositions(decoder, binary(
+ "0136000331313131313131313131313131313120523905563000010000000100000033000000003400004000004500004600005000005100009F76"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/BoxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/BoxProtocolDecoderTest.java
new file mode 100644
index 000000000..d661a10f2
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/BoxProtocolDecoderTest.java
@@ -0,0 +1,67 @@
+package org.traccar.protocol;
+
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class BoxProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ BoxProtocolDecoder decoder = new BoxProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "H,BT,358281002435893,081028142432,F5813D19,6D6E6DC2"));
+
+ verifyNull(decoder, text(
+ "H,BT,N878123,080415081234,D63E6DD9,6D6E6DC2,8944100300825505377"));
+
+ verifyPosition(decoder, text(
+ "L,190227043304,G,25.68773,48.59788,71,53,261.42,1,23;A,0.03;D,0.06;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,081028142429,G,52.51084,-1.70849,0,170,0,1,0"));
+
+ verifyPosition(decoder, text(
+ "L,081028142432,G,52.51081,-1.70849,0,203,0,16,0"));
+
+ verifyNull(decoder, text(
+ "L,080528112501,AI1,145.56"));
+
+ verifyNull(decoder, text(
+ "E,1"));
+
+ verifyPosition(decoder, text(
+ "L,150728150130,G,24.68312,46.67526,0,140,0,3,20;A,0;D,0;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728155815,G,24.68311,46.67528,0,140,0,6,21;A,0;D,0;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728155833,G,24.68311,46.67528,11,140,0,52,23;A,0.79;D,0;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728155934,G,24.68396,46.67489,0,282,0.12,1,21;A,1.27;D,1.23;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728160033,G,24.68414,46.67485,0,282,0.12,1,21;A,0;D,0;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728160133,G,24.68388,46.675,0,282,0.12,1,21;A,0;D,0;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728160233,G,24.68377,46.67501,0,282,0.12,1,21;A,0;D,0;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728160333,G,24.684,46.67488,0,282,0.12,1,21;A,0;D,0;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728155855,G,24.68413,46.67482,0,282,0.14,53,21;A,0;D,0;I,0"));
+
+ verifyPosition(decoder, text(
+ "L,150728160400,G,24.68413,46.67482,0,282,0.14,7,20;A,0;D,0;I,0;END,25,326,150728155814"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/C2stekProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/C2stekProtocolDecoderTest.java
new file mode 100644
index 000000000..9f841fb8c
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/C2stekProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class C2stekProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ C2stekProtocolDecoder decoder = new C2stekProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "PA$863083038046613$D#181123#162850#1#+37.92684#+23.75933#0.62#200.1#0.0#3768#000#9#00#sz-w1001#B0907839$AP"));
+
+ verifyPosition(decoder, text(
+ "PA$353990030327618$D#091117#020928#1#22.537222#114.020948#0.00#0.0#42.1#4183#011#1#101#Wsz-wl001#B0101940#C+3.0,-5.0,+2.0$AP"));
+
+ verifyNull(decoder, text(
+ "PA$863083030602124$20$AP"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CalAmpProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CalAmpProtocolDecoderTest.java
new file mode 100644
index 000000000..5ed3f5dc8
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CalAmpProtocolDecoderTest.java
@@ -0,0 +1,54 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class CalAmpProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CalAmpProtocolDecoder decoder = new CalAmpProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "83051633033459010101028afd59ae7c1459ae7c140b06bbce2c01520e0000d916000001b900450900005affa50f091f00260d040000000f24000001b90000000000003714"));
+
+ verifyPosition(decoder, binary(
+ "83092701131797081078220107010200dc583d4d3f583d4d3f19c70502cd1d512d00005f180000008500ec0800101eff980f090100313102000000000000000000"));
+
+ verifyPosition(decoder, binary(
+ "8305133303910501010102004557E5AB2457E3B3E01FD828DBFE9E3465000028C90000004201310704001EFFA12F0B22081BCA05000000000000000F87000E8E2F00EA029E0000082D"));
+
+ verifyPosition(decoder, binary(
+ "8305313301481601010102045557ea2eba57ea2eba1ebf06db005f2e5e0000220c00000000000006200000ff8f000a00000bca06000000000000000f1b000f35ef00ea02900000087000000060"));
+
+ verifyPosition(decoder, binary(
+ "8305454205067001010102008157a9bddc57a96aaa17cdb98fccc1a457000056ac00000000000007250000ff8f000e00082711570000000000ffff101b00003148000010680000000000000000000000050000000000000000000005b0000000000000289600000000000000000000069b00000000000008e400000000000000000000000000000003000000010000070f"));
+
+ verifyPosition(decoder, binary(
+ "83052132052924010101020001575c590300000000000000000000000000000000000000000000002c0000ff8f0000030801010000"));
+
+ verifyPosition(decoder, binary(
+ "830543321494860101010a0080560b5a5e0eadd0291becf3c500f005090f1f3305000003010040c0a600000000000000008b12a102"));
+
+ verifyPosition(decoder, binary(
+ "830543321494860101010a0c215608b6680ead5ada1bed88d300000049801f000500000300003cf33200000000000000008b0ce101"));
+
+ verifyNull(decoder, binary(
+ "830545321041830101010300010000333862000023c301000000004532104183ffffff353816051610691f420040163953294fffffffffffffffff8996604211639032949f4f54413a317c303b302c317c343b302c34004f5441535441543a302c302c302c302c302c222200564255533a342c322e302e302c343533323130343138332c5630312e30332e30312e34302c5630312e30332e30312e33312c2c0056494e2d494e464f3a56494e3d31464d5a5537324539355a4137303032362c4445562d5245474e3d55532c535256522d5245474e3d555300"));
+
+ verifyPosition(decoder, binary(
+ "8308353301059723580f01020102088952d994c352d994c4134fa767c4c482e20000c12700000d29006e1002019affc90f061d00060c0000"));
+
+ verifyPosition(decoder, binary(
+ "8308355233050116134f01020102445652d993e152d993e1124c728cc68f0647000023c00000000000000e02019affc90f071c0015020000"));
+
+ verifyPosition(decoder, binary(
+ "830545420185450101010200075517fb335516c5c40fb1aea4cf4cbf250000000000000000008900260015ffb10f001108110a0000"));
+
+ verifyPosition(decoder, binary(
+ "830543321494750101010A00085492798A0EC4F9E71BDA3B81005600040F1F33050000030000000076000000000000000000000000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CarTrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CarTrackProtocolDecoderTest.java
new file mode 100644
index 000000000..c8db07ee3
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CarTrackProtocolDecoderTest.java
@@ -0,0 +1,32 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class CarTrackProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CarTrackProtocolDecoder decoder = new CarTrackProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "$$020040????????&A0000"));
+
+ verifyPosition(decoder, text(
+ "$$020040????????&A9955&B011939.000,A,4436.3804,N,02606.9434,E,0.00,0.00,190317,,,A*64|0.9|&C0100000000&D01830=?6&E00000001&Y00000000"));
+
+ verifyPosition(decoder, text(
+ "$$2222234???????&A9955&B102904.000,A,2233.0655,N,11404.9440,E,0.00,,030109,,*17|6.3|&C0100000100&D000024?>&E10000000"),
+ position("2009-01-03 10:29:04.000", true, 22.55109, 114.08240));
+
+ verifyPosition(decoder, text(
+ "$$2222234???????&A9955&B102904.000,A,2233.0655,N,11404.9440,E,0.00,,030109,,*17|6.3|&C0100000100&D000024?>&E10000000&Y00100020"));
+
+ verifyPosition(decoder, text(
+ "$$2222234???????&A9955&B102904.000,A,2233.0655,N,11404.9440,E,0.00,,030109,,*17|6.3|&C0100000100&D000024?>&E10000000"));
+
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CarscopProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CarscopProtocolDecoderTest.java
new file mode 100644
index 000000000..412901d90
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CarscopProtocolDecoderTest.java
@@ -0,0 +1,46 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class CarscopProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CarscopProtocolDecoder decoder = new CarscopProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "*170821223045UB00HSO"));
+
+ verifyPosition(decoder, text(
+ "*170821223121UB05ORANGE000731512061825V0000.0000N00000.0000E000.0040331309.62"));
+
+ verifyPosition(decoder, text(
+ "*170724163029UB05ORANGE000000010061825V0000.0000N00000.0000E000.0040331309.62"));
+
+ verifyNull(decoder, text(
+ "*160618233129UB00HSO"));
+
+ verifyNull(decoder, text(
+ "*160618232614UD00232614A5009.1747N01910.3829E0.000160618298.2811000000L000000"));
+
+ verifyNull(decoder, text(
+ "*160618232529UB05CW9999C00000538232529A5009.1747N01910.3829E0.000160618298.2811000000L000000"));
+
+ verifyPosition(decoder, text(
+ "*040331141830UB05123456789012345061825A2934.0133N10627.2544E000.0040331309.6200000000L000000"),
+ position("2004-03-31 06:18:25.000", true, 29.56689, 106.45424));
+
+ verifyPosition(decoder, text(
+ "*040331141830UB04999999984061825A2934.0133N10627.2544E000.0040331309.6200000000L000000"));
+
+ verifyPosition(decoder, text(
+ "*040331141830UA012Hi-jack061825A2934.0133N10627.2544E000.0040331309.6200000000L000000"));
+
+ verifyPosition(decoder, text(
+ "*150817160254UB05CC8011400042499160254A2106.8799S14910.2583E000.0150817158.3511111111L000000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CastelProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CastelProtocolDecoderTest.java
new file mode 100644
index 000000000..27f503b34
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CastelProtocolDecoderTest.java
@@ -0,0 +1,144 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class CastelProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CastelProtocolDecoder decoder = new CastelProtocolDecoder(null);
+
+ verifyAttributes(decoder, binary(
+ "40403a00043231335750323031373030363135360000000000a00200000100000101201100344a474446364545374a4230373632363056ff0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "4040560004323133474c3230313630303033363400000000004002a122a05a5423a05abe0f2a000000000007f1f90014000000040001640011170003001e000505210b210c210d210f2101062b58ef02001a25950d0a"));
+
+ verifyAttributes(decoder, binary(
+ "404057000431303031313132353239393837000000000000004002C1F06952F0F169529C9111000000000069830000470000000400036401014C01030078000505210C210D210F21102101073BE8030064280AEB930D0A"));
+
+ verifyPosition(decoder, binary(
+ "40405f000536303331353030303335313200000000000000004001040212102a2f72b29302a0af8512b40787018e000000000043e4ae000000007ca0f7224d5049503632305f56312e312e30004d5049502d3632302056322e300072140d0a"));
+
+ verifyPosition(decoder, binary(
+ "24245000363137313135313243333133360000000000000040011b011207133ac49a390464514a15000000008e480c00000917000000000000ffafffaf00010000ffff7800ffffffffffffff003c0d0a"));
+
+ verifyPositions(decoder, binary(
+ "40408200033231334c32303137303031313039000000000000100136477b5964477b590400000000000000dc410f000000000204000709207910008304011c07110e110dd41a160714a95a0f00001e058c4944442d3231334c2056312e312e3120323031372d30352d3038004944442d3231334c2056312e312e300000006da10d0a"));
+
+ verifyPositions(decoder, binary(
+ "40408200033231334c323031373030303131370000000000001001000c6759a10d67590a9e1200000000000e3e0000000000020000000e4e791c000004010d0711060515083017086cd1181f000040067d4944442d3231334c2056312e312e3120323031372d30352d3038004944442d3231334c2056312e312e3000000066e30d0a"));
+
+ verifyAttributes(decoder, binary(
+ "404043000432313345503230313630303035383500000000004006a2021d5810031d58ae940400da050000f6040000070000000400076401680000000001001bd20d0a"));
+
+ verifyNull(decoder, binary(
+ "4040d0000432313345503230313630303035383500000000001001831c1c58b1fc1c58ae94040012220000f60400005800000000000763016800008484004944445f3231335730315f532056312e302e37004944445f3231335730315f482056312e302e370032000110021003100410051006100710081009100a100b100c100d100e1011100111021103110411051106110711011202120312041201130213031301160216011701180218011b011c011d011e011f021f031f041f051f061f071f0121022101260127012861780d0a"));
+
+ verifyNull(decoder, binary(
+ "404029000432313345503230313630303035383500000000009001ffffffff0000b4fc1c582b6e0d0a"));
+
+ verifyPositions(decoder, binary(
+ "40406000043231334550323031363030303538350000000000400708000000831c1c58f4fb1c58ae94040012220000f604000058000000200007630168000084c401040b10090c3532db3f07f07f7520090100000101010e00000000c7920d0a"));
+
+ verifyNull(decoder, binary(
+ "404042000432313345503230313630303035383500000000001002831c1c58b7fc1c58ae94040012220000f604000058000000000007630168000084840072a20d0a"));
+
+ verifyNull(decoder, binary(
+ "4040d0000432313345503230313630303035383500000000001001831c1c5805fe1c58ae94040012220000f60400005800000000000763016800008484004944445f3231335730315f532056312e302e37004944445f3231335730315f482056312e302e370032000110021003100410051006100710081009100a100b100c100d100e1011100111021103110411051106110711011202120312041201130213031301160216011701180218011b011c011d011e011f021f031f041f051f061f071f012102210126012701284eb10d0a"));
+
+ verifyAttributes(decoder, binary(
+ "40405700043231334e583230313630303131373700000000004002c458ce572159ce57a9e2020082030000500c00000f0000000400036401240e0403023c000505210c210d210f21102101075b14030121330269430d0a"));
+
+ verifyNull(decoder, binary(
+ "40407800043231334e583230313630303131373700000000004004fa52ce574b53ce57cad1020041020000050c00000d0000000400036401240b0503001b042105210c210d210f211021112113211c211f212121232124212c212d213021312133213e2141214221452149214a214c214f215021384e0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "4040a600043231334e583230313630303131373700000000004005fa52ce575053ce57cad102006b020000050c00000d0000000400036401240b050300001b042105210c210d210f211021112113211c211f212121232124212c212d213021312133213e2141214221452149214a214c214f215021015bd604301f500600000653000000bc0bffff78250000ff2d98642401000f8080e038000f0f0000000000000077b10d0a"));
+
+ verifyAttributes(decoder, binary(
+ "40404300043231334e583230313630303131373700000000004006fa52ce574e53ce57cad1020053020000050c00000d0000000400036401240b0503000000feec0d0a"));
+
+ verifyPosition(decoder, binary(
+ "40403600043231334e583230313630303033343600000000004009ad31a457050810061a35b29bf80ae6da83180300320bbe32580d0a40403600043231334e583230313630303033343600000000004009ad31a457050810061a35b29bf80ae6da83180300320bbe32580d0a"));
+
+ verifyNull(decoder, binary(
+ "4040d400043535333133350000000000000000000000000000100196d499574bd899570000000000000000010000000000000000000000002410000000004944445f3231334730325f532056322e332e345f4e004944445f3231334730325f482056322e332e345f4e0032000110021003100410051006100710081009100a100b100c100d100e1011100111021103110411051106110711011202120312041201130213031301160216011701180218011b011c011d011e011f021f031f041f051f061f071f012102210126012701285b410d0a"));
+
+ verifyPosition(decoder, binary(
+ "24243f00676e6768656636313031313132393030313734002001840d0000d2deb556020602100b35360456cf09e6ebac0200000000030000000001abc10d0a"));
+
+ verifyPosition(decoder, binary(
+ "24243f00676e6768656636313031313132393030313734002001840d000000dfb556020602100b36298256cf0956ebac020000990c7f0000000001b4830d0a"));
+
+ verifyPositions(decoder, binary(
+ "4040590004313030303030303030303800000000000000000040010072f53f56c25240560000000078b00900000000009c3100000000030100011900030001090b0f080106c04fe40b4037310c0060e001ff018d01e05e0d0a"));
+
+ verifyPositions(decoder, binary(
+ "40405900043231334e5832303135303030303336000000000040010073dd735600df7356b9220000270b000000000000000000000400000000240e03000201120c0f0a19050c1e5808ca35530dd902540d9c010000e5300d0a"));
+
+ verifyPositions(decoder, binary(
+ "404055000431303031313132353239393837000000000000001002C1F0695230086A529C911100000000000F890000A60500000000036301014CFF000001190A0D0539191480D60488C5721800000000BF8A640D0A"));
+
+ verifyPositions(decoder, binary(
+ "40406000043130303131313235323939383700000000000000400705000000C1F0695249F469529C9111000000000069830000D80040000400036401014C04030001190A0D04201E1480D60488C5721800000000AF0101060F000F00EA1E0D0A"));
+
+ verifyAttributes(decoder, binary(
+ "404057000431303031313132353239393837000000000000004002C1F06952F0F169529C9111000000000069830000470000000400036401014C01030078000505210C210D210F21102101073BE8030064280AEB930D0A"));
+
+ verifyPositions(decoder, binary(
+ "40405900043130303131313235323939383700000000000000400101C1F06952E7F069529C9111000000000069830000070000000400036401014C00030001190A0D0412041480D60488C57218000000009F01E803ED9A0D0A"));
+
+ verifyAttributes(decoder, binary(
+ "4040B9000431303031313132353239393837000000000000004005C1F069521BF169529C9111000000000069830000130000000400036401014C0003000022032104210521062107210C210D210E210F2110211121132115211C211F21212124212E212F2130213121322133213C214221432144214521472149214A214C214D214E210100643B6232E803003E64280A3C24FE00010E010F00D5805A483C640000000000010000E02E000000066400000500000000A7710D0A"));
+
+ verifyAttributes(decoder, binary(
+ "404043000431303031313132353239393837000000000000004006C1F0695209F169529C91110000000000698300000D0000000400036401014C00030000009AF40D0A"));
+
+ verifyNull(decoder, binary(
+ "404086000431303031313132353239393837000000000000004004C1F0695200F169529C91110000000000698300000D0000000400036401014C00030022032104210521062107210C210D210E210F2110211121132115211C211F21212124212E212F2130213121322133213C214221432144214521472149214A214C214D214E219AE90D0A"));
+
+ verifyPositions(decoder, binary(
+ "40407F000431303031313132353239393837000000000000001001C1F06952FDF069529C91110000000000698300000C0000000000036401014C00030001190A0D04121A1480D60488C5721800000000AF4944445F3231364730325F532056312E322E31004944445F3231364730325F482056312E322E31000000DF640D0A"));
+
+ verifyPositions(decoder, binary(
+ "404044000c3631313135303030303935360000000000000000420600011e0a0f0b1312864fcd08c07a13030100640acf000004000a000000000000007ba083a66ad80d0a"));
+
+ verifyPosition(decoder, binary(
+ "40405c000c363131313530303030393536000000000000000040011c0a0f0e362dca53cd0860831303000000000300000000ff000000000000007ba083a650542d3639305f56312e312e320050542d3639302056312e32008a020d0a"));
+
+ verifyAttributes(decoder, binary(
+ "4040450004323132474c31313433303035303033000000000040082ca89b55a6a99b555c57000000000000c40200000b0000001400036401111f000302f5533bd653f10d0a"));
+
+ verifyNull(decoder, binary(
+ "40404d0004323132474c3131343330303530303300000000004007120000002ca89b55cba99b555c57000000000000c40200000b0000000000036401111f000102000101170000000068850d0a"));
+
+ verifyNull(decoder, binary(
+ "4040420004323132474c31313433303035303033000000000010022ca89b55cca99b555c57000000000000cf0200000b0000000000036401111f0000020013be0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "4040870004323132474c31313433303035303033000000000040052ca89b55e3a89b555c57000000000000c4020000040000001400036401111f0003000012042105210b210c210d210f211021112113211c2121212321242133213421422146214f212b50663603003ce9030dff060000600dffffc25865ffff9e02b43624000000003cbc0d0a"));
+
+ verifyNull(decoder, binary(
+ "4040d00004323132474c31313433303035303033000000000010013ec09b5596c29b555c57000000000000de0200000f0000000000036401111f000000004944445f3231334730325f532056322e322e36004944445f3231334730325f482056322e322e360032000110021003100410051006100710081009100a100b100c100d100e1011100111021103110411051106110711011202120312041201130213031301160216011701180218011b011c011d011e011f021f031f041f051f061f071f012102210126012701288a690d0a"));
+
+ verifyNull(decoder, binary(
+ "40404d0004323132474c3131343330303530303300000000004007050000003ec09b5564c29b555c57000000000000de0200000f0000002000036401111f0000020001010e00000000237e0d0a"));
+
+ verifyNull(decoder, binary(
+ "40401F00043130303131313235323939383700000000000000100303320D0A"));
+
+ verifyPositions(decoder, binary(
+ "40407F000431303031313132353239393837000000000000001001C1F06952FDF069529C91110000000000698300000C0000000000036401014C00030001190A0D04121A1480D60488C5721800000000AF4944445F3231364730325F532056312E322E31004944445F3231364730325F482056312E322E31000000DF640D0A"));
+
+ verifyPositions(decoder, binary(
+ "40405900043130303131313235323939383700000000000000400101C1F06952E7F069529C9111000000000069830000070000000400036401014C00030001190A0D0412041480D60488C57218000000009F01E803ED9A0D0A"));
+
+ verifyPositions(decoder, binary(
+ "40405900043335343034333035303834343134330000000000400100f61a7355c11b7355710000000b00000000000000000000000400000000240e0200020106060f100b2d5a78a7076ec0fb1d00008c065f010000ac220d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CastelProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/CastelProtocolEncoderTest.java
new file mode 100644
index 000000000..bcb93a010
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CastelProtocolEncoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class CastelProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ CastelProtocolEncoder encoder = new CastelProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_STOP);
+
+ verifyCommand(encoder, command, binary("40402000013132333435363738393031323334350000000000458301a94a0d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CautelaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CautelaProtocolDecoderTest.java
new file mode 100644
index 000000000..28236c87f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CautelaProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class CautelaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CautelaProtocolDecoder decoder = new CautelaProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "20,010907000000,14,02,18,16.816667,96.166667,1325,S,*2E"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CellocatorProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CellocatorProtocolDecoderTest.java
new file mode 100644
index 000000000..769760fa5
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CellocatorProtocolDecoderTest.java
@@ -0,0 +1,33 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class CellocatorProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CellocatorProtocolDecoder decoder = new CellocatorProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "4d4350470041420f000402021226d8a70221d801010000000001000000000000000000000000c4d90000000ca7a741ff0096dd15a40700000000000000001619130c01e307e4"));
+
+ verifyPosition(decoder, binary(
+ "4D434750008AD01500080103011804000000460020000000005E750000000000000000000000C34300040204DA4DA30367195703E803000000000000000001030F0802E10778"));
+
+ verifyPosition(decoder, binary(
+ "4D434750008AD01500080102011804000000360060000000005E750000000000000000000000C24300040204DA4DA30367195703E80300000000000000003B020F0802E107DF"));
+
+ verifyPosition(decoder, binary(
+ "4D4347500006000000081A02021204000000210062300000006B00E100000000000000000000E5A100040206614EA303181A57034E1200000000000000001525071403D60749"));
+
+ verifyPosition(decoder, binary(
+ "4d434750000101000008011f041804000000200100000000005e750000000000000000000000548500040204da4da30367195703e80300000000000000002014151007dd07f7"));
+
+ verifyPosition(decoder, binary(
+ "4d434750005e930100080102041804000000200f20000000005e7500000000000000000000005af400040204da4da30367195703e8030000000000000000021a111e08dd0760"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CellocatorProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/CellocatorProtocolEncoderTest.java
new file mode 100644
index 000000000..89850fb5f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CellocatorProtocolEncoderTest.java
@@ -0,0 +1,26 @@
+package org.traccar.protocol;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class CellocatorProtocolEncoderTest extends ProtocolTest {
+
+ @Ignore
+ @Test
+ public void testEncode() throws Exception {
+
+ CellocatorProtocolEncoder encoder = new CellocatorProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_OUTPUT_CONTROL);
+ command.set(Command.KEY_INDEX, 0);
+ command.set(Command.KEY_DATA, "1");
+
+ verifyCommand(encoder, command, binary("4D434750000000000000000000000303101000000000000026"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CguardProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CguardProtocolDecoderTest.java
new file mode 100644
index 000000000..a386b6b47
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CguardProtocolDecoderTest.java
@@ -0,0 +1,78 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class CguardProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CguardProtocolDecoder decoder = new CguardProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "IDRO:354868050655283"));
+
+ verifyPosition(decoder, text(
+ "NV:190225 144543:55.776505:37.729000:0:10:0:0"));
+
+ verifyAttributes(decoder, text(
+ "BC:190225 144543:CSQ1:64:NSQ1:0:NSQ2:1:BAT1:100"));
+
+ verifyAttributes(decoder, text(
+ "BC:190225 142653:CSQ1:80:NSQ1:0:NSQ2:1:BAT1:3.53"));
+
+ verifyPosition(decoder, text(
+ "NV:170409 031456:56.808553:60.595476:0:NAN:0"));
+
+ verifyAttributes(decoder, text(
+ "BC:170409 031456:CSQ1:64:NSQ1:17:PWR1:0"));
+
+ verifyPosition(decoder, text(
+ "NV:161007 122043:55.812730:37.733689:3.62:NAN:244.05:143.4"));
+
+ verifyPosition(decoder, text(
+ "NV:161007 122044:55.812732:37.733670:3.97:NAN:260.95:143.9"));
+
+ verifyAttributes(decoder, text(
+ "BC:161007 122044:CSQ1:77:NSQ1:18:BAT1:100"));
+
+ verifyPosition(decoder, text(
+ "NV:160711 044023:54.342907:48.582590:0:NAN:0:110.1"));
+
+ verifyPosition(decoder, text(
+ "NV:160711 044023:54.342907:-148.582590:0:NAN:0:110.1"));
+
+ verifyAttributes(decoder, text(
+ "BC:160711 044023:CSQ1:48:NSQ1:7:NSQ2:1:BAT1:98:PWR1:11.7:CLG1:NAN"));
+
+ verifyAttributes(decoder, text(
+ "BC:160711 044524:CSQ1:61:NSQ1:18:BAT1:98:PWR1:11.7:CLG1:NAN"));
+
+ verifyNull(decoder, text(
+ "VERSION:3.3"));
+
+ verifyPosition(decoder, text(
+ "NV:160420 101902:55.799425:37.674033:0.94:NAN:213.59:156.6"));
+
+ verifyAttributes(decoder, text(
+ "BC:160628 081024:CSQ1:32:NSQ1:10:BAT1:100"));
+
+ verifyAttributes(decoder, text(
+ "BC:160628 081033:NSQ2:0"));
+
+ verifyPosition(decoder, text(
+ "NV:160630 151537:55.799913:37.674267:0.7:NAN:10.21:174.9"));
+
+ verifyAttributes(decoder, text(
+ "BC:160630 153316:BAT1:76"));
+
+ verifyAttributes(decoder, text(
+ "BC:160630 153543:NSQ2:0"));
+
+ verifyNull(decoder, text(
+ "PING"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CityeasyProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CityeasyProtocolDecoderTest.java
new file mode 100644
index 000000000..146e13ae8
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CityeasyProtocolDecoderTest.java
@@ -0,0 +1,41 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+
+public class CityeasyProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CityeasyProtocolDecoder decoder = new CityeasyProtocolDecoder(null);
+
+ verifyNotNull(decoder, binary(
+ "545400853575570249020100033b3430342c34352c31303638312c31313632312c33352c31303638312c31313632322c32332c31303638312c32383938332c32332c31303638312c31313632332c32312c31303638312c32333338312c31372c31303638312c32323538332c31372c31303638312c32363434312c31330000000d352e0d0a"));
+
+ verifyNull(decoder, binary(
+ "54540019357557024902010002520704100000000bbe700d0a"));
+
+ verifyNull(decoder, binary(
+ "5454001735755702490201434a01000000000c24280d0a"));
+
+ verifyNull(decoder, binary(
+ "545400153520000000000100010000000111000D0A"));
+
+ verifyNull(decoder, binary(
+ "54540019357557024902000002520704300000000376390d0a"));
+
+ verifyPosition(decoder, binary(
+ "5454006135200000000001000332303134313131303039353430392C412C342C4E2C32322E3533373232382C452C3131342E3032323737342C302E312C312E392C35302E363B3436302C302C31303137332C343635322C34310000000B63130D0A"),
+ position("2014-11-10 09:54:09.000", true, 22.53723, 114.02277));
+
+ verifyPosition(decoder, binary(
+ "5454006135200000000001000432303134313131303039353330362C412C352C4E2C32322E3533373233352C452C3131342E3032323838312C302E322C312E362C35342E313B3436302C302C31303137332C343635322C343100000045EC620D0A"));
+
+ verifyPosition(decoder, binary(
+ "5454009035755702490200000332303135303732393033303834352c412c362c4e2c31322e3833353735362c452c37372e3638373039362c302e332c312e322c3931302e303b3430342c34352c31303638312c31313632312c34332c31303638312c31313632332c32312c31303638312c32323538332c32302c31303638312c32333338312c31380000000267370d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CityeasyProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/CityeasyProtocolEncoderTest.java
new file mode 100644
index 000000000..7c03b7d5b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CityeasyProtocolEncoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class CityeasyProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ CityeasyProtocolEncoder encoder = new CityeasyProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SET_TIMEZONE);
+ command.set(Command.KEY_TIMEZONE, "GMT+6");
+
+ verifyCommand(encoder, command, binary("5353001100080001680000000B60820D0A"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ContinentalProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ContinentalProtocolDecoderTest.java
new file mode 100644
index 000000000..83722ef97
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ContinentalProtocolDecoderTest.java
@@ -0,0 +1,29 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ContinentalProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ContinentalProtocolDecoder decoder = new ContinentalProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "5356003216001eb48505025b4001e90f7f18ce0f00522200400001015b4001e9000e820100000c24000100014e0400736a7a"),
+ position("2018-07-06 23:57:29.000", true, -23.46609, -46.54497));
+
+ verifyPosition(decoder, binary(
+ "5356002A1100003039030243A68B5700FEB5AB00FD715F012700000143A68B57000E000000000C2F00000130"),
+ position("2005-12-19 10:28:39.000", true, -23.49027, -46.55138));
+
+ verifyPosition(decoder, binary(
+ "5356002a0d0010a12403025a9ea47f00feb48400fd6e63000c0000015a9ea480000e000100000c000000"));
+
+ verifyPosition(decoder, binary(
+ "5356002a0d0010a1240302581b944100febed800fd9fa30139001300581c73fa000e000000000d000001"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/CradlepointProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/CradlepointProtocolDecoderTest.java
new file mode 100644
index 000000000..7ffad8015
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/CradlepointProtocolDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class CradlepointProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ CradlepointProtocolDecoder decoder = new CradlepointProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "356526070063940,0,4337.19009,N,11612.34705,W,0.0,277.2,AT&T,,,-79,,-14.0,"));
+
+ verifyPosition(decoder, text(
+ "356526070063940,1,4337.19008,N,11612.34705,W,0.0,277.2,AT&T,,,-79,,-14.0,"));
+
+ verifyPosition(decoder, text(
+ "+14063964266,162658,4333.62404,N,11636.23469,W,0.0,,Verizon Wireless,LTE,-107,-74,-16,,100.68.169.178"));
+
+ verifyPosition(decoder, text(
+ "+12084014675,162658,4337.174385,N,11612.338373,W,0.0,,Verizon,,-71,-44,-11,,"));
+
+ verifyPosition(decoder, text(
+ "353547063544681,170515,3613.25,N,11559.14,W,0.0,,,,,,,,"));
+
+ verifyPosition(decoder, text(
+ "353547060558130,170519,4337.17,N,11612.34,W,0.0,294.7,,,,,,,"));
+
+ verifyPosition(decoder, text(
+ "+12084014675,162658,4337.174385,N,11612.338373,W,0.0,,Verizon,,-71,-44,-11,,"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/DishaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/DishaProtocolDecoderTest.java
new file mode 100644
index 000000000..ddb5aca18
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/DishaProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class DishaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ DishaProtocolDecoder decoder = new DishaProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$A#A#864161028848856#A#053523#010216#2232.7733#N#08821.1940#E#002.75#038.1#09#00.8#1800#0#000#0000#9999#11.7#285.7#0001*"));
+
+ verifyPosition(decoder, text(
+ "$A#A#864161028848856#A#182134#090116#2232.0191#N#08821.3278#E#001.74#231.4#04#01.5#1300#0#000#0000#9999#54.4#6407.7#0000*"),
+ position("2016-01-09 18:21:34.000", true, 22.53365, 88.35546));
+
+ verifyPosition(decoder, text(
+ "$A#A#353943046615971#A#064219#281113#1836.7267#N#07347.4177#E#000.00#280.4#09#00.8#3000#2#100#0000#8888#86.5#3919.1#0000*"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/DmtHttpProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/DmtHttpProtocolDecoderTest.java
new file mode 100644
index 000000000..e9d98d6d3
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/DmtHttpProtocolDecoderTest.java
@@ -0,0 +1,19 @@
+package org.traccar.protocol;
+
+import io.netty.handler.codec.http.HttpMethod;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class DmtHttpProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ DmtHttpProtocolDecoder decoder = new DmtHttpProtocolDecoder(null);
+
+ verifyPositions(decoder, request(HttpMethod.POST, "/",
+ buffer("{\"SerNo\":131693,\"IMEI\":\"356692063643328\",\"ICCID\":\"8944538523010771676\",\"ProdId\":33,\"FW\":\"33.4.1.27\",\"Records\":[{\"SeqNo\":125,\"Reason\":11,\"DateUTC\":\"2017-05-11 05:58:44\",\"Fields\":[{\"GpsUTC\":\"2017-05-08 18:04:57\",\"Lat\":43.7370138,\"Long\":-79.3462607,\"Alt\":197,\"Spd\":0,\"SpdAcc\":13,\"Head\":66,\"PDOP\":18,\"PosAcc\":37,\"GpsStat\":7,\"FType\":0},{\"DIn\":2,\"DOut\":0,\"DevStat\":2,\"FType\":2},{\"AnalogueData\":{\"1\":14641,\"3\":2484,\"4\":26,\"5\":10868},\"FType\":6},{\"AnalogueData\":{\"11\":34,\"12\":0,\"13\":309,\"14\":9921,\"15\":3},\"FType\":7}]},{\"SeqNo\":128,\"Reason\":11,\"DateUTC\":\"2017-05-11 17:59:45\",\"Fields\":[{\"GpsUTC\":\"2017-05-08 18:04:57\",\"Lat\":43.7370138,\"Long\":-79.3462607,\"Alt\":197,\"Spd\":0,\"SpdAcc\":13,\"Head\":66,\"PDOP\":18,\"PosAcc\":37,\"GpsStat\":7,\"FType\":0},{\"DIn\":2,\"DOut\":0,\"DevStat\":2,\"FType\":2},{\"AnalogueData\":{\"1\":14607,\"3\":2752,\"4\":26,\"5\":11062},\"FType\":6},{\"AnalogueData\":{\"11\":34,\"12\":1,\"13\":325,\"14\":10881,\"15\":3},\"FType\":7}]},{\"SeqNo\":130,\"Reason\":9,\"DateUTC\":\"2017-05-11 19:30:03\",\"Fields\":[{\"GpsUTC\":\"2017-05-08 18:04:57\",\"Lat\":43.7370138,\"Long\":-79.3462607,\"Alt\":197,\"Spd\":0,\"SpdAcc\":13,\"Head\":66,\"PDOP\":18,\"PosAcc\":37,\"GpsStat\":3,\"FType\":0},{\"DIn\":6,\"DOut\":0,\"DevStat\":2,\"FType\":2},{\"AnalogueData\":{\"1\":14599,\"3\":2731,\"4\":27,\"5\":10965},\"FType\":6},{\"AnalogueData\":{\"11\":34,\"12\":2,\"13\":329,\"14\":11121,\"15\":3},\"FType\":7}]},{\"SeqNo\":131,\"Reason\":11,\"DateUTC\":\"2017-05-11 19:32:03\",\"Fields\":[{\"GpsUTC\":\"2017-05-08 18:04:57\",\"Lat\":43.7370138,\"Long\":-79.3462607,\"Alt\":197,\"Spd\":0,\"SpdAcc\":13,\"Head\":66,\"PDOP\":18,\"PosAcc\":37,\"GpsStat\":7,\"FType\":0},{\"DIn\":6,\"DOut\":0,\"DevStat\":2,\"FType\":2},{\"AnalogueData\":{\"1\":14403,\"3\":2783,\"4\":27,\"5\":10965},\"FType\":6},{\"AnalogueData\":{\"11\":34,\"12\":2,\"13\":330,\"14\":11181,\"15\":3},\"FType\":7}]},{\"SeqNo\":133,\"Reason\":11,\"DateUTC\":\"2017-05-11 19:36:15\",\"Fields\":[{\"GpsUTC\":\"2017-05-08 18:04:57\",\"Lat\":43.7370138,\"Long\":-79.3462607,\"Alt\":197,\"Spd\":0,\"SpdAcc\":13,\"Head\":66,\"PDOP\":18,\"PosAcc\":37,\"GpsStat\":7,\"FType\":0},{\"DIn\":6,\"DOut\":0,\"DevStat\":2,\"FType\":2},{\"AnalogueData\":{\"1\":14319,\"3\":2898,\"4\":23,\"5\":10965},\"FType\":6},{\"AnalogueData\":{\"11\":34,\"12\":3,\"13\":331,\"14\":11241,\"15\":3},\"FType\":7}]}]}")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/DmtProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/DmtProtocolDecoderTest.java
new file mode 100644
index 000000000..ae5e9353c
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/DmtProtocolDecoderTest.java
@@ -0,0 +1,42 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class DmtProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ DmtProtocolDecoder decoder = new DmtProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "0255003300001b00003335333232393032373533393235310038393931353030303030303030313330343539340000000403041910780603"));
+
+ verifyPositions(decoder, false, binary(
+ "02551040000eaca40d00d2b8e562c51f9912f39a6bee00007e420091090903070100000000008b1065360000000000007fd401c4fcf2feffffffffffffffffee0000003f1b"));
+
+ verifyPositions(decoder, false, binary(
+ "02551080000eada40d00d2b8e58ac51f9912f39a6bee00007e42007e090709070000000000009010fc330000000000007fc201a0fc04ffffffffffffffffffe5000000c5d00eaea40d00d2b8e58ac51f9912f39a6bee00007e42007e09070207000000000000851008340000000000007fc201a0fc04ff0000000000000000e5000000c96d"));
+
+ verifyNull(decoder, binary(
+ "025500310038f90100333533333233303831363639373330003839363130313835303031383234383434363330002202010900000000"));
+
+ verifyNull(decoder, binary(
+ "0255220000"));
+
+ verifyPositions(decoder, false, binary(
+ "025504d80352000602000052185c0803001552185c0842ee19eaba2524682d000d060973112b0302080100000000000300060901421003e40604140007190b300000000c030000000de80100000ec90e00000f0700000052000702000069185c0803001569185c089ac019ea0ad223682300fb02047d152f03020801000000000003000609013f1003fc0604140007190b300000000c030000000de90100000ecb0e00000f0700000052000802000092185c0803001592185c0800a619eaa5e7226821009c0506880e250302080100000000000300060901411003f30604140007190b300000000c030000000dea0100000ef10e00000f07000000520009020000a9185c08030015a9185c0818ae19ea1e62226826001e05038e0e2203020801000000000003000609013f1003030704140007190b300000000c030000000deb0100000ef60e00000f0700000052000a020000c0185c08030015c0185c0893b619ea7fd321681a00640403860f1d0302080100000000000300060901401003ff0604140007190b300000000c030000000dec0100000ef80e00000f0700000052000b020000d7185c08030015d7185c08e08519eab7c921682300fd04035510270302080100000000000300060901401003ea0604140007190b300000000c030000000ded0100000efa0e00000f0700000052000c020000ee185c08030015ee185c08f61719ea61e221682c004c0503540f190302080100000000000300060901421003dd0604140007190b300000000c030000000dee0100000efc0e00000f0700000052000d02000005195c0803001505195c0836b518eac9f221683000fa0107740e2d03020801000000000003000609013f1003fe0604140007190b300000000c030000000def0100000efe0e00000f0700000052000e0200001d195c080300151d195c08d1b518ea2d6721682300980502870e1d0302080100000000000300060901411003ed0604140007190b300000000c030000000df00100000e000f00000f0700000052000f02000034195c0803001534195c086acd18ea742b2168400006020500132903020801000000000003000609013d10030d0704140007190b300000000c030000000df10100000e030f00000f070000005200100200004d195c080300154d195c08dfba18eab81721684e003000093b0e1e03020801000000000003000609013e1003130704140007190b300000000c030000000df20100000e050f00000f0700000052001102000065195c0803001565195c081db318ea871f216822000400080416250302080100000000000300060901401003060704140007190b300000000c030000000df30100000e090f00000f07000000"));
+
+ verifyPositions(decoder, false, binary(
+ "025504e9032f000d000000000000001501222700524553455420446172742033342e322e312e3920666c6167733d312057443d303f000e0000000000000015013214004e6f2041646d696e20706172616d7320666f756e64202d207573696e672064656661756c7473202b204175746f41504e37000f00000000000000090015000000000000000000000000000000000000000000020805000000000007000609012b1002400003700e37001000000000000000090015000000000000000000000000000000000000000000020801000000000007000609012b1002400003700e37001100000000000000090015000000000000000000000000000000000000000000020800000000000007000609012b1002400003700e37001200000000000000020015000000000000000000000000000000000000000000020800000000000006000609012b1002400003700e370013000000000000000f001500000000000000000000000000000000000000000002080000000000000200060901271002370003670e2e0014000000000000001501211300526f6c6c20646574656374656420636f735e32203c203338333535333838343700150000000000000017001500000000000000000000000000000000000000000002080000000000000200060901071002300003d60e2a00160000000000000015011d130054756d626c65722074726967676572656420636f735e32203c20302e0017000000000000001501211300526f6c6c20646574656374656420636f735e32203c203338333535333838343700180000000000000017001500000000000000000000000000000000000000000002080000000000000200060901071002300003f70e2a00190000000000000015011d130054756d626c65722074726967676572656420636f735e32203c203026001a000000000000001501190b0047534d3a20544350206261642053594e432063686172732e001b000000000000001501211300526f6c6c20646574656374656420636f735e32203c203338333535333838343a001c0000000000000017001500000000000000000000000000000000000000000002080000000000000200060c01c90f02300003e20f041f002a001d0000000000000015011d130054756d626c65722074726967676572656420636f735e32203c20302e001e000000000000001501211300526f6c6c20646574656374656420636f735e32203c203338333535333838343a001f0000000000000017001500000000000000000000000000000000000000000002080000000000000200060c01d80f02300003ff0f0418002a00200000000000000015011d130054756d626c65722074726967676572656420636f735e32203c2030"));
+
+ verifyNull(decoder, binary(
+ "025500310038f90100333533333233303831363639373330003839363130313435363839393333303030303835002202010900000000"));
+
+ verifyPositions(decoder, binary(
+ "0255043D003D004746000096D684020B001502D48402F043F4EC2A6909452B001F00050011230302080000000000000A00060F041D0001FE0F021E0005000003BF08"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/DwayProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/DwayProtocolDecoderTest.java
new file mode 100644
index 000000000..107a2a435
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/DwayProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class DwayProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ DwayProtocolDecoder decoder = new DwayProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "AA55,36,10024,1,171025,161055,36.0294,-79.7881,201, 2.5,111,1000,0000,00000,3578,0,0,0,D"));
+
+ verifyPosition(decoder, text(
+ "AA55,115,318,1,171024,195059,28.0153,-82.4761,3, 1.0,319,1000,0000,00000,4244,0,0,0,D"));
+
+ verifyPosition(decoder, text(
+ "AA55,117,318,1,171025,153758,28.0152,-82.4759,19, 0.6,319,1000,0000,10000,4242,0,0,0,D"));
+
+ verifyPosition(decoder, text(
+ "AA55,1,123456,1,140101,101132,22.5500,113.6770,75,70.5,320,1100,0011,1110,3950,33000,24000,12345678"));
+
+ verifyNull(decoder, text(
+ "AA55,HB"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EasyTrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/EasyTrackProtocolDecoderTest.java
new file mode 100644
index 000000000..b26991ae7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EasyTrackProtocolDecoderTest.java
@@ -0,0 +1,55 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class EasyTrackProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ EasyTrackProtocolDecoder decoder = new EasyTrackProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "*ET,358155100054249,HB,A,100b06,053318,803a0b51,03d507c9,0017,0000,00400000,07,100,0000,1435,63"));
+
+ verifyNull(decoder, text(
+ "*ET,358155100054249,MQ"));
+
+ verifyNull(decoder, text(
+ "*ET,358155100054249,TX,A,100b06,053230"));
+
+ verifyPosition(decoder, text(
+ "*ET,358155100054249,HB,A,100b06,053212,803a0b20,03d507a2,0054,0000,40400000,06,100,0000,1435,44"));
+
+ verifyNull(decoder, text(
+ "*ET,135790246811221,GZ,0001,0005"));
+
+ verifyPosition(decoder, text(
+ "*ET,135790246811221,DW,A,0A090D,101C0D,00CF27C6,0413FA4E,0000,0000,00000000,20,4,0000,00F123"),
+ position("2010-09-13 16:28:13.000", true, 22.62689, 114.03021));
+
+ verifyNull(decoder, text(
+ "*ET,358155100048430,CC,0.0,V,100603,141817,80d77ae8,81ab1ffd,0000,6b08,40000000,19,99,0000,fa9,918"));
+
+ verifyPosition(decoder, text(
+ "*ET,135790246811221,DW,A,050915,0C2A27,00CE5954,04132263,0000,0000,01000000,20,4,0000,001254"));
+
+ verifyPosition(decoder, text(
+ "*ET,135790246811221,DW,A,0A090D,101C0D,00CF27C6,0413FA4E,0000,0000,00000000,20,4,0000,00F123,100"));
+
+ verifyPosition(decoder, text(
+ "*ET,135790246811221,DW,A,0A090D,101C0D,00CF27C6,8413FA4E,0000,0000,00000000,20,4,0000,00F123,100"));
+
+ verifyPosition(decoder, text(
+ "*ET,358155100003016,HB,A,0d081e,07381e,8038ee09,03d2e9be,004f,0000,40c00000,0f,100,0000,00037c,29"));
+
+ verifyPosition(decoder, text(
+ "*ET,358155100003016,HB,A,0d081e,073900,8038ee2f,03d2e9fd,0114,0000,40c00000,12,100,0000,00037c,32"));
+
+ verifyPosition(decoder, text(
+ "*ET,135790246811221,HB,A,050915,0C2A27,00CE5954,04132263,0000,0000,01000000,20,4,0000,00F123,100,200"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EelinkProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/EelinkProtocolDecoderTest.java
new file mode 100644
index 000000000..e3cff9525
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EelinkProtocolDecoderTest.java
@@ -0,0 +1,114 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class EelinkProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ EelinkProtocolDecoder decoder = new EelinkProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "454C0027E753035254407167747167670100180002035254407167747100200205020500010432000086BD"));
+
+ verifyAttributes(decoder, binary(
+ "676707006502df5c89fde800bc3fa8030302005555045b555555057a5555550b225555550c105c55550d115555550e7e5555550f4555555510017b5555112b5555551f01ed5555208005b0012100005555407ad000004237f5555589000000498a0000aef78b00000000"));
+
+ verifyAttribute(decoder, binary(
+ "676712003400e45c5b0ade02012e03702d87064546aa24066a1086018a0000002dc1a0ffffffff0afd074d000000000000000000000000fce0"),
+ Position.PREFIX_TEMP + 2, -50.0);
+
+ verifyAttribute(decoder, binary(
+ "6767120043000e5c37387c0304e4e1b4f8194fa800160013009408012e03702d8706453c6e5b066f115f05710000001b067f8d248d240313020500000000000000000000000001cc"),
+ Position.PREFIX_TEMP + 2, 28.75);
+
+ verifyPosition(decoder, binary(
+ "676714002414B05AD43A7D03026B92B10C395499FFD7000000000701CC00002495000014203604067B"));
+
+ verifyNotNull(decoder, binary(
+ "676714004F14B0E68CAFE58AA8E68AA5E8ADA621E5B9BFE4B89CE79C81E6B7B1E59CB3E5B882E58D97E5B1B1E58CBAE696B0E8A5BFE8B7AF3138EFBC88E8B79DE5AE87E998B3E5A4A7E58EA63230E7B1B3EFBC89"));
+
+ verifyPosition(decoder, binary(
+ "676780005a000001000000004c61743a4e33312e38333935352c4c6f6e3a5738322e36313334362c436f757273653a302e30302c53706565643a302e30306b6d2f682c4461746554696d653a323031372d31322d30322031313a32393a3433"));
+
+ verifyPosition(decoder, binary(
+ "676780005E5788014C754C754C61743A4E32332E3131313734330A4C6F6E3A453131342E3430393233380A436F757273653A302E30300A53706565643A302E31374B4D2F480A446174652054696D653A323031352D30392D31332032303A32313A3230"));
+
+ verifyPosition(decoder, binary(
+ "454C0050EAE2035254407167747167671200410021590BD93803026B940D0C3952AD0021000000000501CC0001A53F0170F0AB1305890F11000000000000C2D0001C001600000000000000000000000000000000"));
+
+ verifyNull(decoder, binary(
+ "676701000c007b03525440717505180104"));
+
+ verifyPosition(decoder, binary(
+ "6767120048000559c1829213059a7400008e277d000c000000000800cc00080d2a000034df3cf0b429dd82cad3048910320000000000007b7320d005ba0000000019a000000000000000000000"));
+
+ verifyPosition(decoder, binary(
+ "6767050020213b59c6aecdff41dce70b8b977d00000001fe000a36e30078fe010159c6aecd"));
+
+ verifyPosition(decoder, binary(
+ "676705002102b459ae7388fcd360d7034332b1000000028f000a4f64002eb101010159ae7388"));
+
+ verifyPosition(decoder, binary(
+ "676702001c02b259ae7387fcd360d6034332b2000000028f000a4f64002eb10101"));
+
+ verifyPosition(decoder, binary(
+ "6767050022001F59643640000000000000000000000001CC0000249500142000015964A6C0006E"));
+
+ verifyAttributes(decoder, binary(
+ "67670300040021006E"));
+
+ verifyPosition(decoder, binary(
+ "676705002200255964369D000000000000000000000001CC0000249500142000025964A71D006A"));
+
+ verifyAttributes(decoder, binary(
+ "67670300040028006A"));
+
+ verifyPosition(decoder, binary(
+ "676712002d066c592cca6803002631a60b22127700240046005c08020d000301af000da0fd12007f11ce05820000001899c0"));
+
+ verifyPosition(decoder, binary(
+ "676702002509f65868507603a1e92e03cf90fe000000019f000117ee00111e0120631145003101510000"));
+
+ verifyAttributes(decoder, binary(
+ "676712001e0092579714d60201f90001785003a301cd1a006a118504f2000000000000"));
+
+ verifyPosition(decoder, binary(
+ "676712003400505784cc0b130246479b07d05a06001800000000070195039f046100002cc52e6466b391604a4900890e7c00000000000006ca"));
+
+ verifyPosition(decoder, binary(
+ "676714002b00515784cc24130246479b07d05a06001800010000060195039f046100002cc52f6466b391604a49020089"));
+
+ verifyNull(decoder, binary(
+ "676701000c002603541880486128290120"));
+
+ verifyPosition(decoder, binary(
+ "676704001c01a4569ff2dd0517a0f7020b0d9a06011000d8001e005b0004450183"));
+
+ verifyPosition(decoder, binary(
+ "676705002200ba569fc3520517a0d8020b0f740f007100d8001e005b0004460101569fd162001f"));
+
+ verifyPosition(decoder, binary(
+ "676702002500bb569fc3610517a091020b116000001900d8001e005b00044601001f1170003200000000"));
+
+ verifyPosition(decoder, binary(
+ "676704001c00b7569fc3020517a2d7020b08e100000000d8001e005b0004460004"));
+
+ verifyNull(decoder, binary(
+ "676701000b001b035418804661834901"));
+
+ verifyAttributes(decoder, binary(
+ "6767030004001A0001"));
+
+ verifyAttributes(decoder, binary(
+ "6767070088001050E2281400FFFFFFFF02334455660333445566043344556605AA00000007334455660A334455660B334455660C4E2000000DAA0000000E334455660F3344556610AAAA000011334455661C334455661F334455662133445566423344556646334455664D334455665C334455665E33445566880000000089000000008A000000008B00000000"));
+
+ verifyPosition(decoder, binary(
+ "676702001b03c5538086df0190c1790b3482df0f0157020800013beb00342401"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EelinkProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/EelinkProtocolEncoderTest.java
new file mode 100644
index 000000000..e4502f919
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EelinkProtocolEncoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class EelinkProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_STOP);
+
+ verifyCommand(new EelinkProtocolEncoder(false), command, binary("676780000f0000010000000052454c41592c3123"));
+
+ verifyCommand(new EelinkProtocolEncoder(true), command, binary("454c001eb41a0123456789012345676780000f0000010000000052454c41592c3123"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EgtsFrameDecoderTest.java b/src/test/java/org/traccar/protocol/EgtsFrameDecoderTest.java
new file mode 100644
index 000000000..237c849c5
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EgtsFrameDecoderTest.java
@@ -0,0 +1,19 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class EgtsFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ EgtsFrameDecoder decoder = new EgtsFrameDecoder();
+
+ verifyFrame(
+ binary("0100020B0025003A5701C91A003A5701CD6E68490202101700CBB4740F7617FD924364104F116A0000000000010300001EC2"),
+ decoder.decode(null, null, binary("0100020B0025003A5701C91A003A5701CD6E68490202101700CBB4740F7617FD924364104F116A0000000000010300001EC2")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EgtsProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/EgtsProtocolDecoderTest.java
new file mode 100644
index 000000000..2210893e7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EgtsProtocolDecoderTest.java
@@ -0,0 +1,37 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class EgtsProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ EgtsProtocolDecoder decoder = new EgtsProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "0100010b002200c06401f21700c1640171360d00010101140071360d000238363539303500000000000000000047fc"));
+
+ verifyNull(decoder, binary(
+ "0100000b002400a0d601f01900030081030000000101011600030000004238363434393530333436343333373600014cdc"));
+
+ verifyPositions(decoder, binary(
+ "0100000b002700030e01211800030e8573890100845e980f0202101500f85d980fb37f50aae9653c2b193708317b00000001c51b"));
+
+ verifyPositions(decoder, binary(
+ "0100010b00a308c26401029808c3640171360d000202101800e19a7b0fcfb4c49a0bfdb87a911801b70000000010d90000180400021c0000120300000000101800f39a7b0f2fc9c39a9bf2b87a914001b50000000010da0000180400021c0000120300000000101800fa9a7b0fc663c39a21eeb87a914001b60000000010da0000180400021c0000120300000000101800069b7b0f56d8c29a26ebb87a919600ab0000000010da0000180400021c00001203000000001018000a9b7b0fb2c5c29a19f4b87a915a007d0000000010da0000180400021c0000120300000000101800089b7b0f68ccc29a21eeb87a9164008f0000000010da0000180400021c0000120300000000101800079b7b0fa0d1c29aa4ecb87a918200980000000010da0000180400021c00001203000000001018000b9b7b0f34c4c29ad3f7b87a915a00670000000010da0000180400021c00001203000000001018000f9b7b0f3dbec29aaf0fb97a91c8005e0000000010dc0000180400021c0000120300000000101800199b7b0f42bbc29a0855b97a9178006b0000000010db0000180400021c00001203000000001018001b9b7b0fc8b6c29a3c5db97a916e007e0000000010db0000180400021c00001203000000001018001a9b7b0fc4b9c29a8159b97a916e00750000000010db0000180400021c00001203000000001018001d9b7b0f94aec29a3363b97a916400930000000010db0000180400021c00001203000000001018001c9b7b0fcdb3c29a3760b97a916e008a0000000010db0000180400021c0000120300000000101800209b7b0f28a1c29af263b97a918200ba0000000010db0000180400021c00001203000000001018001f9b7b0f61a6c29af263b97a917800b30000000010db0000180400021c00001203000000001018001e9b7b0f58acc29af263b97a916400a50000000010db0000180400021c0000120300000000101800299b7b0ff26fc29ab561b97a916e00b20000000010d90000180400021c00001203000000001018002d9b7b0fd05bc29a3760b97a916e00bd0000000010d80000180400021c0000120300000000101800359b7b0f4f31c29abe5bb97a916400b50000000010d70000180400021c0000120300000000101800379b7b0f5d28c29abe5bb97a916e00b40000000010d60000180400021c0000120300000000101800369b7b0fd62cc29abe5bb97a916400bd0000000010d60000180400021c00001203000000001018003c9b7b0fca09c29a0358b97a918c00bc0000000010d50000180400021c0000120300000000101800419b7b0f38ebc19a0855b97a916e00b40000000010d60000180400021c0000120300000000101800449b7b0f4edcc19a8a53b97a916400c30000000010d60000180400021c0000120300000000101800469b7b0fded1c19acb52b97a916e00b70000000010d60000180400021c0000120300000000101800649b7b0f7a69c19a154cb97a810000bc0000000010d60000180400021c0000120300000000101800709b7b0fcc5cc19a114fb97a915000970000000010d70000180400021c0000120300000000101800729b7b0fda53c19a8a53b97a91a0007d0000000010d70000180400021c0000120300000000101800749b7b0fa24ec19a3c5db97a91a000650000000010d70000180400021c0000120300000000101800789b7b0fe74ac19aca7eb97a910e015c0000000010d80000180400021c00001203000000001018007f9b7b0f6e46c19a78e0b97a9190015c0000000010d80000180400021c0000120300000000101800869b7b0f3641c19a144eba7a9190015c0000000010d60000180400021c00001203000000001018008d9b7b0ffd3bc19a74b9ba7a9190015c0000000010d40000180400021c0000120300000000101800949b7b0fc536c19a1524bb7a9186015b0000000010d20000180400021c00001203000000001018009b9b7b0fce30c19af78dbb7a919a015c0000000010d00000180400021c0000120300000000101800a29b7b0f552cc19a93fbbb7a9172015d0000000010cd0000180400021c0000120300000000101800b09b7b0f2521c19a6ec0bc7a9186015b0000000010c90000180400021c0000120300000000101800a99b7b0f5e26c19a8759bc7a915e015b0000000010cb0000180400021c0000120300000000101800b79b7b0fa81fc19a1328bd7a9172015b0000000010c70000180400021c0000120300000000101800be9b7b0f6b1dc19ac686bd7a914a015c0000000010c60000180400021c0000120300000000101800c19b7b0fed1bc19ad2a9bd7a912201530000000010c60000180400021c0000120300000000101800c39b7b0f6223c19af4bdbd7a910401420000000010c60000180400021c0000120300000000101800c29b7b0fe91ec19a42b4bd7a910e014c0000000010c60000180400021c0000120300000000101800c59b7b0f502fc19a1acfbd7a91fa00300000000010c60000180400021c0000120300000000101800c49b7b0fdb27c19ae6c6bd7a91fa00390000000010c60000180400021c0000120300000000101800c79b7b0fb83fc19a8ad9bd7a91f000180000000010c60000180400021b0000120300000000101800c69b7b0fc536c19a52d4bd7a91f000250000000010c60000180400021b0000120300000000101800ca9b7b0fc85fc19a81dfbd7a910401030000000010c50000180400021b0000120300000000101800c89b7b0fe74ac19a86dcbd7a91fa000e0000000010c50000180400021b0000120300000000101800d29b7b0f06b7c19afbe3bd7a91a000100000000010c50000180400021c0000120300000000101800d59b7b0ff0c5c19a6beebd7a91b400410000000010c40000180400021c0000120300000000101800d49b7b0ff4c2c19af2e9bd7a91a000310000000010c40000180400021c0000120300000000101800d39b7b0f3ebcc19a79e5bd7a9196001e0000000010c40000180400021c0000120300000000101800d69b7b0f6dc7c19ae0f5bd7a91c800570000000010c40000180400021c000012030000000016b7"));
+
+ verifyPositions(decoder, binary(
+ "0100020B0025003A5701C91A003A5701CD6E68490202101700CBB4740F7617FD924364104F116A0000000000010300001EC2"),
+ position("2018-03-21 05:38:19.000", true, 51.67569, 55.59189));
+
+ verifyPositions(decoder, binary(
+ "0100020B0079000000011F6A001424951CA5CB0F23B5740F020210180023B5740F0A301994DA9C524C9128000A000000100082000011040018110300120900000003150100E803001B0700010000340900001B0700420000000000001B0700430000000000001B0700440000000000001B0700450000000000001B0700460000000000008020"));
+
+ verifyPositions(decoder, binary(
+ "0100020B00F200000001D66A001224951CA5CB0FFCB4740F0202101800FCB4740F502119943D9F524C9119805C000000100084000011040018110300120900000003150100E803001B0700410000000000001B0700420000000000001B0700430000000000001B0700440000000000001B0700450000000000001B0700460000000000006A001324951CA5CB0F05B5740F020210180005B5740F222519942D9E524C9100008B000000100083000011040018110300120900000003160100E803001B0700010000310900001B0700420000000000001B0700430000000000001B0700440000000000001B0700450000000000001B070046000000000000134E"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EnforaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/EnforaProtocolDecoderTest.java
new file mode 100644
index 000000000..1c2f9492a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EnforaProtocolDecoderTest.java
@@ -0,0 +1,31 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class EnforaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ EnforaProtocolDecoder decoder = new EnforaProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "000A08002020202020303131303730303030353730323637"));
+
+ verifyNull(decoder, binary(
+ "003B000502000000000820202020202030313130373030303035373032363720383A000000000D00508401358E640032B37700000367B00000A804"));
+
+ verifyPosition(decoder, binary(
+ "007100040200202020202020202020382020202020202031323334353637383930313233343520313320244750524D432C3232333135322E30302C412C333530392E3836303539342C4E2C30333332322E3734333838372C452C302E302C302E302C3032303631322C2C2C412A35320D0A"),
+ position("2012-06-02 22:31:52.000", true, 35.16434, 33.37906));
+
+ verifyPosition(decoder, binary(
+ "007600040200202020202020202020382020202020202030313138393230303036303831383920313320244750524D432C3137313834312E30302C412C333530392E3835323431302C4E2C30333332322E3735393131332C452C302E302C302E302C3137303731322C332E342C572C412A32350D0A00"));
+
+ verifyPosition(decoder, binary(
+ "006a000a081000202020202020202020333320202020202038363130373430323137313936353620204750524d432c3136313234382e30302c412c333433322e36393231312c532c30353833312e30323231372c572c302e3034382c2c3232303831342c2c2c412a3734"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EsealProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/EsealProtocolDecoderTest.java
new file mode 100644
index 000000000..b615e5062
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EsealProtocolDecoderTest.java
@@ -0,0 +1,33 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class EsealProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ EsealProtocolDecoder decoder = new EsealProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "##S,eSeal,1000821,256,3.0.6,Normal,34,2017-08-31,08:14:40,15,A,25.708828N 100.372870W,10,0,Close,0.71,0:0:3:0,3.8,-73,E##"));
+
+ verifyPosition(decoder, text(
+ "##S,eSeal,1000821,256,3.0.6,Startup,1,2017-08-31,02:01:19,3,V,0.000000N 0.000000E,0,0,Close,3.25,0:0:5:0,3.8,-93,E##"));
+
+ verifyNull(decoder, text(
+ "##S,eSeal,1000821,256,3.0.6,Startup OK,1,180,30,30,16,1,E##"));
+
+ verifyNull(decoder, text(
+ "##S,eSeal,1000821,256,3.0.6,Startup OK,1,180,30,30,16,1,E##"));
+
+ verifyPosition(decoder, text(
+ "##S,eSeal,1000898,256,3.0.6,Normal,6,2017-09-06,23:48:39,3,V,0.000000N 0.000000E,0,0,Close,1.0,0:0:3:0,4.0,-81,E##"));
+
+ verifyNull(decoder, text(
+ "##S,eSeal,1000898,256,3.0.6,RC-NFC DEL ACK,,E##"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EsealProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/EsealProtocolEncoderTest.java
new file mode 100644
index 000000000..16f00d69b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EsealProtocolEncoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class EsealProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ EsealProtocolEncoder encoder = new EsealProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ALARM_DISARM);
+
+ assertEquals("##S,eSeal,123456789012345,256,3.0.8,RC-Unlock,E##", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EskyFrameDecoderTest.java b/src/test/java/org/traccar/protocol/EskyFrameDecoderTest.java
new file mode 100644
index 000000000..ed587e4f3
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EskyFrameDecoderTest.java
@@ -0,0 +1,31 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class EskyFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ EskyFrameDecoder decoder = new EskyFrameDecoder();
+
+ verifyFrame(
+ binary("454f3b303b3836313331313030363436313930383b523b363b3138303432303130343735313b322e39373839363b3130312e36353039313b302e37353b3332303b333339383b313b7c"),
+ decoder.decode(null, null, binary("454f3b303b3836313331313030363436313930383b523b363b3138303432303130343735313b322e39373839363b3130312e36353039313b302e37353b3332303b333339383b313b7c")));
+
+ verifyFrame(
+ binary("454c3b313b3836343930363032393139363632363b3137303832323134333432363b"),
+ decoder.decode(null, null, binary("454c3b313b3836343930363032393139363632363b3137303832323134333432363b")));
+
+ verifyFrame(
+ binary("454f3b303b3836343930363032393139363632363b523b302b3137303830383135353335322b302e30303030302b302e30303030302b302e30302b302b3078312b302b302b302b31323333"),
+ decoder.decode(null, null, binary("454f3b303b3836343930363032393139363632363b523b302b3137303830383135353335322b302e30303030302b302e30303030302b302e30302b302b3078312b302b302b302b31323333")));
+
+ verifyFrame(
+ binary("454f3b303b3836343930363032393139363632363b523b302b3137303830383135353335322b302e30303030302b302e30303030302b302e30302b302b3078312b302b302b302b31323333"),
+ decoder.decode(null, null, binary("454f3b303b3836343930363032393139363632363b523b302b3137303830383135353335322b302e30303030302b302e30303030302b302e30302b302b3078312b302b302b302b31323333454f3b303b3836343930363032393139363632363b523b302b3137303830383135353335322b302e30303030302b302e30303030302b302e30302b302b3078312b302b302b302b31323333")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java
new file mode 100644
index 000000000..da7df0ab2
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/EskyProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class EskyProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ EskyProtocolDecoder decoder = new EskyProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "EO;0;861311006461908;R;6;180420104751;2.97896;101.65091;0.75;320;3398;1;|"));
+
+ verifyNull(decoder, text(
+ "EL;1;864906029196626;170822143426;"));
+
+ verifyPosition(decoder, text(
+ "EO;0;864906029196626;R;7+170822143646+-26.10806+27.94600+0.40+0+0x1+0+102540+0+1242"));
+
+ verifyPosition(decoder, text(
+ "EO;0;864906029196626;R;0+170808155352+0.00000+0.00000+0.00+0+0x1+0+0+0+1233"));
+
+ verifyPosition(decoder, text(
+ "ET;1;014682000989425;R;0+171216001250+33.34405+-111.96682+0.00+0+0x1+0+25598+0+1257+0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ExtremTracProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ExtremTracProtocolDecoderTest.java
new file mode 100644
index 000000000..c5b3364cf
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ExtremTracProtocolDecoderTest.java
@@ -0,0 +1,33 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ExtremTracProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ExtremTracProtocolDecoder decoder = new ExtremTracProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$GPRMC,862106020628733,050859.000,A,1404.8573,N,08710.9967,W,0.00,0,080117,0,,00C8,00218,99,,,,,,0.00"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,10000000001,092313.299,A,2238.8947,N,11355.2253,E,0.00,311.19,010307,0,,"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,00000000000,092244.000,A,0000.0000,S,00000.0000,E,0.00,0.00,101016,0,,8000,0"));
+
+ verifyNull(decoder, text(
+ "$GPRMC,092313.299,A,2238.8947,N,11355.2253,E,0.00,311.19,010307,0,,1111,1111"));
+
+ verifyNull(decoder, text(
+ "$GPRMC,092313.299,A,2238.8947,N,11355.2253,E,0.00,311.19,010307,0,,"));
+
+ verifyNull(decoder, text(
+ "$GPRMC,100936.000,A,0000.0000,S,00000.0000,E,0.00,0.00,101016,0,,8000,0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/FifotrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/FifotrackProtocolDecoderTest.java
new file mode 100644
index 000000000..1dcfc89c4
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/FifotrackProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class FifotrackProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ FifotrackProtocolDecoder decoder = new FifotrackProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "$$79,868345037864709,382,D05,190220085833,22.643210,114.018176,1,1,1,13152,23FFD339*25"));
+
+ verifyPosition(decoder, text(
+ "$$105,866104023179743,AB,A00,,161007085534,A,54.738791,25.271918,0,350,151,0,17929,0000,0,,246|1|65|96DB,936|0*0B"));
+
+ verifyPosition(decoder, text(
+ "$$103,866104023179743,5,A00,,161006192841,A,54.738791,25.271918,0,342,200,0,4265,0000,0,,246|1|65|96DB,9C4|0*75"));
+
+ verifyPosition(decoder, text(
+ "$$103,866104023179743,4,A00,,161006192810,V,54.738791,25.271918,0,158,122,0,4235,0000,0,,246|1|65|96DB,9C5|0*69"));
+
+ verifyPosition(decoder, text(
+ "$$135,866104023192332,29,A01,,160606093046,A,22.546430,114.079730,0,186,181,0,415322,0000,02,2,460|0|27B3|EA7,A2F|3B9|3|0,940C7E,31.76|30.98*46"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/FlespiProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/FlespiProtocolDecoderTest.java
new file mode 100644
index 000000000..9e5a45a83
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/FlespiProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import io.netty.handler.codec.http.HttpMethod;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class FlespiProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ FlespiProtocolDecoder decoder = new FlespiProtocolDecoder(null);
+
+ verifyPositions(decoder, request(HttpMethod.POST, "/",
+ buffer("[{\"position.speed\":0,\"position.latitude\":53.90573,\"time.valid.status\":true,\"timestamp\":1506956075,\"position.satellites\":10,\"message.buffered.status\":false,\"business.mode.status\":true,\"gps.status\":true,\"position.longitude\":27.455848,\"position.direction\":0,\"ident\":\"605630\"},{\"siren.status\":false,\"business.mode.status\":true,\"position.satellites\":8,\"timestamp\":1506695785,\"led.status\":false,\"position.latitude\":53.905569,\"position.longitude\":27.455986,\"position.speed\":0,\"gradual.stop.status\":false,\"position.direction\":262.643854,\"hardware.version.enum\":223,\"vehicle.mileage\":160,\"message.buffered.status\":false,\"blinkers.status\":false,\"ident\":\"605630\",\"position.altitude\":233.48,\"immobilizer.status\":false}]")));
+
+ verifyPositions(decoder, request(HttpMethod.POST, "/",
+ buffer("[{\"geofence.inside.status\":false,\"position.valid\":false,\"ain#4\":0,\"rs232.sensor.value#1\":0,\"position.direction\":0,\"rs232.sensor.value#0\":0,\"position.speed\":0,\"position.latitude\":10.11223,\"refrigerator.sensor.temperature#1\":62.5,\"gnss.antenna.cut.status\":true,\"din\":3,\"ain#3\":0,\"refrigerator.sensor.temperature#3\":71.4,\"position.altitude\":0,\"shock.event.trigger\":false,\"alarm.mode.status\":false,\"ibutton.event.connect\":false,\"refrigerator.sensor.temperature#4\":66.7,\"internal.battery.voltage.limit.lower.status\":false,\"ain#2\":0,\"gsm.signal.level\":0,\"refrigerator.connection.status\":0,\"position.satellites\":0,\"external.powersource.voltage.range.outside.status\":false,\"refrigerator.sensor.temperature#2\":68.2,\"incline.event.trigger\":false,\"alarm.event.trigger\":false,\"movement.status\":true,\"refrigerator.sensor.temperature#6\":68.9,\"ident\":\"605630\",\"timestamp\":946684840,\"engine.ignition.status\":true,\"gsm.sim.status\":true,\"record.seqnum\":8165,\"external.powersource.voltage\":15.298,\"gnss.enum\":\"glonass\",\"position.longitude\":20.88774,\"battery.voltage\":4.088,\"refrigerator.sensor.temperature#5\":71.3,\"ain#1\":0,\"internal.bus.supply.voltage.range.outside.status\":false},{\"geofence.inside.status\":false,\"position.valid\":true,\"ain#4\":0,\"rs232.sensor.value#1\":0,\"position.direction\":0,\"rs232.sensor.value#0\":0,\"position.speed\":0,\"position.latitude\":57.986744,\"refrigerator.sensor.temperature#1\":74.1,\"gnss.antenna.cut.status\":false,\"ain#3\":0,\"position.hdop\":21.1,\"refrigerator.sensor.temperature#3\":71.4,\"position.altitude\":219,\"shock.event.trigger\":false,\"alarm.mode.status\":false,\"ibutton.event.connect\":false,\"refrigerator.sensor.temperature#4\":70.5,\"internal.battery.voltage.limit.lower.status\":false,\"ain#2\":0,\"gsm.signal.level\":0,\"refrigerator.connection.status\":0,\"position.satellites\":5,\"external.powersource.voltage.range.outside.status\":false,\"refrigerator.sensor.temperature#2\":71.3,\"incline.event.trigger\":false,\"alarm.event.trigger\":false,\"movement.status\":true,\"refrigerator.sensor.temperature#6\":69.3,\"ident\":\"605630\",\"timestamp\":1392272112,\"engine.ignition.status\":true,\"gsm.sim.status\":true,\"record.seqnum\":8174,\"external.powersource.voltage\":15.303,\"gnss.enum\":\"glonass\",\"position.longitude\":56.207576,\"battery.voltage\":3.934,\"refrigerator.sensor.temperature#5\":68.1,\"ain#1\":0,\"internal.bus.supply.voltage.range.outside.status\":false}]")));
+
+ verifyPositions(decoder, request(HttpMethod.POST, "/",
+ buffer("[{\"ain#1\":1,\"ain#2\":0,\"ain#3\":0,\"ain#4\":0,\"alarm.event.trigger\":true,\"custom.SOS\":1,\"custom.dparam\":3.141593,\"custom.ign\":1,\"custom.iparam\":-55,\"custom.tparam\":\"lorem\",\"din\":722,\"dout\":1048576,\"ident\":\"namo:namo\",\"position.altitude\":300,\"position.direction\":0,\"position.hdop\":1.1,\"position.latitude\":53.90821,\"position.longitude\":27.524165,\"position.satellites\":7,\"position.speed\":0,\"timestamp\":1508508510.013227}]")));
+ }
+
+} \ No newline at end of file
diff --git a/src/test/java/org/traccar/protocol/FlexCommProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/FlexCommProtocolDecoderTest.java
new file mode 100644
index 000000000..28ecaf646
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/FlexCommProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class FlexCommProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ FlexCommProtocolDecoder decoder = new FlexCommProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "7E00865067022408382201705302358271024932258006712785200700022601010224100040002C5002A2210001000000010012342107"));
+
+ verifyPosition(decoder, text(
+ "7E27865067022408382201705241211301024932197006712794000910022481008234100040002C5002A2200011000000006306941827"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/FlextrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/FlextrackProtocolDecoderTest.java
new file mode 100644
index 000000000..3f268fde9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/FlextrackProtocolDecoderTest.java
@@ -0,0 +1,32 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+
+public class FlextrackProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ FlextrackProtocolDecoder decoder = new FlextrackProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "-1,LOGON,7000000123,8945000000"));
+
+ verifyNull(decoder, text(
+ "-1,LOGON,1080424008,8945020110126633198"));
+
+ verifyPosition(decoder, text(
+ "-2,UNITSTAT,20060101,123442,1080424008,N0.00.0000,E0.00.0000,0,0,0,4129,-61,2,23866,0,999,A214,63,2EE2,3471676"));
+
+ verifyPosition(decoder, text(
+ "-2,UNITSTAT,20050205,181923,7000004634,N55.46.0812,E009.21.1665,122,198,6,3934,-81,01A8,23802,213,55,37FD,45,0055,12878"),
+ position("2005-02-05 18:19:23.000", true, 55.76802, 9.35278));
+
+ verifyPosition(decoder, text(
+ "-2,UNITSTAT,20050205,181923,7000004634,N55.46.0812,E009.21.1665,122,198,6,3934,-81,01A8,23802,213,55,37FD,45,0055,12878"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/FoxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/FoxProtocolDecoderTest.java
new file mode 100644
index 000000000..837b36b64
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/FoxProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class FoxProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ FoxProtocolDecoder decoder = new FoxProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "<fox><gps id=\"10\" data=\"51,A,010416,085317,4444.4158,N,02025.4466,E,1,182,,1110111111110111 141 0 0 0 0 0 10010000 10142,018C81851800009B\"/></fox>"));
+
+ verifyPosition(decoder, text(
+ "<fox><gps id=\"90\" data=\"1092,V,010101,000004,0000.0000,N,00000.0000,E,0,0,,1111111111111111 123 0 0 0 0 0 00000000 47664,47664\"/></fox>"));
+
+ verifyPosition(decoder, text(
+ "<fox><gps id=\"90\" data=\"31,V,110316,125952,0000.0000,N,00000.0000,E,0,0,,1111111111111111 123 0 0 0 0 0 00000000 47664,65 60 60 60 60 60 60 60 65 65 55 55 60 60 60 60 60 60 60 60 55 55 60 55 65 60 60 60 60 60 60 55\"/></fox>"));
+
+ verifyPosition(decoder, text(
+ "<fox><gps id=\"90\" data=\"0,V,110316,130154,0000.0000,N,00000.0000,E,0,0,,1111111111111111 123 0 0 0 0 0 00000000 47664,47664 0\"/></fox>"));
+
+ verifyPosition(decoder, text(
+ "<fox><gps id=\"90\" data=\"0,A,110316,131834,4448.8355,N,02028.2021,E,0,217,,1111111111111111 123 0 0 0 0 0 00000000 50020,50020 0\"/></fox>"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/FreedomProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/FreedomProtocolDecoderTest.java
new file mode 100644
index 000000000..b2fc1fd8d
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/FreedomProtocolDecoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class FreedomProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ FreedomProtocolDecoder decoder = new FreedomProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "IMEI,353358011714362,2014/05/22, 20:49:32, N, Lat:4725.9624, E, Lon:01912.5483, Spd:5.05"),
+ position("2014-05-22 20:49:32.000", true, 47.43271, 19.20914));
+
+ verifyPosition(decoder, text(
+ "IMEI,353358011714362,2014/05/22, 20:49:32, N, Lat:4725.9624, E, Lon:01912.5483, Spd:5.05"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/FreematicsProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/FreematicsProtocolDecoderTest.java
new file mode 100644
index 000000000..a84c4e357
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/FreematicsProtocolDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class FreematicsProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ FreematicsProtocolDecoder decoder = new FreematicsProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "1#EV=2,TS=1871902,ID=ESP32305C06C40A24*AC"));
+
+ verifyNull(decoder, text(
+ "0#EV=1,TS=23930,ID=ID1C6606C40A24,SK=TEST_SERVER_KEY*49"));
+
+ verifyPositions(decoder, text(
+ "1#0:102560,20:0;0;0,24:425,10:4285580,A:-35.803696,B:175.748413,C:0.22,D:0.41,F:5,0:103174,20:0;0;0,24:423,10:4285660,A:-35.803696,B:175.748413,C:0.22,D:0.41,F:5,30:88193792*21"));
+
+ verifyPositions(decoder, text(
+ "1#0:49244,20:0;0;0,24:423,0:50779,20:0;0;0,24:425,30:32924444*38"));
+
+ verifyNotNull(decoder, text(
+ "1#0:47607,20:0;0;0,24:423,0:48732,20:0;0;0,24:428,10:4280140,A:0.000000,B:0.000000,C:0.00,D:18520000.00,F:2,30:32924444*BA"));
+
+ verifyPositions(decoder, text(
+ "1#0:68338,10D:79,30:1010,105:199,10C:4375,104:56,111:62,20:0;-1;95,10:6454200,A:-32.727482,B:150.150301,C:159,D:0,F:5,24:1250*7A"));
+
+ verifyPositions(decoder, text(
+ "1#0=68338,10D=79,30=1010,105=199,10C=4375,104=56,111=62,20=0;-1;95,10=6454200,A=-32.727482,B=150.150301,C=159,D=0,F=5,24=1250*7A"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GalileoFrameDecoderTest.java b/src/test/java/org/traccar/protocol/GalileoFrameDecoderTest.java
new file mode 100644
index 000000000..4f4972895
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GalileoFrameDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class GalileoFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GalileoFrameDecoder decoder = new GalileoFrameDecoder();
+
+ assertEquals(
+ binary("011780011102e603383633353931303238393630323437043200801c"),
+ decoder.decode(null, null, binary("011780011102e603383633353931303238393630323437043200801c")));
+
+ assertEquals(
+ binary("01d48304320010020520a5829f58300f50dc8a024c0965013300000000344102350740003a41e14b426610431b4459fa672a4500004601a050364c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e293000000043200100105202d829f58300f50dc8a024c0965013300000000344102350740003a41d04b426110431b445702882a4500004601a050374c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29400000004320010000520b5819f58300f50dc8a024c0965013300000000344102350740003a419e4b426a10431c4456fab72a4500004601a050434c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010ff04203d819f58300f50dc8a024c0965013300000000344102350740003a41874b426310431c4454fe572a4500004601a050334c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29600000004320010fe0420c5809f58300f50dc8a024c0965013300000000344102350840003a41a24b426710431c4457fea72a4500004601a050214c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fd04204d809f58300f50dc8a024c0965013300000000344102350840003a41a34b426310431c4455f6772a4500004601a0502e4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29900000004320010fc0420d57f9f58300f50dc8a024c0965013300000000344102350840003a41bd4b426510431d4458fe672a4500004601a0501f4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fb04205d7f9f58300f50dc8a024c0965013300000000344102350840003a41b54b426310431d4456fa772a4500004601a0502d4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010fa0420e57e9f58300f50dc8a024c0965013300000000344102350840003a41b24b426210431e4454fa872a4500004601a050fe4b510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29000000004320010f904206d7e9f58300f50dc8a024c0965013300000000344102350a40003a41af4b426710431f4458fea72a4500004601a0500a4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e28900000067c5"),
+ decoder.decode(null, null, binary("01d48304320010020520a5829f58300f50dc8a024c0965013300000000344102350740003a41e14b426610431b4459fa672a4500004601a050364c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e293000000043200100105202d829f58300f50dc8a024c0965013300000000344102350740003a41d04b426110431b445702882a4500004601a050374c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29400000004320010000520b5819f58300f50dc8a024c0965013300000000344102350740003a419e4b426a10431c4456fab72a4500004601a050434c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010ff04203d819f58300f50dc8a024c0965013300000000344102350740003a41874b426310431c4454fe572a4500004601a050334c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29600000004320010fe0420c5809f58300f50dc8a024c0965013300000000344102350840003a41a24b426710431c4457fea72a4500004601a050214c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fd04204d809f58300f50dc8a024c0965013300000000344102350840003a41a34b426310431c4455f6772a4500004601a0502e4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29900000004320010fc0420d57f9f58300f50dc8a024c0965013300000000344102350840003a41bd4b426510431d4458fe672a4500004601a0501f4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fb04205d7f9f58300f50dc8a024c0965013300000000344102350840003a41b54b426310431d4456fa772a4500004601a0502d4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010fa0420e57e9f58300f50dc8a024c0965013300000000344102350840003a41b24b426210431e4454fa872a4500004601a050fe4b510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29000000004320010f904206d7e9f58300f50dc8a024c0965013300000000344102350a40003a41af4b426710431f4458fea72a4500004601a0500a4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e28900000067c5")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GalileoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GalileoProtocolDecoderTest.java
new file mode 100644
index 000000000..74612caab
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GalileoProtocolDecoderTest.java
@@ -0,0 +1,45 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GalileoProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GalileoProtocolDecoder decoder = new GalileoProtocolDecoder(null);
+
+ verifyPositions(decoder, binary(
+ "011801018202130338363833343530333230343234323604640010a406207caa9f5b300c830a7901ca0ec802330000000034b802350540003e41703f422b1043234504004600e09000000000a000a100a200a300a400a500a600a700a800a900aa00ab00ac00ad00ae00af00b00000b10000b20000b30000b40000b50000b60000b70000b80000b90000c000000000c100000000c200000000c300000000c400c500c600c700c800c900ca00cb00cc00cd00ce00cf00d000d100d200d4d3140000d60000d70000d80000d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f300000000f400000000f500000000f600000000f700000000f800000000f9000000008960"));
+
+ verifyPositions(decoder, binary(
+ "017583018202120338363833343530333230363635373304520010384520c850975b300cc03a910107cbf9023365000607341300350640012a41236a4215104329450400460020500000510000520000530000540000550000c000000000c100000000c44bc500c6ffc700c800c900ca00cb00d4993b0500d64100d70000d8be02d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f300000000018202120338363833343530333230363635373304520010394520c950975b300cab3a91010ecbf902336000be06341300350640012a41266a4216104329450400460020500000510000520000530000540000550000c000000000c100000000c44bc500c6ffc700c800c900ca00cb00d49b3b0500d64100d70000d8bc02d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f3000000000182021203383638333435303332303636353733045200103a4520ca50975b300c953a910113cbf9023358008f06341300350640012a41206a4215104329450400460020500000510000520000530000540000550000c000000000c100000000c44bc500c6ffc700c800c900ca00cb00d49e3b0500d64100d70000d8ba02d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f3000000000182021203383638333435303332303636353733045200103b45204251975b300c6d3a91011dcbf9023300008a06341300350640013a41726a4216104329450400460020500000510000520000530000540000550000c000000000c100000000c44bc500c6ffc700c800c900ca00cb00d4a33b0500d64800d70000d80003d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f3000000000182021203383638333435303332303636353733045200103c4520bb51975b300c6d3a91011dcbf9023300008a06341300350640013a41816a4216104329450400460020500000510000520000530000540000550000c000000000c100000000c44bc500c6ffc700c800c900ca00cb00d4a33b0500d64800d70000d80003d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f300000000e007"));
+
+ verifyNull(decoder, binary(
+ "07e10300ffd8ffe000114a464946000101010000000000000affe1011445786966000049492a000800000005000e010200140000004a0000000f0102000a0000005e000000100102000a0000006800000032010200130000007200000025880400010000008600000000000000494d45492033353336313230383730353035393247616c696c656f536b7971717a6d202020202020323031383a30383a30392030363a35393a303100060001000200020000004e0000000200050003000000d40000000300020002000000450000000400050003000000ec000000050001000100000000000000060005000100000004010000000000008e7f930240420f0000000000010000000000000001000000a11aaa0140420f00000000000100000000000000010000003300000001000000ffdb0084000d09090b09080d0b0a0b0e0d0d0f131f1413111113261b1d171f2d28302f2d282c2b3238483d323544362b2c3f553f444a4d505150303c585f584e5e484f504d010d0e0e131013251414254d342c344d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4dffc000110801e0028003012100021101031101ffdd0004000affc401a20000010501010101010100000000000000000102030405060708090a0b100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa0100030101010101010101010000000000000102030405060708090a0b1100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00f41237526768c119a0811803c8e29a7eb40075151ba9e2801436060d0df779ef408685c50092db6801e63c9c83834c772a3140c818163522924fa5310367b9a8f3ce2806382734e2bc7340c68031c52ab1e86811ffd0edcf0335170fd7b5333023151c83d4ba"));
+
+ verifyPositions(decoder, false, binary(
+ "01560003383636303530303338343337353836044701e000000000e13c494e414c4c3a696e303d31313230362c696e313d302c696e323d302c696e333d302c696e343d302c696e353d302c4163633d3536363932343732353bfdef"));
+
+ verifyPositions(decoder, false, binary(
+ "012a0003383633353931303233353137333732046600e000000000e1104f555428332e2e3029203d2031313130bb29"));
+
+ verifyPositions(decoder, binary(
+ "0144030338363832303430303132363939333404320010ee0f20f5a86c57300570172f03bc7dfd023363002604343e00351c40092a414a6842af0e432445000046030050246b51666a524c055300000338363832303430303132363939333404320010ed0f20f4a86c57300570172f03b47dfd023363000d05343e00351140090a41c56742a60e432445000046030050b56a514f6a521b045300000338363832303430303132363939333404320010ec0f20e6a86c57300b34172f03287efd023300000000344900350d40290a41562742030b43234500004603205023455190445295005300000338363832303430303132363939333404320010eb0f20e4a86c57300b34172f03287efd023300000000344900350d40290b41000042bd0b432345000046032050dc31518c315200005300000338363832303430303132363939333404320010ea0f20c7a86c57300b34172f03287efd023300000000344900350d40a90b41000042050d43234500004600205000005100005200005300000338363832303430303132363939333404320010e90f204fa86c57300b34172f03287efd023300000000344900350d40a90b41000042ff0c43244500004600205000005100005200005300000338363832303430303132363939333404320010e80f20d7a76c57300b34172f03287efd023300000000344900350d40a90b41000042fd0c43244500004600205000005100005200005300000338363832303430303132363939333404320010e70f205fa76c57300b34172f03287efd023300000000344900350d40a90b41000042fd0c43254500004600205000005100005200005300000338363832303430303132363939333404320010e60f20e7a66c57300b34172f03287efd023300000000344900350d40a90b41000042fd0c43264500004600205000005100005200005300000338363832303430303132363939333404320010e50f206fa66c57300468172f03907cfd023300007a0a343600352b40a90b41000042030d43274500004600205000005100005200005300000338363832303430303132363939333404320010e40f2051a66c5730048c172f03ac7cfd02335300980a341600352b40a12b41000042040d43274500004600e0500000510000520000530000abde"));
+
+ verifyNull(decoder, binary(
+ "011380033836383230343030313534393038370432008590"));
+
+ verifyPositions(decoder, binary(
+ "01cf030446ba10630320a7054c533008f86c8e0310062c043347049e02344000350940013241506b428f10432244aeea572045f9004604a0500000510000529a6b5300000446ba10712420ce1c4b533009b4f06703043df4033381037b0a343800350a40093241db6b428f10432544c05ef81f45f9004604a050000051000052886b5300000446ba10702420c11c4b53300a54f16703c450f403336e034e0a343900350840093241dd6b428f1043254491eaf71f45f9004604a050000051000052c26b5300000446ba106f2420b31c4b53300cecf267033865f403336a03300a343800350740093241e66b429010432544b446582045f9004604a050000051000052f76b5300000446ba106e2420a61c4b53300c9cf467038878f403337b03370a343800350740093241b56b428f10432544ba46f81f45f9004604a050000051000052c66b5300000446ba106d2420991c4b53300bc8f56703508cf403338d036e0a343700350840093241d66b428f10432544b4ea572045f9004604a050000051000052846b5300000446ba106c24208c1c4b533008c8f5670370a0f403338703920a343a00350e40093241c76b428f10432544c0fef71f45f9004604a0500000510000528d6b5300000446ba106b24207f1c4b533009a4f5670338b4f403337603920a343c00350a40093241d06b428f104325449146a81f45f9004604a0500000510000528a6b5300000446ba106a2420721c4b53300b9cf56703ecc7f403337103810a343a00350840093241ca6b428f10432544d12e582045f9004604a050000051000052996b5300000446ba10692420651c4b53300a64f6670358dbf403337a03490a343900350840093241e56b429010432544aed2f71f45f9004604a050000051000052b26b5300000446ba10682420581c4b5330094cf86703e0eef4033381030c0a343a00350940093241f96b428f10432544cb2e182145f9004604a050000051000052926b5300000446ba106724204b1c4b533009f8fa67032802f503337b03fc09343b00350a40093241d86b428f10432544c0ea772145f9004604a0500000510000529e6b5300000446ba106624203e1c4b533009a0fd67036815f503338403fd09343c00350a40093241a86b428f10432544ae2e582045f9004604a050000051000052a86b5300000446ba10652420311c4b53300944006803b028f503338003ff09343d00350940093241dc6b428e10432544a8fea71f45f9004604a050000051000052e26b5300000446ba10642420241c4b533008f0026803083cf503338b03f909343c00350d40093241d36b428f10432544c0eaa71f45f9004604a050000051000052ab6b530000ff3f"));
+
+ verifyPositions(decoder, binary(
+ "011e8304320010270220dbd2f051300a90cf740328ac59033300000000347600351240012a41e92e42500f431f440006c814450f00460020500000510000520000530000540000550000560000570000580000600000610000620000a000a100a200a300a400a500a600a700a800a900aa00ab00ac00ad00ae00af00b00000b10000b20000b30000b40000b50000b60000b70000b80000b90000c000000000c100000000c200000000c300000000c400c500c600c700c800c900ca00cb00cc00cd00ce00cf00d000d100d200d471020000d60000d70000d80000d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f30000000004320010260220bdd2f051300590cf740328ac59033300000000347600351440090a41f02e427b0f431f44ff0db814450f00460000500000510000520000530000540000550000560000570000580000600000610000620000a000a100a200a300a400a500a600a700a800a900aa00ab00ac00ad00ae00af00b00000b10000b20000b30000b40000b50000b60000b70000b80000b90000c000000000c100000000c200000000c300000000c400c500c600c700c800c900ca00cb00cc00cd00ce00cf00d000d100d200d471020000d60000d70000d80000d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f300000000043200102502208ed2f051300ed8d0740304ac5903330000000034a500350a40012a41ec2e422d0f431f440016b814450f00460020500000510000520000530000540000550000560000570000580000600000610000620000a000a100a200a300a400a500a600a700a800a900aa00ab00ac00ad00ae00af00b00000b10000b20000b30000b40000b50000b60000b70000b80000b90000c000000000c100000000c200000000c300000000c400c500c600c700c800c900ca00cb00cc00cd00ce00cf00d000d100d200d44d020000d60000d70000d80000d90000da0000db00000000dc00000000dd00000000de00000000df00000000f000000000f100000000f200000000f300000000622e"));
+
+ verifyPositions(decoder, binary(
+ "01d48304320010020520a5829f58300f50dc8a024c0965013300000000344102350740003a41e14b426610431b4459fa672a4500004601a050364c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e293000000043200100105202d829f58300f50dc8a024c0965013300000000344102350740003a41d04b426110431b445702882a4500004601a050374c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29400000004320010000520b5819f58300f50dc8a024c0965013300000000344102350740003a419e4b426a10431c4456fab72a4500004601a050434c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010ff04203d819f58300f50dc8a024c0965013300000000344102350740003a41874b426310431c4454fe572a4500004601a050334c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29600000004320010fe0420c5809f58300f50dc8a024c0965013300000000344102350840003a41a24b426710431c4457fea72a4500004601a050214c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fd04204d809f58300f50dc8a024c0965013300000000344102350840003a41a34b426310431c4455f6772a4500004601a0502e4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29900000004320010fc0420d57f9f58300f50dc8a024c0965013300000000344102350840003a41bd4b426510431d4458fe672a4500004601a0501f4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29700000004320010fb04205d7f9f58300f50dc8a024c0965013300000000344102350840003a41b54b426310431d4456fa772a4500004601a0502d4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29500000004320010fa0420e57e9f58300f50dc8a024c0965013300000000344102350840003a41b24b426210431e4454fa872a4500004601a050fe4b510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e29000000004320010f904206d7e9f58300f50dc8a024c0965013300000000344102350a40003a41af4b426710431f4458fea72a4500004601a0500a4c510000520000530000c000000000c100000000c200000000c300000000d80000dd00000000e28900000067c5"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GalileoProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/GalileoProtocolEncoderTest.java
new file mode 100644
index 000000000..34423578d
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GalileoProtocolEncoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class GalileoProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ GalileoProtocolEncoder encoder = new GalileoProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "status");
+
+ verifyCommand(encoder, command, binary("01200003313233343536373839303132333435040000e000000000e1067374617475731f64"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GatorProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GatorProtocolDecoderTest.java
new file mode 100644
index 000000000..e2be99cb9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GatorProtocolDecoderTest.java
@@ -0,0 +1,50 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class GatorProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecodeId() {
+
+ assertEquals("3512345006", GatorProtocolDecoder.decodeId(12, 162, 50, 134));
+
+ }
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GatorProtocolDecoder decoder = new GatorProtocolDecoder(null);
+
+ verifyAttributes(decoder, binary(
+ "2424800026364101b31608041108380273453415301532000000008000010000122800000124000000c40d"));
+
+ verifyNull(decoder, binary(
+ "242421000658e3d851150d"));
+
+ verifyAttributes(decoder, binary(
+ "242480002658e3d851a60101c662bc00000000000000000000000000470007a30b0c00b10fc900ff00460d"));
+
+ verifyNull(decoder, binary(
+ "242421000643e30282070d"));
+
+ verifyPosition(decoder, binary(
+ "24248000260009632d141121072702059226180104367500000000c04700079c0c34000ad80b00ff000a0d"),
+ position("2014-11-21 07:27:02.000", true, 59.37697, 10.72792));
+
+ verifyPosition(decoder, binary(
+ "24248100230CA23285100306145907022346901135294700000000C04001012C0E1100000021CB0D"));
+
+ verifyPosition(decoder, binary(
+ "2424800023c2631e00111220104909833268648703804100000000c0470000000b4e00000000550d"),
+ position("2011-12-20 10:49:09.000", true, -33.44773, -70.63402));
+
+ verifyPosition(decoder, binary(
+ "24248000260009632d141121072702059226180104367500000000c04700079c0c34000ad80b00ff000a0d"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GenxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GenxProtocolDecoderTest.java
new file mode 100644
index 000000000..373c8c49e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GenxProtocolDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GenxProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GenxProtocolDecoder decoder = new GenxProtocolDecoder(null);
+
+ decoder.setReportColumns("28,2,3,4,13,17,10,23,27,11,7,8,46,56,59,70,74,75,77,89,90,93,99,107,112,113,114,176,175,178,181,182");
+
+ verifyPosition(decoder, text(
+ "000036004133,11/05/2017 00:03:45,45.54767,-73.75547,0,0,63,569.35,118,ON,10687,0,12,O,9,3669.000,95.0,0.0,1,107.9464,0.0065,583.752,43,0.00,28.26,7.60,NA,U,UUU,0,-95.0,U"));
+
+ decoder.setReportColumns("1,2,3,4");
+
+ verifyPosition(decoder, text(
+ "000036004130,08/31/2017 17:24:13,45.47275,-73.65491,5,19,117,1.14,147,ON,1462,0,6,N,0,0.000,-95.0,-1.0,0,0.0000,0.0000,0.000,0,0.00,0.00,0.00,NA,U,UUU,0,-95.0,U"));
+
+ verifyPosition(decoder, text(
+ "000036004130,08/31/2017 17:24:37,45.47257,-73.65506,3,0,117,1.14,124,ON,1489,0,5,N,0,0.000,-95.0,-1.0,0,0.0000,0.0000,0.000,0,0.00,0.00,0.00,NA,U,UUU,0,-95.0,U"));
+
+ decoder.setReportColumns("1,2,3,4,13,17,10,23,27,11,7,8,46,56,59,70,74,75,77,89,90,93,99,107,112,113,114,176,175,178,181,182");
+
+ verifyPosition(decoder, text(
+ "000036035855,04/16/2017 21:19:07,45.46485,-73.65424,24,32,61:213,342.51,157,ON,20984,0,12,O,18,0.000,95.0,24.0,1990,64.0894,0.0219,316.009,71,0.00,16.78,5.10,NA,U,UUU,0,-95.0,U"));
+
+ verifyPosition(decoder, text(
+ "000036004129,10/20/2017 00:54:27,43.44638,-79.68616,36,310,6,4954.40,321,ON,35377,0,12,O,13,0.000,85.6,36.0,1573,451.2514,0.0012,5260.953,0,0.00,122.48,33.17,NA,U,UUU,0,-95.0,U"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gl100ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gl100ProtocolDecoderTest.java
new file mode 100644
index 000000000..ffafcd7b1
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gl100ProtocolDecoderTest.java
@@ -0,0 +1,56 @@
+package org.traccar.protocol;
+
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Gl100ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gl100ProtocolDecoder decoder = new Gl100ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "+RESP:GTLGL,359464030492644,1,2,1,0,0.4,0,299.7,1,5.455551,51.449776,20160311083229,0204,0016,03EC,BD94,00,0036,0102090501"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTTRI,359464030439249,1,0,61,1,0.0,346,-2.7,2,-80.392825,26.122424,20151214000354,0310,0260,72BC,35F5,00,04B6,0102070407"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTTRI,135790246811220,1,0,0,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,11F0,0102070202"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTTRI,135790246811220,2,0,0,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,1,-3.6,145,30.0,2,121.354442,31.221940,20090101000100,0460,0000,18d8,6141,00,11F0,0102070202"));
+
+ verifyNull(decoder, text(
+ "AT+GTHBD=HeartBeat,359231030000010,20090101000000,11F0,0102120204"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTSOS,359231030000010,0,0,0,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,11F0,0102120204"),
+ position("2009-01-01 00:00:00.000", false, 31.22207, 121.35434));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTRTL,359231030000010,0,0,0,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,11F0,0102120204"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTEST,359231030000010,0,0,0,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,11F0,0102120204"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTSZI,359231030000010,0,3,0,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,11F0,0102120204"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTLBC,359231030000010,02132523415,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,11F0,0102120204"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTTRI,359231030000010,1,0,0,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,11F0,0102120204"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTTRI,359231030000010,2,0,0,1,4.3,92,70.0,1,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,0,0,1,-3.6,145,30.0,2,121.354442,31.221940,20090101000100,0460,0000,18d8,6141,00,11F0,0102120204"));
+
+ verifyPosition(decoder, text(
+ "+RESP:GTTRI,359464030073766,1,0,0,0,1.7,254,-27.8,3,30.474475,50.488383,20131107155511,0255,0003,6995,4761,00,0071,0103090402"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gl200BinaryProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gl200BinaryProtocolDecoderTest.java
new file mode 100644
index 000000000..e6fb98340
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gl200BinaryProtocolDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Gl200BinaryProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gl200BinaryProtocolDecoder decoder = new Gl200BinaryProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "2b4556542d00fc1fbf0063450102020956325403000343056437f8220700000200000000010000160100f2007eff75a1f0025c6b1a07e1080108241a02680003189c1ac500000000000002100800000000000000000007e1080108241a19e24e4e0d0a"));
+
+ verifyPositions(decoder, binary(
+ "2b5253506400fc1fbf058e450102020956325403000343056438ed2205010e61c6f0ff75a1b4025c6af959803d8ba07ffe17dea03f7e1fdda0007df7dfa03e7e3fd0a0befdf7cea001fddfd8a000fdefdca042fd9fe1a0427d6fe9a0017db7dca0407d47e7a0027d67e5bfc0fd77eca03ffd8fe4bfff7dcfddbffd7dbfdebffdfddfe2bfbe7e0fe1bf7f7e67e2bf7bfed7e2bf7c7f5fe2bffbffc7e3a12880a7daa0b9013fe3a0f801b7dfa0bd81efe1a03f8207e0a03e8217e4a07e023fe9a0bd824feca03a02affda07b02d004a07f02e007a00002d808a041830001a003834fefa00402b7eebf8382a7ebbfc28267e9bf81821fe3bf0181d7e3bf01016fe9bf010117edbf4080c7f6bf7f8087fabfbf805ff9a0fa8097fca23401300aa0b4016019a13a817026a13b81883ea0be81a83fa0bd81b03ba00101d83abfc0039874bfc081b835bfbf819834bfc081982fa01004702ea00502500da002827802bfc0825fffbf41821fffbf4081d801bf3f816802bec180fffebec20077fdbf80002801bfc0000800a000000800e0e0a202804ffba14a8127eea0460107e4a0cc809fd9a0c4004fcda0c2004fcaa080007fbfa0410067bebfc100c7b6a03f8037c1bfbf004fc6a03f0057c6a0410027c5a081001fbaa0418017baa001001fb8a0007fe7bca000ffdfb7a0817fc7b7a040ffbfb3a0407fb7b4a0407fb7b1bf807fbfb3a0007fb7b5a0007fb7b1a0007fb7b2a0007fbfb3a0407fafaba000ffb7ada0017f97aba040ff7faca001ff77b6bf3fff67b3bf007f87bea082ff47b4bfc27f17c1bfffff3fc2bebdff9fcabe3effbfe0bf3cff47e9a03c002ff0a1740097e9a1f8813fe1a12f01f7fca0fa028ff8a07f02a7fea041829007a00302bff8bf810287f2a0080257e1a0050207dbbfc481cfd3a044819fcda043015fc3a043810fc2a0c680a7b2a0448027b0a0857fa7aea0c37f67a2a0017ee7a7a0407f0f9fa000ff079fa03ffeffa1a03ffeffa2a07fff17a0a03fff1fa0a03fff2fa2a03fff3fa0a07fff47a2a0007f579fa03fff4f9da03fff679ca0007f679ea000ff4f9ca07fff5f9ca0007f579cbfc07f5f9fbf407f6fa6bf807f6fabbfc07f7fadbf807f87b2a0407f87b0a0407f77aba000ff77afbfc07f77aea03fff7fada07fff7faca000ff7fada0007f77abbfc0ff77b0a000ff7faea042ff2faba0037ee7ada0437e57a1a0037e27abbfc1fdf7bcbf827defc5bf01fe0fcebf017e3fd5bfc17e2fdca0ff7e27d7a13cfe27cba0bd7e0fa7a07d7e6fb9a07d7eb7b3a07efedfaea03ffef7afa0c07eefa7a07f7f07a3a03fff0fa3a03f7f27a2a03f7f37a4bfff7f6fa3bfff7f5fa3a07eff979fa03f7fbfa2a03f7fdfa1bfbf8017a5bfbf0037adbeff004fb8bfbf004fc1beff804fcbbf7f8047d5bf408027debf408007e8a03e804fdebf7e8027f2bf00ffefffa0400017efa0418017f1a041002feca0410017edbf007fbffea0007fdff6a1018027e4bf81ffc7f6a1008017dca0c10087bea0018097baa083ffc7cda0837fafc7a102ff0fc8a0c27effb9a0c2fe87c1a143fbf78ea07f7dcfc0a0bd7dffb3a03d7e47b1a03ffe77afa07ffe77ada0007e77aebfc07e77afbfc07e8faea03ffea7afbfbf7ecfb4bfbcfeffbbbf7bff8fb8bf7d0027bebffb809fc7bffa00ffc9bf78813fd9a03d8197e1a03b81d7e6a07e01efdda00081bfdda00101bfdba03f81a7dfbfc001afdbbfbd81a7f1bfbe0187eebf80814feea0028127e7a081813fe2a0010147e6a03e8147f4a0408167eca040817fe7a0018157e4bfc8011fdaa08b002fd1a009ffa7d5a009fe57f6a04b7df7f4a0097e07eca0027df7edbf807e2feca000fe3feca07ffe37f0a0407e0ff7a040fde7f0a0007de7eea000fdcff4a001fddffaa000fdcff8a0027dcffda07f7dbff3a03f7dc7f402680003189c355300000109000002120700000000000000000007e1080108290019e63b5c0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "2B5253500300FC1FFF0064450102020867623130302D446F642F442105007018217345005F010100000001100045073C4D4101DB86BD07E106130B2B0F0460000018770013000000030000000106020F2300002714301107E106130B2B1003424EFB0D0A"));
+
+ verifyPositions(decoder, binary(
+ "2b5253500700fc1fbf005d4501020209563254030003430564377e42071001000000000000007eff75a151025c6a8107e10801081a2a02680003189c1ac500000000000002100700000000000000000007e1080108241019e17ebe0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "2b494e4601fd7f0076676231303000000045010202090104020500004100054007e107150b061d0000003f010e02580000000000d0312a1013648935103226313921591f1200000000000302680003189c1ac3001b02680003189c1ac4000d02680003189c1ac5001207e107150b0d3704f658060d0a"));
+
+ verifyPosition(decoder, binary(
+ "2b4556540c00fc1fbf005c4501010108563254030003430564312a41090100000000003f007dff75a11a025c6a7807e1070a14041202680003189c1ac500000000000000000000000000000000000007e1070b041134054e5c6e0d0a"));
+
+ verifyNull(decoder, binary(
+ "2b41434b017f244501010108676231303000000000ffff07e1070b03112d054dfe030d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gl200FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Gl200FrameDecoderTest.java
new file mode 100644
index 000000000..e90c6495a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gl200FrameDecoderTest.java
@@ -0,0 +1,29 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class Gl200FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gl200FrameDecoder decoder = new Gl200FrameDecoder();
+
+ assertEquals(
+ binary("2b41434b017f244501010108676231303000000000ffff07e1070b03112d054dfe030d0a"),
+ decoder.decode(null, null, binary("2b41434b017f244501010108676231303000000000ffff07e1070b03112d054dfe030d0a")));
+
+ assertEquals(
+ binary("2b4556540c00fc1fbf005c4501010108563254030003430564312a41090100000000003f007dff75a11a025c6a7807e1070a14041202680003189c1ac500000000000000000000000000000000000007e1070b041134054e5c6e0d0a"),
+ decoder.decode(null, null, binary("2b4556540c00fc1fbf005c4501010108563254030003430564312a41090100000000003f007dff75a11a025c6a7807e1070a14041202680003189c1ac500000000000000000000000000000000000007e1070b041134054e5c6e0d0a")));
+
+ assertEquals(
+ binary("2b524553503a47545354522c3430303330302c3836323336353033303134323238392c474c3530302c302c302c302c33392e342c39332c312c302e332c31372c3130352e382c32352e3934343234302c34342e3430333733362c32303137303532393134303533302c303232362c303030312c353643322c373038342c2c2c2c32303137303532393136303533302c30324441"),
+ decoder.decode(null, null, binary("2b524553503a47545354522c3430303330302c3836323336353033303134323238392c474c3530302c302c302c302c33392e342c39332c312c302e332c31372c3130352e382c32352e3934343234302c34342e3430333733362c32303137303532393134303533302c303232362c303030312c353643322c373038342c2c2c2c32303137303532393136303533302c3032444124")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gl200TextProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gl200TextProtocolDecoderTest.java
new file mode 100644
index 000000000..2fe860573
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gl200TextProtocolDecoderTest.java
@@ -0,0 +1,390 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class Gl200TextProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gl200TextProtocolDecoder decoder = new Gl200TextProtocolDecoder(null);
+
+ verifyAttribute(decoder, buffer(
+ "+RESP:GTPFA,F50201,866425030235982,GL300M,20190208124849,0BD4$"),
+ Position.KEY_ALARM, Position.ALARM_POWER_OFF);
+
+ verifyAttribute(decoder, buffer(
+ "+RESP:GTPNA,F50201,866425030235982,GL300M,20190208124909,0BD5$"),
+ Position.KEY_ALARM, Position.ALARM_POWER_ON);
+
+ verifyAttributes(decoder, buffer(
+ "+BUFF:GTSTC,410301,864802030022424,,,0,,,,,,,0228,0002,4EE8,1BFF489,00,20181207134332,EC90$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,1A0900,860599000306845,G3-313,0,0,4,1,2.1,0,426.7,8.611466,47.681639,20181214134603,0228,0001,077F,4812,25.2,1,5.7,34,437.3,8.611600,47.681846,20181214134619,0228,0001,077F,4812,25.2,1,4.4,62,438.2,8.611893,47.681983,20181214134633,0228,0001,077F,4812,25.2,1,4.8,78,436.6,8.612236,47.682040,20181214134648,0228,0001,077F,4812,25.2,83,20181214134702,0654$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTCAN,270703,867162025056839,gv300w,0,1,E07FFFFF,,2,H9307659,368713.50,1291,90,91,,P82.40,,61,10.10,6.76,3.34,524.08,,,0000,,00,,,007FFFFF,,,,,,,,,,,,,,,,,,,,,0000,2,0,,,0,88.6,104,117.6,-116.886007,32.543697,20181031202959,0334,0020,5234,7FCC3D0,00,20181031203002,9F50$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,310701,863286023712855,,00000004,28378,10,1,1,0.0,294,358.4,14.271475,50.110771,20181111185001,0230,0003,94D4,3B30,00,14.5,,,,110000,2,0,C03FFFFF,,0,H46400,12310.70,0,0,83,,,,0,,0.53,3.43,,,,40,,0,,,20181111185252,2DFF"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTCAN,310701,863286023712855,,10,0,003FFFFF,,2,H46358,12305.50,601,0,83,,P53.00,,0,2749.15,0.19,2.80,,,,40,,0,,,20181110103016,2945$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTCAN,310701,863286023712855,,10,0,203FFFFF,,2,H46358,12305.50,601,0,83,,P53.00,,0,2749.15,0.19,2.80,,,,40,,0,,,007FFFFF,,,,,,0,,,134,37,6,0.19,,0.00,0,,,,,,0,0,0,20181110112126,299F$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTCAN,310701,863286023712855,,10,0,E03FFFFF,,2,H46358,12305.50,601,0,83,,P53.00,,0,2749.15,0.19,2.80,,,,40,,0,,,007FFFFF,,,,,,0,,,134,37,6,0.19,,0.00,0,,,,,,0,0,0,0,0.0,312,358.4,14.271460,50.110796,20181110103130,0230,0003,94D4,3B30,00,20181110105348,2969$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,1F0301,862193022001432,WF0GXXGBBGBM26503,,14900,41,1,1,11.6,74,356.0,14.120023,50.167894,20181104080703,0230,0003,9B14,5891,00,74.1,,,,83,220000,799,7.3,,20181104080703,099B$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTCAN,4B0201,867995030001575,,10,0,C03FFFFF,,0,H0,,,,,,,,,,0.00,0.03,,,,0,,0,,,0,10.0,310,404.3,14.096743,50.143363,20181102110535,0230,0003,9B14,5066,00,20181102112101,03E0$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTSTR,440502,866427030112088,GL530,0,0,2,,100,3,0.6,0,127.5,2.413963,48.877096,20180704180102,0208,0001,0310,E625,,,0000,20180704180100,004C$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTLSW,300500,860599002636595,,0,0,0,0.0,0,2886.5,-78.467145,-0.165335,20180518221815,,,,,,20180518221817,B6FD$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTLSW,300500,860599002636595,,0,1,0,0.0,0,2886.5,-78.467145,-0.165335,20180518221818,,,,,,20180518221819,B6FF$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTTSW,1A0100,135790246811220,,1,0,0,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,20100214093254,11F0$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTLSW,1A0100,135790246811220,,0,1,0,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,20100214093254,11F0$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTIGF,270302,867162025085234,,3519,0,0.0,92,111.2,-116.867638,32.450321,20180327070835,0334,0020,2B24,52CC3DE,00,,243.1,20180327070837,2A98$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTDIS,270302,867162025086950,,,21,1,1,0.0,81,117.8,-116.862025,32.453497,20180309084516,0334,0020,2B24,52CA916,00,1286.2,20180309084517,357E$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTIGL,270302,867162025085234,,,01,1,1,0.0,92,111.2,-116.867638,32.450321,20180327070838,0334,0020,2B24,52CC3DE,00,243.1,20180327070839,2A9A$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,310603,863286023345490,,00000002,,10,1,2,0.3,0,155.7,8.000000,52.000000,20171215213040,0262,0002,1450,9F13,00,1130.3,00539:27:19,,,110000,2,1,28FFD5239115034E,1,,20171215213041,27C7$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,250C02,868789023691057,,00000019,,10,1,1,0.0,196,2258.0,-99.201807,19.559242,20180214002957,0334,0003,235B,7F8D,00,6786.7,,,,100,110000,1,0394,1,4,100.0,100.0,20180214003006,C72B$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTCAN,310603,863286023335723,gv65,00,1,C03FFFFF,,0,,719601.00,,,,,,,,274.99,179.02,95.98,84761.00,,,0,,0,,,0,0.0,216,29.8,-2.155296,51.899400,20180209172714,0234,0010,53F3,8D38,00,20180211002128,E94E$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTCAN,310201,153759012347650,gv65,0,1,C03FFFFF,,2,H89394,63.14,200,0,87,,P43.60,0,0,17.53,11.61,5.92,0.00,0,0,4002,0,1,0.76,35.00,0,,,,0,0,,0000,0000,0000,0000,00,20040101000052,05A6$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTCAN,310603,863286023346480,gv65,00,1,C03FFFFF,,2,H2843820,373.76,1440,44,77,M23,P35.00,1810,,59.48,42.68,16.80,15.42,,,610,,0,,,0,42.7,263,27.2,-2.156478,51.899989,20171021151805,0234,0010,15D6,9AD2,00,20171021151807,0B28$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTCAN,310603,863286023346480,gv65,02,1,C03FFFFF,,0,H2843820,373.80,0,4,75,M12,,1800,,59.49,42.69,16.80,15.42,,,0,,0,,,0,0.7,75,24.3,-2.155148,51.899400,20171021151837,0234,0010,15D6,9AD2,00,20171021152355,0B2E$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,380603,869606020025833,gv65,00000002,12003,10,1,1,0.0,172,24.6,-81.931875,26.577439,20171002045352,0310,0260,72BD,8E5B,00,1052.1,01383:52:12,0,100,210700,2,1,28FF4560A3150483,1,05B0,20171002045402,9548$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,04040E,861074023747143,gv200,41,8959301000648637556f,24,0,1,0,1,4.4,0,1,0,0,20170912221854,0,00,01,-0500,1,20170912193448,1D5B$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,210102,354524044950583,,42,89011702272048900184,11,99,0,,,4.08,0,1,1,0,0,20170831170831,87,0.00,,,,20170831171010,0064$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTOBD,360701,864251020253807,LSGTC58UX7Y067312,GV500,0,70FFFF,LSGTC58UX7Y067312,1,12309,983A8140,0,0,33,nan,,0,0,0,,10,0,,0,4.4,0,83.7,36.235142,49.967324,20170829112348,0255,0001,2760,9017,00,690.1,20170829112400,3456$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,060502,861074023620928,,00000002,27822,10,1,1,0.0,84,2870.9,-78.531796,-0.277329,20170825045344,,,,,,0.0,01138:30:24,,,83,220104,2,1,28FF2776A2150308,1,FFAD,0,20170825045348,A88C$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,280500,A1000043D20139,GL300VC,41,,31,0,0,,,3.87,0,1,1,,,20170802150751,70,,48.0,,,20170802112145,03AC$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,2D0300,A1000043D20139,1G1JC5444R7252367,,11,,31,0,1,12986,,4.16,0,2,,,20170802145640,,,,,,+0000,0,20170802145643,CD5A$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTMPN,450102,865084030001323,gb100,0,1.6,0,-93.1,121.393023,31.164105,20170619103113,0460,0000,1806,2142,00,20170619103143,0512$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTTRI,862370030005908,1,0,99,1,0.0,354,18.5,18.821100,-34.084002,20170607152024,0655,0001,00DD,1CAE,00,0103010100,20170607172115,3E7D$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,060800,861074023677175,,00000002,12351,10,1,1,0.0,0,2862.4,-78.467273,-0.164998,20170529181717,,,,,,0.0,00259:11:50,,,0,210104,2,1,28E17436060000E2,1,015F,0,20170529181723,2824$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTSWG,110100,358688000000158,,1,0,2.1,0,27.1,121.390717,31.164424,20110901073917,0460,0000,1878,0873,,20110901154653,0015$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTTMP,110100,358688000000158,,2,60,1,1,4.3,92,70.0,121.354335,31.222073,20110214013254,0460,0000,18d8,6141,00,80,20110214093254,000F$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTSTT,110100,358688000000158,,41,0,4.3,92,70.0,121.354335,31.222073,20110214013254,0460,0000,18d8,6141,,20110214093254,0022$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTBPL,110100,358688000000158,,3.53,0,4.3,92,70.0,121.354335,31.222073,20110214013254,0460,0000,18d8,6141,,20110214093254,001F$"));
+
+ verifyNotNull(decoder, buffer(
+ "+BUFF:GTIGL,060228,862894020180553,,,00,1,1,3.4,199,409.6,-63.174466,-17.739317,20170407121823,0000,0000,0000,0000,00,15989.5,20170407081824,9606$"));
+
+ verifyNotNull(decoder, buffer(
+ "+RESP:GTFRI,060228,862894020180553,,14827,10,1,1,3.4,199,409.6,-63.174466,-17.739317,20170407121823,0000,0000,0000,0000,00,15989.5,01070:43:13,13,180,0,220101,,,,20170407081824,9607$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,060502,861074023376992,,00000002,27239,10,1,1,0.2,312,183.3,-79.320820,-2.499110,20170401212005,0740,0000,EE4E,C98F,00,0.0,02114:36:35,,,90,220504,2,0,0,20170401212007,9E3D$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,060502,861074023689626,,25202,10,1,1,0.0,0,2744.1,-78.261047,0.023452,20170401211940,,,,,,0.0,00079:19:15,,,51,110000,,,,20170401212003,4DA7$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,060100,135790246811220,,,00,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,2000.0,12345:12:34,,,80,210100,,,,20090214093254,11F0$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,06020B,862170010196747,,00000000,,10,1,2,1.8,0,-2.5,117.198440,31.845219,20120802061037,0460,0000,5663,0358,00,0.0,,,,0,410000,20120802061040,0012$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTERI,060502,861074023692562,,00000002,14197,10,1,1,0.2,220,491.8,-79.064212,-2.159754,20170401212007,0740,0000,EE49,CE25,00,0.0,01509:10:58,,,87,220104,2,0,0,20170401212010,D14D$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,210102,354524044925825,,1,1,1,29,2.8,0,133.7,-90.203063,32.265473,20170318005208,,,,,10800,4,20170318005208,0002$"));
+
+ verifyPositions(decoder, false, buffer(
+ "+RESP:GTFRI,210102,354524044925825,,1,1,1,,,,,,,,310,410,51bc,ca1dae6,10800,1,20170318214333,0002$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTGSM,400201,862365030025161,STR,0234,0015,003a,62a2,16,,0234,0015,003a,56a2,14,,0234,0015,003a,062a,13,,0234,0015,003a,32d9,11,,0234,0015,003a,56a0,11,,,,,,,,0234,0015,003a,7489,17,,20170219200048,0033$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTGSM,400201,862365030025161,STR,0234,0015,003a,56a2,18,,0234,0015,003a,77bc,14,,0234,0015,003a,32d9,12,,0234,0015,003a,062a,12,,0234,0015,003a,62a2,11,,0234,0015,003a,56a0,10,,0234,0015,003a,7489,15,,20170219080049,0030$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTGSM,400201,862365030034940,STR,0234,0030,0870,2469,19,,0234,0030,0870,35ee,18,,0234,0030,0870,16ac,12,,0234,0030,0870,16b2,11,,0234,0030,0870,360f,6,,0234,0030,0870,165d,6,,0234,0030,0870,35ef,17,,20170215220049,008D$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTSTR,400201,862365030034940,GL500,0,0,2,21.1,86,0,1.6,0,5.8,0.622831,51.582688,20170215090422,0234,0030,0870,35EF,,,,20170215220049,008C$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,2C0402,867162020000816,,0,0,1,2,0.3,337,245.7,-82.373387,34.634011,20170215003054,,,,,,63,20170215003241,3EAB$"));
+
+ verifyNotNull(decoder, buffer(
+ "+RESP:GTWIF,210102,354524044608058,,4,c413e200ff14,-39,,,,c413e2010e55,-39,,,,c8d3ff04a837,-43,,,,42490f997c6d,-57,,,,,,,,100,20170201020055,0001$"));
+
+ verifyNotNull(decoder, buffer(
+ "+RESP:GTWIF,210102,354524044484948,,1,08626693fb98,-36,,,,,,,,97,20170119071300,05E3$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,210102,A100004D9EF2AE,,41,,8,99,0,17.7,21,3.58,0,1,1,0,0,20161216135038,4,,,,,20161216135038,00AB$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTSTR,400201,862365030034957,GL500,0,0,2,23.1,5,2,0.2,0,36.0,0.623089,51.582744,20161129174625,0234,0015,03C3,3550,,,,20161129174625,0026$"));
+
+ verifyNotNull(decoder, buffer(
+ "+RESP:GTSTR,400201,862365030034957,GL500,0,1,2,21.8,100,0,,,,,,,0234,0015,03C3,3550,,,,20161129174009,0023$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,210102,A10000499AEF9B,,41,,0,0,0,15.0,9,3.87,0,1,1,0,0,20161101140211,72,,,,,20161101140211,00A3$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTNMR,210102,A10000499AEF9B,,0,0,1,9,0.0,0,288.0,-76.902364,39.578828,20161101134145,,,,,00,73,20161101134145,009F$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,210102,A10000499AEF9B,,0,1,1,9,0.5,0,288.0,-76.902364,39.578828,20161101134124,,,,,00,73,20161101134123,009D$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTRTL,210102,A10000499AEF9B,,0,0,1,10,0.2,0,305.4,-76.902274,39.578517,20161101155001,,,,,00,73,20161101155001,00A6$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,110100,358688000000158,,41,898600810906F8048812,18,99,0,33.23,1,4.19,1,1,1,0,0,20110714104934,100,,,,,20110714104934,0014$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,080100,135790246811220,,16,898600810906F8048812,16,0,1,11870,,4.1,0,0,0,,20090214013254,,12340,,00,00,+0800,0,20090214093254,11F0$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,040100,135790246811220,,16,898600810906F8048812,16,0,1,,0,4.4,0,0,0,0,20090214013254,13000,00,00,+0800,0,20090214093254,11F0$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,060100,135790246811220,,16,898600810906F8048812,16,0,1,12000,,4.4,0,0,0,0,20090214013254,0,1300,2000,00,00,+0800,0,20090214093254,11F0$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,1A0800,860599000773978,GL300,41,89701016426133851978,17,0,1,26.6,,3.90,1,1,0,0,0,20161003184043,69,1,44,,,20161004040811,022C$"));
+
+ verifyAttributes(decoder, buffer(
+ "+BUFF:GTINF,1A0800,860599000773978,GL300,41,89701016426133851978,23,0,1,204.7,,3.84,1,1,0,0,0,20161006072548,62,1,38,,,20161006082343,0C98$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,360100,864251020141408,3VWGW6AJ0FM237324,gv500,,10,1,1,0.0,0,2258.4,-99.256948,19.555800,20160929214743,0334,0020,0084,65AC,00,0.0,,,,100,410000,0,nan,,20160929214743,13BA$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTOBD,360201,864251020186064,4T1BE46KX7U018210,,0,19FFFF,4T1BE46KX7U018210,1,14283,983901C0,799,36,18,,33792,0,0,0,,,38,,6,53557,0,0.0,0,219.5,-76.661456,39.832588,20160507132153,20160507132154,0230$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,360201,864251020186064,1G1JC5444R7252367,,12802,10,1,0,0.0,0,219.5,-76.661456,39.832588,20160507132235,,,,,,20460.9,00080:03:37,,,100,210000,791,,56,20160507132239,0233$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,1F0101,135790246811220,1G1JC5444R7252367,,,00,2,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,0,4.3,92,70.0,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,2000.0,12345:12:34,,,80,210100,,,50,20090214093254,11F0$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,1F0101,135790246811220,1G1JC5444R7252367,,,00,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,2000.0,12345:12:34,,92,80,210100,,,50,20090214093254,11F0$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTSTT,060228,862894020178276,,21,0,0.0,0,411.3,-63.169745,-17.776330,20160319132220,0736,0003,6AD4,5BAA,00,20160319092223,1FBD$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTNMR,210102,A10000458356CE,,0,1,1,9,0.0,8,190.7,-85.765865,42.894837,20160316123202,,,,,60,30,20160316123202,0137$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTIDA,060228,862894020178276,,,01C68011010000C7,1,1,0,0.0,0,413.0,-63.169675,-17.776349,20160317222129,0736,0003,6AD4,32CF,00,34.9,,,,,20160317182130,1626$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTIGN,060228,862894020180553,,9860,0,0.2,189,420.0,-63.158195,-17.800608,20160309022951,0736,0003,6AD4,3471,00,,881.2,20160308222956,129A$"));
+
+ verifyPosition(decoder, buffer(
+ "+BUFF:GTIGF,060228,862894020180553,,1958,0,0.0,240,390.3,-63.089213,-17.764712,20160309122854,0736,0003,6AB8,5A23,00,,936.8,20160309082858,1368$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,060228,862894020180553,,,10,1,1,20.0,147,329.7,-62.899703,-17.720434,20160309113548,0736,0003,6AAE,3381,00,913.3,,,,0,220101,,,,20160309073554,132B$"));
+
+ verifyPositions(decoder, buffer(
+ "+BUFF:GTFRI,060402,862894021808798,,,10,1,1,0.0,349,394.3,-63.287717,-17.662410,20160116234031,0736,0003,6ABA,8305,00,3326.8,,,,94,220100,,,,20160116194035,4D83"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,2C0204,867162020003125,GL300W,0,0,2,1,1.7,205,2867.0,-78.481127,-0.206828,20160215210433,0740,0000,7596,5891C,0.0,1,1.7,205,2867.0,-78.481127,-0.206828,20160215210503,0740,0000,7596,5891C,0.0,88,20160215210506,1E78$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,060228,862894020178276,,15153,10,1,1,0.0,0,431.7,-63.169571,-17.776235,20160210153458,0736,0003,6AD4,80EF,00,34.9,00117:31:26,13442,15163,0,210101,,,,20160210113503,38EE$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,110100,A5868800000015,,0,0,1,1,4.3,92,70.0,121.354335,31.222073,20110214013254,0460,0000,18d8,6141,00,80,20110214013254,000C"));
+
+ verifyNotNull(decoder, buffer(
+ "+RESP:GTFRI,210102,A10000458356CE,,0,1,1,15,1.4,0,190.6,-85.765763,42.894896,20160208164505,4126,210,0,18673,00,92,20160208164507,00A6"));
+
+ verifyPositions(decoder, buffer(
+ "+BUFF:GTFRI,060402,862894021808798,,,10,1,1,0.0,349,394.3,-63.287717,-17.662410,20160116234031,0736,0003,6ABA,8305,00,3326.8,,,,94,220100,,,,20160116194035,4D83"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTIDA,06020A,862170013895931,,,D2C4FBC5,1,1,1,0.8,0,22.2,117.198630,31.845229,20120802121626,0460,0000,5663,2BB9,00,0.0,,,,,20120802121627,008E$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTINF,1F0101,135790246811220,1G1JC5444R7252367,,16,898600810906F8048812,16,0,1,12000,,4.2,0,0,,,20090214013254,,,,,,+0800,0,20090214093254,11F0$"));
+
+ verifyPositions(decoder, false, buffer(
+ "+RESP:GTFRI,120113,555564055560555,,1,1,1,,,,,,,,0282,0380,f080,cabf,6900,79,20140824165629,0001$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,0F0106,862193020451183,,,10,1,1,0.0,163,,-57.513617,-25.368191,20150918182145,,,,,,21235.0,,,,0,210100,,,,20150918182149,00B8$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTOBD,1F0109,864251020135483,,gv500,0,78FFFF,,1,12613,,,,,,,,,,,,,,1286,0,0.0,0,17.1,3.379630,6.529701,20150813074639,0621,0030,51C0,A2B3,00,0.0,20150813074641,A7E6$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTOBD,1F0109,864251020135483,4T1BE46KX7U018210,gv500,0,78FFFF,4T1BE46KX7U018210,1,13411,981B81C0,787,3,43,,921,463,1,10,0300030103030304001200310351035203530354,20,55,,1286,0,6.5,74,21.6,3.379710,6.529714,20150813074824,0621,0030,51C0,A2B3,00,0.0,20150813074828,A7E9$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTSTT,1A0401,860599000508846,,41,0,0.0,84,107.5,-76.657998,39.497203,20150623160622,0310,0260,B435,3B81,,20150623160622,0F54$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,1A0401,860599000508846,,0,0,1,1,134.8,154,278.7,-76.671089,39.778885,20150623154301,0310,0260,043F,7761,,99,20150623154314,0F24$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,1A0200,860599000165464,CRI001,0,0,1,2,,41,,-71.153137,42.301634,20150328020301,,,,,280.3,55,20150327220351,320C"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,02010D,867844001675407,,0,0,1,2,0.0,0,28.9,8.591011,56.476397,20140915213209,0238,0001,03CB,2871,,97,20140915213459,009A"));
+
+ verifyNull(decoder, buffer(
+ "+RESP:GTINF,359464030073766,8938003990320469804f,18,99,100,1,0,+2.00,0,20131018084015,00EE,0103090402"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,04040C,359231038939904,,,10,1,2,0.0,117,346.0,8.924243,50.798077,20130618122040,0262,0002,0299,109C,00,0.0,,,,,,,,,20130618122045,00F6"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTSTT,04040C,359231038939904,,42,0,0.0,117,346.0,8.924243,50.798077,20130618125152,0262,0002,0299,109C,00,20130618125154,017A"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,020102,000035988863964,,0,0,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,,20090214093254,11F0"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,020102,135790246811220,,0,0,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,,20090214093254,11F0"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,020102,135790246811220,,0,0,2,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,0,4.3,92,70.0,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,,20090214093254,11F0"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTDOG,020102,135790246811220,,0,0,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,2000.0,20090214093254,11F0"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTLBC,020102,135790246811220,,+8613800000000,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,,20090214093254,11F0"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTGCR,020102,135790246811220,,3,50,180,2,0.4,296,-5.4,121.391055,31.164473,20100714104934,0460,0000,1878,0873,00,,20100714104934,000C"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTFRI,07000D,868487001005941,,0,0,1,1,0.0,0,46.3,-77.039627,38.907573,20120731175232,0310,0260,B44B,EBC9,0015e96913a7,-58,,100,20120731175244,0114"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTHBM,0F0100,135790246811220,,,10,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,2000.0,20090214093254,11F0$"));
+
+ verifyPosition(decoder, buffer(
+ "+RESP:GTHBM,0F0100,135790246811220,,,11,1,1,24.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,2000.0,20090214093254,11F0$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,02010C,867844001274144,,0,0,1,1,18.0,233,118.1,7.615551,51.515600,20140106130516,0262,0007,79E6,B956,,72,20140106140524,09CE$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,02010C,867844001274649,,0,0,1,1,0.0,0,122.5,7.684216,51.524512,20140106233722,0262,0007,79EE,1D22,,93,20140107003805,03C4$"));
+
+ verifyPositions(decoder, buffer(
+ "+BUFF:GTFRI,210101,863286020016706,,,10,1,1,,,,49.903915,40.391669,20140818105815,,,,,,,,,,,210100,,,,,000C$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,240100,135790246811220,,,10,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,2000.0,12345:12:34,,80,,,,,,20090214093254,11F0$"));
+
+ verifyPositions(decoder, buffer(
+ "+RESP:GTFRI,240100,135790246811220,,,10,2,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,0,4.3,92,70.0,121.354335,31.222073,20090101000000,0460,0000,18d8,6141,00,2000.0,12345:12:34,,,80,,,,,20090214093254,11F0$"));
+
+ verifyNotNull(decoder, buffer(
+ "+RESP:GTSTT,280100,A1000043D20139,,42,0,0.1,321,228.6,-76.660884,39.832552,20150615120628,0310,0484,00600019,0A52,,20150615085741,0320$"));
+
+ verifyNotNull(decoder, buffer(
+ "+RESP:GTRTL,280100,A1000043D20139,,0,0,1,1,0.1,321,239.1,-76.661047,39.832501,20150615114455,0310,0484,00600019,0A52,,87,20150615074456,031E$"));
+
+ verifyAttributes(decoder, buffer(
+ "+BUFF:GTBPL,1A0800,860599000773978,GL300,3.55,0,0.0,0,257.1,60.565437,56.818277,20161006070553,,,,,204.7,20161006071028,0C75$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTTEM,1A0102,860599000000448,,3,33,0,5.8,0,33.4,117.201191,31.832502,20130109061410,0460,0000,5678,2079,,20130109061517,0091$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTJDR,0A0102,135790246811220,,0,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,20090214093254,11F0$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTJDS,0A0102,135790246811220,,2,0,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,20090214093254,11F0$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTSOS,020102,135790246811220,,0,0,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,00,,20090214093254,11F0$"));
+
+ verifyAttributes(decoder, buffer(
+ "+RESP:GTVER,1A0800,860599000773978,GL300,GL300,0A03,0103,20161007041531,10F8$"));
+
+ verifyNull(decoder, buffer(
+ "+ACK:GTHBD,1A0401,135790246811220,,20100214093254,11F0"));
+
+ verifyAttributes(decoder, buffer(
+ "+ACK:GTRTO,1A0800,860599000773978,GL300,VER,FFFF,20161006053520,0C19"));
+
+ verifyAttributes(decoder, buffer(
+ "+ACK:GTJDC,0A0102,135790246811220,,0016,20090214093254,11F0"));
+
+ verifyAttributes(decoder, buffer(
+ "+ACK:GTGEO,1A0102,135790246811220,,0,0008,20100310172830,11F0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GlobalSatProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GlobalSatProtocolDecoderTest.java
new file mode 100644
index 000000000..9746845a0
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GlobalSatProtocolDecoderTest.java
@@ -0,0 +1,56 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GlobalSatProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GlobalSatProtocolDecoder decoder = new GlobalSatProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "GSh,131826789036289,3,M,ea04*3d"));
+
+ decoder.setFormat0("SORPZAB27GHKLMN*U!");
+
+ verifyPosition(decoder, text(
+ "GSr,011412001878820,4,5,00,,1,250114,105316,E00610.2925,N4612.1824,0,0.02,0,1,0.0,64*51!"));
+
+ verifyPosition(decoder, text(
+ "GSr,357938020310710,,4,04,,1,170315,060657,E00000.0000,N0000.0000,148,0.00,0,0,0.0,11991mV*6c!"));
+
+ decoder.setFormat0("TSPRXAB27GHKLMnaicz*U!");
+
+ verifyPosition(decoder, text(
+ "GSr,1,135785412249986,01,I,EA02,3,230410,153318,E12129.2839,N2459.8570,0,1.17,212,8,1.0,12.3V*55"));
+
+ verifyPosition(decoder, text(
+ "GSr,GTR-128,012896009148443,0040,5,0080,3,190813,185812,W11203.3661,N3330.2104,344,0.24,78,9,0.8,60%,0,0,12,\"310,410,0bdd,050d,02,21\",\"310,410,0bdd,0639,24,7\"*79"));
+
+ verifyPosition(decoder, text(
+ "$355632004245866,1,1,040202,093633,E12129.2252,N2459.8891,00161,0.0100,147,07,2.4"));
+
+ verifyPosition(decoder, text(
+ "$355632000959420,9,3,160413,230536,E03738.4906,N5546.3148,00000,0.3870,147,07,2.4"));
+
+ verifyPosition(decoder, text(
+ "$353681041893264,9,3,240913,100833,E08513.0122,N5232.9395,181.3,22.02,251.30,9,1.00"));
+
+ decoder.setFormat0("SPRXYAB27GHKLMmnaefghiotuvwb*U!");
+
+ verifyPosition(decoder, text(
+ "GSr,GTR-128,013227006963064,0080,1,a080,3,190615,163816,W07407.7134,N0440.8601,2579,0.01,130,12,0.7,11540mV,0,77,14,\"732,123,0744,2fc1,41,23\",\"732,123,0744,2dfe,05,28\",\"732,123,0744,272a,15,21\",\"732,123,0744,2f02,27,23\"*3b!"));
+
+ verifyPosition(decoder, text(
+ "$80050377796567,0,13,281015,173437,E08513.28616,N5232.85432,222.3,0.526,,07*37"),
+ position("2015-10-28 17:34:37.000", true, 52.54757, 85.22144));
+
+ verifyPosition(decoder, text(
+ "$80050377796567,0,18,281015,191919,E08513.93290,N5232.42141,193.4,37.647,305.40,07*37"),
+ position("2015-10-28 19:19:19.000", true, 52.54036, 85.23222));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GnxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GnxProtocolDecoderTest.java
new file mode 100644
index 000000000..91aca50c8
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GnxProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GnxProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GnxProtocolDecoder decoder = new GnxProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$GNX_MIF,865733022354161,143,0,172642,180316,172642,180316,1,13.034581,N,080.234521,E,0,05396274,ROUTE_2#########,Deo ############,GNX04008,B0*"));
+
+ verifyPosition(decoder, text(
+ "$GNX_LOC,865733022352132,095,0,102134,280914,102134,280914,1,18.765432,N,073.752811,W,032,165.32,12,25,0,A,E,2,000099.9,000099.5,GNX01001,12*"));
+
+ verifyNull(decoder, text(
+ "$GNX_LOC,865733022354161,139,0,142838,160316,142825,160316,0,000000000,N,0000000000,E,000,0.00,00,48,0,e,C,2,000000.0,000000.0,GNX04008,BB*"));
+
+ verifyPosition(decoder, text(
+ "$GNX_DIO,863071015071563,110,1,155627,121214,151244,121214,1,08.878321,N,076.643154,E,0,0,0,0,0,0,GNX01001,B1*"));
+
+ verifyNull(decoder, text(
+ "$GNX_DIO,865733022354161,112,1,142849,160316,142714,160316,0,000000000,N,0000000000,E,0,0,0,0,0,0,0,GNX04008,1A*"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GoSafeProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GoSafeProtocolDecoderTest.java
new file mode 100644
index 000000000..70c86bb23
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GoSafeProtocolDecoderTest.java
@@ -0,0 +1,87 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GoSafeProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GoSafeProtocolDecoder decoder = new GoSafeProtocolDecoder(null);
+
+ verifyPositions(decoder, text(
+ "*GS06,860078024226974,101437211218,,SYS:G3SC;V3.36;V1.1.8,GPS:A;7;N3.052302;E101.787216;16;137;48;1.58,COT:4261733103,ADC:22.86;0.58;0.01,DTT:4004;E1;0;0;0;3$101439211218,,SYS:G3SC;V3.36;V1.1.8,GPS:A;8;N3.052265;E101.787200;12;152;46;1.31,COT:4261733103,ADC:22.98;0.58;0.01,DTT:4004;E1;0;0;0;3$101441211218,,SYS:G3SC;V3.36;V1.1.8,GPS:A;8;N3.052247;E101.787232;8;131;46;1.34,COT:4261733103,ADC:23.13;0.58;0.01,DTT:4004;E1;0;0;0;3$101510211218,,SYS:G3SC;V3.36;V1.1.8,GPS:A;8;N3.052150;E101.787152;0;131;40;0.97,COT:4261733160,ADC:22.88;0.58;0.01,DTT:4000;E1;0;0;0;1$101540211218,,SYS:G3SC;V3.36;V1.1.8,GPS:A;7;N3.052150;E101.787152;0;131;40;0.97,COT:4261733160,ADC:22.91;0.58;0.00,DTT:4000;E1;0;0;0;1#"));
+
+ verifyPositions(decoder, text(
+ "*GS06,359568052570135,090349191018,,SYS:G3C;V1.40;V1.0.4,GPS:A;10;S26.112722;E28.078766;0;23;1581;0.80,COT:,ADC:10.86;3.79,DTT:4000;E7;0;0;0;1$090419191018,,SYS:G3C;V1.40;V1.0.4,GPS:A;10;S26.112722;E28.078766;0;23;1581;0.80,COT:,ADC:10.85;3.79,DTT:4000;E7;0;0;0;1#"));
+
+ verifyPositions(decoder, text(
+ "*GS06,359913060650380,152248050718,,SYS:G3C;V1.38;V05,GPS:A;10;N31.914370;E35.914640;0;0,COT:689,ADC:0.18;3.55,DTT:4025;E6;0;0;0;1#"));
+
+ verifyPositions(decoder, text(
+ "*GS06,359913060650380,101019050718,,SYS:G3C;V1.38;V05,GPS:L;6;N31.916576;E35.908480;0;0,GSM:1;4;416;3;627A;A84B;-66,COT:188,ADC:4.31;3.88,DTT:4005;E6;0;0;0;1#"));
+
+ verifyPositions(decoder, text(
+ "*GS06,860078024287174,070120310318,,SYS:G3SC;V3.32;V1.1.8,GPS:A;9;N23.169946;E113.450568;0;0;23;0.86,COT:65;20,ADC:4.27;3.73;0.01;0.02,DTT:4004;E0;0;0;0;1,IWD:0;0;000000000000#"));
+
+ verifyPositions(decoder, text(
+ "*GS06,860078024213915,032544190318,,SYS:G3SC;V3.32;V1.1.8,GPS:A;7;N3.052417;E101.787112;0;0;94;1.38,COT:686;0-0-0,ADC:16.25;4.09,DTT:4000;E0;0;0;0;1#"));
+
+ verifyPositions(decoder, text(
+ "*GS06,351535058659335,062728190318,,SYS:G6S;V3.32;V1.0.5,GPS:A;10;N23.169806;E113.450760;0;0;81;0.77,COT:0,ADC:0.00;0.16,DTT:80;E0;0;0;0;1#"));
+
+ verifyPositions(decoder, text(
+ "*GS26,356449061046586,082522030117,,SYS:G737IC;V1.13;V1.0.5,GPS:V;5;N42.594136;W70.723832;0;0;8;2.06,GSM:;;310;260;C76D;9F1D;-85,ADC:3.86,DTT:3918C;;0;0;0;1,#"));
+
+ verifyPositions(decoder, text(
+ "*GS56,357330051092344,123918301116,10,GPS:L;9;N47.582920;W122.238720;0;0;102;0.99,GSM:0;0;310;410;A7DB;385C;-86,COT:76506,ADC:0.82;3.77,DTT:2184;;0;0;10000;0$000000000000,86,GPS:A;6;N47.582912;W122.238840;0;0;88;2.20,COT:76506,ADC:0.00;3.75,DTT:0;;0;0;40;0$000000000000,86,GPS:A;6;N47.582912;W122.238840;0;0;88;2.20,COT:76506,ADC:0.00;3.74,DTT:0;;0;0;40;0$000000000000,93,GPS:A;6;N47.582912;W122.238840;0;0;88;2.20,COT:76506,ADC:0.00;3.73,DTT:8000;;0;0;80000;0$000000000000,13,GPS:L;6;N47.582912;W122.238840;0;0;88;2.20,COT:76506,ADC:11.09;3.79,DTT:2004;;0;0;80000;0$000000000000,90,GPS:L;6;N47.582912;W122.238840;0;0;88;2.20,COT:76506,ADC:11.13;3.79,DTT:23004;;0;0;10000;0$000000000000,,GPS:L;6;N47.582912;W122.238840;0;0;88;2.20,GSM:5;2;310;410;A7DB;385C;-89,COT:76506,ADC:14.12;3.81,DTT:23184;;0;0;0;6#"));
+
+ verifyPositions(decoder, text(
+ "*GS26,356449061139936,022918011216,,SYS:G737IC;V1.13;V1.0.5,GPS:A;9;N42.651728;W70.623520;0;0;48;1.50,ADC:4.08,DTT:3900C;;0;0;0;1,#"));
+
+ verifyNotNull(decoder, text(
+ "*GS56,356449063230915,052339180916,,SYS:G7S;V1.08;V1.2,GPS:V;4;N24.730006;E46.637816;14;0;630,GSM:;;420;4;5655;507A;-70,COT:75242;2-8-17,ADC:13.22;0.08,DTT:23004;;0;0;0;1#"));
+
+ verifyNotNull(decoder, text(
+ "*GS56,356449063230915,052349180916,,SYS:G7S;V1.08;V1.2,GPS:V;6;N24.730384;E46.637620;47;56;607,GSM:;;420;4;5655;507A;-70,COT:75290;2-8-27,ADC:13.24;0.08,DTT:23004;;0;0;0;1#"));
+
+ verifyNotNull(decoder, text(
+ "*GS56,356449063230915,052444180916,,SYS:G7S;V1.08;V1.2,GPS:V;6;N24.730384;E46.637620;47;56;607,GSM:;;420;4;5655;F319;-102,COT:75290;2-9-27,ADC:13.00;0.08,DTT:23004;;0;0;0;1$052449180916,,SYS:G7S;V1.08;V1.2,GPS:V;6;N24.730384;E46.637620;47;56;607,GSM:;;420;4;5655;F319;-102,COT:75290;2-9-27,ADC:13.13;0.08,DTT:23004;;0;0;0;1#"));
+
+ verifyPositions(decoder, text(
+ "*GS16,356449062643845,141224290316,,SYS:G79;V1.13;V1.0.2,GPS:V;5;N24.694972;E46.680736;46;334;606;1.43,GSM:;;420;4;5655;4EB8;-57,COT:330034,ADC:13.31;3.83,DTT:27004;;0;0;0;1,OBD:064101000400000341057E04410304000341510104411001C203410F4B0341112904411F01AB0641010004000014490201FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03410D21,FUL:28260"));
+
+ verifyPositions(decoder, text(
+ "*GS16,351535059439208,145425130316,,GPS:V;0;N0.000000;E0.000000;0;0;0;0.00;0.00,GSM:1;3;416;3;A8C;2820;-81;416;3;A8C;281F;-83;416;3;A8C;368A;-87;416;3;A8C;368B;-89;416;3;A8C;2C26;-103;416;3;A8C;3689;-107;416;3;A8C;2D83;-107"));
+
+ verifyPosition(decoder, text(
+ "*GS02,358696043774648,GPS:230040;A;S1.166829;E36.934287;0;0;170116,STT:20;0,MGR:32755204,ADC:0;11.2;1;28.3;2;4.1,GFS:0;0"));
+
+ verifyNull(decoder, text(
+ "*GS02,358696043774648"));
+
+ verifyPositions(decoder, text(
+ "*GS16,351535058709775,100356130215,,SYS:G79W;V1.06;V1.0.2,GPS:A;6;N24.802700;E46.616828;0;0;684;1.35,COT:60,ADC:4.31;0.10,DTT:20000;;0;0;0;1"));
+
+ verifyPositions(decoder, text(
+ "*GS16,351535059439208,074558291015,,GPS:A;9;N31.935942;E35.867092;;345;921;1.03;1.59,GSM:1;3;416;3;A8C;368B;-78;416;3;A8C;2820;-73;416;3;BB8;2CBE;-76;416;3;A8C;368A;-76;416;3;A8C;2C26;-79,OBD:04410C122003410D0F03411C0103410547037F011203411100"));
+
+ verifyPositions(decoder, text(
+ "*GS16,351535059439208,083515281015,,GPS:A;9;N31.959502;E35.908316;;108;890;1.05;1.79,GSM:1;4;416;3;AF0;A3A6;-59;416;3;AF0;A3A3;-50;416;3;AF0;A3A4;-56;416;3;AF0;A3A5;-62;416;3;AF0;B195;-76,OBD:04410C194603410D2303411C0103410583037F011203411115"));
+
+ verifyNull(decoder, text(
+ "*GS16,351535058709775"));
+
+ verifyPositions(decoder, text(
+ "*GS16,351535059439208,103441131015,,GPS:A;8;N31.960122;E35.921652;27;99;847;1.33;2.41,GSM:1;4;416;3;AF0;9C73;-61;416;3;AF0;9C89;-68,OBD:04410C0DA403410D0B03411C010341057A037F011203411100$103453131015,,GPS:A;8;N31.959976;E35.922144;6;0;835;1.33;2.41,GSM:1;4;416;3;AF0;9C73;-67;416;3;AF0;9C89;-64;416;3;AF0;B389;-83,OBD:04410C0D8E03410D0B03411C010341057D037F011203411100$103503131015,,GPS:A;9;N31.959870;E35.922284;11;127;830;1.33;2.41,GSM:1;4;416;3;AF0;9C73;-67;416;3;AF0;9C89;-64;416;3;AF0;B389;-83,OBD:04410C0D8E03410D0B03411C010341057D037F011203411100$103513131015,,GPS:A;9;N31.959742;E35.922516;10;106;830;1.37;2.91,GSM:1;4;416;3;AF0;9C73;-67;416;3;AF0;9C89;-64;416;3;AF0;B389;-83,OBD:04410C0D1003410D0603411C010341057E037F011203411100$103553131015,,GPS:A;8;N31.959564;E35.923308;6;0;836;1.41;2.43,GSM:1;4;416;3;AF0;9C73;-65;416;3;AF0;B389;-71;416;3;AF0;9C89;-74,OBD:04410C0DAE03410D0403411C010341057C037F011203411100#"));
+
+ verifyPositions(decoder, text(
+ "*GS16,351535059439208,155750220815,,SYS:G79;V1.10;V1.0.2,GPS:A;4;N31.944198;E35.846644;0;0;923;9.47;1.00,COT:155133,ADC:12.21;0.10,DTT:20002;;0;0;0;1#"));
+
+ verifyPositions(decoder, text(
+ "*GS16,351535059439208,070034220815,,SYS:G79;V1.10;V1.0.2,GPS:A;8;N31.945970;E35.859848;29;65;922;1.14;1.68,COT:147528,ADC:14.07;0.11,DTT:27006;;0;0;0;3,OBD:04410C1ECD03410D2D03411C010341057A037F011203411107$070035220815,,SYS:G79;V1.10;V1.0.2,GPS:A;8;N31.945934;E35.859908;29;86;922;1.14;1.68,COT:147528,ADC:13.94;0.15,DTT:27006;;0;0;0;3,OBD:04410C1ECD03410D2D03411C010341057A037F011203411107$070037220815,,SYS:G79;V1.10;V1.0.2,GPS:A;8;N31.945844;E35.859952;29;123;922;1.14;1.68,COT:147625,ADC:13.75;0.11,DTT:27006;;0;0;0;3,OBD:04410C0FE803410D1803411C010341057C037F011203411100$070038220815,,SYS:G79;V1.10;V1.0.2,GPS:A;8;N31.945808;E35.859940;29;145;923;1.14;1.68,COT:147625,ADC:14.00;0.11,DTT:27006;;0;0;0;3,OBD:04410C0FE803410D1803411C010341057C037F011203411100#"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GotopProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GotopProtocolDecoderTest.java
new file mode 100644
index 000000000..ca3ddfda8
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GotopProtocolDecoderTest.java
@@ -0,0 +1,37 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GotopProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GotopProtocolDecoder decoder = new GotopProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ ""));
+
+ verifyNull(decoder, text(
+ "353327020412763,CMD-X"));
+
+ verifyPosition(decoder, text(
+ "013226009991924,CMD-T,A,DATE:130802,TIME:153721,LAT:25.9757433S,LOT:028.1087816E,Speed:000.0,X-X-X-X-81-26,000,65501-00A0-4B8E"));
+
+ verifyPosition(decoder, text(
+ "353327020115804,CMD-T,A,DATE:090329,TIME:223252,LAT:22.7634066N,LOT:114.3964783E,Speed:000.0,84-20,000"),
+ position("2009-03-29 22:32:52.000", true, 22.76341, 114.39648));
+
+ verifyPosition(decoder, text(
+ "353327020115804,CMD-T,A,DATE:090329,TIME:223252,LAT:22.7634066N,LOT:114.3964783E,Speed:000.0,1-1-0-84-20,000"));
+
+ verifyPosition(decoder, text(
+ "353327020412763,CMD-F,V,DATE:140125,TIME:183636,LAT:51.6384466N,LOT:000.2863866E,Speed:000.0,61-19,"));
+
+ verifyPosition(decoder, text(
+ "013949008891817,CMD-F,A,DATE:150225,TIME:175441,LAT:50.000000N,LOT:008.000000E,Speed:085.9,0-0-0-0-52-31,000,26201-1073-1DF5"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gps056FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Gps056FrameDecoderTest.java
new file mode 100644
index 000000000..ce21f733f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gps056FrameDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class Gps056FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gps056FrameDecoder decoder = new Gps056FrameDecoder();
+
+ assertEquals(
+ binary("242435314750534c5f30323836323436323033333738323934361905110f160b0b7710584e1cbd1b9b4500005b100300fb0a071700ffff23"),
+ decoder.decode(null, null, binary("242435314750534c5f30323836323436323033333738323934361905110f160b0b7710584e1cbd1b9b4500005b100300fb0a071700ffff230030")));
+
+ assertEquals(
+ binary("242432354c4f474e5f3131383632343632303333373832393436322e3123"),
+ decoder.decode(null, null, binary("242432354c4f474e5f3131383632343632303333373832393436322e3123")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gps056ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gps056ProtocolDecoderTest.java
new file mode 100644
index 000000000..a6d0c024a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gps056ProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Gps056ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gps056ProtocolDecoder decoder = new Gps056ProtocolDecoder(null);
+
+ verifyNull(decoder, buffer(
+ "$$25LOGN_118624620337829462.1#"));
+
+ verifyPosition(decoder, binary(
+ "242435314750534C5F30323836333037313031353034353834391D0A0E091A0A0B1112C34E1E23230A45FF00000000000000000000000023"));
+
+ verifyAttributes(decoder, binary(
+ "2424323853594E435F313138363330373130313530343538343900000000000023"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gps103ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gps103ProtocolDecoderTest.java
new file mode 100644
index 000000000..da8d8ff5a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gps103ProtocolDecoderTest.java
@@ -0,0 +1,261 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class Gps103ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gps103ProtocolDecoder decoder = new Gps103ProtocolDecoder(null);
+
+ verifyAttribute(decoder, text(
+ "imei:868683023212255,tracker,190205084503,,F,064459.000,A,4915.1221,N,01634.5655,E,3.91,83.95;"),
+ "course", 83.95);
+
+ verifyPosition(decoder, text(
+ "imei:864180034124375,vt14,190116192753,,F,172750.000,A,3649.2186,N,00235.8411,W,0.00,0,,0,0,51.93%,,+22;"));
+
+ verifyNull(decoder, text(
+ "imei:864180034124375,vr,0c00fa011ea05a03d726977103ad0034c98ef49e6d303fffd1c8361303f2dbb0fa530d8ca3930be3e94f4110145c7029a507a0a00028f4a70514c05c500503170334b400531971cad002ab7634f001a4027949c8e541ea47f853bca2f961ba427ab1e290089197711c485e4f6e82ad0d1ee8f25573eed4af60284f6935bb7ef2307f1dc3f4355bbf3f90a607ffd2e5fcc6c60310be80f152dbca54ed53147fed3ae7fa1fe54809e45330fdedc993d073b7f2a6340a00d8cabeb9a4980c68900e5cb1f6e29aab9e00fc334012a5a5c32e5227c7b21a9a2d35dc02cdb49edb189fe545ec058fec7565e667cfa08b1fccd34686e4f12003dd7ffaf4b980957440bd595beb53269bb082a517dd570693604cb6299cb1663f5a9d608e3e42807d71cd002d206028011e50aa49381513494011349cd2092803ffd3d031f154ef11bc86d870781f8679a90302540adc545c55a00e28c8a602e47ad2e46680133cd19e6800cd1cf4a0063293ce695188e0d20265e58559305c3ffcb2948eca10d20278adb50518890c40f5ed9a5fece941ccb29cfd19ff00c2a6e860d6471c7da1cffb3b507eb9aaafa3dc4a4909b7fdf6c9fd28b88fffd4ca5d06e7b94152af87a53f7a7403d949a8e60265f0eaff0014ee7e8807f5a99340857abcadf881fd2973013a6936f1f48d4ffbc01fe95652dd63fba00fa521926d1de8e07a51600dc3d01d00;"));
+
+ verifyPosition(decoder, text(
+ "imei:868683026321020,T:+11,181217080050,,F,080047.000,A,3227.3057,N,11649.4754,W,0.00,0,,0,0,0.00%,,+11;"));
+
+ verifyAttribute(decoder, text(
+ "imei:868683026321020,tracker,181217080106,,F,080102.000,A,3227.3057,N,11649.4754,W,0.00,0,,0,0,0.00%,0,+11;"),
+ Position.PREFIX_TEMP + 1, 11);
+
+ verifyPosition(decoder, text(
+ "imei:861359038609986,Equipo 1,---,------,----,214734,241018,26,1,-33.42317,-70.61930,067,229,0674,1.00,08,0,1,---,*"));
+
+ verifyPosition(decoder, text(
+ "imei:861359038609986,Equipo 1,---,------,----,214812,241018,14,0,-33.42317,-70.61930,000,000,0000,99.9,00,0,1,---,*"));
+
+ verifyNull(decoder, text(
+ "imei:123451234512345,L,*"));
+
+ verifyAttributes(decoder, text(
+ "imei:868683027758113,OBD,180905200218,,,,0,0,0.39%,70,9.41%,494,0.00,P0137,P0430,,;"));
+
+ verifyAttribute(decoder, text(
+ "imei:353451044508750,001,0809231929,13554900601,F,055403.000,A,2233.1870,N,11354.3067,E,0.00,30.1,65.43,1,0,10.5%,0.0%,28;"),
+ "fuel1", 10.5);
+
+ verifyPosition(decoder, text(
+ "imei:864180036029895,acc on,180508145653,,F,065645.000,A,4729.1497,N,01904.2342,E,0.00,0,,1,,0.00%,,;"));
+
+ verifyNotNull(decoder, text(
+ "imei:864895030279986,ac alarm,180404174252,,L,,,296a,,51f7,,,"));
+
+ verifyAttributes(decoder, text(
+ "imei:359710048977327,OBD,180301094003,5000000,0.00,0.00,98,18,68.63%,55,25.10%,1368,14.24,,,,;"));
+
+ verifyAttributes(decoder, text(
+ "imei:862106025092216,OBD,170605095949,195874,,370.8,808,066,30.0%,+87,13.0%,02444,14.3,,,,;"));
+
+ verifyAttributes(decoder, text(
+ "imei:868683027825532,OBD,170613203014,,,,0,0,0.00%,0,0.00%,0,0.00,,,,;"));
+
+ verifyAttributes(decoder, text(
+ "imei:862106025092216,OBD,170612165656,196043,,145803.9,,000,0.0%,+,0.0%,00000,12.6,,,,;"));
+
+ verifyAttributes(decoder, text(
+ "imei:862106025092216,OBD,170605095949,195874,,370.8,808,066,30.0%,+87,13.0%,02444,14.3,,,,;"));
+
+ verifyPosition(decoder, text(
+ "imei:353451044508750,DTC,0809231929,,F,055403.000,A,2233.1870,N,11354.3067,E,0.00,30.1,,1,0,10.5%,P0021,;"));
+
+ verifyPosition(decoder, text(
+ "imei:353451044508750,oil1,0809231929,,F,055403.000,A,2233.1870,N,11354.3067,E,0.00,,,,51.6,41.7,;"));
+
+ verifyPosition(decoder, text(
+ "imei:353451044508750,oil2,0809231929,,F,055403.000,A,2233.1870,N,11354.3067,E,0.00,,,,51.6,41.7,;"));
+
+ verifyPosition(decoder, text(
+ "imei:353451044508750,oil 51.67,0809231929,,F,055403.000,A,2233.1870,N,11354.3067,E,0.00,,;"));
+
+ verifyPosition(decoder, text(
+ "imei:353451044508750,T:+28.0,0809231929,,F,055403.000,A,2233.1870,N,11354.3067,E,0.00,,;"));
+
+ verifyPosition(decoder, text(
+ "imei:353451044508750,bonnet alarm,0809231929,,F,055403.000,A,2233.1870,N,11354.3067,E,0.00,,;"));
+
+ verifyPosition(decoder, text(
+ "imei:353451044508750,footbrake alarm,0809231929,,F,055403.000,A,2233.1870,N,11354.3067,E,0.00,,;"));
+
+ verifyPosition(decoder, text(
+ "imei:862106021237716,ac alarm,1611291645,,F,204457.000,A,1010.2783,N,06441.0274,W,0.00,,;"));
+
+ verifyAttributes(decoder, text(
+ "imei:359710049057798,OBD,161003192752,1785,,,0,54,96.47%,75,20.00%,1892,0.00,P0134,P0571,,;"));
+
+ verifyAttributes(decoder, text(
+ "imei:359710049090138,OBD,160629022949,51442,0.00,15.88,5632,122,40.39%,95,0.00%,2101,13.80,,,,;"));
+
+ verifyPosition(decoder, text(
+ "imei:359710049090138,tracker,160629022948,,F,182949.000,A,4043.8839,N,11328.8029,W,65.26,271.82,,1,0,31.37%,51442,;"));
+
+ verifyAttributes(decoder, text(
+ "imei:359710049042014,001,160615040011,,F,040011.000,A,2833.0957,N,07711.9465,E,0.01,215.33,,0,,,,;"));
+
+ verifyAttributes(decoder, text(
+ "imei:359710049028435,OBD,160316053657,70430,,,0,49,60.00%,46,19.22%,859,0.00,U1108,,,;"));
+
+ verifyPosition(decoder, text(
+ "359769031878322imei:359769031878322,tracker,1602160718,2,F,221811.000,A,1655.2193,S,14546.6722,E,0.00,,"));
+
+ verifyNull(decoder, text(
+ "imei:865328021049167,OBD,141118115036,,,0.0,,000,0.0%,+,0.0%,00000,,,,,"));
+
+ verifyAttributes(decoder, text(
+ "imei:359710049032874,OBD,160208152900,13555,,,45,0,24.71%,35,13.73%,1230,14.13,U1108,,,"));
+
+ verifyAttributes(decoder, text(
+ "imei:359710049064398,OBD,160101035156,17887,0.00,17.06,0,0,0.00%,0,0.00%,16383,10.82,,,,"));
+
+ verifyPosition(decoder, text(
+ "imei:868683020235846,rfid,160202091347,49121185,F,011344.000,A,0447.7273,N,07538.9934,W,0.00,0,,0,0,0.00%,,"));
+
+ verifyNotNull(decoder, text(
+ "imei:359710049075097,help me,,,L,,,113b,,558f,,,,,0,0,,,"));
+
+ verifyNotNull(decoder, text(
+ "imei:359710041100000,tracker,000000000,,L,,,fa8,,c9af,,,,,0,0,0.00%,,"));
+
+ verifyNotNull(decoder, text(
+ "imei:863070016871385,tracker,0000000119,,L,,,0FB6,,CB5D,,,"));
+
+ verifyPosition(decoder, text(
+ "imei:359710045559474,tracker,151030080103,,F,000101.000,A,5443.3834,N,02512.9071,E,0.00,0;"),
+ position("2015-10-30 00:01:01.000", true, 54.72306, 25.21512));
+
+ verifyPosition(decoder, text(
+ "imei:359710049092324,tracker,151027025958,,F,235957.000,A,2429.5156,N,04424.5828,E,0.01,27.91,,0,0,,,;"),
+ position("2015-10-26 23:59:57.000", true, 24.49193, 44.40971));
+
+ verifyPosition(decoder, text(
+ "imei:865328021058861,tracker,151027041419,,F,011531.000,A,6020.2979,N,02506.1940,E,0.49,113.30,,0,0,0.0%,,;"),
+ position("2015-10-27 01:15:31.000", true, 60.33830, 25.10323));
+
+ // Log on request
+ verifyNull(decoder, text(
+ "##,imei:359586015829802,A"));
+
+ // Heartbeat package
+ verifyNull(decoder, text(
+ "359586015829802"));
+
+ // No GPS signal
+ verifyNull(decoder, text(
+ "imei:359586015829802,tracker,000000000,13554900601,L,;"));
+
+ verifyPosition(decoder, text(
+ "imei:869039001186913,tracker,1308282156,0,F,215630.000,A,5602.11015,N,9246.30767,E,1.4,,175.9,"));
+
+ verifyPosition(decoder, text(
+ "imei:359710040656622,tracker,13/02/27 23:40,,F,125952.000,A,3450.9430,S,13828.6753,E,0.00,0"));
+
+ verifyPosition(decoder, text(
+ "imei:359710040565419,tracker,13/05/25 14:23,,F,062209.000,A,0626.0411,N,10149.3904,E,0.00,0"));
+
+ verifyPosition(decoder, text(
+ "imei:353451047570260,tracker,1302110948,,F,144807.000,A,0805.6615,S,07859.9763,W,0.00,,"));
+
+ verifyPosition(decoder, text(
+ "imei:359587016817564,tracker,1301251602,,F,080251.000,A,3223.5832,N,11058.9449,W,0.03,"));
+
+ verifyPosition(decoder, text(
+ "imei:359587016817564,tracker,1301251602,,F,080251.000,A,3223.5832,N,11058.9449,W,,"));
+
+ verifyPosition(decoder, text(
+ "imei:012497000208821,tracker,1301080525,,F,212511.000,A,2228.5279,S,06855.6328,W,18.62,268.98,"));
+
+ verifyPosition(decoder, text(
+ "imei:012497000208821,tracker,1301072224,,F,142411.077,A,2227.0739,S,06855.2912,,0,0,"));
+
+ verifyPosition(decoder, text(
+ "imei:012497000431811,tracker,1210260609,,F,220925.000,A,0845.5500,N,07024.7673,W,0.00,,"));
+
+ verifyPosition(decoder, text(
+ "imei:100000000000000,help me,1004171910,,F,010203.000,A,0102.0003,N,00102.0003,E,1.02,"));
+
+ verifyPosition(decoder, text(
+ "imei:353451040164707,tracker,1105182344,+36304665439,F,214418.000,A,4804.2222,N,01916.7593,E,0.37,"));
+
+ verifyPosition(decoder, text(
+ "imei:353451042861763,tracker,1106132241,,F,144114.000,A,2301.9052,S,04909.3676,W,0.13,"));
+
+ verifyPosition(decoder, text(
+ "imei:359587010124900,tracker,0809231929,13554900601,F,112909.397,A,2234.4669,N,11354.3287,E,0.11,321.53,"));
+
+ verifyPosition(decoder, text(
+ "imei:353451049926460,tracker,1208042043,123456 99008026,F,124336.000,A,3509.8668,N,03322.7636,E,0.00,,"));
+
+ // SOS alarm
+ verifyPosition(decoder, text(
+ "imei:359586015829802,help me,0809231429,13554900601,F,062947.294,A,2234.4026,N,11354.3277,E,0.00,"));
+
+ // Low battery alarm
+ verifyPosition(decoder, text(
+ "imei:359586015829802,low battery,0809231429,13554900601,F,062947.294,A,2234.4026,N,11354.3277,E,0.00,"));
+
+ // Geo-fence alarm
+ verifyPosition(decoder, text(
+ "imei:359586015829802,stockade,0809231429,13554900601,F,062947.294,A,2234.4026,N,11354.3277,E,0.00,"));
+
+ // Move alarm
+ verifyPosition(decoder, text(
+ "imei:359586015829802,move,0809231429,13554900601,F,062947.294,A,2234.4026,N,11354.3277,E,0.00,"));
+
+ // Over speed alarm
+ verifyPosition(decoder, text(
+ "imei:359586015829802,speed,0809231429,13554900601,F,062947.294,A,2234.4026,N,11354.3277,E,0.00,"));
+
+ verifyPosition(decoder, text(
+ "imei:863070010423167,tracker,1211051840,,F,104000.000,A,2220.6483,N,11407.6377,,0,0,"));
+
+ verifyPosition(decoder, text(
+ "imei:863070010423167,tracker,1211051951,63360926,F,115123.000,A,2220.6322,N,11407.5313,E,0.00,,"));
+
+ verifyPosition(decoder, text(
+ "imei:863070010423167,tracker,1211060621,,F,062152.000,A,2220.6914,N,11407.5506,E,15.85,347.84,"));
+
+ verifyPosition(decoder, text(
+ "imei:863070012698733,tracker,1303092334,,F,193427.000,A,5139.0369,N,03907.2791,E,0.00,,"));
+
+ verifyPosition(decoder, text(
+ "imei:869039001186913,tracker,130925065533,0,F,065533.000,A,5604.11015,N,9232.12238,E,0.0,,329.0,"));
+
+ verifyPosition(decoder, text(
+ "imei:359710041641581,acc alarm,1402231159,,F,065907.000,A,2456.2591,N,06708.8335,E,7.53,76.10,,1,0,0.03%,,"));
+
+ verifyPosition(decoder, text(
+ "imei:359710041641581,acc alarm,1402231159,,F,065907.000,A,2456.2591,N,06708.8335,E,7.53,76.10,,1,0,0.03%,,"));
+
+ verifyPosition(decoder, text(
+ "imei:313009071131684,tracker,1403211928,,F,112817.000,A,0610.1133,N,00116.5840,E,0.00,,,0,0,0.0,0.0,"));
+
+ verifyPosition(decoder, text(
+ "imei:866989771979791,tracker,140527055653,,F,215653.00,A,5050.33113,N,00336.98783,E,0.066,0"));
+
+ verifyPosition(decoder, text(
+ "imei:353552045375005,tracker,150401165832,61.0,F,31.0,A,1050.73696,N,10636.49489,E,8.0,,22.0,"));
+
+ verifyPosition(decoder, text(
+ "imei:353552045403597,tracker,150420050648,53.0,F,0.0,A,N,5306.64155,E,00700.77848,0.0,,1.0,;"));
+
+ verifyPosition(decoder, text(
+ "imei:353552045403597,tracker,150420051153,53.0,F,0.0,A,5306.64155,N,00700.77848,E,0.0,,1.0,;"));
+
+ verifyPosition(decoder, text(
+ "imei:359710047424644,tracker,150506224036,,F,154037.000,A,0335.2785,N,09841.1543,E,3.03,337.54,,0,0,45.16%,,;"));
+
+ verifyPosition(decoder, text(
+ "imei:865328023776874,acc off,150619152221,,F,072218.000,A,5439.8489,N,02518.5945,E,0.00,,,1,1,0.0,0.0,23.0,;"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gps103ProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/Gps103ProtocolEncoderTest.java
new file mode 100644
index 000000000..f888ee252
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gps103ProtocolEncoderTest.java
@@ -0,0 +1,39 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class Gps103ProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncodePositionPeriodic() throws Exception {
+
+ Gps103ProtocolEncoder encoder = new Gps103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_PERIODIC);
+ command.set(Command.KEY_FREQUENCY, 300);
+
+ assertEquals("**,imei:123456789012345,C,05m", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeCustom() throws Exception {
+
+ Gps103ProtocolEncoder encoder = new Gps103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "H,080");
+
+ assertEquals("**,imei:123456789012345,H,080", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GpsGateProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GpsGateProtocolDecoderTest.java
new file mode 100644
index 000000000..d35666b56
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GpsGateProtocolDecoderTest.java
@@ -0,0 +1,52 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GpsGateProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GpsGateProtocolDecoder decoder = new GpsGateProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$FRCMD,0097,_SendMessage,,7618.51990,S,4002.26182,E,350.0,1.08,0.0,250816,183522.000,0*7F"));
+
+ verifyPosition(decoder, text(
+ "$FRCMD,356406061385182,_SendMessage,,5223.88542,N,11440.45866,W,951.2,0.027,,220716,153507.00,1*5F"));
+
+ verifyPosition(decoder, text(
+ "$FRCMD,353067011068246,_SendMessage,,1918.1942,N,09906.3696,W,2246.5,000.0,295.9,150416,213147.00,1,Odometer=*70"));
+
+ verifyNull(decoder, text(
+ "$FRCMD,862950025974620,_Ping,voltage=4*4F"));
+
+ verifyPosition(decoder, text(
+ "$FRCMD,862950025974620,_SendMessage, ,2721.5781,S,15259.145,E,61,0.00,61,080316,092612,1,SosButton=0,voltage=4*60"));
+
+ verifyNull(decoder, text(
+ "$FRLIN,,user1,8IVHF*7A"));
+
+ verifyNull(decoder, text(
+ "$FRLIN,,354503026292842,VGZTHKT*0C"));
+
+ verifyNull(decoder, text(
+ "$FRLIN,IMEI,1234123412341234,*7B"));
+
+ verifyNull(decoder, text(
+ "$FRLIN,,saab93_device,KLRFBGIVDJ*28"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,154403.000,A,6311.64120,N,01438.02740,E,0.000,0.0,270707,,*0A"),
+ position("2007-07-27 15:44:03.000", true, 63.19402, 14.63379));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,074524,A,5553.73701,N,03728.90491,E,10.39,226.5,160614,0.0,E*75"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,154403.000,A,6311.64120,N,01438.02740,E,0.000,0.0,270707,,*0A"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GpsMarkerProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GpsMarkerProtocolDecoderTest.java
new file mode 100644
index 000000000..d6ba11cb7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GpsMarkerProtocolDecoderTest.java
@@ -0,0 +1,32 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+
+public class GpsMarkerProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GpsMarkerProtocolDecoder decoder = new GpsMarkerProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$GM23D863071014445404T260816142611N55441051E037325071033063C0530304#"));
+
+ verifyNull(decoder, text(
+ "$GM300350123456789012T100511123300G25000001772F185200000000000000005230298#"));
+
+ verifyPosition(decoder, text(
+ "$GM200350123456789012T100511123300N55516789E03756123400000035230298#"),
+ position("2011-05-10 12:33:00.000", true, 55.86132, 37.93539));
+
+ verifyPosition(decoder, text(
+ "$GM1350123456789012T1005111233N55516789E03756123400000035200298#"));
+
+ verifyPosition(decoder, text(
+ "$GM203863071014445404T150715202258N55481576E03729275300000040530301#"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GpsmtaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GpsmtaProtocolDecoderTest.java
new file mode 100644
index 000000000..438d0fb3a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GpsmtaProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GpsmtaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GpsmtaProtocolDecoder decoder = new GpsmtaProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "3085a94ef459 1446536867 49.81621 24.054207 1 0 22 0 10 12 24 0 0"));
+
+ verifyPosition(decoder, text(
+ "864528021249771 1446116686 49.85073 24.004438 0 217 6 338 00 59 27 0 0"));
+
+ verifyNotNull(decoder, text(
+ "359144048138856 1442932957 -49.85064 -24.003979 1 0 40 0 10 110 26 0 0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GranitFrameDecoderTest.java b/src/test/java/org/traccar/protocol/GranitFrameDecoderTest.java
new file mode 100644
index 000000000..7c4bb06c2
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GranitFrameDecoderTest.java
@@ -0,0 +1,45 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class GranitFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GranitFrameDecoder decoder = new GranitFrameDecoder();
+
+ assertEquals(
+ binary("2b525243427e1a003e2934757c57b8b03c38d279b4e61e9bd7006b000000001c00002a4533"),
+ decoder.decode(null, null, binary("2b525243427e1a003e2934757c57b8b03c38d279b4e61e9bd7006b000000001c00002a45330d0a")));
+
+ assertEquals(
+ binary("2b525243427e1a000d0a34757c57b8b03c38d279b4e61e9bd7006b000000001c00002a4533"),
+ decoder.decode(null, null, binary("2b525243427e1a000d0a34757c57b8b03c38d279b4e61e9bd7006b000000001c00002a45330d0a")));
+
+ assertEquals(
+ binary("4f4b"),
+ decoder.decode(null, null, binary("4f4b0d0a2b525243427e1a000d0a34757c57b8b03c38d279b4e61e9bd7006b000000001c00002a45330d0a")));
+
+ assertEquals(
+ binary("2b444441547e84003e290401d01690737c57b8903c383c7fa0e5081b64006b000000001c0000b8803c388e7fe7e5102197006c000000001c0000b8813c38ad7f02e6042035006c000000001d0000b8813c38bf7f13e6001d1e006c000000001d0000b8813c38bf7f13e6001d00006c000000001d0000b8903c38977f34e6091065006c000000001e000014002a3932"),
+ decoder.decode(null, null, binary("2b444441547e84003e290401d01690737c57b8903c383c7fa0e5081b64006b000000001c0000b8803c388e7fe7e5102197006c000000001c0000b8813c38ad7f02e6042035006c000000001d0000b8813c38bf7f13e6001d1e006c000000001d0000b8813c38bf7f13e6001d00006c000000001d0000b8903c38977f34e6091065006c000000001e000014002a39320d0a")));
+
+ assertEquals(
+ binary("2b444441547e84003e290401d41680747c57f8a03c38987f50e6005300006c000000001c0000f8b03c38987f50e6005300006c000000001c0000fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe14002a4346"),
+ decoder.decode(null, null, binary("2b444441547e84003e290401d41680747c57f8a03c38987f50e6005300006c000000001c0000f8b03c38987f50e6005300006c000000001c0000fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe14002a43460d0a")));
+
+ assertEquals(
+ binary("2b49444e543a204e6176696761746f722e30347820204669726d776172652076657273696f6e202030373132474c4e202a3231"),
+ decoder.decode(null, null, binary("2b49444e543a204e6176696761746f722e30347820204669726d776172652076657273696f6e202030373132474c4e202a32310d0a")));
+
+ assertEquals(
+ binary("4552524f522057524f4e4720434845434b53554d5f31"),
+ decoder.decode(null, null, binary("4552524f522057524f4e4720434845434b53554d5f310d0a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/GranitProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/GranitProtocolDecoderTest.java
new file mode 100644
index 000000000..fc75b2a53
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/GranitProtocolDecoderTest.java
@@ -0,0 +1,49 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class GranitProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ GranitProtocolDecoder decoder = new GranitProtocolDecoder(null);
+
+ verifyPositions(decoder, binary(
+ "2b444441547e8400c500040130050c43495808002839aee3150200000000640000000000000008002839aee3150200000000640000000000000008002839aee3150200000000640000000000000008002839aee3150200000000640000000000000008002839aee3150200000000640000000000000008002839aee3150200000000640000000000000014002a37420d0a"));
+
+ verifyPosition(decoder, binary(
+ "2b525243427e1a00c5008443495808002839aee315020000000064000000000000002a37410d0a"),
+ position("2016-12-08 11:27:00.000", false, 57.00888, 40.97143));
+
+ verifyPosition(decoder, binary(
+ "2b525243427e1a00c500ec904858b842283997e30002000000005e000000000d00002a32390d0a"),
+ position("2016-12-07 22:45:00.000", true, 57.00853, 40.97105));
+
+ verifyPosition(decoder, binary(
+ "2b525243427e1a00c500009148580800283997e30002000000005f000000000000002a33410d0a"));
+
+ verifyPositions(decoder, binary(
+ "2b444441547e84003b6d0401b10e9217445800b051398f35d34a313b000072000000010b000080b051398f35d34a313b000072000000010b0000f0b051390f33314c303b900371000000010b0000f0b05139cd31e54c2f3cd0016f000000010b0000f0b051396831204d303d950071000000010b0000f0b051397530aa4d323c610171000000010b00000a002a30420d0a"));
+
+ verifyPosition(decoder, binary(
+ "2b525243427e1a003e2934757c57b8b03c38d279b4e61e9bd7006b000000001c00002a4533"));
+
+ verifyPositions(decoder, binary(
+ "2b444441547e84003e290401d01690737c57b8903c383c7fa0e5081b64006b000000001c0000b8803c388e7fe7e5102197006c000000001c0000b8813c38ad7f02e6042035006c000000001d0000b8813c38bf7f13e6001d1e006c000000001d0000b8813c38bf7f13e6001d00006c000000001d0000b8903c38977f34e6091065006c000000001e000014002a3932"));
+
+ verifyPositions(decoder, binary(
+ "2b444441547e84003e290401d41680747c57f8a03c38987f50e6005300006c000000001c0000f8b03c38987f50e6005300006c000000001c0000fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe14002a4346"));
+
+ // +IDNT: Navigator.04x Firmware version 0712GLN *21
+ verifyAttributes(decoder, binary(
+ "2b49444e543a204e6176696761746f722e30347820204669726d776172652076657273696f6e202030373132474c4e202a3231"));
+
+ // ERROR WRONG CHECKSUM_1
+ verifyAttributes(decoder, binary(
+ "4552524f522057524f4e4720434845434b53554d5f31"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gt02ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gt02ProtocolDecoderTest.java
new file mode 100644
index 000000000..f9b8f6509
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gt02ProtocolDecoderTest.java
@@ -0,0 +1,43 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Gt02ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gt02ProtocolDecoder decoder = new Gt02ProtocolDecoder(null);
+
+ verifyAttributes(decoder, binary(
+ "6868150000035889905895258400831c07415045584f4b210d0a"));
+
+ verifyAttributes(decoder, binary(
+ "68682d0000035889905895258400951c1f415045584572726f723a20506172616d65746572203120284f4e2f4f4646290d0a"));
+
+ verifyAttributes(decoder, binary(
+ "68680f0504035889905831401700df1a00000d0a"));
+
+ verifyAttributes(decoder, binary(
+ "6868130504035889905831401700001a040423261e290d0a"));
+
+ verifyAttributes(decoder, binary(
+ "68681905040358899058314017000e1a010a2623211b2722252329000d0a"));
+
+ verifyAttributes(decoder, binary(
+ "68681a060303588990500037252de91a010a171a191b171915191e10000d0a"));
+
+ verifyPosition(decoder, binary(
+ "68682500000123456789012345000110010101010101026B3F3E026B3F3E000000000000000000010D0A"),
+ position("2001-01-01 01:01:01.000", true, -22.54610, -22.54610));
+
+ verifyAttributes(decoder, binary(
+ "6868110603035889905101276600001a0402292d0d0a"));
+
+ verifyPosition(decoder, binary(
+ "68682500a403588990510127660001100e09060a1d1b00ade1c90b79ea3000011b000000000000050d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gt06FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Gt06FrameDecoderTest.java
new file mode 100644
index 000000000..cf6d1cfd7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gt06FrameDecoderTest.java
@@ -0,0 +1,51 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Gt06FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gt06FrameDecoder decoder = new Gt06FrameDecoder();
+
+ verifyFrame(
+ binary("787803691604130318491475905BD30E25001E10BBF7635D14759006E626560501CC0028660F213228660F1F2828660EA81E286610731428660F20140D0A"),
+ decoder.decode(null, null, binary("787803691604130318491475905BD30E25001E10BBF7635D14759006E626560501CC0028660F213228660F1F2828660EA81E286610731428660F20140D0A")));
+
+ verifyFrame(
+ binary("78780d0103563140414198583c0d0a"),
+ decoder.decode(null, null, binary("78780d0103563140414198583c0d0a")));
+
+ verifyFrame(
+ binary("787800691709261259400700cc0400d376714600d37a3d5000d37a3c5000d393505a00d3765d5a00d376735a00d32e6b640d0a"),
+ decoder.decode(null, null, binary("787800691709261259400700cc0400d376714600d37a3d5000d37a3c5000d393505a00d3765d5a00d376735a00d32e6b640d0a")));
+
+ verifyFrame(
+ binary("7878121011091c0b1e2e98058507f80097a6ac03344a0d0a"),
+ decoder.decode(null, null, binary("7878121011091c0b1e2e98058507f80097a6ac03344a0d0a")));
+
+ verifyFrame(
+ binary("787808171709281135331491827b75594dc8d719a9708452cad719a9708550cad719a97086521491827b75574cac9e17b308085dc8d71939633947cad71939633a480700cc0400d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a0d0a"),
+ decoder.decode(null, null, binary("787808171709281135331491827b75594dc8d719a9708452cad719a9708550cad719a97086521491827b75574cac9e17b308085dc8d71939633947cad71939633a480700cc0400d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a0d0a")));
+
+ verifyFrame(
+ binary("787808134606020002044dc5050d0a"),
+ decoder.decode(null, null, binary("787808134606020002044dc5050d0a")));
+
+ verifyFrame(
+ binary("78781f1210020e14061dcc0476fcd0003e3faf3e14b20000000000000000044ef6740d0a"),
+ decoder.decode(null, null, binary("78781f1210020e14061dcc0476fcd0003e3faf3e14b20000000000000000044ef6740d0a")));
+
+ verifyFrame(
+ binary("78780d010352887071911998000479d00d0a"),
+ decoder.decode(null, null, binary("78780d010352887071911998000479d00d0a")));
+
+ verifyFrame(
+ binary("78782516000000000000c000000000000000000020000900fa0210ef00fb620006640301000468030d0a"),
+ decoder.decode(null, null, binary("78782516000000000000c000000000000000000020000900fa0210ef00fb620006640301000468030d0a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java
new file mode 100644
index 000000000..a6008e682
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gt06ProtocolDecoderTest.java
@@ -0,0 +1,294 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class Gt06ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gt06ProtocolDecoder decoder = new Gt06ProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "787805120099abec0d0a"));
+
+ verifyNull(decoder, binary(
+ "78780D01086471700328358100093F040D0A"));
+
+ verifyPosition(decoder, binary(
+ "787821121303120b2524c70138e363085b549003d43301940057d200cd52c000006aa1ca0d0a"));
+
+ verifyAttribute(decoder, binary(
+ "7878251613020C12141AC5027951430C2A16F60014000900000000001A00007C550300020002F1E70D0A"),
+ Position.KEY_ALARM, Position.ALARM_REMOVING);
+
+ verifyNotNull(decoder, binary(
+ "7878006919012105090303028f01007549e05a00bc9c5c5a007a8d1a5a0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "7878001719011910543607028f0100bc2e695a00bcb3635a00bc27c56400bc447b6400bc46c96400bc33ce6400bc64ca640d0a"));
+
+ verifyAttributes(decoder, binary(
+ "797900de8c120b1502121b013137333d302c3232333d312c3238333d30303030303030302c3436333d30303030303035362c3437333d30303030303030662c3438333d30303030303031312c3242333d30303030303030302c3244333d30303030313839632c3335333d30303030313661382c3336333d30303032386163382c3339333d30303030303230612c3330333d30303030303561612c3439333d30303030303030302c3441333d4b4e4146323431434d4b353031343235352c3341333d30303030303338352c3530333d30303030c0041df0940f89c06700000000c800910d0a"));
+
+ verifyAttributes(decoder, binary(
+ "79790020940A035985708053908307060104900402788950301217070401538F0003E8210D0A"));
+
+ verifyPosition(decoder, binary(
+ "78783c3439000000120a0902093a07031f9e690529be2e00155500000016214901a30308b70000b3fb004aa82b059401a3422100000001000000007d9370b90d0a"));
+
+ verifyAttributes(decoder, binary(
+ "7878079404eb001c705d0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78781219028f0a29e10036f12003040102000875dc0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "79790008940000ed0289d6860d0a"));
+
+ verifyNull(decoder, binary(
+ "797900a59404414c4d313d34353b414c4d323d44353b414c4d333d35353b535441313d34303b4459443d30313b534f533d303538353036313536372c2c3b43454e5445523d3b46454e43453d46656e63652c4f46462c302c302e3030303030302c302e3030303030302c3330302c494e206f72204f55542c303b49434349443d38393937313033313031303038393539303432463b4d4f44453d4d4f44452c312c3138303b0008f65e0d0a"));
+
+ verifyPosition(decoder, binary(
+ "78782222120616083817c5050cc8c801a819d600152400e8011dbf003332000000004862500d0a"));
+
+ verifyAttributes(decoder, binary(
+ "78780B23C00122040001000818720D0A"));
+
+ verifyNotNull(decoder, binary(
+ "78782EA4110C0C02281BF6026C18720C38D22800149C1181CC00010000260E000000000615F8012C05041102FF001058FD0D0A"));
+
+ verifyNotNull(decoder, binary(
+ "78787aa2110c0e06372c813601040000591200000000009d7c01040000591200000000009d7c01040000591200000000009d7c01040000591200000000009d7c01040000591200000000009d7c01040000591200000000009d7c01040000591200000000009d7c0104ff02001801eb4039d10000000000000004fabeb50d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78782727110c0b0e170f850450059107f461ae001c7e0a81360104cb8a00bef32806030c02ff000316b10d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78782322110c070f1b0270000000000000000000040081360104cb8a00bef3000000000523030d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787880a2110b161010140136040000591200000000009d7c01020000591200000000009d7c01020000591200000000009d7c01020000591200000000009d7c01020000591200000000009d7c01020000591200000000009d7c01020000591200000000009d7c0102ff033c1e04ddc28aa6001801eb4039c90000000000000014db84730d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78782ba701cc000000919100000000090617032b3836313832323038343735363200000000000000000100049fb60d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787819a501cc0000009191000000000906170304050400010005f44d0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78782ca3110b10081336f000000000000000000004003901cc0000009191000000000906170304050400010003e0940d0a"));
+
+ verifyNotNull(decoder, binary(
+ "7878A3A2110B0603201501CC010000254E000000000615F804000000254E000000000615F804000000254E000000000615F804000000254E000000000615F804000000254E000000000615F804000000254E000000000615F804000000254E000000000615F80400FF08F483CD4DF4C0D750BD5F8BC5CECFB0D59DAFB459CDA8574E8424C6CC50BD5F6C7E1CC9B0D59D8AA718C90087363040E0C83496727B4DE4C7002919670D0A"));
+
+ verifyNotNull(decoder, binary(
+ "78786CA1110B0413093801CC01000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201000025FC000000000618C10201FF0002000541D70D0A"));
+
+ verifyPosition(decoder, binary(
+ "787822220F0C1D023305C9027AC8180C46586000140001CC00287D001F71000001000820860D0A"));
+
+ verifyAttributes(decoder, binary(
+ "797900262100000000020043006f006d006d0061006e00640020006500720072006f0072002100236e850d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787803691604130318491475905BD30E25001E10BBF7635D14759006E626560501CC0028660F213228660F1F2828660EA81E286610731428660F20140D0A"));
+
+ verifyNotNull(decoder, binary(
+ "787800691710231108500200cc080c4e2fa5640c4e2fa66e0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787800171710231108290200cc080c4e2fa5640c4e2fa5640d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787800691710231109200400cc080c4e2fa55a0c4ec0025a0c4e2fa6640c583918640d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787800691710231111210700cc080c4e2fa55a0c4ec0025a0c4e39295a0c583918640c4e2fa6640c4e2fa4640c4ec854640d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787800171710231112510600cc080c4e2fa55a0c4e2fa55a0c4e2fa55a0c4e2fa55a0c4e2fa55a0c4e2fa55a0d0a"));
+
+ verifyPosition(decoder, binary(
+ "7878121011091c0b1b2999058508040097a89e0034520d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78780869170928113413ac9e17b30808514494fcf6e148596cb0ce2c67bd4a6eb0ce2c67bd4b0018e7d4333e55ec086be7f2df5fe48d8c94fc6657e48d8cb8f378510600cc0400d37a3d4600d37a3c5000d37a3b6400d376716400d305ac6400d393506e0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787808171709281135331491827b75594dc8d719a9708452cad719a9708550cad719a97086521491827b75574cac9e17b308085dc8d71939633947cad71939633a480700cc0400d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a00d37a3d5a0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78783b281108111002050136041bcf0000bf09000000000000000000000000000000000000000000000000000000000000000000000000ff00020007d3280d0a"));
+
+ verifyNotNull(decoder, binary(
+ "7878412c11030b011c1f013604cb8a00b17754cb8a00bef357cb8a00b73f5fcb8900b0e25fcb8900b6655fcb8a00b74960cb8a00b178620701001801eb40393800bbbde10d0a"));
+
+ verifyNotNull(decoder, binary(
+ "7878412c11030b012629013604cb8a00b17757cb8a00b73f5bcb8a00b7495ecb8900b0e25fcb8a00b1b9620000000000ff0000000000ffff01001801eb40393e00c0e6340d0a"));
+
+ verifyPosition(decoder, binary(
+ "787822221106160a1016c60278019407c7783800040001940504700046fc01030100065f570d0a"));
+
+ verifyAttributes(decoder, binary(
+ "797900143311070609020b00000000a0030046000109e4610d0a"));
+
+ verifyAttributes(decoder, binary(
+ "7979003e32110707083819000901fe0a060f006a1e3f24000000000000000000000000000000000000000000000000000000000000000000000000000000012116ba0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "7979007632110706090217000901fe0a060f006a1c2024060f0053a429060f006a1d21060f0053a720060f006f151d0000000000000000000000003844d9e7f7e1773d60e327a9e442405cf28628b9c640a42bb0fc0d0244d855a38c220a4c802aa8da7dab50b0e235ef32dd5348ee0ce77a52540000010a205a0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "7979006f210000000001426174746572793a352e3536562c4e4f524d414c3b20475052532a4c696e6b2055702047534d205369676e616c204c6576656c3a5374726f6e673b204750533a4f46463b2020204c4f434b3a4f46463b204254204d41433a4234413832383034343436323b007260880d0a"));
+
+ verifyPosition(decoder, binary(
+ "7979004a321106170c1b180cc900a875580b7ab4f00010350901fe0a007c0009112424007c000912240081004efe2100c500100f1200000000000000000000000000000000000000000000bc7c900d0a"));
+
+ verifyNotNull(decoder, binary(
+ "79790045321106170c1b13000901fe0a007c0009112424007c000912230081004efe1e00c500100f120000000000000000000000000000000000000710bef565574e37000000b26f140d0a"));
+
+ verifyNull(decoder, binary(
+ "787811010863586038760942a0010000010aa4000d0a"));
+
+ verifyNull(decoder, binary(
+ "78781f3511061a0b24330503107d06084889cb01000100000cfa20e3acd301333fcb0d0a"));
+
+ verifyPosition(decoder, binary(
+ "78783c340000000011061809130c0903107d2408488a5800144c00000000000001940b00b1000047ff000000000500018f42210000000100050003010b69450d0a"));
+
+ verifyPosition(decoder, binary(
+ "78783c34000000001106190336070903107d51084889b900152e0000000043b101940b00b10000480100000000050001a3422100000001000300011bdc7b5f0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "78780a13c40604000201298f5b0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78781f12110616091835d0024bb93007d3fb783dd4c501940500f2006c8504a6e0370d0a"));
+
+ verifyPosition(decoder, binary(
+ "787822221106160a1016c60278019407c7783800040001940504700046fc01030100065f570d0a"));
+
+ verifyNotNull(decoder, binary(
+ "7878661500000000004459443d537563636573732100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010009e82b0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "7979000894000000000338ba0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "79790020940a03516080825457290502194200448892980691312079088572f50004d4350d0a"));
+
+ verifyPosition(decoder, binary(
+ "7979007121000000000143757272656e7420706f736974696f6e214c61743a4e35342e3733393333322c4c6f6e3a4532352e3237333237302c436f757273653a3132362e35332c53706565643a302e303030302c4461746554696d653a323031372d30352d3236202031303a32373a3437000bbee30d0a"));
+
+ verifyAttributes(decoder, binary(
+ "7979003F940D110315102A202141494F494C2C30322C3030382E3239302C3032392E3630302C3531394A2C303430302C3030382E3433302C302C30302C4142001678EA0D0A"));
+
+ verifyAttributes(decoder, binary(
+ "79790039940d2141494f494c2c30322c3030322e3732302c3032392e3530302c3532344a2c303130302c3030332e3430302c302c30302c393309ad72000d0a"));
+
+ verifyNull(decoder, binary(
+ "79790005840016BB1A0D0A"));
+
+ verifyAttributes(decoder, binary(
+ "797900089400000002e852d70d0a"));
+
+ verifyAttributes(decoder, binary(
+ "7979000794050000c9b63e0d0a"));
+
+ verifyNotNull(decoder, binary(
+ "78783b18100c0f1201010195271784005ab63617840002fa47178400ff8f4817840019f3491784005ab54b178400ff8e4c17840019f24cff0002012287c80d0a"));
+
+ verifyPosition(decoder, binary(
+ "7878251610051b0f1c34c5022515d504b5dcd20738080902d4022bdf009cba5006640201006759680d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787866150000000000416c726561647920696e20746865207374617465206f66206675656c20737570706c7920746f20726573756d652c74686520636f6d6d616e64206973206e6f742072756e6e696e672100000000000000000000000000000000000001001981e50d0a"));
+
+ verifyAttributes(decoder, binary(
+ "78782d152500000000437574206f666620746865206675656c20737570706c793a2053756363657373210002013b898a0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "787829152100000000526573746f7265206675656c20737570706c793a2053756363657373210002014077ce0d0a"));
+
+ verifyNull(decoder, binary(
+ "78780D01012345678901234500018CDD0D0A"));
+
+ verifyNull(decoder, binary(
+ "78780d0103534190360660610003c3df0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "78780a13440604000201baaf540d0a"));
+
+ verifyAttributes(decoder, binary(
+ "787825160F0C1D0A2B21C8027AC8040C46581000146F0901CC00287D001F714804040301001C84CF0D0A"));
+
+ verifyPosition(decoder, binary(
+ "78781f120f0a140e150bc505e51e780293a9e800540000f601006e0055da00035f240d0a"),
+ position("2015-10-20 14:21:11.000", true, 54.94535, 24.01762));
+
+ verifyPosition(decoder, binary(
+ "787823120f081b121d37cb01c8e2cc08afd3c020d50201940701d600a1190041ee100576d1470d0a"));
+
+ verifyPosition(decoder, binary(
+ "78781F120B081D112E10CC027AC7EB0C46584900148F01CC00287D001FB8000380810D0A"));
+
+ verifyPosition(decoder, binary(
+ "787819100B031A0B1B31CC027AC7FD0C4657BF0115210001001CC6070D0A"));
+
+ verifyPosition(decoder, binary(
+ "787821120C010C0F151FCF027AC8840C4657EC00140001CC00287D001F720001000F53A00D0A"));
+
+ verifyPosition(decoder, binary(
+ "787825160B051B093523CF027AC8360C4657B30014000901CC00266A001E1740050400020008D7B10D0A"));
+
+ verifyPosition(decoder, binary(
+ "787819100e010903230ec803ae32a60653cded00180000020072feb70d0a"));
+
+ verifyPosition(decoder, binary(
+ "7878471e0e03110b0511c501c664fd074db73f0218a602e003433a002fed40433a0056e14e433a0056104e433a0056fd53433a002eed55433a007e4b57433a002ee25aff00020120f6720d0a"));
+
+ verifyNull(decoder, binary(
+ "7979005bfd0358899050927725004c0020bf984358df603b2ea3a339e54335013a5b56455253494f4e5d47543036445f32305f3630444d325f423235455f5631355f574d5b4255494c445d323031332f31322f32382031353a3234002a3b240d0a7979005bfd0358899050927725004c0020bf984358df603b2ea3a339e54335013a5b56455253494f4e5d47543036445f32305f3630444d325f423235455f5631355f574d5b4255494c445d323031332f31322f32382031353a3234002d4f9b0d0a7979005bfd0358899050927725004c0020bf984358df603b2ea3a339e54335013a5b56455253494f4e5d47543036445f32305f3630444d325f423235455f5631355f574d5b4255494c445d323031332f31322f32382031353a3234003084ff0d0a"));
+
+ verifyNull(decoder, binary(
+ "78788b818300000000534545464e2626004f04220045042626262b37393035343031353534362626262626260410041b0415041a04210415041926262b373930363433333031313526260410043d044f26262b373936303437383430363426260412043e0432043026262b373932383834373738383126262626262626262626262626262626232300020022155d0d0a"));
+
+ verifyPosition(decoder, binary(
+ "787822220e0914160f07c9021a362805090a7800d8b802d402c30e00a98a0105010213f4bb0d0a"));
+
+ verifyNull(decoder, binary(
+ "787811010864717003664467100f190a0002c6d20d0a"));
+
+ verifyNull(decoder, binary(
+ "787811010123456789012345100B3201000171930D0A"));
+
+ verifyNull(decoder, binary(
+ "78780d1f000000000000000200b196a20d0a"));
+
+ verifyPosition(decoder, binary(
+ "78781f12110819110216d402f250340828924055d4c801944600d300c09501429c830d0a"));
+
+ verifyPosition(decoder, binary(
+ "78782516110819110208d402f264dc08289a4058d4c70901944600d300c0954606040600014057e90d0a"));
+
+ verifyNull(decoder, binary(
+ "78780d010359339075005244340d0a"));
+
+ verifyNotNull(decoder, binary(
+ "787800691709261259400700cc0400d376714600d37a3d5000d37a3c5000d393505a00d3765d5a00d376735a00d32e6b640d0a"));
+
+ verifyNull(decoder, binary(
+ "787801080d0a"));
+
+ verifyNull(decoder, binary(
+ "78782E2A0F0C1D071139CA027AC8000C4658000014D83132353230313335333231373730373900000000000001002A6ECE0D0A"));
+
+ verifyNull(decoder, binary(
+ "7878058A000688290D0A"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gt06ProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/Gt06ProtocolEncoderTest.java
new file mode 100644
index 000000000..aceaef434
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gt06ProtocolEncoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class Gt06ProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ Gt06ProtocolEncoder encoder = new Gt06ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_STOP);
+
+ verifyCommand(encoder, command, binary("787812800c0000000052656c61792c312300009dee0d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Gt30ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Gt30ProtocolDecoderTest.java
new file mode 100644
index 000000000..cb792ba09
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Gt30ProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Gt30ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Gt30ProtocolDecoder decoder = new Gt30ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$$005D3037811014 9955102834.000,A,3802.8629,N,02349.7163,E,0.00,,060117,,*13|1.3|26225BD"));
+
+ verifyPosition(decoder, text(
+ "$$005E3037811014 9999\u0003121909.000,A,3802.9133,N,02349.9354,E,0.00,,060117,,*18|1.8|264518B"));
+
+ verifyPosition(decoder, text(
+ "$$00633037811014 9999\u0002121901.000,A,3802.9137,N,02349.9334,E,2.86,18.16,060117,,*3E|1.8|262D752"));
+
+ verifyPosition(decoder, text(
+ "$$005E3037811014 9999\u0001121849.000,A,3802.9094,N,02349.9384,E,0.00,,060117,,*1C|1.2|2683812"));
+
+ verifyPosition(decoder, text(
+ "$$005B3037811124 9955161049.000,A,3802.9474,N,02241.1897,E,0.00,,021115,,*15|2.9|5A639"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/H02FrameDecoderTest.java b/src/test/java/org/traccar/protocol/H02FrameDecoderTest.java
new file mode 100644
index 000000000..bdb2ff37b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/H02FrameDecoderTest.java
@@ -0,0 +1,71 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class H02FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecodeShort() throws Exception {
+
+ H02FrameDecoder decoder = new H02FrameDecoder(0);
+
+ assertEquals(
+ binary("2a48512c3335353438383032303131333931312c56312c3031323934352c412c353233312e37393238332c4e2c30313332342e31303731382c452c302e30352c302c3137303231372c464646464646464623"),
+ decoder.decode(null, null, binary("2a48512c3335353438383032303131333931312c56312c3031323934352c412c353233312e37393238332c4e2c30313332342e31303731382c452c302e30352c302c3137303231372c4646464646464646230d0a")));
+
+ assertEquals(
+ binary("2441060116601245431311165035313006004318210e000000fffffbffff0024"),
+ decoder.decode(null, null, binary("2441060116601245431311165035313006004318210e000000fffffbffff0024")));
+
+ assertEquals(
+ binary("2441060116601245431311165035313006004318210e000000fffffbffff0024"),
+ decoder.decode(null, null, binary("2441060116601245431311165035313006004318210e000000fffffbffff00242a48512c343130363031313636302c56312c3132343535322c412c353033352e333132392c4e2c30303433312e383231312c452c3030302e32302c3030302c3133313131362c464646464642464623")));
+
+ assertEquals(
+ binary("2a48512c3335333538383036303031353536382c56312c3139333530352c412c3830392e303031302c532c333435342e383939372c572c302e30302c302e30302c3239313031332c65666666666266662c3030303264342c3030303030622c3030353338352c3030353261612c323523"),
+ decoder.decode(null, null, binary("2a48512c3335333538383036303031353536382c56312c3139333530352c412c3830392e303031302c532c333435342e383939372c572c302e30302c302e30302c3239313031332c65666666666266662c3030303264342c3030303030622c3030353338352c3030353261612c323523")));
+
+ assertEquals(
+ binary("24430025645511183817091319355128000465632432000100ffe7fbffff0000"),
+ decoder.decode(null, null, binary("24430025645511183817091319355128000465632432000100ffe7fbffff0000")));
+
+ }
+
+ @Test
+ public void testDecodeLong() throws Exception {
+
+ H02FrameDecoder decoder = new H02FrameDecoder(0);
+
+ assertEquals(
+ binary("24410600082621532131081504419390060740418306000000fffffbfdff0015060000002c02dc0c000000001f"),
+ decoder.decode(null, null, binary("24410600082621532131081504419390060740418306000000fffffbfdff0015060000002c02dc0c000000001f")));
+
+ }
+
+ @Test
+ public void testDecodeAlternative() throws Exception {
+
+ H02FrameDecoder decoder = new H02FrameDecoder(0);
+
+ assertEquals(
+ binary("2a48512c343230363131393133302c4e42522c3130323430332c3233382c312c302c372c313131312c323236342c36332c313131312c323236352c35382c313131312c323236362c35302c313131312c333133352c33372c313131312c3630352c33332c313131312c343932302c33302c313131312c3630372c32382c3131303131372c46464646444646462c3623"),
+ decoder.decode(null, null, binary("2a48512c343230363131393133302c4e42522c3130323430332c3233382c312c302c372c313131312c323236342c36332c313131312c323236352c35382c313131312c323236362c35302c313131312c333133352c33372c313131312c3630352c33332c313131312c343932302c33302c313131312c3630372c32382c3131303131372c46464646444646462c3623")));
+
+ assertEquals(
+ binary("2442061191301024031101175540227006012321670c000095fffffbffff001f00000001f800ee010000000032"),
+ decoder.decode(null, null, binary("2442061191301024031101175540227006012321670c000095fffffbffff001f00000001f800ee010000000032")));
+
+ assertEquals(
+ binary("5800009814991024031101175540227006012321670c000095fffffbffff0033"),
+ decoder.decode(null, null, binary("5800009814991024031101175540227006012321670c000095fffffbffff0033")));
+
+ assertEquals(
+ binary("2a48512c343230363131393133302c4e42522c3130323431362c3233382c312c302c372c313131312c323236342c35332c313131312c323236352c36302c313131312c323236362c34342c313131312c333133352c34332c313131312c3630352c33392c313131312c343932302c32392c313131312c3630372c32342c3131303131372c46464646464246462c3623"),
+ decoder.decode(null, null, binary("2a48512c343230363131393133302c4e42522c3130323431362c3233382c312c302c372c313131312c323236342c35332c313131312c323236352c36302c313131312c323236362c34342c313131312c333133352c34332c313131312c3630352c33392c313131312c343932302c32392c313131312c3630372c32342c3131303131372c46464646464246462c3623")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/H02ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/H02ProtocolDecoderTest.java
new file mode 100644
index 000000000..4a5eadf52
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/H02ProtocolDecoderTest.java
@@ -0,0 +1,261 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class H02ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ H02ProtocolDecoder decoder = new H02ProtocolDecoder(null);
+
+ verifyNotNull(decoder, buffer(
+ "*hq,356327081001239,VP1,V,470,002,92,3565,0Y92,19433,30Y92,1340,29#"));
+
+ verifyPosition(decoder, binary(
+ "2435248308419329301047591808172627335900074412294E024138FEFFFFFFFF01120064BA73005ECC"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4210209006,V1,054048,A,2828.2297,N,07733.4332,E,000.5,047,4,080918,EEE7FBDF,4261193,0#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,353505221264507,V2,100220,0,5238.26259,N,00507.33983,E,0.25,0,280917,FFFFFFFF,cc,28, db,d75b#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,,V1,173212,A,2225.78879,S,02829.19021,E,0.00,0,290418,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,353505221264507,VI1,075146,0,5238.25900,N,00507.33429,E,0.54,0,250917,FFFFFFFF,cc,28, db,d75b#"));
+
+ verifyNull(decoder, buffer(
+ "*HQ,353505510948929,V1,,V,,N,,E,0.00,0,,FFFFF7FF,f0,a,11a0,c0c6#"));
+
+ verifyPosition(decoder, buffer(
+ "*hq,356327080425330,VP1,A,2702.7245,S,15251.9311,E,0.48,0.0000,080917#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4209951296,V19,214452,A,5201.0178,N,01830.5029,E,000.00,000,200417,,195.63.13.195,89480610500392633029,BFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*hq,356327080425330,VP1,A,2702.7215,S,15251.9309,E,0.62,0.0000,050917#"));
+
+ verifyNull(decoder, buffer(
+ "*HQ,356327080425330,XT,1,100#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,353111080001055,V3,044855,28403,01,001450,011473,158,-62,0292,0,X,030817,FFFFFBFF#"));
+
+ verifyPosition(decoder, binary(
+ "2442091341332059572807175137358006000183640e000000fffffbfdff001f080000000000ea1e0000000021"));
+
+ verifyNull(decoder, buffer(
+ "*HQ,4109198974,#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,1700086468,LINK,180902,15,0,84,0,0,240517,FFFFFBFF#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,355488020882405,V3,095426,74001,01,010278,045142,128,-92,02DE,0,X,090517,FFFFFBFF#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,355488020882405,V3,095426,74001,04,010278,045142,128,-92,010278,026311,125,,010278,026582,125,,010278,028322,119,,02DD,0,X,090517,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4109179024,V19,181519,V,3853.2587,S,06205.9175,W,000.00,000,090217,,5492932630888,8954315265044716555?,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,8161289587,V1,181933,A,5444.3994,N,02516.3844,E,000.05,000,090317,FFFFBBFF,246,03,00002,41565#"));
+
+ verifyPosition(decoder, binary(
+ "2421305109380127171003170520046500100286297e003085ffffdfffff03440069129344006400001151415a20"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,2130510938,V1,012632,A,0520.0663,N,10028.6324,E,0.286,023,100317,FFFFDFFF,69129336,0,100.0,18,5141,5A20#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4210209006,V1,201812,A,2608.9437,N,08016.2521,W,000.80,000,150317,EFE7F9FF,310,260,0,0,6#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4210209006,V1,201844,A,2608.9437,N,08016.2521,W,000.80,000,150317,FFFFF9FF,310,260,0,0,6#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4109179024,V19,103732,V,3853.2770,S,06205.8678,W,000.00,000,100217,,5492932630888,8954314165044716555?,FFFFFBFF#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,4109179024,NBR,103732,722,310,0,6,8106,32010,23,8101,22007,25,8106,12010,23,8106,22105,22,8101,22012,16,8106,42010,5,100217,FFFFFBFF,5#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,355488020930796,V3,002339,62160,06,024852,035421,148,0,024852,035425,143,,022251,036482,137,,024852,000335,133,,024852,031751,133,,024852,035423,133,,02A1,0,X,010104,EFE7FBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4106012736,V1,224434,A,1827.3855,N,06705.7577,W,000.00,000,100117,FFFFFBFF,310,260,49101,1753,5#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,4208150188,NBR,210249,260,6,0,7,1014,50675,37,1014,50633,27,1014,17933,18,1014,17231,15,1014,50632,12,1014,13211,11,1014,17031,10,281216,FFFFFBFF,2#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,1600068812,NBR,141335,262,02,255,6,431,17003,26,431,11101,13,431,6353,13,431,22172,13,431,11093,13,431,60861,10,151216,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,353588020068342,V1,084436,A,3257.01525,N,00655.03865,W,57.78,40,011216,FFFBFFFF,25c,a, 154,b04c#"));
+
+ verifyNull(decoder, buffer(
+ "*HQ,356803210091319,BS,,2d4,a,1b63,1969,26,1b63,10b2,31,0,0,25,,ffffffff,60#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,1400046168,NBR,160169,460,0,1,4,9338,3692,150,9338,3691,145,9338,3690,140,9338,3692,139,180813,FFFFFBFF#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,1600068860,NBR,120156,262,03,255,6,802,54702,46,802,5032,37,802,54782,30,802,5052,28,802,54712,12,802,5042,12,081116,FFFFFBFF#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,1600068860,NBR,110326,262,03,255,6,802,23152,23,812,49449,14,802,35382,13,802,35402,11,812,56622,09,802,23132,04,081116,FFFFFBFF#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,1600068860,LINK,112137,20,8,67,0,0,081116,FFFFFBFF#"));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,355488020533263,V3,121536,65501,04,000152,014001,156,-64,000161,010642,138,,000152,014003,129,,000152,013973,126,,02E4,0,X,071116,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4209917484,V19,093043,V,5052.9749,N,00426.4322,E,000.00,000,130916,,0032475874141,8944538530000543700F,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,353505220873067,V1,,V,4605.75732,N,01430.73863,E,0.00,0,,FFFFFFEF,125,194, 64,d3#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4210051415,V1,164549,A,0956.3869,N,08406.7068,W,000.00,000,221215,FFFFFBFF,712,01,0,0,6#"),
+ position("2015-12-22 16:45:49.000", true, 9.93978, -84.11178));
+
+ verifyAttributes(decoder, buffer(
+ "*HQ,1451316451,NBR,112315,724,10,2,2,215,2135,123,215,2131,121,011215,FFFFFFFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,1451316485,V1,121557,A,-23-3.3408,S,-48-2.8926,W,0.1,158,241115,FFFFFFFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,1451316485,V1,121557,A,-23-35.3408,S,-48-2.8926,W,0.1,158,241115,FFFFFFFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,355488020119695,V1,050418,,2827.61232,N,07703.84822,E,0.00,0,031015,FFFEFBFF#"),
+ position("2015-10-03 05:04:18.000", false, 28.46021, 77.06414));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,1451316409,V1,030149,A,-23-29.0095,S,-46-51.5852,W,2.4,065,070315,FFFFFFFF#"),
+ position("2015-03-07 03:01:49.000", true, -23.48349, -46.85975));
+
+ verifyNull(decoder, buffer(
+ "*HQ,353588020068342,V1,000000,V,0.0000,0,0.0000,0,0.00,0.00,000000,ffffffff,000106,000002,000203,004c87,16#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,3800008786,V1,062507,V,3048.2437,N,03058.5617,E,000.00,000,250413,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,4300256455,V1,111817,A,1935.5128,N,04656.3243,E,0.00,100,170913,FFE7FBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,123456789012345,V1,155850,A,5214.5346,N,2117.4683,E,0.00,270.90,131012,ffffffff,000000,000000,000000,000000#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,353588010001689,V1,221116,A,1548.8220,S,4753.1679,W,0.00,0.00,300413,ffffffff,0002d4,000004,0001cd,000047#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,354188045498669,V1,195200,A,701.8915,S,3450.3399,W,0.00,205.70,050213,ffffffff,000243,000000,000000#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,2705171109,V1,213324,A,5002.5849,N,01433.7822,E,0.00,000,140613,FFFFFFFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V1,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,FFFFFBFF#\r\n"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V4,S17,130305,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V4,S14,100,10,1,3,130305,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V4,S20,ERROR,130305,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V4,S20,DONE,130305,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,F7FFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V4,R8,ERROR,130305,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V4,S23,165.165.33.250:8800,130305,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V4,S24,thit.gd,130305,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,FFFFFBFF#"));
+
+ verifyPosition(decoder, buffer(
+ "*TH,2020916012,V4,S1,OK,pass_word,130305,050316,A,2212.8745,N,11346.6574,E,14.28,028,220902,FFFFFBFD#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,353588020068342,V1,062840,A,5241.1249,N,954.9490,E,0.00,0.00,231013,ffffffff,000106,000002,000203,004c87,24#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,353505220903211,V1,075228,A,5227.5039,N,01032.8443,E,0.00,0,231013,FFFBFFFF,106,14, 201,2173#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,353505220903211,V1,140817,A,5239.3538,N,01003.5292,E,21.03,312,221013,FFFBFFFF,106,14, 203,1cd#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ,356823035368767,V1,083618,A,0955.6392,N,07809.0796,E,0.00,0,070414,FFFBFFFF,194,3b5, 71,c9a9#"));
+
+ verifyNull(decoder, buffer(
+ "*HQ,8401016597,BASE,152609,0,0,0,0,211014,FFFFFFFF#"));
+
+ verifyPosition(decoder, binary(
+ "2441060116601245431311165035313006004318210e000000fffffbffff0024"));
+
+ verifyPosition(decoder, binary(
+ "24410600082621532131081504419390060740418306000000fffffbfdff0015060000002c02dc0c000000001f"),
+ position("2015-08-31 21:53:21.000", true, 4.69898, -74.06971));
+
+ verifyPosition(decoder, binary(
+ "2427051711092133391406135002584900014337822e000000ffffffffff0000"));
+
+ verifyPosition(decoder, binary(
+ "2427051711092134091406135002584900014337822e000000ffffffffff0000"));
+
+ verifyPosition(decoder, binary(
+ "2410307310010503162209022212874500113466574C014028fffffbffff0000"));
+
+ verifyPosition(decoder, binary(
+ "2441090013450831250401145047888000008554650e000000fffff9ffff001006000000000106020299109c01"));
+
+ verifyPosition(decoder, binary(
+ "24270517030820321418041423307879000463213792000056fffff9ffff0000"));
+
+ verifyPosition(decoder, binary(
+ "2441091144271222470112142233983006114026520E000000FFFFFBFFFF0014060000000001CC00262B0F170A"));
+
+ verifyPosition(decoder, binary(
+ "24971305007205201916101533335008000073206976000000effffbffff000252776566060000000000000000000049"));
+
+ }
+
+ @Test
+ public void testDecodeStatus() throws Exception {
+
+ H02ProtocolDecoder decoder = new H02ProtocolDecoder(null);
+
+ verifyAttribute(decoder, buffer(
+ "*HQ,2705171109,V1,213324,A,5002.5849,N,01433.7822,E,0.00,000,140613,FFFFFFFF#"),
+ Position.KEY_STATUS, 0xFFFFFFFFL);
+
+ verifyAttribute(decoder, binary(
+ "2441091144271222470112142233983006114026520E000000FFFFFBFFFF0014060000000001CC00262B0F170A"),
+ Position.KEY_STATUS, 0xFFFFFBFFL);
+
+ verifyAttribute(decoder, buffer(
+ "*HQ,4210051415,V1,164549,A,0956.3869,N,08406.7068,W,000.00,000,221215,FFFFFBFF,712,01,0,0,6#"),
+ Position.KEY_STATUS, 0xFFFFFBFFL);
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/H02ProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/H02ProtocolEncoderTest.java
new file mode 100644
index 000000000..a7ce3fc7e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/H02ProtocolEncoderTest.java
@@ -0,0 +1,72 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+
+public class H02ProtocolEncoderTest extends ProtocolTest {
+
+ private H02ProtocolEncoder encoder = new H02ProtocolEncoder();
+ private Date time = Date.from(
+ LocalDateTime.of(LocalDate.now(), LocalTime.of(1, 2, 3)).atZone(ZoneOffset.systemDefault()).toInstant());
+
+ @Test
+ public void testAlarmArmEncode() throws Exception {
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ALARM_ARM);
+
+ assertEquals("*HQ,123456789012345,SCF,010203,0,0#", encoder.encodeCommand(command, time));
+ }
+
+ @Test
+ public void testAlarmDisarmEncode() throws Exception {
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ALARM_DISARM);
+
+ assertEquals("*HQ,123456789012345,SCF,010203,1,1#", encoder.encodeCommand(command, time));
+ }
+
+ @Test
+ public void testEngineStopEncode() throws Exception {
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_STOP);
+
+ assertEquals("*HQ,123456789012345,S20,010203,1,1#", encoder.encodeCommand(command, time));
+ }
+
+ @Test
+ public void testEngineResumeEncode() throws Exception {
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_RESUME);
+
+ assertEquals("*HQ,123456789012345,S20,010203,1,0#", encoder.encodeCommand(command, time));
+ }
+
+ @Test
+ public void testPositionPeriodicEncode() throws Exception {
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.set(Command.KEY_FREQUENCY, 10);
+ command.setType(Command.TYPE_POSITION_PERIODIC);
+
+ assertEquals("*HQ,123456789012345,S71,010203,22,10#", encoder.encodeCommand(command, time));
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/HaicomProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/HaicomProtocolDecoderTest.java
new file mode 100644
index 000000000..6d879daf2
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/HaicomProtocolDecoderTest.java
@@ -0,0 +1,28 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class HaicomProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ HaicomProtocolDecoder decoder = new HaicomProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$GPRS012497007097169,T100001,150618,230031,5402267400332464,0004,2014,000001,,,1,00#V040*"),
+ position("2015-06-18 23:00:31.000", true, 40.37790, -3.54107));
+
+ verifyPosition(decoder, text(
+ "$GPRS123456789012345,602S19A,100915,063515,7240649312041079,0019,3156,111000,10004,0000,11111,00LH#V037"));
+
+ verifyPosition(decoder, text(
+ "$GPRS123456789012345,T100001,141112,090751,7240649312041079,0002,1530,000001,,,1,00#V039*"));
+
+ verifyPosition(decoder, text(
+ "$GPRS012497007101250,T100001,141231,152235,7503733600305643,0000,2285,000001,,,1,00#V041*"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/HomtecsProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/HomtecsProtocolDecoderTest.java
new file mode 100644
index 000000000..9acf2ce87
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/HomtecsProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class HomtecsProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ HomtecsProtocolDecoder decoder = new HomtecsProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "MDS0001_R6d1821f7,170323,143601.00,04,,,,,,,,,"));
+
+ verifyPosition(decoder, text(
+ "MDS0001_R6d1821f7,170323,143621.00,06,5105.29914,N,11400.52675,W,0.223,198.41,1,2.12,1042.3"));
+
+ verifyPosition(decoder, text(
+ "strommabus939_R01272028,160217,191003.00,06,5540.12292,N,01237.49814,E,0.391,,1,1.27,1.2"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/HuaShengFrameDecoderTest.java b/src/test/java/org/traccar/protocol/HuaShengFrameDecoderTest.java
new file mode 100644
index 000000000..0f24d4b5c
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/HuaShengFrameDecoderTest.java
@@ -0,0 +1,33 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class HuaShengFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ HuaShengFrameDecoder decoder = new HuaShengFrameDecoder();
+
+ assertEquals(
+ binary("c0010c00120060000000000004000600010100c0"),
+ decoder.decode(null, null, binary("c0010c00120060000000000004000600010100c0")));
+
+ assertEquals(
+ binary("c0010c003e0002000000000010020012a0014f42445f3347315f56312e302e330013a0043335353835353035303434303635380006a08701000006a0a1035fc0"),
+ decoder.decode(null, null, binary("c0010c003e0002000000000010020012a0014f42445f3347315f56312e302e330013a0043335353835353035303434303635380006a08701000006a0a1035fc0")));
+
+ assertEquals(
+ binary("c00000003faa0000000000003ea5a5005a3f00c000000031363037303530373132353700e6d186ffcc7a25002201160010000000010015000000000000000000c0"),
+ decoder.decode(null, null, binary("c00000003faa0000000000003ea5a5005a3f00dbdc00000031363037303530373132353700e6d186ffcc7a25002201160010000000010015000000000000000000c0")));
+
+ assertEquals(
+ binary("C000000041AA00000000000030C000000031353035323630373538323800ADDCC100226AEF0000000000120005000100151206EF0504E99975002903EB80556492CEC0"),
+ decoder.decode(null, null, binary("C000000041AA00000000000030DBDC00000031353035323630373538323800ADDCC100226AEF0000000000120005000100151206EF0504E99975002903EB80556492CEC0")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java
new file mode 100644
index 000000000..319d34e4c
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/HuaShengProtocolDecoderTest.java
@@ -0,0 +1,45 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class HuaShengProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ HuaShengProtocolDecoder decoder = new HuaShengProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "c0010c003c0002000000000044020010a0014f42445f3347315f56322e320013a0043335353835353035313032303536360006a08700000006a0a105c9c0"));
+
+ verifyNull(decoder, binary(
+ "c000000077aa0200000000000e000100143347315f48312e315f56312e30372e54000300133335353835353035303434303635380004000b3531323030303000050005010006000400070004000800050000090018383936313032353431343533333239313833360d000a000f796573696e7465726e6574c0"));
+
+ verifyPosition(decoder, binary(
+ "c00000004baa0000000000000f8000000031363130323030373236333600e6d4f9ffcc78c700000022003600000001001500000000000000000000059bffffffffff0005000a040300000253c0"));
+
+ verifyPosition(decoder, binary(
+ "c00000004baa000000000000098000000031363130303732323236343700e6d4efffcc789f000000000026000000010015000000000000000000000488ffffffffff0005000a10060000008dc0"));
+
+ verifyPosition(decoder, binary(
+ "c00000004baa000000000000098000000031363130303732323236343700e6d4efffcc789f000000000026000000010015000000000000000000000488ffffffffff0005000a10060000008dc0"));
+
+ verifyPosition(decoder, binary(
+ "c00000004baa00000000000005c400000131363037303630323537303800e6c82effcc7cb0003900a30089000000010015000000000000000000f20559ff577ce3980005000a060500000087c0"));
+
+ verifyNull(decoder, binary(
+ "c0010c003e0002000000000010020012a0014f42445f3347315f56312e302e330013a0043335353835353035303434303635380006a08701000006a0a1035fc0"));
+
+ verifyNull(decoder, binary(
+ "c0010c00120060000000000004000600010100c0"));
+
+ verifyNull(decoder, binary(
+ "C00000007EAA020000000000010001001047315F48312E305F56312E3000030013383632393530303238353334333036000400144C342D56374C673979497A7A2D724A6D0005000501000600084341524400070008434152440008000500000900183839383630303530313931343436313130393134000A0009434D4E4554C0"));
+
+ verifyPosition(decoder, binary(
+ "C000000041AA00000000000030C000000031353035323630373538323800ADDCC100226AEF0000000000120005000100151206EF0504E99975002903EB80556492CEC0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/HuabaoFrameDecoderTest.java b/src/test/java/org/traccar/protocol/HuabaoFrameDecoderTest.java
new file mode 100644
index 000000000..2d3937903
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/HuabaoFrameDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class HuabaoFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ HuabaoFrameDecoder decoder = new HuabaoFrameDecoder();
+
+ assertEquals(
+ binary("7e307e087d557e"),
+ decoder.decode(null, null, binary("7e307d02087d01557e")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/HuabaoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/HuabaoProtocolDecoderTest.java
new file mode 100644
index 000000000..d4ae3b50c
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/HuabaoProtocolDecoderTest.java
@@ -0,0 +1,69 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class HuabaoProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ HuabaoProtocolDecoder decoder = new HuabaoProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "7E01000021013345678906000F002C012F373031313142534A2D4D3742203030303030303001D4C1423838383838B47E"));
+
+ verifyPosition(decoder, binary(
+ "7e020000400303000002280042000000000000000301618ab406c31ec800000000000518092116145701040000047830011031010aeb16000c00b28986011780108622216500060089ffffffffc37e"));
+
+ verifyPosition(decoder, binary(
+ "7E0200002A013833501744001900000000000000C201597FA806CC01580080000000081508180721210104000002F502020000030200009F7E"));
+
+ verifyPositions(decoder, binary(
+ "7E0704014301356777777707F5000801002600000000000000030159741206CBFD5001720000000116052709062401040000001D03020000002600000000000000030159746606CBFD50016B0000000116052709065301040000001D0302000000260000000000000003015975E406CBFE58013F0000000116052709072701040000001D0302000000260000000000000003015976DE06CBFF10012E0000000116052709075601040000001D0302000000260000000000000003015976BC06CBFED0012D0000000116052709083001040000001D0302000000260000000000000003015976FE06CBFEC001080000000116052709090001040000001D0302000000260000000000000003015976FE06CBFE7800FC0000000116052709093301040000001D0302000000260000000000000003015977A606CBFF3001080000000116052709100201040000001D030200001F7E"));
+
+ verifyAttributes(decoder, binary(
+ "7E0200002F01357888888800B60000000000000003015972B406CBF6B802230000000116061317571301040000000003020000EB0700050001016708B37E"));
+
+ verifyPositions(decoder, binary(
+ "7E070400F30303000002450064000401003A000000000000000301618AC606C31F20000000000029180514202847010400000000EB16000C00B28986061708003732585700060089FFFFFFFE003A000000000000000301618AE806C31EB800000000009F180514202917010400000000EB16000C00B28986061708003732585700060089FFFFFFFE003A000000000000000301618AE806C31EB800000000009F180514202947010400000000EB16000C00B28986061708003732585700060089FFFFFFFE003A000001000000080301618AE806C31EB800000000009F180514203006010400000000EB16000C00B28986061708003732585700060089FFFFFFFED77E"));
+
+ verifyPosition(decoder, binary(
+ "7e02000054093037612710000700000000000000010223aca000dc9dd800000000000017121417122133362a4d30302c34352c31313336393042383030313233303026303030303030303030303030263132333435363738393031323334353623897e"));
+
+ verifyPosition(decoder, binary(
+ "7e0200002c00160128561400020000000000040001005de1f7065c6cef00000000000017011710044201040000a9002a02000030011b3101030c7e"));
+
+ verifyPosition(decoder, binary(
+ "7e0200002c00160128561400030000000000040007005de13c065c6cdb00160000000017011710054201040000a9002a02000030011b310104e47e"));
+
+ verifyNull(decoder, binary(
+ "7e0100002d0141305678720024002c012f373031313142534a2d41362d424400000000000000000000003035363738373201d4c14238383838386d7e"));
+
+ verifyNull(decoder, binary(
+ "7E0100002D013511221122000500000000373031303748422D52303347424400000000000000000000003233363631303402CBD5424136383630387E"));
+
+ verifyNull(decoder, binary(
+ "7e0100002d007089994489002800000000000000000048422d523033474244000000000000000000000031393036373531024142433030303030d17e"));
+
+ verifyNull(decoder, binary(
+ "7E0102000E013511221122000661757468656E7469636174696F6E3F7E"));
+
+ verifyPosition(decoder, binary(
+ "7E02000032013511221122000700000000000C000301578CC006CA3A5C00470000000014072317201501040000000030011631010BD07E"));
+
+ verifyNull(decoder, binary(
+ "7E010200100940278494700084323031313131303831313333323139369F7E"));
+
+ verifyNull(decoder, binary(
+ "7e010000190940278494700012000000000000000000000000000000000000094027849470000a7e"));
+
+ verifyPosition(decoder, binary(
+ "7e0200002e094027587492000a000000010000000a03083db7001329f3000000140000130412164952010400000012360a0002341502cb0c20085c107e"));
+
+ verifyPosition(decoder, binary(
+ "7e020000220014012499170007000000000000400e012af16f02cbd2ba000000000000150101194257010400000077a97e"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/HuabaoProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/HuabaoProtocolEncoderTest.java
new file mode 100644
index 000000000..771e6d28c
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/HuabaoProtocolEncoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class HuabaoProtocolEncoderTest extends ProtocolTest {
+
+ @Ignore
+ @Test
+ public void testEncode() throws Exception {
+
+ HuabaoProtocolEncoder encoder = new HuabaoProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_STOP);
+
+ verifyCommand(encoder, command, binary("7e81050001080201000027001ff0467e"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/HunterProProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/HunterProProtocolDecoderTest.java
new file mode 100644
index 000000000..f0697f423
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/HunterProProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class HunterProProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ HunterProProtocolDecoder decoder = new HunterProProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ ">0002<$GPRMC,170559.000,A,0328.3045,N,07630.0735,W,0.73,266.16,200816,,,A77, s000078015180\",0MD"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/IdplProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/IdplProtocolDecoderTest.java
new file mode 100644
index 000000000..d211d80ce
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/IdplProtocolDecoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class IdplProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ IdplProtocolDecoder decoder = new IdplProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "*ID1,863071011086474,210314,153218,A,1831.4577,N,07351.1433,E,0.79,240.64,9,20,A,1,4.20,0,1,01,1,0,0,A01,R,935D#"),
+ position("2014-03-21 15:32:18.000", true, 18.524295, 73.852388333333));
+
+ verifyPosition(decoder, text(
+ "*ID1,863071011086474,210314,162752,A,1831.4412,N,07351.0983,E,0.04,213.84,9,25,A,1,4.20,0,1,01,1,0,0,A01,L,EA01#"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/IntellitracProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/IntellitracProtocolDecoderTest.java
new file mode 100644
index 000000000..00b7de094
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/IntellitracProtocolDecoderTest.java
@@ -0,0 +1,64 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class IntellitracProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ IntellitracProtocolDecoder decoder = new IntellitracProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "$OK:TRACKING"));
+
+ verifyPosition(decoder, text(
+ "101000001,20100304075545,121.64547,25.06200,0,0,61,7,2,1,0,0.046,0.000,20100304075546,0"),
+ position("2010-03-04 07:55:45.000", true, 25.06200, 121.64547));
+
+ verifyPosition(decoder, text(
+ "1010000002,20030217132813,121.646060,25.061725,20,157,133,7,0,11,15,0.096,0.000"));
+
+ verifyPosition(decoder, text(
+ "1010000002,20030217132813,121.646060,25.061725,20,157,-133,7,0,11,15,0.096,0.000"));
+
+ verifyPosition(decoder, text(
+ "1001070919,20130405084206,37.903730,48.011377,0,0,235,10,2,2,0,20.211,0.153"));
+
+ verifyPosition(decoder, text(
+ "1010000002,20030217144230,121.646102,25.061398,0,0,139,0,0,0,0,0.093,0.000"));
+
+ verifyPosition(decoder, text(
+ "1010000004,20050513153524,121.646075,25.063675,0,166,50,6,1,0,0,0.118,0.000"));
+
+ verifyPosition(decoder, text(
+ "1010000004,20050513154001,121.646075,25.063675,0,166,55,7,1,0,0,0.096,0.000"));
+
+ verifyPosition(decoder, text(
+ "1010000002,20030217132813,121.646060,25.061725,20,157,0,7,0,11,15"));
+
+ verifyPosition(decoder, text(
+ "12345,1010000002,20030217132813,121.646060,25.061725,20,157,0,7,0,11,15"));
+
+ verifyPosition(decoder, text(
+ "1010000002,20030217144230,121.646102,25.061398,0,0,0,7,2,0,0"));
+
+ verifyPosition(decoder, text(
+ "$RP:12345,1010000002,20030217144230,121.646102,25.061398,0,0,0,7,2,0,0"));
+
+ verifyPosition(decoder, text(
+ "1010000001,20030105092129,121.651598,25.052325,0,0,33,0,1,0,0"));
+
+ verifyPosition(decoder, text(
+ "1010000001,20030105092129,-121.651598,-25.052325,0,0,33,0,1,0,0"));
+
+ verifyPosition(decoder, text(
+ "1015210962,20131010144712,-77.070037,-12.097935,0,0,77,7,2,2,0,0,139446.8,2095,20131010144712,,0.103,0.000"));
+
+ verifyPosition(decoder, text(
+ "1003269480,20131126100258,10.32989,49.93836,0,304,217,6,2,0,0,0.000,0.000,20131126100258,0,0,0,-40,0,0,-273,0,0,0,0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ItsProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ItsProtocolDecoderTest.java
new file mode 100644
index 000000000..7523e29a0
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ItsProtocolDecoderTest.java
@@ -0,0 +1,54 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ItsProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ItsProtocolDecoder decoder = new ItsProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$NRM,ROADRPA,1.8AIS,EA,01,L,869867036341099,,1,11032019,231048,19.25166667,N,73.04615167,E,0.0,230.21,17,12.8,0.80,0.80,airtel,0,1,13.5,4.2,0,O,22,404,90,0CC9,EBC8,19,0CC9,8992,16,0CC9,AB49,15,0CC9,AB44,14,0CC9,F03C,0000,00,002080,C9FBBF99"));
+
+ verifyPosition(decoder, text(
+ "$NRM,ROADRPA,1.7AIS,NR,01,L,869867036345389,,1,25022019,051716,25.12891000,N,75.85587833,E,7.6,350.00,14,284.8,1.00,1.00,AIRTEL,1,1,28.0,4.2,0,C,13,404,70,4E3B,3C84,11,4E3B,39B8,08,4E3B,3965,07,4E3B,48B5,07,4E3B,3C85,0000,00,000551,71978C6B"));
+
+ verifyPosition(decoder, text(
+ "$,03,XYZ123,0.0.1,TA,16,L,869867035297185,MH12AB1234,1,20,02,2019,10,59,13,023.482630,N,086.399673,E,000.1,015.19,21,212.3,01.12,00.58,NOSERV,0,1,00.0,4.6,1,C,11,404,75,082a,db3a,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,01,000013,01dbd51f,"));
+
+ verifyPosition(decoder, text(
+ "$NRM,ROADRPA,1.7AIS,NR,01,L,869867036345389,,1,25022019,051716,25.12891000,N,75.85587833,E,7.6,350.00,14,284.8,1.00,1.00,AIRTEL,1,1,28.0,4.2,0,C,13,404,70,4E3B,3C84,11,4E3B,39B8,08,4E3B,3965,07,4E3B,48B5,07,4E3B,3C85,0000,00,000551,71978C6B"));
+
+ verifyPosition(decoder, text(
+ "$,1,CHVTS,CHVTS1.0,DT,16,L,861359039868243,861359039868243,1,05022019,071225,19.965062,N,73.736088,E,0,050,03,0632,6.67,6.75,Idea Cel,1,1,23.96,4.0,0,W,28,404,004,4e2b,49e,4e2bea86727ab3d6704e2bea7714e2be9d72,0000,00,001133,232"));
+
+ verifyPosition(decoder, text(
+ "$,04,XYZ123,0.0.1,TA,16,L,861359034100626,MH12AB1234,1,12,11,2018,08,53,08,018.489645,N,073.855972,E,000.0,220.04,12,593.0,01.13,00.75,AIRTEL,1,1,00.0,4.1,1,C,18,404,90,0c23,781a,5169,0c23,-093,0000,0000,0000,0000,0000,0000,0000,0000,0000,1000,01,000006,f906c65c,"));
+
+ verifyPosition(decoder, text(
+ "$,A,MFR,7.0,NR,01,L,869026034780985,PJ09BU1234,1,12112018,121953,12.756974,N,077.800025,E,000.0,318.03,15,794.0,001.3,000.7,TAMIL NAD,0,1,13.08,04.13,0,O,22,404,80,0919,71C1,0919,7168,19,0919,71c3,17,0919,71c2,11,0919,7167,09,0011,00,000173,D8,000000.00,,,"));
+
+ verifyPosition(decoder, text(
+ "$,04,XYZ123,0.0.1,TA,16,L,861359034100626,MH12AB1234,1,14,10,2018,04,50,52,018.489624,N,073.855980,E,000.0,039.86,13,584.1,01.11,00.75,AIRTEL,1,1,00.0,4.1,1,C,15,404,90,0c23,781a,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,1000,01,000005,13b75499,"));
+
+ verifyNull(decoder, text(
+ "$,01,XYZ123,0.0.1,861359034137271,MH12AB1234,"));
+
+ verifyNull(decoder, text(
+ "$,02,XYZ123,0.0.1,861359034137271,100,30,00.0,00005,00600,1000,01,00.1,00.0,"));
+
+ verifyPosition(decoder, text(
+ "$,EPB,EMR,861359034100626,SP,00,00,0000,00,00,00,V,000.000000,N,000.000000,E,000.0,000.0,000.00,N,MH12AB1234,0000000000000,d34679e1,"));
+
+ verifyPosition(decoder, text(
+ "$,03,XYZ123,0.0.1,TA,16,L,861359034137271,MH12AB1234,0,00,00,0000,00,00,00,000.000000,N,000.000000,E,000.0,000.00,00,000.0,00.00,00.00,IDEAIN,1,1,00.0,4.0,1,O,16,404,22,2797,11b7,11b9,2797,-087,11b8,2797,-093,11b4,2797,-106,0000,0000,0000,1000,01,000032,8173e058,"));
+
+ verifyPosition(decoder, text(
+ "$,04,XYZ123,0.0.1,BR,06,L,861359034137271,MH12AB1234,0,00,00,0000,00,00,00,000.000000,N,000.000000,E,000.0,000.00,00,000.0,00.00,00.00,IDEAIN,1,1,00.0,3.8,1,O,17,404,22,2797,11b7,11b9,2797,-093,11b8,2797,-098,0000,0000,0000,0000,0000,0000,1000,00,000006,abd26284,"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Ivt401ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Ivt401ProtocolDecoderTest.java
new file mode 100644
index 000000000..b0b416891
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Ivt401ProtocolDecoderTest.java
@@ -0,0 +1,60 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Ivt401ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Ivt401ProtocolDecoder decoder = new Ivt401ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "(TLA,356917051007891,190118,090211,+16.986606,+82.242416,0,66,4,13,1,5,000,00,0.0,11.59,8.30,37.77,0.0,1,1.02,0,0,208,0,0,0,0,000000000,0,0,0,0,0,0,0,1,8654604,5,9,114)"));
+
+ verifyPosition(decoder, text(
+ "(TLN,862107032006249,230218,180500,+18.479728,+73.896339,30,0,944,13,1,5,111,11,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)"));
+
+ verifyPosition(decoder, text(
+ "(TLN,865933030026336,250118,063827,+18.598098,+73.806518,0,79,0,1,1,5,1200,0,0.0,11.50,4.00,36,0,0,1.00,0,0,12702,202,0)"));
+
+ verifyPosition(decoder, text(
+ "(TLA,865933030026336,250118,063838,+18.598110,+73.806518,0,334,0,1,1,5,1200,0,0.0,12.20,4.10,36,0,0,1.00,0,0,12704,0,0,0,0,0,0,0,0,0,0,0,0,1,0,3,203,0)"));
+
+ verifyNull(decoder, text(
+ "(TLB,356917050440515,0,0,+0.0,+0.0,0,0,0,0,0,0,000,00,0.00,12.21,7.95,26.57,0.0,1,1.12,0,0,0,1,90)"));
+
+ verifyPosition(decoder, text(
+ "(TLN,356917050440515,250118,094723,+0.0,+0.0,0,0,0,0,3,5,000,00,0.00,12.25,7.95,27.11,0.0,0,1.13,0,0,0,4,86)"));
+
+ verifyPosition(decoder, text(
+ "(TLA,356917050440515,250118,094733,+0.0,+0.0,0,0,0,0,3,5,000,00,0.00,12.25,7.95,27.20,0.0,0,1.12,0,0,0,0,0,0,0,000000000,0,1,0,0,0,0,0,1,0,0,5,70)"));
+
+ verifyPosition(decoder, text(
+ "(TLN,356917050440515,250118,094733,+0.0,+0.0,0,0,0,0,3,5,000,00,0.00,12.25,7.95,27.20,0.0,0,1.13,0,0,0,6,87)"));
+
+ verifyPosition(decoder, text(
+ "(TLN,356917050440515,250118,103541,+17.015546,+54.080841,0,0,31,12,1,5,000,00,0.0,0.00,8.04,28.59,M+0+0+0+0+0,0,1.12,0,0,2,48,30)"));
+
+ verifyPosition(decoder, text(
+ "(TLN,356917050291991,090315,133525,+12.990582,+77.589080,0,0,944,13,1,5,000,00,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)"));
+
+ verifyPosition(decoder, text(
+ "(TLN,356917050269732,061117,220046,+21.134126,+74.798561,51,28,204,14,1,5,100,00,0.0,13.92,7.82,23.74,0.0,1,1.33,-9,0,429,4848,67)"));
+
+ verifyPosition(decoder, text(
+ "(TLN,356917050269732,061117,220116,+21.137619,+74.800659,52,28,202,14,1,3,100,00,0.0,13.92,7.82,23.74,0.0,1,1.26,-23,0,445,4849,125)"));
+
+ verifyPosition(decoder, text(
+ "(TLA,356917050217335,190115,011336,+12.932403,+79.898887,0,0,71.7,08,3,10,000,00,0.00,10.41,7.07,26.84,0.00,0,0.99,63,0,0,0,0,0,0,000000000,0,0,0,0,0,0,0,2,0,0,14,86)"));
+
+ verifyPosition(decoder, text(
+ "(TLB,356917050291991,090315,133525,+12.990582,+77.589080,0,0,944,13,1,5,000,00,0.00,10.88,6.31,29.55,0.00,0,0.99,66,0,0,88,95)"));
+
+ verifyPosition(decoder, text(
+ "(TLL,356917050217335,190115,011336,+12.932403,+79.898887,0,0,71.7,08,3,10,000,00,0.00,10.41,7.07,26.84,0.00,0,0.99,63,0,0,0,0,0,0,000000000,0,0,0,0,0,0,0,2,0,0,14,86)"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/JpKorjarProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/JpKorjarProtocolDecoderTest.java
new file mode 100644
index 000000000..8179a2bae
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/JpKorjarProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class JpKorjarProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ JpKorjarProtocolDecoder decoder = new JpKorjarProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "KORJAR.PL,329587014519383,160910144240,52.247254N,021.013375E,0.00,1,F:4.18V,1 260 01 794B 3517,"));
+
+ verifyPosition(decoder, text(
+ "KORJAR.PL,329587014519383,160910144240,52.895515N,021.949151E,6.30,212,F:3.94V,0 260 01 794B 3519,"));
+
+ verifyPosition(decoder, text(
+ "KORJAR.PL,329587014519383,160910144240,52.895596N,021.949343E,12.46,087,L:2.18V,1 260 01 794B 3517,"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Jt600FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Jt600FrameDecoderTest.java
new file mode 100644
index 000000000..ae0948987
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Jt600FrameDecoderTest.java
@@ -0,0 +1,39 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Jt600FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Jt600FrameDecoder decoder = new Jt600FrameDecoder();
+
+ verifyFrame(
+ binary("24315011626912001b21111718095900000000000000000e0000005c000000000000000000"),
+ decoder.decode(null, null, binary("24315011626912001b21111718095900000000000000000e0000005c00000000000000000024315011626912001b22111708130400000000000000000e0000005a00000000000000000024315011626912001b22111708140400000000000000000e0000005a000000723e18a61b01")));
+
+ verifyFrame(
+ binary("2475604055531611002311111600311326144436028210791d016c0000001f070000000020c03c4f6d07d80ccf"),
+ decoder.decode(null, null, binary("2475604055531611002311111600311326144436028210791d016c0000001f070000000020c03c4f6d07d80ccf")));
+
+ verifyFrame(
+ binary("2475605035891613002328091601152806086750106533350c00000000000a000000000000e1ff4f97007f1607"),
+ decoder.decode(null, null, binary("2475605035891613002328091601152806086750106533350c00000000000a000000000000e1ff4f97007f1607")));
+
+ verifyFrame(
+ binary("28333132303832303032392C5730312C30323535332E333535352C452C323433382E303939372C532C412C3137313031322C3035333333392C302C382C32302C362C33312C352C32302C323029"),
+ decoder.decode(null, null, binary("28333132303832303032392C5730312C30323535332E333535352C452C323433382E303939372C532C412C3137313031322C3035333333392C302C382C32302C362C33312C352C32302C323029")));
+
+ verifyFrame(
+ binary("24312082002911001B171012053405243809970255335555000406140003EE2B91044D1F02"),
+ decoder.decode(null, null, binary("24312082002911001B171012053405243809970255335555000406140003EE2B91044D1F02")));
+
+ verifyFrame(
+ binary("28373536303430353535332c404a5429"),
+ decoder.decode(null, null, binary("28373536303430353535332c404a5429")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Jt600ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Jt600ProtocolDecoderTest.java
new file mode 100644
index 000000000..2bb4b0fa3
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Jt600ProtocolDecoderTest.java
@@ -0,0 +1,108 @@
+package org.traccar.protocol;
+
+import org.traccar.ProtocolTest;
+
+import org.junit.Test;
+
+public class Jt600ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Jt600ProtocolDecoder decoder = new Jt600ProtocolDecoder(null);
+
+ verifyPositions(decoder, binary(
+ "2475801263981711002713061813333723501622090221558f012f0000002a070000000020c055b88552191f000f0f0f07"));
+
+ verifyPositions(decoder, binary(
+ "24408111888821001B09060908045322564025113242329F0598000001003F0000002D00AB"));
+
+ verifyPositions(decoder, binary(
+ "2475609213701711002701010000020200000000000000000e00000000000f000000000020c164cd7b00d516000f0f0f02"));
+
+ verifyPositions(decoder, binary(
+ "24657060730131001b13111710361906538525079524797f000000000000000003f300036c"));
+
+ verifyPositions(decoder, binary(
+ "24624090196121001b19071703493631277203074235752f295800005308010000768b0822"));
+
+ verifyPositions(decoder, binary(
+ "24624090196123019519071703412131285623074214252f10560000130801000076850819071703420631282832074215165f172c0000030801000076850919071703422131282792074216635f222e0000130801000076850919071703423631282808074218261f212a0000130801000076860819071703435131283678074222928f08350000930801000076860919071703440631283003074223174f19500000930801000076870819071703445131279872074224584f07380000930801000076870819071703453631280643074227091f1b220000530801000076880919071703455131281043074228216f0a260000530801000076880819071703460631281229074228988f0c260000530801000076880819071703462131281551074229954f1f220000530801000076880919071703463631281289074230503f114e0000530801000076880819071703465131281186074230884f094f0000530801000076880819071703470631280308074231240f17500000530801000076880619071703472131280358074231636f0b1d0000530801000076890821"));
+
+ verifyPositions(decoder, binary(
+ "2475604055531611002311111600311326144436028210791d016c0000001f070000000020c03c4f6d07d80ccf"));
+
+ verifyPositions(decoder, binary(
+ "2475201509260111002313101503464722331560113555309F00000000002D0500CB206800F064109326381A03"));
+
+ verifyPositions(decoder, binary(
+ "2475605035891613002328091601152806086750106533350c00000000000a000000000000e1ff4f97007f1607"));
+
+ verifyPosition(decoder, buffer(
+ "(3301210003,U01,040812,185302,T,22.564025,N,113.242329,E,5.21,152,9,32%,00000000000011,10133,5173,22,100,1)"));
+
+ verifyPosition(decoder, buffer(
+ "(3301210003,U02,040812,185302,T,22.564025,N,113.242329,E,5,152,9,32%,00000000000011,10133,5173,22,100,1)"));
+
+ verifyPosition(decoder, buffer(
+ "(3301210003,U03,040812,185302,T,22.564025,N,113.242329,E,5,152,9,32%,00000000000011,10133,5173,22,100,1)"));
+
+ verifyNull(decoder, buffer(
+ "(3301210003,U04)"));
+
+ verifyPosition(decoder, buffer(
+ "(3301210003,U06,1,040812,185302,T,22.564025,N,113.242329,E,5,152,9,32%,0000000000011,10133,5173,22,100,1,300,100,10)"));
+
+ verifyPosition(decoder, buffer(
+ "(3460311327,U01,220916,135251,T,9.552607,N,13.658292,W,0.31,0,9,0%,00001001000000,11012,10,27,0,0,33)"));
+
+ verifyPosition(decoder, buffer(
+ "(3460311327,U01,010100,000024,F,0.000000,N,0.000000,E,0.00,0,0,100%,00000001000000,263,1,18,0,0,33)"));
+
+ verifyNull(decoder, buffer(
+ "(3460311327,@JT)"));
+
+ verifyPosition(decoder, buffer(
+ "(3460311327,U06,11,220916,135643,T,9.552553,N,13.658265,W,0.61,0,9,100%,00000001000000,11012,10,30,0,0,126,0,30)"));
+
+ verifyPosition(decoder, buffer(
+ "(3460311327,U06,10,220916,140619,T,9.552495,N,13.658227,W,0.43,0,7,0%,00101001000000,11012,10,0,0,0,126,0,30)"));
+
+ verifyPositions(decoder, binary(
+ "24311021600111001B16021105591022329862114046227B0598095080012327951435161F"),
+ position("2011-02-16 05:59:10.000", true, 22.54977, -114.07705));
+
+ verifyPositions(decoder, binary(
+ "24312082002911001B171012052831243810120255336425001907190003FD2B91044D1FA0"));
+
+ verifyPositions(decoder, binary(
+ "24312082002911001B1710120533052438099702553358450004061E0003EE000000000C00"));
+
+ verifyPositions(decoder, binary(
+ "24608111888821001B09060908045322564025113242329F0598000001003F0000002D00AB"));
+
+ verifyPosition(decoder, buffer(
+ "(3110312099,W01,11404.6204,E,2232.9961,N,A,040511,063736,4,7,100,4,17,1,1,company)"),
+ position("2011-05-04 06:37:36.000", true, 22.54994, 114.07701));
+
+ verifyPosition(decoder, buffer(
+ "(3120820029,W01,02553.3555,E,2438.0997,S,A,171012,053339,0,8,20,6,31,5,20,20)"));
+
+ verifyPosition(decoder, buffer(
+ "(3330104377,U01,010100,010228,F,00.000000,N,000.000000,E,0,0,0,0%,00001000000000,741,14,22,0,206)"));
+
+ verifyNull(decoder, buffer(
+ "(6221107674,2,U09,129,2,A,280513113036,E,02711.0500,S,1721.0876,A,030613171243,E,02756.7618,S,2300.0325,3491,538200,14400,1)"));
+
+ verifyPosition(decoder, buffer(
+ "(3301210003,U02,040812,185302,T,00.000000,N,000.000000,E,0,0,0,0%,00000000000011,741,51,22,0,1,05)"));
+
+ verifyPosition(decoder, buffer(
+ "(3301210003,U06,4,250916,133207,T,7.011013,N,25.060708,W,27.61,102,10,0%,00101011000000,0,1,0,448,0,126,1,30)"));
+
+ verifyPosition(decoder, buffer(
+ "(3551001012,U01,010100,000032,F,0.000000,N,0.000000,E,0.00,0,0,10%,00000000010000,15748,7923,23,0,0,3E)"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Jt600ProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/Jt600ProtocolEncoderTest.java
new file mode 100644
index 000000000..100d7492a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Jt600ProtocolEncoderTest.java
@@ -0,0 +1,37 @@
+package org.traccar.protocol;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class Jt600ProtocolEncoderTest extends ProtocolTest {
+ Jt600ProtocolEncoder encoder = new Jt600ProtocolEncoder();
+ Command command = new Command();
+
+ @Test
+ public void testEngineStop() throws Exception {
+ command.setType(Command.TYPE_ENGINE_STOP);
+ assertEquals("(S07,0)", encoder.encodeCommand(command));
+ }
+
+ @Test
+ public void testEngineResume() throws Exception {
+ command.setType(Command.TYPE_ENGINE_RESUME);
+ assertEquals("(S07,1)", encoder.encodeCommand(command));
+ }
+
+ @Test
+ public void testSetTimezone() throws Exception {
+ command.setType(Command.TYPE_SET_TIMEZONE);
+ command.set(Command.KEY_TIMEZONE, "GMT+4");
+ assertEquals("(S09,1,240)", encoder.encodeCommand(command));
+ }
+
+ @Test
+ public void testReboot() throws Exception {
+ command.setType(Command.TYPE_REBOOT_DEVICE);
+ assertEquals("(S17)", encoder.encodeCommand(command));
+ }
+}
diff --git a/src/test/java/org/traccar/protocol/KenjiProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/KenjiProtocolDecoderTest.java
new file mode 100755
index 000000000..5596913c9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/KenjiProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class KenjiProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ KenjiProtocolDecoder decoder = new KenjiProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ ">C800000,M005004,O0000,I0002,D124057,A,S3137.2783,W05830.2978,T000.0,H254.3,Y240116,G06*17"),
+ position("2016-01-24 12:40:57.000", true, -31.62131, -58.50496));
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java
new file mode 100644
index 000000000..62b6070b6
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/KhdProtocolDecoderTest.java
@@ -0,0 +1,48 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class KhdProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ KhdProtocolDecoder decoder = new KhdProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "2929b1000605162935b80d"));
+
+ verifyPosition(decoder, binary(
+ "29298e006d1f29402d181117083846801193910365274500000000f80000227ffc3f00001e00500000000000060088000000220019ffc100000000000000000000000000000000007080002000000016ff893839323534303231303734313134323334333639000800233030302e30306e0d"));
+
+ verifyPosition(decoder, binary(
+ "2929a3002e1780c663170216203353003060811013839500000114f8000000ffff5000000a00000000000000060102003db70d"));
+
+ verifyPosition(decoder, binary(
+ "292980002805162935140108074727801129670365336900000103ffff000082fc0000001e78091b000000360d"));
+
+ verifyPosition(decoder, binary(
+ "29298100280A9F9538081228160131022394301140372500000330FF0000007FFC0F00001E000000000034290D"));
+
+ verifyPosition(decoder, binary(
+ "29298000280A81850A120310095750005281370061190800000232F848FFBBFFFF0000001E000000000000ED0D"));
+
+ verifyPosition(decoder, binary(
+ "29298E00280F80815A121218203116022318461140227000720262FB00077C7FBF5600001E3C3200000000850D"));
+
+ verifyPosition(decoder, binary(
+ "29298200230AA2CC391205030505220285947903109550008002078400000002000000000000750D"));
+
+ verifyPosition(decoder, binary(
+ "29298500081DD08C22120312174026026545710312541700000000F819C839FFFF1D00001E00500000003AF90D"));
+
+ verifyPosition(decoder, binary(
+ "292980002822836665140825142037045343770193879200000050ffff000082fc000004b0780b170000002a0d"));
+
+ verifyPosition(decoder, binary(
+ "292980002802425349120811032137022373011140211100000334FFFF000082FC0000001E780913000034DF0D"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/KhdProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/KhdProtocolEncoderTest.java
new file mode 100644
index 000000000..ab858041a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/KhdProtocolEncoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class KhdProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ KhdProtocolEncoder encoder = new KhdProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_STOP);
+
+ verifyCommand(encoder, command, binary("29293900065981972d5d0d"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/L100FrameDecoderTest.java b/src/test/java/org/traccar/protocol/L100FrameDecoderTest.java
new file mode 100644
index 000000000..5ffa3d8d1
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/L100FrameDecoderTest.java
@@ -0,0 +1,31 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class L100FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ L100FrameDecoder decoder = new L100FrameDecoder();
+
+ verifyFrame(
+ binary("41544c2c4c2c3836383334353033383137313936332c4e2c3230313231382c3039333031362c412c3032352e3036373134342c4e2c3035352e3134343833332c452c3030302e302c4750532c333933392c3432342c30332c30303430352c303038383334"),
+ decoder.decode(null, null, binary("41544c2c4c2c3836383334353033383137313936332c4e2c3230313231382c3039333031362c412c3032352e3036373134342c4e2c3035352e3134343833332c452c3030302e302c4750532c333933392c3432342c30332c30303430352c30303838333440")));
+
+ verifyFrame(
+ binary("4c2c41544c2c3836363739353033303437373935322c30312c303033352c"),
+ decoder.decode(null, null, binary("4c2c41544c2c3836363739353033303437373935322c30312c303033352c2a28")));
+
+ verifyFrame(
+ binary("41544c3335363839353033373533333734352c244750524d432c3131313731392e3030302c412c323833382e303034352c4e2c30373731332e333730372c452c302e30302c2c3132303831302c2c2c412a3735242c2330313130303131313030313031302c4e2e432c4e2e432c4e2e432c31323334352e36372c33312e342c342e322c32312c4d43432c4d4e432c4c41432c43656c6c494441544c"),
+ decoder.decode(null, null, binary("200141544c3335363839353033373533333734352c244750524d432c3131313731392e3030302c412c323833382e303034352c4e2c30373731332e333730372c452c302e30302c2c3132303831302c2c2c412a3735242c2330313130303131313030313031302c4e2e432c4e2e432c4e2e432c31323334352e36372c33312e342c342e322c32312c4d43432c4d4e432c4c41432c43656c6c494441544c027a")));
+
+ verifyFrame(
+ binary("41544c3335363839353033373533333734352c244750524d432c3131313731392e3030302c412c323833382e303034352c4e2c30373731332e333730372c452c302e30302c2c3132303831302c2c2c412a3735244c4f432c436f6e6e61756768742043697263757320c2a0436f6e6e617567687420506c61636520c2a04e65772044656c686920c2a044656c6869c2a0496e6469612c2330313130303130313130313031302c322e332c33352e36372c38302c31323334352e36372c33312e342c342e322c32312c4d43432c4d4e432c4c41432c43656c6c494441544c"),
+ decoder.decode(null, null, binary("200341544c3335363839353033373533333734352c244750524d432c3131313731392e3030302c412c323833382e303034352c4e2c30373731332e333730372c452c302e30302c2c3132303831302c2c2c412a3735244c4f432c436f6e6e61756768742043697263757320c2a0436f6e6e617567687420506c61636520c2a04e65772044656c686920c2a044656c6869c2a0496e6469612c2330313130303130313130313031302c322e332c33352e36372c38302c31323334352e36372c33312e342c342e322c32312c4d43432c4d4e432c4c41432c43656c6c494441544c047a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/L100ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/L100ProtocolDecoderTest.java
new file mode 100644
index 000000000..04f586f7a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/L100ProtocolDecoderTest.java
@@ -0,0 +1,51 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class L100ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ L100ProtocolDecoder decoder = new L100ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "ATL,NP,868004029750174,$GPRMC,062943,A,2533.6719,N,09154.3203,E,0,179,311218,,,*39,#01111011000000,0,0,0,934.82,27.13,4.0,25,405,755,15af,974b,0,0,0,ATL"));
+
+ verifyPosition(decoder, text(
+ "ATL,L,868345038171963,N,201218,093016,A,025.067144,N,055.144833,E,000.0,GPS,3939,424,03,00405,008834"));
+
+ verifyPosition(decoder, text(
+ "N,111116,090031,A,028.123456,N,077.123456,E,000.0,GPS,4180,404,11,00159,064753"));
+
+ verifyAttributes(decoder, text(
+ "L,ATLOBD,866795030475584,03,7429,143344,130918,CAN,0101:00076100,0103:0200,0104:3C,0105:84,010A:XX,010B:19,010C:0F98,010D:22,010E:68,010F:5A,0110:XXXX,0111:28,011C:20,011F:XXXX,0121:0000,0122:XXXX,012F:XX,0162:XX,0132:XXXX,0133:61,0143:00A8,0145:0F,0146:XX,0147:30,0148:XX,0149:31,014A:18,014B:XX,014C:92,0151:XX,0131:00BB,0144:8000,015E:XXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0902:XXXXXXXXXXXXXXX"));
+
+ verifyPosition(decoder, text(
+ "H,ATL,866795030478513,02,0981,054448,230318,A,28.633486;N,77.222595;E,0,154,1.14,4.2,18,404,4,88,ad7b,#1031,0,ATL,"));
+
+ verifyNull(decoder, text(
+ "L,ATL,866795030477952,01,0035,"));
+
+ verifyPosition(decoder, text(
+ "ATL861693039769518,$GPRMC,074930.000,A,2838.0112,N,07713.3602,E,0000,223.36,290518,,,A*7E,#01111011000100,0.012689,0,0,2.572415,0,4.015,22,404,4,88,3ad5,0,0.01,1.4_800F_VTS3D3_gen_peri_myn,,internet,00000000,ATL"));
+
+ verifyPosition(decoder, text(
+ "ATL867857039216564,$GPRMC,131101,A,2838.010010,N,7713.354980,E,0,0,240418,,,*09,#00011011000000,0,0,0,10.70,24.31,3.8,0,0,0,0,0ATL"));
+
+ verifyPosition(decoder, text(
+ "ATL867857039216564,$GPRMC,131033,A,2838.010010,N,7713.354980,E,0,51,240418,,,*3D,#00011011000000,0,0,0,10.70,24.31,3.8,20,404,4,88,cfaaATL"));
+
+ verifyPosition(decoder, text(
+ "ATL868004026997257,$GPRMC,095542,A,2838.0107,N,07713.3579,E,0,98,010617,,,*03,#01111011000000,0,0,0,0.01,45.94,4.0,25,404,4,88,3ad5ATL"));
+
+ verifyPosition(decoder, text(
+ "ATL861693035285253,$GPRMC,022040,A,2954.0481,N,07353.1694,E,0,150,280417,,,*36,#01111011000000,0,0,0,82.92,37.92,4.0,23,404,70,163,b178ATL"));
+
+ verifyPosition(decoder, text(
+ "ATL356895037533745,$GPRMC,111719.000,A,2838.0045,N,07713.3707,E,0.00,,120810,,,A*75,#01100111001010,N.C,N.C,N.C,12345.67,31.4,4.2,21,100,000,000001,00000ATL"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/LaipacProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/LaipacProtocolDecoderTest.java
new file mode 100644
index 000000000..31a0434bc
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/LaipacProtocolDecoderTest.java
@@ -0,0 +1,125 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class LaipacProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ LaipacProtocolDecoder decoder = new LaipacProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$AVRMC,80006405,212645,r,3013.9938,N,08133.3998,W,0.00,0.00,010317,a,4076,0,1,0,0,53170583,310260*78"));
+
+ verifyNull(decoder, text(
+ "$AVSYS,99999999,V1.50,SN0000103,32768*15"));
+
+ verifyNull(decoder, text(
+ "$ECHK,99999999,0*35"));
+
+ verifyNull(decoder, text(
+ "$AVSYS,MSG00002,14406,7046811160,64*1A"));
+
+ verifyNull(decoder, text(
+ "$EAVSYS,MSG00002,8931086013104404999,,Owner,0x52014406*76"));
+
+ verifyNull(decoder, text(
+ "$ECHK,MSG00002,0*5E"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,A,4351.0542,N,07923.5445,W,0.29,78.66,180703,0,3.727,17,1,0,0*37"),
+ position("2003-07-18 16:43:39.000", true, 43.85090, -79.39241));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,a,4351.0542,N,07923.5445,W,0.29,78.66,180703,0,3.727,17,1,0,0*17"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,v,4351.0542,N,07923.5445,W,0.29,78.66,180703,0,3.727,17,1,0,0*00"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,r,4351.0542,N,07923.5445,W,0.29,78.66,180703,0,3.727,17,1,0,0*04"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,A,4351.0542,N,07923.5445,W,0.29,78.66,180703,S,3.727,17,1,0,0*54"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,A,4351.0542,N,07923.5445,W,0.29,78.66,180703,T,3.727,17,1,0,0*53"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,A,4351.0542,N,07923.5445,W,0.29,78.66,180703,3,3.727,17,1,0,0*34"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,A,4351.0542,N,07923.5445,W,0.29,78.66,180703,X,3.727,17,1,0,0*5F"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,99999999,164339,A,4351.0542,N,07923.5445,W,0.29,78.66,180703,4,3.727,17,1,0,0*33"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,003016,v,0000.0000,N,00000.0000,E,0.00,0.00,200614,0,3804,167,1,0,0,0D7AB913,020408*23"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,003049,V,0000.0000,N,00000.0000,E,0.00,0.00,200614,H,3804,167,1,0,0,0D7AB913,020408*71"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,041942,V,0000.0000,N,00000.0000,E,0.00,0.00,200614,H,4115,167,1,0,0*0E"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,043703,V,0000.0000,N,00000.0000,E,0.00,0.00,200614,H,4115,167,1,0,0*07"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,043750,V,0000.0000,N,00000.0000,E,0.00,0.00,200614,H,4115,167,1,0,0*01"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,124022,V,0000.0000,N,00000.0000,E,0.00,0.00,240614,3,4076,167,1,0,0,0D7AB913,020408*0D"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,124058,A,5053.0447,N,00557.8549,E,0.45,65.06,240614,0,4037,167,1,0,0,0D7AB913,020408*26"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,124144,A,5053.0450,N,00557.8544,E,0.00,65.06,240614,3,4076,167,1,0,0,0D7AB913,020408*26"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,125142,R,5053.0442,N,00557.8694,E,1.21,40.90,240614,0,4037,167,1,0,0,0D7AB913,020408*33"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,125517,R,5053.0442,N,00557.8694,E,0.00,0.00,240614,H,4076,167,1,0,0,0D7AB913,020408*75"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,043104,p,5114.4664,N,00534.3308,E,0.00,0.00,280614,0,4115,495,1,0,0,0D48C3DC,020408*52"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,MSG00002,050601,P,5114.4751,N,00534.3175,E,0.00,0.00,280614,0,4115,495,1,0,0,0D48C3DC,020408*7D"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,96414215,170046,p,4310.7965,N,07652.0816,E,0.00,0.00,071016,0,4069,98,1,0,0*04"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,999999999999999,111602,r,5050.1262,N,00419.9660,E,0.00,0.00,120318,0,3843,95,1,0,0,3EE4A617,020610*47"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,358174067149865,143456,R,5050.1285,N,00420.0620,E,0.00,309.27,190318,0,3455,119,1,0,0,3EE4A617,020610*54"));
+
+ verifyPosition(decoder, text(
+ "$AVRMC,999999999999999,084514,r,5050.1314,N,00419.9719,E,0.68,306.39,120318,0,3882,84,1,0,0,3EE4A617,020610*4D"));
+
+ //Alarm button
+ verifyPosition(decoder, text(
+ "$AVRMC,358174067149865,142945,R,5050.1254,N,00420.0490,E,0.00,0.00,190318,3,3455,119,1,0,0,3EE4A617,020610*53"));
+
+ //G-Sensor
+ verifyPosition(decoder, text(
+ "$AVRMC,358174067149865,143407,R,5050.1254,N,00420.0490,E,0.00,0.00,190318,8,3455,119,1,0,0,3EE4A617,020610*52"));
+
+ //Powered off
+ verifyPosition(decoder, text(
+ "$AVRMC,358174067149865,143648,A,5050.1141,N,00420.0525,E,1.24,174.38,190318,H,3455,119,1,0,0,3EE4A617,020610*3E"));
+
+ //No network
+ verifyPosition(decoder, text(
+ "$AVRMC,358174067149865,143747,R,5050.1124,N,00420.0542,E,1.34,161.96,190318,a,3416,119,1,0,0*7D"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/M2cProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/M2cProtocolDecoderTest.java
new file mode 100644
index 000000000..65c9cc43b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/M2cProtocolDecoderTest.java
@@ -0,0 +1,27 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class M2cProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ M2cProtocolDecoder decoder = new M2cProtocolDecoder(null);
+
+ verifyPositions(decoder, text(
+ "[#M2C,2020,P1.B1.H3.F9.R1,102,864547034433966,1,L,0,20,171221,062016,28.647552,77.192841,0,0,0.0,0,0,64,255,11983,0,0,0,0.0,0,0,0,404,4,1F6,4D77,31,0*7524\r\n",
+ "#M2C,2020,P1.B1.H3.F9.R1,102,864547034433966,2,L,0,20,171221,062019,28.647552,77.192841,0,0,0.0,0,0,64,255,11983,0,0,0,0.0,0,0,0,404,4,1F6,4D77,31,0*7528\r\n",
+ "#M2C,2020,P1.B1.H3.F9.R1,102,864547034433966,3,L,0,20,171221,062024,28.647552,77.192841,0,0,0.0,0,0,64,255,16292,0,0,0,0.0,0,0,0,404,4,1F6,4D77,31,0*7523\r\n"));
+
+ verifyPositions(decoder, text(
+ "[#M2C,2020,P1.B1.H1.F1.R1,101,862462038980016,2,L,1,100,170704,074933,28.647556,77.192940,900,194,0.0,0,0,0,255,11942,0,0,0,0,0,0,0,0,30068,5051,0,0,1*8159\r\n"));
+
+ verifyPositions(decoder, text(
+ "[#M2C,2020,P1.B1.H1.F1.R1,101,862462038980016,7,L,0,31,170704,075905,28.647615,77.192970,300,260,0.0,6,7,3,255,11967,0,12,0,0,0,0,0,0,19500,5051,0,27,1*8234\r\n",
+ "#M2C,2020,P1.B1.H1.F1.R1,101,862462038980016,8,L,0,33,170704,075905,28.647615,77.192970,300,260,0.0,6,7,0,255,11942,0,12,0,0,0,0,0,0,20300,5051,0,27,1*8217\r\n"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/M2mProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/M2mProtocolDecoderTest.java
new file mode 100644
index 000000000..1c45c976b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/M2mProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class M2mProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ M2mProtocolDecoder decoder = new M2mProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "235A3C2A2624215C287D70212A21254C7C6421220B0B0B"));
+
+ verifyPosition(decoder, binary(
+ "A6E12C2AAADA4628326B2059576E30202A2FE85D20200B"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MaestroProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MaestroProtocolDecoderTest.java
new file mode 100644
index 000000000..c7a7624c0
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MaestroProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MaestroProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MaestroProtocolDecoder decoder = new MaestroProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "@353893040202807,705,UPV-02,1,13.2,17,0,0,16/09/11,11:42:49,0.352705,32.647918,1210.5,0.000000,35.33,11,0.8,0.000,0!\0"));
+
+ verifyPosition(decoder, text(
+ "@353893040202807,705,UPV-02,1,13.4,18,0,0,16/09/11,11:43:30,0.352808,32.647990,1211.0,0.000000,80.96,11,0.8,0.000,0!\0"));
+
+ verifyPosition(decoder, text(
+ "@353893040202807,601,UPV-02,0,13.4,10,0,0,16/11/04,17:21:14,0.352793,32.647927,0,0,0,0,99,0.000,0!\0"));
+
+ verifyPosition(decoder, text(
+ "@123451234512345,531,M2MGTW,1,12.5,30,0,0,11/10/10,09:09:09,22.222222,114.141414,45.6,0.0,160.0,8,1,20!"));
+
+ verifyPosition(decoder, text(
+ "@123451234512345,702,M2MGTW,1,14.7,30,0,1,11/10/10,09:09:09,22.222222,114.141414,45.6,25.12,160.0,8,1,25!"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ManPowerProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ManPowerProtocolDecoderTest.java
new file mode 100644
index 000000000..1d6f80ae3
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ManPowerProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ManPowerProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ManPowerProtocolDecoder decoder = new ManPowerProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "simei:352581250259539,,,tracker,51,24,1.73,130426023608,A,3201.5462,N,03452.2975,E,0.01,28B9,1DED,425,01,1x0x0*0x1*60x+2,en-us,"),
+ position("2013-04-26 02:36:08.000", true, 32.02577, 34.87163));
+
+ verifyPosition(decoder, text(
+ "simei:352581250259539,,,weather,99,20,0.00,130426032310,V,3201.5517,N,03452.3064,E,1.24,28B9,25A1,425,01,1x0x0*0x1*60x+2,en-us,"));
+
+ verifyPosition(decoder, text(
+ "simei:352581250259539,,,SMS,54,19,90.41,130426172308,V,3201.5523,N,03452.2705,E,0.14,28B9,01A5,425,01,1x0x0*0x1*60x+2,en-us,"));
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MegastekFrameDecoderTest.java b/src/test/java/org/traccar/protocol/MegastekFrameDecoderTest.java
new file mode 100644
index 000000000..68606a98a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MegastekFrameDecoderTest.java
@@ -0,0 +1,27 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MegastekFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MegastekFrameDecoder decoder = new MegastekFrameDecoder();
+
+ verifyFrame(
+ binary("30313337244d47563030322c3335343535303035303239323636392c4756543930302c522c3134313231352c3033313830342c412c2c532c2c452c30302c30332c30302c332e36372c302e3030302c302e30302c3131372e312c302e302c3531302c31302c2c2c2c303030302c303030302c32322c31322c302c202c202c2c312d312c39382c5057204f4e3b21"),
+ decoder.decode(null, null, binary("30313337244d47563030322c3335343535303035303239323636392c4756543930302c522c3134313231352c3033313830342c412c2c532c2c452c30302c30332c30302c332e36372c302e3030302c302e30302c3131372e312c302e302c3531302c31302c2c2c2c303030302c303030302c32322c31322c302c202c202c2c312d312c39382c5057204f4e3b21")));
+
+ verifyFrame(
+ binary("244d47563030322c3031333737373030373533363433342c2c522c3031303131342c3030303035372c562c303030302e303030302c4e2c30303030302e303030302c452c30302c30302c30302c39392e392c302e3030302c302e30302c302e302c38302e3236332c3531302c38392c323334322c303330422c2c303030302c303030302c3230302c39362c302c202c202c2c2c2c54696d65723b21"),
+ decoder.decode(null, null, binary("244d47563030322c3031333737373030373533363433342c2c522c3031303131342c3030303035372c562c303030302e303030302c4e2c30303030302e303030302c452c30302c30302c30302c39392e392c302e3030302c302e30302c302e302c38302e3236332c3531302c38392c323334322c303330422c2c303030302c303030302c3230302c39362c302c202c202c2c2c2c54696d65723b210d0a")));
+
+ verifyFrame(
+ binary("53545832363034373520202020202020202020024f244750524d432c3133313131302e30302c562c2c2c2c2c2c2c3036303931332c2c2c4e2a37362c3232322c30312c383135412c443435352c31312c39372c303030302c303030312c302c54696d65723b3735"),
+ decoder.decode(null, null, binary("53545832363034373520202020202020202020024f244750524d432c3133313131302e30302c562c2c2c2c2c2c2c3036303931332c2c2c4e2a37362c3232322c30312c383135412c443435352c31312c39372c303030302c303030312c302c54696d65723b37350d0a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MegastekProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MegastekProtocolDecoderTest.java
new file mode 100644
index 000000000..1bf3dbd25
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MegastekProtocolDecoderTest.java
@@ -0,0 +1,100 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MegastekProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MegastekProtocolDecoder decoder = new MegastekProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "0132$MGV002,869152024261561,,S,310818,133945,V,3814.35442,N,02144.50662,E,00,00,00,99.9,,,44.2,,202,10,,,13,0,0,0,0,90,,,,11,100,Timer;!"));
+
+ verifyPosition(decoder, text(
+ "0151$MGV002,869152024261561,ID,S,070918,155544,V,3814.35419,N,02144.52113,E,00,00,00,99.9,0.062,,12.3,,202,01,0898,D1BE,8,34,1055,0,0,600,,,,11,010,Timer;!"));
+
+ verifyPosition(decoder, text(
+ "0174$MGV002,014682001957744,014682001957744,R,260318,042537,A,3853.77301,N,07728.66673,W,00,09,00,1.06,0.147,329.51,123.3,,310,26,B46C,5E69375,5,0000,0000,0,,,,,,10,019,Timer,,;!"));
+
+ verifyNull(decoder, text(
+ "0112$MGV002,,GVT900-3,S,010114,000003,,,,,,00,00,00,,0.000,0.00,,0.0,,,,,,0000,0000,14,10,0, , ,,1-0,0,Low Ext Vol;!"));
+
+ verifyPosition(decoder, text(
+ "0170$MGV002,354550056642321,GVT900-3,S,011017,090208,A,1635.8484,N,10446.6095,E,00,09,00,0.91,16.980,257.73,177.6,0.0,457,01,0741,00C0,21,0000,0000,20,10,0, , ,,1-1,54,Dist;!"));
+
+ verifyNull(decoder, text(
+ "0140$MGV002,354550056642321,GVT900-3,S,300917,071731,V,,,,,00,00,00,99.9,0.000,0.00,,0.0,457,01,0741,00CD,,0000,0000,20,10,0, , ,,1-1,94,PW ON;!"));
+
+ verifyPosition(decoder, text(
+ "$MGV002,869152024446923,,S,290816,200627,V,5056.21059,N,00439.25034,E,00,00,00,99.9,,,-25.1,,206,01,0BBB,4418,28,,,,,,,,,01,093,Timer;"));
+
+ verifyPosition(decoder, text(
+ "$MGV002,869152024446923,869152024446923,S,240816,151631,A,5053.83335,N,00424.05702,E,00,10,00,0.88,2.645,76.09,22.7,,206,01,07D1,6600,28,,,,,,,,,01,100,Timer;!"));
+
+ verifyPosition(decoder, text(
+ "STX,013950007137061,$GPRMC,191959.000,A,5203.09602,N,00830.77057,E,5.73,255.27,240716,,,A*62,L,Belt Up,imei:013950007137061,0/5,,Battery=52%,,1,262,03,0084,B20E;FD"));
+
+ verifyPosition(decoder, text(
+ "STX,865067021328417,$GPRMC,064721.000,A,4241.2793,N,02321.9762,E,6.74,346.90,300316,,,1*CA,F,Nil-Alarms,imei:865067021328417,9,559.8,Battery=82%,0,284,03,047E,2B5F;99"));
+
+ verifyNull(decoder, text(
+ "0147$MGV002,354550050292669,GVT900,S,141215,031804,A,,S,,E,00,04,00,5.17,0.000,193.05,117.1,0.0,510,10,041B,0A5E,,0000,0000,22,12,0, , ,,1-1,98,Timer;!"));
+
+ verifyNull(decoder, text(
+ "0137$MGV002,354550050292669,GVT900,R,141215,031804,A,,S,,E,00,03,00,3.67,0.000,0.00,117.1,0.0,510,10,,,,0000,0000,22,12,0, , ,,1-1,98,PW ON;!"));
+
+ verifyPosition(decoder, text(
+ "0125$MGV002,860719020193193,DeviceName,R,240214,104742,A,2238.20471,N,11401.97967,E,00,03,00,1.20,0.462,356.23,137.9,1.5,460,07,262C,0F54,25,0000,0000,0,0,0,28.5,28.3,,,100,Timer;"));
+
+ verifyPosition(decoder, text(
+ "$MGV002,860719020193193,DeviceName,R,240214,104742,A,2238.20471,N,11401.97967,E,00,03,00,1.20,0.462,356.23,137.9,1.5,460,07,262C,0F54,25,0000,0000,0,0,0,28.5,28.3,,,100,Timer;!"),
+ position("2014-02-24 10:47:42.000", true, 22.63675, 114.03299));
+
+ verifyPosition(decoder, text(
+ "STX2010101801 j$GPRMC,101053.000,A,2232.7607,N,11404.7669,E,0.00,,231110,,,A*7F,460,00,2795,0E6A,14,94,1000,0000,91,Timer;1D"));
+
+ verifyPosition(decoder, text(
+ "STX,861001005215757,$GPRMC,180118.000,A,4241.330116,N,2321.931251,E,0.00,182.19,130915,,E,A,F,Nil-Alarms,imei:861001005215757,8,577.0,Battery=38%,0,284,03,03E8,3139;7A"));
+
+ verifyPosition(decoder, text(
+ "STX,865067020439090,$GPRMC,171013.000,A,5919.1411,N,01804.1681,E,0.000,294.41,140815,,,A"));
+
+ verifyPosition(decoder, text(
+ "$MGV002,013777007536434,,R,010114,000057,V,0000.0000,N,00000.0000,E,00,00,00,99.9,0.000,0.00,0.0,80.263,510,89,2342,030B,,0000,0000,200,96,0, , ,,,,Timer;!"));
+
+ verifyPosition(decoder, text(
+ "STX,GerAL22,$GPRMC,174752.000,A,3637.060059,S,6416.2354,W,0.00,0.00,030812,,,A*55,F,,imei:861785000249353,05,180.6,Battery=100%,,1,722,310,0FA6,39D0;8F"));
+
+ verifyPosition(decoder, text(
+ "STX,GerAL22,$GPRMC,000051.000,A,3637.079590,S,6416.2148,W,1.72,332.98,010109,,,A*52,L,,imei:861785000249353,03,275.3,Battery=68%,,1,722,07,0515,1413;41"));
+
+ verifyPosition(decoder, text(
+ "STX,,$GPRMC,001339.000,A,4710.85395,N,02733.58209,E,1.65,238.00,010109,,,A*67,L,Help,imei:013227009737796,0/8,137.1,Battery=100%,,0,226,01,2B9B,BBBF;8D"));
+
+ verifyPosition(decoder, text(
+ "STX,102110830074542,$GPRMC,114229.000,A,2238.2024,N,11401.9619,E,0.00,0.00,310811,,,A*64,F,LowBattery,imei:012207005553885,03,113.1,Battery=24%,,1,460,01,2531,647E;57"));
+
+ verifyPosition(decoder, text(
+ "STX863070014949464 $GPRMC,215942.290,A,4200.1831,N,02128.5904,E,003.1,079.8,090813,,,A*6E,294,02,0064,0F3D,18,17,0000,000000,0000,0.00,0.02,0.00,Store;D8"));
+
+ verifyPosition(decoder, text(
+ "STX123456 $GPRMC,063709.000,A,2238.1998,N,11401.9670,E,0.00,,250313,,,A*7F,460,01,2531,647E,11,87,1000,001001,0000,0.00,0.02,0.00,Timer;4A"));
+
+ verifyPosition(decoder, text(
+ "STX260475 $GPRMC,104032.001,A,4022.1119,N,01811.4081,E,000.0,000.0,060913,,,A*67,222,01,815A,D455,11,99,0000,0001,0,Timer;"));
+
+ verifyPosition(decoder, text(
+ "LOGSTX,123456789012345,$GPRMC,225419.000,A,3841.82201,N,09494.73357,W,12.46,135.33,270914,,,A*47,F,,imei:123456789012345,0/6,,Battery=100%,,0,,,5856,78A3;24"));
+
+ verifyPosition(decoder, text(
+ "LOGSTX,123456789012345,$GPRMC,230551.000,A,3841.81956,N,09494.45403,W,0.00,0.00,270914,,,A*7C,L,,imei:123456789012345,0/7,269.7,Battery=100%,,0,,,5856,78A3;83"));
+
+ verifyPosition(decoder, text(
+ "LOGSTX,123456789012345,$GPRMC,230739.000,A,3841.81895,N,09494.12409,W,0.00,0.00,270914,,,A*70,L,,imei:123456789012345,0/7,269.7,Battery=100%,,0,,,5856,78A3;78"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MeiligaoFrameDecoderTest.java b/src/test/java/org/traccar/protocol/MeiligaoFrameDecoderTest.java
new file mode 100644
index 000000000..2d09c626b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MeiligaoFrameDecoderTest.java
@@ -0,0 +1,29 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class MeiligaoFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MeiligaoFrameDecoder decoder = new MeiligaoFrameDecoder();
+
+ assertNull(
+ decoder.decode(null, null, binary("00")));
+
+ assertEquals(
+ binary("2424007b8621700151517899553233323835372e3030302c562c333632372e313835342c4e2c30313034352e323130392c452c302e30302c372c3239303131332c2c2a31347c302e307c347c303030307c303030382c303030357c303235443030303230303541374432327c30367c303030314530353527f40d0a"),
+ decoder.decode(null, null, binary("2424007B8621700151517899553233323835372E3030302C562C333632372E313835342C4E2C30313034352E323130392C452C302E30302C372C3239303131332C2C2A31347C302E307C347C303030307C303030382C303030357C303235443030303230303541374432327C30367C303030314530353527F40D0A")));
+
+ assertEquals(
+ binary("2424007b8621700151517899553233323835372e3030302c562c333632372e313835342c4e2c30313034352e323130392c452c302e30302c372c3239303131332c2c2a31347c302e307c347c303030307c303030382c303030357c303235443030303230303541374432327c30367c303030314530353527f40d0a"),
+ decoder.decode(null, null, binary("002424007B8621700151517899553233323835372E3030302C562C333632372E313835342C4E2C30313034352E323130392C452C302E30302C372C3239303131332C2C2A31347C302E307C347C303030307C303030382C303030357C303235443030303230303541374432327C30367C303030314530353527F40D0A")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java
new file mode 100644
index 000000000..da5a81144
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MeiligaoProtocolDecoderTest.java
@@ -0,0 +1,137 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MeiligaoProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MeiligaoProtocolDecoder decoder = new MeiligaoProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "24240012254748594772ff080002ffff0d0a"));
+
+ verifyNull(decoder, binary(
+ "242403fe254748594772ff99880242681100ffd8ffe000104a46494600010101000000000000ffdb004300080606070605080707070909080a0c140d0c0b0b0c1912130f141d1a1f1e1d1a1c1c20242e2720222c231c1c2837292c30313434341f27393d38323c2e333432ffdb0043010909090c0b0c180d0d1832211c213232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffc000110801e0028003012100021101031101ffda000c03010002110311003f00f0cc679a5a977d84b517d69474a98f615930e3a52edabea50b8a5c54c9e84c9f4178a5c7b50ad617bbd45a5c00287b16d681f852f5eb44aefde32e5bbb0ec0a38eb4d36d9a48753f150f4d5916f74318a70ad5dd8dc75168ed53ccadee8e239452f434afd10921719a7639aad56854ac3c0a5a98cfc8971d6c85a7f6a65ad07e29f8a1b10fc52ff153f405a6e48053f145f4b31abc5928e9cd4cabd3152f4d01ab6a4ca2a50a33509d9d809d56a50b56a7a87c24cbd6a655a2510ea4aa2a555a953b30255a92a80945498a435b8f1520a3d043b14e02974d40752d37a20490b4b40076a2a760129298094949e8030d368527b8c6530d4ddc84861a6353b8119a69e94b402334ca6e5a0861eb4c22b3d876184530d56e85623c506b27cd719e494bdabadab6a2d43e945227588a7d29739e69d92dc7d4703476cd569612d472b6452d4fbb61d828c734d6eac263fb52d539caf7634c55f6a2a1b8885a78e949db94528bd90539714dbea69bea2e7d29d9c51b19db4b053c75abffff0d0a"));
+
+ verifyPosition(decoder, binary(
+ "242400716578902405843299553136323533332e3937382c412c343632332e313137392c4e2c30373932342e323437312c572c303030302c3030302c3139313231372c2c2a31437c31312e357c3139347c303030307c313139322c303030307c3835383030307c30303331343809540d0a"));
+
+ verifyPosition(decoder, binary(
+ "242400716578902405843299553136323533332e3937382c412c343632332e313137392c4e2c30373932342e323437312c572c303030302c3030302c3139313231372c2c2a31437c31312e357c3139347c303030307c313139322c303030307c3835383030307c30303331343809540d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424010a142170525979ff9999753137353830322e3030302c412c313330362e303639342c4e2c31303035342e323439302c452c302e30302c3331332c3234313031372c2c2a30457c302e397c377c323530307c303030302c303030302c303130312c303241447c30323038303030353043313330313638353333427c30427c30303032313034357c30417c2520205e59454e53414241494348414924534f4e474b52414e244d522e5e5e3f3b363030373634333130303530303337333835333d3135303531393637303631343d3f2b202020202020202020202020203234202020202020202020202020312020202020202020202020203030303431313120203030313030545c0d0a"));
+
+ verifyPositions(decoder, binary(
+ "2424006661172036237118668801003039333630342e3030302c562c303330332e333231352c4e2c31303134372e313530302c452c302e30302c2c3235313031377c302e307c302e307c303030307c303030302c303030307c30303030303230343259ca0d0a"));
+
+ verifyPositions(decoder, binary(
+ "242401d961172036237118668805003039353830332e3030302c412c303330332e333431392c4e2c31303134372e343130342c452c372e30342c3230362e36312c3235313031377c302e307c302e307c303230307c303030302c303030307c3030303031313532325c003039353833332e3030302c412c303330332e323630302c4e2c31303134372e333734342c452c31302e33382c3236332e31342c3235313031377c302e307c302e307c303230307c303030302c303030307c3030303031313734355c003039353930332e3030302c412c303330332e313833382c4e2c31303134372e333735362c452c382e34392c3232332e37372c3235313031377c302e307c302e307c303230307c303030302c303030307c3030303031313839375c003039353933332e3030302c412c303330332e313033312c4e2c31303134372e333435332c452c382e37312c3139312e35302c3235313031377c302e307c302e307c303230307c303030302c303030307c3030303031323130325c003130303030302e3030302c412c303330332e313032332c4e2c31303134372e333338372c452c302e30302c3231332e36392c3235313031377c302e307c302e307c303030307c303030312c303030307c3030303031323131380d110d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424007f1092ffffffffff9999523232303534392e3030302c412c333533372e313231372c4e2c30313130302e303633332c452c362e34382c3139332c3238303631372c2c2a30357c302e387c32347c323030307c303030432c303030417c303235443030303230303833354437427c31357c3037303636424142f7310d0a"));
+
+ verifyAttributes(decoder, binary(
+ "242400561001ffffffffff99553030303030302e3030302c562c303030302e303030302c532c30303030302e303030302c572c302e30302c302e30302c3232303839392c2c2c412a37457c7c307c3030303059ae0d0a0000"));
+
+ verifyPosition(decoder, binary(
+ "242400706573402852404799553130313932372e3030302c412c313732362e38323739332c4e2c30373832382e31393637312c452c312e382c362e342c3137313131362c2c2a32427c312e36387c3534342e327c313030307c303030302c303030307c3030303032383638373a1a0d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424007d0000000000000099553231303333302e3030302c562c343533342e333832342c532c30373230332e303630302c572c302e30302c302c3231313031362c2c2a31327c302e307c3332397c323030307c303030452c303030437c303244413030303145413634393541417c31307c30303030303030306e540d0a"));
+
+ verifyAttributes(decoder, binary(
+ "4040005066104020094432990131302E312C302C3135362C302E30302C31392E36312C2D33342C33342E32362C32312E38332C372E39312C313033332C322E36392C362E35352C302C302C309DBF0D0A"));
+
+ verifyAttributes(decoder, binary(
+ "242400736610402421174399553130353033342e3937382c412c333933352e333638392c4e2c30303233382e313638342c452c303034382c3034322c3038313231362c2c2a31437c31312e357c3139347c313030317c303341362c303030307c30303130343030307c3030303030303cd00d0a2424004e66104024211743990131342e312c323638372c39302c32312e35372c342e37312c38352c372e31302c382e31362c342e32372c3130342c302e33342c392e33342c302c312c30b7160d0a2424003266104024211743990232352c322e34302c302e37392c32322c34332c3131392c333735362c37352c3132e4c90d0a"));
+
+ verifyPosition(decoder, binary(
+ "242400746251103044ffff99553033353033392e3939392c412c323832332e373632312c4e2c31303635322e303730342c572c3030302e302c3030302e302c3136303631362c2c2c412a37357c302e397c323038332e327c303030307c303030302c303030307c31303034333736333265780d0a"));
+
+ verifyPosition(decoder, binary(
+ "24240072190820157fffff99553039343335342e3030302c412c313930372e303631392c4e2c30373235312e333235312c452c3031302e312c3138382e352c3234303231362c2c2c412a36427c302e387c36352e327c303830307c303030302c303030307c303336343838373532c73f0d0a"));
+
+ verifyPosition(decoder, binary(
+ "242400680790209818ffff99553038333235382e3030302c412c303131352e393338302c532c30333634382e313430392c452c302e30302c3331352e35352c3132303131367c302e37347c313930322e337c303430307c303030302c303030307c302e30f41b0d0a"));
+
+ verifyNull(decoder, binary(
+ "24240011671440258855405000b24d0d0a"));
+
+ verifyPosition(decoder, binary(
+ "242400706796502079108999553131333131382e3030302c412c313033372e393637382c4e2c30363132312e353637392c572c302e35342c322e34322c3330303931352c2c2c412a37307c302e37377c392e397c303030307c303030302c303161327c3030313138373132374cae0d0a"),
+ position("2015-09-30 11:31:18.000", true, 10.63280, -61.35947));
+
+ verifyPosition(decoder, binary(
+ "24240074630700194707719966009E1F7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007C3132303334302C3238303630362C323430302E303030302C4E2C31323130302E303030302C458F7E0D0A"),
+ position("2006-06-28 12:03:40.000", true, 24.00000, 121.00000));
+
+ verifyPosition(decoder, binary(
+ "24240076220720151fffff99660012b3ab00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c3135303634382c3233303731352c313931352e37323835362c4e2c30373235322e35333034342c456dd00d0a"));
+
+ verifyNull(decoder, binary(
+ "24240000123456FFFFFFFF50008B9B0D0A"));
+
+ verifyPosition(decoder, binary(
+ "242400722015032700004299553134313131352e3030302c412c353031312e343335342c4e2c30303834332e373039322c452c3030302e302c3034342e362c3134303431352c2c2c412a36437c322e317c39392e347c303030307c303030302c303030307c3030303032343730350e480d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424006e241120141fffff99553039333931302e30302c412c313931342e37373736352c4e2c30373235302e36383037322c452c302e3035312c2c3230313231342c2c2c442a37357c302e38327c322e387c303030307c303030302c303030307c3031303833373433311d170d0a"));
+
+ verifyPosition(decoder, binary(
+ "24240000123456FFFFFFFF99553033353634342E3030302C412C323233322E363038332C4E2C31313430342E383133372C452C302E30302C2C3031303830392C2C2A31437C31312E357C3139347C303030307C303030302C3030303069620D0A"));
+
+ verifyPosition(decoder, binary(
+ "242400003358019703581F99553133343335312E3030302C412C303932352E353032352C4E2C30363931342E383130372C572C302E30302C32332C3330313031322C2C2A32437C302E387C3138367C323030307C303132362C303046467C303244453030303244384344423431357C30367C303046443642373995820D0A"));
+
+ verifyPosition(decoder, binary(
+ "242400001691000484124F99553134303630332E3030302C412C303933342E323535342C4E2C30363931332E303936362C572C302E30302C2C3330313031322C2C2A30327C302E387C3230377C30303030FA420D0A"));
+
+ verifyPosition(decoder, binary(
+ "2424000045124220306FFF9999143135353432322E3030302C562C323233302E373632332C4E2C31313430332E343231382C452C302E30302C302C3036303231312C2C2A31417C302E307C32367C303030307C303030302C303030307C303030303030303030303030303030307C36337C3030303030303030BAC10D0A"));
+
+ verifyPosition(decoder, binary(
+ "242400008621700142458F9999503139323935382E3030302C412C333632372E313639392C4E2C30313034332E353632372C452C302E30302C3233392C3039313231322C2C2A30467C312E307C377C303030307C303141392C303139377C303235443030303230303541383639467C31327C3030303333424233E2480D0A"));
+
+ verifyPosition(decoder, binary(
+ "24240000123456789FFFFF99553032303630302E3933302C412C323330392E323035312C4E2C31313331382E383434392C452C302E30302C302E30302C3039303731302C2C2C412A36417C322E367C39362E377C303030307C303030302C334646467C303030303030303030C4520D0A"));
+
+ verifyPosition(decoder, binary(
+ "242400005977203744058499553032303131372E3030302C412C343131372E393231322C4E2C30383133302E323039362C572C302E30302C3330332E38352C3236303231337C312E367C30307C303030307C303030302C3030303071CD0D0A"));
+
+ verifyPosition(decoder, binary(
+ "242400003511111111111199553133343734332e3030332c412c303634382e393836362c532c31303730372e353739352c452c3030302e302c3030302e302c323630333133f3150d0a"));
+
+ verifyPosition(decoder, binary(
+ "242400000091800369764199553038353133302e3030302c412c333035332e313634352c4e2c30373535352e373437362c452c302e30302c32372c3136303431332c2c2a33467c302e387c3234357c323030307c303346372c303030302c303030302c303031422c303030302c303030302c303030302c303030307c303139343030303230314343363237437c31417c3031313630383439e6a70d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424000026016100901fff99553136353835332c412c343130392e36303231322c4e2c3833382e35393131392c572c332e3838332c31322e30302c3034303731332c2c2a34467c322e357c3131307c000600007c0000010f7c303242302c3042333697740d0a"));
+
+ verifyNull(decoder, binary(
+ "2424000067622010053562aa0000010001ae4f00000007800000003039353135362e3030302c412c323632332e383936362c4e2c30353030352e303638302c452c32342e352c3234312e302c323231303133599c0d0a"));
+
+ verifyPosition(decoder, binary(
+ "242400001007ffffffffff99553136323330392e3035342c562c303933312e393136332c4e2c30363931312e383233332c572c2c2c3235313131332c2c2c4e2a36437c7c3135387c303030309cc60d0a"));
+
+ verifyAttributes(decoder, binary(
+ "242400003563070435652099553035323034322e3030302c412c343435382e333536352c4e2c30343130342e343831332c452c302e30302c302e30302c3139303131342c2c2a39437c302e3730303030307c2d3835393131373337367c303130307c307c7c7c4f2a0d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424005035784251ffffff99553030303033362e3938312c562c303933312e333437312c4e2c30363931312e383431322c572c2c2c3238303131342c2c2c4e2a36357c7c3136387c323030305e420d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424007811223344ffffff99553031303735372e3030302c412c323935392e313337342c4e2c30393534302e333238342c572c3030302e302c3038382e372c3234303631342c2c2c412a37397c312e347c33352e317c303030307c303030312c303030307c3030303030333732337c3030303030e39f0d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424007f3568960306760199553131303932342e3030302c412c343533342e323538352c4e2c30313933382e363531342c452c302e30302c2c3237303731342c2c2c412a37317c312e377c3130307c383030307c303737422c303030302c303030302c303030302c303030302c303030302c303030302c303030305dfc0d0a"));
+
+ verifyPosition(decoder, binary(
+ "2424007f2015603256ffff99553230303230392e30302c412c313734342e36393434382c4e2c30383331392e30353537302c452c31302e3236322c3234382e35352c3236303631352c2c2c442a35437c302e39397c33312e397c303830317c303030302c303030637c3030303933303131367c3030376165313035d5550d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MeiligaoProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/MeiligaoProtocolEncoderTest.java
new file mode 100644
index 000000000..ee4a869f9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MeiligaoProtocolEncoderTest.java
@@ -0,0 +1,41 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class MeiligaoProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ MeiligaoProtocolEncoder encoder = new MeiligaoProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_SINGLE);
+
+ verifyCommand(encoder, command, binary("404000111234567890123441016cf70d0a"));
+
+ command.setType(Command.TYPE_POSITION_PERIODIC);
+ command.set(Command.KEY_FREQUENCY, 100);
+
+ verifyCommand(encoder, command, binary("40400013123456789012344102000a2f4f0d0a"));
+
+ command.setType(Command.TYPE_SET_TIMEZONE);
+ command.set(Command.KEY_TIMEZONE, "GMT+8");
+
+ verifyCommand(encoder, command, binary("4040001412345678901234413234383030ad0d0a"));
+
+ command.setType(Command.TYPE_REBOOT_DEVICE);
+
+ verifyCommand(encoder, command, binary("40400011123456789012344902d53d0d0a"));
+
+ command.setType(Command.TYPE_ALARM_GEOFENCE);
+ command.set(Command.KEY_RADIUS, 1000);
+
+ verifyCommand(encoder, command, binary("4040001312345678901234410603e87bb00d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MeitrackFrameDecoderTest.java b/src/test/java/org/traccar/protocol/MeitrackFrameDecoderTest.java
new file mode 100644
index 000000000..53749816e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MeitrackFrameDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class MeitrackFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MeitrackFrameDecoder decoder = new MeitrackFrameDecoder();
+
+ assertEquals(
+ binary("24244e3132372c3836333037313031333830333036362c4141412c33352c2d312e3330323638302c33362e3835323133352c3135303430393231313032362c412c392c302c302e312c302c352c313635332c343039362c33323634382c3633397c30327c313030347c3930432c303030302c307c307c307c3346467c3330302c2a37430d0a"),
+ decoder.decode(null, null, binary("24244e3132372c3836333037313031333830333036362c4141412c33352c2d312e3330323638302c33362e3835323133352c3135303430393231313032362c412c392c302c302e312c302c352c313635332c343039362c33323634382c3633397c30327c313030347c3930432c303030302c307c307c307c3346467c3330302c2a37430d0a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MeitrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MeitrackProtocolDecoderTest.java
new file mode 100644
index 000000000..3e05d5243
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MeitrackProtocolDecoderTest.java
@@ -0,0 +1,110 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MeitrackProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MeitrackProtocolDecoder decoder = new MeitrackProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "242441313038362c3836343530373033313231393937342c4430302c3138303232343037323631345f4331453130395f4e31553144312e6a70672c31342c302cffd8ffdb008400140e0f120f0d14121012171514181e32211e1c1c1e3d2c2e243249404c4b47404645505a736250556d5645466488656d777b8182814e608d978c7d96737e817c011517171e1a1e3b21213b7c5346537c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7cffc000110801e0028003012100021101031101ffdd0004000affc401a20000010501010101010100000000000000000102030405060708090a0b100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa0100030101010101010101010000000000000102030405060708090a0b1100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00cca69ac8d06e3348569884db4845021b498a60371494008692980119a8ca7a5342101a5cd5221a0ab312ed1ee68b943e80dce2a467ffd0c806a48e592270f13b230e841a0096eeea7bb09e6c85b667033552800069c2980e14f15422418a916ad099228a95455089505584140993a2d5fb598a7cae72bd8fa536ae892e8e69e2b9d971168a459fffd1ece8a0028a006b534f4a68ce5b9130a89ab444919a61a6c634d34d21894952310d25002514084a4a00ffd2d2349564086929082929805250025140094940c4a4a04251400949408292819fffd3cca31591a098a5c62801a45464531098a69a6210d371400629a6980628eb400c64cd3791c1aa16c491479393563343105424fcc4d007ffd4c3463c0a94500381a5e3b8cd000c99e57f2a8f3835402834e0d4d08914d4aa6ac4c954d4aad4c4c955aa647a6496236ab51b552132e412e383d3f955b0722b09ab32a0c5a2a0d0ffd5ece8a0028a0061a6d5193dc8daa36ab422334c34c634"));
+
+ verifyPositions(decoder, binary(
+ "24246b3131342c3836353738393032343134303439352c4343452c0000000001005000130006011f05010607071415001b00060800000949010a0c000b9b0119a1011afe010602e934ce0203fc9aeb0004309f13220cafc503000d97741e001c01000000010e0ce8000300092f2e060000b7ff2a33330d0a"));
+
+ verifyPosition(decoder, buffer(
+ "$$^182,864507031245110,AAA,109,13.844553,100.644360,171227173141,A,11,19,0,359,0.8,8,15075,934591,520|4|0643|07D20555,8400,0000|0000|0000|018D|04CB,,,108,0000,,6,0,,,,,10|171227173100*7C"));
+
+ verifyPosition(decoder, buffer(
+ "$$S214,864507031219974,AAA,109,13.844643,100.644395,171207021520,A,10,28,0,31,0.8,6,390,421327,520|0|0016|000F2DB0,8400,0000|0000|0000|018D|04C6,,,108,0000,,6,0,,,,,11|171207091500|171207091500|78|3500|000000|000003*12"));
+
+ verifyPositions(decoder, binary(
+ "24245f3237382c3836353738393032313434373233322c4343452c5b00000003005000130006012305010608070d15001b0006080000091e010a09000b2e0019a1011af90106025c033300039be60c06044f6678210c6f1806000d48db06001c41000000010e0cf60113002005912b830001ff5000130006012305010608070d15001b0006080000091e010a09000b2e0019a0011af90106025c033300039be60c0604506678210c6f1806000d49db06001c41000000010e0cf60113002005912b830001ff5000130006012305010608070d15001b0006080000091e010a09000b2e0019a1011af90106025c033300039be60c0604516678210c6f1806000d4adb06001c41000000010e0cf60113002005912b830001ff2a37460d0a"));
+
+ verifyPosition(decoder, buffer(
+ "$$V177,863835026871173,AAA,35,34.516428,10.470160,170915154043,A,9,12,68,74,0.9,9,1988259,525882,605|2|008C|0007B5A6,0200,0003|0000|0000|01A6|0571,00000001,,3,0000,06FB2E,360,511*74"));
+
+ verifyPosition(decoder, buffer(
+ "$$V177,863835026871173,AAA,35,34.516428,10.470160,170915154043,A,9,12,68,74,0.9,9,1988259,525882,605|2|008C|0007B5A6,0200,0003|0000|0000|01A6|0571,00000001,,3,0000,010A92,360,511*74"));
+
+ verifyPosition(decoder, buffer(
+ "$$B136,011691002364761,AAA,29,47.055220,28.893193,170914144240,V,0,7,0,0,0,132,129754946,129793197,259|2|02F8|413F,0000,000D|000C||028C|,*9E"));
+
+ verifyNotNull(decoder, buffer(
+ "$$F153,863835026880190,AAA,29,25.313160,55.422473,170628150902,V,0,0,0,0,0.0,0,6553,6697,0|0|0000|00000000,0000,0002|0000|0000|018B|0000,,,3,0000,,110,386*22"));
+
+ verifyPosition(decoder, buffer(
+ "$$T143,869013024733944,AAA,1,18.459575,-69.947161,170220142912,A,5,15,10,300,1.6,115,3989,187884,370|2|5337|2B2C,0100,0000|0000|0000|0964|0B04,,*C2"));
+
+ verifyPosition(decoder, buffer(
+ "$$K157,866771027160687,AAA,3,37.040231,10.042391,160412151656,A,10,11,0,48,0.8,21,1035518,774980,605|2|0010|307B,0400,0000|0000|0000|0A47|03E3,,,1,0000,001206*2C"));
+
+ verifyNull(decoder, buffer(
+ "$$D28,353358017784062,D03,OK*F3"));
+
+ verifyPosition(decoder, buffer(
+ "$$A158,79007001520234,AAA,35,40.996370,-8.575065,150730184834,A,8,24,0,1,1.3,173,32573389,31405012,268|3|2BC0|250B,2000,|||0A2D|0000,00000001,,50,,,,,,,,,,,,,*4A"),
+ position("2015-07-30 18:48:34.000", true, 40.99637, -8.57507));
+
+ verifyPosition(decoder, buffer(
+ "$$G145,862106024274815,AAA,35,-1.287125,36.906061,150530054639,A,10,13,12,67,0.8,1621,38359791,42330881,639|2|FB2|2F3,0000,3|0|0|A58|432,,,1,0009,*26"));
+
+ verifyPosition(decoder, buffer(
+ "$$I152,013949004569813,AAA,37,54.739468,25.273648,150208173414,A,5,24,0,73,1.5,165,74,3381,246|1|0065|118A,0000,0003|0003|0000|08D4|0002,006380DF,,1,0008*7C"));
+
+ verifyPosition(decoder, buffer(
+ "$$E141,863071013799553,AAA,35,-1.264521,36.801128,150307132846,A,11,20,0.2,0,5,1767,84045888,36496633,639|02|100E|844,1234,0018|||025D|00CB,*17"));
+
+ verifyPosition(decoder, buffer(
+ "$$m140,013777008931857,AAA,1,54.739580,25.273263,141120144603,V,0,25,0,6,50.0,159,19825,13940,246|1|0065|118A,0100,0000|0000|0000|092A|0001,,*1C"));
+
+ verifyPosition(decoder, buffer(
+ "$$X138,862170010187175,AAA,35,-29.960365,-51.655455,130507201625,A,8,9,0,107,0.9,7,169322,126582,724|6|0547|132B,0000,0009|000A||0278|0000,*BE"));
+
+ verifyPosition(decoder, buffer(
+ "$$X138,862170010187175,AAA,35,-29.960365,-51.655455,130507201625,A,8,9,0,107,0.9,-7,169322,126582,724|6|0547|132B,0000,0009|000A||0278|0000,*BE"));
+
+ verifyPosition(decoder, buffer(
+ "$$]138,012896000475498,AAA,35,-6.138255,106.910545,121205074600,A,5,18,0,0,0,49,3800,24826,510|10|0081|4F4F,0000,0011|0012|0010|0963|0000,,*94"));
+
+ verifyPosition(decoder, buffer(
+ "$$d138,012896000475498,AAA,35,-6.138255,106.910545,121205074819,A,7,18,0,0,0,49,3800,24965,510|10|0081|4F4F,0000,000D|0010|0012|0963|0000,,*BF"));
+
+ verifyPosition(decoder, buffer(
+ "$$j138,012896000475498,AAA,35,-6.138306,106.910655,121205103708,A,3,11,0,0,1,36,4182,35025,510|10|0081|4F4F,0000,000A|000C|000A|0915|0000,,*BF"));
+
+ verifyPosition(decoder, buffer(
+ "$$m139,012896005334567,AAA,35,-33.866423,151.190060,121208020649,A,7,27,0,32,4,13,6150,49517,505|2|0B67|5A6C,0000,0000|0000|0000|0977|0000,,*F1"));
+
+ verifyPosition(decoder, buffer(
+ "$$A141,012896005334567,AAA,35,-33.866543,151.190148,121209081758,A,6,27,0,16,1,48,65551,152784,505|2|0B5F|D9D3,0000,0000|0000|0000|0A39|0000,,*5B"));
+
+ verifyPosition(decoder, buffer(
+ "$$_128,861074020109479,AAA,34,22.512618,114.057065,090215000318,V,0,31,0,0,0,0,0,733,302|720|3EE4|BBB5,0000,0006|0006||028C|0000,*E3"));
+
+ verifyPosition(decoder, buffer(
+ "$$K146,013227004985762,AAA,35,28.618005,-81.246783,131101213828,A,9,22,0,209,1.1,23,80974,1187923,310|260|2A13|634E,0000,0000|0000|0000|09DA|0B34,,*51"));
+
+ verifyPosition(decoder, buffer(
+ "$$E150,013777001165479,AAA,35,10.296601,123.872115,140501161505,A,4,22,1,170,1.4,77,39097,393563,515|3|A0CC|ED96,0000,0008|0003|0000|09D5|0000,,,1,0009*1E"));
+
+ verifyPosition(decoder, buffer(
+ "$$B140,013777001293701,AAA,35,-7.266760,112.743550,140521095314,A,3,22,0,275,2.7,45,1984,8059,510|1|3504|EBFE,0000,0000|0000|0000|0914|0002,,*F9\r\n"));
+
+ verifyPosition(decoder, buffer(
+ "$$J163,123123123123123,AFF,0004,35,58.588926,16.180473,140928192856,A,10,27,0,161,1.2,19,1648894,435695,240|24|88B9|E435,0000,|||0A22|0000,00000001,,50,,,,,,,,,,,,,*70\r\n"));
+
+ verifyPositions(decoder, binary(
+ "24245838362c3336393830303031343039303032312c4343432c020134000100000023381f91ffe354b806c5e3121b0009130000000000000000d33801007cbf0200fe0101000435feeb02000500a3010000000000002a62650d0a"),
+ position("2014-05-24 04:59:49.000", false, -7.26650, 112.74365));
+
+ verifyPositions(decoder, binary(
+ "2424473937302c3336393830303031333436303637342c4343432c020134005b000000010ce304035db9e000ec6f591a000013000000000c001801edb70200c96d0100e60001004838576501000300a101c20400000000010ce304035db9e000ee6f591a000013000000000c001801edb70200ca6d0100e60001004838576501000300a101c20400000000010ce304035db9e000ef6f591a000013000000000c001801edb70200cc6d0100e60001004838576501000300a101c20400000000020ce304035db9e000f76f591a000016000000000c001801edb70200d36d0100e60001004838576502000300a101bf04000000000a0ce304035db9e000f76f591a000016000000000c001801edb70200d46d0100e60001004838576500000300a101bf0400000000020ce304035db9e000fb6f591a000016000000000c001801edb70200d86d0100e60001004838576502000300a101760400000000180ce304035db9e000fc6f591a0000120000000000008c00edb70200d96d0100e60001004838576502000300a10176040000000019b1e2040323b9e0000b70591a0105150600bb0012002901edb70200e76d0100e60001004838576502000300a2017005000000002023e304031fb9e0001070591a010615070027010d001601fcb70200ec6d0100e60001004838576502000300a201800500000000201fe3040302b9e0001170591a010615090019010d001501feb70200ed6d0100e60001004838576502000300a2018005000000002018e30403dcb8e0001270591a0106150b0011010d00150100b80200ee6d0100e60001004838576502000300a2018005000000002036e3040345b8e0001570591a0107150b002d010b0013010ab80200f16d0100e60001004838576502000300a2018005000000002053e3040326b8e0001670591a0107150d0041010b0013010eb80200f26d0100e60001004838576502000300a2018005000000002070e3040310b8e0001770591a0107150e004f010b00130111b80200f36d0100e60001004838576502000300a2018005000000002095e3040306b8e0001870591a0107150d005a010b00140115b80200f46d0100e60001004838576502000300a20180050000000020b3e3040305b8e0001970591a0107150b0060010b00140118b80200f56d0100e60001004838576502000300a20183050000000020cfe3040308b8e0001a70591a0107150b0066010b0014011bb80200f66d0100e60001004838576502000300a20183050000000020eee304030cb8e0001b70591a0106170b0004000d0014011eb80200f76d0100e60001004838576502000300a2018305000000002a62350d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MeitrackProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/MeitrackProtocolEncoderTest.java
new file mode 100644
index 000000000..b63ce5051
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MeitrackProtocolEncoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class MeitrackProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ MeitrackProtocolEncoder encoder = new MeitrackProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_SINGLE);
+
+ assertEquals("@@Q25,123456789012345,A10*68\r\n", encoder.encodeCommand(command));
+
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_REQUEST_PHOTO);
+
+ assertEquals("@@D46,123456789012345,D03,1,camera_picture.jpg*1F\r\n", encoder.encodeCommand(command));
+
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SEND_SMS);
+ command.set(Command.KEY_PHONE, "15360853789");
+ command.set(Command.KEY_MESSAGE, "Meitrack");
+
+ assertEquals("@@f48,123456789012345,C02,0,15360853789,Meitrack*B0\r\n", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MilesmateProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MilesmateProtocolDecoderTest.java
new file mode 100644
index 000000000..be0209975
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MilesmateProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MilesmateProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MilesmateProtocolDecoder decoder = new MilesmateProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "ApiString={A:861359037373030,B:09.8,C:00.0,D:083506,E:2838.5529N,F:07717.8049E,G:000.00,H:170918,I:G,J:00004100,K:0000000A,L:1234,M:126.86}"));
+
+ verifyPosition(decoder, text(
+ "ApiString={A:861359037496211,B:12.7,C:06.0,D:060218,E:2837.1003N,F:07723.3162E,G:016.80,H:310818,I:G,J:10010100,K:0000000A,L:1234,M:358.33}"),
+ position("2018-08-31 06:02:18.000", true, 28.61834, 77.38860));
+
+ verifyPosition(decoder, text(
+ "ApiString={A:862631032208018,B:12.1,C:24.4,D:055852,E:2838.5310N,F:07717.8126E,G:000.0,H:200117,I:G,J:10100100,K:1000000A,L:1234,M:324.45}"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MiniFinderProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MiniFinderProtocolDecoderTest.java
new file mode 100644
index 000000000..afa930e5b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MiniFinderProtocolDecoderTest.java
@@ -0,0 +1,73 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MiniFinderProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MiniFinderProtocolDecoder decoder = new MiniFinderProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "!1,867273023933661,V07S.5701.1621,100"));
+
+ verifyAttributes(decoder, text(
+ "!3,ok"));
+
+ verifyNull(decoder, text(
+ "!1,123456789012345"));
+
+ verifyNull(decoder, text(
+ "!5,17,V"));
+
+ verifyNull(decoder, text(
+ "!1,860719027585011"));
+
+ verifyPosition(decoder, text(
+ "!D,02/05/17,19:56:17,47.083542,15.482373,0,0,100001,479.3,100,4,9,0"));
+
+ verifyPosition(decoder, text(
+ "!D,15/04/17,13:58:53,51.483067,-0.452548,60,180,140001,28.7,47,4,13,0"));
+
+ verifyPosition(decoder, text(
+ "!D,07/04/17,05:42:26,-37.588970,145.121231,0,0,0c0001,185.2,92,7,14,1.2"));
+
+ verifyPosition(decoder, text(
+ "!D,28/11/16,00:04:09,42.926067,-85.747589,124,236,140001,179.8,60,11,16,0"));
+
+ verifyPosition(decoder, text(
+ "!C,30/1/16,1:1:6,31.259157,30.020910,0,0,100001,25.32,100,0.03,0.01,0"));
+
+ verifyPosition(decoder, text(
+ "!A,26/10/12,00:28:41,7.770385,-72.215706,0.0,25101,0"));
+
+ verifyPosition(decoder, text(
+ "!A,01/12/10,13:25:35,22.641724,114.023666,000.1,281.6,0"));
+
+ verifyPosition(decoder, text(
+ "!D,08/07/15,04:01:32,40.428257,-3.704808,0,0,170001,701.7,22,5,14,0"));
+
+ verifyPosition(decoder, text(
+ "!D,08/07/15,04:55:13,40.428257,-3.704932,0,0,180001,680.0,8,8,13,0"));
+
+ verifyPosition(decoder, text(
+ "!D,08/07/15,02:01:32,40.428230,-3.704950,4,170,170001,682.7,43,6,13,0"));
+
+ verifyNull(decoder, text(
+ "!1,860719020212696"));
+
+ verifyPosition(decoder, text(
+ "!D,22/2/14,13:40:58,56.899601,14.811541,0,0,1,176.0,98,5,16,0"),
+ position("2014-02-22 13:40:58.000", true, 56.89960, 14.81154));
+
+ verifyPosition(decoder, text(
+ "!D,22/2/14,13:47:51,56.899517,14.811665,0,0,b0001,179.3,97,5,16,0"));
+
+ verifyPosition(decoder, text(
+ "!D,3/7/13,6:35:30,22.645952,114.040436,0.0,225.8,1f0001,12.11,98,0,0,0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MiniFinderProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/MiniFinderProtocolEncoderTest.java
new file mode 100644
index 000000000..e9422da9f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MiniFinderProtocolEncoderTest.java
@@ -0,0 +1,33 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class MiniFinderProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ MiniFinderProtocolEncoder encoder = new MiniFinderProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SET_TIMEZONE);
+ command.set(Command.KEY_TIMEZONE, "GMT+1");
+
+ assertEquals("123456L+01", encoder.encodeCommand(command));
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SOS_NUMBER);
+ command.set(Command.KEY_INDEX, 2);
+ command.set(Command.KEY_PHONE, "1111111111");
+
+ assertEquals("123456C1,1111111111", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MtxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MtxProtocolDecoderTest.java
new file mode 100644
index 000000000..c4f15d907
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MtxProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MtxProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MtxProtocolDecoder decoder = new MtxProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "#MTX,353815011138124,20101226,195550,41.6296399,002.3611174,000,035,000000.00,X,X,1111,000,0,0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/MxtProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MxtProtocolDecoderTest.java
new file mode 100644
index 000000000..834a35011
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/MxtProtocolDecoderTest.java
@@ -0,0 +1,45 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class MxtProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ MxtProtocolDecoder decoder = new MxtProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "01a631144c7e0008643ad2f456fb2d49747cfe4cbe0ffd002008800000001021000fd43d3f1403000000ff300000f42760001031102445a81fda04"));
+
+ verifyPosition(decoder, binary(
+ "01a631361e7a00082471418b052a2c46b587ffc01ae3fd000008800000000000003345422203000000f000f00000000000ea1e04"));
+
+ verifyPosition(decoder, binary(
+ "01a63118787d00086440628d226e2bc26a97feac8a3afd10210010308000000000000018003d2b10240000005e2f0000f427f21031feff0000593804"));
+
+ verifyPosition(decoder, binary(
+ "01a631bd777d0008646e319e17292ce86798fed4cd3afd102110211030800000102403001f15003e2b102400000034300000f4271021007b175535a7be04"));
+
+ verifyPosition(decoder, binary(
+ "01a631e3f97e00087cf40a98151c2cc46898fee0ce3afd1021001030c0000006102116072e003829bb00000036102100001024000000062b0000f42730004b06a6384b4304"));
+
+ verifyPosition(decoder, binary(
+ "01a63118787d00086468457a466a2bc26a97feac8a3afd10212010308000000000001fe1053d291024000000922f0000f4271021007b17553599bb04"));
+
+ verifyPosition(decoder, binary(
+ "01a63118787d0008648645ec486a2bc26a97feac8a3afd1021001030c0000000001419eb05372b1024000000982a0000f4271021007b17000010308c04"));
+
+ verifyPosition(decoder, binary(
+ "01a631e3f97e00087cfa0af3151c2c126798febace3afd1021801030c0000006102122082f003e29bb00000037102100001024000000ab2f0000f42730004b060000488c04"));
+
+ verifyPosition(decoder, binary(
+ "01a631e3f97e00087cfe0a4b161c2c126798febace3afd1021801030800000071021240731003e2abb00000038102100001024000000c12f0000f42730004b06a638633104"));
+
+ verifyPosition(decoder, binary(
+ "01a63118787d0008648645ec486a2bc26a97feac8a3afd1021001030c0000000001419eb05372b1024000000982a0000f4271021007b17000010308c04"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NavigilProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/NavigilProtocolDecoderTest.java
new file mode 100644
index 000000000..2db4afbf2
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NavigilProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class NavigilProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ NavigilProtocolDecoder decoder = new NavigilProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "01004300040020000000f60203080200e7cd0f510c0000003b00000000000000"));
+
+ verifyPosition(decoder, binary(
+ "0100b3000f0024000000f4a803080200ca0c1151ef8885f0b82e6d130400c00403000000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NavisFrameDecoderTest.java b/src/test/java/org/traccar/protocol/NavisFrameDecoderTest.java
new file mode 100644
index 000000000..0ebfeacd2
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NavisFrameDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.traccar.ProtocolTest;
+
+import org.junit.Test;
+
+public class NavisFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecodeNtcb() throws Exception {
+
+ NavisFrameDecoder frameDecoder = new NavisFrameDecoder();
+
+ verifyFrame(binary(
+ "404e5443010000000000000059009adb2a3e54250000000000ff1500040b0a1008291838001200760ee600000000000000000000000f1500040b0a10ac20703fb1aec23f00000000320149668f430000000000000000000000000000000000000000000000f3808080"),
+ frameDecoder.decode(null, null, binary("404e5443010000000000000059009adb2a3e54250000000000ff1500040b0a1008291838001200760ee600000000000000000000000f1500040b0a10ac20703fb1aec23f00000000320149668f430000000000000000000000000000000000000000000000f3808080")));
+
+ }
+
+ @Test
+ public void testDecodeFlex10() throws Exception {
+
+ NavisFrameDecoder frameDecoder = new NavisFrameDecoder();
+
+ frameDecoder.setFlexDataSize(73);
+
+ verifyFrame(binary(
+ "7e54040000000400000030129957405c000b00632f9857405ccace03021e129101a103000000000000c4005ba3fe3b00000000120046100000000000001aff7f000080bfffff80000080bfffffffff9f"),
+ frameDecoder.decode(null, null, binary("7e54040000000400000030129957405c000b00632f9857405ccace03021e129101a103000000000000c4005ba3fe3b00000000120046100000000000001aff7f000080bfffff80000080bfffffffff9f")));
+
+ verifyFrame(binary(
+ "7e4101080000000917c057405c002b001833c057405cbbce030225129101a00300007c6102408900400c1b3cfce3b23a12004710e000000000001bff7f000080bfffff80000080bfffffffffb2"),
+ frameDecoder.decode(null, null, binary("7e4101080000000917c057405c002b001833c057405cbbce030225129101a00300007c6102408900400c1b3cfce3b23a12004710e000000000001bff7f000080bfffff80000080bfffffffffb2")));
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NavisProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/NavisProtocolDecoderTest.java
new file mode 100644
index 000000000..33a6bab24
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NavisProtocolDecoderTest.java
@@ -0,0 +1,79 @@
+package org.traccar.protocol;
+
+import org.traccar.ProtocolTest;
+
+import org.junit.Test;
+
+public class NavisProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecodeNtcb() throws Exception {
+
+ NavisProtocolDecoder decoder = new NavisProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "404E5443010000007B000000130044342A3E533A383631373835303035323035303739"));
+
+ verifyNull(decoder, binary(
+ "404E5443010000007B000000130047372A3E533A383631373835303035313236303639"));
+
+ verifyPosition(decoder, binary(
+ "404e5443010000000000000059009adb2a3e54250000000000ff1500040b0a1008291838001200760ee600000000000000000000000f1500040b0a10ac20703fb1aec23f00000000320149668f430000000000000000000000000000000000000000000000f3808080"),
+ position("2016-11-11 21:00:04.000", true, 53.74336, 87.14437));
+
+ verifyPositions(decoder, binary(
+ "404e544300000000040000005a00c6812a3e410125e3a60700011705071503011030210c0000fa200910e6000000000000000000000001082106150010ae97643f88a39f3f0000000090001fcc6c450000000000000000000000000000000000000000000000f6808080"));
+
+ verifyPositions(decoder, binary(
+ "404e544301000000000000005a002e6c2a3e410125d7540100001512233a0b0a0f08026300000a000b000b00020000000000000000000c12233b0b0a0f03fd6d3f0fde603f00000000ba0051e0c845000000000000000000000000000000000000000000000080808080"));
+
+ verifyPositions(decoder, binary(
+ "404E5443010000007B0000005A0050692A3E410125DB0E00000015110707110A0C0880630000AA39A2381600020000000000000000000C110708110A0CB389793F1AEF263F00000000120034F516440000000000000000000000FAFF000000FAFF000000FAFF80808080"));
+
+ verifyPosition(decoder, binary(
+ "404e544301000000cdfbf5027200852e2a3e5406aa170000c11116162410001310a9110e80996b281003000a0008000000000000000000d207d207ffffff00fbff00fbff00fbff00fbff00fbff00fbff00fbff2d808080ffffffffffff2b161624100013509b0302b0f89201830500000000000037002fb8cf43eed5843a35003500"),
+ position("2019-01-16 22:22:36.000", true, 56.31800, 44.01523));
+
+ verifyPositions(decoder, binary(
+ "404e54430100000045635902730081972a3e4101060b7e0e000b171328050d00133029110e00bc6141100200000000000000000000000000d207d307ffffff00fbff00fbff00fbff00fbff00fbff00fbff00fbff02808080ffffffffffff4f1328050d001371cd0302c5109101a60300000000000000003d1b37470000000096009600"));
+ }
+
+ @Test
+ public void testDecodeFlex10() throws Exception {
+
+ NavisProtocolDecoder decoder = new NavisProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "404e544301000000c9b5f602130046c52a3e533a383639363936303439373232383235"));
+
+ verifyNull(decoder, binary(
+ "404e544301000000aaecf6021300c8712a3e464c4558b00a0a45ffff300a08080f8388"));
+
+ verifyPosition(decoder, binary(
+ "7e54040000000400000030129957405c000b00632f9857405ccace03021e129101a103000000000000c4005ba3fe3b00000000120046100000000000001aff7f000080bfffff80000080bfffffffff9f"),
+ position("2019-01-17 10:23:20.000", true, 56.33996, 43.80762));
+
+ verifyPositions(decoder, binary(
+ "7e4101080000000917c057405c002b001833c057405cbbce030225129101a00300007c6102408900400c1b3cfce3b23a12004710e000000000001bff7f000080bfffff80000080bfffffffffb2"));
+ }
+
+ @Test
+ public void testDecodeFlex20() throws Exception {
+
+ NavisProtocolDecoder decoder = new NavisProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "404e544301000000a9eef602130043fb2a3e533a383639363936303439373337333835"));
+
+ verifyNull(decoder, binary(
+ "404e544301000000a9eef6021a003f8e2a3e464c4558b014147afffff008080800000e00000000000000"));
+
+ verifyPosition(decoder, binary(
+ "7e5428000000280000002111d16b435c00a900154bd16b435ce19e030259f6920133050000b7623e429300c9e7f03f2ba45a3e1f001f007b6c5910850f0100001629080a000000000000060947"),
+ position("2019-01-19 18:26:25.000", true, 56.31952, 44.01423));
+
+ verifyPositions(decoder, binary(
+ "7e4101270000000b17b16b435c00a9000d4bb26b435caaa2030229f29201620500000000000093004493d53fee892d3e1f001f00ac6c591081f00000001700080a0000000000000609f2"));
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NeosProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/NeosProtocolDecoderTest.java
new file mode 100644
index 000000000..a8db30476
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NeosProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class NeosProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ NeosProtocolDecoder decoder = new NeosProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ ">12345678,1,1,070201,144111,W05829.2613,S3435.2313,,00,034,25,00,126-000,0,3,11111111*2d!\r\n"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NoranProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/NoranProtocolDecoderTest.java
new file mode 100644
index 000000000..7c02402b1
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NoranProtocolDecoderTest.java
@@ -0,0 +1,45 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class NoranProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ NoranProtocolDecoder decoder = new NoranProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "0d0a2a4b57000d000080010d0a"));
+
+ verifyPosition(decoder, binary(
+ "34000800010b0000000000003f43bb8da6c2ebe229424e523039423233343439000031362d30392d31352030373a30303a303700"));
+
+ verifyPosition(decoder, binary(
+ "28003200c380000000469458408c4ad340ad381e3f4e52303947313336303900000001ff00002041"));
+
+ verifyPosition(decoder, binary(
+ "28003200c38000d900fcc97a416b1a7a42b43eef3d4e523039473034383737000000000092fcda4a"));
+
+ verifyPosition(decoder, binary(
+ "3400080001090000000000001D43A29BE842E62520424E523039423036363932000031322D30332D30352031313A34373A343300"));
+
+ verifyPosition(decoder, binary(
+ "34000800010c000000000080a3438e20944149bd07c24e523039423139323832000031352d30342d32362030383a34333a353300"));
+
+ verifyNull(decoder, binary(
+ "0f0000004e52303946303431353500"));
+
+ verifyPosition(decoder, binary(
+ "22000800010c008a007e9daa42317bdd41a7f3e2384e523039463034313535000000"));
+
+ verifyPosition(decoder, binary(
+ "34000800010c0000000000001c4291251143388d17c24e523039423131303930000031342d31322d32352030303a33333a303700"));
+
+ verifyPosition(decoder, binary(
+ "34000800010c00000000000000006520944141bd07c24e523039423139323832000031352d30342d32352030303a30333a323200"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NoranProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/NoranProtocolEncoderTest.java
new file mode 100644
index 000000000..38599e0ba
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NoranProtocolEncoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class NoranProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ NoranProtocolEncoder encoder = new NoranProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_STOP);
+
+ verifyCommand(encoder, command, binary(
+ "0d0a2a4b5700440002000000000000002a4b572c3030302c3030372c3030303030302c302300000000000000000000000000000000000000000000000000000000000d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NvsFrameDecoderTest.java b/src/test/java/org/traccar/protocol/NvsFrameDecoderTest.java
new file mode 100644
index 000000000..8a00207eb
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NvsFrameDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class NvsFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ NvsFrameDecoder decoder = new NvsFrameDecoder();
+
+ assertEquals(
+ binary("0012333537303430303630303137383234312e38"),
+ decoder.decode(null, null, binary("0012333537303430303630303137383234312e38")));
+
+ assertEquals(
+ binary("cccccccc0073000144b9ddf2aca002015694823d1f165d80902139a44f00aa001e1400000103000a080115001a001d001e0141004001f00065001301061600001700001800004231da430000440000085000000000480000000049000000004a0000000047ffffffff6900000004c700000000e10000000100954a"),
+ decoder.decode(null, null, binary("cccccccc0073000144b9ddf2aca002015694823d1f165d80902139a44f00aa001e1400000103000a080115001a001d001e0141004001f00065001301061600001700001800004231da430000440000085000000000480000000049000000004a0000000047ffffffff6900000004c700000000e10000000100954a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NvsProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/NvsProtocolDecoderTest.java
new file mode 100644
index 000000000..9a516e733
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NvsProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class NvsProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ NvsProtocolDecoder decoder = new NvsProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "0012333537303430303630303137383234312e38"));
+
+ verifyNull(decoder, binary(
+ "0012313233343536373839303132333435312E31"));
+
+ verifyPositions(decoder, binary(
+ "cccccccc0073000144b9ddf2aca002015694823d1f165d80902139a44f00aa001e1400000103000a080115001a001d001e0141004001f00065001301061600001700001800004231da430000440000085000000000480000000049000000004a0000000047ffffffff6900000004c700000000e10000000100954a"));
+
+ verifyPositions(decoder, binary(
+ "CCCCCCCC00FE00007048860DDF79020446a6f1ce010f14f650209cca80006f00d6040004010300030101150316030001460000015d0046a6f1dc0d0f14ffe0209cc580006e00c7050001010300030101150316010001460000015e0046a6f1ea0e0f150f00209cd20000950108040000010300030101150016030001460000015d0046a6f1ff0b0f150a50209cccc000930068040000010300030101150016030001460000015b006123"));
+
+ verifyPositions(decoder, binary(
+ "cccccccc0217000144b9ddf2aca002055683f72b01165d80632139a3c800ab00ce0a00000403000a080115bf1a001d001e0141004001f00065011301061600001700001800004231a9430000440000085000000000480000000049000000004a0000000047ffffffff69000000b7c700000000e100000001005683f74901165d80632139a3c800ab012a0a00000403000a080115bf1a001d001e0141004001f00065011301061600001700001800004231a9430000440000085000000000480000000049000000004a0000000047ffffffff69000000b8c700000000e100000001005683f76801165d80632139a3c800ab00590a00000403000a080115bf1a001d001e0141004001f00065011301061600001700001800004231a9430000440000085000000000480000000049000000004a0000000047ffffffff69000000b9c700000000e100000001005683f78601165d80632139a3c800ab00c80a00000403000a080115bf1a001d001e0141004001f00065011301061600001700001800004231a9430000440000085000000000480000000049000000004a0000000047ffffffff69000000bac700000000e100000001005683f7a401165d80632139a3c800ab01310a00000403000a080115bf1a001d001e0141004001f00065011301061600001700001800004231a9430000440000085000000000480000000049000000004a0000000047ffffffff69000000bbc700000000e100000001001d72"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/NyitechProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/NyitechProtocolDecoderTest.java
new file mode 100644
index 000000000..4cafd7612
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/NyitechProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class NyitechProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ NyitechProtocolDecoder decoder = new NyitechProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "4040690030313436383230303238373201201c0c12031a308080801c0c12031a3007d67e7e08aceb841002000000ae08000000000000000000000000001e002900f0ffdd002700f2ffe0002700f2ffe1002400f0ffdf002400f3ffe3008a00ffff01010000a9c70d0a"));
+
+ verifyPosition(decoder, binary(
+ "4040390030313436383230303238373203200100010c000000001c0c1203192a1b0c12171d3104fed87d089288801000000000000011ec0d0a"));
+
+ verifyPosition(decoder, binary(
+ "4040480030313436383230303238373201101c0c12031a2907fa7e7e08b8eb841002000000bc080101040904040300010100000a818283848586878862611c0c12031a293f9c0d0a"));
+
+ verifyPosition(decoder, binary(
+ "40404b003247512d313630313030313901101e0b100604190c02c83707f887ac0f000000002d130101030304020000010100000d426162636465666768696a6ba51e0b1006041965c30d0a"));
+
+ verifyPosition(decoder, binary(
+ "4040490030313436383230303238373202201c0c120319348080001b0c12171d3104fed87d0892888010000000000000000000000000000000000000008b00ffff010100008a480d0a"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ObdDongleProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ObdDongleProtocolDecoderTest.java
new file mode 100644
index 000000000..4c33d1766
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ObdDongleProtocolDecoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ObdDongleProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ObdDongleProtocolDecoder decoder = new ObdDongleProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "55550003383634383637303232353131303135010009010011023402010201ABAAAA"));
+
+ verifyPosition(decoder, binary(
+ "5555000338363438363730323235313130313503000100010355AABBCC184F1ABC614E21C1FA08712A84ABAAAA"),
+ position("2015-07-18 20:49:16.000", true, 22.12346, -123.45678));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/OigoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/OigoProtocolDecoderTest.java
new file mode 100644
index 000000000..c79978f88
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/OigoProtocolDecoderTest.java
@@ -0,0 +1,42 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class OigoProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ OigoProtocolDecoder decoder = new OigoProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "7e002e000000146310002523830400001bfb000369150f310c0591594d062ac0c0141508011303cd63101604fd00000000"));
+
+ verifyPosition(decoder, binary(
+ "0103537820628365110310410790660962521813380026EE4EFF8593AA0065003E00794C020600100500000000"));
+
+ verifyPosition(decoder, binary(
+ "0E03537820628344660204043255862749531B100E0026EE3AFF8593A3FFFE00BF00044C20090710C300000000"));
+
+ verifyPosition(decoder, binary(
+ "00035378206638500203340201271426226b190203001ac000ff72eedd00370097238b4c34116a130b000094d9"));
+
+ verifyPosition(decoder, binary(
+ "1d035378206638500203340201271426226b19020c001ab144ff72f74d005f0097298a4c1d066d130b000094de"));
+
+ verifyPosition(decoder, binary(
+ "00035378206638500203340201271426226b191016001c04e5ff760081013d002900814c1a0f5e130b00009576"));
+
+ verifyPosition(decoder, binary(
+ "7e004200000014631000258257000000ffff02d0690e000220690e0002200696dbd204bdfde31a070000b307101135de106e05f500000000010908010402200104ffff8001"));
+
+ verifyPosition(decoder, binary(
+ "7e004200000014631000258257000000ffff02d1690e00051f690e00051f0696dbd204bdfde31a070000b307100f35c0106305f500000000010908010402200104ffff8001"));
+
+ verifyPosition(decoder, binary(
+ "7e004200000014631000258257000000ffff0d82691300001669130000160696dbd804bdfdbb1a0800000007101035a2106905f500000000010908010402200104ffff8001"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/OkoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/OkoProtocolDecoderTest.java
new file mode 100644
index 000000000..e2f72c161
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/OkoProtocolDecoderTest.java
@@ -0,0 +1,33 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class OkoProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ OkoProtocolDecoder decoder = new OkoProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "{861694033681089,045403.00,A,4924.14181,N,03207.43787,E,0.080,,151117,07,0.00,01,24.8,1,02,5n4}"));
+
+ verifyPosition(decoder, text(
+ "{045411.00,A,4924.14243,N,03207.43754,E,0.172,,151117,07,0.00,F9,28.1,2,C2,5n4}"));
+
+ verifyPosition(decoder, text(
+ "{861001001016415,115031.000,A,4804.101180,N,02255.227002,E,4.121,111.0,211215,6,0.00,F7,13.6,1,00"));
+
+ verifyPosition(decoder, text(
+ "{132810.000,A,4926.4243,N,03203.6831,E,25.0,183,131011,07,5.69,05,14.1,1,82,3N5"));
+
+ verifyPosition(decoder, text(
+ "{115034.000,A,4804.098944,N,02255.233436,E,7.858,120.9,211215,7,0.00,F7,13.7,1,00"));
+
+ verifyPosition(decoder, text(
+ "{115038.000,A,4804.091227,N,02255.250213,E,17.621,128.1,211215,8,0.00,00,13.7,2,00"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/OpenGtsProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/OpenGtsProtocolDecoderTest.java
new file mode 100644
index 000000000..a04cf4e72
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/OpenGtsProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class OpenGtsProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ OpenGtsProtocolDecoder decoder = new OpenGtsProtocolDecoder(null);
+
+ verifyPosition(decoder, request(
+ "/?id=999000000000003&gprmc=$GPRMC,082202.0,A,5006.747329,N,01416.512315,E,0.0,,131018,1.2,E,A*2E"));
+
+ verifyPosition(decoder, request(
+ "/?id=gprmc_999000000000003&gprmc=$GPRMC,143013.0,A,5006.728217,N,01416.437869,E,0.0,329.6,281017,1.2,E,A*0E"));
+
+ verifyPosition(decoder, request(
+ "/?id=123456789012345&dev=dev_name&acct=account&batt=0&code=0xF020&alt=160.5&gprmc=$GPRMC,191555,A,5025.46624,N,3030.39937,E,0.000000,0.000000,200218,,*2F"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/OrionProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/OrionProtocolDecoderTest.java
new file mode 100644
index 000000000..bb5f1f135
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/OrionProtocolDecoderTest.java
@@ -0,0 +1,30 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class OrionProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ OrionProtocolDecoder decoder = new OrionProtocolDecoder(null);
+
+ verifyPositions(decoder, binary(
+ "5057000137bf6236235a0331b5c6e402a3b5ecff5102980003000e0c1d172936080e0c1d172936b03b01000882050000008e080000000000008c0300940500000084030085030003067600900113150000000000000000000000000000000000000004a4c8"));
+
+ verifyPositions(decoder, binary(
+ "5057004107367C242B440901ADE97D0163143B07B003000000000D041917382D000B0101000511000000000682050000008E080000000000008C0300840300850300090A0000000048010000008AFC"));
+
+ verifyPositions(decoder, binary(
+ "5057004107367C242C440901ADE97D0163143B07B003000000000D041917382D000B0101000513000000000682050000008E080000000000008C0300840300850300090A000000003BFEFFFF01FAE5"));
+
+ verifyPositions(decoder, binary(
+ "5057004107367C242D440901ADE97D0163143B07B003000000000D041917382D000B0101000514000000000682050000008E080000000000008C0300840300850300090A00000000FDFDFFFF023721"));
+
+ verifyPositions(decoder, binary(
+ "505700412ac86236354009114d20e402210f1f00d204000000000e06110d3414000b0101001228000000000682050000008e080000000000008c030084030085030003067b006801000930"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/OsmAndProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/OsmAndProtocolDecoderTest.java
new file mode 100644
index 000000000..3c38bd831
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/OsmAndProtocolDecoderTest.java
@@ -0,0 +1,48 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class OsmAndProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ OsmAndProtocolDecoder decoder = new OsmAndProtocolDecoder(null);
+
+ verifyNotNull(decoder, request(
+ "/?id=123456&timestamp=1377177267&cell=257,02,16,2224&cell=257,02,16,2223,-90&wifi=00-14-22-01-23-45,-80&wifi=00-1C-B3-09-85-15,-70"));
+
+ verifyNull(decoder, request(
+ "/?timestamp=1377177267&lat=60.0&lon=30.0"));
+
+ verifyPosition(decoder, request(
+ "/?id=902064&lat=42.06288&lon=-88.23412&timestamp=2016-01-27T18%3A55%3A47Z&hdop=6.0&altitude=224.0&speed=0.0"));
+
+ verifyPosition(decoder, request(
+ "/?id=902064&lat=42.06288&lon=-88.23412&timestamp=1442068686579&hdop=6.0&altitude=224.0&speed=0.0"));
+
+ verifyPosition(decoder, request(
+ "/?lat=49.60688&lon=6.15788&timestamp=2014-06-04+09%3A10%3A11&altitude=384.7&speed=0.0&id=353861053849681"));
+
+ verifyPosition(decoder, request(
+ "/?id=123456&timestamp=1377177267&lat=60.0&lon=30.0&speed=0.0&bearing=0.0&altitude=0&hdop=0.0"));
+
+ verifyPosition(decoder, request(
+ "/?id=123456&timestamp=1377177267&lat=60.0&lon=30.0"));
+
+ verifyPosition(decoder, request(
+ "/?lat=60.0&lon=30.0&speed=0.0&heading=0.0&vacc=0&hacc=0&altitude=0&deviceid=123456"));
+
+ verifyPosition(decoder, request(
+ "/?id=861001000719969&lat=41.666667&lon=-0.883333&altitude=350.059479&speed=0.000000&batt=87"));
+
+ verifyPosition(decoder, request(
+ "/?id=123456&timestamp=1377177267&location=60.0,30.0"));
+
+ verifyPosition(decoder, request(
+ "/?id=123456789012345&timestamp=1504763810&lat=40.7232948571&lon=-74.0061408571&bearing=7.19889788244&speed=40&ignition=true&rpm=933&fuel=24"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/OwnTracksProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/OwnTracksProtocolDecoderTest.java
new file mode 100644
index 000000000..248920e21
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/OwnTracksProtocolDecoderTest.java
@@ -0,0 +1,27 @@
+package org.traccar.protocol;
+
+import io.netty.handler.codec.http.HttpMethod;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class OwnTracksProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ OwnTracksProtocolDecoder decoder = new OwnTracksProtocolDecoder(null);
+
+ verifyPosition(decoder, request(HttpMethod.POST, "/",
+ buffer("{\"_type\":\"location\",\"acc\":15,\"alt\":440,\"batt\":46,\"conn\":\"w\",\"lat\":46.0681247,\"lon\":11.1512805,\"t\":\"u\",\"tid\":\"5t\",\"tst\":1551874878,\"vac\":2,\"vel\":0}")));
+
+ verifyPosition(decoder, request(HttpMethod.POST, "/",
+ buffer("{\"lon\":2.29513,\"lat\":48.85833,\"tst\":1497349316,\"_type\":\"location\",\"tid\":\"JJ\"}")));
+
+ verifyPosition(decoder, request(HttpMethod.POST, "/",
+ buffer("{\"cog\":271,\"lon\":2.29513,\"acc\":5,\"vel\":61,\"vac\":21,\"lat\":48.85833,\"tst\":1497349316,\"alt\":167,\"_type\":\"location\",\"tid\":\"JJ\",\"t\":\"u\",\"batt\":67}")));
+
+ verifyPosition(decoder, request(HttpMethod.POST, "/",
+ buffer("{\"lat\":48.85,\"lon\":2.295,\"_type\":\"location\",\"tid\":\"JJ\",\"tst\":1497476456}")));
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/PathAwayProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/PathAwayProtocolDecoderTest.java
new file mode 100644
index 000000000..4b9739242
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/PathAwayProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class PathAwayProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ PathAwayProtocolDecoder decoder = new PathAwayProtocolDecoder(null);
+
+ verifyPosition(decoder, request(
+ "?UserName=name&Password=pass&LOC=$PWS,1,\"Roger\",,,100107,122846,45.317270,-79.642219,45.00,42,1,\"Comment\",0*58"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java
new file mode 100644
index 000000000..03d0dd7b9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java
@@ -0,0 +1,20 @@
+package org.traccar.protocol;
+
+import io.netty.handler.codec.http.HttpMethod;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class PiligrimProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ PiligrimProtocolDecoder decoder = new PiligrimProtocolDecoder(null);
+
+ verifyPositions(decoder, request(HttpMethod.POST,
+ "/bingps?imei=868204005544720&csq=18&vout=00&vin=4050&dataid=00000000",
+ binary("fff2200d4110061a32354f3422310062000a0005173b0000a101000300005e00fff2200d4110100932354f2b22310042000b000e173b00009f01000700006000")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/PretraceProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/PretraceProtocolDecoderTest.java
new file mode 100644
index 000000000..61a057dd7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/PretraceProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class PretraceProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ PretraceProtocolDecoder decoder = new PretraceProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "(867967021915915U1110A1701201500102238.1700N11401.9324E000264000000000009001790000000,&P11A4,F1050^47"));
+
+ verifyPosition(decoder, text(
+ "(864244029498838U1110A1509250653072238.1641N11401.9213E000196000000000406002990000000,&P195%,T1050,F14A5,R104C51E47B^30"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/PretraceProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/PretraceProtocolEncoderTest.java
new file mode 100644
index 000000000..1b2780325
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/PretraceProtocolEncoderTest.java
@@ -0,0 +1,39 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class PretraceProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncodePositionPeriodic() throws Exception {
+
+ PretraceProtocolEncoder encoder = new PretraceProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_PERIODIC);
+ command.set(Command.KEY_FREQUENCY, 300);
+
+ assertEquals("(123456789012345D221300,300,,^69)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeCustom() throws Exception {
+
+ PretraceProtocolEncoder encoder = new PretraceProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "D21012");
+
+ assertEquals("(123456789012345D21012^44)", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/PricolProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/PricolProtocolDecoderTest.java
new file mode 100644
index 000000000..dbc1665fb
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/PricolProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class PricolProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ PricolProtocolDecoder decoder = new PricolProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "3c5052493030303350020000011402110b222b0455152e4e001de819ca450000000000000003820249000000000000000000000000000000000000000040003e"));
+
+ verifyNotNull(decoder, binary(
+ "3c544553303030324b02000000000000000000000000000000000000000000000000000000037c01f4000000000000000000000000000000000000000000003e"));
+
+ verifyPosition(decoder, binary(
+ "3c4944303030303150FFFFFFFF1C050C121D38045D09FA4e001DE815F4452FFFFFFFFFFF03FF03FF03FF03FF03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF113e"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ProgressProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ProgressProtocolDecoderTest.java
new file mode 100644
index 000000000..5f6f564b1
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ProgressProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ProgressProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ProgressProtocolDecoder decoder = new ProgressProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "020037000100000003003131310f003335343836383035313339303036320f00323530303136333832383531353535010000000100000000000000e6bb97b6"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Pt3000ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Pt3000ProtocolDecoderTest.java
new file mode 100644
index 000000000..e7d87d583
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Pt3000ProtocolDecoderTest.java
@@ -0,0 +1,22 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Pt3000ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Pt3000ProtocolDecoder decoder = new Pt3000ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "%356939010012099,$GPRMC,124945.752,A,4436.6245,N,01054.4634,E,0.11,358.52,060408,,,A,+393334347445,N028d"),
+ position("2008-04-06 12:49:45.000", true, 44.61041, 10.90772));
+
+ verifyPosition(decoder, text(
+ "%356939010014433,$GPRMC,172821.000,A,4019.5147,N,00919.1160,E,0.00,,010613,,,A,+393998525043,N098d"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Pt502FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Pt502FrameDecoderTest.java
new file mode 100644
index 000000000..487a8500c
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Pt502FrameDecoderTest.java
@@ -0,0 +1,39 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Pt502FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Pt502FrameDecoder decoder = new Pt502FrameDecoder();
+
+ verifyFrame(
+ binary("24504844302c3936302cffd8ffdb008400140e0f120f0d14121012171514181e32211e1c1c1e3d2c2e243249404c4b47404645505a736250556d5645466488656d777b8182814e608d978c7d96737e817c011517171e1a1e3b21213b7c5346537c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7cffc000110800f0014003012100021101031101ffdd0004000affc401a20000010501010101010100000000000000000102030405060708090a0b100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa0100030101010101010101010000000000000102030405060708090a0b1100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00e5292800ef450020a2800a2801d49400b450014b40052e2800a69340094a05007fffd0e5d14b10055b51b00c76a00527273494005250014500251400525001450015347c25003a928010d25007ffd1e52909a00290d0014b40052d0014500145002e297b50018a280109a6d002d2e2803fffd2e7a04da3777a94fbd0025140052500145002514005250014940054e381400b494008690d007fffd3e4f345001486800a5a005a2800a2801680280168a002909e280100cd028016a48937bfb5007fffd4c5038a42280128a004a280128a003ad2500251400945002a8cb0a9a80133450026692803ffd5e4e8a004a2801694500145002d18a005c5140052e280109a69a0029680140abb147b139eb401ffd6c62290d00251400949400114940052500252d002525003e31c93525002521a004a4a00ffd7e4a8a00281400a29d40094b40053ba500252d0018a31400d3cd250018cd2d005ab58777ccdd074ab645007ffd0c72290d00348a2801280"),
+ decoder.decode(null, null, binary("bffbf6d10324504844302c3936302cffd8ffdb008400140e0f120f0d14121012171514181e32211e1c1c1e3d2c2e243249404c4b47404645505a736250556d5645466488656d777b8182814e608d978c7d96737e817c011517171e1a1e3b21213b7c5346537c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7cffc000110800f0014003012100021101031101ffdd0004000affc401a20000010501010101010100000000000000000102030405060708090a0b100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa0100030101010101010101010000000000000102030405060708090a0b1100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00e5292800ef450020a2800a2801d49400b450014b40052e2800a69340094a05007fffd0e5d14b10055b51b00c76a00527273494005250014500251400525001450015347c25003a928010d25007ffd1e52909a00290d0014b40052d0014500145002e297b50018a280109a6d002d2e2803fffd2e7a04da3777a94fbd0025140052500145002514005250014940054e381400b494008690d007fffd3e4f345001486800a5a005a2800a2801680280168a002909e280100cd028016a48937bfb5007fffd4c5038a42280128a004a280128a003ad2500251400945002a8cb0a9a80133450026692803ffd5e4e8a004a2801694500145002d18a005c5140052e280109a69a0029680140abb147b139eb401ffd6c62290d00251400949400114940052500252d002525003e31c93525002521a004a4a00ffd7e4a8a00281400a29d40094b40053ba500252d0018a31400d3cd250018cd2d005ab58777ccdd074ab645007ffd0c72290d00348a28012800d0a")));
+
+ verifyFrame(
+ binary("244655533836353332383032363234333836342c3531302d56312e31322c4131312d56332e30"),
+ decoder.decode(null, null, binary("bffb192d00244655533836353332383032363234333836342c3531302d56312e31322c4131312d56332e300d0d")));
+
+ verifyFrame(
+ binary("24504f532c313336303030303237372c3138323234312e3030302c412c303834362e303839362c4e2c30373535322e313733382c572c31332e35382c32362e38382c3239313031372c2c2c412f30303030302c30303030302f3134322c302c302c302f36323739323930302f2f6636352f2f23"),
+ decoder.decode(null, null, binary("bffb57d50124504f532c313336303030303237372c3138323234312e3030302c412c303834362e303839362c4e2c30373535322e313733382c572c31332e35382c32362e38382c3239313031372c2c2c412f30303030302c30303030302f3134322c302c302c302f36323739323930302f2f6636352f2f230a24504f532c313336303030303237372c3138323235312e3030302c412c303834362e313234382c4e2c30373535322e313534352c572c31352e35322c33362e39332c3239313031372c2c2c412f30303030302c30303030302f3134312c302c302c302f36323739333030302f2f6636382f2f230a24504f532c313336303030303237372c3138323332342e3030302c412c303834362e323633362c4e2c30373535322e303630352c572c31382e39342c32392e39302c3239313031372c2c2c412f30303030302c30303030302f3133652c302c302c302f36323739333330302f2f6639372f2f230a24504f532c313336303030303237372c3138323332362e3030302c412c303834362e323733302c4e2c30373535322e303535342c572c31392e31322c33302e34322c3239313031372c2c2c412f30303030302c30303030302f3134302c302c302c302f36323739333330302f2f6639382f2f230a")));
+
+ verifyFrame(
+ binary("24504f532c3836353332383032363234333836342c3134343733352e3030302c412c313333322e373038332c4e2c3230342e363833312c452c302e302c3233302e30302c3032303531372c2c2c412f30303030302c31302f312c302f3233342f2f4646392f"),
+ decoder.decode(null, null, binary("24504f532c3836353332383032363234333836342c3134343733352e3030302c412c313333322e373038332c4e2c3230342e363833312c452c302e302c3233302e30302c3032303531372c2c2c412f30303030302c31302f312c302f3233342f2f4646392f0d0a")));
+
+ verifyFrame(
+ binary("24504f532c3335333435313030303136342c3038323430352e3030302c412c313235342e383530312c4e2c31303035312e363735322c452c302e30302c3233372e39392c3136303531332c2c2c412f303030302c302f302f35353030302f2f6137312f"),
+ decoder.decode(null, null, binary("24504f532c3335333435313030303136342c3038323430352e3030302c412c313235342e383530312c4e2c31303035312e363735322c452c302e30302c3233372e39392c3136303531332c2c2c412f303030302c302f302f35353030302f2f6137312f0d0a")));
+
+ verifyFrame(
+ binary("24504f532c3335333435313030303136342c3038323430352e3030302c412c313235342e383530312c4e2c31303035312e363735322c452c302e30302c3233372e39392c3136303531332c2c2c412f303030302c302f302f35353030302f2f6137312f"),
+ decoder.decode(null, null, binary("bffb1b6a0024504f532c3335333435313030303136342c3038323430352e3030302c412c313235342e383530312c4e2c31303035312e363735322c452c302e30302c3233372e39392c3136303531332c2c2c412f303030302c302f302f35353030302f2f6137312f0d0a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Pt502ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Pt502ProtocolDecoderTest.java
new file mode 100644
index 000000000..cb1c1eb0e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Pt502ProtocolDecoderTest.java
@@ -0,0 +1,86 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class Pt502ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Pt502ProtocolDecoder decoder = new Pt502ProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "24504844302c3936302cffd8ffdb008400140e0f120f0d14121012171514181e32211e1c1c1e3d2c2e243249404c4b47404645505a736250556d5645466488656d777b8182814e608d978c7d96737e817c011517171e1a1e3b21213b7c5346537c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7cffc000110800f0014003012100021101031101ffdd0004000affc401a20000010501010101010100000000000000000102030405060708090a0b100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa0100030101010101010101010000000000000102030405060708090a0b1100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00e5292800ef450020a2800a2801d49400b450014b40052e2800a69340094a05007fffd0e5d14b10055b51b00c76a00527273494005250014500251400525001450015347c25003a928010d25007ffd1e52909a00290d0014b40052d0014500145002e297b50018a280109a6d002d2e2803fffd2e7a04da3777a94fbd0025140052500145002514005250014940054e381400b494008690d007fffd3e4f345001486800a5a005a2800a2801680280168a002909e280100cd028016a48937bfb5007fffd4c5038a42280128a004a280128a003ad2500251400945002a8cb0a9a80133450026692803ffd5e4e8a004a2801694500145002d18a005c5140052e280109a69a0029680140abb147b139eb401ffd6c62290d00251400949400114940052500252d002525003e31c93525002521a004a4a00ffd7e4a8a00281400a29d40094b40053ba500252d0018a31400d3cd250018cd2d005ab58777ccdd074ab645007ffd0c72290d00348a2801280"));
+
+ verifyPosition(decoder, buffer(
+ "$PHO3821-1,1156802639,022125.000,A,0707.0014,N,07307.3725,W,0.0,0.1,110418,,,A/00000,00000/0,0,0,0/500//fd4//"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,1360000277,182241.000,A,0846.0896,N,07552.1738,W,13.58,26.88,291017,,,A/00000,00000/142,0,0,0/62792900//f65//#"));
+
+ verifyPosition(decoder, buffer(
+ "$PHO0-1,1360000260,123012.000,A,0913.9644,N,07548.8345,W,0.0,309.8,111017,,,A/00000,10000/0,0,0,0/64551600//f98//"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,865328026243864,151105.000,A,1332.7096,N,204.6787,E,0.0,10.00,050517,,,A/00000,10/1,0/234//FD9/"));
+
+ verifyNull(decoder, buffer(
+ "$FUS865328026243864,510-V1.12,A11-V3.0"));
+
+ verifyPosition(decoder, buffer(
+ "$HDA,20007,134657.000,A,0626.1607,N,00330.2245,E,33.38,81.79,041016,,,A/00010,00000/270,0,0,0/19948900//fa4//"));
+
+ verifyPosition(decoder, buffer(
+ "$HDB,20007,134708.000,A,0626.1759,N,00330.3192,E,26.55,80.37,041016,,,A/00010,00000/23b,0,0,0/19949100//fa4//"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,20007,134704.000,A,0626.1698,N,00330.2870,E,31.23,79.58,041016,,,A/00010,00000/26c,0,0,0/19949100//fa4//#"));
+
+ verifyPosition(decoder, buffer(
+ "$PHO6608,115099,133140.000,A,1307.1238,N,05936.4194,W,0.00,21.50,290816,,,A/00010,00000/0,0,0,0/185100//f59/"));
+
+ verifyPosition(decoder, buffer(
+ "$DFR,40456789,083125.000,A,2232.0971,N,11400.9504,E,0.0,5.00,090714,,,A/00000,00/0,0/200076//FE7/"));
+
+ verifyPosition(decoder, buffer(
+ "$FDA,40456789,083125.000,A,2232.0971,N,11400.9504,E,0.0,5.00,090714,,,A/00000,00/0,0/200076//FE7/"));
+
+ verifyAttribute(decoder, buffer(
+ "$CPA,40456789,083125.000,A,2232.0971,N,11400.9504,E,7.62,265.24,291117,,,A/00000,00000/0/1200//#"), Position.KEY_ALARM, Position.ALARM_POWER_CUT);
+
+ verifyPosition(decoder, buffer(
+ "$POS,216769295715,163237.000,A,3258.1738,S,02755.4350,E,0.00,215.88,100915,,,A/0000,0//232300//5b3/"),
+ position("2015-09-10 16:32:37.000", true, -32.96956, 27.92392));
+
+ verifyPosition(decoder, buffer(
+ "$POS,11023456,033731.000,A,0335.2617,N,09841.1587,E,0.00,88.12,210615,,,A/0000,0/1f8/388900//f33//"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,6094,205523.000,A,1013.6223,N,06728.4248,W,0.0,99.3,011112,,,A/00000,00000/0/23895000//"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,6120,233326.000,V,0935.1201,N,06914.6933,W,0.00,,151112,,,A/00000,00000/0/0/"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,6002,233257.000,A,0931.0430,N,06912.8707,W,0.05,146.98,141112,,,A/00010,00000/0/5360872"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,6095,233344.000,V,0933.0451,N,06912.3360,W,,,151112,,,N/00000,00000/0/1677600/"));
+
+ verifyPosition(decoder, buffer(
+ "$PHO0,6091,233606.000,A,0902.9855,N,06944.3654,W,0.0,43.8,141112,,,A/00010,00000/0/224000//"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,353451000164,082405.000,A,1254.8501,N,10051.6752,E,0.00,237.99,160513,,,A/0000,0/0/55000//a71/"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,012896008586486,154215.000,A,0118.0143,S,03646.9144,E,0.00,83.29,180714,,,A/0000,0/0/29200//644/"));
+
+ verifyPosition(decoder, buffer(
+ "$POS,1151000,205326.000,A,0901.3037,N,07928.2751,W,48.79,30.55,170814,,,A/00010,10000/0,0,0,0/15986500//fb8/"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Pt502ProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/Pt502ProtocolEncoderTest.java
new file mode 100644
index 000000000..a6c8bb50f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Pt502ProtocolEncoderTest.java
@@ -0,0 +1,69 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class Pt502ProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncodeCustom() throws Exception {
+
+ Pt502ProtocolEncoder encoder = new Pt502ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "#PTI300");
+
+ assertEquals("#PTI300\r\n", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeOutputControl() throws Exception {
+
+ Pt502ProtocolEncoder encoder = new Pt502ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_OUTPUT_CONTROL);
+ command.set(Command.KEY_INDEX, 2);
+ command.set(Command.KEY_DATA, "1");
+
+ assertEquals("#OPC2,1\r\n", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeTimezone() throws Exception {
+
+ Pt502ProtocolEncoder encoder = new Pt502ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SET_TIMEZONE);
+ command.set(Command.KEY_TIMEZONE, "GMT+8");
+
+ assertEquals("#TMZ8\r\n", encoder.encodeCommand(command));
+
+ }
+
+
+ @Test
+ public void testEncodeAlarmSpeed() throws Exception {
+
+ Pt502ProtocolEncoder encoder = new Pt502ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ALARM_SPEED);
+ command.set(Command.KEY_DATA, 120);
+
+ assertEquals("#SPD120\r\n", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Pt60ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Pt60ProtocolDecoderTest.java
new file mode 100644
index 000000000..1ba8d25c7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Pt60ProtocolDecoderTest.java
@@ -0,0 +1,54 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Pt60ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Pt60ProtocolDecoder decoder = new Pt60ProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "@B#@|01|006|864891030184954|9425010450971470|20181213093127|2|1|"));
+
+ verifyNull(decoder, text(
+ "@B#@|01|006|864891030184954|9425010450971470|20181213093235|40412,10461,1,425,4|2|1|"));
+
+ verifyNotNull(decoder, text(
+ "@B#@|01|001|864891030184852|9425010450971470|1|84|20181205161005|40412,10461,1,425,10|2|"));
+
+ verifyPosition(decoder, text(
+ "@B#@|01|001|864891030184852|9425010450971470|1|45|20181127122717|32.701093|35.570938|1|"));
+
+ verifyNull(decoder, text(
+ "@B#@|01|003|864891030184954|9425010450971470|S6_EN_A_V1.3.7|0|66|20181122113251|40412,10461,1,425,18|49382,10461,1,425,9|40411,10461,1,425,7|2|"));
+
+ verifyNull(decoder, text(
+ "@B#@|01|033|864891030184954|9425010450971470|0|4|20181120151744|"));
+
+ verifyPosition(decoder, text(
+ "@B#@|01|001|111112222233333|8888888888888888|1|55|20160715150323|37.615124|125.48276|111.059279|49.346383|1|"));
+
+ verifyPosition(decoder, text(
+ "@B#@|01|001|111112222233333|8888888888888888|1|55|20160715150323|37.615124|125.48276|1|"));
+
+ verifyAttributes(decoder, text(
+ "@G#@,V01,14,357653051059785,9404223001501310,20180419165604,101,26,"));
+
+ verifyAttributes(decoder, text(
+ "@G#@,V01,13,357653051059785,9404223001501310,20180419112656,1180,"));
+
+ verifyPosition(decoder, text(
+ "@G#@,V01,6,111112222233333,8888888888888888,20150312010203,23.2014050;104.235212,"));
+
+ verifyNull(decoder, text(
+ "@G#@,V01,1,353882080015633,9460025014649193,"));
+
+ verifyNull(decoder, text(
+ "@G#@,V01,43,105681639001701,9460000412618231,20180410092923,5,460;0;9763;3852;-63|460;0;9763;3851;-26|460;0;9763;4080;-22|460;0;9763;3593;-18|460;0;9763;3591;-10,5,14:b8:37:26:64:88;004300680069006e0061004e00650074002d006e0047006e0058;-76|08:9b:4b:93:b5:b1;005400480049004e004b0052004100430045;-77|ec:3d:fd:c9:38:4a;004b00460052006f0075007400650072;-78|b0:d5:9d:c6:f8:82;003300360030514d8d390057006900460069002d00380032;-81|02:fa:84:3b:fa:6a;00470075006500730074005f0032002e003400470048007a;-82,"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/RaveonProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/RaveonProtocolDecoderTest.java
new file mode 100644
index 000000000..165027351
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/RaveonProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class RaveonProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ RaveonProtocolDecoder decoder = new RaveonProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$PRAVE,0001,0001,3308.9051,-11713.1164,195348,1,10,168,31,13.3,3,-83,0,0,,1003.4*66"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/RecodaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/RecodaProtocolDecoderTest.java
new file mode 100644
index 000000000..668879787
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/RecodaProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class RecodaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ RecodaProtocolDecoder decoder = new RecodaProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "01100020480000000300000030393535360000000000000001000000303030303000000000000000000000000000000000000000006100004531313037353500ffffffffffff0000"));
+
+ verifyNull(decoder, binary(
+ "01200020100000000300000002000000"));
+
+ verifyNull(decoder, binary(
+ "0110000008000000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/RetranslatorProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/RetranslatorProtocolDecoderTest.java
new file mode 100644
index 000000000..779e21823
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/RetranslatorProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class RetranslatorProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ RetranslatorProtocolDecoder decoder = new RetranslatorProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "74000000333533393736303133343435343835004B0BFB70000000030BBB000000270102706F73696E666F00A027AFDF5D9848403AC7253383DD4B400000000000805A40003601460B0BBB0000001200047077725F657874002B8716D9CE973B400BBB00000011010361766C5F696E707574730000000001"));
+
+ verifyPosition(decoder, binary(
+ "1f010000333533353439303930303934373330005b129b5f000000010bbb000000270102706f73696e666f004e3be14e5ec356c0e0e92f6201282c400000000000000000000000130d0bbb0000000a00036d636300000002c00bbb0000000a00036d6e6300000000010bbb0000000a00036c616300000001490bbb0000000e000363656c6c5f696400000056590bbb0000000a000361636300000000000bbb000000100003646174615f6d6f6465000000000e0bbb0000001200036770735f7265616c5f757000000000000bbb0000000d000373657269616c000000089b0bbb0000001000016d73675f747970650030783232000bbb000000110004637573746f6d0000000000000033400bbb0000001200046d696c65616765000000000000000000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/RitiProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/RitiProtocolDecoderTest.java
new file mode 100644
index 000000000..73d07efd6
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/RitiProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class RitiProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ RitiProtocolDecoder decoder = new RitiProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "3b28a2a2056315316d4000008100000000000000005f710000244750524d432c3138303535332e3030302c412c353532342e383437312c4e2c30313133342e313837382c452c302e30302c2c3032313231332c2c2c412a37340d0a00000000000000000000000000000000040404"));
+
+ verifyPosition(decoder, binary(
+ "3b2864a3056300006d40000003000000000000000000000000244750524d432c3231313734332e3030302c412c313335372e333637352c4e2c31303033362e363939322c452c302e30302c2c3031303931342c2c2c412a37380d0a00000000000000000000000000000000040404"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/RoboTrackFrameDecoderTest.java b/src/test/java/org/traccar/protocol/RoboTrackFrameDecoderTest.java
new file mode 100644
index 000000000..2e3853f86
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/RoboTrackFrameDecoderTest.java
@@ -0,0 +1,19 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class RoboTrackFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ RoboTrackFrameDecoder decoder = new RoboTrackFrameDecoder();
+
+ verifyFrame(
+ binary("00524f424f545241434b00000000000000383638323034303032323533343136313233343536373839303132312e313261000000312e353761000000312e3030000000003e"),
+ decoder.decode(null, null, binary("00524f424f545241434b00000000000000383638323034303032323533343136313233343536373839303132312e313261000000312e353761000000312e3030000000003e")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/RoboTrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/RoboTrackProtocolDecoderTest.java
new file mode 100644
index 000000000..0c969ab68
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/RoboTrackProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class RoboTrackProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ RoboTrackProtocolDecoder decoder = new RoboTrackProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "00524f424f545241434b00000000000000383638323034303032323533343136313233343536373839303132312e313261000000312e353761000000312e3030000000003e"));
+
+ verifyPosition(decoder, binary(
+ "03e020bb5a034409034862120210a9e105000000000000b9"));
+
+ verifyPosition(decoder, binary(
+ "03f120bb5a30460903426312021798e105000000000000cd"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/RuptelaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/RuptelaProtocolDecoderTest.java
new file mode 100644
index 000000000..12f63ef7d
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/RuptelaProtocolDecoderTest.java
@@ -0,0 +1,48 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class RuptelaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ RuptelaProtocolDecoder decoder = new RuptelaProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "002e000315bc70d3e2ff0f4f42443130302e30312e30382e30300000c2b30ea77e430000601b000001f40000003c00144aa0"));
+
+ verifyAttributes(decoder, binary(
+ "0011000315A07F440B1D07534554494f20636f6e66696775726174696f6e2064617461206f6b341C"));
+
+ verifyAttributes(decoder, binary(
+ "0044000313612d76c5cb0744494e313d312c44494e323d302c44494e333d302c44494e343d302c444f5554313d312c444f5554323d312c41494e313d31372c41494e323d3236ac80"));
+
+ verifyPositions(decoder, binary(
+ "000B00000B1A29F64B1A0902FF4E9CAF2C07D608F11A1480BA015030303130FF4E9CAF2C07D608F11A1480BA0250303031318C91"));
+
+ verifyPositions(decoder, binary(
+ "01a4000315bc70f9b69244000458068f4a0030000d11398a1c0c19fd056524040b000c0a00090c0005010031f40032fd0033f200ce47002400002500001c010199000195010196010086000900aa0000001e0ff000d3ffff0043ffff01930000019200000194000002220000022300000200300000000200af000e872401008e000000000000000058068f4a0031000d11398a1c0c19fd056524040b000c0a00090400870000880000a90000820010008b0002021e0000021f0000021d0000021c0000022400000225000000890000008505f00220000002210000008300000084000002260000022700000228000003008a00000000008d00000000008c000000000058068f4a0032000d11398a1c0c19fd056524040b000c0a000905019f01005800001b1f00ad0000cfb10b02290000022a0000022b0000022c0000022d00000012000000130000001d367400c52f8000740055023e0502060097000000000096000058520041007746cb00d0000003f1005c0007c21b0072001864880058068f4a0033000d11398a1c0c19fd056524040b000c0a000900000001008e0000000000000000e815"));
+
+ verifyPositions(decoder, binary(
+ "033d000315bc70f9b69244000858068f3b0030010d11354e1c0c17a5055d54560c00000900050c0005010031f30032fb0033f300ce00002400002500001c010199000195010196010086000900aa0000001e0ff300d3ffff0043ffff01930000019200000194000002220000022300000200300000000000af000e872401008e000000000000000058068f3b0031010d11354e1c0c17a5055d54560c00000900050400870000880000a90000820010008b0000021e0000021f0000021d0000021c0000022400000225000000890000008500000220000002210000008300000084000002260000022700000228000003008a00000000008d00000000008c000000000058068f3b0032010d11354e1c0c17a5055d54560c000009000505019f01005800001b1f00ad0000cfac0b02290000022a0000022b0000022c0000022d00000012000000130000001d31b100c5000000740000023e0502060097000000000096000058520041007746be00d0000003f1005c0007c2150072001864880058068f3b0033010d11354e1c0c17a5055d54560c000009000500000001008e000000000000000058068f3b0130000d11354e1c0c17a5055d54560d00000900070c0005010031f30032fb0033f300ce00002400002500001c010199000195010196010086000900aa0000001e0ff300d3ffff0043ffff01930000019200000194000002220000022300000200300000000000af000e872401008e000000000000000058068f3b0131000d11354e1c0c17a5055d54560d00000900070400870000880000a90000820010008b0000021e0000021f0000021d0000021c0000022400000225000000890000008500000220000002210000008300000084000002260000022700000228000003008a00000000008d00000000008c000000000058068f3b0132000d11354e1c0c17a5055d54560d000009000705019f01005800001b1f00ad0000cfac0b02290000022a0000022b0000022c0000022d00000012000000130000001d31ae00c5000000740000023e0502060097000000000096000058520041007746be00d0000003f1005c0007c2150072001864880058068f3b0133000d11354e1c0c17a5055d54560d000009000700000001008e0000000000000000084d"));
+
+ verifyPositions(decoder, binary(
+ "0050000310f5615f419c0100015613d8ed0000fff5b37a035af37801e700000900000d07071b0c020003001c01202cad000500064302a81d33e61e100116317cd3ffff174ad60241000077fa960000f232003c2e"));
+
+ verifyPositions(decoder, binary(
+ "00560003116e7438a7a50100015565cbb9000020fd21300f113f4600005f000600090d090805011b13cf00020003001c012029ad00041d31dd1e0ebd160000c50000047200000000d0000000004100016a2a960000a5a300c9ee"));
+
+ verifyPositions(decoder, binary(
+ "00a10003116e7438a7a5010002553dddbe000020fddaff0f12289b007200000600000c070805011b18cf00020003001c01201dad01041d32d81e0d7d160000c50000047200000000d000000000410000b1ae960000a5a300553dddd4000020fdd96f0f122bfe005c16f80700050b090805011b18cf00020003001c01201ead01041d338a1e0d8d160000c50000047200000000d000000000410000b1bd960000a5a3001681"));
+
+ verifyPositions(decoder, binary(
+ "007900000b1a2a5585c30100024e9c036900000f101733208ff45e07b31b570a001009090605011b1a020003001c01ad01021d338e16000002960000601a41014bc16d004e9c038400000f104fdf20900d20075103b00a001308090605011b1a020003001c01ad01021d33b116000002960000601a41014bc1ea0028f9"));
+
+ verifyPositions(decoder, binary(
+ "009200000c07a6bacd4701000552db5cc20000187b8b251ace478e087c044c0a000009070000000052db5cfe0000187b8ab01ace47190879044c0900000b070000000052db5d3a0000187b8b251ace474b089d044c09000009070000000052db5d760000187b8b9a1ace475c08cd044c08000009070000000052db5db20000187b8b141ace46e708b3044c08000009070000000041cb"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/RuptelaProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/RuptelaProtocolEncoderTest.java
new file mode 100644
index 000000000..8a00caa09
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/RuptelaProtocolEncoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class RuptelaProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ RuptelaProtocolEncoder encoder = new RuptelaProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, " Setio 2,1");
+
+ verifyCommand(encoder, command, binary("000b6c20536574696F20322C31eb3e"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SabertekFrameDecoderTest.java b/src/test/java/org/traccar/protocol/SabertekFrameDecoderTest.java
new file mode 100644
index 000000000..7a42a71a0
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SabertekFrameDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class SabertekFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SabertekFrameDecoder decoder = new SabertekFrameDecoder();
+
+ assertEquals(
+ binary("2c3939393939393939392c332c34302c36352c372c302c312c2d32352e3738313636362c32382e3235343730322c34302c3236382c313431342c382c35353632332c"),
+ decoder.decode(null, null, binary("022c3939393939393939392c332c34302c36352c372c302c312c2d32352e3738313636362c32382e3235343730322c34302c3236382c313431342c382c35353632332c030d0a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SabertekProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SabertekProtocolDecoderTest.java
new file mode 100644
index 000000000..20b02841e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SabertekProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SabertekProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SabertekProtocolDecoder decoder = new SabertekProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ ",999999999,3,40,65,7,0,1,-25.781666,28.254702,40,268,1414,8,55623,"));
+
+ verifyPosition(decoder, text(
+ ",999999999,4,356495040613400,89270200120171498287,+27821234123,20180525145412,60,75,15,1,1,-25.781666,28.254702,40,268,1414,8,24844,"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SanavProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SanavProtocolDecoderTest.java
new file mode 100644
index 000000000..36fd7ecba
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SanavProtocolDecoderTest.java
@@ -0,0 +1,37 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SanavProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SanavProtocolDecoder decoder = new SanavProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "imei=353197040023431&rmc=$GPRMC,015258.000,A,2457.8101,N,12125.5393,E,0.00,0.00,210111,,*18,AUTO,0300,2.1,10,466,97,34E7,3391,74,466,9 7,3F2D,3391,65,466,97,39C9,3391,79,466,97,3F2C,3391,81,466,97,0000,00 00,83,466,97,0000,0000,85,466,97,0000,0000,85,1,24"));
+
+ verifyPosition(decoder, text(
+ "imei=1234567890&rmc=$GPRMC,091950.00,V,5300.10000,N,00900.14000,E,0.160,,200513,,,A*68,STOP,V3.872;67%,S4,H8.3,D2.38"));
+
+ verifyPosition(decoder, text(
+ "imei=352024028982787&rmc=$GPRMC,103048.000,A,4735.0399,N,01905.2895,E,0.00,0.00,171013,,*05,AUTO-4095mv"),
+ position("2013-10-17 10:30:48.000", true, 47.58400, 19.08816));
+
+ verifyPosition(decoder, text(
+ "imei:352024028980000rmc:$GPRMC,093604.354,A,4735.0862,N,01905.2146,E,0.00,0.00,171013,,*09,AUTO-4103mv"));
+
+ verifyPosition(decoder, text(
+ "imei:352024027800000rmc:$GPRMC,000025.000,A,4735.0349,N,01905.2899,E,0.00,202.97,171013,,*03,3950mV,AUTO"));
+
+ verifyPosition(decoder, text(
+ "imei:352024020976845rmc:$GPRMC,000201.000,A,4655.7043,N,01941.3796,E,0.54,159.14,171013,,,A*65,AUTO"));
+
+ verifyPosition(decoder, text(
+ "imei:352024020976845rmc:$GPRMC,000201.000,A,4655.7043,N,01941.3796,E,0.54,159.14,171013,,,A*65,AUTO"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SatsolProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SatsolProtocolDecoderTest.java
new file mode 100644
index 000000000..45e919bbb
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SatsolProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SatsolProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SatsolProtocolDecoder decoder = new SatsolProtocolDecoder(null);
+
+ verifyPositions(decoder, binary(
+ "f0e1bf4cb2ec1600e1005f8791e901000000c959515c2cc24a03aeadcd010e01a800250001090201878e92e901000000cb59515c2dc24a03b8adcd018801a8001d0001080201325993e901000000cc59515c2fc24a03bfadcd01ab01a800220001080201dd8194e901000000cd59515c32c24a03ceadcd015801a8002500010802015f3795e905000900ce59515c32c24a03d8adcd01f600a700250001091401000000000000000000863496e901000000cf59515c34c24a03ddadcd019b00a700280001090201714197e904000600cf59515c34c24a03ddadcd019b00a7002800010a1401becd07001901"));
+
+ verifyPositions(decoder, binary(
+ "22b5bf4cb2ec1600500122b37ba020001500cb5d2f5c68c24a0310aecd016200b1003d000004000177042700a501000000000000000101020100011e00a1657ca020001500cf5d2f5c68c24a03dbadcd013501b10097000004030177042700a501000000000000000101020101011e00816e7da003004800b95e2f5c89c24a03fbadcd010000aa00000000040601011038363133353930333632333039323600383933373530323730313030323335343836363000323537303237303132333534383636004d5453000000000066640101005700e515cf047ea001000000295f2f5c89c24a03fbadcd0100009a0000000106020106dc30a8030048006bc13e5c19c24a03bfadcd010000ad00000000050600011338363133353930333632333039323600383933373530323730313030323335343836363000323537303237303132333534383636004d5453000000000066640101005700e515"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java
new file mode 100644
index 000000000..48adb0ccb
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SigfoxProtocolDecoderTest.java
@@ -0,0 +1,19 @@
+package org.traccar.protocol;
+
+import io.netty.handler.codec.http.HttpMethod;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SigfoxProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SigfoxProtocolDecoder decoder = new SigfoxProtocolDecoder(null);
+
+ verifyPosition(decoder, request(HttpMethod.POST, "/",
+ buffer("%7B++%22device%22%3A%222BF839%22%2C++%22time%22%3A1510605882%2C++%22duplicate%22%3Afalse%2C++%22snr%22%3A45.61%2C++%22station%22%3A%2235A9%22%2C++%22data%22%3A%2200bd6475e907398e562d01b9%22%2C++%22avgSnr%22%3A45.16%2C++%22lat%22%3A-38.0%2C++%22lng%22%3A145.0%2C++%22rssi%22%3A-98.00%2C++%22seqNumber%22%3A228+%7D=")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SiwiProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SiwiProtocolDecoderTest.java
new file mode 100644
index 000000000..3a91d8482
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SiwiProtocolDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SiwiProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SiwiProtocolDecoder decoder = new SiwiProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$SIWI,9803932,23992,E,0,,0,1,1,0,5055,0,5,A,22.289887,70.807192,152,168,102922,090317,28,1,12,5,4098,1,0,13,0,0,0,1.0,3.1CHKS_4.82,0!"));
+
+ verifyPosition(decoder, text(
+ "$SIWI,2845,1320,Q,10,airtelgprs.com,1,1,0,0,876578,43,9,A,19.0123456,72.65347,45,0,055929,071107,22,5,1,0,3700,1210,0,2500,1230,321,0,1.1,4.0,1!"));
+
+ verifyPosition(decoder, text(
+ "$SIWI,9803849,953,R,9,,0,1,1,0,0,0,8,A,19.066145,73.002278,213,178,122738,210217,28,5,12,6,4066,1,0,2,0,0,0,1.0,3.1CHKS_4.82,0"));
+
+ verifyPosition(decoder, text(
+ "$EIT,9803849,953,R,9,,0,1,1,0,0,0,8,A,19.066145,73.002278,213,178,122738,210217,28,5,12,6,4066,1,0,2,0,0,0,1.0,3.1CHKS_4.82,0"));
+
+ verifyPosition(decoder, text(
+ "$SIWI,9803849,954,E,0,,0,1,1,0,0,0,0,V,0.000000,0.000000,0,0,122855,210217,29,5,12,5,4104,1,0,2,0,0,0,1.0,3.1CHKS_4.82,0"));
+
+ verifyPosition(decoder, text(
+ "$SIWI,2845,1320,A,0,,1,1,0,0,876578,43,10,A,19.0123456,72.65347,45,0,055929,071107,22,5,1,0,3700,1210,0,2500,1230,321,0,1.1,4.0,1!"));
+
+ verifyPosition(decoder, text(
+ "$SIWI,9803849,956,E,0,,0,1,1,0,0,0,3,V,19.066935,73.003383,0,111,123037,210217,28,5,12,5,4071,1,0,2,0,0,0,1.0,3.1CHKS_4.82,0"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SkypatrolProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SkypatrolProtocolDecoderTest.java
new file mode 100644
index 000000000..bc2dac7e9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SkypatrolProtocolDecoderTest.java
@@ -0,0 +1,34 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SkypatrolProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SkypatrolProtocolDecoder decoder = new SkypatrolProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "000a02171101303131373232303031333537393833060200000006202020202020202020312020202020202030313137323230303133353739383320"));
+
+ verifyNull(decoder, binary(
+ "000402171101303131373232303031333537393833060200081046202020202020202020392020202020202030313137323230303133353739383320244750524d432c3134303931372e30302c412c333330322e3230313132352c532c30373133352e3837383338332c572c302e302c302e302c3036303731372c322e382c572c412a32370d0a00"));
+
+ verifyPosition(decoder, binary(
+ "0005021004FFFFFFFF0000000D313134373735383300CB000000000E11070C010184D032FB3841370000000016072B000017050032000000000000024E0C071116072C105900050000000000050000000000050000000003100260B7363B6306C11A00B73637F206BF19B73637F106B50EB73638B106BB0BB7363B6106B80AB73637F306B709000000000000000000"));
+
+ verifyNull(decoder, binary(
+ "000500030101383637383434303031373832333336420102000c0000fa07b5e101876c5b0e0a111606131c1b5e"));
+
+ // Enfora TT8750
+ verifyNull(decoder, binary(
+ "000502000000f1143035303031393031d1df002f00000d0187120115e556ff762aa90000000000aae40005d2000ee1bc0e010a042530000000000000070004000002233c096c00ee2a00233c008500f022233c0b0500f21d233c000000fb23000000000000000000000000000000000000000000000000000000"));
+
+ verifyNull(decoder, binary(
+ "00040200202020202020202020382020202020202030313137323230303131383531373820313220244750524d432c3232343833392e30302c412c303332382e3433383830362c4e2c30373633312e3630373731372c572c302e302c302e302c3139303731342c332e382c452c412a32420d0a00"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SmartSoleProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SmartSoleProtocolDecoderTest.java
new file mode 100644
index 000000000..183af899b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SmartSoleProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SmartSoleProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SmartSoleProtocolDecoder decoder = new SmartSoleProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "#GTXRP=359366080000385,8,180514200051,34.041981,-118.255806,60,1,1,7,1.80,180514200051,4.16,11"));
+
+ verifyPosition(decoder, text(
+ "#GTXRP=359372090000290,11,180919105751,46.477173,6.445475,389,0,0,0,1.08,180919105751,4.10,10"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SmokeyProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SmokeyProtocolDecoderTest.java
new file mode 100644
index 000000000..c2d74b433
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SmokeyProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SmokeyProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SmokeyProtocolDecoder decoder = new SmokeyProtocolDecoder(null);
+
+ verifyAttributes(decoder, binary(
+ "534d0300865101019383025f0403000000000b86250200000c0000028f000102f8cc0900127f08"));
+
+ verifyAttributes(decoder, binary(
+ "534d0300865101019383025f0403000000000bcf260200000c0000028f000102f8cc090012360b"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SpotProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SpotProtocolDecoderTest.java
new file mode 100644
index 000000000..7191f31ef
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SpotProtocolDecoderTest.java
@@ -0,0 +1,19 @@
+package org.traccar.protocol;
+
+import io.netty.handler.codec.http.HttpMethod;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SpotProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SpotProtocolDecoder decoder = new SpotProtocolDecoder(null);
+
+ verifyPositions(decoder, request(HttpMethod.POST, "/",
+ buffer("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<messageList xmlns=\"http://v2.shared.globalstar.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://v2.shared.globalstar.com http://share.findmespot.com/shared/schema/spotXml-v2.xsd\">\n <header>\n <totalCount>1</totalCount>\n <mode>LIVE</mode>\n </header>\n <message>\n <id>891801957</id>\n <esn>0-3112123</esn>\n <esnName>0-3112123a</esnName>\n <messageType>NEWMOVEMENT</messageType>\n <messageDetail> SPOT Trace has detected that the asset has moved.</messageDetail>\n <timestamp>2017-12-27T13:19:38.000Z</timestamp>\n <timeInGMTSecond>1514380778</timeInGMTSecond>\n <latitude>-1.28781</latitude>\n <longitude>-47.93042</longitude>\n <batteryState>GOOD</batteryState>\n </message>\n</messageList>")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/StarLinkProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/StarLinkProtocolDecoderTest.java
new file mode 100644
index 000000000..70e173284
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/StarLinkProtocolDecoderTest.java
@@ -0,0 +1,54 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class StarLinkProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ StarLinkProtocolDecoder decoder = new StarLinkProtocolDecoder(null);
+
+ verifyAttributes(decoder, text(
+ "$SLU068328,06,55,170518122023,16,,,,,,000000,1,1,0,0,0,0,0,0,10443,32722,12.664,03.910,,0,0,,01000001FDB3A9*BF"));
+
+ verifyAttributes(decoder, text(
+ "$SLU068328,06,56,170518122023,20,,,,,,000000,1,1,0,0,0,0,0,0,10443,32722,12.664,03.910,,0,0,2,01000001FDB3A9,00000000000000000000*D9"));
+
+ verifyAttributes(decoder, text(
+ "$SLU068328,06,57,170518122038,01,,,,,,000000,1,1,0,0,1,0,0,0,10443,32722,12.669,03.910,,0,0,0,99*6E"));
+
+ verifyAttributes(decoder, text(
+ "$SLU068328,06,58,170518122045,19,,,,,,000000,1,1,0,0,1,0,0,0,10443,32722,12.678,03.910,,0,0*7C"));
+
+ verifyAttributes(decoder, text(
+ "$SLU068328,06,59,170518122054,16,,,,,,000000,1,1,0,0,0,0,0,0,10443,32723,12.678,03.910,,0,0,01000001FDB3A9,01000001ACE0A6*BF"));
+
+ verifyPosition(decoder, text(
+ "$SLU031B2B,06,622,170329035057,01,170329035057,+3158.0018,+03446.6968,004.9,007,000099,1,1,0,0,0,0,0,0,,,14.176,03.826,,1,1,1,4*B0"));
+
+ verifyPosition(decoder, text(
+ "$SLU031B2B,06,624,170329035143,01,170329035143,+3158.0171,+03446.6742,006.8,326,000099,1,1,0,0,0,0,0,0,10452,8723,14.212,03.827,,1,1,1,4*6D"));
+
+ verifyPosition(decoder, text(
+ "$SLU0330D5,06,3556,170314063523,19,170314061634,+3211.7187,+03452.8106,000.0,332,015074,1,1,0,0,0,0,0,0,10443,32722,12.870,03.790,,0,0*FC"));
+
+ verifyPosition(decoder, text(
+ "$SLU0330D5,06,3555,170314063453,20,170314061634,+3211.7187,+03452.8106,000.0,332,015074,1,1,0,0,0,0,0,0,10443,32722,12.838,03.790,,0,0,1,,1122*74"));
+
+ verifyPosition(decoder, text(
+ "$SLU006968,06,375153,170117051824,01,170117051823,+3203.2073,+03448.1360,000.0,300,085725,1,1,0,0,0,0,0,0,10422,36201,12.655,04.085,,0,0,0,99*45"));
+
+ verifyPosition(decoder, text(
+ "$SLU006968,06,375155,170117052615,24,170117052613,+3203.2079,+03448.1369,000.0,300,085725,1,1,0,0,0,0,0,0,10422,36201,14.290,04.083,,1,1*5B"));
+
+ verifyPosition(decoder, text(
+ "$SLU006968,06,375156,170117052616,34,170117052614,+3203.2079,+03448.1369,000.0,300,085725,1,1,0,0,0,0,0,0,10422,36201,14.277,04.084,1,1,1,1*F3"));
+
+ verifyPosition(decoder, text(
+ "$SLU006968,06,375154,170117052613,04,170117052612,+3203.2079,+03448.1369,000.0,300,085725,1,1,0,0,0,0,0,0,10422,36201,14.287,04.084,,1,0*5B"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Stl060ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Stl060ProtocolDecoderTest.java
new file mode 100644
index 000000000..e2be2028e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Stl060ProtocolDecoderTest.java
@@ -0,0 +1,28 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Stl060ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Stl060ProtocolDecoder decoder = new Stl060ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$1,357804048043099,D001,AP29AW0963,23/02/14,14:06:54,17248488N,078342226E,0.08,193.12,1,1,1,1,1,A"),
+ position("2014-02-23 14:06:54.000", true, 17.41415, 78.57038));
+
+ verifyPosition(decoder, text(
+ "$1,357804048043099,D001,AP29AW0963,12/05/14,07:39:57,1724.8564N,07834.2199E,0.00,302.84,1,1,1,1,1,A"));
+
+ verifyPosition(decoder, text(
+ "$1,357804047969310,D001,AP29AW0963,01/01/13,13:24:47,1723.9582N,07834.0945E,00100,010,0,0,0,0,0,A,"));
+
+ verifyPosition(decoder, text(
+ "$1,357804047969310,D001,AP29AW0963,01/01/13,13:24:47,1723.9582N,07834.0945E,00100,010,0,0,0,0,0,0008478660,1450,40,34,0,0,0,A"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java
new file mode 100644
index 000000000..355cda783
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SuntechProtocolDecoderTest.java
@@ -0,0 +1,167 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class SuntechProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecodeTemperature() throws Exception {
+
+ SuntechProtocolDecoder decoder = new SuntechProtocolDecoder(null);
+
+ decoder.setHbm(true);
+ decoder.setIncludeAdc(true);
+ decoder.setIncludeTemp(true);
+
+ verifyPosition(decoder, text(
+ "ST300STT;205173382;07;564;20160322;23:23:18;232e19;+19.288278;-099.128750;000.122;000.00;9;1;478391;11.53;000100;1;9498;079324;4.3;1;0.00;0.00;0.00;00000000000000;0;2898E16006000058:-20.8;2861626006000039:+2.5;:"));
+
+ verifyPosition(decoder, text(
+ "ST300EVT;205173382;07;564;20160322;23:23:18;232e19;+19.288278;-099.128750;000.122;000.00;9;1;478391;11.53;000100;2;1;9498;079324;4.3;1;0.00;0.00;0.00;00000000000000;0;2898E16006000058:-20.8;2861626006000039:+2.5;:"));
+
+ verifyPosition(decoder, text(
+ "ST600STT;008349958;35;523;20181112;00:49:30;0bf10d4e;334;20;2f19;22;+20.552718;-100.824478;050.021;095.41;12;1;1303603;14.30;10000000;4;8911;001987;4.1;0;0.00;;;;00000000000000;0;2826C8A70800000C:+26.6;:;:"));
+
+ }
+
+ @Test
+ public void testDecodeHours() throws Exception {
+
+ SuntechProtocolDecoder decoder = new SuntechProtocolDecoder(null);
+
+ decoder.setHbm(true);
+
+ verifyPosition(decoder, text(
+ "ST300STT;007238270;40;313;20190220;12:05:04;c99e48;+04.644623;-074.076922;010.390;202.77;20;1;997100;14.10;100000;2;8384;003634;4.1;1"));
+
+ verifyPosition(decoder, text(
+ "ST300STT;109002029;08;1080;20190220;13:00:55;85405;+04.645710;-074.078525;007.760;005.19;10;1;6520802;13.86;100100;4;1716;0000039863;4.1;1;0.00;0000;0000;0;0"));
+
+ verifyAttribute(decoder, text(
+ "ST300ALT;007239104;40;313;20190112;01:07:16;c99139;+04.703287;-074.148897;000.000;189.72;21;1;425512;12.61;100000;33;003188;4.1;1"),
+ Position.KEY_HOURS, 3188 * 60000L);
+
+ }
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SuntechProtocolDecoder decoder = new SuntechProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "SA200STT;608945;129;20190215;15:04:53;3dce071558;+22.006721;-098.771016;001.198;000.00;11;1;2632589;12.21;010000;1;3211"));
+
+ verifyPosition(decoder, text(
+ "ST410STT;007272376;408;01;10217;732;103;-87;51511;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;3.8;1;2503;6;20181031;20:12:58;+04.741277;-074.048238;052.375;189.87;20;1"));
+
+ verifyPosition(decoder, text(
+ "ST410STT;007272376;408;01;21651;732;123;-65;1824;1;21654;732;123;1824;0;0;22542;732;123;1824;0;0;21656;732;123;1824;0;0;21655;732;123;1824;0;0;22541;732;123;1824;0;0;0;0;0;0;0;0;3.7;1;0156;1;20180816;05:18:52;+04.722322;-074.052776;000.074;000.00;10;1"));
+
+ verifyPosition(decoder, text(
+ "ST600STT;008084783;20;419;20180308;18:00:36;0032cc3e;736;3;445c;41;-16.530023;-068.084267;018.640;267.99;10;1;11655;13.33;100000;2;0336;000061;4.5;0;0.00"));
+
+ verifyPosition(decoder, text(
+ "ST600STT;107850496;20;419;20180227;14:30:45;00462b08;736;3;4524;50;-16.479091;-068.119119;000.346;000.00;4;1;0;13.89;000000;1;0223;000003;0.0;0;0.00"));
+
+ verifyPosition(decoder, text(
+ "ST600STT;100850000;01;010;20081017;07:41:56;0000004f;450;20;0023;24;+37.478519;+126.886819;000.012;000.00;9;1;0;15.30;00110000;1;0072;0;4.5;1;12.35"));
+
+ verifyPosition(decoder, text(
+ "STT;100850000;3FFFFF;26;010;1;20161117;08:37:39;0000004F;450;0;0014;20;+37.479323;+126.887827;62.03;65.43;10;1;00000101;00001000;1;2;0492"));
+
+ verifyPosition(decoder, text(
+ "STT;6009999006;3FFFFF;26;398;0;20170827;20:04:37;087d4760;310;410;0ba0;23;+40.123420;-074.995971;000.031;000.00;8;1;00000001;00000000;1;1;0006"));
+
+ verifyPosition(decoder, text(
+ "ST500STT;205450135;07;843;20170816;23:24:45;+19.338432;-099.179817;000.283;000.00;6;1;141121;12.89;0;0;1;4659;002.795;0;001.891;611;4.0"));
+
+ verifyPosition(decoder, text(
+ "ST300STT;205170303;12;561;20170816;09:10:34;173f53;+19.082370;-098.214287;006.776;000.00;0;0;52982186;12.75;100000;2;6328;155747;4.2;1;0.00;0;0.00;0.00;00000000000000;0;28F2B7600600005D:+5.2;:;:"));
+
+ verifyPosition(decoder, text(
+ "ST910;Location;205576803;500;20170319;12:18:17;-22.846014;-046.322176;000.000;000.00;0;3.8;0;1;9159"));
+
+ verifyPosition(decoder, text(
+ "ST910;Emergency;205576803;500;20170319;12:15:22;-22.846014;-046.322176;000.000;000.00;0;2"));
+
+ verifyPosition(decoder, text(
+ "ST910;Location;205576803;500;20170312;12:56:52;-22.846014;-046.322176;000.000;000.00;0;3.8;0;0;0019"));
+
+ verifyPosition(decoder, text(
+ "ST300STT;100850000;01;010;20081017;07:41:56;00100;+37.478519;+126.886819;000.012;000.00;9;1;0;15.30;001100;1;0072;0;4.5;1;1750;012497F1160000;1;004f001454;450;00;-320;20;255;1"));
+
+ verifyPosition(decoder, text(
+ "ST300STT;205589913;05;527;20170304;02:21:33;be139;-25.398868;-049.325636;000.476;000.00;6;1;427;12.57;100000010;1;0172;017.159;0;002.327;12;4.0"));
+
+ verifyPosition(decoder, text(
+ "SA200STT;638947;803;20170117;07:40:44;5d309;-01.287213;-047.917462;000.035;000.00;10;1;2036194;12.57;000000;1;0376;010360;4.2;1"));
+
+ verifyPosition(decoder, text(
+ "ST300ALT;205174410;14;712;20110101;00:00:07;00000;+20.593923;-100.336716;000.000;000.00;0;0;0;16.57;000000;81;000000;4.0;0;0.00;0000;0000;0;0"));
+
+ verifyNull(decoder, text(
+ "SA200ALV;317652"));
+
+ verifyPosition(decoder, text(
+ "ST910;Alert;123456;410;20141018;18:30:12;+37.478774;+126.889690;000.000;000.00;0;4.0;1;6002"),
+ position("2014-10-18 18:30:12.000", false, 37.47877, 126.88969));
+
+ verifyPosition(decoder, text(
+ "ST910;Alert;123456;410;20141018;18:30:12;+37.478774;+126.889690;000.000;000.00;0;4.0;1;6002;02;0;0310000100;450;01;-282;70;255;3;0"));
+
+ verifyPosition(decoder, text(
+ "SA200STT;317652;042;20120718;15:37:12;16d41;-15.618755;-056.083241;000.024;000.00;8;1;41548;12.17;100000;2;1979"),
+ position("2012-07-18 15:37:12.000", true, -15.61876, -56.08324));
+
+ verifyPosition(decoder, text(
+ "SA200STT;317652;042;20120721;19:04:30;16d41;-15.618743;-056.083221;000.001;000.00;12;1;41557;12.21;000000;1;3125"));
+
+ verifyPosition(decoder, text(
+ "SA200STT;317652;042;20120722;00:24:23;4f310;-15.618767;-056.083214;000.011;000.00;11;1;41557;12.21;000000;1;3205"));
+
+ verifyPosition(decoder, text(
+ "SA200STT;315198;042;20120808;20:37:34;3fac25;-15.618731;-056.083216;000.007;000.00;12;1;48;0.00;000000;1;0127"));
+
+ verifyPosition(decoder, text(
+ "SA200STT;315198;042;20120809;13:43:34;4f310;-15.618709;-056.083223;000.025;000.00;8;1;49;12.10;100000;2;0231"));
+
+ verifyPosition(decoder, text(
+ "SA200EMG;317652;042;20120718;15:35:41;16d41;-15.618740;-056.083252;000.034;000.00;8;1;41548;12.17;110000;1"));
+
+ verifyPosition(decoder, text(
+ "SA200ALT;317652;042;20120829;14:25:58;16d41;-15.618770;-056.083242;000.029;000.00;0;0;2404240;0.00;000000;10"));
+
+ verifyPosition(decoder, text(
+ "SA200STT;430070;133;20130615;22:22:32;151347;+02.860514;-060.653351;000.003;000.00;12;1;0;12.39;000000;1;0208"));
+
+ verifyPosition(decoder, text(
+ "ST910;Location;344506;017;20130727;14:10:00;-25.398714;-049.296818;000.187;000.00;1;4.32;1;1;0001"));
+
+ verifyPosition(decoder, text(
+ "ST300STT;205027329;03;374;20150108;17:54:42;177b38;-23.566052;-046.477588;000.000;000.00;0;0;0;12.11;000000;1;0312"));
+
+ verifyPosition(decoder, text(
+ "ST910;Emergency;205283272;500;20150716;19:12:01;-23.659019;-046.695403;000.602;000.00;0;4.2;1;1;02;10820;2fdb090736;724;05;0;2311;255;0;100"));
+
+ decoder.setProtocolType(1);
+
+ verifyPosition(decoder, text(
+ "ST910;Location;907510186;552;20180504;23:15:45;3af54e5331;+19.301833;-099.190657;000.246;000.00;1;28462;80;1;0;0423;02;334;05;-215;20051;1;4;100"));
+
+ verifyPosition(decoder, text(
+ "ST910;Alert;485195;20170409;22:37:41;3be0133057;+24.882410;-107.509152;000.070;000.00;1;286734;72;02;295;05;-415;4912;255;10;10"));
+
+ verifyPosition(decoder, text(
+ "ST910;Location;485195;528;20170410;01:18:57;f1dd134840;+24.787139;-107.434679;000.020;000.00;1;286734;100;1;0;0188;02;295;05;-339;4936;255;4;74"));
+
+ verifyPosition(decoder, text(
+ "ST910;Location;560266;500;20161207;21:33:11;af910be101;-25.504234;-049.278003;000.080;000.00;1;10054889;70;1;1;1311;02;724;06;-317;3041;2;10;92"));
+
+ verifyPosition(decoder, text(
+ "ST910;Emergency;238569;528;20170403;00:02:09;7574160020;+19.661292;-099.144473;000.176;000.00;1;228638;1"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/SupermateProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SupermateProtocolDecoderTest.java
new file mode 100755
index 000000000..2a7ab2dee
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SupermateProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SupermateProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SupermateProtocolDecoder decoder = new SupermateProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "2:359672050130411:1:*,00000000,XT,A,10031b,140b28,80ad4c72,81ba2d2c,06ab,238c,020204010000,12,0,0000,0003e6"));
+
+ verifyPosition(decoder, text(
+ "2:359672050130411:2:*,00000000,UP,A,10031b,140a1c,80ad4bf6,81ba2dc3,0000,0000,020204000000,14,0,0000,0003e6"));
+
+ verifyPosition(decoder, text(
+ "2:359672050130411:1:*,00000000,BJ,A,10031b,140c2f,80ad5012,81ba1f27,0f4c,2e18,020204014000,14,0,0000,0003ed"));
+
+ }
+
+} \ No newline at end of file
diff --git a/src/test/java/org/traccar/protocol/SviasProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/SviasProtocolDecoderTest.java
new file mode 100644
index 000000000..f7b15ca2e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/SviasProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class SviasProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ SviasProtocolDecoder decoder = new SviasProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "[7061,3041,57,20324277,710,40618,141342,-93155840,-371754060,0,20469,0,16,1,0,0,11323,100,9,,32,4695"));
+
+ verifyPosition(decoder, text(
+ "[7041,3041,8629,20856286,710,60618,201027,-92268040,-371346250,7994,31844,38271,16,1,0,0,13416,100,0,0,5089"));
+
+ verifyPosition(decoder, text(
+ "[7051,3041,15270,30179873,710,70618,40335,-94679080,-360604930,0,35454,23148,0,1,0,0,12542,100,13,32,4971"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/T55ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/T55ProtocolDecoderTest.java
new file mode 100644
index 000000000..f21acdee7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/T55ProtocolDecoderTest.java
@@ -0,0 +1,126 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class T55ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ T55ProtocolDecoder decoder = new T55ProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "$DEVID,0x0103846677F21422*41"));
+
+ verifyPosition(decoder, text(
+ "660420156A0066AA$GPRMC,122806.0,A,0119.212178,N,10355.000942,E,0.0,,230119,0.0,E,A*27"));
+
+ verifyNull(decoder, text(
+ "$IMEI=355797031609284"));
+
+ verifyNull(decoder, text(
+ "086415031C20"));
+
+ verifyNull(decoder, text(
+ "358244017671308"));
+
+ verifyPosition(decoder, text(
+ "$GPGGA,082350.000,5355.0314,N,01044.1271,E,1,10,0.7,-46.0,M,0.0,M,0.0,0000"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,082350.000,A,5355.0314,N,01044.1271,E,26.20,184.27,080518,,"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,192350.000,V,0000.0000,N,00000.0000,E,,,110318,,*12"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,073446.000,A,1255.5125,N,07738.2948,E,0.00,0.53,080316,D*71,11,865733027593268,1,090,086,123,456,789,987,12345"));
+
+ verifyNotNull(decoder, text(
+ "$GPRMC,161223.000,A,2517.0545,S,05739.1788,W,0.0,0.0,011196,,,A*61"));
+
+ verifyPosition(decoder, text(
+ "4711/022789000688081/$GPRMC,133343,A,5308.56325,N,1029.12850,E,0.000000,0.000000,290316,,*2A"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,073446.000,A,1255.5125,N,07738.2948,E,0.00,0.53,080316,D*71,11,865733027593268,1,090,086"));
+
+ verifyNull(decoder, text(
+ "$GPFID,ID123456ABC"));
+
+ verifyNull(decoder, text(
+ "$PGID,359853000144328*0F"));
+
+ verifyNull(decoder, text(
+ "$PCPTI,CradlePoint Test,184453,184453.0,6F*57"));
+
+ verifyNull(decoder, text(
+ "IMEI 351467108700000"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,012006,A,4828.10,N,1353.52,E,0.00,0.00,180915,020.3,E*42"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,094907.000,A,6000.5332,N,03020.5192,E,1.17,60.26,091111,,*33"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,115528.000,A,6000.5432,N,03020.4948,E,,,091111,,*06"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,064411.000,A,3717.240078,N,00603.046984,W,0.000,1,010313,,,A*6C"));
+
+ verifyPosition(decoder, text(
+ "$GPGGA,000000.0,4337.200755,N,11611.955704,W,1,05,3.5,825.5,M,-11.0,M,,*6F"));
+
+ verifyPosition(decoder, text(
+ "$GPGGA,000000,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"));
+
+ verifyPosition(decoder, text(
+ "$GPRMA,V,0000.00,S,00000.00,E,,,00.0,000.,11.,E*7"));
+
+ verifyPosition(decoder, text(
+ "$TRCCR,20140101001122.333,V,60.0,-100.0,1.1,2.2,3.3,4.4,*00"));
+
+ verifyPosition(decoder, text(
+ "$TRCCR,20140111000000.000,A,60.000000,60.000000,0.00,0.00,0.00,50,*3a"));
+
+ verifyPosition(decoder, text(
+ "$GPRMC,125735.000,A,6010.34349,N,02445.72838,E,1.0,101.7,050509,6.9,W,A*1F"));
+
+ verifyPosition(decoder, text(
+ "$GPGGA,000000.000,6010.34349,N,02445.72838,E,1,05,1.7,0.9,M,35.1,M,,*59"));
+
+ verifyPosition(decoder, text(
+ "123456789$GPGGA,000000.000,4610.1676,N,00606.4586,E,0,00,4.3,0.0,M,50.7,M,,0000*59"));
+
+ verifyPosition(decoder, text(
+ "123456789$GPRMC,155708.252,V,4610.1676,N,00606.4586,E,000.0,000.0,060214,,,N*76"));
+
+ verifyPosition(decoder, text(
+ "990000561287964,$GPRMC,213516.0,A,4337.216791,N,11611.995877,W,0.0,335.4,181214,,,A * 72"));
+
+ verifyPosition(decoder, text(
+ "355096030432529$GPGGA,000000.00,3136.599,S,5213.981,W,1,7,2.13,250.00,M,-16.384,M,3550960304325290.0,1"));
+
+ verifyPosition(decoder, text(
+ "355096030432529$GPGGA,000000.00,3136.628,S,5213.990,W,1,7,2.13,250.00,M,-16.384,M,0.0,1"));
+
+ }
+
+ @Test
+ public void testMaxonDecode() throws Exception {
+
+ // Maxon devices can send NMEA before identification
+
+ T55ProtocolDecoder decoder = new T55ProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "$GPRMC,012006,A,4828.10,N,1353.52,E,0.00,0.00,180915,020.3,E*42"));
+
+ verifyPosition(decoder, text(
+ "$GPFID,ID123456ABC"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/T57FrameDecoderTest.java b/src/test/java/org/traccar/protocol/T57FrameDecoderTest.java
new file mode 100644
index 000000000..f74d3c350
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/T57FrameDecoderTest.java
@@ -0,0 +1,19 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class T57FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ T57FrameDecoder decoder = new T57FrameDecoder();
+
+ verifyFrame(
+ binary("2a5435372346312354353731313137303031233330313131372330303038343323323233342e31333033234e2330383832362e313731342345232b302e3234322c2b302e3130392c2d302e37383923302e30303023362e323030303023413223342e3223"),
+ decoder.decode(null, null, binary("2a5435372346312354353731313137303031233330313131372330303038343323323233342e31333033234e2330383832362e313731342345232b302e3234322c2b302e3130392c2d302e37383923302e30303023362e323030303023413223342e32232a5435372346312354353731313137303031233330313131372330303038353323323233342e31333033234e2330383832362e313731342345232b302e3234322c2b302e3130392c2d302e37383923302e30303023362e323030303023413223342e32232a5435372346312354353731313137303031233330313131372330303039303423323233342e31333033234e2330383832362e313731342345232b302e3234322c2b302e3130392c2d302e37383923302e30303023362e323030303023413223342e32232a5435372346312354353731313137303031233330313131372330303039313423323233342e31333033234e2330383832362e313731342345232b302e3234322c2b302e3130392c2d302e37383923302e30303023362e323030303023413223342e32232a5435372346312354353731313137303031233330313131372330303039323423323233342e31333033234e2330383832362e313731342345232b302e3234322c2b302e3130392c2d302e37383923302e30303023362e323030303023413223342e32232a5435372346312354353731313137303031233330313131372330303038333323323233342e31333033234e2330383832362e313731342345232b302e3234322c2b302e3130392c2d302e37383923302e30303023362e323030303023413223342e3223")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/T57ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/T57ProtocolDecoderTest.java
new file mode 100644
index 000000000..c457b4602
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/T57ProtocolDecoderTest.java
@@ -0,0 +1,27 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class T57ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ T57ProtocolDecoder decoder = new T57ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "*T57#F1#T571117001#301117#000843#2234.1303#N#08826.1714#E#+0.242,+0.109,-0.789#0.000#6.20000#A2#4.2#"));
+
+ verifyPosition(decoder, text(
+ "*T57#F1#0123456789#041117#152900#1258.9653#N#07738.4169#E#00000000000000000000#0.000#926.300#A2#4.0#"));
+
+ verifyPosition(decoder, text(
+ "*T57#F2#0123456789#041117#152900#1258.9653#N#07738.4169#E#00000000000000000000#0.000#926.300#A2#4.0#"));
+
+ verifyNull(decoder, text(
+ "*T57#F3#0123456789#041117#152900#1258.9653#N#07738.4169#E#I#9674432345#340#"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/T800xProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/T800xProtocolDecoderTest.java
new file mode 100644
index 000000000..fe77d91b7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/T800xProtocolDecoderTest.java
@@ -0,0 +1,48 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class T800xProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ T800xProtocolDecoder decoder = new T800xProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "252501001504050880061689888888111111250350"));
+
+ verifyPosition(decoder, binary(
+ "2525020044a66d0862522030401350001403841409c40064edc000051100960000071701370000003ea7ee0019032010581300000000aad3e1bda6f24d42000000001281"));
+
+ verifyPosition(decoder, binary(
+ "252502004400010880616898888888000A00FF2001000020409600989910101010055501550000101005050005051010050558866B4276D6E342912AB441111500051010"));
+
+ verifyNull(decoder, binary(
+ "232301001500000880316890202968140197625020"));
+
+ verifyNull(decoder, binary(
+ "232303000f00000880316890202968"));
+
+ verifyAttributes(decoder, binary(
+ "232302004200000880316890202968001e02582d00000000000000050000320000018901920000001dc1e2001601081154255d0202005a0053875a00a57e5a00af80"));
+
+ verifyNull(decoder, binary(
+ "232301001500020357367031063979150208625010"));
+
+ verifyNull(decoder, binary(
+ "232303000f00000357367031063979"));
+
+ verifyPosition(decoder, binary(
+ "232304004200030357367031063979003c03842307d00000c80000050100008000008900890100000017b100151022121648b8ef0c4422969342cec5944100000110"));
+
+ verifyPosition(decoder, binary(
+ "232302004200150357367031063979003c03842307d000004a0000050100004001009500940000000285ab001510281350477f710d4452819342d1ba944101160038"));
+
+ verifyAttributes(decoder, binary(
+ "232302004200000357367031063979003c03842307d000008000000501000000010094009400000002a0b90015102814590694015a00620cf698620cf49e620cf498"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/T800xProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/T800xProtocolEncoderTest.java
new file mode 100644
index 000000000..af3700225
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/T800xProtocolEncoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class T800xProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ T800xProtocolEncoder encoder = new T800xProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "RELAY,0000,On#");
+
+ verifyCommand(encoder, command, binary("232381001e000101234567890123450152454c41592c303030302c4f6e23"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TaipProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TaipProtocolDecoderTest.java
new file mode 100644
index 000000000..bdbaec8aa
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TaipProtocolDecoderTest.java
@@ -0,0 +1,86 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TaipProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TaipProtocolDecoder decoder = new TaipProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ ">RGP211217112154-2748332-058946350000000FF7F2100;ID=AA01;#0002;*2D<"));
+
+ verifyPosition(decoder, text(
+ ">RCV12270218010247-3471349-058400030002057F001200020A1D013010600001509+0000FF+0000FF;#1DE2;ID=7196;*03<"));
+
+ verifyPosition(decoder, text(
+ ">RPV03874+3477708-0923453100029212;ID=0017;*71<"));
+
+ verifyNull(decoder, text(
+ ">RAL03874+00185+00012;ID=0017;*4A<"));
+
+ verifyNull(decoder, text(
+ ">RCP03874+347771-092345312;ID=0017;*65<"));
+
+ verifyNull(decoder, text(
+ ">RLN03874000+347770828-0923453071+000608270000+0000292309000000000000000000000000000000000000000000000012;ID=0017;*49<"));
+
+ verifyPosition(decoder, text(
+ ">RPV46640+4197412-0752857900015802;ID=5102;*71<"));
+
+ verifyNull(decoder, text(
+ ">RCP46640+419741-075285802;ID=5102;*6C<"));
+
+ verifyPosition(decoder, text(
+ ">REV001958003965+0307178+1016144900031532;IO=300;SV=8;BL=4159;CF=8161,C,13;AD=14145;IX=10233040;FF=0,0,0,0;VO=338578;ID=357042063052352<"));
+
+ verifyPosition(decoder, text(
+ ">REV011958000369+0307185+1016144400000032;IO=200;SV=9;BL=4158;CF=0,0,0;AD=12347;IX=10213040;FF=0,0,0,0;VO=338572;ID=357042063052352<"));
+
+ verifyPosition(decoder, text(
+ ">REV421942237017+1170957-0701880200000032;ID=356612022463055<"));
+
+ verifyPosition(decoder, text(
+ ">RGP200317010815-3852.9306-06204.88560000003000101;&01;ID=5555;#7AD7*51<"));
+
+ verifyPosition(decoder, text(
+ ">RCQ09000000000000-3460365-058381460000007F0000000000000115000FFFF1099;#0000;ID=555224;*05<"));
+
+ verifyPosition(decoder, text(
+ ">RBR00130217040848-3462200-05846708000175FF0022900003B3C13010800001118410+24061A;ID=555224;*07<"));
+
+ verifyPosition(decoder, text(
+ ">REV451891352379+0307152+1016143700000012;SV=8;BL=4416;VO=8055;ID=356612026322000<"));
+
+ verifyPosition(decoder, text(
+ ">RGP230615010248-2682523-065236820000003007F4101;ID=0005;#0002;*2A<"),
+ position("2015-06-23 01:02:48.000", true, -26.82523, -65.23682));
+
+ verifyPosition(decoder, text(
+ ">RGP190805211932-3457215-058493640000000FFBF0300;ID=8251;#2122;*54<"));
+
+ verifyPosition(decoder, text(
+ ">RPV00000+3739438-1220384601512612;ID=1234;*7F"));
+
+ verifyPosition(decoder, text(
+ "\r\n>REV691615354941+3570173+1397742703203212;ID=Test"));
+
+ verifyPosition(decoder, text(
+ ">REV481599462982+2578391-0802945201228512;ID=Test"),
+ position("2010-09-02 17:29:42.000", true, 25.78391, -80.29452));
+
+ verifyPosition(decoder, text(
+ ">REV131756153215+3359479-0075299001031332;VO=10568798;IO=310;SV=10;BL=4190;CV09=0;AD=0;AL=+47;ID=356612021059680"));
+
+ verifyPosition(decoder, text(
+ ">RPV02138+4555512-0735478000000032;ID=1005;*76<"));
+
+ verifyPosition(decoder, text(
+ ">RPV19105+4538405-0739518900000012;ID=9999;*7A<\r\n"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TekFrameDecoderTest.java b/src/test/java/org/traccar/protocol/TekFrameDecoderTest.java
new file mode 100644
index 000000000..0446670d8
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TekFrameDecoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TekFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TekFrameDecoder decoder = new TekFrameDecoder();
+
+ verifyFrame(
+ binary("020315048715E70861074028023219026200400A0340002C007F0009000000000000000000402842064028420641284206402844064128440640284406402844064028440641284406402844060010010C04052B000253000000000001060A0000000000000228330000FF0000FF360014B394"),
+ decoder.decode(null, null, binary("020315048715E70861074028023219026200400A0340002C007F0009000000000000000000402842064028420641284206402844064128440640284406402844064028440641284406402844060010010C04052B000253000000000001060A0000000000000228330000FF0000FF360014B394")));
+
+ verifyFrame(
+ binary("0501C2828E14750861075021004551047B00019700000082010F0A5B28770A5B28770A5B28760A5B28770A5B28770A5B28770A5B28770A5B28760A5B28760A5B28760A5B28770A5B28760A5B28760A5B28760A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5F2877000000000000000000000000EEBA"),
+ decoder.decode(null, null, binary("0501C2828E14750861075021004551047B00019700000082010F0A5B28770A5B28770A5B28760A5B28770A5B28770A5B28770A5B28770A5B28760A5B28760A5B28760A5B28770A5B28760A5B28760A5B28760A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5F2877000000000000000000000000EEBA")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TekProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TekProtocolDecoderTest.java
new file mode 100644
index 000000000..f67ae9c3f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TekProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TekProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TekProtocolDecoder decoder = new TekProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "0501E304E00E76086107502100455111492C33332C3137303935342E302C353235352E393933344E2C30303833322E34333935572C322E312C3133342E382C322C302E30302C302E302C302E302C3234303931352C30362C3C45"));
+
+ verifyAttributes(decoder, binary(
+ "0501C2828E14750861075021004551047B00019700000082010F0A5B28770A5B28770A5B28760A5B28770A5B28770A5B28770A5B28770A5B28760A5B28760A5B28760A5B28770A5B28760A5B28760A5B28760A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5D28770A5F2877000000000000000000000000EEBA"));
+
+ verifyAttributes(decoder, binary(
+ "0509220886157E0863835020373564087B00018C0000018003160A6E28790A6E28790A6E287A0A6E287A0A6E287A0A6E287A0A6E287A0A6E287A0A6E287A0A6E287A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BD35"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TelemaxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TelemaxProtocolDecoderTest.java
new file mode 100644
index 000000000..e330600e5
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TelemaxProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TelemaxProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TelemaxProtocolDecoder decoder = new TelemaxProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "%067374070128"));
+
+ verifyPositions(decoder, text(
+ "Y000007C6999999067374074649003C00A7018074666F60D66818051304321900000000C5"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TelicFrameDecoderTest.java b/src/test/java/org/traccar/protocol/TelicFrameDecoderTest.java
new file mode 100644
index 000000000..5fcbcbb57
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TelicFrameDecoderTest.java
@@ -0,0 +1,42 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TelicFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TelicFrameDecoder decoder = new TelicFrameDecoder();
+
+ verifyFrame(
+ binary("303032363230333339337c3232367c31307c303032303034303130"),
+ decoder.decode(null, null, binary("303032363230333339337c3232367c31307c30303230303430313000")));
+
+ verifyFrame(
+ binary("3030333032303333393332352c3139303331373038333035322c302c3138303331373130333132372c3235393932342c3434353133332c332c302c302c392c2c2c39332c31323231303134312c2c303031302c30302c34302c3234302c302c30343036"),
+ decoder.decode(null, null, binary("630000003030333032303333393332352c3139303331373038333035322c302c3138303331373130333132372c3235393932342c3434353133332c332c302c302c392c2c2c39332c31323231303134312c2c303031302c30302c34302c3234302c302c3034303600")));
+
+ verifyFrame(
+ binary("303032363239363231385343434530315f534343457c3232367c31307c30323637"),
+ decoder.decode(null, null, binary("303032363239363231385343434530315f534343457c3232367c31307c3032363700")));
+
+ verifyFrame(
+ binary("30303434323936323138544c4f43303236372c30302c3031313030393030303239363231382c3139303331373038333033362c3235353137382c3434353037322c332c302c38322c2c2c2c3136382c31343734313239362c2c30302c30302c302c323137"),
+ decoder.decode(null, null, binary("6400000030303434323936323138544c4f43303236372c30302c3031313030393030303239363231382c3139303331373038333033362c3235353137382c3434353037322c332c302c38322c2c2c2c3136382c31343734313239362c2c30302c30302c302c32313700")));
+
+ verifyNull(
+ decoder.decode(null, null, binary("00303032363937393238317c3233327c30337c30303230303430313000")));
+
+ verifyFrame(
+ binary("303032363937393238317c3233327c30337c303032303034303130"),
+ decoder.decode(null, null, binary("303032363937393238317c3233327c30337c30303230303430313000")));
+
+ verifyFrame(
+ binary("3030323039373932383139392c3231303231363038313930302c302c3231303231363038313835392c3031333839333338352c34363635383639352c332c302c302c382c2c2c3534312c36313239382c2c303030302c30302c302c3139362c302c30343037"),
+ decoder.decode(null, null, binary("650000003030323039373932383139392c3231303231363038313930302c302c3231303231363038313835392c3031333839333338352c34363635383639352c332c302c302c382c2c2c3534312c36313239382c2c303030302c30302c302c3139362c302c3034303700")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java
new file mode 100644
index 000000000..b743cef96
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TelicProtocolDecoderTest.java
@@ -0,0 +1,94 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TelicProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TelicProtocolDecoder decoder = new TelicProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "0026355565071347499|206|01|001002008"));
+
+ verifyPosition(decoder, text(
+ "052028495198,160917073641,0,160917073642,43879,511958,3,24,223,17,,,-3,142379,,0010,00,64,205,0,0499"));
+
+ verifyPosition(decoder, text(
+ "01302849516,160917073503,0,160917073504,43907,512006,3,11,160,14,,,-7,141811,,0010,00,64,206,0,0499"));
+
+ verifyPosition(decoder, text(
+ "002135556507134749999,010817171138,0,010817171138,004560973,50667173,3,0,0,11,1,1,100,958071,20601,000000,00,4142,0000,0000,0208,10395,0"));
+
+ verifyPosition(decoder, text(
+ "442045993198,290317131935,0,290317131935,269158,465748,3,26,183,,,,184,85316567,226,01,00,68,218"));
+
+ verifyPosition(decoder, text(
+ "673091036017,290317131801,0,290317131801,262214,450536,3,40,199,8,,,154,19969553,,0011,00,59,240,0,0406"));
+
+ verifyPosition(decoder, text(
+ "092020621198,280317084155,0,280317084156,259762,444356,3,42,278,9,,,89,56793311,,0110,00,67,0,,0400"));
+
+ verifyPosition(decoder, text(
+ "502091227598,280317084149,0,280317084149,261756,444358,3,33,286,9,,,77,3143031,,0010,00,171,240,0,0406"));
+
+ verifyPosition(decoder, text(
+ "232027997498,230317083900,0,230317083900,260105,444112,3,22,259,,,,111,61110817,226,01,00,255,218,00000000000000"));
+
+ verifyPosition(decoder, text(
+ "072027997498,230317082635,0,230317082635,260332,444265,3,28,165,,,,124,61107582,226,01,00,255,219,00000000000000"));
+
+ verifyNull(decoder, text(
+ "0026203393|226|10|002004010"));
+
+ verifyPosition(decoder, text(
+ "003020339325,190317083052,0,180317103127,259924,445133,3,0,0,9,,,93,12210141,,0010,00,40,240,0,0406"));
+
+ verifyNull(decoder, text(
+ "0026296218SCCE01_SCCE|226|10|0267"));
+
+ verifyNull(decoder, text(
+ "1242022592TTUV0100,0201,351266000022592,170403114305,0115859,480323,3,30,5,9,3,4,650,250000000,26202,1001,0001,211,233,111,0"));
+
+ verifyPosition(decoder, text(
+ "123002259213,170403114305,1234,170403114305,0115859,480323,3,30,5,9,3,4,650,250000000,26202,1001,0001,211,233,111,0,600"));
+
+ verifyNull(decoder, text(
+ "0044296218TLOC0267,00,011009000296218,190317083036,255178,445072,3,0,82,,,,168,14741296,,00,00,0,217"));
+
+ verifyPosition(decoder, text(
+ "003097061325,220616044200,0,220616044200,247169,593911,3,48,248,8,,,50,1024846,,1111,00,48,0,51,0406"));
+
+ verifyPosition(decoder, text(
+ "003097061325,210216112630,0,210216001405,246985,594078,3,0,283,12,,,23,4418669,,0010,00,117,0,0,0108"));
+
+ verifyPosition(decoder, text(
+ "592078222222,010100030200,0,240516133500,222222,222222,3,0,0,5,,,37,324,,1010,00,48,0,0,0406"));
+
+ verifyPosition(decoder, text(
+ "002017297899,220216111100,0,220216111059,014306446,46626713,3,7,137,7,,,448,266643,,0000,00,0,206,0,0407"));
+
+ verifyPosition(decoder, text(
+ "003097061325,210216112630,0,210216001405,246985,594078,3,0,283,12,,,23,4418669,,0010,00,117,0,0,0108"));
+
+ verifyNull(decoder, text(
+ "0026970613|248|01|004006011"));
+
+ verifyPosition(decoder, text(
+ "032097061399,210216112800,0,210216112759,246912,594076,3,47,291,10,,,46,4419290,,0010,00,100,0,0,0108"));
+
+ verifyPosition(decoder, text(
+ "002017297899,190216202500,0,190216202459,014221890,46492170,3,0,0,6,,,1034,43841,,0000,00,0,209,0,0407"));
+
+ verifyPosition(decoder, text(
+ "182043672999,010100001301,0,270613041652,166653,475341,3,0,355,6,2,1,231,8112432,23201,01,00,217,0,0,0,0,7"),
+ position("2013-06-27 04:16:52.000", true, 47.53410, 16.66530));
+
+ verifyPosition(decoder, text(
+ "182043672999,010100001301,0,270613041652,166653,475341,3,0,355,6,2,1,231,8112432,23201,01,00,217,0,0,0,0,7"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TeltonikaProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TeltonikaProtocolDecoderTest.java
new file mode 100644
index 000000000..f94cd9460
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TeltonikaProtocolDecoderTest.java
@@ -0,0 +1,134 @@
+package org.traccar.protocol;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class TeltonikaProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TeltonikaProtocolDecoder decoder = new TeltonikaProtocolDecoder(null, false);
+
+ verifyNull(decoder, binary(
+ "000F313233343536373839303132333435"));
+
+ verifyPositions(decoder, binary(
+ "000000000000004c08010000016818d500580009c28d9f1cb3757a00be00c60f0053000f06f0011503c80001011d00fc0007423799180053cdf80dce426f430f88190bb8560bb802f100005aa110002887e000010000ee8d"));
+
+ verifyPositions(decoder, binary(
+ "00000000000000818e0100000166e368a510000f0d8b5b20961c35008d010308000000000014000900ef0000f00100500100150400c800004501001e00002500002900000a00b5000800b60007004230dc0018000000430fcb0044005f001103de001200e50013001200240000000000000001010000113141314a433534343452373235323336370100005e99"));
+
+ verifyPositions(decoder, binary(
+ "000000000000009D10020000013feb55ff74000f0ea850209a690000AE00B90B00000000070A050001000002000003000004000120000200180000004601290200C700000000004C0000000001003E00000000000000000000015B198C7498000F0DBC502095872F00AE00B90B00000000070A050001000002000003000004000120000200180000004601290200C700000000004C0000000001003E000000000000000002000009A5"));
+
+ verifyPositions(decoder, binary(
+ "000000000000009F100100000164D855401800D5E3B744EC11C762023B011A060000000007200A010000010500010600010D00010E00010F00011600011700011800011F001301010000010700000108000001090000010A0000010B0000010C000001100000011100000112000001130000011400000115000001190000011A0000011B0000011C0000011D0000011E000003010200000000010300000000010400000000000100000D3B"));
+
+ verifyPositions(decoder, binary(
+ "000000000000008c08010000013feb55ff74000f0ea850209a690000940000120000001e09FD01FE210300040016014703f0001504c8000c0900730a00460b00501300464306d7440000b5000bb60007422e9f180000cd0386ce000107c700000000f10000601a46000001344800000bb84900000bb84a00000bb84c00000000024e0000000000000000cf00000000000000000100003fca"));
+
+ verifyPositions(decoder, binary(
+ "00000000000000A708010000016269E7D9A8000A5A0F0A1CBF8F3300880046120000001C0801014F005100550F740073007801790103430000440000426F980B540000000056000045275700000047580000022659000000005D0000000068000003D07100007355870000000288000000008A000045270669584C5241534834336A30304731363538326B3600FFFFFF0000008155412055414430308230303039383236368330303000000000000100008396"));
+
+ verifyPositions(decoder, binary(
+ "0000000000000035080100000161f37c50500020de5ba60ef11450000000000000000006040100b300b400ef000109002000014e0000000000000000010000be52"));
+
+ verifyPositions(decoder, binary(
+ "000000000000008c08010000013feb55ff74000f0ea850209a690000940000120000001e09010002000300040016014703f0001504c8000c0900730a00460b00501300464306d7440000b5000bb60007422e9f180000cd0386ce000107c700000000f10000601a46000001344800000bb84900000bb84a00000bb84c00000000024e0000000000000000cf00000000000000000100003fca"));
+
+ verifyPositions(decoder, binary(
+ "0000000000000401080e0000015d12cc211000fadaf627186742f5000d0048080006000a040100f001500515000342318a430fe344000003c700000000f1000068b61000001b05000000015d12c6683800fadaf72118673f82000000000000000007030100f00050040342318a430fe344000001f1000068b6000000015d12bd407800fadaf72118673f82000000000000000007030100f000500403423179430fe144000001f1000068b6000000015d12b414d000fadaf72118673f82000400900c0000fa120a0100f00050051502080007010552090e6f4bfa000542316a430fe14400000600006202b203c700002328f1000068b61000001b05000000015d12b3074800fadaf2821867436a000400890d00170011090100f00150011502081007010553090e6f4d054231fb430fe14400000603ae6202a003c700002328f1000068b61000001b05000000015d12b2ff7800fadaee89186747c60005009a0d001d0011090100f00150011502081b07010553090e6f4d05423125430fe144000006050862029e03c700002328f1000068b61000001b05000000015d12b2e42000fadae8cf18675e0a000300a60d00210011090101f00150011502082407030554090e6f4d0542310a430fe14400000606cf62029703c700002328f1000068b61000001b05000000015d12b2d48000fadae05818676a16000400930c00240011090100f00150011502082207010554090e6f4e05423738430fe144000006066a62029303c700002328f1000068b61000001b05000000015d12b2a1b800fadac33e18678e48000600940d00150011090101f00150051500081907030553090e6f4e054239cc430fe14400000607c662028603c700002328f1000000001000001b05000000015d12b29dd000fadac19d18678fc8000700820d00110011090100f00150051500081607030553090e6f4e054238c8430fe14400000606d962028503c700002328f1000000001000001b05000000015d12b299e800fadabfa9186790e3000700670d00110011090101f00150051500081407030553090e6f4e054231e5430fe144000006060a62028403c700002328f1000000001000001b05000000015d12b2960000fadabd4018679104000600510d00120011090101f00150051500081207030553090e6f4e054231ce430fe144000006057062028303c700002328f1000000001000001b05000000015d12b27aa800fadaa96518678b7c000600470d00120011090101f00150051500081807030551090e6f4e05423a70430fe144000006074462027c03c700002328f1000000001000001b05000000015d12b276c000fadaa73f18678ae60006003b0d000e0011090101f00150051500081607030551090e6f4e05423a5a430fe14400000606b762027b03c700002328f1000000001000001b05000e000007a4"));
+
+ verifyPositions(decoder, binary(
+ "00000000000002cb08080000015a71ccbec00002fc9bfc1e53a1e00016004cf80005001914150216056500ee00ef00f0009d029e029f02a002a102a202a302a402a502a602020003000164d20003480100c6000ac500ce02c80000654ec700004ee8000000015a725aaac80002fc933c1e539d4000150049f80000001914150116056500ee00ef00f0009d029e029f02a002a102a202a302a402a502a602020003000164d200034800f4c6000ac500ce02c80000654ec700004ee8000000015a75a42c900002fc97d01e539640001d0008020000001914150016056500ee00ef00f0009d029e029f02a002a102a202a302a402a502a602020003000164d200034800f8c6000ac500ce02c80006ba5ac700004ee8000000015a75a440180002fc931c1e539b60001d00b9020001001914150016056500ee00ef00f0009d029e029f02a002a102a202a302a402a502a602020003000164d200034800fac6000ac500ce02c80006ba5ac700004ee8000000015a75a453a00002fc93601e539cc0001d015d0c0000001914150016056500ee00ef00f0009d029e029f02a002a102a202a302a402a502a602020003000164d200034800f9c6000ac500ce02c80006ba5ac700004ee8000000015a75a467280002fc93801e539cc0001d013c0c0000001914150016056500ee00ef00f0009d029e029f02a002a102a202a302a402a502a602020003000164d200034800f9c6000ac500ce02c80006ba5ac700004ee8000000015a75a47ab00002fc92cc1e539c80001d00b00c0000001914150016056500ee00ef00f0009d029e029f02a002a102a202a302a402a502a602020003000164d200034800f8c60004c5000a02c800003085c70006ba5a000000015a75a48e380002fc92ec1e539c40001d00410c0000001914150116056500ee00ef00f0009d029e029f02a002a102a202a302a402a502a602020003000164d200034800f8c6000ac500ce02c80000c83dc700004ee800080000e0b2"));
+
+ verifyPositions(decoder, binary(
+ "0000000000000000080100000113fc208dff00209cca800f14f650006f00d60400040004030101150316030001460000015d000100000000")); // invalid length and checksum
+
+ verifyPositions(decoder, binary(
+ "000000000000009f080400000159738f76b8012e13b796110ab27600d700000b00004e01000000014e000000000000000000000159738f6ee8012e13b796110ab27600d700000a00004e01000000014e01000b00791c179300000159738f6b00012e13b796110ab27600d700000a00004e01000000014e000000000000000000000159738f5f48012e13b796110ab27600d700000b00004e01000000014e01000b00791c17930400009671"));
+
+ verifyPositions(decoder, false, binary(
+ "00000000000000710c0106000000694154244d5347534e443d342c225354474234302c50522c3335363630313036303236353035302c313630343232313531372c313630343232313531382c432c2b3032332e332c302c2b3032332e312c302c4445414354492c302c4445414354492c302c312c30220d0a010000d8db"));
+
+ verifyPositions(decoder, false, binary(
+ "0000000000000055070450aa14320201f00150aa17f3031f42332a4c4193d68c008d00020901f00150aa1b6a031f423383f54193624f009d00000a01f00150aa1c230fc01a0000552b040164f400dd00f0010143100c0105000000050400006846"));
+
+ verifyPositions(decoder, binary(
+ "000000000000003508010000014f8e016420002141bbaf0f4e96a7fffa0000120000000602010047030242669c92000002c7000000009100000000000100002df3"));
+
+ verifyPositions(decoder, binary(
+ "00000000000000A7080400000113fc208dff000f14f650209cca80006f00d60400040004030101150316030001460000015d0000000113fc17610b000f14ffe0209cc580006e00c00500010004030101150316010001460000015e0000000113fc284945000f150f00209cd200009501080400000004030101150016030001460000015d0000000113fc267c5b000f150a50209cccc0009300680400000004030101150016030001460000015b00040000"));
+
+ verifyPositions(decoder, binary(
+ "000000000000014708060000013e5a60a4cb003fa7b780fc424518004200000a000000090501010200b300b400f000034268a746011818000001c700000000000000013e5dc8ba28003fa7c080fc4246040001000005000000090501010200b300b400f001034268b44600ef18000001c700000000000000013e5dc90455003fa7b640fc424388003a0000070000f0090501010200b300b400f000034268dc4600f718000001c70000001d000000013e5dc9d368003fa7b800fc4244300049000004000000090501010200b300b400f001034267de46010718000001c700000000000000013e5dca311d003fa7b680fc4243cc00420000070000f0090501010200b300b400f0000342685346010b18000001c700000000000000013e5dcfafe9003fa7b600fc4242f0003d000008000000090501010200b300b400f0000342685246011918000001c700000000000600000275"));
+
+ verifyPositions(decoder, binary(
+ "000000000000002c08010000013eff8d6f9800173295002111f400008100ae0b0000000401010003090016432980422f7200000100007a5d"));
+
+ verifyPositions(decoder, binary(
+ "00000000000000c7070441bf9db00fff425adbd741ca6e1e009e1205070001030b160000601a02015e02000314006615000a160067010500000ce441bf9d920fff425adbb141ca6fc900a2b218070001030b160000601a02015e02000314006615000a160067010500000cc641bf9d740fff425adbee41ca739200b6c91e070001030b1f0000601a02015f02000314006615000a160066010500000ca841bf9cfc0fff425adba041ca70c100b93813070001030b1f0000601a02015f02000314002315000a160025010500000c3004000000"));
+
+ verifyPositions(decoder, binary(
+ "000000000000003107024c61410b013f4231c2c141d0beb9003d000005006483ff4c6140eb013f4231c2c141d0beb9003d000005006483ff02000041df"));
+
+ verifyPositions(decoder, binary(
+ "000000000000002b080100000140d4e3ec6e000cc661d01674a5e0fffc00000900000004020100f0000242322318000000000100007a04"));
+
+ verifyPositions(decoder, false, binary(
+ "000000000000002d0c01060000002523464d323d3236323033323736313732313339362c32363230332c30372e30322e30350d0a0100009a2e"));
+
+ verifyPositions(decoder, binary(
+ "00000000000000a608010000013f14a1d1ce000f0eb790209a778000ab010c0500000000000000000100003390"));
+
+ verifyPositions(decoder, binary(
+ "000000000000004508010000015eb70a86d00024089d4d21dee3860137005f12005f000e06ef01f00150011503c800450108b5000bb6000642382718005fcd057ace19d3430f57440000000001000002bf"));
+
+ verifyPositions(decoder, binary(
+ "000000000000004a08010000015ebc1da508002411926621f15246010b00b913005e000f06ef01f00150011505c800450108b5000bb6000642381b18005ecd0318ce19cd430f5844000001f1000061a900010000c8e1"));
+
+ decoder.setExtended(true);
+
+ verifyPositions(decoder, false, binary(
+ "0000000000000158080b0000015d4b4dc07a00d5dbd13eec04324e020e0000120000000000000000000000015d4b4cd5e800d5dbd13eec04324e020e0000120000000000000000000000015d4b4beb8800d5dbd13eec04324e020e0000130000000000000000000000015d4b4b012800d5dbd13eec04324e020e0000120000000000000000000000015d4b4a16c800d5dbd13eec04324e020f0000110000000000000000000000015d4b492c6800d5dbd13eec04324e020f0000110000000000000000000000015d4b48420800d5dbd13eec04324e020f0000120000000000000000000000015d4b4757a800d5dbd13eec04324e020f00000f0000000000000000000000015d4b466d4800d5dbd13eec04324e020f0000100000000000000000000000015d4b4582e800d5dbd13eec04324e020f0000110000000000000000000000015d4b44988800d5dbd13eec04324e020f0000110000000000000000000b0000ec10"));
+
+ verifyPositions(decoder, false, binary(
+ "00000000000003b5080b0000015ab5642a8800d5db1769ec01d70a020a00e3040004000e0501010200030004006000060900100a00010b0000130000422f1318000302c700000000f7000000000001cb000000000000000000000000000000000000015ab5642e7000d5db178aec01d6d6020a0070040003000e0501010200030004006000060900100a00000b0000130000422f1318000302c700000000f7000000000001cb000000000000000000000000000000000000015ab567050000d5db1805ec01da3c02060101040006000e05010102000300040060000609000f0a00010b0000130000422f0c18000302c700000046f7000000000001cb000000000000000000000000000000000000015ab56708e800d5db1723ec01d9ec020600e5040006000e05010102000300040060000609000f0a00010b0000130000422f1018000502c700000003f7000000000001cb000000000000000000000000000000000000015ab5685cc000d5db20f7ec01d8fa02080033050007000e05010102000300040060000609000f0a00010b0000130000422f0a18000502c700000030f7000000000001cb000000000000000000000000000000000000015ab5693b6800d5db2367ec01d9430211011b040006000e05010102000300040060000609000f0a00010b0000130000422f0c18000302c700000027f7000000000001cb000000000000000000000000000000000000015ab569433800d5db1fb2ec01d9310211008b040006000e0501010200030004006000060900110a00000b0000130000422f1318000402c700000009f7000000000001cb000000000000000000000000000000000000015ab56a0e5800d5db22a2ec01da5502100041050007000e05010102000300040060000609000f0a00000b0000130000422f1118000602c70000000ef7000000000001cb000000000000000000000000000000000000015ab56a700000d5db2afcec01ddb2020a0012050008000e05010102000300040060000609000e0a00000b0000130000422f0918000502c700000026f7000000000001cb000000000000000000000000000000000000015ab56a73e800d5db2ad8ec01de65020a014e050008000e05010102000300040060000609000f0a00010b0000130000422f0818000702c700000002f7000000000001cb000000000000000000000000000000000000015ab56a7bb800d5db2971ec01e00e020a013f040008000e0501010200030004006000060900100a00020b0000130000422f0b18000802c700000004f7000000000001cb000000000000000000000000000000000b00007c5f"));
+
+ }
+
+
+ @Test
+ public void testDecodePhoto() throws Exception {
+
+ TeltonikaProtocolDecoder decoder = new TeltonikaProtocolDecoder(null, false);
+
+ verifyNull(decoder, binary(
+ "000F313233343536373839303132333435"));
+
+ verifyNull(decoder, binary(
+ "00000000000000090c010D00000001000100000CD8"));
+
+ verifyNull(decoder, binary(
+ "000000000000000D0c010D0000000501598493ED01000018B2"));
+
+ verifyNull(decoder, binary(
+ "00000000000008130c010d0000080b02598493ED000000000800ffd8ffe000104a46494600010201006000600000ffdb0084000202020202020202020202020202020403020202020504040304060506060605060606070908060709070606080b08090a0a0a0a0a06080b0c0b0a0c090a0a0a01020202020202050303050a0706070a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0affc401a20000010501010101010100000000000000000102030405060708090a0b0100030101010101010101010000000000000102030405060708090a0b100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa1100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffc000110801e002d003012200021101031101ffdd00040054ffda000c03010002110311003f00fc918d555b0c0007a8cd4e3054a8c807a64540a32d900f07e626ac2fce0f4014718ae652ba68e87ef222238da4f20f415226d00823a838045210149cf24fbd30305c31391cf18a52574269ad2c49b9be518c60d4dbb0194003232323b542092509e840c0a9304120e4827068924e5a8db761a0971b402011c1229ea02608f5ebeb4a09fba00001eb520552a001c83d09a1493d1149a48455009dc4020f029f210a98079a52a32a091b8f24d23042c41c93fc38a517a89b6f61b19dc371c923a1a9631f2b8639c1e326a280124ae0804fe55232153819c93924d17698452488c079380792dc1c5491a80e10825327f3a7b60052a36e4f069e9d77b1c053d4d24d3634aeee3769f31890060f03da9f364c6029cee5e09a7125db790013d69a49200000eb4ecbd0a5749d86a10ab1a827716c64d3d57639181ce4e29c880216246e43c12296360e0c8c4865e9c76a7169bb762534da18b1b3fdfc003a0a951004236e5b77ca49a8959c48a013f33723daa74604c84f0a0e011d8d36d27a83936c67987718c819cf20fa54ae018f6648048c0c74a810b1901009603a9ed53005958900943920f7a9d131deeb41854064519c01c934e000914124865e49a7901ca903af63da918a96418c91c311495a49836e438f240ebb4fcbf4a7a16219828000232691f3953c023a01446e49008da83ef0f5a6acb71249a41b4642331e0f5a7b8023193f311c81e94e5da496750016ea476a64b2050495279f9463b51aa2ac86a200c1412081c9a9810d2384206178c1a8d010a1ca92d8fc853e37551900167079a4db6ef70bc799362f963682c3073dfbd2e49508848e7e6a79264894e3033900543138569093b8b82001d8d5dd2d985d262801880bcaaf1c1ef52b92c91c600c27041f4a6292acaa9c0c724fad293f3161938eb93509b6f713695d844586e00e060e38a72260b9e8aab9247a546a30c40242b8e07a54b9fbca092ae3814ee9ec4ab45a60c140c81b8b918149b0b2ba3120eee707a5354b052554e54f04f6a7a9561b413bcb0249345d25a17a5ee3c81e5a804860723029502bec2fdb8201ea69db39c90403f74fb5359580057ef6780294527aafe98ad1487ae017278dab900d47390c8072188f978ef52e0b48c41fbc3048a6381bd41390a791449a6c4af263f0ab124472485cb0f53532c8137a6727193c77a81582caace7200e38a7be7cc9b6a819192cc78a77567b84795a240ac0463000232e734b127254fde4078a7021d22232d82371f4a69251caa900b3e4367b526928bbf512516eec91103204271d720fd6a605427cbc04e066aaa615d482483d81ef53306024503049c939e94dd96a55d5c6c6518b316e431c71d6a78c99033138c1f947ad5451f3aae7193f301eb5ad02a44c430071cb023a524d3d413e87b0e829245f0f3c73242e229e4f095e209ca062a1e278fa3023a39edeb5f13ce144ae01dc3770718afb5bc3e88fe0bf1c1b8252de4f09de9322a92630b113b801d4fe07815f155cb0695982ed19e00aceed55934fa47ff6ef989abc48c0cf23800f5cd3d4f24e38238a8949c00304e79a901e7a678a1b5ad898b492255c024824e48e2a55272307041a8548c01d077352a9c923ae2a559bd4a6d264c0e060f04f7a9800001ebd6a01b7007383d2a75008039a4d3be80f995c82f0916f290707674f5aa5e1c19b9949e3e4e3f3ab97b9fb34a31c05e9557c3a019a50724003b576615e8ccab5940ee62c123af5e302aeaf0463a8355225276e3a0ee2ad82474e83b115d8d7bda9cea4921aec76b678c83d6a9d9f319c1c658f22adc9cab6464e0e00aab60018723b93835c59838ac3dcebc124f106cdaa8dcbcf39afa13e0fc65b5e848c83b3e519ef91fe35f3f5a801973d8f15f48fc148fcdf10da2f003ca8a491dcbafaf7e2be2f3549e1a4bb9f474928c6ecfdd5d1a309a7d928fe1b68c0c7fbb5d1c28db01c77ac7d3d156de054185f2d76fd315d25a85d801e7938cd7d2609bf6d7f53e66ac7f77a010000b7cd"));
+
+ }
+
+ @Ignore
+ @Test
+ public void testDecodeConnectionless() throws Exception {
+
+ TeltonikaProtocolDecoder decoder = new TeltonikaProtocolDecoder(null, true);
+
+ verifyPositions(decoder, false, binary(
+ "0049cafe0122000f33353734353430373237313339373508010000015d3766f6a800003eef961ec6215e0063006d09003100070401000200f001c8000242381c18003201c7000000e10001"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TeltonikaProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/TeltonikaProtocolEncoderTest.java
new file mode 100644
index 000000000..83ea961b4
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TeltonikaProtocolEncoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class TeltonikaProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ TeltonikaProtocolEncoder encoder = new TeltonikaProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "setdigout 11");
+
+ verifyCommand(encoder, command, binary("00000000000000160C01050000000E7365746469676F75742031310D0A010000E258"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/ThinkRaceProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/ThinkRaceProtocolDecoderTest.java
new file mode 100644
index 000000000..a30d17502
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/ThinkRaceProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class ThinkRaceProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ ThinkRaceProtocolDecoder decoder = new ThinkRaceProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "48415349483031343730303134382C8000100134363030303134363139363239343806FF"));
+
+ verifyPosition(decoder, binary(
+ "48415349483031343730303134382C90001755701674D70155466406CBB813003D24A410F5000000770B4C"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Tk102ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Tk102ProtocolDecoderTest.java
new file mode 100644
index 000000000..f1ba7c593
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Tk102ProtocolDecoderTest.java
@@ -0,0 +1,51 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Tk102ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Tk102ProtocolDecoder decoder = new Tk102ProtocolDecoder(null);
+
+ verifyNull(decoder, buffer(
+ "[\u00800000000000\u000821315452]"));
+
+ verifyNull(decoder, buffer(
+ "[\u00f00000000000\u000821315452]"));
+
+ verifyPosition(decoder, buffer(
+ "[\u00900100100001\u0036(ONE025857A2232.0729N11356.0030E000.02109110100000000)]"));
+
+ verifyPosition(decoder, buffer(
+ "[\u00900100100001\u0036(ITV025857A2232.0729N11356.0030E000.02109110100000000)]"));
+
+ verifyNull(decoder, buffer(
+ "[\u00210000000081\u0072(353327023367238,TK102-W998_01_V1.1.001_130219,255,001,255,001,0,100,100,0,internet,0000,0000,0,0,255,0,4,1,11,00)]"));
+
+ verifyNull(decoder, buffer(
+ "[\u004c0000001323\u004e(GSM,0,0,07410001,20120101162600,404,010,9261,130,0,2353,130,35,9263,130,33,1)]"));
+
+ verifyNull(decoder, buffer(
+ "[\u00250000000082\u001d(100100000000000600-30-65535)]"));
+
+ verifyNull(decoder, buffer(
+ "[\u00230000000004\u0018(062100000000000600-0-0)]"));
+
+ verifyPosition(decoder, buffer(
+ "[\u003d0000000083\u0036(ITV013939A4913.8317N02824.9241E000.90018031310010000)]"));
+
+ verifyPosition(decoder, buffer(
+ "[\u003d0000000036\u0036(ITV012209A4913.8281N02824.9258E000.32018031310010000)]"));
+
+ verifyPosition(decoder, buffer(
+ "[\u003b0000000010\u0036(ONE200834A5952.8114N01046.0832E003.93212071305010000)]"));
+
+ verifyPosition(decoder, buffer(
+ "[\u00930000000000\u0046(ITV153047A1534.0805N03233.0888E000.00029041500000400&Wsz-wl001&B0000)]"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Tk103FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Tk103FrameDecoderTest.java
new file mode 100644
index 000000000..1f42e588f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Tk103FrameDecoderTest.java
@@ -0,0 +1,44 @@
+package org.traccar.protocol;
+
+import io.netty.buffer.ByteBuf;
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Tk103FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Tk103FrameDecoder decoder = new Tk103FrameDecoder();
+
+ verifyFrame(
+ binary("283836343735353535353535353535352C445733422C3133313131372C412C353536322E30323837304E2C30313334382E3038313934452C312E3539372C3232333730372C3239312E36352C2D302E31302C3429"),
+ decoder.decode(null, null, binary("283836343735353535353535353535352C445733422C3133313131372C412C353536322E30323837304E2C30313334382E3038313934452C312E3539372C3232333730372C3239312E36352C2D302E31302C3429283836343735353535353535353535352C5A4332302C3133313131372C3232333730362C362C3339342C36353533352C32353529")));
+
+ ByteBuf buf = binary("283836343535353535353535353535352C445735422C3231302C362C353939352C34373730312C352C33303A45453A43433A45373A38363A44442A2D35392A31312C34433A36303A43433A45413A42423A45452A2D36382A312C34323A41413A44453A45413A42423A30302A2D36392A312C33323A43443A42423A43333A34463A43432A2D38362A332C31303A30303A34333A42413A32323A31352A2D38382A312C3135313131372C31363337323229283836343735353535353535353535352C5A4332302C3133313131372C3232333730362C362C3339342C36353533352C32353529");
+
+ verifyFrame(
+ binary("283836343535353535353535353535352C445735422C3231302C362C353939352C34373730312C352C33303A45453A43433A45373A38363A44442A2D35392A31312C34433A36303A43433A45413A42423A45452A2D36382A312C34323A41413A44453A45413A42423A30302A2D36392A312C33323A43443A42423A43333A34463A43432A2D38362A332C31303A30303A34333A42413A32323A31352A2D38382A312C3135313131372C31363337323229"),
+ decoder.decode(null, null, buf));
+
+ verifyFrame(
+ binary("283836343735353535353535353535352C5A4332302C3133313131372C3232333730362C362C3339342C36353533352C32353529"),
+ decoder.decode(null, null, buf));
+
+ verifyFrame(
+ binary("283836343735353535353535353535352C445733422C3133313131372C412C353536322E30323837304E2C30313334382E3038313934452C312E3539372C3232333730372C3239312E36352C2D302E31302C3429"),
+ decoder.decode(null, null, binary("676172626167652540232A5E242D2B3C3E3F2429292924242D2D283836343735353535353535353535352C445733422C3133313131372C412C353536322E30323837304E2C30313334382E3038313934452C312E3539372C3232333730372C3239312E36352C2D302E31302C3429283836343735353535353535353535352C5A4332302C3133313131372C3232333730362C362C3339342C36353533352C32353529")));
+
+ verifyNull(decoder.decode(null, null, binary("67")));
+
+ verifyNull(decoder.decode(null, null, binary("676172626167652540232a5e242d2b3c3e3f24")));
+
+ verifyFrame(
+ binary("2838363437353535353535352C5A4330332C3139313131372C3233343432312C24294E6F746963653A0D0A446576696365732073657269616C206E756D6265723A200D0A3538303535353535353535292E0D0A536F6674776172652076657273696F6E3A0D0A56322E3030302C323031362F30382F32332031313A3137292429"),
+ decoder.decode(null, null, binary("610D0A676172626167652540232A5E242D2B3C3E3F2429292924242D2D2838363437353535353535352C5A4330332C3139313131372C3233343432312C24294E6F746963653A0D0A446576696365732073657269616C206E756D6265723A200D0A3538303535353535353535292E0D0A536F6674776172652076657273696F6E3A0D0A56322E3030302C323031362F30382F32332031313A3137292429283836343735353535353535353535352C5A4332302C3133313131372C3232333730362C362C3339342C36353533352C32353529")));
+
+ verifyNull(decoder.decode(null, null, binary("610D0A676172626167652540232A5E242D2B3C3E3F2429292924242D2D2838363437353535353535352C5A4330332C3139313131372C3233343432312C24294E6F746963653A0D0A446576696365732073657269616C206E756D6265723A200D0A3538303535353535353535292E0D0A536F6674776172652076657273696F6E3A0D0A56322E3030302C323031362F30382F32332031313A31372929283836343735353535353535353535352C5A4332302C3133313131372C3232333730362C362C3339342C36353533352C32353529")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Tk103ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Tk103ProtocolDecoderTest.java
new file mode 100644
index 000000000..db636893b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Tk103ProtocolDecoderTest.java
@@ -0,0 +1,202 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+public class Tk103ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Tk103ProtocolDecoder decoder = new Tk103ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "(094625928000BR00190213A1156.0431S07705.6145W000.000023521.40000000007L00000314T113)"));
+
+ verifyPosition(decoder, text(
+ "(019358704260BR00180725A2300.0957N07235.2748E032.412092187.58001100166L000D9779)"));
+
+ verifyPosition(decoder, text(
+ "(358511020000026,DW5B,310,6,29876,30393,0,041217,102211)"));
+
+ verifyPosition(decoder, text(
+ "(007611121184BR00170816A2401.5217N07447.0788E000.0221352232.340000004FL0030F14F)"));
+
+ verifyNull(decoder, text(
+ "(027044702512BP00027044702512HSO01A4)"));
+
+ verifyPosition(decoder, text(
+ "(864768011069660,ZC11,250517,V,0000.0000N,00000.0000E,000.0,114725,000.0,0.00,11)"));
+
+ verifyPosition(decoder, text(
+ "(864768011069660,ZC17,250517,A,3211.7118N,03452.8086E,0.68,115525,208.19,64.50,9)"));
+
+ verifyNull(decoder, text(
+ "(357593060760397BP02,G,2,170304A6015.7466N01101.8460E001.609445591.048,7)"));
+
+ verifyPosition(decoder, text(
+ "(325031693849BR00170228A5750.8012N02700.7476E000.2154529000.0000000200L00000000,170228,194530)"));
+
+ verifyAttribute(decoder, text(
+ "(087073803649BR00170221A6142.0334N02712.2197E000.3203149000.00,00000000L00000000)"),
+ Position.KEY_FUEL_LEVEL, 0);
+
+ verifyPosition(decoder, text(
+ "(864768010869060,DW30,050117,A,5135.82713N,00001.17918E,0.089,154745,000.0,43.40,12)"));
+
+ verifyNotNull(decoder, text(
+ "(087073104337BZ00,740,000,3bf7,0425,3bf7,0bf5,3bf7,09e7,3bf7,cbad,3bf7,0dcf,3bf7,c7b2,01000000)"));
+
+ verifyNull(decoder, text(
+ "(087073005534BP00HSO)"));
+
+ verifyNull(decoder, text(
+ "(027028258309BQ86,0,05550c21b10d1d0f431008bd114c0ea5078400010007a100423932,161117005322,01000001)"));
+
+ verifyNull(decoder, text(
+ "(027028258309BQ86,0,05470c0eb20d040f4410022911360e92077e00010007a1004237c7,161117005232,01000001)"));
+
+ verifyPosition(decoder, text(
+ "(01602009983BR00160830V1855.7022S4817.8731W000.0002729000.0010000000L00000000)"));
+
+ verifyPosition(decoder, text(
+ "(088046338039BR00160727A3354.7768N03540.7258E000.0140832068.4700000000L00BEB0D4+017.7)"));
+
+ verifyPosition(decoder, text(
+ "(088046338039BP05000088046338039160727A3354.7768N03540.7258E000.0140309065.1000000000L00BEB0D4+017.3)"));
+
+ verifyAttributes(decoder, text(
+ "(013632651491,ZC20,180716,144222,6,392,65535,255)"));
+
+ verifyAttributes(decoder, text(
+ "(087072009461BR00000007V0000.0000N00000.0000E000.00014039900000000L00000000)"));
+
+ verifyPosition(decoder, text(
+ "(013612345678BO012061830A2934.0133N10627.2544E040.0080331309.6200000000L000770AD)"));
+
+ verifyNotNull(decoder, text(
+ "(088047194605BZ00,510,010,36e6,932c,43,36e6,766b,36,36e6,7668,32)"));
+
+ verifyAttributes(decoder, text(
+ "(013632651491,ZC20,040613,040137,6,421,112,0)"));
+
+ verifyAttributes(decoder, text(
+ "(864768010159785,ZC20,291015,030413,3,362,65535,255)"));
+
+ verifyPosition(decoder, text(
+ "(088047365460BR00151024A2555.3531S02855.3329E004.7055148276.1701000000L00009AA3)"),
+ position("2015-10-24 05:51:48.000", true, -25.92255, 28.92222));
+
+ verifyPosition(decoder, text(
+ "(088047365460BP05354188047365460150929A3258.1754S02755.4323E009.4193927301.9000000000L00000000)"));
+
+ verifyPosition(decoder, text(
+ "(088048003342BP05354188048003342150917A1352.9801N10030.9050E000.0103115265.5600010000L000003F9)"));
+
+ verifyPosition(decoder, text(
+ "(088048003342BR00150917A1352.9801N10030.9050E000.0103224000.0000010000L000003F9)"));
+
+ verifyPosition(decoder, text(
+ "(088048003342BR00150807A1352.9871N10030.9084E000.0110718000.0001010000L00000000)"));
+
+ verifyNull(decoder, text(
+ "(090411121854BP0000001234567890HSO)"));
+
+ verifyPosition(decoder, text(
+ "(01029131573BR00150428A3801.6382N02351.0159E000.0080729278.7800000000LEF9ECB9C)"));
+
+ verifyPosition(decoder, text(
+ "(035988863964BP05000035988863964110524A4241.7977N02318.7561E000.0123536356.5100000000L000946BB)"));
+
+ verifyPosition(decoder, text(
+ "(013632782450BP05000013632782450120803V0000.0000N00000.0000E000.0174654000.0000000000L00000000)"));
+
+ verifyPosition(decoder, text(
+ "(013666666666BP05000013666666666110925A1234.5678N01234.5678W000.002033490.00000000000L000024DE)"));
+
+ verifyPosition(decoder, text(
+ "(013666666666BO012110925A1234.5678N01234.5678W000.0025948118.7200000000L000024DE)"));
+
+ verifyPosition(decoder, text(
+ "(088045133878BR00130228A5124.5526N00117.7152W000.0233614352.2200000000L01B0CF1C)"));
+
+ verifyPosition(decoder, text(
+ "(008600410203BP05000008600410203130721A4152.5790N01239.2770E000.0145238173.870100000AL0000000)"));
+
+ verifyPosition(decoder, text(
+ "(013012345678BR00130515A4843.9703N01907.6211E000.019232800000000000000L00009239)"));
+
+ verifyPosition(decoder, text(
+ "(012345678901BP05000012345678901130520A3439.9629S05826.3504W000.1175622323.8700000000L000450AC)"));
+
+ verifyPosition(decoder, text(
+ "(012345678901BR00130520A3439.9629S05826.3504W000.1175622323.8700000000L000450AC)"));
+
+ verifyPosition(decoder, text(
+ "(352606090042050,BP05,240414,V,0000.0000N,00000.0000E,000.0,193133,000.0)"));
+
+ verifyPosition(decoder, text(
+ "(352606090042050,BP05,240414,A,4527.3513N,00909.9758E,4.80,112825,155.49)"),
+ position("2014-04-24 11:28:25.000", true, 45.45586, 9.16626));
+
+ verifyPosition(decoder, text(
+ "(013632782450,BP05,101201,A,2234.0297N,11405.9101E,000.0,040137,178.48,00000000,L00000000)"));
+
+ verifyPosition(decoder, text(
+ "(864768010009188,BP05,271114,V,4012.19376N,00824.05638E,000.0,154436,000.0)"));
+
+ verifyPosition(decoder, text(
+ "(013632651491,BP05,040613,A,2234.0297N,11405.9101E,000.0,040137,178.48)"));
+
+ verifyPosition(decoder, text(
+ "(013632651491,ZC07,040613,A,2234.0297N,11405.9101E,000.0,040137,178.48)"));
+
+ verifyPosition(decoder, text(
+ "(013632651491,ZC11,040613,A,2234.0297N,11405.9101E,000.0,040137,178.48)"));
+
+ verifyPosition(decoder, text(
+ "(013632651491,ZC12,040613,A,2234.0297N,11405.9101E,000.0,040137,178.48)"));
+
+ verifyPosition(decoder, text(
+ "(013632651491,ZC13,040613,A,2234.0297N,11405.9101E,000.0,040137,178.48)"));
+
+ verifyPosition(decoder, text(
+ "(013632651491,ZC17,040613,A,2234.0297N,11405.9101E,000.0,040137,178.48)"));
+
+ verifyPosition(decoder, text(
+ "(094050000111BP05000094050000111150808A3804.2418N04616.7468E000.0201447133.3501000011L0028019DT000)"));
+
+ verifyPosition(decoder, text(
+ "(864555555555555,DW3B,131117,A,5544.02870N,01315.08194E,1.597,223707,291.65,-0.10,4)"));
+
+ verifyPosition(decoder, text(
+ "(864555555555555,DW3B,131117,A,5544.02870N,01315.08194E,1.597,223707,291.65,0.10,8)"));
+
+ verifyPosition(decoder, text(
+ "(013632651491,ZC07,040613,A,2234.0297N,11405.9101E,000.0,040137,178.48)"));
+
+ verifyAttributes(decoder, text(
+ "(013632651491,ZC20,040613,040137,6,42,112,0)"));
+
+ verifyNotNull(decoder, text(
+ "(864555555555555,DW51,200,1,3215,43370,2,58:F3:BB:3B:AA:82*-65*1,1C:6A:BB:AA:81:95*-78*1,151117,154419)"));
+
+ verifyNotNull(decoder, text(
+ "(864555555555555,DW5B,210,6,5995,47701,5,30:EE:CC:E7:86:DD*-59*11,4C:60:CC:EA:BB:EE*-68*1,42:AA:DE:EA:BB:00*-69*1,32:CD:BB:C3:4F:CC*-86*3,10:00:43:BA:22:15*-88*1,151117,163722)"));
+
+ verifyNotNull(decoder, text(
+ "(013632651491,DW50,460,0,0,6,2,aa:bb:cc:dd:ee:ff*-8*0,aa:bb:cc:dd:ee:ff*-8*0,040613,040137)"));
+
+ verifyNotNull(decoder, text(
+ "(013632651491,DW50,460,0,0,6,0,040613,040137)"));
+
+ verifyNotNull(decoder, text(
+ "(864555555555555,ZC03,191117,234207,$Notice: Device version: 1.0$)"));
+
+ verifyNotNull(decoder, text(
+ "(864555555555555,ZC03,191117,234207,$1 .Sensor sensitivity: 1\r\n2 .Alert status: Off\r\n3 .Check interval is set to 240 minute(s).\r\n4 .Checkgsm interval is set to 60 minute(s).\r\n5 .SOS SMS Alert: On\r\n6 .SOS Call Alert: On\r\n7 . Power: 95%$)"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Tk103ProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/Tk103ProtocolEncoderTest.java
new file mode 100644
index 000000000..34b2acf86
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Tk103ProtocolEncoderTest.java
@@ -0,0 +1,282 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class Tk103ProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncodeOutputControl() {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_OUTPUT_CONTROL);
+ command.set(Command.KEY_DATA, "1");
+
+ assertEquals("(123456789012345AV001)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeEngineStop() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ENGINE_STOP);
+
+ assertEquals("(123456789012345AV010)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodePositionSingle() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_SINGLE);
+
+ assertEquals("(123456789012345AP00)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodePositionPeriodic() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_PERIODIC);
+ command.set(Command.KEY_FREQUENCY, 60);
+
+ assertEquals("(123456789012345AR00003C0000)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodePositionStop() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_STOP);
+
+ assertEquals("(123456789012345AR0000000000)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeGetVersion() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_GET_VERSION);
+
+ assertEquals("(123456789012345AP07)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeRebootDevice() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_REBOOT_DEVICE);
+
+ assertEquals("(123456789012345AT00)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeSetOdometer() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SET_ODOMETER);
+
+ assertEquals("(123456789012345AX01)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodePositionSingleAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_SINGLE);
+
+ assertEquals("[begin]sms2,*getposl*,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodePositionPeriodicAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_PERIODIC);
+
+ assertEquals("[begin]sms2,*routetrack*99*,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodePositionStopAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_STOP);
+
+ assertEquals("[begin]sms2,*routetrackoff*,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeGetVersionAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_GET_VERSION);
+
+ assertEquals("[begin]sms2,*about*,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeRebootDeviceAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_REBOOT_DEVICE);
+
+ assertEquals("[begin]sms2,88888888,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeIdentificationAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_IDENTIFICATION);
+
+ assertEquals("[begin]sms2,999999,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeSosOnAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ALARM_SOS);
+ command.set(Command.KEY_ENABLE, true);
+
+ assertEquals("[begin]sms2,*soson*,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeSosOffAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_ALARM_SOS);
+ command.set(Command.KEY_ENABLE, false);
+
+ assertEquals("[begin]sms2,*sosoff*,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeCustom() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "AA00");
+
+ assertEquals("(123456789012345AA00)", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeCustomAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "any text is ok");
+
+ assertEquals("[begin]sms2,any text is ok,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeSetConnectionAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SET_CONNECTION);
+ command.set(Command.KEY_SERVER, "1.2.3.4");
+ command.set(Command.KEY_PORT, "5555");
+
+ assertEquals("[begin]sms2,*setip*1*2*3*4*5555*,[end]", encoder.encodeCommand(command));
+
+ }
+
+ @Test
+ public void testEncodeSosNumberAlternative() throws Exception {
+
+ Tk103ProtocolEncoder encoder = new Tk103ProtocolEncoder(true);
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SOS_NUMBER);
+ command.set(Command.KEY_INDEX, "0");
+ command.set(Command.KEY_PHONE, "+55555555555");
+ command.set(Command.KEY_DEVICE_PASSWORD, "232323");
+
+ assertEquals("[begin]sms2,*master*232323*+55555555555*,[end]", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Tlt2hProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Tlt2hProtocolDecoderTest.java
new file mode 100644
index 000000000..83caae208
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Tlt2hProtocolDecoderTest.java
@@ -0,0 +1,64 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Tlt2hProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Tlt2hProtocolDecoder decoder = new Tlt2hProtocolDecoder(null);
+
+ verifyPositions(decoder, text(
+ "#867962040161955#MT600#0000#0#0#137#41#0#AUTO#1\r\n" +
+ "#00019023402$GPRMC,084702.00,A,3228.6772,S,11545.9684,E,,159.80,251018,,,A*56\r\n"));
+
+ verifyPositions(decoder, text(
+ "#868323028789359#MT600#0000#AUTOLOW#1\r\n",
+ "#07d8cd5198$GPRMC,164934.00,A,1814.4854,N,09926.0566,E,0.03,,240417,,,A*4A\r\n"));
+
+ verifyNull(decoder, text(
+ "#861075026000000#\r\n",
+ "#0000#AUTO#1\r\n",
+ "#002c4968045$GPRMC,001556.00,A,3542.1569,N,13938.9814,E,7.38,185.71,160417,,,A*55\r\n"));
+
+ verifyPositions(decoder, text(
+ "#863835026938048#MT500#0000#AUTO#1\r\n",
+ "#67904917c0e$GPRMC,173926.00,A,4247.8476,N,08342.6996,W,0.03,,160417,,,A*59\r\n"));
+
+ verifyPositions(decoder, text(
+ "#357671030108689##0000#AUTO#1\r\n",
+ "#13AE2F8F$GPRMC,211452.000,A,0017.378794,S,03603.441981,E,0.000,0,060216,,,A*68\r\n"));
+
+ verifyPositions(decoder, text(
+ "#357671030946351#V500#0000#AUTO#1\r\n",
+ "#$GPRMC,223835.000,A,0615.3545,S,10708.5779,E,14.62,97.41,070313,,,D*70\r\n"),
+ position("2013-03-07 22:38:35.000", true, -6.25591, 107.14297));
+
+ verifyPositions(decoder, text(
+ "\r\n#357671030946351#V500#0000#AUTO#1\r\n",
+ "#$GPRMC,223835.000,A,0615.3545,S,10708.5779,E,14.62,97.41,070313,,,D*70\r\n"));
+
+ verifyPositions(decoder, text(
+ "#357671030938911#V500#0000#AUTOSTOP#1\r\n",
+ "#00b34d3c$GPRMC,140026.000,A,2623.6452,S,02828.8990,E,0.00,65.44,130213,,,A*4B\r\n"));
+
+ verifyPositions(decoder, text(
+ "#123456789000001#V3338#0000#SMS#3\r\n",
+ "#25ee0dff$GPRMC,083945.180,A,2233.4249,N,11406.0046,E,0.00,315.00,251207,,,A*6E\r\n",
+ "#25ee0dff$GPRMC,083950.180,A,2233.4249,N,11406.0046,E,0.00,315.00,251207,,,A*6E\r\n",
+ "#25ee0dff$GPRMC,083955.180,A,2233.4249,N,11406.0046,E,0.00,315.00,251207,,,A*6E"));
+
+ verifyPositions(decoder, text(
+ "#353686009063310#353686009063310#0000#AUTO#2\r\n",
+ "#239757a9$GPRMC,150252.001,A,2326.6856,S,4631.8154,W,,,260513,,,A*52\r\n",
+ "#239757a9$GPRMC,150322.001,A,2326.6854,S,4631.8157,W,,,260513,,,A*55"));
+
+ verifyPositions(decoder, text(
+ "#357671031289215#V600#0000#AUTOLOW#1\r\n",
+ "#00735e1c$GPRMC,115647.000,A,5553.6524,N,02632.3128,E,0.00,0.0,130614,0.0,W,A*28"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TlvProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TlvProtocolDecoderTest.java
new file mode 100644
index 000000000..0aaf567e8
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TlvProtocolDecoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TlvProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TlvProtocolDecoder decoder = new TlvProtocolDecoder(null);
+
+ verifyNull(decoder, binary(
+ "30430f383630323437303330303934333931ff10393233323132323030303834353433340f533636385f415f56312e30315f454eff1130303a30433a45373a30303a30303a30300132"));
+
+ verifyNull(decoder, binary(
+ "30410f383630323437303330303934333931"));
+
+ verifyNull(decoder, binary(
+ "30420f3836303234373033303039343339310131"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TmgFrameDecoderTest.java b/src/test/java/org/traccar/protocol/TmgFrameDecoderTest.java
new file mode 100644
index 000000000..4f7be1b28
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TmgFrameDecoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TmgFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TmgFrameDecoder decoder = new TmgFrameDecoder();
+
+ verifyFrame(
+ binary("24696f662c3836343530323033373939393630342c323238323133323031372c383132343238302c302c3239393133363231362e2d3438323235383537362ca52c313337393234353339382e3831383733343637362c142c2d36393936393937332e302c313135333435343433372e2d313938363833343039322c3439323039373739392c32302c302c2d3332302c302c4c4c4c4c2c4e4e544e2c48482c302e31372c332e30312c3330313131363030312c302c56455230302e3161"),
+ decoder.decode(null, null, binary("111538360b383634353032303337393939363034eb0b1c8d00ffff23000000000000000000000000000000001c9401008c320c00188901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000001d940100c8950100bd0024696f662c3836343530323033373939393630342c323238323133323031372c383132343238302c302c3239393133363231362e2d3438323235383537362ca52c313337393234353339382e3831383733343637362c142c2d36393936393937332e302c313135333435343433372e2d313938363833343039322c3439323039373739392c32302c302c2d3332302c302c4c4c4c4c2c4e4e544e2c48482c302e31372c332e30312c3330313131363030312c302c56455230302e31610a000195010090960100bd0024746d702c3836343530323033373939393630342c323238323133323031372c383132343238302c302c3239393133363231362e2d3438323235383537362ca52c313337393234353339382e3831383733343637362c142c2d36393936393937332e302c313135333435343433372e2d313938363833343039322c3439323039373739392c32302c302c2d3237372c302c4c4c4c4c2c4e4e544e2c48482c302e31372c332e30312c3330313131363030312c302c56455230302e31610a00c9950100289701008b002462616b2c3836343530323033373939393630342c32313131323031372c3132303230312c312c323832362e353938312c4e2c30373731382e363436352c452c3030302e302c3239382e35322c35323834372c32322c332c2d3233392c302c4c4c4c4c2c4e4e544e2c48482c302e32342c332e30332c3330313131363030312c302c56455230302e31610a00000091960100c09701008b002462616b2c3836343530323033373939393630342c32313131323031372c3132303231322c312c323832362e353938312c4e2c30373731382e363437322c452c3030302e302c3037392e34322c35323834372c32332c332c2d3230352c302c4c4c4c4c2c4e4e544e2c48482c302e31352c332e30332c3330313131363030312c302c56455230302e31610a00000029970100589801008a002462616b2c3836343530323033373939393630342c32313131323031372c3132303232322c312c323832362e353938302c4e2c30373731382e363438352c452c3030302e302c3037372e332c35323834372c32332c332c2d3137342c302c4c4c4c4c2c4e4e544e2c48482c302e31382c332e30332c3330313131363030312c302c56455230302e31610a00000000c1970100f09801008a002462616b2c3836343530323033373939393630342c32313131323031372c3132303233312c312c323832362e353936342c4e2c30373731382e363437312c452c3030302e302c3133312e352c35323834372c32322c342c2d3134362c302c4c4c4c4c2c4e4e544e2c48482c302e31392c332e30332c3330313131363030312c302c56455230302e31610a0000000059980100889901008b002462616b2c3836343530323033373939393630342c32313131323031372c3132303234332c312c323832362e353935382c4e2c30373731382e363436382c452c3030302e302c3133392e36362c35323834372c32322c342c2d3132312c302c4c4c4c4c2c4e4e544e2c48482c302e31322c332e30332c3330313131363030312c302c56455230302e31610a000000f1980100209a01008a002462616b2c3836343530323033373939393630342c32313131323031372c3132303235332c312c323832362e353934392c4e2c30373731382e363436")));
+
+ verifyFrame(
+ binary("246c6f632c3836343530323033303335323734342c32393131323031372c3038333034392c312c323533342e363733312c4e2c30383733342e363735352c452c3033382e302c3037372e31392c35343234312c362c31312c3130302c302c48484c4c2c4e4e4e4e2c48482c302e31342c332e31312c3330313131363030312c332c56455230302e3161"),
+ decoder.decode(null, null, binary("246c6f632c3836343530323033303335323734342c32393131323031372c3038333034392c312c323533342e363733312c4e2c30383733342e363735352c452c3033382e302c3037372e31392c35343234312c362c31312c3130302c302c48484c4c2c4e4e4e4e2c48482c302e31342c332e31312c3330313131363030312c332c56455230302e31610a246c6f632c3836343530323033303335323734342c32393131323031372c3038333035392c312c323533342e363634322c4e2c30383733342e373333352c452c3032392e302c3132322e37302c35343234312c362c31312c3130302c302c48484c4c2c4e4e4e4e2c48482c302e31342c332e31312c3330313131363030312c342c56455230302e31610a246c6f632c3836343530323033303335323734342c32393131323031372c3038333130392c312c323533342e363531362c4e2c30383733342e373938312c452c3034342e302c3039342e39382c36303631322c31312c31312c3130302c302c48484c4c2c4e4e4e4e2c48482c302e31372c332e31302c3330313131363030312c342c56455230302e31610a246c6f632c3836343530323033303335323734342c32393131323031372c3038333131392c312c323533342e363432312c4e2c30383733342e383639312c452c3033352e302c3130312e37332c36303631322c31322c31312c3130302c302c48484c4c2c4e4e4e4e2c48482c302e31342c332e31312c3330313131363030312c342c56455230302e31610a246c6f632c3836343530323033303335323734342c32393131323031372c3038333132392c312c323533342e363335352c4e2c30383733342e393135322c452c3032302e302c3131312e31322c36303631322c31322c31312c3130302c302c48484c4c2c4e4e4e4e2c48482c302e31362c332e31312c3330313131363030312c342c56455230302e31610a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TmgProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TmgProtocolDecoderTest.java
new file mode 100644
index 000000000..5df2378d9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TmgProtocolDecoderTest.java
@@ -0,0 +1,54 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TmgProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TmgProtocolDecoder decoder = new TmgProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$loc,869309013800417,08032014,094459,1,2826.1956,N,07659.7690,E,0.0,2.5,4441,31,6,95,1,LLLL,NNTN,HH,0.15,0.26,HR38AU1389,0,SW0.1a"));
+
+ verifyPosition(decoder, text(
+ "$bak,864502037999604,21112017,120243,1,2826.5958,N,07718.6468,E,000.0,139.66,52847,22,4,-174,0,LLLL,NNTN,HH,0.12,3.03,301116001,0,VER00.1a"));
+
+ verifyNull(decoder, text(
+ "$iof,864502037999604,2282132017,8124280,0,299136216.-482258576,¥,1379245398.818734676,,-69969973.0,1153454437.-1986834092,492097799,20,0,-320,0,LLLL,NNTN,HH,0.17,3.01,301116001,0,VER00.1a"));
+
+ verifyPosition(decoder, text(
+ "$nor,L,868325023006341,14022017,103947,1,2836.6542,N,07706.2504,E,0.0,0.0,0.0,0.0,0,22,VODAFONE - DELH,15,49B7,1,2.57,13.2,00000010,00000000,0111,00.0,00.0,0.0,SW10.12,NA,#"));
+
+ verifyPosition(decoder, text(
+ "$rid,L,868325023006341,14022017,103706,1,2836.6542,N,07706.2504,E,0.0,0.0,0.0,0.0,0,22,VODAFONE - DELH,15,49B7,1,2.57,13.2,00000011,00000000,0111,00.0,00.0,0.0,SW10.12,0004909463,#"));
+
+ verifyPosition(decoder, text(
+ "$ion,H,868324023777431,27012017,101057,4,2830.2952,N,07705.2532,E,0.0,202.38,225.9,1.22,8,20,N.A,0,N.A,1,4.09,00.0,00000111,00000000,1101,00.0-00.0,00.0-0.0,4.42,01.02,#"));
+
+ verifyPosition(decoder, text(
+ "$iof,H,868324023777431,27012017,101111,4,2830.2952,N,07705.2532,E,0.0,202.38,225.9,0.87,11,21,N.A,25,N.A,0,4.09,00.0,00000111,00000000,1110,00.0-00.0,00.0-0.0,4.42,01.02,#"));
+
+ verifyPosition(decoder, text(
+ "$rmv,L,868324023777431,27012017,101141,4,2830.2952,N,07705.2532,E,0.0,202.38,225.9,0.86,12,21,VODAFONE - DELH,24,3220,0,4.11,00.0,00000111,00000000,1110,00.0-00.0,00.0-0.0,4.42,01.02,#"));
+
+ verifyPosition(decoder, text(
+ "$rnc,H,868324023777431,27012017,101013,4,2830.2923,N,07705.2551,E,0.0,9.65,226.0,0.88,12,21,VODAFONE - DELH,28,3220,0,4.14,07.4,00000111,00000000,1111,00.0-00.0,00.0-0.0,4.42,01.02,#"));
+
+ verifyPosition(decoder, text(
+ "$ebl,H,868324023777431,27012017,101046,4,2830.2923,N,07705.2551,E,0.0,9.65,226.0,0.97,11,21,VODAFONE - DELH,25,3220,0,4.11,00.0,00000111,00000000,1110,00.0-00.0,00.0-0.0,4.42,01.02,#"));
+
+ verifyPosition(decoder, text(
+ "$nor,L,868324023777431,17012017,001023,4,2830.2977,N,07705.2478,E,0.0,207.07,229.2,0.97,11,22,IDEA CELLULAR L,18,DCDE,0,4.09,12.9,00000111,00000000,1111,00.0-00.0,00.0-0.0,3.59,01.02,#"));
+
+ verifyPosition(decoder, text(
+ "$nor,L,868324023777431,17012017,001523,4,2830.2939,N,07705.2527,E,0.0,50.96,236.5,1.05,11,21,IDEA CELLULAR L,18,DCDE,0,4.09,12.8,00000111,00000000,1111,00.0-00.0,00.0-0.0,3.59,01.02,#"));
+
+ verifyPosition(decoder, text(
+ "$nor,L,869309999985699,24062015,094459,4,2826.1956,N,07659.7690,E,67.5,2.5,167,0.82,15,22,airtel,31,4441,1,4.1,12.7,00000011,00000011,1111,0.0,0.0,21.3,SW00.01,#"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TopflytechProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TopflytechProtocolDecoderTest.java
new file mode 100644
index 000000000..666a48bfa
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TopflytechProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TopflytechProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TopflytechProtocolDecoder decoder = new TopflytechProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "(880316890094910BP00XG00b600000000L00074b54S00000000R0C0F0014000100f0130531152205A0706.1395S11024.0965E000.0251.25"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TotemFrameDecoderTest.java b/src/test/java/org/traccar/protocol/TotemFrameDecoderTest.java
new file mode 100644
index 000000000..8fb5f8d54
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TotemFrameDecoderTest.java
@@ -0,0 +1,35 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TotemFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TotemFrameDecoder decoder = new TotemFrameDecoder();
+
+ verifyFrame(
+ binary("24243030323542423836323031303033373239343836313345"),
+ decoder.decode(null, null, binary("24243030323542423836323031303033373239343836313345")));
+
+ verifyFrame(
+ binary("24243030363545363836313137323033353932363639357c3137303931323135333235372c2d37392e3337333835332c34332e3736353631392c302c302c7c3441"),
+ decoder.decode(null, null, binary("24243030363545363836313137323033353932363639357c3137303931323135333235372c2d37392e3337333835332c34332e3736353631392c302c302c7c3441")));
+
+ verifyFrame(
+ binary("24243031303841413836343234343032363036333433377c3141303030303030313430313031303130313031343131313030303032374241304535373030333130303030303030302e3030303030303030303030302e303030304e30303030302e3030303045303438313536"),
+ decoder.decode(null, null, binary("24243031303841413836343234343032363036333433377c3141303030303030313430313031303130313031343131313030303032374241304535373030333130303030303030302e3030303030303030303030302e303030304e30303030302e3030303045303438313536")));
+
+ verifyFrame(
+ binary("242442393335363839353033373537383531387c4141244750524d432c3036313730382e3030302c412c333734302e323033332c4e2c30323132382e383132312c452c33382e38352c3237322e33362c3132313131332c2c2c412a35327c30322e337c30312e337c30312e397c3030303030303030303030307c32303133313131323036313730387c31343034313430327c30303030303030307c30303245323137317c303030307c302e323137327c383930327c34463945"),
+ decoder.decode(null, null, binary("242442393335363839353033373537383531387c4141244750524d432c3036313730382e3030302c412c333734302e323033332c4e2c30323132382e383132312c452c33382e38352c3237322e33362c3132313131332c2c2c412a35327c30322e337c30312e337c30312e397c3030303030303030303030307c32303133313131323036313730387c31343034313430327c30303030303030307c30303245323137317c303030307c302e323137327c383930327c344639450d0a")));
+
+ verifyFrame(
+ binary("242442393335363839353033373537383531387c4141244750524d432c3036313730382e3030302c412c333734302e323033332c4e2c30323132382e383132312c452c33382e38352c3237322e33362c3132313131332c2c2c412a35327c30322e337c30312e337c30312e397c3030303030303030303030307c32303133313131323036313730387c31343034313430327c30303030303030307c30303245323137317c303030307c302e323137327c383930327c34463945"),
+ decoder.decode(null, null, binary("0d0a242442393335363839353033373537383531387c4141244750524d432c3036313730382e3030302c412c333734302e323033332c4e2c30323132382e383132312c452c33382e38352c3237322e33362c3132313131332c2c2c412a35327c30322e337c30312e337c30312e397c3030303030303030303030307c32303133313131323036313730387c31343034313430327c30303030303030307c30303245323137317c303030307c302e323137327c383930327c344639450d0a")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java
new file mode 100644
index 000000000..287c54968
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TotemProtocolDecoderTest.java
@@ -0,0 +1,116 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TotemProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TotemProtocolDecoder decoder = new TotemProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$$0113AA862010037348253|588040001901220851494212000000753AE901655121700100000.800000002632.6084S02803.3289E29497E"),
+ position("2019-01-22 08:51:49.000", true, -26.54347, 28.05548));
+
+ verifyPosition(decoder, text(
+ "$$011602867119025755430|50099800180420045019401400000000000000B8797D110816811201.500002132615.7037S02801.8099E056149"));
+
+ verifyPosition(decoder, text(
+ "$$0108AB863835028447675|5004C0001710250234064214059828A058AE121010604000.600000320304.7772N10134.8238E11625B"));
+
+ verifyPosition(decoder, text(
+ "$$0108AA863835028447675|5004C0001710250234134114057728A058AE112108305100.600000660304.7787N10134.8719E116458"));
+
+ verifyPosition(decoder, text(
+ "$$0112AA864244026065291|180018001409160205244011000027BA0E57063100000001.200000002237.8119N11403.5075E05202D"));
+
+ verifyPosition(decoder, text(
+ "$$0116AA864244026065291|18001800140916020524401100000000000027BA0E57063100000001.200000002237.8119N11403.5075E052020"));
+
+ verifyPosition(decoder, text(
+ "$$0116AA867119025683137|108000001611020925324112000000000000616027F7001300000099.900000000000.0000N00000.0000E531824"));
+
+ verifyPosition(decoder, text(
+ "$$0128AA864244026065291|18001800140916020524401100000000000000000000000027BA0E57063100000001.200000002237.8119N11403.5075E05202D"));
+
+ verifyPosition(decoder, text(
+ "$$0128AA867965024919124|10010800160223032415401203270321032103270189000027BA0E4E001800200001.000000002237.7581N11403.5088E000957"),
+ position("2016-02-23 03:24:15.000", false, 22.62930, 114.05848));
+
+ verifyPosition(decoder, text(
+ "$$0108AA863835024426319|18004000160216160756411100007DCD0000111000000000.800000000316.3519N10228.5086E126522"));
+
+ verifyPosition(decoder, text(
+ "$$0128AA867521029231005|1880100015101802314842140000000000000000000000001AB48366093127600000.900000000806.1947N09818.4795E080355"));
+
+ verifyPosition(decoder, text(
+ "$$0108AA864244026063437|1A0000001401010101014111000027BA0E57003100000000.000000000000.0000N00000.0000E048156"));
+
+ verifyPosition(decoder, text(
+ "$$BE863771024392112|AA$GPRMC,044704.000,A,1439.3334,N,12059.1417,E,0.00,0.00,200815,,,A*67|01.7|00.8|01.4|000000000000|20150820044704|14291265|00000000|4EECBF8B31|0000|0.0000|0002|00000|56E7"),
+ position("2015-08-20 04:47:04.000", true, 14.65556, 120.98570));
+
+ verifyPosition(decoder, text(
+ "$$AE860990002922822|AA$GPRMC,051002.00,A,0439.26245,N,10108.94448,E,0.023,,140315,,,A*71|02.98|01.95|02.26|000000000000|20150314051003|13841157|105A3B1C|0000|0.0000|0005|5324"),
+ position("2015-03-14 05:10:02.000", true, 4.65437, 101.14907));
+
+ verifyPosition(decoder, text(
+ "$$AE860990002922822|AA$GPRMC,051002.00,A,0439.26245,N,10108.94448,E,0.023,,140315,,,A*71|02.98|01.95|02.26|000000000000|20150314051003|13841157|105A3B1C|0000|0.0000|0005|5324\r"));
+
+ verifyNull(decoder, text(
+ "$$BB862170017856731|AA$GPRMC,000000.00,V,0000.0000,N,00000.0000,E,000.0,000.0,000000,,,A*73|00.0|00.0|00.0|000000001000|20000000000000|13790000|00000000|00000000|00000000|0.0000|0007|8C23"));
+
+ verifyPosition(decoder, text(
+ "$$B8862170017856731|AA$GPRMC,171849.00,A,3644.9893,N,01012.9927,E,0.049,51,200813,,,A*73|1.59|0.97|1.25|100000001000|20130820171849|13690000|00000000|019BD508|00000000|0.0000|0026|1B2C"));
+
+ verifyPosition(decoder, text(
+ "$$B2359772032984289|AA$GPRMC,104446.000,A,5011.3944,N,01439.6637,E,0.00,,290212,,,A*7D|01.8|00.9|01.5|000000100000|20120229104446|14151221|00050000|046D085E|0000|0.0000|1170|29A7"));
+
+ verifyPosition(decoder, text(
+ "$$8B862170017861566|AA180613080657|A|2237.1901|N|11402.1369|E|1.579|178|8.70|100000001000|13811|00000000|253162F5|00000000|0.0000|0014|2B16"),
+ position("2013-06-18 08:06:57.000", true, 22.61984, 114.03562));
+
+ verifyPosition(decoder, text(
+ "$$72862170017856731|3913090911165280000370000000000000000019BD508A0400000003.400000093644.9817N01012.9944E00506F2E"));
+
+ verifyPosition(decoder, text(
+ "$$B0456123|61$GPRMC,114725.00,A,1258.68276,N,07730.60237,E,0.410,,080113,,,A*79|1.44|0.66|1.27|000000000000|20130108114425|03600000|00000000|053C2BFE|0000|0.3325|0063|2005"));
+
+ verifyNull(decoder, text(
+ "$$AE359772033395899|AA000000000000000000000000000000000000000000000000000000000000|00.0|00.0|00.0|000000000000|20090215000153|13601435|00000000|00000000|0000|0.0000|0007|2DAA"));
+
+ verifyNull(decoder, text(
+ "$$AE359772033395899|AA000000000000000000000000000000000000000000000000000000000000|00.0|00.0|00.0|00000000|20090215001204|14182037|00000000|0012D888|0000|0.0000|0016|5B51"));
+
+ verifyNull(decoder, text(
+ "$$AE359772033395899|AA00000000000000000000000000000000000000000000000000000000000|00.0|00.0|00.0|00000000000|20090215001337|14182013|00000000|0012D888|0000|0.0000|0017|346E"));
+
+ verifyPosition(decoder, text(
+ "$$B3359772032399074|60$GPRMC,094859.000,A,3648.2229,N,01008.0976,E,0.00,,221211,,,A*79|02.3|01.3|02.0|000000000000|20111222094858|13360808|00000000|00000000|0000|0.0000|0001||A977"));
+
+ verifyPosition(decoder, text(
+ "$$B3359772032399074|09$GPRMC,094905.000,A,3648.2229,N,01008.0976,E,0.00,,221211,,,A*71|02.1|01.3|01.7|000000000000|20111222094905|03210533|00000000|00000000|0000|0.0000|0002||FA58"));
+
+ verifyPosition(decoder, text(
+ "$$B3359772032399074|AA$GPRMC,093911.000,A,3648.2146,N,01008.0977,E,0.00,,140312,,,A*7E|02.1|01.1|01.8|000000000000|20120314093910|04100057|00000000|0012D887|0000|0.0000|1128||C50E"));
+
+ verifyPosition(decoder, text(
+ "$$B3359772032399074|AA$GPRMC,094258.000,A,3648.2146,N,01008.0977,E,0.00,,140312,,,A*7F|02.1|01.1|01.8|000000000000|20120314094257|04120057|00000000|0012D887|0000|0.0000|1136||CA32"));
+
+ verifyPosition(decoder, text(
+ "$$B3359772032399074|AA$GPRMC,234603.000,A,3648.2179,N,01008.0962,E,0.00,,030412,,,A*74|01.8|01.0|01.5|000000000000|20120403234603|14251914|00000000|0012D888|0000|0.0000|3674||940B"));
+
+ verifyPosition(decoder, text(
+ "$$B3359772032399074|AA$GPRMC,234603.000,A,3648.2179,N,01008.0962,E,0.00,,030412,,,A*74|01.8|01.0|01.5|000000000000|20120403234603|14251914|00000000|0012D888|0000|0.0000|3674|940B"));
+
+ verifyPosition(decoder, text(
+ "$$B2356895037578518|AA$GPRMC,173829.000,A,3740.4107,N,02129.9815,E,0.00,,111113,,,A*7B|02.6|01.6|02.1|000000000000|20131111173829|14041251|00000000|002E0DD7|0000|0.0240|6010|8128"));
+
+ verifyPosition(decoder, text(
+ "$$B2356895037578518|AA$GPRMC,203823.000,A,3740.3285,N,02129.9295,E,0.00,,111113,,,A*79|01.5|01.0|01.1|000000000000|20131111203823|14041251|00000000|002E0DD7|0000|0.0000|6371|3824"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TotemProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/TotemProtocolEncoderTest.java
new file mode 100644
index 000000000..5a47f74cc
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TotemProtocolEncoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class TotemProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ TotemProtocolEncoder encoder = new TotemProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(2);
+ command.setType(Command.TYPE_ENGINE_STOP);
+ command.set(Command.KEY_DEVICE_PASSWORD, "000000");
+
+ assertEquals("*000000,025,C,1#", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Tr20ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Tr20ProtocolDecoderTest.java
new file mode 100644
index 000000000..76355066b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Tr20ProtocolDecoderTest.java
@@ -0,0 +1,31 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Tr20ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Tr20ProtocolDecoder decoder = new Tr20ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "%%123456789012345,A,120101121800,N6000.0000E13000.0000,0,000,0,01034802,150,[Message]"));
+
+ verifyNull(decoder, text(
+ "%%TRACKPRO01,1"));
+
+ verifyPosition(decoder, text(
+ "%%868873457748532,A,181109121248,N2237.4181E11403.2857,000,282,NA,47010000,108"));
+
+ verifyPosition(decoder, text(
+ "%%TR-10,A,050916070549,N2240.8887E11359.2994,0,000,NA,D3800000,150,CFG:resend|"),
+ position("2005-09-16 07:05:49.000", true, 22.68148, 113.98832));
+
+ verifyPosition(decoder, text(
+ "%%TR-10,A,050916070549,N2240.8887E11359.2994,0,000,NA,D3800000,150,CFG:resend|"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Tr900ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Tr900ProtocolDecoderTest.java
new file mode 100644
index 000000000..92fe0da29
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Tr900ProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Tr900ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Tr900ProtocolDecoder decoder = new Tr900ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ ">00001001,4,1,150626,131252,W05830.2978,S3137.2783,,00,348,18,00,003-000,0,3,11111011*3b!"),
+ position("2015-06-26 13:12:52.000", true, -31.62131, -58.50496));
+
+ verifyPosition(decoder, text(
+ ">12345678,1,1,070201,144111,W05829.2613,S3435.2313,,00,034,25,00,126-000,0,3,11111111*2d!"));
+
+ verifyPosition(decoder, text(
+ ">00001001,4,1,150626,131252,W05830.2978,S3137.2783,,00,348,18,00,003-000,0,3,11111011*3b!\r\n"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TrackboxProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TrackboxProtocolDecoderTest.java
new file mode 100644
index 000000000..e83824fb4
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TrackboxProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TrackboxProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TrackboxProtocolDecoder decoder = new TrackboxProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "a=connect&v=11&i=111111111111111"));
+
+ verifyPosition(decoder, text(
+ "183457.999,5126.0247N,00002.8686E,5.2,70.4,3,57.63,32.11,17.32,150507,05"),
+ position("2007-05-15 18:34:57.999", true, 51.43375, 0.04781));
+
+ verifyPosition(decoder, text(
+ "183558.999,5126.3979N,00003.0745E,5.2,70.4,3,57.63,32.11,17.32,150507,05"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TrakMateProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TrakMateProtocolDecoderTest.java
new file mode 100644
index 000000000..4352fc935
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TrakMateProtocolDecoderTest.java
@@ -0,0 +1,27 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TrakMateProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TrakMateProtocolDecoder decoder = new TrakMateProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "^TMSTP|352984083995323|116|13.07809|77.55979|131508|131118|0.0|146.51|7|0|71 -2 248|0|13.1|0.0|10.5|1|0|0|0|#"));
+
+ verifyPosition(decoder, text(
+ "^TMPER|354678456723764|1|12.59675|77.56789|123456|030414|2.3|34.0|1|0|0|0.015|3.9|12.0|23.4|23.4|1|1|0|#"));
+
+ verifyPosition(decoder, text(
+ "^TMALT|354678456723764|3|2|1|12.59675|77.56789|123456|030414|1.2|34.0|#"));
+
+ verifyPosition(decoder, text(
+ "^TMSRT|354678456723764|12.59675|77.56789|123456|030414|1.03|1.01|#"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TramigoFrameDecoderTest.java b/src/test/java/org/traccar/protocol/TramigoFrameDecoderTest.java
new file mode 100644
index 000000000..f482a00bb
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TramigoFrameDecoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TramigoFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TramigoFrameDecoder decoder = new TramigoFrameDecoder();
+
+ verifyFrame(
+ binary("8000ed2bb0009c000101bee000050b09633d925b5472616d69676f3a205472697020737461727465642c2053686f636b2053656e736f722c206174204b696e6720437265656b20526f61642d46726565746f776e205374726565742c20506f727420486172636f7572742c205269766572732c204e472c20342e37363336312c20372e30313836382c2030373a31383a333620536570203320454f46"),
+ decoder.decode(null, null, binary("8000ed2bb0009c000101bee000050b09633d925b5472616d69676f3a205472697020737461727465642c2053686f636b2053656e736f722c206174204b696e6720437265656b20526f61642d46726565746f776e205374726565742c20506f727420486172636f7572742c205269766572732c204e472c20342e37363336312c20372e30313836382c2030373a31383a333620536570203320454f46")));
+
+ verifyFrame(
+ binary("80003d1ac0001c00010100000367152b13bc1d5970696e6720454f46"),
+ decoder.decode(null, null, binary("80003d1ac0001c00010100000367152b13bc1d5970696e6720454f46")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TramigoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TramigoProtocolDecoderTest.java
new file mode 100644
index 000000000..d35c5c54e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TramigoProtocolDecoderTest.java
@@ -0,0 +1,63 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TramigoProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TramigoProtocolDecoder decoder = new TramigoProtocolDecoder(null);
+
+ verifyAttributes(decoder, binary(
+ "8000c426b000a6000101c557037598050d5c8a595472616d69676f3a204d6f76696e672c20302e3132206b6d2045206f66204c617275742054696e2049736c616d6963205072696d617279205363686f6f6c2c2054616970696e672c20506572616b2c204d592c20342e38333134392c203130302e37333038352c204e572077697468207370656564203130206b6d2f682c2030303a34393a30382041756720392020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000c526b000a6000101f17d03759805115c8a595472616d69676f3a204d6f76696e672c20302e3133206b6d205345206f66204c617275742054696e2049736c616d6963205072696d617279205363686f6f6c2c2054616970696e672c20506572616b2c204d592c20342e38333132322c203130302e37333037382c204e4520776974682073706565642039206b6d2f682c2030303a34383a35332041756720392020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000d426b0009f00010184f20375980593638a595472616d69676f3a204d6f76696e672c20302e3039206b6d204e57206f66204a616c616e2053696d70616e672042617475204d61726b65742c2054616970696e672c20506572616b2c204d592c20342e38333034332c203130302e37323230342c20532077697468207370656564203130206b6d2f682c2030313a32313a31322041756720392020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000d626b0007f0001013c0b037598051d648a595472616d69676f3a2053746f707065642c206174204a616c616e2053696d70616e672042617475204d61726b65742c2054616970696e672c20506572616b2c204d592c20342e38323937322c203130302e37323233322c2030313a32323a34342041756720392020454f46"));
+
+ verifyNull(decoder, binary(
+ "80003d1ac0001c00010100000367152b13bc1d5970696e6720454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000d316b000860001018f8703771bee11fdf2585472616d69676f3a205061726b65642c20302e3131206b6d2053206f6620492e452e532e2050756572746120426f6e6974612c204361726162616e6368656c2c204d61647269642c2045532c2034302e33373736362c202d332e37333833352c2030353a3131204170722031362020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "80009e08b00086000101bc1803778a59c58dea57546573742054323320547261636b65723a204d6f76696e672c20312e3639206b6d204e57206f66205574656b6f6e2c2045646f2c204e472c20362e34363137302c20352e36313938322c20452077697468207370656564203333206b6d2f682c2031363a3138205365702032372020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000853eb000b8000101fcff032f14665a89e2564176656e7369732053797353657276653a2049676e6974696f6e206f6e2064657465637465642c206d6f76696e672c20302e3135206b6d205357206f66204261626120416e696d61736861756e205374726565742d426f64652054686f6d61732053742e2c20537572756c6572652c204c61676f7320436974792c204e472c20362e34383736352c20332e33343735352c2031303a3031204d6172203131202020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000973eb000b90001012128032f14667794e2564176656e7369732053797353657276653a2049676e6974696f6e206f6e2064657465637465642c2073746f707065642c20302e3134206b6d205357206f66204261626120416e696d61736861756e205374726565742d426f64652054686f6d61732053742e2c20537572756c6572652c204c61676f7320436974792c204e472c20362e34383736372c20332e33343737332c2031303a3438204d6172203131202020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000b73eb000ad000101fdd2032f1466c9cbe2564176656e7369732053797353657276653a2049676e6974696f6e206f6e2064657465637465642c206d6f76696e672c20302e3131206b6d2045206f6620416c68616a69204d6173686120526f616420466f6f746272696467652c20537572756c6572652c204c61676f7320436974792c204e472c20362e35303031342c20332e33353434332c2031343a3434204d6172203131202020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000883eb000d3000101b223032f1466fc89e2564176656e7369732053797353657276653a2049676e6974696f6e206f66662064657465637465642c2049676e4f6e506572696f643a2030303a30323a34312c2073746f707065642c20302e3039206b6d205345206f66204a696e616475205072696d617279205363686f6f6c20416465204f6e6974696d6572696e2053742e2c20537572756c6572652c204c61676f7320436974792c204e472c20362e34383639332c20332e33343636302c2031303a3033204d6172203131202020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "80009a3eb000d300010109ff032f1466b195e2564176656e7369732053797353657276653a2049676e6974696f6e206f66662064657465637465642c2049676e4f6e506572696f643a2030303a30353a31342c2073746f707065642c20302e3039206b6d205345206f66204a696e616475205072696d617279205363686f6f6c20416465204f6e6974696d6572696e2053742e2c20537572756c6572652c204c61676f7320436974792c204e472c20362e34383639312c20332e33343636322c2031303a3533204d6172203131202020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000bc3eb000ba000101622c032f1466bacce2564176656e7369732053797353657276653a2049676e6974696f6e206f66662064657465637465642c2049676e4f6e506572696f643a2030303a30343a30302c206d6f76696e672c20617420416b6572656c6520526f61642d4f67756e6c616e612044726976652c20537572756c6572652c204c61676f7320436974792c204e472c20362e35303630332c20332e33353232382c2031343a3438204d6172203131202020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "80001d3cb000b3000101160f032f1466b475e0564176656e7369732053797353657276653a205374617475732c204750533a203931252c2047534d3a203737252c20475052533a20436f6e6e65637465642c20626174746572793a20313030252c207265706f7274733a2049676e6974696f6e20286f6666292c205374617475732028352c322e302c3732302c3330292c20362e34393239382c20332e33343836352c2031393a3038204d6172203920454f46"));
+
+ verifyAttributes(decoder, binary(
+ "80005408b000af000101b23903677f00c8436d3842616c697365204f6e653a20416c6c756d616765206d61726368652064e974656374e92c20676172e92c20302e3735206b6d20452064652045636f6c65204175746f726f757465206465204b696e73686173612c2056696c6c65206465204b696e73686173612c204b696e73686173612c2043442c202d342e33343130362c2031352e33343931352c2030313a3030204a616e2031202020454f46"));
+
+ verifyAttributes(decoder, binary(
+ "8000011bb0009e0001015b93032ef6f35994a9545472616d69676f3a204d6f76696e672c20302e3930206b6d205345206f66204372616e6562726f6f6b20466972652053746174696f6e2c2050656e726974682c205379646e65792c2041552c202d33332e37303732322c203135302e37313735392c2053452077697468207370656564203337206b6d2f682c2031393a3438204a616e20342020454f46"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TrvProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TrvProtocolDecoderTest.java
new file mode 100644
index 000000000..2fdb86218
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TrvProtocolDecoderTest.java
@@ -0,0 +1,67 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TrvProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TrvProtocolDecoder decoder = new TrvProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "TRVAP00352121088015548"));
+
+ verifyNotNull(decoder, text(
+ "IWAP02,zh_cn,0,6,260,1,11002|39252|9,11002|35112|23,11002|11043|24,11002|39253|24,11002|13751|24,11018|8102|26,3,a|c0-4a-00-b6-9c-f5|64&a|c0-4a-00-b6-9c-f5|64&a|18-a6-f7-92-35-da|84"));
+
+ verifyPosition(decoder, text(
+ "TRVAP01170905A5227.1382N00541.4256E001.7095844000.0008100610020100,204,8,3230,13007"));
+
+ verifyAttributes(decoder, text(
+ "TRVCP01,07800010010000602001206001120124"));
+
+ verifyNull(decoder, text(
+ "IWAP00353456789012345"));
+
+ verifyPosition(decoder, text(
+ "IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97& Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97& Home3|74-DE-2B-44-88-8C|97"));
+
+ verifyNotNull(decoder, text(
+ "IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7,4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65"));
+
+ verifyPosition(decoder, text(
+ "IWAP10080524A2232.9806N11404.9355E000.1061830323.8706000908000502,460,0,9520,3671,00,zh-cn,00,HOME|74-DE-2B-44-88-8C|97&HOME1|74-DE-2B-44-88-8C|97&HOME2|74-DE-2B-44-88-8C|97&HOME3|74-DE-2B-44-88-8C|97"));
+
+ verifyNull(decoder, text(
+ "IWAP03,06000908000102,5555,30"));
+
+ verifyNull(decoder, text(
+ "TRVAP00353456789012345"));
+
+ verifyAttributes(decoder, text(
+ "TRVCP01,06000908000102"));
+
+ verifyAttributes(decoder, text(
+ "TRVCP01,100007100000001020151060011"));
+
+ verifyPosition(decoder, text(
+ "TRVAP01160211A2544.5118N05553.7586E105.711185941.52010001010010000,424,030,3011,27003"));
+
+ verifyPosition(decoder, text(
+ "TRVAP01160209A2540.8863N05546.6125E005.6075734123.7910000810010000,424,030,3012,27323"));
+
+ verifyPosition(decoder, text(
+ "TRVAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671"));
+
+ verifyPosition(decoder, text(
+ "TRVAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671"),
+ position("2008-05-24 06:18:30.000", true, 22.54968, 114.08226));
+
+ verifyPosition(decoder, text(
+ "TRVAP10080524A2232.9806N11404.9355E000.1061830323.8706000908000502,460,0,9520,3671,00,zh-cn,00"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Tt8850ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Tt8850ProtocolDecoderTest.java
new file mode 100644
index 000000000..e3833bcc7
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Tt8850ProtocolDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Tt8850ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Tt8850ProtocolDecoder decoder = new Tt8850ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "\u0000\u0004,007F,0,GTFRI,020102,867844000667538,4142726856,0,0,1,3,1.6,0,997.3,-66.830786,10.483394,20171212171418,0734,0004,041A,4220,69,20171212171657,FF61"));
+
+ verifyPosition(decoder, text(
+ "\u0000\u0004,005F,0,GTFRI,020100,135790246811220,,0,0,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,90,20090214093254,11F0"));
+
+ verifyPosition(decoder, text(
+ "\u0000\u0004,005F,0,GTGEO,020100,135790246811220,,0,0,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,90,20090214093254,11F0"));
+
+ verifyPosition(decoder, text(
+ "\u0000\u0004,005F,0,GTNMR,020100,135790246811220,,0,0,1,1,4.3,92,70.0,121.354335,31.222073,20090214013254,0460,0000,18d8,6141,90,20090214093254,11F0"));
+
+ verifyPosition(decoder, text(
+ "\u0000\u0004,0017,0,GTNMR,,867844000400914,,0,41,1,2,0.0,0,1504.2,-75.569202,6.242850,20150404162835,,,,,97,20150404162836,05EF"));
+
+ verifyNull(decoder, text(
+ "\u0000\u0004,0017,0,GTPNA,,867844000400914,,0,0,1,0,,,,0,0,,,,,,99,20150404190153,0601"));
+
+ verifyPosition(decoder, text(
+ "\u0000\u0004,0017,0,GTEPN,,867844000400914,,0,0,1,0,0.0,0,1717.4,-75.598445,6.278578,20150405003116,,,,,95,20150405003358,0607"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TytanProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TytanProtocolDecoderTest.java
new file mode 100644
index 000000000..ed75cee38
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TytanProtocolDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TytanProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TytanProtocolDecoder decoder = new TytanProtocolDecoder(null);
+
+ verifyPositions(decoder, binary(
+ "B500192000001405125652CA9B1A325FC98D11A9990018020118FC0D"));
+
+ verifyPositions(decoder, binary(
+ "B500197800007422125652D7AC32325FD08D11A69900180200188280"));
+
+ verifyPositions(decoder, binary(
+ "B500181000001405115652DEEB2A325FC68D11A7D00005012A2AE1"));
+
+ verifyPositions(decoder, binary(
+ "B5005690000068494F561CEAE932325FD28D11A299000702000063045532030066013567018768014B6901286B0240396C04030785986D013E7F040000A7CE81040000A76C82027EAB83080FA01068FFFF0F3C880202583156"));
+
+ verifyPositions(decoder, binary(
+ "b50069a00000689d315604512b32378f1a8e9fe094005a04d7c84b41020300ab250402140c0702c0006501006601006b0280646c0402883db0315604525732378f1d8e9fdd94005a04d7c84b41020300ab250402140c0702c0006501006601006b0280646c0402883db08887"));
+
+ verifyPositions(decoder, binary(
+ "b50028080000689d215602772f00378f1b8e9fdd98005a042efb3e4102030000000402140c070200000901"));
+
+ verifyPositions(decoder, binary(
+ "b500280a0000689d215602772f00378f1b8e9fdd98005a042efb3e4102030000000402140c07020000da20"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/TzoneProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/TzoneProtocolDecoderTest.java
new file mode 100644
index 000000000..bd1fc71f4
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/TzoneProtocolDecoderTest.java
@@ -0,0 +1,53 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class TzoneProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ TzoneProtocolDecoder decoder = new TzoneProtocolDecoder(null);
+
+ verifyAttributes(decoder, binary(
+ "545a005b24240406010800000866050033819630120911071824000472bd8e5b0008aac01b07019b04bb002f00040b06161154000e100132ff2006161152000e080096ff4606161151000e1e0101ff1406161156000db6405bff490024469e0d0a"));
+
+ verifyAttributes(decoder, binary(
+ "545a006624240406010800000866050033819630120911070e1d000472bd8e5b0008aac01b17019b04bc003a00050b06161151000e1e00ffff1406161152000e08008aff4706161154000e100134ff1f06161156000db0406cff4906161155000df44011ff4e0023811a0d0a"));
+
+ verifyPosition(decoder, binary(
+ "545a005624240111010e0000086169303626931411091b151d2600160801de26ec002f633411091b151d2500000000160c0000040d2a34df000eaa4000001b37016000000000319c0000000000000000000000000000003a84240d0a"));
+
+ verifyPosition(decoder, binary(
+ "545a005024240153011000000863835025559464110103080a22001609011bed79245964a9110103080a22000a0000550c00000604396f04222c000daac000151701a204870000000000000003000959000546190d0a"));
+
+ verifyPosition(decoder, binary(
+ "545A005224240153010E000008638350256668551008130616090016050079F63D2527FAF710081306160900A000002F0D33000803015B07013D7976000DAAE0400537016C049E000000000000000300800002B65EEA0D0A"));
+
+ verifyPosition(decoder, binary(
+ "545a00582424010b022000000860041028904798100803030c2700160a007da96203356669100803030c2700000000000e000004002813730010aa4000000617017100000000000080000000000000000000000000000000007701fe0d0a"));
+
+ verifyPosition(decoder, binary(
+ "545a00582424010b022000000860041028904798100803030d1a001609007da9620335666a100803030d1900000000000e000004002813730010aa400000063701720000000000008000000000000000000000000000000000787f0c0d0a"));
+
+ verifyPosition(decoder, binary(
+ "545a00582424010b021e000008637710239476270f080b0a3228001600000000000000000000000000000000000000000000000401a00822001088c00020183701a6053800000000800000000000000000000000000000000077c9860d0a"),
+ position("1999-11-30 00:00:00.000", false, 0.0, 0.0));
+
+ verifyPosition(decoder, binary(
+ "545A00912424010B021E000008661040203754350F061807083800160400CE5ADC041447620F0618070838000A0000060C7C0004253378370010AAC000000C37018504E500000000800000000000000000390B0A0014061113000000051200140610600014061220001000133800140610070010001473001000151100101500640010000920001000148400000000000000F2EF570D0A"),
+ position("2015-06-24 07:08:56.000", true, 22.53946, 114.06310));
+
+ verifyAttributes(decoder, binary(
+ "545A009E2424010A0205000008637710225481290F010F081E33000000000010A0C000310E35000005840000000000000000000000000066140A00140612200010001511001406101000140612490014061308001015006400051400170014061012000000050200140612470000000504001406100700140612510014061260001015012000000005080014061252001406130900101501410000000506000853A40D0A"));
+
+ verifyAttributes(decoder, binary(
+ "545A00992424010A0205000008637710225481290F010F082634000000000010A0C000311035000005870000000000000000000000000061130A000000050800101500640014061251001406130800051400170010150141001406101000140612200014061309000000050200140610070014061260001406124900140612470014061012001406125200100015110010150120000000050400183E8A0D0A"));
+
+ verifyAttributes(decoder, binary(
+ "545A00942424010A0205000008637710225481290F010F091C1F000000000010A1C000310F3500000586000000000000000000000000005C120A001406101000140612490014061012001406125200000005040000000502001015012000000005080010001511001406122000140612600014061247001406130900140610070010150141000514001700140612510010150064007A907C0D0A"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/UlbotechFrameDecoderTest.java b/src/test/java/org/traccar/protocol/UlbotechFrameDecoderTest.java
new file mode 100644
index 000000000..d3d0429d6
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/UlbotechFrameDecoderTest.java
@@ -0,0 +1,29 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class UlbotechFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ UlbotechFrameDecoder decoder = new UlbotechFrameDecoder();
+
+ assertEquals(
+ binary("f8010103515810532780699f7e2e3f010e015ee4c906bde45c00000000008b0304004000000404002c776005060373193622110b00240b00fee8ffff807dffff606d0b00fee9af000000af0000000b00feee7d78807dffffffff100101cc2af8"),
+ decoder.decode(null, null, binary("f8010103515810532780699f7e2e3f010e015ee4c906bde45c00000000008b0304004000000404002c776005060373193622110b00240b00fee8ffff807dffff606d0b00fee9af000000af0000000b00feee7d78807dffffffff100101cc2af8")));
+
+ assertEquals(
+ binary("2a545330312c33353430343330353133383934363023"),
+ decoder.decode(null, null, binary("2a545330312c33353430343330353133383934363023")));
+
+ assertEquals(
+ binary("f8010108679650230646339de69054010e015ee17506bde2c60000000000ac0304024000000404000009f705060390181422170711310583410c0000310d00312f834131018608040003130a100101136cf8"),
+ decoder.decode(null, null, binary("f8010108679650230646339de69054010e015ee17506bde2c60000000000ac0304024000000404000009f70005060390181422170711310583410c0000310d00312f834131018608040003130a100101136cf8")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/UlbotechProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/UlbotechProtocolDecoderTest.java
new file mode 100644
index 000000000..1c29ccd4a
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/UlbotechProtocolDecoderTest.java
@@ -0,0 +1,90 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class UlbotechProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ UlbotechProtocolDecoder decoder = new UlbotechProtocolDecoder(null);
+
+ verifyNull(decoder, buffer(
+ "*TS01,353323081464660#"));
+
+ verifyAttributes(decoder, buffer(
+ "*TS01,868323025245751,134955140317,WFE:0#"));
+
+ verifyPosition(decoder, binary(
+ "f8010103515810532780699f7e2e3f010e015ee4c906bde45c00000000008b0304004000000404002c776005060373193622110b00240b00fee8ffff807dffff606d0b00fee9af000000af0000000b00feee7d78807dffffffff100101cc2af8"));
+
+ verifyPosition(decoder, binary(
+ "F8010103596580420045259CFB3329010E015ED91506BDE5A800000000009E030402420000040400492AA405060344197E220D071131058F410C1591310D48312F8F413107C60804027666B00C138254D182607A826EE083BE554385F50019423CAD1DF8"));
+
+ verifyNotNull(decoder, binary(
+ "F8010108683230231070781EA3676E020BFFFFFFFFFFFFFFFFFFFF780304000000030404000002C20506032A1790220E100101AC72F8"));
+
+ verifyNotNull(decoder, binary(
+ "f8010108683230220996561ea6ce1c020bffffffffffffffffffff78030400000000040400087b710506035519ad2214060800000000000000006220f8"));
+
+ verifyAttributes(decoder, binary(
+ "f8010108683230220996561ea6ce3f020b02cc00114e86000002f153030400000000040400087b710506035619a4221406080000000000000000fbcff8"));
+
+ verifyAttributes(decoder, binary(
+ "f8010108683230211861161e9d8c48020b00de0063eb730128b56161030400010001040400127d0705060174179422021005e000000001db06f8"));
+
+ verifyPosition(decoder, binary(
+ "f8010108683230220996561ea6cdf9010eff47465cfb68d7a000000000270f030400000000040400087b710506035119ba22140608000000000000000022cef8"));
+
+ verifyPosition(decoder, binary(
+ "f8010108683230220996561ea74274010eff47477bfb68d89000000000270f030400000000040400087b710506035419472214060800000000000000006661f8"));
+
+ verifyPosition(decoder, binary(
+ "f8010103515790566431569e5fbb9d010e015ee2b906bde4a000000000009f03040a4000000404000115fe05060340173f22030711310583410c0000310d00312f834131000008040000b78c09077320290082c021100101120af8"));
+
+ verifyNull(decoder, buffer(
+ "*TS01,354043051389460#"));
+
+ verifyPosition(decoder, binary(
+ "f8010108679650230646339de69054010e015ee17506bde2c60000000000ac0304024000000404000009f705060390181422170711310583410c0000310d00312f834131018608040003130a100101136cf8"));
+
+ verifyPosition(decoder, binary(
+ "f8010108679650230651689dc8e45b010e01194a26fbd47fa6001f003c0054030402420000040400024d7b0506037c18692212071131057f410c0ee0310d1b312f41413112ef0804000dd59fcc32f8"));
+
+ verifyPosition(decoder, binary(
+ "f8010103596580419465449da89d16010efe5580fe0923d82100140129005903040242000004040001a7f10506037818be220e070e31057b410c1324310d144131fa3208040020b1418297f8"));
+
+ verifyPosition(decoder, binary(
+ "f8010103596580419465449da8564e010efe55a1800923d04b0000000000710304000000000404000178d2050603571876220ec3caf8"));
+
+ verifyPosition(decoder, binary(
+ "f8010103545500500179009ccb4b62010e00144db906310d3f0000000000cb0304000000000404000a8123050603211860221006080000000100000000ef97f8"));
+
+ verifyPosition(decoder, binary(
+ "F80101035785203457289495D60235010E016175A506C2C838000000000064"));
+
+ verifyPosition(decoder, binary(
+ "F8010108621060211481299C4247FA010E015EE1D606BDE797000301370081030402420000040400523CAF050603921743220706080000000000000000071131058E410C0E30310D48312F8E4131046A080402C8F2545445F8"));
+
+ verifyPosition(decoder, binary(
+ "F8010108621060211481299C4249FA010E015EE27506BDE80900020000008F030402420000040400523CAF05060392173F220706080000000000000000071131058E410C0E40310D48312F8E41310884080402CA60E43872F8"));
+
+ verifyNotNull(decoder, binary(
+ "f8010108653280262660481cdacf830209ffffffffffffffff780304000300000404000000030506017418a021f99697f8"));
+
+ verifyNotNull(decoder, binary(
+ "f801010865328026266048fffeae800209ffffffffffffffff7803040200000004040000000005060375175421f3060800000000000000009c28f8"));
+
+ verifyPosition(decoder, binary(
+ "f8010108653280262660489ce260b4010e01e757bd022340d7002b010d01570304020200000404000000260506036a17d42200060800000000000000000a0101ab9ff8"));
+
+ verifyPosition(decoder, binary(
+ "f8010108653280262660489ce260df010e01e756f30223384a0003010a02a80304020200000404000001280506036217fe22010608000000000000000005aaf8"));
+
+ verifyPosition(decoder, binary(
+ "f8010108653280262660489ce26128010e01e769ac022336290014010300730304020200000404000003c905060371181c2201060800000000000000000a0140e471f8"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/UproProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/UproProtocolDecoderTest.java
new file mode 100644
index 000000000..dbbe4591f
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/UproProtocolDecoderTest.java
@@ -0,0 +1,65 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class UproProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ UproProtocolDecoder decoder = new UproProtocolDecoder(null);
+
+ verifyPosition(decoder, buffer(
+ "*HQ200861810538000002,BA&A0206033302618209658563620115180119&B0100000040&C6328680=&F0039&R2710&V0036&T09&K50000&N04&P0200#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ200999999,AB1&A1656512233362911356523660000230618&B0100060010&C00000<6<&F0000&R2405&V0109&W0000003E&K00100&T65&X(k89860045191536000374)#"));
+
+ verifyPosition(decoder, buffer(
+ "*HQ20113800138000,YAA&A0732142233550011405829060520190314&B0100000000&C00001234&R3109&T80#"));
+
+ verifyPosition(decoder, binary(
+ "2a4d473230313836383530303032303030343836372c414226413035303032343138313438373536303636303131373732323030303031313132313626583331302c3236302c34383837322c353639312c37333b34383837322c3732322c38363b34383837322c353639332c38383b34383837322c323336332c39303b34383837322c323336322c393726423030303030303030303026573030264e3230265a31342659313430303323"));
+
+ verifyPosition(decoder, binary(
+ "2a4d473230303639333530323030303033353537332c42412641303834313237333332363334353230373033383933373630303030303235313131362642303130303030303030302647303036323030264d393930264e3235264f3035303026433030313a363b363926510411058c0c125c0d0a2fff4237ee614d66454c140826555f50000000000300000000000000000026543139333723"));
+
+ verifyPosition(decoder, buffer(
+ "*MG201693502000035441,BA&A1213073325458307036690710000151116&P0730000032ce4fb3&D1&B0000000000&C005799?7&S3,20161115120025,07035.54659E,3324.87721N,3000,0,0,0,0,847,599,8,40,0,19,20&U_P\0\0\0\0\0\0\0\0\0\0\0\0\0\0&T0107"));
+
+ verifyPosition(decoder, buffer(
+ "*MG201693502000034964,AB&A0800253335360507036975710000091116&P0730000032d2a94d&B0000000000&N13&Z12&U_P\0\0\0\u0004\0\0\0\0\0\0\0\0\0\0"),
+ position("2016-11-09 08:00:25.000", true, -33.58934, -70.61626));
+
+ verifyNull(decoder, buffer(
+ "*MG20113800138000,AH"));
+
+ verifyPosition(decoder, buffer(
+ "*MG201693502000034964,AB&A0200183324418107033792800009051116&B0000000000&N15&Z94&U_P\0\0\0\0\0\0\0\0\0\0\0\0\0\0"));
+
+ verifyPosition(decoder, buffer(
+ "*MG201693502000034964,AB&A0200543324412007033805910000051116&P0730000032d66785&B0000000000&N15&Z92&U_P\0\0\0\0\0\0\0\0\0\0\0\0\0\0"));
+
+ verifyPosition(decoder, buffer(
+ "*AI2000905447674,BA&A2003064913201201845107561627121016&B0100000000&C05>8=961&F0333&K023101002154A7"));
+
+ verifyPosition(decoder, buffer(
+ "*AI200905300036,AH&A0317264913209801844913060000251115&B0500000000&C0;4?72:9&F0000"),
+ position("2015-11-25 03:17:26.000", false, 49.22016, 18.74855));
+
+ verifyPosition(decoder, buffer(
+ "*AI2000905300036,AS&A1647304913209801844913060000251115&B0400000000&C0;4?72:9&F0000"));
+
+ verifyPosition(decoder, buffer(
+ "*AI2000905300036,AC1&A1648014913209801844913060000251115&B0400000000&C0;4?72:9&F0000"));
+
+ verifyPosition(decoder, buffer(
+ "*AI2000905300036,AB1&A1702464913231101844949860000251115&B0500000000&C0;4?72:9&F0000"));
+
+ verifyPosition(decoder, buffer(
+ "*AI2000905300036,AD1&A1703054913231101844949860000251115&B0500000000&C0;4?72:9&F0000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/V680ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/V680ProtocolDecoderTest.java
new file mode 100644
index 000000000..e3761c3ef
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/V680ProtocolDecoderTest.java
@@ -0,0 +1,77 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class V680ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ V680ProtocolDecoder decoder = new V680ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "#867967020910610#01234567890#1#0000#AUT#1#0500000000120000#114.036291,E,22.665795,N,111.00,000.00#111116#193333##"),
+ position("2016-11-11 19:33:33.000", true, 22.66579, 114.03629));
+
+ verifyPosition(decoder, text(
+ "#355488020168617##1#0000#AUT#01#260001a412966f#1834.790700,E,5302.748800,N,0.00,0.00#310316#174538.000##"));
+
+ verifyPosition(decoder, text(
+ "#355488020168617##1#0000#AUT#01##1834.770100,E,5302.742800,N,0.62,0.00#310316#211537.000##"));
+
+ verifyNull(decoder, text(
+ "#353588102019155"));
+
+ verifyPosition(decoder, text(
+ "#135790246811222#13486119277#1#0000#SOS#1#27bc10af#11407.4182,E,2232.7632,N,0.00,79.50#070709#134147.000##"));
+
+ verifyPosition(decoder, text(
+ "#356823031193431##0#0000#SF#1#72403#V#04702.3025,W,2252.18380,S,008.18,0#090413#134938"),
+ position("2013-04-09 13:49:38.000", false, -22.86973, -47.038375));
+
+ verifyPosition(decoder, text(
+ "#356823033219838#1000#0#1478#AUT#1#66830FFB#03855.6628,E,4716.6821,N,001.41,259#130812#143905"));
+
+ verifyPosition(decoder, text(
+ "#353588102019155##1#0000#AUT#01#7240060be7873f#4849.079800,W,2614.458200,S,0.00,0.00#130413#182110.000"));
+
+ verifyPosition(decoder, text(
+ "#353588302045917##1#0000#AUT#01#7243141c2b14c3#4738.442300,W,2334.874000,S,0.00,0.30#170413#004831.000"));
+
+ verifyPosition(decoder, text(
+ "#352897045085282##0#0000#AUT#1#72400510730208,00d36307,10734fc4#4647.8922,W,2339.1956,S,2.60,63.74#200413#094310.000"));
+
+ verifyPosition(decoder, text(
+ "#356823033537791##0#0000#AUT#1#V#03610.2179,E,5004.5796,N,000.01,349#180513#073758"));
+
+ verifyPosition(decoder, text(
+ "#356823031236214##0#0000#AUT#1#V#01904.5491,E,6941.0085,N,000.09,248#170513#160140"));
+
+ verifyNull(decoder, text(
+ "#353588550032869##1#0000#AUT#01#72400401cd01a5#00000.0000,E,0000.0000,N,0.00,#000000#000000.000"));
+
+ verifyPosition(decoder, text(
+ "#352897045085282##0#0000#AUT#1#72400510730208,00d36307,10734fc4#4647.8922,W,2339.1956,S,2.60,63.74#200413#094310.000##"));
+
+ verifyPosition(decoder, text(
+ "#352165050199210##13#0000#AUT#1#72400605471305,054712fd,054712ff#05144.0008,W,3005.5011,S,0.11,201.46#260713#172647.000##"));
+
+ verifyPosition(decoder, text(
+ "#356823031166908#13001190527#0#0000#AUT#4#V#07136.4070,W,1040.0575,N,000.35,257#280813#142836#V#07136.4088,W,1040.0580,N,000.49,288#280813#142846#V#07136.4098,W,1040.0590,N,000.59,264#280813#142856#V#07136.4093,W,1040.0605,N,000.30,264#280813#142906##"));
+
+ verifyPosition(decoder, text(
+ "#355488020132015##1#0000#AUT#01#510089246a34c0#10641.338800,E,619.427100,S,0.00,0.00#011113#161942.000##"));
+
+ verifyPosition(decoder, text(
+ "#359094025419110#bigfriend#0#1234#AUTO#1##04632.8846,W,2327.2264,S,0.00,0.00#220913#234808##"));
+
+ verifyPosition(decoder, text(
+ "#353588102031599##1#0000#AUT#01#41300304843fc1#7955.124400,E,642.095500,N,5.28,95.21#041213#074431.000##"));
+
+ verifyPosition(decoder, text(
+ "1#0000#AUT#01#23403007fa650e#16.747700,W,5136.356500,N,0.00,0.00#040415#002051.000"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/VisiontekProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/VisiontekProtocolDecoderTest.java
new file mode 100644
index 000000000..11596945e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/VisiontekProtocolDecoderTest.java
@@ -0,0 +1,40 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class VisiontekProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ VisiontekProtocolDecoder decoder = new VisiontekProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$1,117,28,01,16,15,05,48,1725.0518N,07824.5298E,0620,11,0,185,2062,0,0,0,1,1,1,1,24,00.0000,00.3740,00.0000,VAJRA V1.00,A"));
+
+ verifyPosition(decoder, text(
+ "$1,VMC,358072044271838,26,10,15,10,43,20,17.066418N,080.395667E,000.0,285,00.8,0074,6390,0,0,0,0,0,0,0,0,00.00,00.00,00,00,0000,12.7,4.0,24,10,0000000000000,A,0"));
+
+ verifyNull(decoder, text(
+ "$1,VMC,358072044271838,25,10,15,09,19,40,00.0000000,000.0000000,000.0,000,00.0,0000,6070,0,0,0,0,0,0,0,0,00.00,00.00,00,00,0000,12.5,4.0,99,00,0000000000000,V,0"));
+
+ verifyPosition(decoder, text(
+ "$1,AP116,05,06,15,11,48,32,1725.0460N,07824.5289E,0617,07,0,030,2091,0,0,0,1,1,1,1,20,00.0000,00.3820,00.0000,VAJRA V1.00,A"));
+
+ verifyPosition(decoder, text(
+ "$1,AP09BU9397,861785006462448,20,06,14,15,03,28,17267339N,078279407E,060.0,073,0550,11,0,1,0,0,1,1,26,A,0000000000"),
+ position("2014-06-20 15:03:28.000", true, 17.44556, 78.46567));
+
+ verifyNull(decoder, text(
+ "$1,AP09BU9397,861785006462448,20,06,14,15,03,28,000000000,0000000000,000.0,000,0000,00,0,1,0,0,1,1,24,V,0000000000"));
+
+ verifyNull(decoder, text(
+ "$1,1234567890,02,06,11,17,07,45,00000000,000000000,00.0,0,0,V"));
+
+ verifyPosition(decoder, text(
+ "$1,1234567890,02,06,11,17,07,45,17267690N,078279340E,060.0,113,0,A"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Vt200FrameDecoderTest.java b/src/test/java/org/traccar/protocol/Vt200FrameDecoderTest.java
new file mode 100644
index 000000000..9422f6d74
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Vt200FrameDecoderTest.java
@@ -0,0 +1,23 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Vt200FrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Vt200FrameDecoder decoder = new Vt200FrameDecoder();
+
+ verifyFrame(
+ binary("28631037309456208400340102dc0906171616454415760201144494473f920a0c0000030500200100417c1f383a9d1090510000006a00007000000e00180ee129"),
+ decoder.decode(null, null, binary("28631037309456208400340102dc0906171616454415760201144494473f920a0c0000030500200100417c1f383a9d1090510000006a00007000000e00180ee129")));
+
+ verifyFrame(
+ binary("28631037309456208400340102f51306171327294418267501208948170231071f0000044300200100005f02180000667500000000000000000000080000624629"),
+ decoder.decode(null, null, binary("28631037309456208400340102f513061713273d144418267501208948170231071f0000044300200100005f02180000667500000000000000000000080000624629")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Vt200ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Vt200ProtocolDecoderTest.java
new file mode 100644
index 000000000..9c224bc8e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Vt200ProtocolDecoderTest.java
@@ -0,0 +1,60 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Vt200ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Vt200ProtocolDecoder decoder = new Vt200ProtocolDecoder(null);
+
+ verifyPosition(decoder, binary(
+ "28192030961807208200210101b919011818375801245774036424612500160917000003aa008800007b00aa3429"));
+
+ verifyNull(decoder, binary(
+ "286310373094563082002701033d010817143327c68a14841e00c27f550e9a000000000c000000084700200120007d01af260b29"));
+
+ verifyAttributes(decoder, binary(
+ "2863103730945630880062033d862631037309456f222014604362936f010817140954010817144135076b00002a3800003b7d6127cc91040000000000000000000000005a0000088e000001ce02630000263b000009b401ff00000cb40000069c02af000018190200000102019729"));
+
+ verifyPosition(decoder, binary(
+ "286310373094562086002101033d010817143328441790420114817637207d090a00000847002001207f00d6f229"));
+
+ verifyPosition(decoder, binary(
+ "286310373094562086002101033d0108171433354417932101148139772c9d080a00000847002001207f00dc6729"));
+
+ verifyNull(decoder, binary(
+ "2863103730945600880012180108171433004418103801148375470000dd29"));
+
+ verifyNull(decoder, binary(
+ "28631037309456108800002e29"));
+
+ verifyAttributes(decoder, binary(
+ "2863103730945630880062033c862631037309456f222014604362936f01081713365601081713571904c800001b2c000034f66827f0840000000000000000000000000047000006e7000001b9022a000023ff000007f2018a00000a10000003f300cd00000d8d0300000302002729"));
+
+ verifyNull(decoder, binary(
+ "28631037309456008e000801042307171804584229"));
+
+ verifyNull(decoder, binary(
+ "28631037309456108800002e29"));
+
+ verifyPosition(decoder, binary(
+ "28631037309456208200210103302307171805444417097301147188170198090f0000073a002000007e00074429"));
+
+ verifyNull(decoder, binary(
+ "286310373094563089001200032f2107171740144417075001147188872c29"));
+
+ verifyAttributes(decoder, binary(
+ "2863103730945630880062032f862631037309456f222014604362936f21071717373221071717401400a100000cd700000004020d3c8e0000000000000000000000000000000000000000000000000000000000000000000a000000040000000e009700000cc9000000000000e929"));
+
+ verifyPosition(decoder, binary(
+ "28631037309456208400340102dc0906171616454415760201144494473f920a0c0000030500200100417c1f383a9d1090510000006a00007000000e00180ee129"));
+
+ verifyPosition(decoder, binary(
+ "28631037309456208400340102dc090617161654441577230114439597368c0a0c0000030500200100417c1baa349d3290510000006a00007000003d15004c11c629"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/VtfmsFrameDecoderTest.java b/src/test/java/org/traccar/protocol/VtfmsFrameDecoderTest.java
new file mode 100644
index 000000000..a5eb0b49b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/VtfmsFrameDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class VtfmsFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ VtfmsFrameDecoder decoder = new VtfmsFrameDecoder();
+
+ assertEquals(
+ buffer("(863071010087648,0HK44,00,000,14,2,9,,A,114946,180313,11.0244,076.9768,282,000,00000,00000,K,0000128,1,12.8,,200,2.501,,4.001,0,0,0,0,0,0,0,,)105"),
+ decoder.decode(null, null, buffer("(863071010087648,0HK44,00,000,14,2,9,,A,114946,180313,11.0244,076.9768,282,000,00000,00000,K,0000128,1,12.8,,200,2.501,,4.001,0,0,0,0,0,0,0,,)105")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/VtfmsProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/VtfmsProtocolDecoderTest.java
new file mode 100644
index 000000000..ede5dc7ac
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/VtfmsProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class VtfmsProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ VtfmsProtocolDecoder decoder = new VtfmsProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "(861359037432331,0EF87,00,0,21,2,01,,A,154559,230119,1101.4046,07656.3859,241,000,00078,00000,K,0000812,1,12.7,,,,,,1,0,0,0,1,1,1,+919566531111*+919994462226,)054"),
+ position("2019-01-23 15:45:59.000", true, 11.02341, 76.93977));
+
+ verifyPosition(decoder, text(
+ "(865733028143493,00I76,00,000,,,,,A,133755,210617,10.57354,077.24912,SW,000,00598,00000,K,0017368,1,12.7,,,0.000,,,0,0,0,0,1,1,0,,)074"));
+
+ verifyPosition(decoder, text(
+ "(863071010087648,0HK44,00,000,14,2,9,,A,114946,180313,11.0244,076.9768,282,000,00000,00000,K,0000128,1,12.8,,200,2.501,,4.001,0,0,0,0,0,0,0,,)105"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/WatchFrameDecoderTest.java b/src/test/java/org/traccar/protocol/WatchFrameDecoderTest.java
new file mode 100644
index 000000000..4e40eea86
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/WatchFrameDecoderTest.java
@@ -0,0 +1,35 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class WatchFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ WatchFrameDecoder decoder = new WatchFrameDecoder();
+
+ verifyFrame(
+ binary("5b33472a3335323636313039303134333135302a303030412a4c4b2c302c302c3130305d"),
+ decoder.decode(null, null, binary("5b33472a3335323636313039303134333135302a303030412a4c4b2c302c302c3130305d")));
+
+ verifyFrame(
+ binary("5b33472a383330383430363237392a303030382a72636170747572655d"),
+ decoder.decode(null, null, binary("5b33472a383330383430363237392a303030382a72636170747572655d")));
+
+ verifyFrame(
+ binary("5b33472a383330383430363237392a303030392a4c4b2c302c302c38345d"),
+ decoder.decode(null, null, binary("5b33472a383330383430363237392a303030392a4c4b2c302c302c38345d")));
+
+ verifyFrame(
+ binary("5b5a4a2a3031343131313030313335303330342a303033342a303030392a4c4b2c302c302c31395d"),
+ decoder.decode(null, null, binary("5b5a4a2a3031343131313030313335303330342a303033342a303030392a4c4b2c302c302c31395d")));
+
+ verifyFrame(
+ concatenateBuffers(buffer("[CS*1234567890*000e*TK,#!AMR"), binary("7d5b5d2c2aff"), buffer("]")),
+ decoder.decode(null, null, concatenateBuffers(buffer("[CS*1234567890*000e*TK,#!AMR"), binary("7d017d027d037d047d05ff"), buffer("]"))));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/WatchProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/WatchProtocolDecoderTest.java
new file mode 100644
index 000000000..539e63253
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/WatchProtocolDecoderTest.java
@@ -0,0 +1,128 @@
+package org.traccar.protocol;
+
+import io.netty.buffer.ByteBuf;
+import org.junit.Test;
+import org.traccar.Context;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Position;
+
+import static org.junit.Assert.assertEquals;
+
+public class WatchProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ WatchProtocolDecoder decoder = new WatchProtocolDecoder(null);
+
+ verifyPosition(decoder, buffer(
+ "[ZJ*014111001332708*0075*0064*AL,040418,052156,A,22.536207,N,113.938673,E,0,0,0,5,100,82,1000,50,00100000,1,255,460,0,9340,3663,35]"));
+
+ verifyPosition(decoder, buffer(
+ "[SG*352661090143150*006C*UD,150817,132115,V,28.435142,N,81.354333,W,2.2038,000,99,00,70,100,0,50,00000000,1,1,310,260,1091,30082,139,,00]"));
+
+ verifyAttributes(decoder, buffer(
+ "[3G*4700609403*0013*bphrt,120,79,73,,,,]"));
+
+ verifyPosition(decoder, buffer(
+ "[3G*8308373902*0080*AL,230817,095346,A,47.083950,N,15.4821850,E,7.60,273.8,0.0,4,15,44,0,0,00200010,2,255,232,1,7605,42530,118,7605,58036,119,0,65.8]"));
+
+ verifyPosition(decoder, buffer(
+ "[SG*9051007430*006C*UD,150817,132115,V,28.435142,N,81.354333,W,2.2038,000,99,00,70,100,0,50,00000000,1,1,310,260,1091,30082,139,,00]"));
+
+ verifyPosition(decoder, buffer(
+ "[3G*6005412902*011F*WT,170517,133811,V,18.512200,N,73.7750283,E,0.00,0.0,0.0,0,92,82,4262,0,00000010,2,1,404,22,10125,8301,141,10125,13921,122,5,Skynet,28:c6:8e:be:87:c0,-60,Intel Wi-Fi,4c:60:de:32:3d:38,-70,Nirvanic-2,40:e3:d6:4a:d9:c2,-73,A4-Guest,40:e3:d6:4a:d9:c4,-73,A4Idatix,40:e3:d6:4a:d9:c3,-73,13.8]"));
+
+ verifyPosition(decoder, buffer(
+ "[3G*8308406279*00CC*UD3,170417,190930,V,54.739618,N,25.273213,E,0.0,323.53,175.1,6,51,83,0,0,00000000,1,1,246,01,200,13242758,51,3,TEO-189835,00:8c:54:58:1d:64,-84,Cgates_7137,78:54:2e:e3:71:37,-85,ASUS,9c:5c:8e:b8:d4:78,-93]"));
+
+ verifyPosition(decoder, buffer(
+ "[SG*9051004074*0058*AL,120117,145602,V,40.058413,N,76.336618,W,11.519,188,99,00,01,80,0,50,00000000,0,1,0,0,,10]"));
+
+ verifyPosition(decoder, buffer(
+ "[SG*9051000884*009B*UD,030117,161129,V,52.745450,N,0.369512,,0.1481,000,99,00,70,5,0,50,00000000,5,1,234,15,893,3611,135,893,3612,132,893,3993,131,893,30986,129,893,40088,126,,00]"));
+
+ verifyPosition(decoder, buffer(
+ "[3G*6430073509*00E7*UD2,241016,081622,V,09.951861,N,-84.1422119,W,0.00,0.0,0.0,0,39,94,0,0,00000000,1,0,712,3,2007,18961,123,4,Luz,00:23:6a:34:ee:76,-70,familia,b0:c5:54:b9:90:ef,-78,fam salas delgado,fc:b4:e6:5d:50:ea,-81,QWERTY,c8:3a:35:43:0f:e8,-93]"));
+
+ verifyPosition(decoder, buffer(
+ "[3G*6105117105*008D*UD2,210716,231601,V,-33.480366,N,-70.7630692,E,0.00,0.0,0.0,0,100,34,0,0,00000000,3,255,730,2,29731,54315,167,29731,54316,162,29731,54317,145]"),
+ position("2016-07-21 23:16:01.000", false, -33.48037, -70.76307));
+
+ verifyPosition(decoder, buffer(
+ "[3G*4700222306*0077*UD,120316,140610,V,48.779045,N, 9.1574736,E,0.00,0.0,0.0,0,25,83,0,0,00000000,2,255,262,1,21041,9067,121,21041,5981,116]"));
+
+ verifyPosition(decoder, buffer(
+ "[3G*4700222306*011F*UD2,120316,140444,A,48.779045,N, 9.1574736,E,0.57,12.8,0.0,7,28,77,0,0,00000000,2,2,262,1,21041,9067,121,21041,5981,116,5,WG-Superlativ,34:31:c4:c8:a9:22,-67,EasyBox-28E858,18:83:bf:28:e8:f4,-70,MoMaXXg,be:05:43:b7:19:15,-72,MoMaXX2,bc:05:43:b7:19:15,-72,Gastzugang,18:83:bf:28:e8:f5,-72]"));
+
+ verifyNull(decoder, buffer(
+ "[SG*9081000548*0009*LK,0,100]"));
+
+ verifyPosition(decoder, buffer(
+ "[SG*9081000548*00A9*UD,110116,113639,V,16.479064,S,68.119072,,0.7593,000,99,00,80,80,0,50,00000000,5,1,736,2,10103,10732,153,10103,11061,152,10103,11012,152,10103,10151,150,10103,10731,143,,00]"));
+
+ verifyPosition(decoder, buffer(
+ "[3G*2256002206*0079*UD2,100116,153723,A,38.000000,N,-9.000000,W,0.44,299.3,0.0,7,100,86,0,0,00000008,2,0,268,3,3010,51042,146,3010,51043,132]"));
+
+ verifyNull(decoder, buffer(
+ "[3G*8800000015*0003*TKQ]"));
+
+ verifyPosition(decoder, buffer(
+ "[3G*4700186508*00B1*UD,301015,084840,V,45.853100,N,14.6224899,E,0.00,0.0,0.0,0,84,61,0,11,00000008,7,255,293,70,60,6453,139,60,6432,139,60,6431,132,60,6457,127,60,16353,126,60,6451,121,60,16352,118]"));
+
+ verifyNull(decoder, buffer(
+ "[SG*8800000015*0002*LK]"));
+
+ verifyAttributes(decoder, buffer(
+ "[3G*4700186508*000B*LK,0,10,100]"));
+
+ verifyPosition(decoder, buffer(
+ "[SG*8800000015*0087*UD,220414,134652,A,22.571707,N,113.8613968,E,0.1,0.0,100,7,60,90,1000,50,0000,4,1,460,0,9360,4082,131,9360,4092,148,9360,4091,143,9360,4153,141]"),
+ position("2014-04-22 13:46:52.000", true, 22.57171, 113.86140));
+
+ verifyPosition(decoder, buffer(
+ "[SG*8800000015*0087*UD,220414,134652,A,22.571707,N,113.8613968,E,0.1,0.0,100,7,60,90,1000,50,0000,4,1,460,0,9360,4082,131,9360,4092,148,9360,4091,143,9360,4153,141]"));
+
+ verifyPosition(decoder, buffer(
+ "[SG*8800000015*0088*UD2,220414,134652,A,22.571707,N,113.8613968,E,0.1,0.0,100,7,60,90,1000,50,0000,4,1,460,0,9360,4082,131,9360,4092,148,9360,4091,143,9360,4153,141]"));
+
+ verifyPosition(decoder, buffer(
+ "[SG*8800000015*0087*AL,220414,134652,A,22.571707,N,113.8613968,E,0.1,0.0,100,7,60,90,1000,50,0001,4,1,460,0,9360,4082,131,9360,4092,148,9360,4091,143,9360,4153,141]"));
+
+ verifyAttributes(decoder, buffer(
+ "[CS*8800000015*0008*PULSE,72]"));
+
+ verifyAttributes(decoder, buffer(
+ "[3G*6005412902*0007*heart,0]"));
+
+ verifyAttributes(decoder, buffer(
+ "[3G*6005412902*0008*heart,71]"));
+
+ verifyPosition(decoder, buffer(
+ "[ZJ*014111001350304*0033*0064*UD,070318,020827,V,00.000000,N,000.000000,E,0,0,0,0,100,19,1000,50,00000000,1,255,460,0,9346,5223,42]"));
+
+ verifyPosition(decoder, buffer(
+ "[ZJ*014111001350304*0035*0097*UD,070318,020857,V,00.000000,N,000.000000,E,0,0,0,0,100,19,1000,50,00000000,5,255,460,0,9346,5223,42,9346,5214,21,9784,4083,13,9346,5222,11,9346,5221,8]"));
+
+ verifyPosition(decoder, buffer(
+ "[ZJ*014111001350304*0038*008a*UD,070318,021027,V,00.000000,N,000.000000,E,0,0,0,0,100,18,1000,50,00000000,4,255,460,0,9346,5223,42,9346,5214,20,9784,4083,11,9346,5221,5]"));
+
+ }
+
+ @Test
+ public void testDecodeVoiceMessage() throws Exception {
+
+ WatchProtocolDecoder decoder = new WatchProtocolDecoder(null);
+
+ verifyNull(decoder.decode(null, null, buffer("[CS*1234567890*0004*TK,1]")));
+
+ ByteBuf data = binary("7d5b5d2c2aff");
+
+ Object decodedObject = decoder.decode(null, null, concatenateBuffers(buffer("[CS*1234567890*000e*TK,#!AMR"), data.resetReaderIndex(), buffer("]")));
+ assertEquals("1234567890/mock.amr", ((Position) decodedObject).getAttributes().get("audio"));
+
+ verifyFrame(concatenateBuffers(buffer("#!AMR"), data.resetReaderIndex()), ((MockMediaManager) Context.getMediaManager()).readFile("1234567890/mock.amr"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/WatchProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/WatchProtocolEncoderTest.java
new file mode 100644
index 000000000..a0631be3b
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/WatchProtocolEncoderTest.java
@@ -0,0 +1,83 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+public class WatchProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ WatchProtocolEncoder encoder = new WatchProtocolEncoder();
+
+ Command command;
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_REBOOT_DEVICE);
+ verifyFrame(buffer("[CS*123456789012345*0005*RESET]"), encoder.encodeCommand(null, command));
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SOS_NUMBER);
+ command.set(Command.KEY_INDEX, 1);
+ command.set(Command.KEY_PHONE, "123456789");
+ verifyFrame(buffer("[CS*123456789012345*000e*SOS1,123456789]"), encoder.encodeCommand(null, command));
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_VOICE_MESSAGE);
+ command.set(Command.KEY_DATA, "2321414d520a2573");
+ verifyFrame(buffer("[CS*123456789012345*000b*TK,#!AMR\n%s]"), encoder.encodeCommand(null, command));
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_VOICE_MESSAGE);
+ command.set(Command.KEY_DATA, "7d5b5d2c2a");
+ verifyFrame(concatenateBuffers(buffer("[CS*123456789012345*000d*TK,"), binary("7d017d027d037d047d05"), buffer("]")), encoder.encodeCommand(null, command));
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_VOICE_MESSAGE);
+ command.set(Command.KEY_DATA, "ff");
+ verifyFrame(concatenateBuffers(buffer("[CS*123456789012345*0004*TK,"), binary("ff"), buffer("]")), encoder.encodeCommand(null, command));
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_MESSAGE);
+ command.set(Command.KEY_MESSAGE, "text");
+ verifyFrame(buffer("[CS*123456789012345*0018*MESSAGE,0074006500780074]"), encoder.encodeCommand(null, command));
+
+ command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "WORK,6-9,11-13,13-15,17-19");
+ verifyFrame(buffer("[CS*123456789012345*001a*WORK,6-9,11-13,13-15,17-19]"), encoder.encodeCommand(null, command));
+
+ }
+
+ @Test
+ public void testEncodeTimezone() {
+
+ WatchProtocolEncoder encoder = new WatchProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_SET_TIMEZONE);
+
+ command.set(Command.KEY_TIMEZONE, "Europe/Amsterdam");
+ verifyFrame(buffer("[CS*123456789012345*0006*LZ,,+1]"), encoder.encodeCommand(null, command));
+
+ command.set(Command.KEY_TIMEZONE, "GMT+01:30");
+ verifyFrame(buffer("[CS*123456789012345*0008*LZ,,+1.5]"), encoder.encodeCommand(null, command));
+
+ command.set(Command.KEY_TIMEZONE, "Atlantic/Azores");
+ verifyFrame(buffer("[CS*123456789012345*0006*LZ,,-1]"), encoder.encodeCommand(null, command));
+
+ command.set(Command.KEY_TIMEZONE, "GMT-11:30");
+ verifyFrame(buffer("[CS*123456789012345*0009*LZ,,-11.5]"), encoder.encodeCommand(null, command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/WialonProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/WialonProtocolDecoderTest.java
new file mode 100644
index 000000000..40b0469ea
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/WialonProtocolDecoderTest.java
@@ -0,0 +1,67 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class WialonProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ WialonProtocolDecoder decoder = new WialonProtocolDecoder(null);
+
+ verifyNull(decoder, text(
+ "#L#2.0;42001300083;;CE45"));
+
+ verifyNull(decoder, text(
+ "#L#123456789012345;test"));
+
+ verifyNull(decoder, text(
+ "#L#2002;NA"));
+
+ verifyNull(decoder, text(
+ "#P#"));
+
+ verifyPosition(decoder, text(
+ "#D#101118;061143;0756.0930;N;12338.6403;E;18.223;99.766;-4.000;10;0.800;NA;NA;NA;NA;101_521347:1:521249,101_521126:1:6593598,101_521127:1:774780,101_521072_21.1:1:0,101_521072_21.2:1:71353;F24A"));
+
+ verifyPosition(decoder, text(
+ "#D#151216;135910;5321.1466;N;04441.7929;E;87;156;265.000000;12;1.000000;241;NA;NA;NA;odo:2:0.000000,total_fuel:1:430087,can_fls:1:201,can_taho:1:11623,can_mileage:1:140367515"));
+
+ verifyPosition(decoder, text(
+ "#D#151216;140203;5312.59514;N;04830.37834;E;53;273;NA;10;NA;NA;NA;NA;NA;EvId:1:1,Board:2:12.81,Accum:2:4.28"));
+
+ verifyPosition(decoder, text(
+ "#SD#270413;205601;5544.6025;N;03739.6834;E;1;2;3;4"),
+ position("2013-04-27 20:56:01.000", true, 55.74338, 37.66139));
+
+ verifyPosition(decoder, text(
+ "#SD#021214;065947;2237.7552;N;11404.8851;E;0.000;;170.9;5"));
+
+ verifyPosition(decoder, text(
+ "#D#270413;205601;5544.6025;N;03739.6834;E;1;2;3;4;0.0;0;0;14.77,0.02,3.6;NA;count1:1:564,fuel:2:45.8,hw:3:V4.5"));
+
+ verifyPosition(decoder, text(
+ "#D#190114;051312;4459.6956;N;04105.9930;E;35;306;204.000000;12;NA;452986639;NA;106.000000;NA;sats_gps:1:9,sats_glonass:1:3,balance:2:12123.000000,stay_balance:1:0"));
+
+ verifyPosition(decoder, text(
+ "#D#021214;065947;2237.7552;N;11404.8851;E;0.000;;170.9;5;1.74;NA;NA;NA;NA;NA"));
+
+ verifyPosition(decoder, text(
+ "#D#021214;065947;2237.7552;N;11404.8851;E;0.000;;170.9;5;1.74;NA;NA;;NA;NA"));
+
+ verifyPositions(decoder, text(
+ "#B#080914;073235;5027.50625;N;03026.19321;E;0.700;0.000;NA;4;NA;NA;NA;;NA;Батарея:3:100 %|080914;073420;5027.50845;N;03026.18854;E;1.996;292.540;NA;4;NA;NA;NA;;NA;Батарея:3:100 %"));
+
+ verifyPositions(decoder, text(
+ "#B#110914;102132;5027.50728;N;03026.20369;E;1.979;288.170;NA;NA;NA;NA;NA;;NA;Батарея:3:100 %"));
+
+ verifyPositions(decoder, text(
+ "#B#110315;045857;5364.0167;N;06127.8262;E;0;155;965;7;2.40;4;0;;NA;Uacc:2:3.4,Iacc:2:0.000,Uext:2:13.2,Tcpu:2:14.4,Balance:2:167.65,GPS:3:Off"));
+
+ verifyPositions(decoder, text(
+ "#B#110315;045857;5364.0167;N;06127.8262;E;0;155;965;7;2.40;4;0;14.77,0.02,3.6;AB45DF01145;"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/WondexFrameDecoderTest.java b/src/test/java/org/traccar/protocol/WondexFrameDecoderTest.java
new file mode 100644
index 000000000..642473f2d
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/WondexFrameDecoderTest.java
@@ -0,0 +1,28 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class WondexFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ WondexFrameDecoder decoder = new WondexFrameDecoder();
+
+ assertNull(
+ decoder.decode(null, null, binary("f0d70b0001ca9a3b")));
+
+ assertEquals(
+ binary("313034343938393630312c32303133303332333039353531352c31332e3537323737362c35322e3430303833382c302c3030302c37322c302c32"),
+ decoder.decode(null, null, binary("313034343938393630312c32303133303332333039353531352c31332e3537323737362c35322e3430303833382c302c3030302c37322c302c320d0a")));
+
+ assertEquals(binary("d0d70b0001ca9a3b"),
+ decoder.decode(null, null, binary("d0d70b0001ca9a3b")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/WondexProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/WondexProtocolDecoderTest.java
new file mode 100644
index 000000000..f01a763a1
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/WondexProtocolDecoderTest.java
@@ -0,0 +1,62 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class WondexProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ WondexProtocolDecoder decoder = new WondexProtocolDecoder(null);
+
+ verifyPosition(decoder, buffer(
+ "2000000108,20151030145404,76.948633,43.354700,0,140,15,100,1,1325,125.4,10.5,0.0"),
+ position("2015-10-30 14:54:04.000", true, 43.35470, 76.94863));
+
+ verifyPosition(decoder, buffer(
+ "2000000257,20151030145351,69.379976,53.283905,0,0,16,2,0,0,469.1,58.9,0.0"),
+ position("2015-10-30 14:53:51.000", true, 53.28390, 69.37998));
+
+ verifyPosition(decoder, buffer(
+ "2000000232,20151030145206,51.166900,43.651353,0,132,11,2,0,0,0.0,0.0,0.0"));
+
+ verifyPosition(decoder, buffer(
+ "2000000259,20151030145653,69.380826,53.283890,9,10,15,2,1,695,1002.6,108.2,0.0"));
+
+ verifyPosition(decoder, buffer(
+ "1044989601,20130323074605,0.000000,90.000000,0,000,0,0,2"));
+
+ verifyPosition(decoder, buffer(
+ "123456789000001,20120101123200,130.000000,60.000000,0,000,0,0,0,0"));
+
+ verifyPosition(decoder, buffer(
+ "210000001,20070313170040,121.123456,12.654321,0,233,0,9,2,0.0,0,0.00,0.00,0"));
+
+ verifyPosition(decoder, buffer(
+ "1044989601,20130322172647,13.572583,52.401070,22,204,49,0,2"));
+
+ verifyPosition(decoder, buffer(
+ "1044989601,20130322172647,13.572583,52.401070,22,204,-49,0,2"));
+
+ verifyPosition(decoder, buffer(
+ "3997324533,20140326074908,28.797603,47.041635,0,48,0,6,2,3.90V,0"));
+
+ verifyPosition(decoder, buffer(
+ "2000000001,20140529213210,-63.179111,9.781493,0,0,54.0,8,2,0.0,0,0.01,0.01,0,0,0,0"));
+
+ verifyNotNull(decoder, buffer(
+ "$OK:VER=M7 2.003 DVB rev02c,V2"));
+
+ verifyNotNull(decoder, buffer(
+ "$OK:REBOOT"));
+
+ verifyNotNull(decoder, buffer(
+ "$ERR:GETLOCATION=1"));
+
+ verifyNull(decoder, binary(
+ "d0d70b0001ca9a3b"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/WondexProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/WondexProtocolEncoderTest.java
new file mode 100644
index 000000000..8209fc412
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/WondexProtocolEncoderTest.java
@@ -0,0 +1,24 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class WondexProtocolEncoderTest extends ProtocolTest {
+ @Test
+ public void testEncode() throws Exception {
+
+ WondexProtocolEncoder encoder = new WondexProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(2);
+ command.setType(Command.TYPE_POSITION_SINGLE);
+ command.set(Command.KEY_DEVICE_PASSWORD, "0000");
+
+ assertEquals("$WP+GETLOCATION=0000", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/WristbandProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/WristbandProtocolDecoderTest.java
new file mode 100644
index 000000000..5635ce3d4
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/WristbandProtocolDecoderTest.java
@@ -0,0 +1,36 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class WristbandProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ WristbandProtocolDecoder decoder = new WristbandProtocolDecoder(null);
+
+ verifyNotNull(decoder, binary(
+ "000102004459583836383730343034343735303035357c56312e307c317c7b4630342331382c30372c332c3539303139322c33303a31382c30372c332c3539303139322c33307d0d0afffefc"));
+
+ verifyNotNull(decoder, binary(
+ "000102009c59583836383730343034343735303035357c56312e307c317c7b4630332330383a30353a38313a64383a31383a38372c2d37365f30303a37663a32383a63373a62613a63312c2d37375f39633a33643a63663a65643a62643a36622c2d36335f64383a65623a39373a65653a37373a32342c2d38327c31382c30372c332c3539303735342c33303a31382c30372c332c3539303735342c33307d0d0afffefc"));
+
+ verifyNull(decoder, binary(
+ "000102002259583836383730343034343735303035357c56312e307c307c7b46363423317d0d0afffefc"));
+
+ verifyPositions(decoder, binary(
+ "00010200bc59583836383730343034343735303035357c56312e307c317c7b4630322337372e3437373831372c2d33382e3839363239322c3230313831323239313235352c302e35387c37372e3437373739362c2d33382e3839363234352c3230313831323239313235352c302e30307c37372e3437373738392c2d33382e3839363233322c3230313831323239313235352c302e30307c37372e3437373737362c2d33382e3839363232322c3230313831323239313235352c302e30307d0d0afffefc"));
+
+ verifyNull(decoder, binary(
+ "000102004759583836383730343034343735303035357c56312e307c317c7b463931233331305f30307c30307c30307c30307c57414e444149323031382f31322f31342031353a35367d0d0afffefc"));
+
+ verifyNull(decoder, binary(
+ "000102004159583336373535313631303030303934347c56312e307c317c7b4639312330317c30307c30307c33475f7065745f323031382f30352f31362031313a30307d0d0afffefc"));
+
+ verifyPositions(decoder, false, binary(
+ "000102003559583836383730343034343735303035357c56312e307c317c7b4630312339342c312c3130302c302c33313030302c3930307d0d0afffefc"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/XexunFrameDecoderTest.java b/src/test/java/org/traccar/protocol/XexunFrameDecoderTest.java
new file mode 100644
index 000000000..8fc628bdb
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/XexunFrameDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class XexunFrameDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ XexunFrameDecoder decoder = new XexunFrameDecoder();
+
+ assertEquals(
+ binary("4750524d432c3230353933352e3030302c412c353134302e343335302c4e2c3530312e303638362c452c302e30302c302e30302c3132313031352c30302c303030302e302c412a37302c462c2c696d65693a3335393538373031343731383339322c"),
+ decoder.decode(null, null, binary("313531303132313435392c2b33313635323435343932372c4750524d432c3230353933352e3030302c412c353134302e343335302c4e2c3530312e303638362c452c302e30302c302e30302c3132313031352c30302c303030302e302c412a37302c462c2c696d65693a3335393538373031343731383339322c31323249")));
+
+ assertEquals(
+ binary("4750524d432c3130333733312e3633362c412c343534352e353236362c4e2c30303434382e383235392c452c32312e31322c3237362e30312c3135303631352c2c2c412a35372c4c2c2c20696d65693a3031333934393030323032363637352c"),
+ decoder.decode(null, null, binary("3135303631353132333733312c2b33333634373338343631312c4750524d432c3130333733312e3633362c412c343534352e353236362c4e2c30303434382e383235392c452c32312e31322c3237362e30312c3135303631352c2c2c412a35372c4c2c2c20696d65693a3031333934393030323032363637352c30342c333532322e392c463a332e3732562c302c3134322c32313734342c3230382c30312c303730322c394338430a0d")));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/XexunProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/XexunProtocolDecoderTest.java
new file mode 100644
index 000000000..8b0f245a2
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/XexunProtocolDecoderTest.java
@@ -0,0 +1,118 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class XexunProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ XexunProtocolDecoder decoder = new XexunProtocolDecoder(null, false);
+
+ verifyAttributes(decoder, text(
+ "GPRMC,.000,A,0.000000,S,0.0000,W,0.00,0.00,,00,0000.0,A*55,L,,imei:353579010727036,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,113518.000,A,5303.4150,N,10.2368,E,60.73,207.42,260216,00,0000.0,A*74,F,,imei:351525018007873,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,215853.000,A,5304.9600,N,6.7907,E,1.43,80.67,250216,00,0000.0,A*47,F,,imei:351525018007873,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,121535.000,A,5417.2666,N,04822.1264,E,1.452,30.42,031014,0.0,A*4D\r\n,L,imei:355227042011730,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,150120.000,A,3346.4463,S,15057.3083,E,0.0,117.4,010911,,,A*76,F,imei:351525010943661,"),
+ position("2011-09-01 15:01:20.000", true, -33.77411, 150.95514));
+
+ verifyPosition(decoder, text(
+ "GPRMC,010203.000,A,0102.0003,N,00102.0003,E,1.02,1.02,010203,,,A*00,F,,imei:10000000000000,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,233842.000,A,5001.3060,N,01429.3243,E,0.00,,210211,,,A*74,F,imei:354776030495631,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,080303.000,A,5546.7313,N,03738.6005,E,0.56,160.13,100311,,,A*6A,L,imei:354778030461167,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,220828.678,A,5206.1446,N,02038.2403,,0,0,160912,,,E*23,L,imei:358948012501019,"));
+
+ verifyPosition(decoder, text(
+ "GNRMC,134418.000,A,5533.8973,N,03745.4398,E,0.00,308.85,160215,,,A*7A,F,, imei:864244028033115,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,093341.000,A,1344.5716,N,10033.6648,E,0.00,0.00,240215,,,A*68,F,,imei:865328028306149,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,103731.636,A,4545.5266,N,00448.8259,E,21.12,276.01,150615,,,A*57,L,, imei:013949002026675,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,014623.000,A,4710.8260,N,1948.1220,E,0.11,105.40,111212,00,0000.0,A*49,F,,imei:357713002048962,"));
+
+ verifyPosition(decoder, text(
+ "GPRMC,043435.000,A,811.299200,S,11339.9500,E,0.93,29.52,160313,00,0000.0,A*65,F,,imei:359585014597923,"));
+
+ decoder = new XexunProtocolDecoder(null, true);
+
+ verifyPosition(decoder, text(
+ "171007160505,,GPRMC,160505.000,A,5323.4680,N,00252.4202,W,000.0,129.7,071017,,,A*7A,F,ACCStart, imei:864504031916915,10,41.1,F:4.28V,1,135,19824,234,15,0062,B7D5"));
+
+ verifyPosition(decoder, text(
+ "171007160525,,GPRMC,160525.000,A,5323.4680,N,00252.4202,W,000.0,129.7,071017,,,A*78,F,ACCStop, imei:864504031916915,10,41.1,F:4.28V,1,134,42896,234,15,0062,B7D5"));
+
+ verifyPosition(decoder, text(
+ "170505103845,TELKOMSEL,GPRMC,103845.000,A,0340.2482,N,09841.9689,E,0.00,68.23,050517,,,A*5D,F,ACC On, imei:013227002782161,05,-8.2,F:4.22V,1,141,44712,510,10,2BE5,EC47"));
+
+ verifyPosition(decoder, text(
+ "170607031932,+6282167979090,GPRMC,031932.000,A,0347.2515,N,09841.9433,E,0.00,261.22,070617,,,A*6C,F,ACC OFF, imei:013226004613135,11,23.1,F:4.25V,1,148,44989,510,10,2B34,0268"));
+
+ verifyNull(decoder, text(
+ ",+48606717068,,L,, imei:012207005047292,,,F:4.28V,1,52,11565,247,01,000E,1FC5"));
+
+ verifyPosition(decoder, text(
+ "130302125349,+79604870506,GPRMC,085349.000,A,4503.2392,N,03858.5660,E,6.95,154.65,020313,,,A*6C,F,, imei:012207007744243,03,-1.5,F:4.15V,1,139,28048,250,01,278A,5072"),
+ position("2013-03-02 08:53:49.000", true, 45.05399, 38.97610));
+
+ verifyPosition(decoder, text(
+ "111111120009,+436763737552,GPRMC,120009.590,A,4639.6774,N,01418.5737,E,0.00,0.00,111111,,,A*68,F,, imei:359853000144328,04,481.2,F:4.15V,0,139,2689,232,03,2725,0576"));
+
+ verifyPosition(decoder, text(
+ "111111120009,+436763737552,GPRMC,120600.000,A,6000.0000,N,13000.0000,E,0.00,0.00,010112,,,A*68,F,help me!, imei:123456789012345,04,481.2,F:4.15V,0,139,2689,232,03,2725,0576"));
+
+ verifyPosition(decoder, text(
+ "111111120009,+436763737552,GPRMC,120600.000,A,6000.0000,N,13000.0000,E,0.00,0.00,010112,,,A*68,F,help me!, imei:123456789012345,04,481.2,L:3.5V,0,139,2689,232,03,2725,0576"));
+
+ verifyPosition(decoder, text(
+ "111111120009,436763737552,GPRMC,120600.000,A,6000.0000,N,13000.0000,E,0.00,0.00,010112,,,A*68,F,help me!, imei:123456789012345,04,481.2,L:3.5V,0,139,2689,232,03,2725,0576"));
+
+ verifyPosition(decoder, text(
+ "111111120009,+1234,GPRMC,204530.4,A,6000.0000,N,13000.0000,E,0.0,,010112,0.0,E,A*68,F,imei:123456789012345,04,123.5,F:3.55V,0,139,,232,03,272CE1,0576"));
+
+ verifyPosition(decoder, text(
+ "111111120009,+1234,GPRMC,204530.4,A,6000.000,N,01000.6288,E,0.0,0.00,230713,0.0,E,A*3C,F,imei:123456789012345,00,,F:3.88V,0,125,,262,01,224CE1,379B"));
+
+ verifyPosition(decoder, text(
+ "111111120009,+1234,GPRMC,215840.7,A,6000.000,N,01000.6253,E,0.0,0.00,230713,0.0,E,A*34,F,imei:123456789012345,00,,F:3.9V,0,124,,262,01,224CE1,379B"));
+
+ verifyPosition(decoder, text(
+ "130725134142,,GPRMC,134142.591,A,3845.6283,N,00909.8876,W,2.08,287.33,250713,,,A*71,F,, imei:013227000526784,03,-50.7,L:3.69V,0,128,65337,268,03,177A,119F"));
+
+ verifyPosition(decoder, text(
+ "140602152533,TESCO_INFO,GPRMC,152533.000,A,5145.4275,N,00000.3448,E,0.00,0.00,020614,,,A*66,F,, imei:013227002781643,06,35.1,F:4.15V,1,135,38950,234,10,10B4,5235"));
+
+ verifyPosition(decoder, text(
+ "150216154418,5277,GNRMC,134418.000,A,5533.8973,N,03745.4398,E,0.00,308.85,160215,,,A*7A,F,, imei:864244028033115,10,169.8,F:4.28V,1,132,48269,250,99,6D0D,8572"));
+
+ verifyPosition(decoder, text(
+ "150224173341,+66961544651,GPRMC,093341.000,A,1344.5716,N,10033.6648,E,0.00,0.00,240215,,,A*68,F,,imei:865328028306149,05,106.4,F:4.01V/ADC1=0.20V/ADC2=0.00V,0,159,955,520,01,5DE8,0399,6.21km"));
+
+ verifyPosition(decoder, text(
+ "150316182840,07872167745,GPRMC,182840.000,A,5126.1310,N,00055.5573,W,0.00,0.00,160315,,,A*7C,F,,imei:865328023469306,06,54.3,F:4.10V/ADC1=0.76V/ADC2=0.00V,0,157,38486,234,10,34DC,48A6,3.70km"));
+
+ verifyPosition(decoder, text(
+ "150615123731,+33647384611,GPRMC,103731.636,A,4545.5266,N,00448.8259,E,21.12,276.01,150615,,,A*57,L,, imei:013949002026675,04,3522.9,F:3.72V,0,142,21744,208,01,0702,9C8C"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/XirgoProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/XirgoProtocolDecoderTest.java
new file mode 100644
index 000000000..f795742fd
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/XirgoProtocolDecoderTest.java
@@ -0,0 +1,76 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class XirgoProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecodeCustom() throws Exception {
+
+ XirgoProtocolDecoder decoder = new XirgoProtocolDecoder(null);
+
+ decoder.setForm("UID,EV,D,T,LT,LN,AL,GSPT,HD,SV,HP,BV,CQ,GS,SI,IG,OT");
+
+ verifyPosition(decoder, text(
+ "$$183900034,4002,03/30/2019,02:15:22,46.848577,-114.022213,978,0.0,172.3,16,1.2,13.291,20,3,2,2,1##"));
+
+ verifyPosition(decoder, text(
+ "$$184800793,4002,03/30/2019,02:10:13,46.848600,-114.022256,9723,0.0,1645,17,1.2,13.283,18,3,89011703278246523594,2,0##"));
+
+ decoder.setForm("UID,EV,D,T,LT,LN,AL,GSPT,SV,HP,BV,CQ,MI,GS,SI,IG,OT");
+
+ verifyPosition(decoder, text(
+ "$$184800793,4002,03/15/2019,21:30:21,46.848582,-114.022237,9733,0.0,18,1.1,13.605,20,0,3,89011703278246523602,2,0##"));
+
+ }
+
+ @Test
+ public void testDecodeNew() throws Exception {
+
+ XirgoProtocolDecoder decoder = new XirgoProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$$352054058132185,4001,2017/04/21,00:01:05,32.54659,-116.90670,143.2,0,0,0,598,0.0,12,0.9,765840,7.0,14.5,19,1,1,0011,8.5,63.2,5,21999,184,255,671,207,100,185##"));
+
+ verifyPosition(decoder, text(
+ "$$352054058132185,6011,2017/04/21,04:57:10,32.49658,-116.85957,250.9,0,0,0,602,0.0,12,0.8,765876,7.0,14.1,21,1,1,0011,10.1,0.0,5,170917890,280,255,627,0,100,167##"));
+
+ verifyPosition(decoder, text(
+ "$$355922061611345,6001,2016/08/25,20:10:51,51.13042,-114.22752,1197,44.7,0.0,0.0,2622,27,12,0.8,1,0.0,13.9,24,1,0,0.0,-70,-809,688##"));
+
+ verifyPosition(decoder, text(
+ "$$355922061611345,6001,2016/08/25,20:10:38,51.12948,-114.22637,1203,34.8,0.0,0.0,1377,215,12,0.8,1,0.0,13.8,28,1,0,0.0,-309,-566,754##"));
+
+ verifyPosition(decoder, text(
+ "$$354898045650537,6031,2015/02/26,15:47:26,33.42552,-112.30308,287.8,0,0,0,0,0.0,7,1.2,2,0.0,12.2,22,1,0,82.3"));
+
+ verifyPosition(decoder, text(
+ "$$355922060162167,6015,2016/04/21,17:26:52,39.83267,-76.66139,230,0.0,0.0,0.0,779,0,8,1.2,0,0.0,13.0,19,1,1C4BJWDG4GL191009,X0z1-1137CD1,0402,3GATT,0,83.9,-70,-715,738##"));
+
+ verifyPosition(decoder, text(
+ "$$355922060162167,4002,2016/04/21,17:04:50,39.83253,-76.66102,232,0.0,0.0,0.0,0,0,12,1.2,0,0.0,9.2,15,1,0,0.0,35,-8,1059##"));
+
+ }
+
+ @Test
+ public void testDecodeOld() throws Exception {
+
+ XirgoProtocolDecoder decoder = new XirgoProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "$$354660046140722,6001,2013/01/22,15:36:18,25.80907,-80.32531,7.1,19,165.2,11,0.8,11.1,17,1,1,3.9,2##"),
+ position("2013-01-22 15:36:18.000", true, 25.80907, -80.32531));
+
+ verifyPosition(decoder, text(
+ "$$357207059646786,4003,2015/05/19,15:54:56,-20.21422,-70.14927,37.5,1.8,0.0,11,0.8,12.9,31,297,1,0,0.0,0.0,0,1,1,1##"));
+
+ verifyPosition(decoder, text(
+ "$$354898045650537,6031,2015/02/26,15:47:26,33.42552,-112.30308,287.8,0,0,0,0,0.0,7,1.2,2,0.0,12.2,22,1,0,82.3"));
+
+ verifyPosition(decoder, text(
+ "$$357207059646786,4003,2015/05/19,15:55:27,-20.21421,-70.14920,33.6,0.4,0.0,11,0.8,12.9,31,297,1,0,0.0,0.0,0,1,1,1##"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/XirgoProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/XirgoProtocolEncoderTest.java
new file mode 100644
index 000000000..dd2e939c9
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/XirgoProtocolEncoderTest.java
@@ -0,0 +1,26 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class XirgoProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncode() throws Exception {
+
+ XirgoProtocolEncoder encoder = new XirgoProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_OUTPUT_CONTROL);
+ command.set(Command.KEY_INDEX, 0);
+ command.set(Command.KEY_DATA, 1);
+
+ assertEquals("+XT:7005,2,1", encoder.encodeCommand(command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Xrb28ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Xrb28ProtocolDecoderTest.java
new file mode 100644
index 000000000..0f15f31b4
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Xrb28ProtocolDecoderTest.java
@@ -0,0 +1,33 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Xrb28ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Xrb28ProtocolDecoder decoder = new Xrb28ProtocolDecoder(null);
+
+ verifyAttributes(decoder, text(
+ "*SCOR,OM,123456789123456,Q0,412,80,28#"));
+
+ verifyPosition(decoder, text(
+ "*SCOR,OM,867584030387299,D0,0,012102.00,A,0608.00062,S,10659.70331,E,12,0.69,151118,30.3,M,A#"));
+
+ verifyAttributes(decoder, text(
+ "*SCOR,OM,863158022988725,H0,0,412,28,80,0#"));
+
+ verifyAttributes(decoder, text(
+ "*HBCR,OM,123456789123456,R0,0,55,1234,1497689816#"));
+
+ verifyPosition(decoder, text(
+ "*HBCR,OM,123456789123456,D0,0,124458.00,A,2237.7514,N,11408.6214,E,6,0.21,151216,10,M,A#"));
+
+ verifyPosition(decoder, text(
+ "*SCOR,OM,863158022988725,D0,0,124458.00,A,2237.7514,N,11408.6214,E,6,0.21,151216,10,M,A#"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Xrb28ProtocolEncoderTest.java b/src/test/java/org/traccar/protocol/Xrb28ProtocolEncoderTest.java
new file mode 100644
index 000000000..49476d694
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Xrb28ProtocolEncoderTest.java
@@ -0,0 +1,39 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+import org.traccar.model.Command;
+
+import static org.junit.Assert.assertEquals;
+
+public class Xrb28ProtocolEncoderTest extends ProtocolTest {
+
+ @Test
+ public void testEncodePositionPeriodic() {
+
+ Xrb28ProtocolEncoder encoder = new Xrb28ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_POSITION_PERIODIC);
+ command.set(Command.KEY_FREQUENCY, 300);
+
+ assertEquals("\u00ff\u00ff*SCOS,OM,123456789012345,D1,300#\n", encoder.encodeCommand(null, command));
+
+ }
+
+ @Test
+ public void testEncodeCustom() {
+
+ Xrb28ProtocolEncoder encoder = new Xrb28ProtocolEncoder();
+
+ Command command = new Command();
+ command.setDeviceId(1);
+ command.setType(Command.TYPE_CUSTOM);
+ command.set(Command.KEY_DATA, "S7,0,3,0,0,20,25");
+
+ assertEquals("\u00ff\u00ff*SCOS,OM,123456789012345,S7,0,3,0,0,20,25#\n", encoder.encodeCommand(null, command));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Xt013ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Xt013ProtocolDecoderTest.java
new file mode 100644
index 000000000..aa44929ab
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Xt013ProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Xt013ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Xt013ProtocolDecoder decoder = new Xt013ProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "TK,862950021650364,150131090859,+53.267863,+5.767363,0,38,12,0,F,204,08,C94,336C,24,,4.09,1,,,,,,,,"),
+ position("2015-01-31 09:08:59.000", true, 53.26786, 5.76736));
+
+ verifyPosition(decoder, text(
+ "TK,862950021650364,150118113832,+53.267722,+5.767143,0,86,12,0,F,204,08,C94,336C,22,,4.21,1,,,,,,,,"));
+
+ verifyPosition(decoder, text(
+ "HI,862950021650364TK,862950021650364,150118113832,+53.267722,+5.767143,0,86,12,0,F,204,08,C94,336C,22,,4.21,1,,,,,,,,"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/Xt2400ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/Xt2400ProtocolDecoderTest.java
new file mode 100644
index 000000000..f4a78b5bd
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/Xt2400ProtocolDecoderTest.java
@@ -0,0 +1,25 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class Xt2400ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Xt2400ProtocolDecoder decoder = new Xt2400ProtocolDecoder(null);
+
+ decoder.setConfig("\n:wycfg pcr[0] 001001030406070809570a13121714100565\n");
+
+ verifyPosition(decoder, binary(
+ "000a344f1f0259766ae002074289f8f1c4b200e80000026712068000130000029300883559464255524845364650323433343235"));
+
+ decoder.setConfig("\n:wycfg pcr[0] 000f01030406070809570a131217141005\n");
+
+ verifyPosition(decoder, binary(
+ "0009c4fb9b0b58a771e4020742d9f8f1c4c300bc0000000011077c0015000000000001"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/YwtProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/YwtProtocolDecoderTest.java
new file mode 100644
index 000000000..332d15fa5
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/YwtProtocolDecoderTest.java
@@ -0,0 +1,31 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class YwtProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ YwtProtocolDecoder decoder = new YwtProtocolDecoder(null);
+
+ verifyPosition(decoder, text(
+ "%RP,1222102985:1,170509033842,E102.146563,N14.582175,,0,320,10,0,00-00-00-00-00-00-00-00-00-00-00-00,,1db2-02b3-52004,3>941.523-32,7>1,19>-16,20>30.9V"));
+
+ verifyNull(decoder, text(
+ "%SN,0417061042:0,0,140117041203,404"));
+
+ verifyPosition(decoder, text(
+ "%GP,3000012345:0,090723182813,E114.602345,N22.069725,,30,160,4,0,00,,2794-10FF-46000,3>0-0"));
+
+ verifyPosition(decoder, text(
+ "%RP,3000012345:0,090807182815,E114.602345,N22.069725,,30,160,4,0,00"),
+ position("2009-08-07 18:28:15.000", true, 22.06973, 114.60235));
+
+ verifyPosition(decoder, text(
+ "%KP,3000012345:0,090807183115,E114.602345,N22.069725,,30,160,5,0,00;"));
+
+ }
+
+}
diff --git a/src/test/java/org/traccar/reports/ReportUtilsTest.java b/src/test/java/org/traccar/reports/ReportUtilsTest.java
new file mode 100644
index 000000000..01b9c276f
--- /dev/null
+++ b/src/test/java/org/traccar/reports/ReportUtilsTest.java
@@ -0,0 +1,390 @@
+package org.traccar.reports;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.traccar.BaseTest;
+import org.traccar.TestIdentityManager;
+import org.traccar.model.Position;
+import org.traccar.reports.model.StopReport;
+import org.traccar.reports.model.TripReport;
+import org.traccar.reports.model.TripsConfig;
+
+public class ReportUtilsTest extends BaseTest {
+
+ private Date date(String time) throws ParseException {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return dateFormat.parse(time);
+ }
+
+ private Position position(String time, double speed, double totalDistance) throws ParseException {
+
+ Position position = new Position();
+
+ position.setTime(date(time));
+ position.setValid(true);
+ position.setSpeed(speed);
+ position.set(Position.KEY_TOTAL_DISTANCE, totalDistance);
+
+ return position;
+ }
+
+ @Test
+ public void testCalculateDistance() {
+ Position startPosition = new Position();
+ startPosition.set(Position.KEY_TOTAL_DISTANCE, 500.0);
+ Position endPosition = new Position();
+ endPosition.set(Position.KEY_TOTAL_DISTANCE, 700.0);
+ assertEquals(ReportUtils.calculateDistance(startPosition, endPosition), 200.0, 10);
+ startPosition.set(Position.KEY_ODOMETER, 50000);
+ endPosition.set(Position.KEY_ODOMETER, 51000);
+ assertEquals(ReportUtils.calculateDistance(startPosition, endPosition), 1000.0, 10);
+ }
+
+ @Test
+ public void testCalculateSpentFuel() {
+ Position startPosition = new Position();
+ Position endPosition = new Position();
+ assertEquals(ReportUtils.calculateFuel(startPosition, endPosition), 0.0, 0.01);
+ startPosition.set(Position.KEY_FUEL_LEVEL, 0.7);
+ endPosition.set(Position.KEY_FUEL_LEVEL, 0.5);
+ assertEquals(ReportUtils.calculateFuel(startPosition, endPosition), 0.2, 0.01);
+ }
+
+ @Test
+ public void testDetectTripsSimple() throws ParseException {
+
+ List<Position> data = Arrays.asList(
+ position("2016-01-01 00:00:00.000", 0, 0),
+ position("2016-01-01 00:01:00.000", 0, 0),
+ position("2016-01-01 00:02:00.000", 10, 0),
+ position("2016-01-01 00:03:00.000", 10, 1000),
+ position("2016-01-01 00:04:00.000", 10, 2000),
+ position("2016-01-01 00:05:00.000", 0, 3000),
+ position("2016-01-01 00:06:00.000", 0, 3000),
+ position("2016-01-01 00:07:00.000", 0, 3000));
+
+ TripsConfig tripsConfig = new TripsConfig(500, 300000, 180000, 900000, false, false, 0.01);
+
+ Collection<TripReport> trips = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, TripReport.class);
+
+ assertNotNull(trips);
+ assertFalse(trips.isEmpty());
+
+ TripReport itemTrip = trips.iterator().next();
+
+ assertEquals(date("2016-01-01 00:02:00.000"), itemTrip.getStartTime());
+ assertEquals(date("2016-01-01 00:05:00.000"), itemTrip.getEndTime());
+ assertEquals(180000, itemTrip.getDuration());
+ assertEquals(10, itemTrip.getAverageSpeed(), 0.01);
+ assertEquals(10, itemTrip.getMaxSpeed(), 0.01);
+ assertEquals(3000, itemTrip.getDistance(), 0.01);
+
+ Collection<StopReport> stops = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, StopReport.class);
+
+ assertNotNull(stops);
+ assertFalse(stops.isEmpty());
+
+ Iterator<StopReport> iterator = stops.iterator();
+
+ StopReport itemStop = iterator.next();
+
+ assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:02:00.000"), itemStop.getEndTime());
+ assertEquals(120000, itemStop.getDuration());
+
+ itemStop = iterator.next();
+
+ assertEquals(date("2016-01-01 00:05:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:07:00.000"), itemStop.getEndTime());
+ assertEquals(120000, itemStop.getDuration());
+
+ }
+
+ @Test
+ public void testDetectTripsSimpleWithIgnition() throws ParseException {
+
+ List<Position> data = Arrays.asList(
+ position("2016-01-01 00:00:00.000", 0, 0),
+ position("2016-01-01 00:01:00.000", 0, 0),
+ position("2016-01-01 00:02:00.000", 10, 0),
+ position("2016-01-01 00:03:00.000", 10, 1000),
+ position("2016-01-01 00:04:00.000", 10, 2000),
+ position("2016-01-01 00:05:00.000", 0, 3000),
+ position("2016-01-01 00:06:00.000", 0, 3000),
+ position("2016-01-01 00:07:00.000", 0, 3000));
+
+ data.get(5).set(Position.KEY_IGNITION, false);
+
+ TripsConfig tripsConfig = new TripsConfig(500, 300000, 180000, 900000, true, false, 0.01);
+
+ Collection<TripReport> trips = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, TripReport.class);
+
+ assertNotNull(trips);
+ assertFalse(trips.isEmpty());
+
+ TripReport itemTrip = trips.iterator().next();
+
+ assertEquals(date("2016-01-01 00:02:00.000"), itemTrip.getStartTime());
+ assertEquals(date("2016-01-01 00:05:00.000"), itemTrip.getEndTime());
+ assertEquals(180000, itemTrip.getDuration());
+ assertEquals(10, itemTrip.getAverageSpeed(), 0.01);
+ assertEquals(10, itemTrip.getMaxSpeed(), 0.01);
+ assertEquals(3000, itemTrip.getDistance(), 0.01);
+
+ trips = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, TripReport.class);
+
+ assertNotNull(trips);
+ assertFalse(trips.isEmpty());
+
+ itemTrip = trips.iterator().next();
+
+ assertEquals(date("2016-01-01 00:02:00.000"), itemTrip.getStartTime());
+ assertEquals(date("2016-01-01 00:05:00.000"), itemTrip.getEndTime());
+ assertEquals(180000, itemTrip.getDuration());
+ assertEquals(10, itemTrip.getAverageSpeed(), 0.01);
+ assertEquals(10, itemTrip.getMaxSpeed(), 0.01);
+ assertEquals(3000, itemTrip.getDistance(), 0.01);
+
+ Collection<StopReport> stops = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, StopReport.class);
+
+ assertNotNull(stops);
+ assertFalse(stops.isEmpty());
+
+ Iterator<StopReport> iterator = stops.iterator();
+
+ StopReport itemStop = iterator.next();
+
+ assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:02:00.000"), itemStop.getEndTime());
+ assertEquals(120000, itemStop.getDuration());
+
+ itemStop = iterator.next();
+
+ assertEquals(date("2016-01-01 00:05:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:07:00.000"), itemStop.getEndTime());
+ assertEquals(120000, itemStop.getDuration());
+
+ }
+
+ @Test
+ public void testDetectTripsWithFluctuation() throws ParseException {
+
+ List<Position> data = Arrays.asList(
+ position("2016-01-01 00:00:00.000", 0, 0),
+ position("2016-01-01 00:01:00.000", 0, 0),
+ position("2016-01-01 00:02:00.000", 10, 0),
+ position("2016-01-01 00:03:00.000", 10, 1000),
+ position("2016-01-01 00:04:00.000", 10, 2000),
+ position("2016-01-01 00:05:00.000", 10, 3000),
+ position("2016-01-01 00:06:00.000", 10, 4000),
+ position("2016-01-01 00:07:00.000", 0, 5000),
+ position("2016-01-01 00:08:00.000", 10, 6000),
+ position("2016-01-01 00:09:00.000", 0, 7000),
+ position("2016-01-01 00:10:00.000", 0, 7000),
+ position("2016-01-01 00:11:00.000", 0, 7000));
+
+ TripsConfig tripsConfig = new TripsConfig(500, 300000, 180000, 900000, false, false, 0.01);
+
+ Collection<TripReport> trips = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, TripReport.class);
+
+ assertNotNull(trips);
+ assertFalse(trips.isEmpty());
+
+ TripReport itemTrip = trips.iterator().next();
+
+ assertEquals(date("2016-01-01 00:02:00.000"), itemTrip.getStartTime());
+ assertEquals(date("2016-01-01 00:09:00.000"), itemTrip.getEndTime());
+ assertEquals(420000, itemTrip.getDuration());
+ assertEquals(8.57, itemTrip.getAverageSpeed(), 0.01);
+ assertEquals(10, itemTrip.getMaxSpeed(), 0.01);
+ assertEquals(7000, itemTrip.getDistance(), 0.01);
+
+ Collection<StopReport> stops = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, StopReport.class);
+
+ assertNotNull(stops);
+ assertFalse(stops.isEmpty());
+
+ Iterator<StopReport> iterator = stops.iterator();
+
+ StopReport itemStop = iterator.next();
+
+ assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:02:00.000"), itemStop.getEndTime());
+ assertEquals(120000, itemStop.getDuration());
+
+ itemStop = iterator.next();
+
+ assertEquals(date("2016-01-01 00:09:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:11:00.000"), itemStop.getEndTime());
+ assertEquals(120000, itemStop.getDuration());
+
+ }
+
+ @Test
+ public void testDetectStopsOnly() throws ParseException {
+
+ Collection<Position> data = Arrays.asList(
+ position("2016-01-01 00:00:00.000", 0, 0),
+ position("2016-01-01 00:01:00.000", 0, 0),
+ position("2016-01-01 00:02:00.000", 1, 0),
+ position("2016-01-01 00:03:00.000", 0, 0),
+ position("2016-01-01 00:04:00.000", 1, 0),
+ position("2016-01-01 00:05:00.000", 0, 0));
+
+ TripsConfig tripsConfig = new TripsConfig(500, 300000, 200000, 900000, false, false, 0.01);
+
+ Collection<StopReport> result = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, StopReport.class);
+
+ assertNotNull(result);
+ assertFalse(result.isEmpty());
+
+ StopReport itemStop = result.iterator().next();
+
+ assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:05:00.000"), itemStop.getEndTime());
+ assertEquals(300000, itemStop.getDuration());
+
+ }
+
+ @Test
+ public void testDetectStopsWithTripCut() throws ParseException {
+
+ Collection<Position> data = Arrays.asList(
+ position("2016-01-01 00:00:00.000", 0, 0),
+ position("2016-01-01 00:01:00.000", 0, 0),
+ position("2016-01-01 00:02:00.000", 0, 0),
+ position("2016-01-01 00:03:00.000", 0, 0),
+ position("2016-01-01 00:04:00.000", 1, 0),
+ position("2016-01-01 00:05:00.000", 2, 0));
+
+ TripsConfig tripsConfig = new TripsConfig(500, 300000, 200000, 900000, false, false, 0.01);
+
+ Collection<StopReport> result = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, StopReport.class);
+
+ assertNotNull(result);
+ assertFalse(result.isEmpty());
+
+ StopReport itemStop = result.iterator().next();
+
+ assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:04:00.000"), itemStop.getEndTime());
+ assertEquals(240000, itemStop.getDuration());
+
+ }
+
+ @Test
+ public void testDetectStopsStartedFromTrip() throws ParseException {
+
+ Collection<Position> data = Arrays.asList(
+ position("2016-01-01 00:00:00.000", 2, 0),
+ position("2016-01-01 00:01:00.000", 1, 0),
+ position("2016-01-01 00:02:00.000", 0, 0),
+ position("2016-01-01 00:03:00.000", 0, 0),
+ position("2016-01-01 00:04:00.000", 0, 0),
+ position("2016-01-01 00:05:00.000", 0, 0));
+
+ TripsConfig tripsConfig = new TripsConfig(500, 300000, 200000, 900000, false, false, 0.01);
+
+ Collection<StopReport> result = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, StopReport.class);
+
+ assertNotNull(result);
+ assertFalse(result.isEmpty());
+
+ StopReport itemStop = result.iterator().next();
+
+ assertEquals(date("2016-01-01 00:02:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:05:00.000"), itemStop.getEndTime());
+ assertEquals(180000, itemStop.getDuration());
+
+ }
+
+ @Test
+ public void testDetectStopsMoving() throws ParseException {
+
+ Collection<Position> data = Arrays.asList(
+ position("2016-01-01 00:00:00.000", 5, 0),
+ position("2016-01-01 00:01:00.000", 5, 0),
+ position("2016-01-01 00:02:00.000", 3, 0),
+ position("2016-01-01 00:03:00.000", 5, 0),
+ position("2016-01-01 00:04:00.000", 5, 0),
+ position("2016-01-01 00:05:00.000", 5, 0));
+
+ TripsConfig tripsConfig = new TripsConfig(500, 300000, 200000, 900000, false, false, 0.01);
+
+ Collection<StopReport> result = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, StopReport.class);
+
+ assertNotNull(result);
+ assertTrue(result.isEmpty());
+
+ }
+
+ @Test
+ public void testDetectTripAndStopByGap() throws ParseException {
+
+ Collection<Position> data = Arrays.asList(
+ position("2016-01-01 00:00:00.000", 7, 100),
+ position("2016-01-01 00:01:00.000", 7, 300),
+ position("2016-01-01 00:02:00.000", 5, 500),
+ position("2016-01-01 00:03:00.000", 5, 600),
+ position("2016-01-01 00:04:00.000", 3, 700),
+ position("2016-01-01 00:23:00.000", 2, 700),
+ position("2016-01-01 00:24:00.000", 5, 800),
+ position("2016-01-01 00:25:00.000", 5, 900));
+
+ TripsConfig tripsConfig = new TripsConfig(500, 200000, 200000, 900000, false, false, 0.01);
+
+ Collection<TripReport> trips = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, TripReport.class);
+
+ assertNotNull(trips);
+ assertFalse(trips.isEmpty());
+
+ TripReport itemTrip = trips.iterator().next();
+
+ assertEquals(date("2016-01-01 00:00:00.000"), itemTrip.getStartTime());
+ assertEquals(date("2016-01-01 00:04:00.000"), itemTrip.getEndTime());
+ assertEquals(240000, itemTrip.getDuration());
+ assertEquals(6.75, itemTrip.getAverageSpeed(), 0.01);
+ assertEquals(7, itemTrip.getMaxSpeed(), 0.01);
+ assertEquals(600, itemTrip.getDistance(), 0.01);
+
+ Collection<StopReport> stops = ReportUtils.detectTripsAndStops(
+ new TestIdentityManager(), null, data, tripsConfig, false, StopReport.class);
+
+ assertNotNull(stops);
+ assertFalse(stops.isEmpty());
+
+ StopReport itemStop = stops.iterator().next();
+
+ assertEquals(date("2016-01-01 00:04:00.000"), itemStop.getStartTime());
+ assertEquals(date("2016-01-01 00:24:00.000"), itemStop.getEndTime());
+ assertEquals(1200000, itemStop.getDuration());
+ }
+
+}
diff --git a/src/test/java/org/traccar/web/WebServerTest.java b/src/test/java/org/traccar/web/WebServerTest.java
new file mode 100644
index 000000000..5a79fbac2
--- /dev/null
+++ b/src/test/java/org/traccar/web/WebServerTest.java
@@ -0,0 +1,29 @@
+package org.traccar.web;
+
+import org.junit.Test;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+public class WebServerTest {
+
+ @Test
+ public void contextTest() throws NamingException {
+ DataSource mockDataSource = (DataSource) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[] { DataSource.class }, new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return null;
+ }
+ });
+
+ Context context = new InitialContext();
+ context.bind("java:/DefaultDS", mockDataSource);
+ }
+
+}